幾何概觀
更新:2007 年 11 月
本概觀會說明如何使用 Windows Presentation Foundation (WPF) Geometry 類別描述圖案。本主題也會比較 Geometry 物件與 Shape 項目之間的差異。
這個主題包含下列章節。
- 什麼是 Geometry?
- Geometry 和 Shape 的比較
- 常見接受 Geometry 的屬性
- 簡單幾何型別
- 路徑幾何
- 複合幾何
- 合併後的幾何
- Freezable 功能
- 其他 Geometry 功能
- 相關主題
什麼是 Geometry?
Geometry 類別及其衍生類別 (例如 EllipseGeometry、PathGeometry 以及 CombinedGeometry) 讓您可以描述 2-D 圖案的幾何。這些幾何描述有許多用途,例如定義要繪製至螢幕的圖案或者定義點擊測試和裁剪區域。您甚至可以使用幾何定義動畫路徑。
Geometry 物件可以是簡單的,例如矩形和圓形,或從兩個以上幾何物件建立的複合圖案。PathGeometry 和 StreamGeometry 類別可以讓您描述弧線和曲線,因此可以用來建立更複雜的幾何。
因為 Geometry 是一種 Freezable,所以 Geometry 物件可提供數項特殊功能:可以宣告為資源、供多個物件共用、設成唯讀以提升效能、複製以及設成安全執行緒 (Thread-Safe)。如需 Freezable 物件提供之不同功能的詳細資訊,請參閱 Freezable 物件概觀。
Geometry 和 Shape 的比較
Geometry 和 Shape 類別看似相同,因為它們都描述 2-D 圖案 (例如可以比較 EllipseGeometry 和 Ellipse),但是其實有相當重要的差別。
其中一個就是 Geometry 類別是繼承自 Freezable 類別,而 Shape 類別則是繼承自 FrameworkElement。Shape 物件因為是項目,所以可以自行呈現並參與配置系統,但是 Geometry 物件不行。
雖然 Shape 物件比 Geometry 物件更實用,但是 Geometry 物件用途較廣。Shape 物件是用於呈現 2-D 圖形,而 Geometry 物件則可以用於定義 2-D 圖形的幾何區域、定義裁剪的區域,或定義點擊測試 (Hit Testing) 區域等等。
路徑圖案
有一個 Shape (Path 類別) 實際上會使用 Geometry 描述其內容。藉由以 Geometry 設定 Path 的 Data 屬性,並且設定其 Fill 和 Stroke 屬性,您可以呈現 Geometry。
常見接受 Geometry 的屬性
前面幾節曾提到 Geometry 物件可以與其他物件搭配用於各種目的,例如繪製圖案、建立動畫及裁剪。下表列出數個類別,這些類別都具有會接受 Geometry 物件的屬性。
型別 |
屬性 |
---|---|
簡單幾何型別
所有幾何的基底類別都是抽象類別 Geometry。從 Geometry 類別衍生的類別可以大略分為三類:簡單幾何、路徑幾何和複合幾何。
簡單幾何類別包括 LineGeometry、RectangleGeometry 和 EllipseGeometry,可用於建立基本幾何圖案,例如線條、矩形和圓形。
定義 LineGeometry 的方法是指定線條的起始點和結束點。
RectangleGeometry 是以 Rect 結構定義,這個結構指定它的相對位置和高度與寬度。您可以設定 RadiusX 和 RadiusY 屬性來建立圓角矩形。
EllipseGeometry 是以中心點、X 半徑和 Y 半徑定義。下列範例顯示如何建立用於呈現及裁剪的簡單幾何。
這些相同的圖案以及更複雜的圖案,可以透過 PathGeometry 來建立,或合併幾何物件來建立,但是這些類別可以提供簡單的方法來產生這些基本幾何圖案。
下列範例顯示如何建立和呈現 LineGeometry。如同先前提及的,Geometry 物件本身無法進行繪製,所以範例使用 Path 圖案呈現線條。因為線條沒有面積,所以設定 Path 的 Fill 屬性不會有效果,只要指定 Stroke 和 StrokeThickness 屬性即可。下圖顯示的是範例的輸出。
從 (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。這個範例會將 EllipseGeometry 的 Center 設定為 50,50 一點,並將 X 半徑和 Y 半徑都設定為 50,以建立直徑 100 的圓形。橢圓形的內部是藉由將值 (在這個案例中是 Gold) 指定至 Path 項目的 Fill 屬性來繪製。下圖顯示的是範例的輸出。
繪製在 (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,以建立正方形。下圖顯示的是範例的輸出。
繪製在 (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。這個影像的 Clip 屬性會設定為具有值為 100 的 RadiusX、值為 75 的 RadiusY,以及值為 100,75 的 Center 的 EllipseGeometry。只會顯示在橢圓區域中的影像部分。下圖顯示的是範例的輸出。
用以裁剪 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 類別及其輕量型對等用法 (StreamGeometry 類別) 提供方法來描述由弧線、曲線及線條組成的多個複雜圖形。
PathGeometry 的核心是 PathFigure 物件的集合,會如此命名是因為每個圖形都會描述 PathGeometry 中的不同圖案。每個 PathFigure 本身都是由一個或多個 PathSegment 物件組成,而每個物件都描述圖形的某一個區段。
區段有許多種。
區段類型 |
描述 |
範例 |
---|---|---|
在兩點之間建立橢圓弧線。 |
||
在兩點之間建立三次方貝茲曲線。 |
||
在兩點之間建立線條。 |
||
建立一系列的三次方貝茲曲線。 |
請參閱 PolyBezierSegment 型別頁面 |
|
建立一系列線條。 |
請參閱 PolyLineSegment 型別頁面 |
|
建立一系列二次方貝茲曲線。 |
請參閱 PolyQuadraticBezierSegment 頁面 |
|
建立一條二次方貝茲曲線。 |
PathFigure 中的區段可以合併成單一幾何圖案,其中每個區段的結束點都是下一個區段的起始點。PathFigure 的 StartPoint 屬性會指定繪製第一個區段的起點。後續的區段再從前一個區段的終點開始。例如,要定義 10,50 到 10,150 的垂直線,可以將 StartPoint 屬性設為 10,50,然後建立 LineSegment,並將其 Point 屬性設為 10,150。
下列範例會建立由單一 PathFigure (含 LineSegment) 組成的簡單 PathGeometry,並使用 Path 項目加以顯示。PathFigure 物件的 StartPoint 是設為 10,20,LineSegment 的結束點是定義為 100,130。下圖顯示這個範例所建立的 PathGeometry。
包含單一 LineSegment 的 PathGeometry
<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) 以及兩個控制點 (Point1 和 Point2)。三次方貝茲曲線的兩個控制點就跟磁鐵一樣,會將原本為直線的部分吸引往它們靠近,最後形成曲線。第一個控制點 Point1 會影響曲線的開始部分,而第二個控制點 Point2 則會影響曲線的結束部分。
然後範例會加入 LineSegment,這條線段是從它前面的上一個 BezierSegment 的結束點,繪製至它的 LineSegment 屬性指定的點。
然後範例會加入 ArcSegment,這條弧線是從上述的 LineSegment 的結束點繪製至它的 Point 屬性指定的點。範例也會指定弧線的 X 和 Y 半徑 (Size)、旋轉角度 (RotationAngle)、指出結果弧線角度大小的旗標 (IsLargeArc),以及指出弧線繪製方向的值 (SweepDirection)。下圖顯示這個範例建立的圖案。
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 物件來建立。
下列範例會建立 PathGeometry,它具有兩個 PathFigure 物件,而這兩個物件都包含多個 PathSegment 物件。使用的有上述範例中的 PathFigure、具有 PolyLineSegment 的 PathFigure,以及 QuadraticBezierSegment。PolyLineSegment 是以點的陣列定義,QuadraticBezierSegment 則是以控制點和結束點定義。下圖顯示這個範例建立的圖案。
具有多個圖形的 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 類別因為十分具有效率,所以是描述裝飾項的好選擇。
如需範例,請參閱 HOW TO:使用 StreamGeometry 建立圖案。
路徑標記語法
PathGeometry 和 StreamGeometry 型別支援一種可延伸標記語言 (XAML) 屬性語法,該語法使用一系列特殊的移動和繪製命令。如需詳細資訊,請參閱路徑標記語法。
複合幾何
複合幾何物件可以透過 GeometryGroup (一種 CombinedGeometry) 建立,或藉由呼叫靜態 Geometry 方法 Combine 來建立。
CombinedGeometry 物件和 Combine 方法會執行布林運算,以合併由兩個幾何定義的區域。沒有面積的 Geometry 物件會遭到捨棄。只有兩個 Geometry 物件可以合併 (雖然這兩個幾何也可能是複合幾何)。
GeometryGroup 類別會建立所含 Geometry 物件的彙總,但不合併其區域。任意數目的 Geometry 物件都可以加入至 GeometryGroup。如需範例,請參閱HOW TO:建立複合圖案。
GeometryGroup 物件不會執行合併作業,因此使用這些物件會比使用 CombinedGeometry 物件或 Combine 方法更具效能優點。
合併後的幾何
前面一節曾提到 CombinedGeometry 物件和 Combine 方法會將所含幾何所定義的區域合併。GeometryCombineMode 列舉型別會指定幾何合併的方式。GeometryCombineMode 屬性可能的值為:Union、Intersect、Exclude 和 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>
在下列範例中,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>
如需其他範例,請參閱 HOW TO:建立複合圖案和 HOW TO:建立合併幾何。
Freezable 功能
Geometry 類別繼承自 Freezable 類別,因此可以提供數項特殊功能:Geometry 物件可以宣告為資源概觀、供多個物件共用、設成唯讀以提升效能、複製以及設成安全執行緒 (Thread-Safe)。如需 Freezable 物件提供之不同功能的詳細資訊,請參閱 Freezable 物件概觀。
其他 Geometry 功能
Geometry 類別也會提供有用的公用程式方法,例如下列方法:
FillContains - 判斷 Geometry 是否包含其他 Geometry。
StrokeContains - 判斷 Geometry 的描邊是否包含指定點。
如需 Geometry 方法的完整清單,請參閱 Geometry。