方法: 複合図形の塗りつぶしをコントロールする
GeometryGroup または PathGeometryの FillRule プロパティは、複合図形が特定の点がジオメトリの一部であるかどうかを判断するために使用する "ルール" を指定します。 FillRuleには、EvenOdd と Nonzeroの 2 つの値があります。 以降のセクションでは、これら 2 つの規則の使用方法について説明します。
EvenOdd: このルールは、ポイントから無限大までの光線を任意の方向に描画し、光線が交差する指定された図形内のパス セグメントの数をカウントすることによって、ポイントが塗りつぶし領域にあるかどうかを決定します。 この数値が奇数の場合、ポイントは内側にあります。偶数の場合、ポイントは外側にあります。
たとえば、次の XAML では、FillRule を EvenOddに設定して、一連の同心円 (ターゲット) で構成される複合図形を作成します。
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<GeometryGroup FillRule="EvenOdd">
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
<EllipseGeometry RadiusX="70" RadiusY="70" Center="75,75" />
<EllipseGeometry RadiusX="100" RadiusY="100" Center="75,75" />
<EllipseGeometry RadiusX="120" RadiusY="120" Center="75,75" />
</GeometryGroup>
</Path.Data>
</Path>
次の図は、前の例で作成した図形を示しています。
前の図では、中央と 3 番目のリングが塗りつぶされていないことに注意してください。 これは、これら 2 つのリングのいずれか内の任意のポイントから描画されたレイが、偶数のセグメントを通過するためです。 次の図を参照してください。
NonZero: このルールは、そのポイントから無限大までの光線を任意の方向に描画し、図形のセグメントが光線と交差する場所を調べることによって、ポイントがパスの塗りつぶし領域にあるかどうかを判断します。 ゼロのカウントから始めて、セグメントが左から右に光線を横切るたびに 1 つ加算し、パス セグメントが右から左に光線を横切るたびに 1 つ減算します。 交差をカウントした後、結果が 0 の場合、ポイントはパスの外側にあります。 それ以外の場合は、内部にあります。
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<GeometryGroup FillRule="NonZero">
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
<EllipseGeometry RadiusX="70" RadiusY="70" Center="75,75" />
<EllipseGeometry RadiusX="100" RadiusY="100" Center="75,75" />
<EllipseGeometry RadiusX="120" RadiusY="120" Center="75,75" />
</GeometryGroup>
</Path.Data>
</Path>
前の例を用いて、Nonzero の値が FillRule の場合の結果を次の図で示します。
ご覧のように、すべてのリングが埋まっています。 これは、すべてのセグメントが同じ方向に実行されているため、任意のポイントから描画された光線が 1 つ以上のセグメントを横切り、交差の合計が 0 にならないためです。 たとえば、次の図では、赤い矢印はセグメントが描画される方向を表し、白い矢印は最も内側のリング内の点から実行される任意の光線を表します。 値が 0 から始まり、光線が交差するセグメントごとに、セグメントが左から右に光線と交差するため、1 の値が追加されます。
Nonzero ルールの動作をよりよく実証するには、セグメントが異なる方向に実行されるより複雑な形状が必要です。 次の XAML コードでは、前の例と同様の図形が作成されます。ただし、EllipseGeometry ではなく PathGeometry を使用しているため、完全に閉じた同心円ではなく、4 つの同心円弧が作成されます。
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<GeometryGroup FillRule="NonZero">
<PathGeometry>
<PathGeometry.Figures>
<!-- Inner Ring -->
<PathFigure StartPoint="10,120">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="50,50" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,120" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
<!-- Second Ring -->
<PathFigure StartPoint="10,100">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="70,70" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,100" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
<!-- Third Ring (Not part of path) -->
<PathFigure StartPoint="10,70">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="100,100" IsLargeArc="True" SweepDirection="CounterClockwise" Point="25,70" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
<!-- Outer Ring -->
<PathFigure StartPoint="10,300">
<PathFigure.Segments>
<ArcSegment Size="130,130" IsLargeArc="True" SweepDirection="Clockwise" Point="25,300" />
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>
次の図は、前の例で作成した図形を示しています。
中心から 3 番目の円弧が塗りつぶされていないことに注意してください。 この理由を次の図に示します。 図では、赤い矢印はセグメントが描画される方向を表しています。 2 つの白い矢印は、"塗りつぶされていない" 領域のポイントから移動する 2 つの任意の光線を表します。 図からわかるように、与えられたレイが通過するセグメントの値の合計は0です。 上で定義したように、0 の合計は、ポイントがジオメトリの一部でないことを意味し (塗りつぶしの一部ではありません)、負の値を含むゼロ
手記
FillRuleのために、すべての図形が閉じていると見なされます。 セグメントにギャップがある場合は、架空の線を描画して閉じます。 上記の例では、リングに小さなギャップがあります。 これを考えると、ギャップを通過する光線と別の方向に進む光線では異なる結果を期待するかもしれません。 次に、これらのギャップの 1 つと、それを閉じる "虚数セグメント" (FillRuleを適用するために描画されるセグメント) を拡大した図を示します。
例
関連項目
.NET Desktop feedback