Geometry 概述

更新:2007 年 11 月

本概述介绍如何使用 Windows Presentation Foundation (WPF) Geometry 类来描绘形状。本主题还比较了 Geometry 对象与 Shape 元素之间的区别。

本主题包括下列各节。

  • 什么是 Geometry?
  • Geometry 与 Shape 的比较
  • 采用 Geometry 的常见属性
  • 简单的几何图形类型
  • PathGeometry
  • 复合几何图形
  • 组合的几何图形
  • Freezable 功能
  • 其他 Geometry 功能
  • 相关主题

什么是 Geometry?

使用 Geometry 类以及派生自它的其他类(如 EllipseGeometryPathGeometryCombinedGeometry),可以描绘二维形状的几何图形。这些几何图形的描绘具有许多用途,例如,定义一个要绘制到屏幕的形状或者定义命中测试和剪辑区域。您甚至可以使用 Geometry 来定义动画路径。

Geometry 对象可以很简单,例如矩形和圆形,也可以是基于两个或更多个 Geometry 对象创建的复合形状。使用 PathGeometryStreamGeometry 类可以创建更复杂的几何图形,这两个类可用于描绘弧线和曲线。

由于 Geometry 是一种 Freezable 类型,因此 Geometry 对象提供几个特殊功能:可声明为资源、可在多个对象之间共享、可设为只读以提高性能、可进行克隆以及可设为线程安全对象。有关 Freezable 对象提供的不同功能的更多信息,请参见 Freezable 对象概述

Geometry 与 Shape 的比较

GeometryShape 类的相似之处在于它们均描绘二维形状(例如,比较 EllipseGeometryEllipse),但它们之间存在一些重要的区别。

其一,Geometry 类继承自 Freezable 类,而 Shape 类则继承自 FrameworkElement。因为 Shape 对象是元素,所以它们可以进行自我呈现并参与布局系统,而 Geometry 对象则不能。

尽管 Shape 对象比 Geometry 对象更易于使用,但 Geometry 对象更通用。尽管 Shape 对象用于呈现二维图形,但 Geometry 对象可用于为二维图形定义几何区域、定义剪辑区域或者定义命中测试区域等等。

Path 形状

一个 Shape,即 Path 类实际使用 Geometry 来描绘它的内容。通过使用 Geometry 设置 PathData 属性以及设置它的 FillStroke 属性,可以呈现 Geometry

采用 Geometry 的常见属性

前面几部分提到 Geometry 对象可以与其他对象一起使用以实现多种用途,例如,绘制形状、进行动画处理以及剪辑。下表列出了几个类,这几个类都具有采用 Geometry 对象的属性。

类型

属性

DoubleAnimationUsingPath

PathGeometry

DrawingGroup

ClipGeometry

GeometryDrawing

Geometry

Path

Data

UIElement

Clip

简单的几何图形类型

所有几何图形的基类都是抽象类 Geometry。派生自 Geometry 类的类大致可以分为三个类别:简单的几何图形、路径几何图形以及复合几何图形。

简单的几何图形类包括 LineGeometryRectangleGeometryEllipseGeometry,用于创建基本的几何形状,如直线、矩形和圆。

  • LineGeometry 通过指定直线的起点和终点来定义。

  • RectangleGeometry 使用 Rect 结构来定义,该结构指定它的相对位置以及它的高度和宽度。您可以通过设置 RadiusXRadiusY 属性来创建圆角矩形。

  • EllipseGeometry 通过中心点、x 半径和 y 半径来定义。下面的示例演示如何创建简单的几何图形来进行呈现和剪辑。

可以使用 PathGeometry 或者通过将 Geometry 对象组合在一起来创建这些形状以及更复杂的形状,但是这些类提供了一种生成这些基本的几何形状的更简单方式。

下面的示例演示如何创建并呈现 LineGeometry。前面已提到,Geometry 对象无法进行自我绘制,因此本示例使用 Path 形状来呈现直线。因为直线没有面积,设置 PathFill 属性没有任何效果;因此仅指定 StrokeStrokeThickness 属性。下面的插图显示此示例的输出。

从 (10,20) 绘制到 (100,130) 的 LineGeometry

一个 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。该示例将 EllipseGeometryCenter 设置为点 50,50,将 x 半径和 y 半径均设置为 50,这将创建一个直径为 100 的圆。通过为 Path 元素的 Fill 属性赋予一个值(在本例中为 Gold)来绘制椭圆的内部。下面的插图显示此示例的输出。

绘制在 (50,50) 处的 EllipseGeometry

一个 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,这将创建一个正方形。下面的插图显示此示例的输出。

绘制在 50,50 处的 RectangleGeometry

