Draw a Circle Using Bezier Curves

Bézier Circles and Bézier Ellipses

Dec 6, 2012
New York, N.Y.

About 11 years ago, while writing my first book well-nigh Windows Forms programming, I became interested in the technique of rendering round arcs using Bézier curves, and I read a couple articles on the discipline from i of the many periodicals available at the New York Public Library:

    Tor Dokken, et al, "Expert Approximation of Circles past Curvature-Continuous Bézier curves," Reckoner Aided Geometric Design 7 (1990), 33-41.
    Michael Goldapp, "Approximation of Round Arcs by Cubic Polynomials," Computer Aided Geometric Design 8 (1991), 227-238.

As you know, a cubic Bézier curve in 2 dimensions is described by four points. The bend passes through the 2 endpoints p0 and p3, while p1 and p2 are control points that seem to pull the curve in their directions. When using a Bézier curve to draw a circular arc, p0 and p3 are points on the circle, and the two control points lie outside the circumvolve. Here are those four points defining the arc of a pie slice that is 1/8th of a circle:

The lines from p0 to p1 and from p3 to p2 are tangent to the circle, and hence at right angles to lines from the heart of the circle to the endpoints. This means that a vector describing the direction of these lines from the endpoints to the command points is easily calculable by rotating the vectors from the circle's centre to the endpoints by 90 degrees. (A 90 degree rotation of a normalized vector is pretty easy because y'all merely bandy the X and Y coordinates of the vector and make i of them negative.) The hard office is the length of those lines from p0 to p1 and from p3 to p2, which I've labeled with the letter of the alphabet L.

The kickoff article cited above indicates that a fairly skilful approximation results from:

L = four * tan(α / 4) / iii

times the radius of the circle, where the bending α is in degrees. For the above diagram, α is 45 degrees, so 50 is 0.265, and y'all can see that the length of these lines is approximately 1/4 of the radius.

The calculations of the two command points becomes exceptionally easy when the angle is 90 degrees, and the ii endpoints are at the top and sides of the circle:

The Y coordinates of p0 and p1 are now the same, as are the X coordinates of p2 and p3, and L is near 0.55. If the radius is 100, so the control points are 55 units from the endpoints, which is fairly easy to remember. But four Bézier curves are required to define a whole circle.

How well does this approximation work? Let's try a piddling XAML. This is for Windows 8 only it can be adjusted to any XAML-based framework. Two 100-pixel radius circles are drawn, i by a Path and an EllipseGeometry filled with blue, the second by a Path, PathFigure and four BezierSegment objects stroked with carmine. In both cases the center of the circle is (0, 0) which is centered in the window using a technique I like involving centering a complanate Canvas:

<Page ten:Grade="BezierCircle.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid Background="White">
<Sheet HorizontalAlignment="Center"
VerticalAlignment="Center">

            <Path Fill="Blueish">
<Path.Data>
<EllipseGeometry Middle="0 0"
RadiusX="100"
RadiusY="100" />
</Path.Data>
</Path>

            <Path Stroke="Cherry-red">
<Path.Information>
<PathGeometry>
<PathFigure StartPoint="0 -100"
IsClosed="True"
IsFilled="False">

                            <BezierSegment Point1="55 -100"
Point2="100 -55"
Point3="100 0" />

                            <BezierSegment Point1="100 55"
Point2="55 100"
Point3="0 100" />

                            <BezierSegment Point1="-55 100"
Point2="-100 55"
Point3="-100 0" />

                            <BezierSegment Point1="-100 -55 "
Point2="-55 -100"
Point3="0 -100" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Canvas>
</Filigree>
</Page>

Of course I could have used a single PolyBezierSegment for the circumvolve'south outline, merely it'south probably more than helpful to come across the actual coordinates for each segment of the total bend.

If the Bézier approximation is "good enough," the ruby circle should outline the blue interior without whatsoever white background peaking through on the within, or whatsoever blueish visible outside the red circumference. That appears to be the case:

Recently I received an email from a reader of Programming Windows 6th edition about applying this technique to ellipses. It's always helpful to recollect that an ellipse is a circle that's been stretched in ane direction, and possibly rotated (if the axes aren't parallel to the coordinate system). Regardless how a circle has been constructed, you tin can plow it into an ellipse by applying a ScaleTransform. Or, if you lot're using an EllipseGeometry, by setting different values of the RadiusX and RadiusY properties. Or, if you're defining a circle from Bézier curves, by uniformly scaling the 10 or Y coordinates of the points defining the curves.

The post-obit XAML file is very similar to the showtime one except that RadiusX is set to 300 and all the X coordinates of the points contributing to the Bézier curve accept been increased by a factor of 3:

<Page 10:Class="BezierEllipse.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid Background="White">
<Sheet HorizontalAlignment="Center"
VerticalAlignment="Center">

            <Path Fill up="Blue">
<Path.Data>
<EllipseGeometry Heart="0 0"
RadiusX="300"
RadiusY="100" />
</Path.Data>
</Path>

            <Path Stroke="Cherry-red">
<Path.Information>
<PathGeometry>
<PathFigure StartPoint="0 -100"
IsClosed="True"
IsFilled="False">

                            <BezierSegment Point1="165 -100"
Point2="300 -55"
Point3="300 0" />

                            <BezierSegment Point1="300 55"
Point2="165 100"
Point3="0 100" />

                            <BezierSegment Point1="-165 100"
Point2="-300 55"
Point3="-300 0" />

                            <BezierSegment Point1="-300 -55 "
Point2="-165 -100"
Point3="0 -100" />
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
</Sail>
</Grid>
</Page>

And hither'southward the result:

Again, the approximation if visually fine.

cunninghamthental.blogspot.com

Source: http://www.charlespetzold.com/blog/2012/12/Bezier-Circles-and-Bezier-Ellipses.html

0 Response to "Draw a Circle Using Bezier Curves"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel