質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Q&A

解決済

3回答

5194閲覧

始点,終点,中心点,方向から円弧の角度を求めたい

Shake_Salmon

総合スコア1

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

0グッド

0クリップ

投稿2020/05/09 13:22

前提・実現したいこと

引数として、始点(x,y),終点(x,y),中心点(x,y)と方向(時計回り/反時計回り)を受け取り、
円弧を描画するための角度を求めようとしております。
現在、内積を求めるところまでは出来たのですが、ここからどのようにして円弧の角度を求めてよいかがわかりません。
もし、ご存知の方がいらっしゃいましたらご教示ください。

該当のソースコード

C#

1/// <summary> 2/// 描画する円弧の角度を取得する 3/// </summary> 4/// <param name="spX">始点X</param> 5/// <param name="spY">始点Y</param> 6/// <param name="epX">終点X</param> 7/// <param name="epY">終点Y</param> 8/// <param name="cpX">中心点X</param> 9/// <param name="cpY">中心点Y</param> 10/// <param name="isClockwise">円弧の向きが時計回りの場合はtrue</param> 11/// <returns>算出した角度</returns> 12private double A(double spX, double spY, double epX, double epY, double cpX, double cpY, bool isClockwise) 13{ 14 double normSX = 0; // 中心点から始点に対するX座標のベクトル長 15 double normSY = 0; // 中心点から始点に対するY座標のベクトル長 16 double normEX = 0; // 中心点から終点に対するX座標のベクトル長 17 double normEY = 0; // 中心点から終点に対するY座標のベクトル長 18 19 double rootS = 0; 20 double rootE = 0; 21 double sqRoot = 0; 22 double numerator = 0; 23 double cos = 0; 24 double rad = 0; // 求めた内積のラジアン値 25 double angle = 0; // 求めた内積の角度 26 bool isReverse = false; //求めた内積角を反転させるか 27 28 // ベクトル長算出(中心点から始点) 29 normSX = spX - cpX; 30 normSY = spY - cpY; 31 // ベクトル長算出(中心点から終点) 32 normEX = epX - cpX; 33 normEY = epY - cpY; 34 // ベクトルの平方根を求める(=分母) 35 rootS = Math.Pow(normSX, 2) + Math.Pow(normSY, 2); 36 rootE = Math.Pow(normEX, 2) + Math.Pow(normEY, 2); 37 sqRoot = Math.Sqrt(rootS * rootE); 38 numerator = ( ( normSX * normEX ) + ( normSY * normEY ) ); 39 // コサインを求める 40 cos = ( numerator / sqRoot ); 41 // アークコサインを求める 42 rad = Math.Acos(cos); 43 // ラジアン値から角度を求める 44 angle = Math.Round((double)( rad * 180 / Math.PI )); 45 // 内積の角度を使用するか、外積の角度を使用するか判断する-S 46 // ここがわからない 47 // 内積の角度を使用するか、外積の角度を使用するか判断する-E 48 return angle; 49}

試したこと

始点と終点の大小関係などを考慮して判断処理を入れたりなどもしたのですが、
想定の結果を現在得られていません。

補足情報(FW/ツールのバージョンなど)

.net FW4.5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

x軸が左から右に向かって正であり、y軸が下から上に向かって正である一般的なデカルト座標系を仮定して話を進める。
Math.Atan2(y,x)というメソッドがある。これを使うことで、原点と点(x,y)をつなぐ線分が、x軸の正の向きと反時計回りになす角を-π~πの範囲で得ることができる。
これを利用して、始点を(xs,ys),終点を(xg,yg),中心点を(xc,yc)として、(Math.Atan2は以下Atan2と表記)
Atan2(yg-yc,xg-xc)-Atan2(ys-yc,xs-xc)
をすれば、とりあえず「反時計回りに回転する角」が得られる。負の数であればその絶対値分時計回りの回転を意味する。
「反時計回り」で正の値ならそのまま、負の値なら2πを加える。
「時計回り」で負の値なら絶対値を取り、正の値なら2πから引く。
そうして得られた角に半径を掛ければ、円弧の長さになる。

投稿2020/05/09 17:40

編集2020/05/10 03:17
swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shake_Salmon

2020/05/10 02:39

ありがとうございます。 とても具体的に記載されていて大変助かりました。 Math.Atanだと引数が合わなかったので、Math.Atan2のメソッドを利用しました。 おかげさまで取得したい角度を求めることができました。
swordone

2020/05/10 03:17 編集

あ、なんで2がなくなってるんだ…(書き忘れ) 追記:修正しました。
guest

0

ベクトルa,b の内積 P = |a||b|cosθ だから cosθ = P/(|a||b|)
a = b = 半径r だから cosθ = P/(r*r)

投稿2020/05/09 16:08

編集2020/05/09 16:12
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shake_Salmon

2020/05/10 02:42

回答いただきありがとうございます。 多分、正しいのだと思いましたが、私の数学力の無さが原因で頂いた回答を理解できずソースにまで落とし込むことが出来ませんでした・・・。 ありがとうございます。
guest

0

点を2つ与えられたときに、それを結ぶ直線の角度は算出できるでしょうか。
始点の角度と終点の角度がわかればいいのでは

投稿2020/05/09 15:10

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問