我试图计算两个Angular 间隔之间的交点,如下图所示。不幸的是,-pi的分支使代码比我希望的要丑陋得多。这是我的初稿。请注意,我还没有测试这段代码的正确性,只是在脑海中浏览了一下场景。
正如您在函数branchify
中看到的,Angular 间隔受到限制,使得从(p)a1 -> (p)a2
逆时针方向开始,差值最多为pi。否则,间隔由Angular 的 * 最小 * 差定义。[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“了。有更好的办法吗?一个更纯粹的数学方法,避免跟踪,如果一个角间隔交叉分支?
谢谢你,谢谢
4条答案
按热度按时间umuewwlo1#
让我们的结束角是
a1, a2
和b1, b2
则Angular 区间相交,如果
(第一条件-扇区
A
的平分线与矢量OB1
之间的Angular 小于半角da
)xqkwcwgp2#
我最近在一个游戏项目中遇到了这个问题。我的解决方案是首先将Angular 标准化为[0和360)度之间,然后检查是否有任何线段穿过邪恶的分支。如果有,就在恶分支处把它们分成两段,然后把它们各自独立的重叠角相加。我使用递归来简化分支场景。
下面是我用C#编写的代码,特别是Unity 3D:
如果两个线段的重叠Angular 足够接近于0,则可以轻松检查它们是否重叠。
6ljaweal3#
假设你将你的Angular 标准化为范围
[0..1]
,你可以使用overlapBetweenCircularNormalizedRanges
的实现:hyrbngr74#