# Drawing Rotated and Skewed Ellipses

### WEBINAR:On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017

#### Introduction

Rectangles, Rounded Rectangles and Ellipses in Windows can only be drawn by GDI as axis-aligned figures. If one wishes to draw rotated or skewed figures under Windows NT, one can use World Transforms but they are unfortunately not available under Windows 95/98. For a cross-platform solution, one needs to do more of the work oneself. Rectangles can be simulated trivially using polygons with four vertices, which can then be rotated or skewed. However, what is one do for ellipses? There are basically three choices:

#### Alternatives

• Use a custom function to draw the ellipse.

The mathematics for ellipses are relatively simple and there are modified Bresenham equations for rotated ellipses in standard texts. However, this means that one must perform the rasterization oneself, which can get complicated for thick lines. This amount of effort is probably only worthwhile if one is already drawing to an off-screen surface (e.g. DirectDraw) or a bitmap.

• Drawing ellipses as connected line segments.

The actual lines can be drawn via LineTo(...) or Polyline(...) GDI calls. One can perform the approximation of the ellipses oneself or take advantage of the GDI FlattenPath(...) function.

• Use cubic bezier curves to approximate ellipses.

This is the method illustrated here.

#### Drawing ellipses as connected bezier curves

Using just four bezier curves, each representing 90 degrees of the original axis-aligned ellipse, one can arrive at a fair approximation with a maximum error of just 0.027%. This is equivalent to a maximum error of less than one pixel for ellipses with radii up to 3700, more than enough accuracy for our purposes.

1. Simplicity.

Only four GDI calls are needed. The calculations of the bezier control points are trivial.

2. Speed.

One can take advantage of hardware support of curve drawing on newer video cards. On my system, this is as fast as, if not faster than, GDI calls to Ellipse(...)

3. Transformations.

Because bezier curves are invariant under rotation, scaling and translation, one only needs to transform the control points to apply the same transformations to one's ellipse. More precisely, since each point on a cubic bezier curve is a barycentric combination of the control points, the relationship of the curve to the control points is not changed under affine maps.

4. Device independence.

If one is converting ellipses to line segments or rasterizing oneself, each time the resolution of one's surfaces or device context changes (for example when drawing to a printer DC), one must re-rasterize. This is not necessary with bezier curves. An additional advantage is that the ellipses can be exported via metafiles to drawing programmes such as CORELDRAW, which can then scale the figures without gross distortions or artefacts.

#### Procedure

First start off with a rectangle bounding an axis aligned ellipse (as in a normal GDI call). The thirteen bezier control points (labelled 0-12 below) defining the four bezier curves making up the ellipse can be calculated easily using an empirically derived "magical constant". The following code produces the control points for mapping modes where +ve Y is downwards (e.g. MM_TEXT). Where the opposite is true, just have a negative y value for the offset variable as indicated in the comments.

```
// Create points to simulate ellipse using beziers
void EllipseToBezier(CRect& r, CPoint* cCtlPt)
{
// MAGICAL CONSTANT to map ellipse to beziers
//  			2/3*(sqrt(2)-1)
const double EToBConst =	0.2761423749154;

CSize offset((int)(r.Width() * EToBConst), (int)(r.Height() * EToBConst));
//  Use the following line instead for mapping systems where +ve Y is upwards
//  CSize offset((int)(r.Width() * EToBConst), -(int)(r.Height() * EToBConst));

CPoint centre((r.left + r.right) / 2, (r.top + r.bottom) / 2);

cCtlPt[0].x  =                            //------------------------/
cCtlPt[1].x  =                            //                        /
cCtlPt[11].x =                            //        2___3___4       /
cCtlPt[12].x = r.left;                    //     1             5    /
cCtlPt[5].x  =                            //     |             |    /
cCtlPt[6].x  =                            //     |             |    /
cCtlPt[7].x  = r.right;                   //     0,12          6    /
cCtlPt[2].x  =                            //     |             |    /
cCtlPt[10].x = centre.x - offset.cx;      //     |             |    /
cCtlPt[4].x  =                            //    11             7    /
cCtlPt[8].x  = centre.x + offset.cx;      //       10___9___8       /
cCtlPt[3].x  =                            //                        /
cCtlPt[9].x  = centre.x;                  //------------------------*

cCtlPt[2].y  =
cCtlPt[3].y  =
cCtlPt[4].y  = r.top;
cCtlPt[8].y  =
cCtlPt[9].y  =
cCtlPt[10].y = r.bottom;
cCtlPt[7].y  =
cCtlPt[11].y = centre.y + offset.cy;
cCtlPt[1].y  =
cCtlPt[5].y  = centre.y - offset.cy;
cCtlPt[0].y  =
cCtlPt[12].y =
cCtlPt[6].y  = centre.y;
}
```
Rotation of the Ellipse can be accomplished using code similar to:
```
// LDPoint is an equivalent type to CPoint but with floating point precision
void Rotate(double radians, const CPoint& c, CPoint* vCtlPt, unsigned Cnt)
{
LDPoint constTerm(      c.x - c.x * cosAng - c.y * sinAng,
c.y + c.x * sinAng - c.y * cosAng);

for (int i = Cnt-1; i>=0; --i)
{
vCtlPt[i] = (LDPoint(   vCtlPt[i].x * cosAng + vCtlPt[i].y * sinAng,
-vCtlPt[i].x * sinAng + vCtlPt[i].y * cosAng) + constTerm).GetCPoint();
}
}

// Create Ellipse
CRect rect; GetClientRect(&rect);
CPoint ellipsePts[13];
EllipseToBezier(ellipseR, ellipsePts);

// Rotate
```

