午後わてんのブログ

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

WPF、ベジェ曲線、違和感なく滑らかになるような制御点座標はどこ?その2、アプリでの角度とラジアン、座標から角度

VBC#だと便利な三角関数が用意されているけど、角度じゃなくてラジアンが基本になる
ラジアンは日本語だと弧度っていうらしい
 
角度とラジアン
 
イメージ 1
角度の180度はラジアンだと3.14、パイだと1パイ(π)
 
ラジアンを角度に変換する
ラジアン/パイ*180 = 角度
 
 
 
 
アプリの座標は算数とは上下が逆
イメージ 4
 
 
 
右回り(時計回り)、左回り

f:id:gogowaten:20191213122124p:plain

原点から右に伸ばしたところが0度になって、そこから
左回りだとマイナス
右回りだとプラスのラジアンが返ってくる
180を超えるとそれぞれ符号が逆になって数値も逆周りと同じになる
下側半周はプラスで上がわ半周はマイナスになるみたい
 
 
 
エクセルのATAN2関数で座標からラジアンを求めてみる
イメージ 3
座標はアプリの座標で右回りに一周するように上から並べてある
DEGREES関数でラジアンを角度に変更
 
 
 
 
VBC#にも座標からラジアンを返す関数Math.Atan2ってのがあるけど
エクセルとは引数の順番が逆!
イメージ 5
Math.Atan2(y,x)
紛らわしい

