Compartilhar via


Como: Controlar o preenchimento de uma forma de composição

The FillRule property of a GeometryGroup or a PathGeometry, specifies a "rule" which the composite shape uses to determine whether a given point is part of the geometry. Há dois valores possíveis para FillRule: EvenOdd and Nonzero. The following sections will describe how to use these two rules.

EvenOdd: Esta regra determina se um ponto está na região de preenchimento por um raio de desenho desse ponto ao infinito em qualquer direção e contando o número de segmentos de caminho dentro da forma de determinado a ray cruza. If this number is odd, the point is inside; if even, the point is outside.

For example, the XAML below creates a composite shape made up of a series of concentric rings (target) with a FillRule set to 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>

The following illustration shows the shape created in the previous example.

Captura de tela: propriedade FillRule de EvenOdd

In the illustration above, notice that the center and 3rd ring are not filled. This is because a ray drawn from any point within either of those two rings passes through an even number of segments. See illustration below:

Diagrama: valor EvenOdd da propriedade FillRule

Diferente de zero: Esta regra determina se um ponto está na região de preenchimento do caminho pelo desenho de um ray desse ponto ao infinito em qualquer direção e em seguida, examinando os lugares onde um segmento da forma cruza o ray. Starting with a count of zero, add one each time a Segment crosses the ray from left to right and subtract one each time a path segment crosses the ray from right to left. After counting the crossings, if the result is zero then the point is outside the path. Otherwise, it is inside.

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

Using the example above, a value of Nonzero for FillRule gives the following illustration as a result:

Captura de tela: valor NonZero de FillRule

As you can see, all the rings are filled. This is because all the segments are running in the same direction and so a ray drawn from any point will cross one or more segments and the sum of the crossings will not equal zero. For example, in the illustration below, the red arrows represent the direction the segments are drawn and the white arrow represents an arbitrary ray running from a point in the innermost ring. Starting with a value of zero, for each segment that the ray crosses, a value of one is added because the segment crosses the ray from left to right.

Diagrama: valor da propriedade FillRule igual a NonZero

To better demonstrate the behavior of Nonzero rule a more complex shape with segments running in different directions is required. The XAML code below creates a similar shape as the previous example except that it is created with a PathGeometry rather then a EllipseGeometry which creates four concentric arcs rather then fully closed concentric circles.

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

The following illustration shows the shape created in the previous example.

Captura de tela: valor NonZero da propriedade FillRule

Notice that the third arc from the center is not filled. The illustration below shows why this is. In the illustration, the red arrows represent the direction the segments are drawn. The two white arrows represent two arbitrary rays that move out from a point in the "non-filled" region. As can be seen from the illustration, the sum of the values from a given ray crossing the segments in its path is zero. As defined above, a sum of zero means that the point is not part of the geometry (not part of the fill) while a sum that is not zero, including a negative value, is part of the geometry.

Diagrama: valor NonZero da propriedade FillRule

Note: Para fins de FillRule, todas as formas são consideradas fechada. If there is a gap in a segment, draw an imaginary line to close it. In the example above, there are small gaps in the rings. Given this, one might expect a ray that runs through the gap to give a different result then a ray running in another direction. Below is an enlarged illustration of one of these gaps and the "imaginary segment" (segment that is drawn for purposes of applying the FillRule) that closes it.

Diagrama: para FillRule, os segmentos estão sempre fechados

Consulte também

Tarefas

Como: Create a Composite Shape

Conceitos

Visão Geral de Geometria