Title: Draw an elliptical arc in WPF and XAML
This example shows how to use XAML code to draw an elliptical arc in a WPF. The following sections explain how to specify an elliptical arc and how to draw one in XAML.
Specifying an Elliptical Arc
WPF provides several drawing classes that draw shapes such as Rectangle, Line, and Ellipse. Those objects are relatively straightforward. You create the object and then specify some fairly intuitive properties to determine the shape's geometry, fill, and outline characteristics.
Unfortunately, the ArcSegment class that WPF uses to draw an elliptical arc provides a nice demonstration of the unofficial WPF slogan, "Twice as flexible and only five times as hard." Actually drawing an elliptical arc may be ten times as hard as it is in Windows Forms. Here's what I think the WPF engineers were thinking and how you draw arcs in WPF.
What Were They Thinking?
Shapes such as rectangles and ellipses are two-dimensional closed shapes. An elliptical arc is a one-dimensional curve. Because it is a curve, you might want to use it in a sequence of other one-dimensional shapes such as Bézier curves, polylines, and lines. (The model is inconsistent here because you can add lines to a sequence but there is also a perfectly usable Line class.)
If you are going to use an elliptical arc in a sequence of curves, it might make sense to specify the arc by giving its start and end points. Then, for example, you could draw a line from point A to point B, a B zier curve from point B to point C, an elliptical arc from point C to point D, and so forth.
In general there are an infinite number of ellipses that pass through two given points, so you need to specify a few other parameters to determine the ellipse to use and the arc on that ellipse that you want. For some reason, the WPF developers decided that you should specify the width and height of the ellipse that defines the arc. In general, there are up to two ellipses with a given width and height that pass through two points. The picture at the top of this post shows two black points and two ellipses (pink and blue) with a specific size that pass through the points.
If you look at the ellipses in the figure, you can see that there are four elliptical arcs that move from the blue point to the red point. The pink and blue ellipses each contain two of the arcs, one in the clockwise direction and one in the counterclockwise direction.
Notice that the larger arc from the blue point to the red point is in the clockwise direction on the blue ellipse and in the counterclockwise direction on the pink ellipse.
The parameters that you need to specify to completely determine the elliptical arc are the following.
- The start point
- The end point
- The width and height of the ellipse
- Whether the elliptical arc is a large arc (spans more than half of the ellipse)
- Whether the arc should move clockwise or counterclockwise
Drawing an Elliptical Arc
Unfortunately, you can't just place an elliptical arc inside another control such as a Grid or Canvas in WPF. Because WPF assumes that the arc is part of a sequence of one-dimensional curves, you need to build such a sequence even if you only want to draw a single arc.
To build the arc, you need to create a Path. Then you set the Path object's Data property to a PathGeometry object. You then give the PathGeometry object a new PathFigure object.
The PathFigure object's StartPoint property indicates where the sequence of one-dimensional shapes begins. If you only want to draw a single elliptical arc, then this is its start point. If you are drawing a sequence of shapes, then each shape's start point is where the previous shape ended.
The PathFigure object contains a segment collection. This is where you finally add an ArcSegment to represent the elliptical arc.
Here's the XAML code that the example program uses to create the blue dashed arc shown in the picture at the top of the post.
<Path Stroke="Blue" StrokeThickness="3" StrokeDashArray="5,5">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigureCollection>
<PathFigure StartPoint="62,114">
<PathFigure.Segments>
<PathSegmentCollection>
<ArcSegment Size="90,70"
RotationAngle="0"
IsLargeArc="True"
SweepDirection="Clockwise"
Point="198,159" />
</PathSegmentCollection>
</PathFigure.Segments>
</PathFigure>
</PathFigureCollection>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
Simple, isn't it?
Notice how the PathFigure determines the arc's starting point. If you look again at the picture, you should be able to see how the IsLargeArc and SweepDirection parameters determine which arc to draw.
Personally, I find this a ridiculously difficult way to specify an elliptical arc. In my next post, I'll explain how you can specify an arc in a more intuitive way. (The way that's used by Windows Forms programs and every other drawing package I've used.)
Download the example to experiment with it and to see additional details.
|