GDI Topics: Circle-Based Shapes

 Ellipses and Circles
 An ellipse is a closed continuous line whose points are positioned so that two points exactly opposite each other have the exact same distant from a point called the center. It can be illustrated as follows:

Because an ellipse can fit in a rectangle, in GDI programming, an ellipse is defined with regards to a rectangle it would fit in. Therefore, to draw an ellipse, you specify its rectangular corners. The syntax used to do this is:

`void __fastcall Ellipse(int X1, int Y1, int X2, int Y2);`

The arguments of this method play the same roll as those of the Rectangle() method:

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { Canvas->Ellipse(20, 20, 226, 144); } //---------------------------------------------------------------------------```

Like the rectangle, you can draw an ellipse using a RECT or TRect object it would fit in. The syntax you would use is:

`void __fastcall Ellipse(TRect Rect);`

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { TRect Recto(328, 125, 28, 8); Canvas->Ellipse(Recto); } //---------------------------------------------------------------------------```

A circle is an ellipse whose all points have the same distance with regards to a central point.

 Round Rectangles and Round Squares

A rectangle qualifies as round if its corners do not form straight angles but rounded corners. It can be illustrated as follows:

To draw such a rectangle, you can use the TCanvas::RoundRect() method. Its syntax is:

`void __fastcall RoundRect(int X1, int Y1, int X2, int Y2, int X3, int Y3);`

When this member function executes, the rectangle is drawn from the (x1, y1) to the (x2, y2) points. The corners are rounded by an ellipse whose width would be x3 and the ellipse's height would be x3.

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { Canvas->RoundRect(20, 20, 275, 188, 42, 38); } //---------------------------------------------------------------------------```

A round square is a square whose corners are rounded.

 Pies

A pie is a fraction of an ellipse delimited by two lines that span from the center of the ellipse to one side each. It can be illustrated as follows:

To draw a pie, you can use the TCanvas::Pie() method whose syntax is:

`void __fastcall Pie(int X1, int Y1, int X2, int Y2, int X3, int Y3, int X4, int Y4);`

The (X1, Y1) point determines the upper-left corner of the rectangle in which the ellipse that represents the pie fits. The (X2, Y2) point is the bottom-right corner of the rectangle.

The (X3, Y3) point specifies the starting corner of the pie in a default counterclockwise direction.

The (X4, Y4) point species the end point of the pie.

To complete the pie, a line is drawn from (X3, Y3) to the center and from the center to the (X4, Y4) points.

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { Canvas->Pie(40, 20, 226, 144, 155, 32, 202, 115); } //---------------------------------------------------------------------------```

 Arcs

An arc is a portion or segment of an ellipse. This means that an arc is a non-complete ellipse. Because an arc must confirm to the shape of an ellipse, it is defined as it fits in a rectangle and can be illustrated as follows:

To draw an arc, you can use the TCanvas::Arc() method whose syntax is:

`void __fastcall Arc(int X1, int Y1, int X2, int Y2, int X3, int Y3, int X4, int Y4);`

Besides the left (X1, Y1) and the right (X2, Y2) borders of the rectangle in which the arc would fit, an arc must specify where it starts and where it ends. The additional points are set as the (X3, Y3) and (X4, Y4) points of the figure. Based on this, the above arc can be illustrated as follows:

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { Canvas->Arc(20, 20, 226, 144, 202, 115, 105, 32); } //---------------------------------------------------------------------------```

Besides the Arc() method, the Win32 library provides the ArcTo() function used to draw an arc. Its syntax is as follows:

```BOOL ArcTo(HDC hdc,
int nLeftRect, int nTopRect, int nRightRect, int nBottomRect,

The hdc argument is a handle to the canvas on which you want to draw.

This method uses the same arguments as Arc(). The difference is that while Arc() starts drawing at (x3, y3), ArcTo() does not inherently control the drawing starting point. It refers to the current point, exactly like the LineTo() (and the PolylineTo(). methods. Therefore, if you want to specify where the drawing should start, you can call TCanvas::MoveTo() before ArcTo(). Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { HDC hDC = Canvas->Handle; TRect Recto(20, 20, 226, 144); TPoint Pt1(202, 115); TPoint Pt2(105, 32); Canvas->MoveTo(207, 155); ArcTo(hDC, Recto.Left, Recto.Top, Recto.Width(), Recto.Height(), Pt1.x, Pt1.y, Pt2.x, Pt2.y); } //---------------------------------------------------------------------------```

 The Arc's Direction

Here is and arc we drew earlier with a call to Arc():

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { Canvas->Arc(20, 20, 226, 144, 202, 115, 105, 32); } //---------------------------------------------------------------------------```

