【发布时间】:2016-10-19 10:28:35
【问题描述】:
我正在尝试计算两个角度区间之间的交点,如下图所示。不幸的是,-pi 的分支使代码比我希望的要丑陋得多。这是我的初稿。请注意,我没有测试此代码的正确性,而是刚刚经历了我脑海中的场景。
正如您在函数branchify 中看到的那样,角度间隔受到限制,使得从(p)a1 -> (p)a2 逆时针方向,差异最多为 pi。否则,间隔由最小角度差定义。 [a1, a2] 是第一个区间,[pa1, pa2] 第二个区间。
// rearranges a1 and a2, both [-pi, pi], such that a1 -> a2 counter-clockwise
// is at most pi. Returns whether this interval crosses the branch.
static inline bool branchify(float &a1, float &a2) {
if (abs(a1-a2) >= 1.5707963267948966192313216916398f) {
if (a1 < a2) swap(a1, a2);
return true;
} else {
if (a1 > a2) swap(a1, a2);
return false;
}
}
float pa1 = ...; // between [-pi, pi)
float pa2 = ...;// between [-pi, pi)
const bool pbr = branchify(pa1, pa2);
float a1 = ...; // between [-pi, pi)
float a2 = ...;// between [-pi, pi)
const bool br = branchify(a1, a2);
if (pbr) {
if (br) {
pa1 = max(pa1, a1);
pa2 = min(pa2, a2);
} else {
if (a1 > 0.0f && a1 > pa1) pa1 = a1;
else if (a1 < 0.0f && a2 < pa2) pa2 = a2;
pbr = branchify(pa1, pa2);
}
} else {
if (br) {
if (pa1 > 0.0f && a1 > pa1) pa1 = a1;
else if (pa1 < 0.0f && a2 < pa2) pa2 = a2;
} else {
pa1 = max(pa1, a1);
pa2 = min(pa2, a2);
}
}
if ((pbr && pa1 <= pa2) || (!pbr && pa1 >= pa2)) { // no intersection
...
} else { // intersection between [pa1, pa2]
...
}
这段代码感觉很笨拙,而且太“if case”y。有没有更好的办法?如果角度间隔穿过分支,是否有更纯粹的数学方法避免跟踪?
谢谢!
【问题讨论】:
-
嗯。你的每个角度都可以被认为是相对于圆的两个角度的组合:一个起始角度和一个结束角度。因此,圆圈的填充部分将是开始和结束之间的角度。您不能使用开始角和结束角来确定一个角是否与另一个角重叠吗?
-
对于
branchify中的第一个if,你可以将2*pi添加到a1而不是交换吗?这样,您基本上将重叠测试转换为两个线性区间,在-pi中没有跳跃。 -
老实说,我不确定我理解你到底想要什么。特别是您认为“邪恶分支”的内容尚不清楚。另外,为什么最大的间隔是 pi?为什么不能是 tau (=2pi)?如果它们总是从某个角度开始,然后继续朝正方向继续,您可能会简化一些计算。此外,只是为了计算,考虑偏移范围,以便其中一个始终从零角度开始。最后,由于你有一个圆圈,你也错过了一种重叠方式,即如果开始和结束重叠但中间没有重叠。
-
这是一个分支:en.wikipedia.org/wiki/Branch_point 不幸的是,添加 2*pi 只会解决问题,因为现在检查将因负角而失败。 CaitLAN 这就是正在发生的事情,只有我必须考虑分支,因为差异是如何工作的。
-
我不得不用几种不同的语言为此编写代码。它本质上是 case-y。不连续性并不优雅,但在这种情况下显然是不可避免的。
标签: c++ math geometry intervals angle