Freigeben über


Xamarin.Forms Shapes: Füllregeln

Mehrere Xamarin.Forms Shapes-Klassen verfügen über FillRule Eigenschaften vom Typ FillRule. Dazu zählen Polygon , Polyline und GeometryGroup .

Die FillRule-Enumeration definiert EvenOdd- und Nonzero-Mitglieder. Jedes Mitglied steht für eine andere Regel zur Bestimmung, ob ein Punkt im Füllbereich einer Form liegt.

Wichtig

Alle Formen werden für die Zwecke der Füllregeln als geschlossen betrachtet.

EvenOdd

Die Füllregel EvenOdd zeichnet einen Strahl vom Punkt ins Unendliche in eine beliebige Richtung und zählt die Anzahl der Segmente innerhalb der Form, die der Strahl durchquert. Wenn diese Zahl ungerade ist, liegt der Punkt im Inneren. Wenn diese Zahl gerade ist, liegt der Punkt außerhalb.

Im folgenden XAML-Beispiel wird eine zusammengesetzte Form erstellt und gerendert, wobei FillRule standardmäßig auf EvenOdd gesetzt wird:

<Path Stroke="Black"
      Fill="#CCCCFF"
      Aspect="Uniform"
      HorizontalOptions="Start">
    <Path.Data>
        <!-- FillRule doesn't need to be set, because EvenOdd is the default. -->
        <GeometryGroup>
            <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>

In diesem Beispiel wird eine zusammengesetzte Form angezeigt, die aus einer Reihe von konzentrischen Ringen besteht:

Zusammengesetzte Form mit EvenOdd-Füllregel

Bei der zusammengesetzten Form ist zu beachten, dass der mittlere und der dritte Ring nicht gefüllt sind. Das liegt daran, dass ein Strahl, der von einem beliebigen Punkt innerhalb eines dieser beiden Ringe ausgeht, durch eine gerade Anzahl von Segmenten verläuft:

Kommentierte zusammengesetzte Form mit EvenOdd-Füllregel

In der obigen Abbildung stellen die roten Kreise Punkte und die Linien beliebige Strahlen dar. Für den oberen Punkt durchlaufen die beiden willkürlichen Strahlen jeweils eine gerade Anzahl von Liniensegmenten. Daher ist der Ring, in dem sich der Punkt befindet, nicht gefüllt. Für den unteren Punkt gehen die beiden willkürlichen Strahlen jeweils durch eine ungerade Anzahl von Liniensegmenten. Daher ist der Ring, in dem sich der Punkt befindet, gefüllt.

Nonzero

Die Füllregel Nonzero zeichnet einen Strahl vom Punkt ins Unendliche in eine beliebige Richtung und untersucht dann die Stellen, an denen ein Segment der Form den Strahl kreuzt. Beginnend mit einem Zählerstand von Null wird der Zählerstand jedes Mal erhöht, wenn ein Segment den Strahl von links nach rechts kreuzt, und jedes Mal verringert, wenn ein Segment den Strahl von rechts nach links kreuzt. Wenn das Ergebnis nach dem Zählen der Kreuzungen Null ist, liegt der Punkt außerhalb des Polygons. Ansonsten ist es drinnen.

Im folgenden XAML-Beispiel wird eine zusammengesetzte Form erstellt und gerendert, wobei FillRule auf Nonzero gesetzt wird:

<Path Stroke="Black"
      Fill="#CCCCFF"
      Aspect="Uniform"
      HorizontalOptions="Start">
    <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>

In diesem Beispiel wird eine zusammengesetzte Form angezeigt, die aus einer Reihe von konzentrischen Ringen besteht:

Das Diagramm zeigt vier konzentrische Kreise, die alle ausgefüllt sind.

Bei der zusammengesetzten Form ist zu beachten, dass alle Ringe gefüllt sind. Das liegt daran, dass alle Segmente in dieselbe Richtung verlaufen, so dass ein von einem beliebigen Punkt aus gezogener Strahl ein oder mehrere Segmente kreuzt und die Summe der Kreuzungen nicht gleich Null ist:

Das Diagramm zeigt die Kreise aus dem vorherigen Diagramm mit direktionalen Pfeilen und einem mit + 1 versehenen Strahl für jeden Kreis, den er kreuzt.