イメージ 19
WPF(VBC#)のMath.Atan2もエクセルのATAN2も結果は同じ
 
 
上下逆だったり、似た関数の引数の順番が逆だったりだけど、これで座標から角度を得られる
 
前回は方向線の長さをいろいろ変えてみたけど答えが出なかったので
方向線の角度を変えれば、もう少し良くなるんじゃないかと
思いついたのは
イメージ 6
今のアンカー点から始点側のアンカー点の線分の角度と
今のアンカー点から終点側のアンカー点の線分の角度
この2つの中間角度に直角になるような角度の方向線


こんな流れで

f:id:gogowaten:20191213122221p:plain

相変わらずエクセル方眼紙は便利だなあ
 
 
イメージ 7
xy
-2 -2 始点側のアンカー点
0 0 今のアンカー点、これの方向線の角度を求める
4 -2 終点側のアンカー点
 
 
始点側、終点側それぞれの角度
イメージ 9
Math.Atan2(y, x)を使ってラジアンを求める
始点側y-今yと始点側x-今xを引数にして
Math.Atan2(-2-0, -2-0)
Math.Atan2(-2, -2)、この結果が-2.356ラジアン、角度だと-135度
イメージ 10
終点側y-今yと終点側x-今xを引数にして
Math.Atan2(-2-0, 4-0)
Math.Atan2(-2, 4)、この結果が-0.464ラジアン、角度だと-26.57度
イメージ 11

f:id:gogowaten:20191213122244p:plain

 
 
中間角度

f:id:gogowaten:20191213122305p:plain

単純に2つの角度を足して2で割る
(-135-26.6)/2=-80.8度
(-2.356-0.464)/2=-1.41ラジアン
 
 
中間角度に直角になる角度
イメージ 13
右回りと左回り両方あるので、中間角度に90度を足す、引くでそれぞれになる
足す -80.8+90=9.2度
引く -80.8-90=-170.8度
180度の半分が90度で
180度のラジアンが1パイ=3.14なので、その半分が90度とおなじになる
足す -1.41+(1パイ/2.0)=0.161ラジアン
引く -1.41-(1パイ/2.0)=-2.981ラジアン
 
 
これで2つの角度がわかったけど、どちらが始点側の方向線角度なのか
イメージ 14
始点側角度と終点側角度を比較して
始点側角度>終点側角度なら
足したほうが始点側方向線角度
引いたほうが終点側方向線角度
もし、比較結果が逆なら適用も逆
 
今回のは始点側-135、終点側-26.6で逆なので適用する方も逆になって
引いたほうが始点側方向線角度
足したほうが終点側方向線角度で
イメージ 15
これでできた!
けどよくわかっていない
 
 
 
イメージ 17
距離が1なら、制御点位置はこんな感じになるはず
 
 
using System;
using System.Windows;

namespace _20181027_ラジアン_角度
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            RadianTest(new Point(-2, -2), new Point(0, 0), new Point(4, -2));
            //RadianTest(new Point(-2, 2), new Point(0, 0), new Point(4, 2));
            //RadianTest(new Point(6, -2), new Point(0, 0), new Point(2, -2));
            //RadianTest(new Point(2, -2), new Point(0, 0), new Point(6, -2));
        }

        /// <summary>
        /// ベジェ曲線の前後のアンカー点から方向線弧度を計算
        /// 中間角度に直角
        /// </summary>
        /// <param name="begin">始点側アンカー点</param>
        /// <param name="current">現在アンカー点</param>
        /// <param name="end">終点側アンカー点</param>
        private void RadianTest(Point begin, Point current, Point end)
        {
            double 始点側アンカー弧度 = GetRadianFrom2Points(current, begin);
            double 終点側アンカー弧度 = GetRadianFrom2Points(current, end);
            double 中間弧度 = (始点側アンカー弧度 + 終点側アンカー弧度) / 2.0;
                        
            double 始点側方向線弧度, 終点側方向線弧度;
            if (始点側アンカー弧度 > 終点側アンカー弧度)
            {
                始点側方向線弧度 = 中間弧度 + (Math.PI / 2.0);//右回りに直角
                終点側方向線弧度 = 中間弧度 - (Math.PI / 2.0);//左
            }
            else
            {
                始点側方向線弧度 = 中間弧度 - (Math.PI / 2.0);
                終点側方向線弧度 = 中間弧度 + (Math.PI / 2.0);
            }
            double 始点側方向線角度 = RadianToDegree(始点側方向線弧度);
            double 終点側方向線角度 = RadianToDegree(終点側方向線弧度);
        }
        
        //2点間線分のラジアン(弧度)を取得
        private double GetRadianFrom2Points(Point begin, Point end)
        {
            return Math.Atan2(end.Y - begin.Y, end.X - begin.X);
        }
        
        //ラジアンを角度に変換
        private double RadianToDegree(double radian)
        {
            return radian / Math.PI * 180.0;
        }
    }
}
 
 
イメージ 18
始点側アンカー点(-2,-2)
今のアンカー点(0,0)
終点側アンカー点(4,-2)
のとき今のアンカー点の方向線角度は
始点側方向線角度が-170.8
終点側方向線角度が9.2
できた!
 
 
 
 
 
ラジアンは高校で習うらしいんだけど、全く記憶にない、もしかしたら分散と同じように文系の普通科高校では習わないのかも?とぐぐったら
高校二年三角関数で弧度法(ラジアン 字が間違っていればすいません... - Yahoo!知恵袋
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q139664333
1994年から2002年の間はなかったみたい、だけどもっと昔だからなあ
 
第2章 普通教育に関する各教科 第4節 数学:文部科学省
http://www.mext.go.jp/a_menu/shotou/cs/1320230.htm
平成15年から復活したみたい、平成15年が西暦何年かわかんないけど、これも違うかなあ
 
新学習指導要領における数学について
http://www003.upp.so-net.ne.jp/chief/newmath.htm
ここは2003年から復活ってある、もしかして15年が2003年?
でも普通科では扱わなかった時期があったのは確かみたい
普通科ってなんなんだろうねえ
 
三角関数でもわかっていないから理解はできないんだけど、存在を知っているのと知らないのではぜんぜん違うんだよなあ、知らなければ聞くことも調べることもできない
ラジアンをググった感想は、なるほどわからん
 
 
 
 
関連記事
前回、2018/10/27
WPFベジェ曲線、違和感なく滑らかになるような制御点座標はどこ?その1 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15728810.html