Xamarin.Forms Formas: regras de preenchimento
Várias Xamarin.Forms classes Shapes têm FillRule
propriedades, do tipo FillRule
. Elas incluem Polygon
, Polyline
e GeometryGroup
.
A FillRule
enumeração define EvenOdd
e Nonzero
membros. Cada membro representa uma regra diferente para determinar se um ponto está na região de preenchimento de uma forma.
Importante
Todas as formas são consideradas fechadas para fins de regras de preenchimento.
EvenOdd
A EvenOdd
regra de preenchimento desenha um raio do ponto ao infinito em qualquer direção e conta o número de segmentos dentro da forma que o raio atravessa. Se esse número é ímpar, o ponto está dentro. Se esse número for par, o ponto está fora.
O exemplo XAML a seguir cria e renderiza uma forma composta, com o FillRule
padrão para 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>
Neste exemplo, uma forma composta composta por uma série de anéis concêntricos é exibida:
Na forma composta, observe que o centro e o terceiro anéis não estão preenchidos. Isso ocorre porque um raio desenhado de qualquer ponto dentro de qualquer um desses dois anéis passa por um número par de segmentos:
Na imagem acima, os círculos vermelhos representam pontos, e as linhas representam raios arbitrários. Para o ponto superior, os dois raios arbitrários passam cada um por um número par de segmentos de linha. Portanto, o anel em que o ponto está não está preenchido. Para o ponto inferior, os dois raios arbitrários passam cada um por um número ímpar de segmentos de linha. Portanto, o anel em que o ponto está é preenchido.
Diferentes de zero
A Nonzero
regra de preenchimento desenha um raio do ponto ao infinito em qualquer direção e, em seguida, examina os lugares onde um segmento da forma cruza o raio. Começando com uma contagem de zero, a contagem é incrementada cada vez que um segmento cruza o raio da esquerda para a direita e diminuída cada vez que um segmento cruza o raio da direita para a esquerda. Depois de contar os cruzamentos, se o resultado for zero, o ponto está fora do polígono. Caso contrário, está dentro.
O exemplo XAML a seguir cria e renderiza uma forma composta, com o FillRule
conjunto como 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>
Neste exemplo, uma forma composta composta por uma série de anéis concêntricos é exibida:
Na forma composta, observe que todos os anéis estão preenchidos. Isso ocorre porque todos os segmentos estão correndo na mesma direção, e assim um raio desenhado de qualquer ponto cruzará um ou mais segmentos e a soma dos cruzamentos não será igual a zero:
Na imagem acima, as setas vermelhas representam a direção em que os segmentos são desenhados, e a seta preta representa um raio arbitrário que corre de um ponto no anel mais interno. Iniciando com um valor de zero, para cada segmento que o raio cruza, um valor de um é adicionado, já que o segmento cruza o raio da esquerda para a direita.
Uma forma mais complexa Nonzero
com segmentos correndo em direções diferentes é necessária para demonstrar melhor o comportamento da regra de preenchimento. O exemplo XAML a seguir cria uma forma semelhante ao exemplo anterior, exceto que ele é criado com um PathGeometry
em vez de um 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>
Neste exemplo, uma série de segmentos de arco são desenhados, que não são fechados:
Na imagem acima, o terceiro arco do centro não é preenchido. Isso ocorre porque a soma dos valores de um determinado raio cruzando os segmentos em seu caminho é zero:
Na imagem acima, o círculo vermelho representa um ponto, as linhas pretas representam raios arbitrários que se movem do ponto na região não preenchida e as setas vermelhas representam a direção em que os segmentos são desenhados. Como pode ser visto, a soma dos valores dos raios que cruzam os segmentos é zero:
- O raio arbitrário que viaja diagonalmente para a direita cruza dois segmentos que correm em direções diferentes. Portanto, os segmentos se anulam dando um valor de zero.
- O raio arbitrário que viaja diagonalmente para a esquerda cruza um total de seis segmentos. No entanto, as travessias se anulam para que zero seja a soma final.
Uma soma de zero resulta no anel não ser preenchido.