今まで、TemplateやBindingといった部分を中心に勉強をしてきた。
今日は、ちょっと毛色を変えてWPFでの2Dの描画についてやってみようと思う。
WPFの協力なコントロール群も、最終的には2Dとして描画されるのでWPFにおける2D描画を勉強するってことは損にはならないはず。というかやらねばならぬ。と思ったのでやることにした。
WPFのピクセル
WPFを使う限り、画面上の1ピクセルというものを塗りつぶすと言ったことは厳密には出来ないようだ。何故ならWPFの1ピクセルは必ず1/96インチになる。つまりデバイスに依存しないということだ。
これによって「画面の解像度がめっさ高い画面とかでも、常に同じ大きさでレンダリングされるといったメリットがある。」とのこと。
確かに。覚えておこう。
因みにSilverlightでは、1ピクセルは本当に1ピクセルらしいという話を聞いた。聞いただけで確認はしてない。
ブラウザとかだと1/96インチにするのは難しかったのかなぁ?
ジオメトリ
WPFの2Dの描画を細かく砕いていくと、ジオメトリという単位に落ち着くらしい。つまり、ジオメトリをマスターすれば、描画については大体OKとなるみたいだ。
んで、ジオメトリで一番強力なのが、PathGeometryになる。
PathGeometryは、一連の図形で構成される。図形は、一連のセグメントとして構成される。
とりあえず、この関係がわかるような簡単なXAMLを書いてみた。Wpf2DEduという名前のプロジェクトを作ってWindow1.ぁmlにタグを書いていく。
<Window x:Class="Wpf2DEdu.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Canvas>
<!-- 塗りつぶしは赤色 線は黒色で描画 -->
<Path Width="200" Height="200" Fill="Red" Stroke="Black">
<Path.Data>
<!-- ジオメトリ登場 -->
<PathGeometry>
<PathGeometry.Figures>
<!-- 図形登場 -->
<PathFigure StartPoint="10,10">
<!-- セグメント登場 -->
<LineSegment Point="100,100" />
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Window>
これを実行すると、(10,10)から(100,100)ぬ向かって一本の黒い線が表示される。
PathFigureで開始点を指定して、LineSegmentで、どのポイントまで線を引っ張るのかを指定するイメージみたい。LineSegmentを複数指定すると、もうちょい複雑な図形が描画できる。
<Window x:Class="Wpf2DEdu.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Canvas>
<!-- 塗りつぶしは赤色 線は黒色で描画 -->
<Path Width="200" Height="200" Fill="Red" Stroke="Black">
<Path.Data>
<!-- ジオメトリ登場 -->
<PathGeometry>
<PathGeometry.Figures>
<!-- 図形登場 -->
<PathFigure StartPoint="10,10">
<!-- セグメント登場 -->
<LineSegment Point="100,100" />
<LineSegment Point="100,200" />
<LineSegment Point="10,200" />
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Window>
実行すると、今度はちゃんと塗りつぶしまで行われた図形が表示される。
よくよく見ないと気づかないけど、最後の点から開始点までは、線がひっぱられてない。LineSegmentを追加することで線をひっぱることは出来るけど、PathFigureにはIsClosedというプロパティがあるので、それをTrueに設定することで自動的に図形が閉じるように線をひっぱってくれる。
<!-- IsClosedをTrueに設定 -->
<PathFigure StartPoint="10,10" IsClosed="True">
よく見ないとわからないけど、今度は左端に黒い線が入ってる。
曲線をかを描画することも出来る。これには、BezierSegmentを使う。これを使うことでベジエ曲線をお手軽に描画できる。
<Window x:Class="Wpf2DEdu.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Canvas>
<!-- 塗りつぶしは赤色 線は黒色で描画 -->
<Path Width="200" Height="200" Fill="Red" Stroke="Black">
<Path.Data>
<!-- ジオメトリ登場 -->
<PathGeometry>
<PathGeometry.Figures>
<!-- 図形登場 -->
<PathFigure StartPoint="10,10" IsClosed="True">
<!-- セグメント登場 -->
<LineSegment Point="100,100" />
<!-- 制御点を2つ(Point1, Point2)と使用して終点(Point3)まで線を引く -->
<BezierSegment Point1="200,133" Point2="0,166" Point3="100,200" />
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Window>
これを実行すると、さっきより不思議な図形が出来上がる。
ベジエ曲線には、QuadraticBezzierSegmentという制御点を1つだけ指定するものも用意されている。(10,10)の位置から、制御点(200,150)を使って(100,200)まで描画するには、以下のような感じになる。(ここからXAML全体じゃなくて一部抜粋のみ示します。)
<!-- 図形登場 -->
<PathFigure StartPoint="10,10" IsClosed="True">
<!-- 制御点が1つでいいベジエ曲線 -->
<QuadraticBezierSegment Point1="200,150" Point2="100,200" />
</PathFigure>
実行すると下のような感じになる。
ベジエ曲線じゃなくて単純な弧を描きたいってときにはArcSegmentが使える。ArcSegmentはPointで指定した点までSizeで指定したサイズの円の弧を描く。SweepDirectionプロパティを使うと、弧が上に来るか下に来るかを指定できる。
<PathFigure StartPoint="10,10" IsClosed="True">
<!-- 弧が上 -->
<ArcSegment Point="100,100" Size="200,200" SweepDirection="Clockwise"/>
<!-- 弧が下 -->
<ArcSegment Point="150,150" Size="200,200" SweepDirection="Counterclockwise"/>
</PathFigure>
実行結果は下の通り。
こういうのを駆使して、デザインセンスのある人が綺麗な図形を描くのだという。
因みに俺にセンスは無いorz