Udostępnij za pośrednictwem


Instrukcje: sterowanie wypełnieniem kształtu złożonego

Właściwość FillRuleGeometryGroup lub PathGeometryokreśla "regułę", której kształt złożony używa do określenia, czy dany punkt jest częścią geometrii. Istnieją dwie możliwe wartości dla FillRule: EvenOdd i Nonzero. W poniższych sekcjach opisano sposób używania tych dwóch reguł.

EvenOdd: Ta reguła określa, czy punkt znajduje się w obszarze wypełnienia, rysując promień od tego punktu do nieskończoności w dowolnym kierunku i zliczając liczbę segmentów ścieżki w danym kształcie, które promień przecina. Jeśli ta liczba jest nieparzysta, punkt znajduje się wewnątrz; jeśli nawet, punkt znajduje się poza.

Na przykład poniższy kod XAML tworzy złożony kształt składający się z serii pierścieni koncentrycznych (docelowych) z zestawem FillRule ustawionym 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>

Poniższa ilustracja przedstawia kształt utworzony w poprzednim przykładzie.

Okrąg składający się z pierścieni koncentrycznych serii z przemiennymi kolorami.

Na poprzedniej ilustracji zwróć uwagę, że środek i trzeci pierścień nie są wypełnione. Wynika to z faktu, że promienie pobrane z dowolnego punktu w obrębie jednego z tych dwóch pierścieni przechodzi przez parzystą liczbę segmentów. Zobacz następującą ilustrację:

Diagram przedstawiający promienie EvenOdd narysowane w kole.

NonZero: Ta reguła określa, czy punkt znajduje się w regionie wypełnienia ścieżki, rysując promienie od tego punktu do nieskończoności w dowolnym kierunku, a następnie sprawdzając miejsca, w których segment kształtu przecina promienie. Zaczynając od liczby zero, dodaj jeden za każdym razem, gdy segment przecina promień od lewej do prawej, i odejmij jeden za każdym razem, gdy segment ścieżki przecina promień od prawej do lewej. Po zliczaniu przepraw, jeśli wynik wynosi zero, punkt znajduje się poza ścieżką. W przeciwnym razie znajduje się wewnątrz.

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

Korzystając z poprzedniego przykładu, wartość Nonzero dla FillRule daje następującą ilustrację w wyniku:

Okrąg składający się z pierścieni koncentrycznych serii wypełnionych tym samym kolorem.

Jak widać, wszystkie pierścienie są wypełnione. Wynika to z faktu, że wszystkie segmenty biegną w tym samym kierunku, a więc promień wyciągnięty z jakiegoś punktu przetnie jeden lub więcej segmentów, a suma przecięć nie będzie równa zero. Na przykład na poniższej ilustracji czerwone strzałki reprezentują kierunek, w którym segmenty są rysowane, a biała strzałka reprezentuje dowolny promień uruchomiony od punktu w najbardziej wewnętrznym pierścieniu. Zaczynając od wartości zero, dla każdego segmentu, który promień przecina, dodawana jest wartość jeden, ponieważ segment ów przekracza promień z lewej na prawą.

Diagram przedstawiający wartość właściwości FillRule równą Nonzero.

Aby lepiej zademonstrować zachowanie reguły Nonzero, wymagany jest bardziej złożony kształt z segmentami działającymi w różnych kierunkach. Poniższy kod XAML tworzy podobny kształt, jak w poprzednim przykładzie, z tą różnicą, że jest tworzony przy użyciu PathGeometry a następnie EllipseGeometry, który tworzy cztery łuki koncentryczne, a nie w pełni zamknięte okręgi koncentryczne.

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

Poniższa ilustracja przedstawia kształt utworzony w poprzednim przykładzie.

Okrąg składający się z serii koncentrycznych pierścieni o naprzemiennych kolorach z niewypełnionym trzecim łukiem.

Zwróć uwagę, że trzeci łuk z środka nie jest wypełniony. Na poniższej ilustracji pokazano, dlaczego tak jest. Na ilustracji czerwone strzałki reprezentują kierunek rysowania segmentów. Dwie białe strzałki reprezentują dwa dowolne promienie, które wychodzą z punktu w obszarze bez wypełnienia. Jak widać na ilustracji, suma wartości z danego promienia przechodzącego przez segmenty w ścieżce wynosi zero. Jak zdefiniowano powyżej, suma zera oznacza, że punkt nie jest częścią geometrii (nie jest częścią wypełnienia), podczas gdy suma, która jest różna od zera, w tym wartość ujemna, jest częścią geometrii.

Diagram przedstawiający dowolne promienie przecinające segmenty.

Notatka

Do celów FillRulewszystkie kształty są uznawane za zamknięte. Jeśli w segmencie występuje luka, narysuj wyimaginowaną linię, aby ją zamknąć. W powyższym przykładzie istnieją małe luki w pierścieniach. Biorąc to pod uwagę, można oczekiwać, że promień biegnący przez szczelinę da inny wynik niż promień biegnący w innym kierunku. Poniżej znajduje się powiększona ilustracja jednej z tych luk oraz segmentu hipotetycznego (segment, który jest rysowany do celów zastosowania FillRule), który ją zamyka.

Diagram przedstawiający segmenty FillRule, które są zawsze zamknięte.

Przykład

Zobacz też