午後わてんのブログ

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

Pathを等分したところに印と角度を表示してみた、GetPointAtFractionLength

 
PathGeometryクラスのGetPointAtFractionLengthを使って
Pathを等分したところに印と角度を表示してみた
 
今回のアプリのダウンロード先
GetPointAtFractionLength

f:id:gogowaten:20191213100602p:plain

うーん、よくわからん…Fraction(分数)
第1引数のprogressに渡すのは0から1の数値で、これがPathの長さ全体の比率になっていて、0.5を渡すとPathのちょうど真ん中の位置の座標をpointとして得られると同時にPoint型のtangentも得られる、角度はこのtangentから計算
 
 
 
イメージ 1
stepが分割数
水色の線が対象になるPathで4つの頂点を結ぶ直線
イメージ 6

角度は全部45度づつの変化になるような頂点のPath

そのPathをstep数で等分したところに○印と数値は角度
角度はどうやら等分したところから伸びる線の方向の角度みたいで、基準になる0度は真下で時計だと6時の方向、そこから反時計回りで右方向が90度で時計回りだとマイナスになるみたい、-45度は360度足すと-45+360=315度
 
 
1分割
イメージ 3
Pathの始点は左上で、そこから右下、右、左下で終点になっている、↘→↙の順番
初期状態では分割数はstep=001で1分割なので、表示される○は始点と終点の2つだけ
 
2等分
イメージ 4
始点から終点までの経路長を2等分する場所が角度90の表示のところの○
 
5等分
イメージ 5
イメージ 8
イメージ 9
 
 
↘→↑↖
イメージ 10
真上方向は180度になった、それを越えると-マイナス
 
デザイン画面

f:id:gogowaten:20191213100743p:plain

 
コード
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace _20180614_直線の等分したところに印
{
    public partial class MainWindow : Window
    {
        List<Path> MyListEllipse = new List<Path>();
        List<Label> MyListLabel = new List<Label>();

        public MainWindow()
        {
            InitializeComponent();

            MyInitialize();
        }
        private void SliderStep_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            ChangeStep();
        }
        //いろいろ初期化
        private void MyInitialize()
        {
            ChangeStep();
            SliderStep.ValueChanged += SliderStep_ValueChanged;
        }
        //表示をクリア
        private void ClearStepObject()
        {
            foreach (var item in MyListLabel)
            {
                MyCanvas.Children.Remove(item);
            }
            MyListLabel.Clear();
            foreach (var item in MyListEllipse)
            {
                MyCanvas.Children.Remove(item);
            }
            MyListEllipse.Clear();
        }
        //Step(分割)数変更時とかに実行
        private void ChangeStep()
        {
            ClearStepObject();//表示をクリア

            double step = SliderStep.Value;
            var pg = (PathGeometry)MyPath.Data;
            Point p, pt;
            for (int i = 0; i < step + 1; i++)
            {
                //GetPointAtFractionLengthの第1引数は計測する位置の割合を0から1で指定する
                //Path全体からの割合なので、中間を取得したいなら0.5を指定する
                //1個めのoutは指定した位置の座標が返ってくる
                //2個めのoutはタンジェント座標?が返ってくる、Math.Atan2に入れるとラジアンが得られる?
                pg.GetPointAtFractionLength(i / step, out p, out pt);
                //半径4の○印の作成
                var path = new Path();
                path.Stroke = Brushes.Blue;
                path.Data = new EllipseGeometry(p, 4, 4);
                MyCanvas.Children.Add(path);
                MyListEllipse.Add(path);

                //角度の計算とLabelの表示
                //GetPointAtFractionLengthで得られたタンジェントをMath.Atan2に入れると
                //ラジアンが得られるので、Math.PI*180で角度に変換
                var kakudo = Math.Atan2(pt.X, pt.Y) / Math.PI * 180;
                Label label = new Label();
                label.Content = kakudo;
                Canvas.SetTop(label, p.Y);
                Canvas.SetLeft(label, p.X);
                MyCanvas.Children.Add(label);
                MyListLabel.Add(label);

            }
        }

    }
}
 
角度の計算のところはよく解っていない、それっぽい数値をそれっぽい関数に入れたらそれっぽい数値が得られただけ、なので間違っているかも
Math.Atan2の引数はxとy逆だったかも、逆にしたら
イメージ 11
こうなった、こっちのほうが自然かな、水平で0度
そもそも角度を求めるならPathの座標は解っているんだから、そこから計算すればいいんだけど、曲線だった場合は前回のGetFlattenedPathGeometryと組み合わせると…
 
 
参照したところ
 
コード
 
関連記事
続きは翌日、2018/06/16
GetPointAtFractionLengthで分割した座標からのPathの長さ測定の確認 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15551929.html
 
前回、2018/06/14
曲線Pathを近似の直線PathにするGetFlattenedPathGeometry使ってみた ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15549065.html