午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

マウスドラッグでラベルコントロールの移動と直線の描画その4、三角関数

gogowaten.hatenablog.com

2日前の続き

 

今度こそ頂点の追加を修正した

 
直線以外の曲線も描画してみた

VBにはいろいろな線の描画があって簡単に変更できる
 
頂点の追加する時の判定方法を座標から角度に変えた
イメージ 1
始点(0)から終点(3)まで順番につながった直線の
2と3の間をクリックして新頂点を追加する場合
0,1,2,3を
0,1,2,新(3)、4にしたい
目的は2の次に新を入れる
目で見れば簡単にわかるのにw
今まではそれぞれの直線をグラフの関数にして新頂点がそれに当てはまるかで
判定していたけどうまくいかないことがあるので他の方法…
今回は角度で判定
 
イメージ 2
0から1の直線と0から新への直線の角度
1から2の直線と1から新への直線の角度
2から3の直線と2から新への直線の角度
一番小さい角度が当たりってことにした
上の場合は2から3が当たりなので新頂点は2の次に入れればいいことになる
 
角度の出し方、求め方
三角関数を使う
VBには三角関数が用意されているのでそれを使えばいい
だけど使い方がわからないというか三角関数自体が理解できないので
どれをどう使えばいいのかわからないw
ググって
三角関数の基礎 SIN サイン 正弦 COS コサイン 余弦 TAN タンジェント 正接 ASIN ACOS アークコサイン COS-1 ATAN DEGREES RADIANS 度 角度 ラジアン 斜辺 対辺 隣辺 エクセル Excel [エクセルの学校]
ここ
さすが神アプリエクセル、三角関数もある

f:id:gogowaten:20191016110853p:plain

なんとなくわかったのが2辺の長さで角度が得られる
辺の名前はそれぞれ斜辺、隣辺、対辺
頂点の座標から簡単にわかる長さの辺は斜め以外の
隣辺と対辺
これに関係する三角関数タンジェント
角度を求める時はアークタンジェントで行けそう
 
エクセルもVBも返ってくる角度はラジアンで返ってくる
ラジアンとか知らないしわかりにくいので角度に変換は
エクセルならDEGREES関数に入れればいいだけ
VB
角度 = 180 / Math.PI * radian
角度=180/3.14*ラジアン
 
イメージ 4
画像の描画ではyは普通のグラフと違って上下が逆になる
どこを0にするか、どっち周りにするか迷った
0度と359度の差は
360度と359度にしないとおかしいことにさっき気づいて
片方が0度の時もう片方が180度以上なら0度を360度で計算するようにとか
3日くらいかかった
これで間違えることは少なくなった
正確にするには実際に線が描画されている場所を計算するか
もっと別の方法かなあ
どちらも思いつかないのでもう今回のこれでいいや
 
Private Sub ToolStripMenuItem頂点の追加_Click(sender As Object, e As EventArgs) Handles ToolStripMenuItem頂点の追加.Click
   '右クリックしたところに頂点を追加
    Dim newPoint As New Point(mousePoint) '新しい頂点の座標
    Dim ps As Generic.List(Of Point) = nowPic.PointN '頂点のコレクションリスト
    Dim i As Long

    Dim kakudo1, kakudo2 As Single '角度
    Dim oTaihen, oRinpen, nTaihen, nRinpen As Long '対辺と隣辺用
    Dim aryKakudo As New ArrayList '角度の差のリスト用
    Dim ore1 As New ArrayList
    Dim ore2 As New ArrayList

    For i = 0 To ps.Count - 2
        oRinpen = ps(i + 1).X - ps(i).X '始点から次点の隣辺の長さ
        oTaihen = ps(i + 1).Y - ps(i).Y '始点から次点の対辺の長さ
        nRinpen = newPoint.X - ps(i).X '始点から新頂点の隣辺の長さ
        nTaihen = newPoint.Y - ps(i).Y '始点から新頂点の対辺の長さ
        kakudo1 = ore角度(oTaihen, oRinpen)
        kakudo2 = ore角度(nTaihen, nRinpen)

       '二つの角度のどちらかが0でもう一方が180度以上なら0を360に変換する
        If kakudo1 = 0 And kakudo2 >= 180 Then
            kakudo1 = 360
        ElseIf kakudo2 = 0 And kakudo1 >= 180 Then
            kakudo2 = 360
        End If

        aryKakudo.Add(Math.Abs(kakudo1 - kakudo2)) '角度の差をリストに追加
        ore1.Add(kakudo1)
        ore2.Add(kakudo2)
    Next

   '角度の差が一番小さい頂点のインデックス番号を取得
    Dim min3 As Single = aryKakudo(0)
    Dim idx As Long = 0
    For i = 1 To UBound(aryKakudo.ToArray)
        If min3 > aryKakudo(i) Then
            idx = i
        End If
    Next
    nowPic.PointN.Insert(idx + 1, newPoint) '新頂点をexPictureBoxのPointNに挿入
    Call 頂点の初期化(nowPic)

End Sub

f:id:gogowaten:20191016110915p:plain

座標から対辺と隣辺の長さを取得して↓の「ore角度」関数に送って
返ってきた角度を比較して新頂点を挿入
 
Private Function ore角度(Taihen As Long, Rinpen As Long) As Single
   '対辺と隣辺を受け取って角度を返す
    Dim kakudo As Single
    If Taihen = 0 Or Rinpen = 0 Then '対辺と隣辺のどちらかが0の時は0,90,180,270のいずれか
        Select Case True
            Case Taihen = 0 And Rinpen > 0
                kakudo = 180
            Case Taihen = 0 And Rinpen < 0
                kakudo = 0
            Case Taihen > 0 And Rinpen = 0
                kakudo = 270
            Case Taihen < 0 And Rinpen = 0
                kakudo = 90
        End Select

    Else '対辺と隣辺どちらも0以外の時
        Dim radian As Single
        radian = Math.Atan(Taihen / Rinpen) 'ラジアン取得
        kakudo = 180 / Math.PI * radian 'ラジアンを角度に変換
        Select Case True '対辺と隣辺が+-で加算する値が変わる
            Case Taihen < 0 And Rinpen > 0 '対辺マイナスで隣辺プラスの時
                kakudo += 180
            Case Taihen < 0 And Rinpen < 0 '対辺隣辺どちらもマイナスの時
                kakudo += 0
            Case Taihen > 0 And Rinpen < 0 '対辺がプラスで隣辺がマイナスの時
                kakudo += 360
            Case Taihen > 0 And Rinpen > 0 '対辺隣辺どちらもプラスの時
                kakudo += 180
        End Select
    End If

    Return kakudo
End Function

f:id:gogowaten:20191016110933p:plain

対辺と隣辺の長さを受け取って角度を返す「ore角度」関数
あまり使ったことがないselect caseが活躍、使い方あってるかな
 
参照したところ
三角関数の基礎 SIN サイン 正弦 COS コサイン 余弦 TAN タンジェント 正接 ASIN ACOS アークコサイン COS-1 ATAN DEGREES RADIANS 度 角度 ラジアン 斜辺 対辺 隣辺 エクセル Excel [エクセルの学校]
 
 
ダウンロード
 
 
関連記事
今回のをもとにPixtack紫陽花に直線描画機能を追加
2014/12/24は1日後