In der obigen Abbildung geben die roten Pfeile die Richtung an, in der die Segmente gezeichnet werden, und der schwarze Pfeil stellt einen beliebigen Strahl dar, der von einem Punkt im innersten Ring ausgeht. 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.

Eine komplexere Form mit Segmenten, die in verschiedene Richtungen verlaufen, ist erforderlich, um das Verhalten der Füllregel Nonzero besser zu demonstrieren. Das folgende XAML-Beispiel erstellt eine ähnliche Form wie das vorherige Beispiel, nur dass es mit einem PathGeometry statt einem EllipseGeometry erstellt wird:

<Path Stroke="Black"
      Fill="#CCCCFF">
     <Path.Data>
         <GeometryGroup FillRule="Nonzero">
             <PathGeometry>
                 <PathGeometry.Figures>
                     <!-- Inner ring -->
                     <PathFigure StartPoint="120,120">
                         <PathFigure.Segments>
                             <PathSegmentCollection>
                                 <ArcSegment Size="50,50"
                                             IsLargeArc="True"
                                             SweepDirection="CounterClockwise"
                                             Point="140,120" />
                             </PathSegmentCollection>
                         </PathFigure.Segments>
                     </PathFigure>

                     <!-- Second ring -->
                     <PathFigure StartPoint="120,100">
                         <PathFigure.Segments>
                             <PathSegmentCollection>
                                 <ArcSegment Size="70,70"
                                             IsLargeArc="True"
                                             SweepDirection="CounterClockwise"
                                             Point="140,100" />
                             </PathSegmentCollection>
                         </PathFigure.Segments>
                     </PathFigure>

                     <!-- Third ring  -->
                         <PathFigure StartPoint="120,70">
                         <PathFigure.Segments>
                             <PathSegmentCollection>
                                 <ArcSegment Size="100,100"
                                             IsLargeArc="True"
                                             SweepDirection="CounterClockwise"
                                             Point="140,70" />
                             </PathSegmentCollection>
                         </PathFigure.Segments>
                     </PathFigure>

                     <!-- Outer ring -->
                     <PathFigure StartPoint="120,300">
                         <PathFigure.Segments>
                             <ArcSegment Size="130,130"
                                         IsLargeArc="True"
                                         SweepDirection="Clockwise"
                                         Point="140,300" />
                         </PathFigure.Segments>
                     </PathFigure>
                 </PathGeometry.Figures>
             </PathGeometry>
         </GeometryGroup>
     </Path.Data>
 </Path>

In diesem Beispiel wird eine Reihe von Bogensegmenten gezeichnet, die nicht geschlossen sind:

Das Diagramm zeigt vier konzentrische Kreise, wobei die äußerste und dritte aus äußerster Rand gefüllt ist.

In der obigen Abbildung ist der dritte Bogen von der Mitte aus nicht ausgefüllt. Das liegt daran, dass die Summe der Werte eines bestimmten Strahls, der die Segmente auf seinem Weg kreuzt, gleich Null ist:

Das Diagramm zeigt die Kreise aus dem vorherigen Diagramm mit direktionalen Pfeilen und zwei Strahlen, die mit + 1 oder – 1 für jeden Kreis markiert sind, den sie kreuzen.

In der obigen Abbildung stellt der rote Kreis einen Punkt dar, die schwarzen Linien stellen beliebige Strahlen dar, die sich vom Punkt aus in den nicht gefüllten Bereich bewegen, und die roten Pfeile geben die Richtung an, in die die Segmente gezogen werden. Wie man sieht, ist die Summe der Werte der Strahlen, die die Segmente kreuzen, gleich Null:

  • Der beliebige Strahl, der diagonal nach rechts verläuft, kreuzt zwei Segmente, die in unterschiedliche Richtungen verlaufen. Daher heben sich die Segmente gegenseitig auf und ergeben einen Wert von Null.
  • Der beliebige Strahl, der diagonal nach links verläuft, durchquert insgesamt sechs Segmente. Die Kreuzungen heben sich jedoch gegenseitig auf, so dass die Endsumme Null ergibt.

Eine Summe von Null bedeutet, dass der Ring nicht gefüllt wird.