Общие сведения о классе Geometry

Обновлен: Ноябрь 2007

В данном обзоре объясняется, как использовать классы Windows Presentation Foundation (WPF) Geometry для описания фигур. Также в данном обзоре описаны различия между объектами класса Geometry и элементами класса Shape.

В этом разделе содержатся следующие подразделы.

  • Понятие о классе Geometry
  • Сравнение классов Geometry и Shape
  • Общие свойства, которые может принимать объект класса Geometry
  • Простые типы класса Geometry
  • Объекты PathGeometry
  • Составные объекты Geometry
  • Комбинированные объекты Geometry
  • Возможности объектов Freezable
  • Другие возможности объектов Geometry
  • Связанные разделы

Понятие о классе Geometry

Класс Geometry и производные от него классы, например, EllipseGeometry, PathGeometry и CombinedGeometry позволяют описывать геометрию двумерной фигуры. Данные геометрические описания имеют множество применений. Например, их можно использовать при определении фигуры для вывода на экран или при проверки нажатия и задании областей отсечения. Помимо этого геометрические описания можно использовать для определения пути анимации.

Объекты класса Geometry могут быть простыми, такими как прямоугольники и круги, или сложными, созданными из двух или более геометрических объектов. Более сложные геометрические объекты могут быть созданы с помощью классов PathGeometry и StreamGeometry, позволяющих описывать дуги и кривые.

Поскольку класс Geometry является наследником класса Freezable, то объекты класса Geometry обладают рядом специальных возможностей: их можно объявлять как ресурсы, которые могут совместно использоваться несколькими объектами, делать доступными только для чтения с целью повышения производительности, клонировать и делать потокобезопасными. Дополнительные сведения о различных возможностях, предоставляемых объектами класса Freezable, см. в разделе Общие сведения об объектах класса Freezable.

Сравнение классов Geometry и Shape

Сходство классов Geometry и Shape заключается в том, что они описывают двумерные фигуры (к примеру, сравните классы EllipseGeometry и Ellipse), но между ними существуют важные отличия.

Например, класс Geometry наследуется от класса Freezable, а класс Shape наследуется от класса FrameworkElement. Поскольку последние являются элементами, объекты класса Shape могут отображаться сами и участвовать в системе макета, а объекты класса Geometry не могут.

Несмотря на то, что с объектами Shape легче работать, чем с объектами Geometry, объекты Geometry являются более универсальными. Например, объект Shape можно использовать для отображения двумерной графики, а объект Geometry можно использовать для определения геометрической области для двумерной графики, определения области отсечения или определения области для проверки попадания курсора.

Подкласс Path класса Shape

Класс Path наследуется от класса Shape и фактически использует класс Geometry для описания своего содержимого. Задав свойство Data класса Path с помощью Geometry, и задав его свойства Fill и Stroke, можно отобразить объект класса Geometry.

Общие свойства, которые может принимать объект класса Geometry

В предыдущих разделах упоминалось, что объекты класса Geometry могут использоваться с другими объектами в различных целях, например, для рисования фигур, анимации и отсечения. В следующей таблице перечислены несколько классов, имеющих свойства, которые может принимать объект класса Geometry.

Класс

Свойство

DoubleAnimationUsingPath

PathGeometry

DrawingGroup

ClipGeometry

GeometryDrawing

Geometry

Path

Data

UIElement

Clip

Простые типы класса Geometry

Базовым классом для всех геометрических объектов является абстрактный класс Geometry. Классы, являющиеся производными от класса Geometry, можно сгруппировать в три категории: простые объекты Geometry, объекты PathGeometry и составные объекты Geometry.

Простые геометрические классы включают классы LineGeometry, RectangleGeometry и EllipseGeometry и используются для создания основных геометрических фигур, таких как линии, прямоугольники и окружности.

  • Объект класса LineGeometry определяется путем задания для линии начальной и конечной точек.

  • Объект класса RectangleGeometry определяется структурой Rect, которая задает его относительное положение, высоту и ширину. Можно создать скругленный прямоугольник, задав свойства RadiusX и RadiusY.

  • Объект класса EllipseGeometry определяется центральной точкой, x-радиусом и y-радиусом. В следующих примерах показано, как создать простые объекты Geometry для оотрисовки на экране и для отсечения.

Эти же фигуры, а также более сложные фигуры, могут быть созданы с помощью класса PathGeometry или путем объединения геометрических объектов, но данные классы предоставляют более простые средства для создания основных геометрических фигур.

