2012-09-02 15 views
16

私は、AがBの一定の距離内にある場合に文字Aが文字Bを見ることができるかどうかを文字を「見る」ことができるかどうかを確認しながら、角度Aの角度は、角度Bの+/- 45度である。これは、我々は360度線を越えたときを除いて正常に動作します角度が2つの角度の間であるかどうかを計算する

(facingAngle - 45) =< angleOfTarget =< (facingAngle + 45) 

場合

現在、私がチェックしてる少し計算を行います。 としましょう。このような状況では、ターゲットは中心から6度しか離れていないので、関数をtrueに戻す必要があります。残念ながら、5は314と404

+0

可能な重複(http://stackoverflow.com/questions/11406189/determine-if-angle-lies- 2つの他の角度間) – sschuberth

答えて

14

だけの理由が違いということです

anglediff = (facingAngle - angleOfTarget + 180 + 360) % 360 - 180 

if (anglediff <= 45 && anglediff>=-45) .... 

を試してみてくださいアングルの角度はfacingAngle - angleOfTargetですが、折り返し効果のために360度ずれている可能性があります。

180を加算して360を法とし、180を減算して効果的にすべてを-180〜180度の範囲に変換します(360度の加算または減算による)。

次に、-45度から45度の範囲内で角度差を簡単に確認できます。

+1

ファーで私は話題のケースではうまくいきませんでしたが、Pythonでテストしました。そこで、私はパスカルに戻って、なぜそこで動作していないのか理解しました。パスカルの 'mod'は負の数値では機能しません... – JHolta

+1

facesAngleが0でangleOfTargetが359の場合、例えば。 私が何かを逃していない限り、あなたは(0 - 359 + 180)%360 - 180 = -359を得ます。 facingAngle - angleOfTarget引き算の周りに絶対値が必要です。 –

+0

Java(Android)で完全にテストされています。できます。 – pascalbros

0

間(負の値に変換する)ローエンドで包む処理するための簡単な解決策ではありません、ただ、すべての値に360を追加することです:

(facingAngle + 315) =< (angleOfTarget + 360) =< (facingAngle + 405) 

そうすれば、 45の減算は、もはや起こらないので、負になることはありません。上端に包む処理するには

、あなたはangleOfTarget値に 360を追加し、再チェックする必要があります。

canSee = (facingAngle + 315 <= angleOfTarget + 360) && 
      (angleOfTarget + 360 <= facingAngle + 405); 
canSee |= (facingAngle + 315 <= angleOfTarget + 720) && 
      (angleOfTarget + 720 <= facingAngle + 405); 
8

ラッピング問題を回避する三角法があります。

P1との両方の座標が(x、y)であることを前提としています。あなたはすでに、ピタゴラスの定理を使って計算された2つの間の距離を知っていると指定しました。

あなたはそれらの間の角度を計算するために2つのベクトルの内積を使用することができます。

A . B = |A| . |B| . cos(theta). 

あなたはfacingAngleベクトルとしてAを取る場合、それは[cos(fA), sin(fA)]になり、1の大きさ|A|を持つことになります。

次の2つの文字間のベクトルとしてBを取り、あなた以上のあなたの距離を取得する場合:

cos(theta) = (cos(fA) * (P2x - P1x) + sin(fA) * (P2y - P1y))/|B| 

ここで、|B|は既に計算した距離です。

-45〜+45の範囲では、cos(theta) >= 0.70710678(つまり1/sqrt(2))を確認するだけでよいので、実際に逆余弦をとる必要はありません。thetaです。

これはおそらくと思われるかもしれませんが、お使いのプログラムに必要なすべての変数が既に用意されている可能性があります。

6

ここでは、私がオンラインで見つけた簡単な機能を変更しました。 これはどの角度でも正しく動作します(0-360の外にあります)。 (この関数は、Cで動作するように構成されている、Xcodeで動作する。)

それは角度が:)

間にある場合は、 YES(true)を返し、角度Aから角度Bに反時計回りにチェックし、覚えて

まず、簡単な変換機能角度が:)

//check if angle is between angles 
static inline BOOL angle_is_between_angles(float N,float a,float b) { 
N = angle_1to360(N); //normalize angles to be 1-360 degrees 
a = angle_1to360(a); 
b = angle_1to360(b); 

if (a < b) 
return a <= N && N <= b; 
return a <= N || N <= b; 
} 

であれば、すべての角度1から360

//function to convert angle to 1-360 degrees 
static inline double angle_1to360(double angle){ 
angle=((int)angle % 360) + (angle-trunc(angle)); //converts angle to range -360 + 360 
if(angle>0.0) 
return angle; 
else 
return angle + 360.0; 
} 

チェックをします

例:角度300は、180〜10度であるかどうかを確認するには:

BOOL isBetween=angle_is_between_angles(300, 180,10); 

// YESを返し

+1

trunc()がMath.floor()に置き換えられた場合、Javaで動作するようです。 – mindoverflow

0

常に最小の正の差を利用して、しきい値と比較するもう一つの方法:オリオン座ゼータ星の答えを修正再表示

anglediff = Math.min(Math.abs(facingAngle - angleOfTarget), 360 - Math.abs(angleOfTarget - allowDirection)); 
if (anglediff <= 45) 
0

別のやり方では、360度の角度ラップを避ける解決策は、角度が常に小さい異なる座標系で問題を再現することである。コードは次のとおりです。

def inside_angle(facing, target): 
    dot = cos(facing)*cos(target) + sin(facing)*sin(target) 
    angle = acos(dot) 

    return angle <= pi/4 

これはベクトル投影を使用して行われます。 | target> = [cos(target)sin(target)]と仮定すると、ターゲットを向ベクトルに投影すると、角度はゼロからターゲットは対面するベクトルに正確にあるか、どちらかの側に増加します。このようにしてpi/4(45度)と比較することができます。角度の式は以下である:|対向>及び|

ある
cos(angle) = <facing|target>/<target|target> <facing|facing> 

、角度の余弦ベクトル間のドット積であるターゲット>この場合には1であり、それらのモジュールを、分割されなる:

angle = acos(<facing|target>) 

リファレンス: https://en.wikipedia.org/wiki/Vector_projection

[角度が2つの他の角度の間にあるかどうかを確認]の
関連する問題