今回のアプリのダウンロード先
昨日の続きで直線Pathの長さ測定
GetPointAtFractionLengthを使ってPathを等分割できたので、2点間の距離を測るユークリッド距離を使って長さを求める
普通ならこんな面倒なことしなくても、元の直線の座標から計算すればいいんだけど、確認のために試してみた
actually Path Lengthが実際の長さで
Path Length measureがGetPointAtFractionLengthを使って測定した長さ
結果は分割数が多いほど測定は正確になる
分割数1のとき
始点と終点との直線距離になるので実際の長さの383とはかけ離れた224が測定される、絵で見てもその測り方はおかしいってのがわかる
2等分だと292、さっきより近くなったけどまだ遠い
絵で見ても元の線に近い
4等分は317、3等分のときより正解から離れてしまった
分割数は多いほど正確になるはずなんだけど、そうならないこともある
46分割で測定したときに実際の長さとほぼ同じ長さになった
80分割、これ以上だと測定値は常に380以上になったので、分割数は多いほど誤差は小さくなるってのが確認できた
デザイン画面
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
namespace _20180614_PolyLine測定
{
public partial class MainWindow : Window
{
List<Path> MyListEllipse = new List<Path>();
List<Label> MyListLabel = new List<Label>();
List<Path> MyListLine = new List<Path>();
public MainWindow()
{
InitializeComponent();
MyInitialize();
}
private void SliderStep_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
ChangeStep();
}
private void MyInitialize()
{
ChangeStep();
SliderStep.ValueChanged += SliderStep_ValueChanged;
double pathLength = 0;
var pg = (PathGeometry)MyPath.Data;
Point p1 = pg.Figures[0].StartPoint;
var ls = (PolyLineSegment)pg.Figures[0].Segments[0];
for (int i = 0; i < ls.Points.Count; i++)
{
var p2 = ls.Points[i];
pathLength += Distance(p1, p2);
p1 = p2;
}
TextBlockTrueLength.Text =
"Actually Path Lenght = " +
Math.Round(pathLength, MidpointRounding.AwayFromZero).ToString();//四捨五入
}
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();
foreach (var item in MyListLine)
{
MyCanvas.Children.Remove(item);
}
MyListLine.Clear();
}
private void ChangeStep()
{
ClearStepObject();
double step = SliderStep.Value;
var pg = (PathGeometry)MyPath.Data;
Point p, pt;
Point p1 = pg.Figures[0].StartPoint;
Point p2 = p1;
double pathLength = 0;
for (int i = 0; i < step + 1; i++)
{
pg.GetPointAtFractionLength(i / step, out p, out pt);
var path = new Path();
path.Stroke = Brushes.Blue;
path.Data = new EllipseGeometry(p, 4, 4);
MyCanvas.Children.Add(path);
MyListEllipse.Add(path);
var kakudo = Math.Atan2(pt.Y, pt.X) / 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);
//長さ測定
p2 = p;
pathLength += Distance(p1, p2);
//測定対象の2頂点を結ぶ赤色の直線Pathの作成
var lineG = new LineGeometry(p1, p2);
p1 = p;
path = new Path();
path.Stroke = Brushes.Red;
path.Data = lineG;
MyCanvas.Children.Add(path);
MyListLine.Add(path);
}
TextBlockPathLength.Text =
"Path Length Measure = " +
Math.Round(pathLength, MidpointRounding.AwayFromZero).ToString();//四捨五入
}
private double Distance(Point p1, Point p2)
{
return Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
}
}
}
赤文字が追加したところで、それ以外は昨日のコードとほぼ同じ
今回のは頂点座標がわかっている直線を、GetPointAtFractionLengthでわざわざ分割して測定するっていうものだったけど、本命は
ベジェ曲線の長さ測定
コード
関連記事
続きは2日後、2018/06/18
前回、2018/06/15