В следующем примере показано создание и отображение объекта класса LineGeometry. Как было отмечено ранее, объект класса Geometry не может нарисовать сам себя, поэтому в примере используются фигуры класса Path для отображения линии. Так как линия не имеет области, задание свойства Fill класса Path никак не повлияет на объект. Вместо этого необходимо задать значения только для свойств Stroke и StrokeThickness. На следующем рисунке представлен результат выполнения данного примера.

LineGeometry, построенная от точки с координатами (10,20) до точки с координатами (100,130)
LineGeometry

<Path Stroke="Black" StrokeThickness="1" >
  <Path.Data>
    <LineGeometry StartPoint="10,20" EndPoint="100,130" />
  </Path.Data>
</Path>
LineGeometry myLineGeometry = new LineGeometry();
myLineGeometry.StartPoint = new Point(10,20);
myLineGeometry.EndPoint = new Point(100,130);

Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myLineGeometry;

В следующем примере демонстрируется создание и отображение объекта класса EllipseGeometry. В данном примере свойство Center класса EllipseGeometry задано точкой с координатами 50,50, а x-радиус и y-радиус задаются равными 50. В результате получается круг диаметром 100. Внутренняя часть эллипса закрашивается путем задания значения свойства Fill элемента Path, в данном случае Gold. На следующем рисунке представлен результат выполнения данного примера.

EllipseGeometry с центром в точке с координатами (50,50)
EllipseGeometry

<Path Fill="Gold" Stroke="Black" StrokeThickness="1">
  <Path.Data>
    <EllipseGeometry Center="50,50" RadiusX="50" RadiusY="50" />
  </Path.Data>
</Path>
EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new Point(50, 50);
myEllipseGeometry.RadiusX = 50;
myEllipseGeometry.RadiusY = 50;

Path myPath = new Path();
myPath.Fill = Brushes.Gold;
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myEllipseGeometry;

В следующем примере демонстрируется создание и отображение RectangleGeometry. Положение и размеры прямоугольника определяются структурой Rect. Относительное положение задано координатой 50,50, а высота и ширина равны 25. В результате получается квадрат. На следующем рисунке представлен результат выполнения данного примера.

RectangleGeometry, нарисованный в точке с координатами 50,50
RectangleGeometry

<Path Fill="LemonChiffon" Stroke="Black" StrokeThickness="1">
  <Path.Data>
    <RectangleGeometry Rect="50,50,25,25" />
  </Path.Data>
</Path>
RectangleGeometry myRectangleGeometry = new RectangleGeometry();    
myRectangleGeometry.Rect = new Rect(50,50,25,25);

Path myPath = new Path();
myPath.Fill = Brushes.LemonChiffon;
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myRectangleGeometry;

В следующем примере показано использование объекта класса EllipseGeometry в качестве области отсечения изображения. Объект Image задается с помощью свойства Width, значение которого равного 200 и с помощью свойства Height, значение которого равно 150. Объект класса EllipseGeometry со свойством RadiusX, значение которого равно 100, свойством RadiusY, значение которого равно 75, и свойством Center, значение которого равно (100,75), задает свойство Clip изображения. Будет отображаться только часть изображения, находящаяся внутри эллипса. На следующем рисунке представлен результат выполнения данного примера.

Использование объекта EllipseGeometry для отсечения элемента управления Image
Изображение с и без обрезки

<Image
  Source="sampleImages\Waterlilies.jpg"
  Width="200" Height="150" HorizontalAlignment="Left">
  <Image.Clip>
    <EllipseGeometry
      RadiusX="100"
      RadiusY="75"
      Center="100,75"/>
  </Image.Clip>
</Image>
// Create the image to clip.
Image myImage = new Image();
Uri imageUri = 
    new Uri(@"C:\\Documents and Settings\\All Users\\Documents\My Pictures\\Sample Pictures\\Water lilies.jpg", UriKind.Relative);
myImage.Source = new BitmapImage(imageUri);
myImage.Width = 200;
myImage.Height = 150;
myImage.HorizontalAlignment = HorizontalAlignment.Left;    

// Use an EllipseGeometry to define the clip region. 
EllipseGeometry myEllipseGeometry = new EllipseGeometry();
myEllipseGeometry.Center = new Point(100, 75);
myEllipseGeometry.RadiusX = 100;
myEllipseGeometry.RadiusY = 75;
myImage.Clip = myEllipseGeometry;

Объекты PathGeometry

Класс PathGeometry и его облегченный эквивалент класс StreamGeometry, предоставляют средства для описания нескольких сложных фигур, состоящих из дуг, кривых и линий.

Внутри класса PathGeometry находится коллекция объектов PathFigure, названных таким образом, потому что каждая фигура описывает дискретную форму в классе PathGeometry. Каждый объект PathFigure состоит из одного или нескольких объектов PathSegment, каждый из которых описывается сегмент фигуры.

