CombinedGeometry

20

Класс GeometryGroup — неоценимый инструмент для построения сложных фигур из базовых примитивов (прямоугольник, эллипс и линия). Однако он не лишен очевидных ограничений. Этот класс отлично работает при создании фигур посредством рисования одной фигуры и последующего "вычитания" из нее других. Однако получить требуемый результат сложно, если границы фигур пересекают друг друга, кроме того, он не поможет, если требуется удалить часть какой-то фигуры.

Класс CombinedGeometry предназначен для комбинирования перекрывающихся фигур, при этом ни одна фигура не содержит другую полностью. В отличие от GeometryGroup, класс CombinedGeometry принимает две геометрии, которые указываются в свойствах Geometry1 и Geometry2. Он не имеет свойства FillRule — вместо этого он имеет гораздо более мощное свойство GeometryCombineMode, которое принимает одно из четырех значений, перечисленных ниже:

Union

Создает фигуру, включающую все области обеих геометрий

Intersect

Создает фигуру, содержащую области, которые принадлежат обеим геометриям

Xor

Создает фигуру, содержащую область, которая принадлежит любой из геометрий, но не обеим сразу. Это равносильно комбинированию двух фигур (с помощью Union) с удалением их общей части (Intersect)

Exclude

Создает фигуру, включающую все области из первой геометрии, исключая области, которые принадлежат второй геометрии

Ниже показан пример, иллюстрирующий каждый из этих режимов:

<Window.Resources>
    <RectangleGeometry x:Key="rect" Rect="0 0 100 100"></RectangleGeometry>
    <EllipseGeometry x:Key="ellipse" Center="85 50" RadiusX="65" RadiusY="35"></EllipseGeometry>
  </Window.Resources>
    <Grid Margin="5" TextBlock.FontSize="16">
      <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>        
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
        <ColumnDefinition Width="Auto"></ColumnDefinition>
      </Grid.ColumnDefinitions>

      <Path Fill="Yellow" Stroke="Blue" Margin="5">
        <Path.Data>
          <CombinedGeometry GeometryCombineMode="Union"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
          </CombinedGeometry>                  
        </Path.Data>
      </Path>
      <TextBlock Grid.Column="1" Margin="10" VerticalAlignment="Center">Union</TextBlock>

      <Path Grid.Row="1" Fill="Yellow" Stroke="Blue" Margin="5">
        <Path.Data>
          <CombinedGeometry GeometryCombineMode="Intersect"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
          </CombinedGeometry>
        </Path.Data>
      </Path>
      <TextBlock Grid.Row="1" Grid.Column="1" Margin="10" VerticalAlignment="Center">Intersect</TextBlock>

      <Path Grid.Row="2" Fill="Yellow" Stroke="Blue" Margin="5">
        <Path.Data>
          <CombinedGeometry GeometryCombineMode="Xor"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
          </CombinedGeometry>
        </Path.Data>
      </Path>
      <TextBlock Grid.Row="2" Grid.Column="1" Margin="10" VerticalAlignment="Center">Xor</TextBlock>

      <Path Grid.Row="3" Fill="Yellow" Stroke="Blue" Margin="5">
        <Path.Data>
          <CombinedGeometry GeometryCombineMode="Exclude"
            CombinedGeometry.Geometry1="{StaticResource rect}"
            CombinedGeometry.Geometry2="{StaticResource ellipse}">
          </CombinedGeometry>                  
        </Path.Data>
      </Path>
      <TextBlock Grid.Row="3" Grid.Column="1" Margin="10" VerticalAlignment="Center">Exclude</TextBlock>
      
    </Grid>
Комбинирование фигур

Тот факт, что CombinedGeometry может комбинировать только две фигуры, может показаться существенным ограничением, но на самом деле это не так. Можно строить фигуру, которая включает десятки и более разных геометрий — для этого необходимо просто использовать вложенные объекты CombinedGeometry. Например, один объект CombinedGeometry может комбинировать два других объекта CombinedGeometry, которые сами могут комбинировать другие геометрии, и т.д. С применением этой техники можно строить весьма сложные детализированные фигуры.

Чтобы понять, как это работает, рассмотрим простой запрещающий знак (круг, перечеркнутый косой линией). Хотя не существует примитивов WPF, которые представляют такую фигуру, ее можно достаточно быстро собрать с помощью объектов CombinedGeometry:

<Canvas>
                <Path>
                    <Path.Data>
                        <CombinedGeometry GeometryCombineMode="Union">
                            <CombinedGeometry.Geometry1>
                                <CombinedGeometry GeometryCombineMode="Exclude">
                                    <CombinedGeometry.Geometry1>
                                        <EllipseGeometry Center="100,100" RadiusX="80" RadiusY="80"></EllipseGeometry>
                                    </CombinedGeometry.Geometry1>
                                    <CombinedGeometry.Geometry2>
                                        <EllipseGeometry Center="100,100" RadiusX="65" RadiusY="65"></EllipseGeometry>
                                    </CombinedGeometry.Geometry2>
                                </CombinedGeometry>
                            </CombinedGeometry.Geometry1>
                            <CombinedGeometry.Geometry2>
                                <RectangleGeometry Rect="30,93 140,15">
                                    <RectangleGeometry.Transform>
                                        <RotateTransform Angle="135" CenterX="100" CenterY="100"></RotateTransform>
                                    </RectangleGeometry.Transform>
                                </RectangleGeometry>
                            </CombinedGeometry.Geometry2>
                        </CombinedGeometry>
                    </Path.Data>
                    <Path.Fill>
                        <RadialGradientBrush GradientOrigin="0.75,0.25" RadiusX="0.6" RadiusY="0.6">
                            <GradientStop Color="Orange" Offset="0"></GradientStop>
                            <GradientStop Color="Red" Offset="1"></GradientStop>
                        </RadialGradientBrush>
                    </Path.Fill>
                </Path>
            </Canvas>
Несколько комбинированных фигур
Пройди тесты
Лучший чат для C# программистов