一个 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 用作图像的剪辑区域。用 Width 200 和 Height 150 定义了一个 Image 对象。一个 RadiusX 值为 100、RadiusY 值为 75、Center 值为 100,75 的 EllipseGeometry 设置为图像的 Clip 属性。图像中只有位于椭圆区域内部的部分才会显示。下面的插图显示此示例的输出。

用于剪辑 Image 控件的 EllipseGeometry

具有剪辑和没有剪辑的图像

<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

在两个点之间创建一条直线。

如何:在 PathGeometry 中创建 LineSegment

PolyBezierSegment

创建一系列三次方贝塞尔曲线。

请参见 PolyBezierSegment 类型页。

PolyLineSegment

创建一系列直线。

请参见 PolyLineSegment 类型页。

PolyQuadraticBezierSegment

创建一系列二次贝塞尔曲线。

请参见 PolyQuadraticBezierSegment 页。

QuadraticBezierSegment

创建一条二次贝塞尔曲线。

如何:创建二次贝塞尔曲线 .

PathFigure 中的线段将合并为一个几何形状,该形状将每一条线段的终点作为下一条线段的起点。PathFigureStartPoint 属性指定绘制第一条线段的起始点。后面的每条线段都以上一条线段的终点作为起点。例如,通过将 StartPoint 属性设置为 10,50 并创建 Point 属性设置为 10,150 的 LineSegment,可定义一条从 10,50 到 10,150 的竖线。

下面的示例创建由一个 PathFigure(具有一个 LineSegment)组成的简单 PathGeometry,并使用 Path 元素来显示它。PathFigure 对象的 StartPoint 设置为 10,20,并用终点 100,130 定义一个 LineSegment。下面的插图显示了此示例创建的 PathGeometry

包含一个 LineSegment 的 PathGeometry

一个 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 的详细语法可以创建极其复杂的几何区域。

使用 PathSegment 对象的组合可以创建更复杂的几何图形。

下一个示例使用一个 BezierSegment、一个 LineSegment 以及一个 ArcSegment 来创建形状。该示例首先通过定义四个点来创建一个三次方贝塞尔曲线:起点(前一条线段的终点)、终点 (Point3) 以及两个控制点(Point1Point2)。三次方贝塞尔曲线的两个控制点的作用像磁铁一样,朝着自身的方向吸引本应为直线的部分,从而形成一条曲线。第一个控制点 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;

通过在一个 PathGeometry 内使用多个 PathFigure 对象,可以创建更复杂的几何图形。

下面的示例创建一个具有两个 PathFigure 对象的 PathGeometry,其中每个对象均包含多个 PathSegment 对象。使用了上面的示例中的 PathFigure 以及具有一个 PolyLineSegment 和一个 QuadraticBezierSegmentPathFigurePolyLineSegment 是用一个点数组定义的,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 创建形状

路径标记语法

PathGeometryStreamGeometry 类型使用一系列特殊的移动和绘制命令来支持可扩展应用程序标记语言 (XAML) 属性语法。有关更多信息,请参见路径标记语法

复合几何图形

使用 GeometryGroupCombinedGeometry 或者通过调用静态的 Geometry 方法 Combine,可以创建复合几何图形对象。

因为它们不执行合并操作,所以使用 GeometryGroup 对象的性能比使用 CombinedGeometry 对象或 Combine 方法的性能高。

组合的几何图形

前面一节提到,CombinedGeometry 对象和 Combine 方法合并它们包含的几何图形所定义的面积。GeometryCombineMode 枚举指定如何组合几何图形。GeometryCombineMode 属性的可能值有:UnionIntersectExcludeXor

在下面的示例中,用 Union 组合模式定义了一个 CombinedGeometryGeometry1Geometry2 定义为相同半径的圆,但是中心偏离 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>

“联合”组合模式的结果

在下面的示例中,用 Xor 组合模式定义了一个 CombinedGeometryGeometry1Geometry2 定义为相同半径的圆,但是中心偏离 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 功能

由于 Geometry 类继承自 Freezable 类,因此它提供了几个特殊功能:Geometry 对象可按资源概述中的方式进行声明、在多个对象之间共享、设为只读以提高性能、进行克隆以及设为线程安全。有关 Freezable 对象提供的不同功能的更多信息,请参见 Freezable 对象概述

其他 Geometry 功能

Geometry 类还提供有用的实用程序方法,例如:

有关其方法的完整列表,请参见 Geometry 类。

请参见

概念

优化性能:二维图形和图像处理

路径标记语法

动画概述

WPF 中的形状和基本绘图概述

Drawing 对象概述

参考

Geometry

PathGeometry

Path

GeometryDrawing

其他资源

几何图形帮助主题

几何图形示例