Существует много типов сегментов.

Тип сегмента

Описание

Пример

ArcSegment

Создает эллиптическую дугу между двумя точками.

Практическое руководство. Создание эллиптической дуги.

BezierSegment

Создает кривую Безье третьего порядка между двумя точками.

Практическое руководство. Создание кривой Безье третьего порядка.

LineSegment

Создает линию между двумя точками.

Как создать LineSegment в PathGeometry

PolyBezierSegment

Создает набор кривых Безье третьего порядка.

См. в описании страницы типа класса PolyBezierSegment.

PolyLineSegment

Создает набор линий.

См. в описании страницы типа класса PolyLineSegment.

PolyQuadraticBezierSegment

Создает набор кривых Безье второго порядка.

См. в описании страницы типа класса PolyQuadraticBezierSegment.

QuadraticBezierSegment

Создает кривую Безье второго порядка.

Практическое руководство. Создание кривой Безье второго порядка.

Сегменты объекта PathFigure объединяются в одну геометрическую форму, причем конечная точка каждого сегмента совпадает с начальной точкой следующего сегмента. Свойство StartPoint класса PathFigure задает точку, из которой рисуется первый сегмент. Каждый последующий сегмент начинается в конечной точке предыдущего сегмента. Например, вертикальную линию из точки с координатами 10,50 в точку с координатами 10,150 можно определить, задав для свойства StartPoint значение 10,50 и создав объект LineSegment со свойством Point, имеющим значение 10,150.

В следующем примере создается простой объект PathGeometry, состоящий из одного объекта PathFigure с LineSegment, и отображается с помощью элемента Path. Для объекта PathFigure свойство StartPoint имеет значение 10,20, а объект LineSegment задается с конечной точкой 100,130. На следующем рисунке показан объект PathGeometry, созданный в данном примере.

Объект PathGeometry, содержащий один объект LineSegment
LineGeometry

<Path Stroke="Black" StrokeThickness="1">
  <Path.Data>
    <PathGeometry>
      <PathGeometry.Figures>
        <PathFigure StartPoint="10,20">
          <PathFigure.Segments>
            <LineSegment Point="100,130"/>
          </PathFigure.Segments>
        </PathFigure>
      </PathGeometry.Figures>
    </PathGeometry>
  </Path.Data>
</Path>
// Create a figure that describes a 
// line from (10,20) to (100,130).
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(10,20);
myPathFigure.Segments.Add(
    new LineSegment(new Point(100,130),
    true /* IsStroked */ ));

/// Create a PathGeometry to contain the figure.
PathGeometry myPathGeometry = new PathGeometry();
myPathGeometry.Figures.Add(myPathFigure);

// Display the PathGeometry. 
Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;

Стоит сравнить этот пример с предыдущим примером LineGeometry. Синтаксис, используемый для объектов PathGeometry, является гораздо более подробным, чем синтаксис, который используется для простых объектов LineGeometry, и в этом случае лучше использовать объект LineGeometry, но подробный синтаксис PathGeometry позволяет создавать очень сложные геометрические области.

Более сложные объекты Geometry можно создать с помощью комбинации объектов PathSegment.

В следующем примере для создания фигуры используются объекты BezierSegment, LineSegment и ArcSegment. В примере сначала создается кривая Безье третьего порядка путем задания четырех точек: начальной точки, которая является конечной точкой предыдущего сегмента, конечной точки (Point3) и двух контрольных точек (Point1 и Point2). Две контрольные точки кривой Безье третьего порядка подобны магнитам, притягивающим к себе сегменты кривой (в противном случае она была бы прямой), создавая таким образом кривую. Первая контрольная точка Point1, влияет на начальный участок кривой, а вторая контрольная точка Point2, влияет на конечный участок кривой.

На следующем шаге добавляется объект LineSegment, который отрисовывается из конечной точки предыдущего объекта BezierSegment в точку, заданную LineSegment.

Затем добавляется объект ArcSegment, который отрисовывается из конечной точки предыдущего LineSegment в точку, заданную Point. В примере также указываются x и y радиусы дуги (Size), угол поворота (RotationAngle), флаг, указывающий насколько большим должен быть угол полученной дуги (IsLargeArc), и значение, указывающее, в каком направлении строится дуга (SweepDirection). На следующем рисунке показана форма, созданная в данном примере.

Объект PathGeometry
Объект PathGeometry

