我正在尝试解决简单的任务,但我找不到任何优雅的解决方案。
我基本上解决了两个循环扇区的交集。 每个扇区由(-pi,pi)范围内的2个角度(来自atan2 func)给出。 每个选择器占据最大角度179.999。因此可以分析循环扇区的每两个角度。
返回值应根据以下内容描述相互交叉:
value <1 if one angle is contained by second one (value represents how much space occupy percentually)
value >1 if first angle (the dotted one) is outside the other one, value represents how much of dotted angle is out of the other one
基本案例和一些例子如下图所示
问题是应该处理的案件很多,我正在寻找一些优雅的方法来解决它。
我可以仅在它们位于单位圆的右侧(cos> 0)时比较两个角度,因为在左侧,数字上较大的角度在图形上较低。我尝试在右半部分使用一些投影:
if(x not in <-pi/2, pi/2>)
{
c = getSign(x)*pi/2;
x = c - (x - c);
}
但是扇区存在问题,占据了单位圈的两半的一部分...
案件很多......有人知道如何优雅地解决这个问题吗? (我使用c ++,但任何提示或伪代码都没问题)
答案 0 :(得分:4)
您可以执行以下操作:
s_start
,s_end
),其中s_start
位于(-pi,pi)和s_end
中{s_start
, s_start+pi
)。s0_start
&lt;扇区s1_start
现在我们只有3个案例(a,b1,b2):
a)s1_start <= s0_end
:交集,s1_start在s0
b)s1_start > s0_end
:
b1)s0_start + 2*pi <= s1_end
:s1内的交叉点,(s0_start + 2 * pi)
b2)s0_start + 2*pi > s1_end
:没有交集
因此我们得到以下代码:
const double PI = 2.*acos(0.);
struct TSector { double a0, a1; };
// normalized range for angle
bool isNormalized(double a)
{ return -PI < a && a <= PI; }
// special normal form for sector
bool isNormalized(TSector const& s)
{ return isNormalized(s.a0) && s.a0 <= s.a1 && s.a1 < s.a0+PI; }
// normalize a sector to the special form:
// * -PI < a0 <= PI
// * a0 < a1 < a0+PI
void normalize(TSector& s)
{
assert(isNormalized(s.a0) && isNormalized(s.a1));
// choose a representation of s.a1 s.t. s.a0 < s.a1 < s.a0+2*PI
double a1_bigger = (s.a0 <= s.a1) ? s.a1 : s.a1+2*PI;
if (a1_bigger >= s.a0+PI)
std::swap(s.a0, s.a1);
if (s.a1 < s.a0)
s.a1 += 2*PI;
assert(isNormalized(s));
}
bool intersectionNormalized(TSector const& s0, TSector const& s1,
TSector& intersection)
{
assert(isNormalized(s0) && isNormalized(s1) && s0.a0 <= s1.a0);
bool isIntersecting = false;
if (s1.a0 <= s0.a1) // s1.a0 inside s0 ?
{
isIntersecting = true;
intersection.a0 = s1.a0;
intersection.a1 = std::min(s0.a1, s1.a1);
}
else if (s0.a0+2*PI <= s1.a1) // (s0.a0+2*PI) inside s1 ?
{
isIntersecting = true;
intersection.a0 = s0.a0;
intersection.a1 = std::min(s0.a1, s1.a1-2*PI);
}
assert(!isIntersecting || isNormalized(intersection));
return isIntersecting;
}
main()
{
TSector s0, s1;
s0.a0 = ...
normalize(s0);
normalize(s1);
if (s1.a0 < s0.a0)
std::swap(s0, s1);
TSection intersection;
bool isIntersection = intersectionNormalized(s0, s1, intersection);
}