提问者:小点点

给定一个分段圆和一个撞击点,计算碰撞的分段


我有一个旋转的圆。例如,请参阅下面的图像。这个圆被分成不同程度的片段,在这个例子中,我将圆分成三个相等的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的分段时,我目前错误地提供了什么。

注意:为分割提供的角度AtAngle和CircleRotation也永远不会是负数或高于360。我通过{度=度%360; if(度

在给定偏移旋转的情况下,计算圆的命中段的正确方法是什么?


共3个答案

匿名用户

一个简单的临时解决方案是复制你的片段列表。然后你覆盖了从0°到2·360°=720°的整个范围。如果圈旋转在0°和360°之间,就像你说的那样,那么它们的总和将在0°和720°之间,并且拥有两倍的片段列表将在所有情况下产生匹配。如果生成的索引大于或等于原始未重复列表的长度,您可以减去该长度以从原始列表中获得索引。

匿名用户

首先,您的for循环的条件看起来有点奇怪。l将始终大于零,因此循环永远不会执行。其次,您可能应该在每次添加sumTo时对其进行标准化。第三,您在循环中返回,它永远不会改变。您想返回受影响段的索引吗?

var circleRotation = 270;
var segments = [120, 120, 120];
function standardize(degrees){
    degrees = degrees % 360; 
    if (degrees < 0) degrees += 360; 
    return degrees;
}
function segmentAtAngle(angle) {
    var sumTo = circleRotation;
    for (var i = 0; i<segments.length; i++) {
        if (sumTo <= angle && sumTo + segments[i] >= angle) {
            return i;
        }
        sumTo = standardize(sumTo + segments[i]);
    }
}

匿名用户

函数atan2(DY,DX)将为您提供从中心到任何点的角度。这个角度将在-pi到pi的范围内。为了讨论,让我们将其转换为-180…180°范围。

现在考虑你的片段的定界角度,就好像是由同一个函数获得的:它们将对应于范围[-120…0][0…120][120,-120]。一切都很好,除了第三个间隔跨越了不连续性,它应该被分成[120…180][-180…-120]

最后,您应该考虑这个边界列表,以及相应的扇区:

   -180    -120      0      120     180
      Yellow |  Red  | Green | Yellow

使用N颜色,您需要考虑N 1间隔并与N边界进行比较(无需检查极值,它们是隐式实现的)。您将通过线性或二分法搜索(或在等距边界的情况下简单重新缩放)来做到这一点。