<Path Stroke="Black" StrokeThickness="1" >
  <Path.Data>
    <PathGeometry>
      <PathGeometry.Figures>
        <PathFigure StartPoint="10,50">
          <PathFigure.Segments>
            <BezierSegment
              Point1="100,0"
              Point2="200,200"
              Point3="300,100"/>
            <LineSegment Point="400,100" />
            <ArcSegment
              Size="50,50" RotationAngle="45"
              IsLargeArc="True" SweepDirection="Clockwise"
              Point="200,100"/>
          </PathFigure.Segments>
        </PathFigure>
      </PathGeometry.Figures>
    </PathGeometry>
  </Path.Data>
</Path>
// Create a figure.
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(10,50);
myPathFigure.Segments.Add(
    new BezierSegment(
        new Point(100,0),
        new Point(200,200),
        new Point(300,100),
        true /* IsStroked */  )); 
myPathFigure.Segments.Add(
    new LineSegment(
        new Point(400,100),
        true /* IsStroked */ ));
myPathFigure.Segments.Add(
    new ArcSegment(
        new Point(200,100),
        new Size(50,50),
        45,
        true, /* IsLargeArc */ 
        SweepDirection.Clockwise, 
        true /* IsStroked */ ));                       

/// Create a PathGeometry to contain the figure.
PathGeometry myPathGeometry = new PathGeometry();
myPathGeometry.Figures.Add(myPathFigure);

// Display the PathGeometry. 
Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;

С помощью нескольких объектов PathFigure в коллекции PathGeometry можно создать еще более сложные геометрические объекты.

В следующем примере создается объект PathGeometry с двумя объектами PathFigure, каждый из которых содержит несколько объектов PathSegment. Используются PathFigure из предыдущего примера и PathFigure с PolyLineSegment и QuadraticBezierSegment. Объект PolyLineSegment задан с помощью массива точек, а объект QuadraticBezierSegment задан с помощью контрольной точки и конечной точки. На следующем рисунке показана форма, созданная в данном примере.

Объект PathGeometry с несколькими фигурами
Объект PathGeometry

<Path Stroke="Black" StrokeThickness="1" >
  <Path.Data>
    <PathGeometry>
      <PathGeometry.Figures>
        <PathFigure StartPoint="10,50">
          <PathFigure.Segments>
            <BezierSegment
              Point1="100,0"
              Point2="200,200"
              Point3="300,100"/>
            <LineSegment Point="400,100" />
            <ArcSegment
              Size="50,50" RotationAngle="45"
              IsLargeArc="True" SweepDirection="Clockwise"
              Point="200,100"/>
          </PathFigure.Segments>
        </PathFigure>

        <PathFigure StartPoint="10,100">
          <PathFigure.Segments>
            <PolyLineSegment Points="50,100 50,150" />
            <QuadraticBezierSegment Point1="200,200" Point2="300,100"/>
          </PathFigure.Segments>
        </PathFigure>                
      </PathGeometry.Figures>
    </PathGeometry>
  </Path.Data>
</Path>
PathGeometry myPathGeometry = new PathGeometry();            

// Create a figure.
PathFigure pathFigure1 = new PathFigure();
pathFigure1.StartPoint = new Point(10,50);
pathFigure1.Segments.Add(
    new BezierSegment(
        new Point(100,0),
        new Point(200,200),
        new Point(300,100),
        true /* IsStroked */ )); 
pathFigure1.Segments.Add(
    new LineSegment(
        new Point(400,100),
        true /* IsStroked */ ));
pathFigure1.Segments.Add(
    new ArcSegment(
        new Point(200,100),
        new Size(50,50),
        45,
        true, /* IsLargeArc */
        SweepDirection.Clockwise, 
        true /* IsStroked */ ));
myPathGeometry.Figures.Add(pathFigure1);    

// Create another figure.
PathFigure pathFigure2 = new PathFigure();
pathFigure2.StartPoint = new Point(10,100);
Point[] polyLinePointArray = 
    new Point[]{ new Point(50, 100), new Point(50, 150)};
PolyLineSegment myPolyLineSegment = new PolyLineSegment();
myPolyLineSegment.Points = 
    new PointCollection(polyLinePointArray);
pathFigure2.Segments.Add(myPolyLineSegment);
pathFigure2.Segments.Add(
    new QuadraticBezierSegment(
        new Point(200,200),
        new Point(300,100),
        true /* IsStroked */ ));
myPathGeometry.Figures.Add(pathFigure2);

// Display the PathGeometry. 
Path myPath = new Path();
myPath.Stroke = Brushes.Black;
myPath.StrokeThickness = 1;
myPath.Data = myPathGeometry;

Объект StreamGeometry

