Gewusst wie: Steuern des Ausfüllens einer zusammengesetzten Form
Die FillRule-Eigenschaft einer GeometryGroup oder einer PathGeometry gibt eine „Regel“ an, die von der zusammengesetzten Form verwendet wird, um zu ermitteln, ob ein bestimmter Punkt Teil der Geometrie ist. Es gibt zwei mögliche Werte für FillRule: EvenOdd und Nonzero. In den folgenden Abschnitten wird beschrieben, wie diese beiden Regeln verwendet werden.
EvenOdd:Diese Regel ermittelt, ob sich ein Punkt im Ausfüllbereich befindet, indem von diesem Punkt aus ein Strahl in beliebiger Richtung gegen Unendlich gezeichnet wird und die Anzahl der vom Strahl geschnittenen Pfadsegmente in der Form gezählt wird. Bei einer ungeraden Zahl liegt der Punkt innen, und bei einer geraden Zahl liegt er außen.
Das folgende XAML-Codebeispiel erstellt eine aus einer Reihe von konzentrischen Ringen (Ziel) zusammengesetzte Form, wobei eine FillRule auf EvenOdd festgelegt ist.
<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>
Die folgende Abbildung zeigt die im vorherigen Beispiel erstellte Form.
Beachten Sie, dass in der Abbildung oben die Mitte und der dritte Ring nicht ausgefüllt sind. Dies ist darauf zurückzuführen, dass ein Strahl, der von einem beliebigen Punkt innerhalb eines dieser beiden Ringe gezeichnet wird, eine gerade Anzahl von Segmenten schneidet. Sehen Sie sich die folgende Abbildung an:
NonZero:Diese Regel bestimmt, ob sich ein Punkt im Ausfüllbereich im Pfad befindet, indem ein unendlicher Strahl von diesem Punkt in eine beliebige Richtung gezeichnet wird und anschließend die Stellen überprüft werden, an denen ein Segment der Form den Strahl schneidet. Beginnen Sie mit dem Wert 0 (null), und addieren Sie für jede Stelle, an der ein Segment den Strahl von links nach rechts schneidet, den Wert 1. Wenn das Ergebnis nach dem Zählen der Überschneidungen 0 (null) ist, liegt der Punkt außerhalb des Pfads. Andernfalls liegt er innerhalb des Pfads.
<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>
Im vorherigen Beispiel ergibt ein Wert von Nonzero für FillRule die folgende Abbildung:
Wie Sie sehen können, sind alle Ringe ausgefüllt. Dies kommt daher, dass alle Segmente in die gleiche Richtung verlaufen und deshalb ein Strahl, der von einem beliebigen Punkt aus gezeichnet wird, ein oder mehrere Segmente schneidet, sodass die Summe der Schnitte ungleich 0 (null) ist. So stellen zum Beispiel die roten Pfeile in der folgenden Abbildung die Richtung dar, in die die Segmente gezeichnet werden. Die weißen Pfeile stellen einen zufälligen Strahl dar, der von einem Punkt im innersten Ring aus verläuft. Ausgehend vom Wert 0 (null) wird für jedes Segment, das der Strahl schneidet, der Wert 1 addiert, da das Segment den Strahl von links nach rechts schneidet.
Um das Verhalten der Nonzero-Regel noch besser zu verdeutlichen, ist eine komplexere Form mit in verschiedene Richtungen verlaufenden Segmenten erforderlich. Mit dem unten aufgeführten XAML-Code wird eine ähnliche Form wie im vorhergehenden Beispiel erstellt, mit der Ausnahme, dass sie mit einer PathGeometry anstelle einer EllipseGeometry erstellt wird, wodurch vier konzentrische Bögen statt vollständig geschlossener konzentrischer Kreise erstellt werden.
<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>
Die folgende Abbildung zeigt die im vorherigen Beispiel erstellte Form.
Beachten Sie, dass der dritte Bogen ab der Mitte nicht ausgefüllt ist. Die folgende Abbildung veranschaulicht dies. In der Abbildung stellen die roten Pfeile die Richtung dar, in der die Segmente gezeichnet werden. Die beiden weißen Pfeile stellen zwei zufällige Strahlen dar, die von einem Punkt im „nicht ausgefüllten“ Bereich ausgehen. Wie aus der Abbildung ersichtlich, ist die Summe der Werte eines bestimmten Strahls, der die Segmente in seinem Pfad schneidet, gleich 0 (null). Wie oben bereits definiert, bedeutet eine Summe von null, dass der Punkt nicht Teil der Geometrie ist (kein Teil der Füllung), während eine Summe, die ungleich null oder negativ ist, Teil der Geometrie ist.
Hinweis
Bei der FillRule wird davon ausgegangen, dass alle Formen geschlossen sind. Wenn in einem Segment eine Lücke vorhanden ist, zeichnen Sie eine gedachte Linie, um sie zu schließen. Im oben aufgeführten Beispiel weisen die Ringe kleine Lücken auf. Daher könnte man erwarten, dass ein Strahl durch die Lücke verläuft und ein anderes Ergebnis ergibt als ein Strahl, der in eine andere Richtung verläuft. Unten ist eine vergrößerte Abbildung einer dieser Lücken und des „gedachten“ Segments dargestellt (Segment, das gezeichnet wird, um die FillRule anwenden zu können), das die Lücke schließt.
Beispiel
Siehe auch
.NET Desktop feedback