#### Filled Ellipses

Of course, four bezier curves together only make up the outline of an ellipse, whether rotated or not. Thankfully, Win32 Path functions are there for filled ellipses. One only needs to enclose the PolyBezier(...) call in a Path Bracket. The resulting path can be stroked and filled to one's satisfaction. If one is feeling adventurous, further special fills like gradients, custom bitmaps or fractals etc. can be achieved by first setting the clipping region to the path via SelectClipPath(...).

```
dc.BeginPath();
dc.PolyBezier(ellipsePts);
dc.EndPath();
dc.StrokePath;
// or FillPath();
// or StrokeAndFillPath();
// or PathToRegion(dc.m_hDC);
```

#### Thick Dashed or Dotted Ellipses Outlines under Win95/8

Win95/8 only supports solid thick lines. However, dashed or dotted ellipse outlines can easily be simulated with a series of bezier segments.

• #### Drawing rotated and skewed ellipses

Posted by Legacy on 01/04/2004 12:00am

Originally posted by: Chryssa Sferidou

My target is to draw several continuous Bezier curves by clicking with the mouse points on the screen, not by pre-defining the coordinates of the points in the code - How can I achieve this?
Regards

• #### How to use the code?Any exmaple?

Posted by Legacy on 06/05/2003 12:00am

• #### http://www.ucancode.net

Posted by Legacy on 03/23/2003 12:00am

Originally posted by: Cindy wang

Very cool article,I like it.

• #### How to rotate a total 2D drawing drawn in picture box control with a user defined angle

Posted by Legacy on 03/13/2003 12:00am

Originally posted by: Amit Thite

```How to rotate a total 2D drawing drawn in picture box control with a user defined angle

```

• #### sin() error-- undefined identifier

Posted by Legacy on 12/10/2002 12:00am

Originally posted by: Caroline

while i have included math.h..
why?

• #### z-axis with win GDI ?

Posted by Legacy on 08/10/2002 12:00am

Originally posted by: Jason

How do you rotate or position a polygon in the z-axis
Im trying to build a small software renderer for 3D
using the GDI, Instead of using OpenGL or Direct3D for rendering. -just for fun :)and I need to learn how you can implement 3D with the GDI

• #### How to rotate static control,Edit box control

Posted by Legacy on 07/20/2002 12:00am

Originally posted by: Sachin V. Kulkarni

Please any body tell me how to rottate static text box control,Edit box control or bitmap.

• #### Very Elegant

Posted by Legacy on 05/22/2002 12:00am

Originally posted by: Stan Mlynek

Looks very good and solves a problem with trying to use the windows api ellispe function for W95/98 under extreme conditions

• #### rotation algorithm shrinks ellipse........fixed

Posted by Legacy on 04/11/2002 12:00am

Originally posted by: lis

the rotation algorithm given is great, but it shrinks the ellipse....if you want a better (and simpler) one convert to polar rotate and convert back again.....here is an example....in VB where atan2 is a special function that will compute the tangent in the correct quadrant....

For i = 0 To 12
'first center the circle we want to rotate around....
x(i) = A(i).x - center.x
y(i) = A(i).y - center.y

'then get the polar coordinates
r = Sqr(x(i) ^ 2 + y(i) ^ 2)
theta = Atan2(y(i), x(i))

theta = theta + angle

'then convert back into cartesian
x(i) = r * Cos(theta)
y(i) = r * Sin(theta)

'then move back to center
x(i) = x(i) + center.x
y(i) = y(i) + center.y

'now set a(i) = x, y
A(i).x = x(i)
A(i).y = y(i)
Next

• #### piechart and barchart

Posted by Legacy on 03/25/2002 12:00am

Originally posted by: senthilprakash

```how to draw a piechart and biechart using the mfc sdi environment?
how to pass the parameters of the recordset to graph?
```

• You must have javascript enabled in order to post comments.

## Top White Papers and Webcasts

• Technology has transformed the distribution industry so much that the industry is barely recognizable today. With the new technology options available today, smaller distributors can have the agility, precision, and speed they need to succeed against large competitors with deep pockets. Configure-price-quote (CPQ) software is one of the main technologies helping distributors become more competitive. Read this white paper to learn how an integrated, rules-based CPQ solution can provide an interactive visual …

• With the cloud transforming application development and deployment — enabling organizations to improve flexibility, automate processes, and decrease time to market — some big questions remain. One of the most important issues an organization must address is how it can best employ the smarter tools and limitless scale that the cloud offers. One way that enterprises take advantage of the benefits of the cloud is by deploying their own private cloud. Read this white paper to learn how private clouds …