19

ある角度が他の 2 つの角度の間にあるかどうかを調べようとしています。これを実行するための単純な関数を作成しようとしましたが、角度のすべての可能な値に対して機能するテクニックはありません。

関数を編集して、角度が他の 2 つの角度の間にあるかどうかを正しく判断するのを手伝ってもらえますか?

ここに画像の説明を入力

上の写真では; 緑の点を中心点として使用し、緑の点に対する各線の角度を決定します。次に、緑の点に対する黒の点の角度を計算します。黒い点の角度が2本の線の角度の間にあるかどうかを確認しようとしています

注: 私の場合; 角度 (targetAngle) は、2 つの角度の差が < 180 度であり、targetAngle がそれらの 2 つの角度によって形成される空洞内にある場合、他の 2 つの角度の間にあると言われます。


次のコードは機能するはずですが、これらの場合は失敗します(角度の間にあります)
:

bool is_angle_between(int target, int angle1, int angle2) 
{  
  int rAngle1 = ((iTarget - iAngle1) % 360 + 360) % 360;  
  int rAngle2 = ((iAngle2 - iAngle1) % 360 + 360) % 360;  
  return (0 <= rAngle1 && rAngle1 <= rAngle2);  
}  

// Example usage  
is_angle_between(3, 41, 345);  

私が試みた別のテクニックも機能しません:

int is_angle_between(int target, int angle1, int angle2)
{
  int dif1  = angle1-angle2;
  int dif2  = angle2-angle1;
  int uDif1 = convert_to_positive_angle( dif1 ); // for eg; convert -15 to 345
  int uDif2 = convert_to_positive_angle( dif2 );

  if (uDif1 <= uDif2) {
    if (dif1 < 0) {
      return (target <= angle1 && target >= angle2);
    }
    else return (in_between_numbers(iTarget, iAngle1, iAngle2));
  }
  else {
    if (dif2 < 0) {
      return (target <= angle1 && target >= angle2);
    }
    else return (in_between_numbers(iTarget, iAngle1, iAngle2));
  }

  return -1;
}
4

11 に答える 11

11
bool is_angle_between(int target, int angle1, int angle2) 
{
  // make the angle from angle1 to angle2 to be <= 180 degrees
  int rAngle = ((angle2 - angle1) % 360 + 360) % 360;
  if (rAngle >= 180)
    std::swap(angle1, angle2);

  // check if it passes through zero
  if (angle1 <= angle2)
    return target >= angle1 && target <= angle2;
  else
    return target >= angle1 || target <= angle2;
}  
于 2012-07-10T11:13:35.177 に答える
9

モジュラー算術の間隔に関する投稿に触発されました:

static bool is_angle_between(int x, int a, int b) {
    b = modN(b - a);
    x = modN(x - a);

    if (b < 180) {
        return x < b;
    } else {
        return b < x;
    }
}

どこで(角度をチェックする場合)modN()は次のように実装されます

// modN(x) is assumed to calculate Euclidean (=non-negative) x % N.
static int modN(int x) {
    const int N = 360;
    int m = x % N;
    if (m < 0) {
        m += N;
    } 
    return m;
}
于 2015-11-24T11:29:46.800 に答える
4
void normalize( float& angle ) 
{
    while ( angle < -180 ) angle += 360;
    while ( angle >  180 ) angle -= 360;
}

bool isWithinRange( float testAngle, float a, float b )
{
    a -= testAngle;
    b -= testAngle;
    normalize( a );
    normalize( b );
    if ( a * b >= 0 )
        return false;
    return fabs( a - b ) < 180;
}
于 2014-05-08T18:42:48.193 に答える
2

angle2 が常に 0 で、 angle1 が常に 0 から 180 の間である場合、これは簡単です。

return angle1 < 180 && 0 < target && target < angle1;

要件を正しく読んでいる場合。

しかし、そこにたどり着くのはそれほど難しくありません。

int reduced1 = (angle1 - angle2 + 360) % 360; // and imagine reduced2 = 0
if (180 < reduced1) { angle2 = angle1; reduced1 = 360 - reduced1; } // swap if backwards
int reducedTarget = (target - angle2 + 360) % 360;
return reduced1 < 180 && 0 < reducedTarget && reducedTarget < reduced1;
于 2012-07-10T04:17:30.263 に答える
1

以前に角度を比較してこれを行いました。

ここに画像の説明を入力

上のスケッチでは、次の場合に限り、ベクトル AD は AB と AC の間にあります。

angle BAD + angle CAD == angle BAC

浮動小数点が不正確なため、最初に小数点以下 5 桁に丸めて値を比較しました。

したがって、2 つのベクトル間の角度アルゴリズムを持つことにpなり、次のqように簡単に言えます。

double a = p.DotProduct(q);
double b = p.Length() * q.Length();
return acos(a / b); // radians

ベクトルの DotProduct と Length の計算は、Google 検索の課題として残しておきます。また、一方の端子の座標を他方の端子から差し引くだけでベクトルを取得できます。

もちろん、最初に AB と AC が平行か逆平行かを確認する必要があります。

于 2012-07-10T16:36:19.420 に答える
0

私はこのスレッドからこの引用を見つけました:

点Pが三角形ABCの​​内側にある場合、

エリアPAB+エリアPBC+エリアPAC=エリアABC

PがAB、BC、またはCAの端にある場合、上記が成り立つことに注意してください。しかし、事実上、PAB、PBC、PACのいずれかの領域は0です(したがって、必ず確認してください)。

Pが外側にある場合、上記の等式は成り立たない...

面積を決定する方法は?2つのオプションがあります:1)ヘロンの公式、平方根を含み、遅い2)より好ましい方法は外積です(または事実上、(ダウン積の合計からアップ積の合計を引いた)の絶対値の半分)

たとえば、A =(x1、y1)B =(x2、y2)の場合、C =(x3、y3)Area = abs(x1 * y2 + x2 * y3 + x3 * y1-x1 * y3-x3 * y2- x2 * y1)/ 2

また、浮動小数点エラーに注意する必要があるかもしれません...厳密な不等式をチェックする代わりに、abs(ba)をチェックしてください。

うまくいけば、それが役立つでしょう

于 2012-07-10T03:48:06.360 に答える
0

角度 $$a$ と $b$ があり、角度xがこれらの角度の間にあるかどうかを確認したくない場合。

a->xとの間の角度を計算できますa->b∠a->xが 未満の場合、∠a->bxの間にある必要がaありbます。

角度間の距離、aおよびb

function distanceBetweenAngles(a, b) {
    distance = b - a;
    if (a > b) {
       distance += 2*pi;
    }
    return distance;
}

それからあなたはすることができます

// Checks if angle 'x' is between angle 'a' and 'b'
function isAngleBetween(x, a, b) {
    return distanceBetweenAngles(a, b) >= distanceBetweenAngles(a, x);
}

これは、度数ではなくラジアンを使用していることを前提としています。多くの不要なコードを削除します。

于 2016-02-09T18:49:18.990 に答える
0

あなたの質問と同様のスタイルの関数を使用して、次の方法でうまくいきました。

    public static bool IsInsideRange(double testAngle, double startAngle, double endAngle)
    {
        var a1 = System.Math.Abs(AngleBetween(startAngle, testAngle));
        var a2 = System.Math.Abs(AngleBetween(testAngle, endAngle));
        var a3 = System.Math.Abs(AngleBetween(startAngle, endAngle));
        return a1 + a2 == a3;
    }

    public static double AngleBetween(double start, double end)
    {
        return (end - start) % 360;
    }
于 2014-02-16T22:35:33.730 に答える