Quantcast
Channel: 午後わてんのブログ
Viewing all articles
Browse latest Browse all 420

マウスクリックでCanvasにベジェ曲線で曲線、PolyBezierSegment

$
0
0
ベジェ曲線で曲線
System.Windows.Media.PolyBezierSegment

Path.Dataの
PathGeometryの
FigureのSegmentに
PolyBezierSegmentを指定してベジェ曲線
ってのはおとといのベジェ曲線で直線と同じ方法で、制御点座標を調整するようにして曲線にする

イメージ 1
クリックしたところがアンカーポイントになる


デザイン画面
イメージ 2
この前と同じ


コード
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace _20180610_マウスクリックでベジェ曲線
{
public partial class MainWindow : Window
{
PolyBezierSegment MySegment;

public MainWindow()
{
InitializeComponent();

MyInitialize();
MyCanvas.MouseLeftButtonDown += MyCanvas_MouseLeftButtonDown;
MyCanvas.MouseMove += MyCanvas_MouseMove;
MyCanvas.MouseRightButtonDown += MyCanvas_MouseRightButtonDown;
}

private void MyCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
MySegment.Points.Clear();
}

//Path.Dataを作成
private void MyInitialize()
{
MySegment = new PolyBezierSegment();
var pf = new PathFigure();
pf.Segments.Add(MySegment);
var pg = new PathGeometry();
pg.Figures.Add(pf);
MyPath.Data = pg;
}

//マウス移動時、終端のアンカーポイント移動とその他の制御点の位置調整
private void MyCanvas_MouseMove(object sender, MouseEventArgs e)
{
PointCollection ps = MySegment.Points;
if (ps.Count > 5)
{
Point p = e.GetPosition(MyCanvas);//マウスカーソル位置

//最後のアンカーポイントの座標は今のカーソル座標
ps[ps.Count - 1] = p;

Point ap1 = ps[ps.Count - 4];//一個前のアンカーポイント
Point ap2;//二個前のアンカーポイント
if (ps.Count < 7)
{
var pg = (PathGeometry)MyPath.Data;
var pathFigureCollection = pg.Figures;
ap2 = pathFigureCollection[0].StartPoint;
}
else
{
ap2 = ps[ps.Count - 7];
}

//最後のアンカーポイントと二個前のアンカーポイントとの距離の1 / 4
double xDiff = (p.X - ap2.X) / 4.0;
double yDiff = (p.Y - ap2.Y) / 4.0;
//一個前のアンカーポイントの制御点座標
ps[ps.Count - 3] = new Point(ap1.X + xDiff, ap1.Y + yDiff);
ps[ps.Count - 5] = new Point(ap1.X - xDiff, ap1.Y - yDiff);

//最後のアンカーポイントと一個前のアンカーポイントの距離の1/4
xDiff = (p.X - ps[ps.Count - 3].X) / 4.0;
yDiff = (p.Y - ps[ps.Count - 3].Y) / 4.0;
//最後のアンカーポイントの制御点座標
ps[ps.Count - 2] = new Point(p.X - xDiff, p.Y - yDiff);
}
else if (MySegment.Points.Count > 0)
{
//最後のアンカーポイントのインデックスはCount-1
ps[ps.Count - 1] = e.GetPosition(MyCanvas);//カーソル位置に
}
}

//マウスクリック時、アンカーポイントと制御点2つを追加
private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var p = e.GetPosition(MyCanvas);
//最初のクリック時だけはStartPointを指定する
if (MySegment.Points.Count == 0)
{
var pathGeometry = (PathGeometry)MyPath.Data;
var pathFigureCollection = pathGeometry.Figures;
pathFigureCollection[0].StartPoint = p;
//制御点2つとアンカーポイント追加
MySegment.Points.Add(p);
MySegment.Points.Add(p);
MySegment.Points.Add(p);
}
else
{
//制御点2つとアンカーポイント追加
MySegment.Points.Add(p);
MySegment.Points.Add(p);
MySegment.Points.Add(p);
}

}
}
}

前回から変更があったのはマウス移動時のところ



なめらかなベジェ曲線を描くには制御点座標を調整
イメージ 3
灰色がアンカーポイント
紫色が制御点
アンカーポイント03の制御点02と04の座標を調整して

イメージ 4
対角線上みたいに配置すると線がなめらかになる


マウスカーソル位置を終端のアンカーポイントとしたときに連動させる制御点座標の決め方は
Pixtack紫陽花2.6.50.134_マウスクリックでもベジェ曲線を描けるようにした ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/12656208.html
この記事より
こんな感じで


ベジェ曲線はアンカーポイントと制御点の2種類のポイント(座標)があって
始点と終点のアンカーポイントには1つの制御点
それ以外のアンカーポイントには2つの制御点が付く
イメージ 5
始点の00には制御点01
終点の09には制御点08
それ以外の03と06にはそれぞれ2つの制御点02と04、05と07

Path.Dataの
PathGeometryの
FigureのSegmentに
PolyBezierSegmentを指定してベジェ曲線
FigureのStartPointに始点座標を指定して、それ以降の座標はPolyBezierSegmentに入れていくことになる
上の図だと
Figure.StartPoint = new Point(50, 50);
PolyBezierSegment.Points.Add(new Point(150, 50);
PolyBezierSegment.Points.Add(new Point(322, 72);

なので始点だけ特別扱いみたいになる


イメージ 6
49行目からの二個前のアンカーポイントを取得するところがめんどくさくなっているは始点が特別扱いだから、これがなければ58行目だけで済むんだけどなあ
アンカーポイントとその制御点の距離は一個前や二個前のアンカーポイントとの距離の1/4って決めたから4.0で割っている、1/4に決めたのは適当だったから


MainWindow.xaml
MainWindow.xaml.cs



関連記事
2018/06/09
マウスクリックでCanvasに直線を描画その3、ベジェ曲線で直線、PolyBezierSegment ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15542192.html


2015/1/27
Pixtack紫陽花2.6.50.134_マウスクリックでもベジェ曲線を描けるようにした ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/12656208.html





Viewing all articles
Browse latest Browse all 420

Trending Articles