0

あるオブジェクトが別のオブジェクトに面しているか、別のオブジェクトの背後にあるかを計算するより良い方法を探しています。これまでのところ、これを作成できましたが、100% 正しく動作していないようです :(

また、度ではなくラジアンである必要があると思います。

public static float GetAngle(float x1, float y1, float x2, float y2)
{
    float xDiff = x2 - x1;
    float yDiff = y2 - y1;
    var angle = RadianToDegree((float)Math.Atan2(yDiff, xDiff));

    if (angle < 0)
        return 360 + angle;

        return angle;
    }

public static bool IsFacing(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
    var angleBetweenPoints = GetAngle(obj, target);

    return rotationAngle >= angleBetweenPoints - arcDegree / 2 && rotationAngle <= angleBetweenPoints + arcDegree / 2;
}

public static bool IsBehind(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
    var angleBetweenPoints = GetAngle(obj, target);
    var backViewAngle = rotationAngle > 180 ? rotationAngle - 180 : 180 - rotationAngle;
    return backViewAngle >= angleBetweenPoints - arcDegree / 2 && backViewAngle <= angleBetweenPoints + arcDegree / 2;
}
4

1 に答える 1

0

一見すると、問題はメソッドのrotationAnglevsangleBetweenPointsのテストにあるように見えます。IsFacing()

与えられた:

rotationAngle = 0, angleBetweenPoints = 350, arcDegree = 180

次に、テストは次のようになります。

test = 0 >= (350 - 180 / 2) && 0 <= (350 + 180 / 2)
     = 0 >= 260 && 0 <= 440
     = false

これはかなり頻繁に発生し、角度に [0..360] の範囲を使用しているためです。これは場合によっては役立ちますが、これはそのようなケースの 1 つではありません。ここではるかに役立つのは、[-180..180] の範囲で方位角と目標角の差を取得することです。これにより、 との比較arcDegreeがはるかに簡単になります。

これを試して:

// Adjust a value to fit in the specified range
public static float Clamp(float v, float low, float high)
{
    float range = high - low;
    float modifier = ((int)((v - low) / range) - (v < low ? 1 : 0)) * range;
    v -= modifier;
    return v;
}

// Get the angle between a point+heading and another point
// Returns an angle in the range (-180..180) where:
//  res < 0     target clockwise from heading
//  res == 0    target at heading
//  res > 0     target counter-clockwise from heading
static float RelativeAngle(float heading, float x1, float y1, float x2, float y2)
{
    // get angle between points in world coordinates
    float angle = RadianToDegree((float)Math.Atan2(y2 - y1, x2 - x1));
    // adjust to local coordinates and normalize
    return Clamp(angle - heading, -180, 180);
}

public static bool IsFacing(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
    var angleBetweenPoints = RelativeAngle(rotationAngle, obj.x, obj.y, target.x, target.y);
    return angleBetweenPoints >= -(arcDegree / 2) && angleBetweenPoints <= (arcDegre / 2);
}
于 2013-02-15T03:15:01.677 に答える