我有一个旋转的圆圈 . 请参见下面的图片 . 圆被分成不同程度的段,对于这个例子,我将圆分成三个相等的120度段 .
给定一个影响点(圆的外半径上的一个点),我计算圆心和冲击点之间的度数 . 然后,我需要确定哪个细分受影响 .
我目前的解决方案是这样的:
var circleRotation = 270;
var segments = [120, 120, 120];
function segmentAtAngle(angle) {
var sumTo = circleRotation;
for (var i = 0, l = segments.length; l > i; i++) {
if (sumTo <= angle && sumTo + segments[i] >= angle) {
// return the segment
return i;
}
sumTo += segments[i];
}
}
我的解决方案在所有情况下都不起作用,假设270的大偏移量,并且当在冲击度45处请求该段时,我目前几乎没有提供任何东西 .
注意:为segmentAtAngle和circleRotation提供的角度也永远不会为负或高于360.我将度数标准化为 { degrees = degrees % 360; if (degrees < 0) degrees += 360; return degrees; }
在给定偏移旋转的情况下,计算圆的命中段的正确方法是什么?
3 回答
一个简单的临时解决方案将复制您的细分列表 . 然后你的整个范围从0°到2·360°= 720°覆盖 . 如果
angle
和circleRotation
介于0°和360°之间(正如您所说的那样),那么它们的总和将介于0°和720°之间,并且具有两倍的段列表将在所有情况下产生匹配 . 如果结果索引大于或等于原始未重复列表的长度,则可以减去该长度以从该原始列表中获取索引 .首先,你的
for
循环的条件看起来很奇怪 .l
将始终大于零,因此循环将永远不会执行 . 其次,每次添加时都应该标准化sumTo
. 第三,在循环中返回angle
,它永远不会改变 . 您想要返回受影响的段的索引吗?函数
atan2(DY, DX)
将为您提供从中心到任意点的角度 . 该角度将在-pi to +pi
范围内 . 为了便于讨论,我们将其转换为-180..+180°
范围 .现在考虑段的分界角,就好像通过相同的函数获得:它们将对应于范围
[-120..0]
,[0..120]
和[120, -120]
. 一切都很好,除了第三个区间跨越不连续性,它应该被分成[120..180]
和[-180..-120]
.最后,您应该考虑这个边界列表,以及相应的扇区:
使用
N
颜色,您需要考虑N+1
间隔并与N
边界进行比较(无需检查极值,它们是隐式实现的) . 您将通过线性或二分法搜索(或在等距边界的情况下进行简单重新缩放)来完成此操作 .