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.
Der folgende XAML-Code erstellt beispielsweise eine zusammengesetzte Form aus einer Reihe konzentrischer Ringe (Zielbereich), bei der FillRule auf EvenOddgesetzt 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 in der vorherigen Abbildung, dass die Mitte und der dritte Ring nicht gefüllt sind. Dies liegt daran, dass ein Strahl, der von einem beliebigen Punkt innerhalb einer dieser beiden Ringe gezogen wird, eine gerade Anzahl von Segmenten durchläuft. 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. In der folgenden Abbildung stellen die roten Pfeile beispielsweise die Richtung dar, in der die Segmente gezeichnet werden, und der weiße Pfeil stellt einen beliebigen Strahl dar, der von einem Punkt im innersten Ring verläuft. Beginnend mit einem Wert von Null wird für jedes Segment, das die Strahlung kreuzt, ein Wert von 1 hinzugefügt, da das Segment den Strahl von links nach rechts kreuzt.
Um das Verhalten der Nonzero-Regel besser zu veranschaulichen, ist eine komplexere Form mit Segmenten erforderlich, die in unterschiedliche Richtungen verlaufen. Der folgende XAML-Code erstellt eine ähnliche Form wie im vorherigen Beispiel, mit der Ausnahme, dass sie mit einem PathGeometry erstellt wird anstelle einer EllipseGeometry, wodurch vier konzentrische Bögen anstatt vollständig geschlossener konzentrischer Kreise entstehen.
<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 vom Mittelpunkt nicht gefüllt ist. Die folgende Abbildung zeigt, warum dies der Fall ist. 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, ist die Summe der Werte eines bestimmten Strahls, der die Segmente in seinem Pfad durchquert, 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.
Anmerkung
Für FillRulewerden alle Formen als geschlossen betrachtet. Wenn es eine Lücke in einem Segment gibt, zeichnen Sie eine imaginäre Linie, um sie zu schließen. Im obigen Beispiel gibt es kleine Lücken in den Ringen. 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