在角度坐标系中判断2个角度是否有交集的正确处理方式
问题背景
有这样的需求,以x轴正方向为0度,逆时针建立0-360度的角度系 判断2个扇形有没有交集 比如判断355到15度 和 0到90度有没有交集。也就是说,并非以角度值的大小进行判断,而是可以横跨0度,存在355-15度这样的扇形角
研究方案
1.必须把每一个角度都规范到到360以内
2.直接处理355 - 15 这样的角度,要写大量的if else判断。4种情况,普通角和普通角比 普通角和跨域角比 跨越角和普通角比 跨域角和跨越角比。逻辑复杂且不好懂。编写这样的函数浪费了时间,而且大概率存在一定的bug
3.化繁为简,分段处理。把圆形角度化分到直线的坐标轴上面,比如355到15度,那不就是[355-360],[0-15]吗?
这样问题一下子简单起来,问题变成了,如何判断一个区间集合,和另外一个区间集合里面的区间有没有交集。
对于2个集合,我们可以遍历。核心是判断2个区间有没有交集,有交集的情况有很多种(头相交 尾相交 包含 被包含 。。),
但是不相交的情况只有2种: 如[a1,a2] [b1,b2], 不相交那么肯定是 a2 < b1 或者 a1 > b1。
核心代码
function haveIntersection(angle1_start, angle1_end, angle2_start, angle2_end) {
// 转换角度为区间
let interval1, interval2;
if (angle1_end >= angle1_start) {
interval1 = [[angle1_start, angle1_end]];
} else {
interval1 = [[angle1_start, 360], [0, angle1_end]];
}
if (angle2_end >= angle2_start) {
interval2 = [[angle2_start, angle2_end]];
} else {
interval2 = [[angle2_start, 360], [0, angle2_end]];
}
// 判断区间是否有交集
for (let int1 of interval1) {
for (let int2 of interval2) {
if (!(int1[1] <= int2[0] || int1[0] >= int2[1])) {
return true; // 有交集
}
}
}
return false; // 没有交集
}
其实核心逻辑只有一句!(int1[1] <= int2[0] || int1[0] >= int2[1]),用了正确处理思路之后,业务逻辑是简单而直接的
当我们的算法里面存在大量的if else的时候,就应该考虑是不是处理方式错了
总结
算法函数应该是直接而且优雅的

浙公网安备 33010602011771号