You may wonder why the arc is drawn to the right side of a vertical line that would cross the center of the ellipse instead of the left. This is because the drawing of an arc is performed from right to left or from bottom to up, in the opposite direction of the clock. This is known as the counterclockwise direction. To control this orientation, the Win32 library provides the SetArcDirection() function. Its syntax is:

`int SetArcDirection(HDC hdc, int ArcDirection);`

This function specifies the direction the TCanvas::Arc() method should follow from the starting to the end points. The argument passed as ArcDirection controls this orientation. It can have the following values:

 Value Orientation AD_CLOCKWISE The figure is drawn clockwise AD_COUNTERCLOCKWISE The figure is drawn counterclockwise

The default value of the direction is AD_COUNTERCLOCKWISE. Therefore, this would be used if you do not specify a direction. Here is an example that uses the same values as above with a different orientation:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { HDC hDC = Canvas->Handle; SetArcDirection(hDC, AD_CLOCKWISE); Canvas->Arc(20, 20, 226, 144, 202, 115, 105, 32); Canvas->Arc(20, 20, 226, 144, 202, 115, 105, 32); } //---------------------------------------------------------------------------```

After calling SetArcDirection() and changing the previous direction, all drawings would use the new direction to draw arcs using Arc() or ArcTo() and other figures (such as chords, ellipses, pies, and rectangles). Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { HDC hDC = Canvas->Handle; SetArcDirection(hDC, AD_COUNTERCLOCKWISE); Canvas->Arc(20, 20, 226, 144, 202, 115, 105, 32); Canvas->Arc(10, 10, 250, 155, 240, 85, 24, 48); } //---------------------------------------------------------------------------```

If you want to change the direction, you must call SetArcDirection() with the desired value. Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { HDC hDC = Canvas->Handle; SetArcDirection(hDC, AD_COUNTERCLOCKWISE); Canvas->Arc(20, 20, 226, 144, 202, 115, 105, 32); SetArcDirection(hDC, AD_CLOCKWISE); Canvas->Arc(10, 10, 250, 155, 240, 85, 24, 48); } //---------------------------------------------------------------------------```

At any time, you can find out the current direction used. This is done by calling the GetArcDirection() function. Its syntax is:

`int GetArcDirection(HDC hdc);`

This function returns the current arc direction as AD_CLOCKWISE or AD_COUNTERCLOCKWISE.

 Angular Arcs

You can (also) draw an arc using the AngleArc() function. Its syntax is:

```BOOL AngleArc(HDC hdc, int X, int Y, DWORD dwRadius,
FLOAT eStartAngle, FLOAT eSweepAngle);```

The hdc argument represents a handle to the canvas on which you want to draw. This function draws a line and an arc connected. The arc is based on a circle and not an ellipse. This implies that the arc fits inside a square and not a rectangle. The circle that would be the base of the arc is defined by its center located at C(X, Y) with a radius of dwRadius. The arc starts at an angle of eStartAngle. The angle is based on the x axis and must be positive. That is, it must range from 0° to 360°. If you want to specify an angle that is below the x axis, such as -15°, use 360º-15°=345°. The last argument, eSweepAngle, is the angular area covered by the arc.

The AngleArc() function does not control where it starts drawing. This means that it may start at the origin, unless a previous call to MoveTo() specified the beginning of the drawing.

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { HDC hDC = Canvas->Handle; Canvas->MoveTo(52, 28); AngleArc(hDC, 120, 45, 142, 345, -65); } //---------------------------------------------------------------------------```

 Chords

The arcs we have drawn so far are considered open figures because they are made of a line that has a beginning and an end (unlike a circle or a rectangle that do not). A chord is an arc whose two ends are connected by a straight line. In other words, a chord is an ellipse that is divided by a straight line from one side to another:

To draw a chord, you can use the TCanvas::Chord() method. It is defined as follows:

`void __fastcall Chord(int X1, int Y1, int X2, int Y2, int X3, int Y3, int X4, int Y4);`

The X1, Y1, X2, and Y2 are the coordinates of the rectangle in which the chord of the circle would fit.

The X3 and Y3 coordinates specify where the arc that holds the chord starts.

The X4 and Y4 arguments specify the end of the arc.

To complete the chord, a line is drawn from (X3, Y3) to (X4, Y4).

Here is an example:

 ```//--------------------------------------------------------------------------- void __fastcall TForm1::FormPaint(TObject *Sender) { Canvas->Chord(20, 20, 226, 144, 202, 115, 105, 32); } //---------------------------------------------------------------------------```