Como: Controlar o preenchimento de uma forma de composição
A propriedade FillRule de um GeometryGroup ou um PathGeometry, especifica uma "regra" que a forma de composição usa para determinar se um determinado ponto é parte de geometria. Há dois valores possíveis para FillRule: EvenOdd e Nonzero. As seções a seguir serão descrevem como para usar essas duas regras.
EvenOdd: Esta regra determina se é um ponto na região de preenchimento por desenho um raio desse ponto ao infinito em qualquer direção e contando o número de segmentos de caminho dentro da forma determinado que atravessa o raio. Se esse número for ímpar, o ponto está dentro; se é par, o ponto está fora.
Por exemplo, o XAML abaixo cria uma forma de composição composta de uma série de anéis concêntricos (destino) com um conjunto de FillRule para 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>
A ilustração a seguir mostra a forma criada no exemplo anterior.
Na ilustração acima, observe que o centro e o terceiro anel não estão preenchidos. Isso ocorre porque um raio desenhado a partir de um ponto dentro de qualquer um desses dois anéis passa por um número par de segmentos. Veja a ilustração abaixo:
Diferente de zero: Esta regra determina se é um ponto na região de preenchimento do caminho de desenhar um raio desse ponto ao infinito em qualquer direção e, em seguida, examinando os locais onde um segmento da forma cruza o ray. Começando com uma contagem do zero, adiciona um cada vez que um segmento cruza da esquerda para a direita e subtrai um cada vez que um segmento cruza o raio da direita para a esquerda. Após a contagem de cruzamentos, se o resultado é zero então o ponto está fora de caminho. Caso contrário, ele está dentro.
<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>
Usando o exemplo acima, um valor de Nonzero para FillRule fornece a ilustração a seguir como resultado:
Como você pode ver, todos os anéis estão preenchidos. Isto ocorre porque todos os segmentos vão na mesma direção e um raio desenhado de qualquer ponto irá cruzar um ou mais segmentos e a soma dos cruzamentos não será igual a zero. Por exemplo, na ilustração abaixo, as setas vermelhas representam a direção que os segmentos são desenhados a direção e a seta branca representa um raio arbitrário que começa em um ponto dentro do anel mais interno. Iniciando com um valor de zero, para cada segmento que o raio cruza, um valor de um é adicionado porque o segmento cruza o raio da esquerda para a direita.
Para melhor demonstrar o comportamento da regra Nonzero, uma forma mais complexa com segmentos indo em direções diferentes é necessária. O código XAML abaixo cria uma forma semelhante do exemplo anterior, exceto que ela é criada com uma PathGeometry em vez de um EllipseGeometry que cria quatro arcos concêntricos em vez de círculos concêntricos totalmente fechados.
<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>
A ilustração a seguir mostra a forma criada no exemplo anterior.
Observe que o terceiro arco a partir do centro não é preenchido. A ilustração abaixo mostra o porquê disso. Na ilustração, as setas vermelhas representam a direção em que os segmentos são desenhados. As duas setas em branco representam dois raios arbitrários que se movem para fora de um ponto na região não preenchida. Como pode ser deduzido da ilustração, a soma dos valores de um determinado raio que cruza os segmentos nos seus caminhos é zero. Como definido acima, uma soma zero significa que o ponto não é parte da geometria (não é parte do preenchimento) enquanto uma soma que é não-zero, incluindo um valor negativo, é parte a geometria.
Observação: Para fins de FillRule, todas as formas são consideradas fechado. Se houver um buraco em um segmento, desenhe uma linha imaginário para fechá-lo. No exemplo acima, existem pequenos buracos nos anéis. Dado isso, esperá-se que um raio que passa pelo buraco dê um resultado diferente de um raio indo em outra direção. Abaixo está uma ilustração ampliada de uma desses buracos e o "segmento imaginário" (segmento que é desenhado para fins de aplicar a FillRule) que o fecha.
Consulte também
Tarefas
Como: Create a Composite Shape