Как и класс PathGeometry, класс StreamGeometry определяет сложную геометрическую форму, которая может содержать кривые, дуги и линии. В отличие от объектов PathGeometry, содержимое StreamGeometry не поддерживает привязку данных, анимацию или изменения. Объект используется StreamGeometry для описания сложной геометрии, но без служебных данных поддержки привязки данных, анимации или изменения. Ввиду своей эффективности, класс StreamGeometry лучше всего подходит для описания декоративных элементов.

Пример см. в разделе Как создать фигуру с помощью StreamGeometry.

Синтаксис разметки пути

Типы PathGeometry и StreamGeometry поддерживают синтаксис атрибута Язык XAML (Extensible Application Markup Language) с использованием специальных последовательностей команд перемещения и рисования. Дополнительные сведения см. в разделе Синтаксис разметки пути.

Составные объекты Geometry

Составные объекты Geometry можно создать с помощью GeometryGroup, CombinedGeometry или путем вызова статического метода GeometryCombine.

  • Объект CombinedGeometry и метод Combine выполняют логическую операцию объединения областей, занимаемых двумя объектами Geometry. Объекты Geometry, не имеющие занимаемой области, отбрасываются. Можно скомбинировать только два объекта Geometry (хотя эти два объекта также могут быть составными).

  • Класс GeometryGroup создает объединение содержащихся в нем объектов Geometry без объединения занимаемых ими областей. К объекту GeometryGroup можно добавить любое число объектов Geometry. Пример см. в разделе Практическое руководство. Создание составной фигуры.

Поскольку они не выполняют операцию объединения, использование объектов GeometryGroup обеспечивает выигрыш в производительности по сравнению с использованием объектов CombinedGeometry или метода Combine.

Комбинированные объекты Geometry

В предыдущем подразделе упоминалось, что объект CombinedGeometry и метод Combine объединяют области, занимаемые содержащимися в них объектами Geometry. Перечисление GeometryCombineMode задает способ комбинирования объектов Geometry. Возможны следующие значения свойства GeometryCombineMode: Union, IntersectExclude и Xor.

В следующем примере объект CombinedGeometry определен режимом объединения Union. Geometry1 и Geometry2 задаются как круги с одинаковыми радиусами, но с центрами, смещенными на 50.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>

    <!-- Combines two geometries using the union combine mode. -->
    <CombinedGeometry GeometryCombineMode="Union">
      <CombinedGeometry.Geometry1>
        <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
      </CombinedGeometry.Geometry1>
      <CombinedGeometry.Geometry2>
        <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
      </CombinedGeometry.Geometry2>
    </CombinedGeometry>
  </Path.Data>
</Path>

Результаты объединенного режима Union

В следующем примере объект CombinedGeometry определен режимом объединения Xor. Geometry1 и Geometry2 задаются как круги с одинаковыми радиусами, но с центрами, смещенными на 50.

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
  <Path.Data>

    <!-- Combines two geometries using the XOR combine mode. -->
    <CombinedGeometry GeometryCombineMode="Xor">
      <CombinedGeometry.Geometry1>
        <EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
      </CombinedGeometry.Geometry1>
      <CombinedGeometry.Geometry2>
        <EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
      </CombinedGeometry.Geometry2>
    </CombinedGeometry>
  </Path.Data>
</Path>

Результаты объединенного режима Xor

Дополнительные примеры см. в разделах Практическое руководство. Создание составной фигуры и Практическое руководство. Создание объединенных геометрических объектов.

Возможности объектов Freezable

Поскольку класс наследуется от класса Freezable, класс Geometry предоставляет несколько особенных возможностей: объекты класса Geometry можно объявлять как Общие сведения о ресурсах, которые могут совместно использоваться несколькими объектами, делать доступными только для чтения с целью повышения производительности, клонировать и делать потокобезопасными. Дополнительные сведения о различных возможностях, предоставляемых объектами класса Freezable, см. в разделе Общие сведения об объектах класса Freezable.

Другие возможности объектов Geometry

Класс Geometry также предоставляет полезные служебные методы, например:

  • GetArea — возвращает область, занимаемую объектом Geometry.

  • FillContains — определяет, есть ли в объекте Geometry другие объекты Geometry.

  • StrokeContains — определяет, содержит ли объект Geometry указанную точку.

Полный список методов см. в классе Geometry.

См. также

Основные понятия

Оптимизация производительности: двумерная графика и обработка изображений

Синтаксис разметки пути

Общие сведения об эффектах анимации

Обзор фигур и базовых средств рисования в приложении WPF

Обзор объектов Drawing

Ссылки

Geometry

PathGeometry

Path

GeometryDrawing

Другие ресурсы

Разделы руководства, посвященные геометрии

Примеры работы с геометрическими объектами