Xamarin.Forms Obrazce: Pravidla výplně

Download Sample Stažení ukázky

Několik Xamarin.Forms tříd obrazců má FillRule vlastnosti typu FillRule. Patří mezi ně Polygon, Polylinea GeometryGroup.

Výčet FillRule definuje EvenOdd a Nonzero členy. Každý člen představuje jiné pravidlo pro určení, zda je bod v oblasti výplně obrazce.

Důležité

Všechny obrazce jsou považovány za zavřené pro účely pravidel výplně.

EvenOdd

Pravidlo EvenOdd výplně nakreslí paprsek od bodu do nekonečna v libovolném směru a spočítá počet segmentů ve tvaru, který paprsk protíná. Pokud je toto číslo liché, bod je uvnitř. Pokud je toto číslo sudé, bod je mimo.

Následující příklad XAML vytvoří a vykreslí složený obrazec s FillRule výchozím nastavením:EvenOdd

<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>

V tomto příkladu se zobrazí složený obrazec tvořený řadou soustředných kroužků:

Composite shape with EvenOdd fill rule

Ve složeného tvaru si všimněte, že střed a třetí kroužky nejsou vyplněné. Je to proto, že paprsek nakreslený z libovolného bodu v některém z těchto dvou kroužků prochází sudým počtem segmentů:

Annotated composite shape with EvenOdd fill rule

Na obrázku výše představují červené kruhy body a čáry představují libovolné paprsky. U horního bodu obě libovolné paprsky procházejí sudým počtem segmentů čáry. Proto prstenec, ve které je bod, není vyplněný. V dolním bodě obě libovolné paprsky projdou lichým počtem segmentů čar. Proto je prstenec, ve které je bod vyplněný.

Nenulová

Pravidlo Nonzero výplně nakreslí paprsek z bodu do nekonečna v libovolném směru a pak prozkoumá místa, kde segment obrazce protíná paprsk. Počínaje počtem nul se počet zvýší pokaždé, když segment protíná paprsek zleva doprava a odpojí se pokaždé, když segment protíná paprsek zprava doleva. Po počítání přechodů platí, že pokud je výsledek nulový, bod je mimo mnohoúhelník. Jinak je uvnitř.

Následující příklad XAML vytvoří a vykresluje složený obrazec se FillRule sadou na Nonzero:

<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>

V tomto příkladu se zobrazí složený obrazec tvořený řadou soustředných kroužků:

Diagram shows four concentric circles, all filled in.

Ve složeného tvaru si všimněte, že jsou vyplněny všechny kroužky. Důvodem je to, že všechny segmenty běží ve stejném směru, a proto paprsk nakreslený z libovolného bodu protíná jeden nebo více segmentů a součet přechodů se nerovná nule:

Diagram shows the circles from the previous diagram with directional arrows and a ray annotated with + 1 for each circle it crosses.

Na obrázku nad červenými šipkami představují směr vykreslení segmentů a černá šipka představuje libovolný paprsek spuštěný z bodu v nejvnitřnějším kruhu. Počínaje hodnotou nuly, pro každý segment, který paprsek kříží, je přidána hodnota jednoho, protože segment protíná paprsek zleva doprava.

Složitější obrazec se segmenty spuštěnými v různých směrech je potřeba k lepšímu předvedení chování Nonzero pravidla výplně. Následující příklad XAML vytvoří podobný obrazec jako v předchozím příkladu, s tím rozdílem PathGeometryEllipseGeometry, že se vytvoří místo :

<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>

V tomto příkladu jsou nakresleny řady obloukových segmentů, které nejsou uzavřeny:

Diagram shows four concentric circles, with the outmost and third from outermost filled in.

Na obrázku výše není třetí oblouk ze středu vyplněný. Důvodem je to, že součet hodnot z daného paprsku, který překračuje segmenty v jeho cestě, je nula:

Diagram shows the circles from the previous diagram with directional arrows and two rays annotated with + 1 or – 1 for each circle they cross.

Na obrázku výše představuje červený kruh bod, černé čáry představují libovolné paprsky, které se pohybují od bodu v nezaplněné oblasti, a červené šipky představují směr, kterým jsou segmenty nakresleny. Jak je vidět, součet hodnot z paprsků překračujících segmenty je nula:

  • Libovolný paprsek, který se pohybuje diagonálně doprava, protíná dva segmenty, které běží v různých směrech. Proto se segmenty navzájem ruší a poskytují hodnotu nuly.
  • Libovolný paprsek, který cestuje diagonálně vlevo, překříží celkem šest segmentů. Přechody se ale navzájem ruší, takže nula je konečný součet.

Součet nulových výsledků v prstenci se nevyplní.