Sdílet prostřednictvím


Jak ovládat výplň složeného tvaru

Vlastnost FillRuleGeometryGroup nebo PathGeometryurčuje pravidlo, které složený obrazec používá k určení, zda je daný bod součástí geometrie. Existují dvě možné hodnoty pro FillRule: EvenOdd a Nonzero. Následující části popisují, jak tato dvě pravidla používat.

EvenOdd: Toto pravidlo určuje, zda je bod v oblasti výplně nakreslením paprsku z tohoto bodu do nekonečna v libovolném směru a počítáním počtu segmentů cesty v daném tvaru, který paprsk protíná. Pokud je toto číslo liché, bod je uvnitř; je-li sudé, bod je venku.

Kód XAML níže například vytvoří složený obrazec tvořený řadou soustředných kroužků (cíl) s FillRule nastaveným na 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>

Následující obrázek znázorňuje obrazec vytvořený v předchozím příkladu.

kruh tvořený řadou soustředných kroužků se střídavými barvami.

Na předchozím obrázku si všimněte, že střed a třetí kruh nejsou vyplněné. Je to proto, že paprsk nakreslený z libovolného bodu v některém z těchto dvou kroužků prochází sudým počtem segmentů. Podívejte se na následující obrázek:

diagram znázorňující paprsky EvenOdd nakreslené v kruhu

NonZero: Toto pravidlo určuje, zda je bod v oblasti výplně cesty nakreslením paprsku z tohoto bodu do nekonečna v libovolném směru a následným zkoumáním míst, kde segment obrazce protíná paprsek. Počínaje nulou, přidejte jeden pokaždé, když segment protíná paprsek zleva doprava, a odečtěte jeden pokaždé, když segment cesty protíná paprsek zprava doleva. Po počítání přechodů platí, že pokud je výsledek nula, bod je mimo cestu. Jinak je uvnitř.

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

Pomocí předchozího příkladu dává hodnota Nonzero pro FillRule následující ilustraci jako výsledek:

Kruh tvořený řadou soustředných kroužků všech naplněných stejnou barvou.

Jak vidíte, všechny kroužky jsou vyplněné. 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. Například na následujícím obrázku znázorňují červené šipky směr vykreslení segmentů a bílá š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.

Diagram znázorňující hodnotu vlastnosti FillRule se rovná Nonzero.

Pro lepší předvedení chování pravidla Nonzero je zapotřebí složitější tvar se segmenty vedoucími v různých směrech. Níže uvedený kód XAML vytvoří podobný obrazec jako v předchozím příkladu s tím rozdílem, že se vytvoří s PathGeometry než EllipseGeometry, což vytvoří čtyři soustředné oblouky než zcela uzavřené soustředné kruhy.

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

Následující obrázek znázorňuje obrazec vytvořený v předchozím příkladu.

Kruh tvořený řadou soustředných kroužků se střídavými barvami se třetím obloukem, který není vyplněn.

Všimněte si, že třetí oblouk ze středu není vyplněn. Následující obrázek ukazuje, proč to je. Na obrázku znázorňují červené šipky směr vykreslení segmentů. Dvě bílé šipky představují dva libovolné paprsky, které se přesouvají z bodu v "nezaplněné" oblasti. Jak je vidět na obrázku, součet hodnot z daného paprsku procházejícího segmenty v jeho cestě je nula. Jak je uvedeno výše, součet nuly znamená, že bod není součástí geometrie (nikoli část výplně), zatímco součet, který je není nula, včetně záporné hodnoty, je součástí geometrie.

Diagram zobrazující libovolné paprsky protínající segmenty.

Poznámka

Pro účely FillRulejsou všechny obrazce považovány za uzavřené. Pokud je v segmentu mezera, nakreslete imaginární čáru a zavřete ji. V předchozím příkladu jsou v prstencích malé mezery. Vzhledem k tomu může člověk očekávat, že paprsek procházející mezerou přinese jiný výsledek než ten směřující jiným směrem. Níže je zvětšená ilustrace jedné z těchto mezer a "imaginární segment" (segment, který je vykreslen pro účely použití FillRule), který ji zavře.

diagram znázorňující segmenty FillRule, které jsou vždy zavřené

Příklad

Viz také