[解決済み】直線と水平軸のなす角の計算方法とは?
2022-04-18 03:35:44
質問
プログラミング言語(Python、C#など)で、直線と横軸の角度を計算する方法を知りたいのですが。
画像は私が欲しいものを最もよく表していると思います。
与えられた(P1 <サブ x ,P1 <サブ y ) と (P2 <サブ x ,P2 <サブ y ) この角度を計算するのに最適な方法は何でしょうか?原点は左上にあり、正の四分円のみ使用します。
解答方法は?
まず、始点と終点の差を求めます(線は無限に伸びていて特定の点から始まらないので、これは線分ではなく、有向線分と言えます)。
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
次に、角度(X軸の正の部分から
P1
にある正のY軸に
P1
).
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
しかし
arctan
というのも、この方法で差分を分割すると、角度がどの象限にあるかを区別するのに必要な区別が消えてしまうからです(下記参照)。もしあなたの言語に
atan2
関数を使用します。
angleInDegrees = atan2(deltaY, deltaX) * 180 / PI
EDIT(2017年2月22日)。ただし、一般的には
atan2(deltaY,deltaX)
に対して適切な角度を得るためだけに
cos
と
sin
はエレガントでない場合があります。そのような場合は、代わりに以下のようにすることがよくあります。
-
扱う
(deltaX, deltaY)
をベクトルとして扱います。 -
そのベクトルを単位ベクトルに正規化する。これを行うには
deltaX
とdeltaY
は、ベクトルの長さによって (sqrt(deltaX*deltaX+deltaY*deltaY)
ただし、長さが0である場合を除く。 -
その後
deltaX
は,ベクトルと水平軸(で正の X 軸から正の Y 軸に向かう方向)とのなす角の余弦となります.P1
). -
そして
deltaY
はその角度の正弦となる。 - ベクトルの長さが 0 の場合、水平軸との間に角度はありません(したがって意味のあるサインとコサインが得られません)。
EDIT(2017年2月28日)。正規化しなくても
(deltaX, deltaY)
:
-
の記号は
deltaX
は、手順3で記述したコサインが正なのか負なのかを教えてくれる。 -
の符号は
deltaY
を見れば、手順4で説明した正弦が正なのか負なのかがわかる。 -
の符号は
deltaX
とdeltaY
にある正の X 軸に対して、どの象限にあるかがわかります。P1
:-
+deltaX
,+deltaY
: 0~90度 -
-deltaX
,+deltaY
: 90度から180度 -
-deltaX
,-deltaY
: 180度~270度(-180度~-90度)。 -
+deltaX
,-deltaY
: 270度~360度(-90度~0度)です。
-
ラジアンを使ったPythonでの実装(2015年7月19日提供:Eric Leschinski氏、私の回答を編集してくれた)。
from math import *
def angle_trunc(a):
while a < 0.0:
a += pi * 2
return a
def getAngleBetweenPoints(x_orig, y_orig, x_landmark, y_landmark):
deltaY = y_landmark - y_orig
deltaX = x_landmark - x_orig
return angle_trunc(atan2(deltaY, deltaX))
angle = getAngleBetweenPoints(5, 2, 1,4)
assert angle >= 0, "angle must be >= 0"
angle = getAngleBetweenPoints(1, 1, 2, 1)
assert angle == 0, "expecting angle to be 0"
angle = getAngleBetweenPoints(2, 1, 1, 1)
assert abs(pi - angle) <= 0.01, "expecting angle to be pi, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 3)
assert abs(angle - pi/2) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(2, 1, 2, 0)
assert abs(angle - (pi+pi/2)) <= 0.01, "expecting angle to be pi+pi/2, it is: " + str(angle)
angle = getAngleBetweenPoints(1, 1, 2, 2)
assert abs(angle - (pi/4)) <= 0.01, "expecting angle to be pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(-1, -1, -2, -2)
assert abs(angle - (pi+pi/4)) <= 0.01, "expecting angle to be pi+pi/4, it is: " + str(angle)
angle = getAngleBetweenPoints(-1, -1, -1, 2)
assert abs(angle - (pi/2)) <= 0.01, "expecting angle to be pi/2, it is: " + str(angle)
全てのテストに合格する。参照 https://en.wikipedia.org/wiki/Unit_circle
関連
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
[解決済み] 関数デコレータを作成し、それらを連鎖させるには?
-
[解決済み] C#のStringとstringの違いは何ですか?
-
[解決済み] staticmethodとclassmethodの違いについて
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonのリストメソッドであるappendとextendの違いは何ですか?
-
[解決済み] 最小限の驚き」と「変更可能なデフォルトの引数
-
[解決済み】__str__と__repr__の違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】文字列が有効な DateTime " format dd/MM/yyyy " として認識されなかった。
-
[解決済み】SmtpException: トランスポート接続からデータを読み取れません:net_io_connectionclosed
-
[解決済み】Sequence contains no matching element(シーケンスにマッチする要素がない
-
[解決済み】値が期待した範囲に収まらない
-
[解決済み] 'IEnumerable<SelectListItem>' 型の ViewData アイテムで、キーが国であるものは存在しない。
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015
-
[解決済み] 2つの角度の差を求めるにはどうすればよいのでしょうか?