XAMLはベクター図形を描くことが出来るので、今回は曲線を引いて見たいと思います。
ベジェ曲線のサンプル
MainWindow.xaml(XAMLのみ)
<Window x:Class="BezierDemo1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:BezierDemo1"
mc:Ignorable="d"
Title="Bezier Demo" Width="800" Height="500">
<Grid Background="#1E1E1E">
<Canvas>
<!-- PathGeometryでCubic Bezier (BezierSegment) -->
<Path Stroke="DeepSkyBlue" StrokeThickness="4" StrokeLineJoin="Round">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="80,300" IsClosed="False" IsFilled="False">
<BezierSegment Point1="200,80"
Point2="420,520"
Point3="700,250" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Grid>
</Window>
実行例スクリーンショット

Point1
Point1="200,80"
を
Point1="0,80"
へ変更します。
予想ではx軸の左側に移動するはず。
Point2
Point2="420,520"
を
Point2="420,760"
へ変更します。
予想ではy軸の下側に移動するはず。
変更後スクリーンショット

予想通りの結果になりました。
Catmull-Romスプライン曲線
MainWindow.xaml(Canvasだけ)
<Window x:Class="CatmullRomDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CatmullRomDemo"
mc:Ignorable="d"
Title="Catmull-Rom → Bezier (Minimal)"
Width="800" Height="500">
<Canvas Name="CanvasRoot" Background="#1E1E1E"/>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace CatmullRomDemo;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += (_, __) => Draw();
}
private void Draw()
{
// === Catmull-Rom 用の固定点列 ===
var points = new List<Point>
{
new Point(100, 300),
new Point(200, 120),
new Point(350, 260),
new Point(520, 100),
};
// 端点対策(複製)
points.Insert(0, points[0]);
points.Add(points[^1]);
// Catmull-Rom → Bezier
PathGeometry geometry = ConvertCatmullRomToBezier(points);
// 描画
var path = new Path
{
Data = geometry,
Stroke = Brushes.DeepSkyBlue,
StrokeThickness = 4,
StrokeLineJoin = PenLineJoin.Round,
StrokeStartLineCap = PenLineCap.Round,
StrokeEndLineCap = PenLineCap.Round
};
CanvasRoot.Children.Add(path);
}
// ================================
// Catmull-Rom → Cubic Bezier 変換
// ================================
private static PathGeometry ConvertCatmullRomToBezier(IList<Point> pts)
{
if (pts.Count < 4)
throw new ArgumentException("Need at least 4 points");
var figure = new PathFigure
{
StartPoint = pts[1],
IsClosed = false,
IsFilled = false
};
for (int i = 0; i < pts.Count - 3; i++)
{
Point p0 = pts[i];
Point p1 = pts[i + 1];
Point p2 = pts[i + 2];
Point p3 = pts[i + 3];
// Catmull-Rom (tension = 0.5) → Bezier
Point c1 = p1 + (p2 - p0) / 6.0;
Point c2 = p2 - (p3 - p1) / 6.0;
figure.Segments.Add(
new BezierSegment(c1, c2, p2, true)
);
}
return new PathGeometry(new[] { figure });
}
}
実行例、スクリーンショット

var points
にポイントを足してみます。
new Point(650, 300),
変更後、スクリーンショット

曲線が伸びたことが確認出来ます。
感想
ベジェ曲線、Catmull-Romスプライン曲線のいずれも理屈は全く理解していないのですが、
座標をノードとして曲線を描くことが出来ることを確認しましたので、
プログラムに組み込む目処が立ちました。
前回の記事では、マウスのカーソルの位置を取得する方法を確認しました。


WPFのCanvas上のマスカーソルの座標を取得する
・コードビハインドでMouseMoveイベントを使えば、マウス座標が取得出来るはず。using System.Windows;namespace MouseEventSample;public partial class MainWindo...
マウスのクリックイベントで、座標を取得し曲線を描くプログラムが作れると思います。
ただ、UIとして作り込む場合、ベジェ曲線は、ハンドル等を実装する必要があるので、
比較的簡単そうなCatmull-Romスプライン曲線で実装したいと思います。


コメント