Xamarin.Forms Kształty: reguły wypełniania
Kilka Xamarin.Forms klas kształtów ma FillRule
właściwości typu FillRule
. Należą do nich Polygon
: , Polyline
i GeometryGroup
.
Wyliczenie FillRule
definiuje EvenOdd
elementy i Nonzero
elementy członkowskie. Każdy element członkowski reprezentuje inną regułę określania, czy punkt znajduje się w regionie wypełnienia kształtu.
Ważne
Wszystkie kształty są uznawane za zamknięte dla celów reguł wypełniania.
Evenodd
Reguła EvenOdd
wypełnienia rysuje promienie od punktu do nieskończoności w dowolnym kierunku i zlicza liczbę segmentów w kształcie, które krzyże promienia. Jeśli ta liczba jest nieparzysta, punkt znajduje się wewnątrz. Jeśli ta liczba jest parzysta, punkt znajduje się poza.
Poniższy przykład XAML tworzy i renderuje kształt złożony z wartością domyślną FillRule
: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>
W tym przykładzie zostanie wyświetlony kształt złożony składający się z serii pierścieni koncentrycznych:
W kształcie złożonym zwróć uwagę, że środkowe i trzecie pierścienie 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:
Na powyższym obrazie czerwone okręgi reprezentują punkty, a linie reprezentują dowolne promienie. Dla górnego punktu dwa dowolne promienie przechodzą przez parzystą liczbę segmentów linii. W związku z tym pierścień, w którym znajduje się punkt, nie jest wypełniony. Dla dolnego punktu dwa dowolne promienie przechodzą przez nieparzyste segmenty linii. W związku z tym pierścień, w którym znajduje się punkt, jest wypełniony.
Niezerowa
Reguła Nonzero
wypełnienia rysuje promienie od punktu do nieskończoności w dowolnym kierunku, a następnie bada miejsca, w których segment kształtu przecina promienie. Począwszy od liczby zera, liczba jest zwiększana za każdym razem, gdy segment przecina promienie od lewej do prawej i dekrementowane za każdym razem, gdy segment przecina promienie od prawej do lewej. Po zliczaniu przepraw, jeśli wynik wynosi zero, punkt znajduje się poza wielokątem. W przeciwnym razie znajduje się wewnątrz.
Poniższy przykład XAML tworzy i renderuje kształt złożony z zestawem FillRule
na wartość 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>
W tym przykładzie zostanie wyświetlony kształt złożony składający się z serii pierścieni koncentrycznych:
Zwróć uwagę, że wszystkie pierścienie są wypełnione w kształcie złożonym. Wynika to z faktu, że wszystkie segmenty działają w tym samym kierunku, a więc promienie pobrane z dowolnego punktu przekroczy jeden lub więcej segmentów, a suma przekroczeń nie będzie równa zero:
Na ilustracji powyżej czerwonych strzałek reprezentują kierunek, w którym segmenty są rysowane, a czarna strzałka reprezentuje dowolny promień uruchomiony od punktu na najbardziej wewnętrznym pierścieniu. Począwszy od wartości zero, dla każdego segmentu, który przekreśli, wartość jednego jest dodawana, ponieważ segment przecina promienie od lewej do prawej.
Aby lepiej zademonstrować zachowanie Nonzero
reguły wypełnienia, wymagany jest bardziej złożony kształt z segmentami działającymi w różnych kierunkach. Poniższy przykład XAML tworzy podobny kształt do poprzedniego przykładu, z tą różnicą, że został utworzony za pomocą elementu PathGeometry
zamiast :EllipseGeometry
<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>
W tym przykładzie rysowana jest seria segmentów łuku, które nie są zamykane:
Na powyższym obrazie trzeci łuk z środka nie jest wypełniony. Wynika to z faktu, że suma wartości z danego promienia przekraczającego segmenty w ścieżce wynosi zero:
Na powyższej ilustracji czerwony okrąg reprezentuje punkt, czarne linie reprezentują dowolne promienie, które wynoszą się z punktu w nienapełnionym regionie, a czerwone strzałki reprezentują kierunek rysowania segmentów. Jak widać, suma wartości z promieni przekraczających segmenty wynosi zero:
- Dowolny promień, który porusza się po przekątnej po prawej, przecina dwa segmenty, które biegną w różnych kierunkach. W związku z tym segmenty anulują się nawzajem, dając wartość zero.
- Dowolny ray, który porusza się ukośnie lewe krzyże w sumie sześć segmentów. Jednak przejścia anulują się nawzajem, aby zero było ostateczną sumą.
Suma zera powoduje, że pierścień nie jest wypełniony.