Draw a Circle in vb.net or c#.net?

• Question

• Hi All Respected,
I am doing a graphical work, I have a bitmap which is plain canvas, user will choose three desire point and the application will draw a circle if will possible between the three point.
1) vb or c#.net according my search, don't have any circle method except ellips....
2) how will i draw circle between those three point?
3) any api which i will call with P/Invoke approach.
Thanks
Bye
Regards Rajat.
Rajat Solanki makes I M P.
Friday, April 10, 2009 8:03 AM

• This is Pascal code from a CAD program I wrote several life-times ago.  You should have no trouble translating the algorithm:

procedure fit3 (var p1, p2, p3 : dpoint);
{Fits a circlular arc through points <p1, p2 and p3>. Data is stored in
record <p1>}
var x1, x2, x3, y1, y2, y3, cx, cy, y, d : real;
rotcw : boolean;

begin
x1 := p1.co.x; x2 := p2.co.x; x3 := p3.co.x;
y1 := p1.co.y; y2 := p2.co.y; y3 := p3.co.y;
d  := (y2-y1)*(x3-x1) - (y3-y1)*(x2-x1);
if d = 0 then           {Straight line}
begin
p1.ccur := line;
end
else if y1 = y2 then    {Special case}
begin
cx := (x1+x2)/2;
cy := (y3+y1+(x3-x1)*(x3-x2)/(y3-y1))/2;
p1.ccur := arcseg;
end
else
begin                 {Normal case}
cx := (y2-y1)*(y3*y3+x3*x3)+(y3-y2)*(y1*y1+x1*x1)+(y1-y3)*(y2*y2+x2*x2);
cy := (x1-x2)*(y3*y3+x3*x3)+(x2-x3)*(y1*y1+x1*x1)+(x3-x1)*(y2*y2+x2*x2);
cx := cx / 2.0 / d;
cy := cy / 2.0 / d;
p1.ccur := arcseg;
end;

if p1.ccur = arcseg then
begin
p1.center.x := cx;
p1.center.y := cy;
p1.radius   := sqrt (sqr (cx-x1) + sqr (cy-y1));
end;
begin
{Compute rotation direction}
rotcw := true;
if x1 = x2 then
begin
if y2 < y1 then rotcw := false;
if x3 < x1 then rotcw := not rotcw;
end
else
begin
y := ((y2-y1)*x3+y1*x2-y2*x1)/(x2-x1);
if x2 < x1 then rotcw := false;
if y3 > y  then rotcw := not rotcw;
end;
if rotcw then p1.dir := CW else p1.dir := CCW;

{Compute starting and ending tangents}
p1.sang := comparctang (p1, p1.co);
p1.eang := comparctang (p1, p2.co);
end
else
begin
p1.ccur := line;
p1.sang := complinetang (p1.co, p2.co);
p1.eang := p1.sang;
end;
end;

Hans Passant.
• Marked as answer by Thursday, April 16, 2009 9:31 AM
Saturday, April 11, 2009 3:57 PM
• I needed something to do also.  This uses gaussian elimination of a N X N matrix to fit three points to a circle.  The points are supplied in a point array and the bounding rectangle of the circle is returned.

```Private Function GetCircleRectFromPoints(ByVal Pts() As Point) As RectangleF
'(X - Cx)^2 + (Y - Cy)^2 = R^2
'(R^2 - Cx^2 - Cy^2) + 2X*Cx + 2Y*Cy = X^2 +  Y^2
'Cr + A*X + B*Y = X^2 + Y^2
'Solve matrix using gaussian elimination.
Dim N As Integer = Pts.Length - 1
Dim X(N, N) As Double, Y(N) As Double
For I As Integer = 0 To N
X(I, 0) = 1 : X(I, 1) = Pts(I).X : X(I, 2) = Pts(I).Y
Y(I) = X(I, 1) * X(I, 1) + X(I, 2) * X(I, 2)
Next
Dim MatInv As New Elimination
MatInv.ComputeCoefficents(X, Y)
Dim A As Single = CSng(Y(1) / 2)
Dim B As Single = CSng(Y(2) / 2)
Dim R As Single = CSng(Math.Sqrt(Y(0) + A * A + B * B))
Return New RectangleF(A - R, B - R, 2 * R, 2 * R)
End Function

Public Class Elimination
Sub ComputeCoefficents(ByVal X(,) As Double, ByVal Y() As Double)
Dim I, J, K, K1, N As Integer
N = Y.Length
For K = 0 To N - 1
K1 = K + 1
For I = K To N - 1
If X(I, K) <> 0 Then
For J = K1 To N - 1
X(I, J) /= X(I, K)
Next J
Y(I) /= X(I, K)
End If
Next I
For I = K1 To N - 1
If X(I, K) <> 0 Then
For J = K1 To N - 1
X(I, J) -= X(K, J)
Next J
Y(I) -= Y(K)
End If
Next I
Next K
For I = N - 2 To 0 Step -1
For J = N - 1 To I + 1 Step -1
Y(I) -= X(I, J) * Y(J)
Next J
Next I
End Sub
End Class
```
• Marked as answer by Thursday, April 16, 2009 9:31 AM
Saturday, April 11, 2009 8:15 PM
• So anyway if you're for some reason not happy with nobugz' or JohnWein's solution, you can find the math for calculating the coordinates of the circumcenter here:

http://en.wikipedia.org/wiki/Circumcircle#Cartesian_coordinates

(Ax, Ay, Bx, By, Cx, Cy are the coordinates of your three points, D is just a temporary variable and the formulas give you x and y coordinates of the center of the circle you're looking for.) I would recommend translating point A to the origin of the coordinate system just like the article suggests. This simplifies the formula a lot. You'll also need the radius of the circle but this is easy to find, you only need to calculate the distance of the center to any of the three points. Keep in mind than if D = 0, the points are collinear and therefore there is no circle going through all of them. (Unless you consider straight line a special case of circle with infinite radius.) Here's an implementation I came up with:
```    Private Sub DrawCircle(ByVal a As PointF, ByVal b As PointF, ByVal c As PointF, ByVal g As Graphics)
g.TranslateTransform(a.X, a.Y)
b.X -= a.X
b.Y -= a.Y
c.X -= a.X
c.Y -= a.Y
a.X = 0
a.Y = 0
Dim d As Single = 2 * (b.X * c.Y - b.Y * c.X)
If d = 0 Then
' Points a, b, c are collinear
g.DrawLine(Pens.Black, a.X, a.Y, b.X, b.Y)
g.DrawLine(Pens.Black, b.X, b.Y, c.X, c.Y)
g.DrawLine(Pens.Black, c.X, c.Y, a.X, a.Y)
Else
Dim center As New PointF((c.Y * (b.X * b.X + b.Y * b.Y) - b.Y * (c.X * c.X + c.Y * c.Y)) / d, (b.X * (c.X * c.X + c.Y * c.Y) - c.X * (b.X * b.X + b.Y * b.Y)) / d)
Dim radius As Single = CSng(Math.Sqrt(center.X * center.X + center.Y * center.Y))
g.FillEllipse(Brushes.Blue, center.X - 2, center.Y - 2, 4, 4)
End If
g.FillEllipse(Brushes.Red, a.X - 2, a.Y - 2, 4, 4)
g.FillEllipse(Brushes.Red, b.X - 2, b.Y - 2, 4, 4)
g.FillEllipse(Brushes.Red, c.X - 2, c.Y - 2, 4, 4)
g.ResetTransform()
End Sub```
• Marked as answer by Thursday, April 16, 2009 9:31 AM
Monday, April 13, 2009 1:04 PM

All replies

• By drawing circle is kind of ellips... just set same width and height parameters and you got circle. Like:

```Graphics graphics = this.CreateGraphics();

float x = ..;// x point where use clickfloat y = ..;// y point where use clickfloat circleSize = 10;// required circle size

graphics.DrawEllipse(new Pen(Brushes.DeepSkyBlue), x, y, circleSize, circleSize);

```

Regards
Friday, April 10, 2009 8:19 AM
• One more example - to draw circle when user click on form you could use the following code:

```public Form1()
{
InitializeComponent();

this.Click += new EventHandler(Form1_Click);
}

void Form1_Click(object sender, EventArgs e)
{
MouseEventArgs clickArgs = (MouseEventArgs)e;
Graphics graphics = this.CreateGraphics();

this.Refresh();

float circlesize = 20;

float x = clickArgs.X - circlesize / 2;
float y = clickArgs.Y - circlesize / 2;

graphics.DrawEllipse(new Pen(Brushes.DeepSkyBlue), x, y, circlesize, circlesize);
}```

Regards
Friday, April 10, 2009 8:41 AM
• You'll have to do the math to compute the extends of the circle.  Beware that two circles fit 3 points, a small one and a large one.  Also beware that it is quite unpredictable to the user what circle she'll get.  CAD programs typically let you pick two points, then show a rubber-band circle (moves with the mouse) to give a preview of the final circle.
Hans Passant.
Friday, April 10, 2009 9:06 AM
• Hi All,
Thanks for all to reply soon, but I have tried Ellisp.
Actually Ellips first draw a rectangle, than draw a circle in the rectangle.
but I want to draw to use of the three points in boundary of circle.
may it possible to draw it?
Thanks
Bye
Regards Rajat
Rajat Solanki makes I M P.
Friday, April 10, 2009 11:20 AM
• Solve the three equations containing (X0,Y0), (X1,Y1) and (X2,Y2) for the circle's center and radius and supply the rectangles described to DrawEllipse.  Good homework.
Friday, April 10, 2009 11:37 AM
• Hi John Wein,
Thanks for good work, but I am not expert as well as you, tell me how can solve it all, till draw a circle.
I am waiting.
Thanks
Bye
Rajat
Rajat Solanki makes I M P.
Friday, April 10, 2009 1:43 PM
• The equation  of a circle is:

(X - Xc)*2 + (Y - Yc)*2 = R*2

When you substitute your three points for X and Y, you'll have three equations which can be solved for Xc, Yc and R.  From these points, you can compute the bounding rectangle for the DrawEllipse method.
Friday, April 10, 2009 2:46 PM
• This is Pascal code from a CAD program I wrote several life-times ago.  You should have no trouble translating the algorithm:

procedure fit3 (var p1, p2, p3 : dpoint);
{Fits a circlular arc through points <p1, p2 and p3>. Data is stored in
record <p1>}
var x1, x2, x3, y1, y2, y3, cx, cy, y, d : real;
rotcw : boolean;

begin
x1 := p1.co.x; x2 := p2.co.x; x3 := p3.co.x;
y1 := p1.co.y; y2 := p2.co.y; y3 := p3.co.y;
d  := (y2-y1)*(x3-x1) - (y3-y1)*(x2-x1);
if d = 0 then           {Straight line}
begin
p1.ccur := line;
end
else if y1 = y2 then    {Special case}
begin
cx := (x1+x2)/2;
cy := (y3+y1+(x3-x1)*(x3-x2)/(y3-y1))/2;
p1.ccur := arcseg;
end
else
begin                 {Normal case}
cx := (y2-y1)*(y3*y3+x3*x3)+(y3-y2)*(y1*y1+x1*x1)+(y1-y3)*(y2*y2+x2*x2);
cy := (x1-x2)*(y3*y3+x3*x3)+(x2-x3)*(y1*y1+x1*x1)+(x3-x1)*(y2*y2+x2*x2);
cx := cx / 2.0 / d;
cy := cy / 2.0 / d;
p1.ccur := arcseg;
end;

if p1.ccur = arcseg then
begin
p1.center.x := cx;
p1.center.y := cy;
p1.radius   := sqrt (sqr (cx-x1) + sqr (cy-y1));
end;
begin
{Compute rotation direction}
rotcw := true;
if x1 = x2 then
begin
if y2 < y1 then rotcw := false;
if x3 < x1 then rotcw := not rotcw;
end
else
begin
y := ((y2-y1)*x3+y1*x2-y2*x1)/(x2-x1);
if x2 < x1 then rotcw := false;
if y3 > y  then rotcw := not rotcw;
end;
if rotcw then p1.dir := CW else p1.dir := CCW;

{Compute starting and ending tangents}
p1.sang := comparctang (p1, p1.co);
p1.eang := comparctang (p1, p2.co);
end
else
begin
p1.ccur := line;
p1.sang := complinetang (p1.co, p2.co);
p1.eang := p1.sang;
end;
end;

Hans Passant.
• Marked as answer by Thursday, April 16, 2009 9:31 AM
Saturday, April 11, 2009 3:57 PM
• I needed something to do also.  This uses gaussian elimination of a N X N matrix to fit three points to a circle.  The points are supplied in a point array and the bounding rectangle of the circle is returned.

```Private Function GetCircleRectFromPoints(ByVal Pts() As Point) As RectangleF
'(X - Cx)^2 + (Y - Cy)^2 = R^2
'(R^2 - Cx^2 - Cy^2) + 2X*Cx + 2Y*Cy = X^2 +  Y^2
'Cr + A*X + B*Y = X^2 + Y^2
'Solve matrix using gaussian elimination.
Dim N As Integer = Pts.Length - 1
Dim X(N, N) As Double, Y(N) As Double
For I As Integer = 0 To N
X(I, 0) = 1 : X(I, 1) = Pts(I).X : X(I, 2) = Pts(I).Y
Y(I) = X(I, 1) * X(I, 1) + X(I, 2) * X(I, 2)
Next
Dim MatInv As New Elimination
MatInv.ComputeCoefficents(X, Y)
Dim A As Single = CSng(Y(1) / 2)
Dim B As Single = CSng(Y(2) / 2)
Dim R As Single = CSng(Math.Sqrt(Y(0) + A * A + B * B))
Return New RectangleF(A - R, B - R, 2 * R, 2 * R)
End Function

Public Class Elimination
Sub ComputeCoefficents(ByVal X(,) As Double, ByVal Y() As Double)
Dim I, J, K, K1, N As Integer
N = Y.Length
For K = 0 To N - 1
K1 = K + 1
For I = K To N - 1
If X(I, K) <> 0 Then
For J = K1 To N - 1
X(I, J) /= X(I, K)
Next J
Y(I) /= X(I, K)
End If
Next I
For I = K1 To N - 1
If X(I, K) <> 0 Then
For J = K1 To N - 1
X(I, J) -= X(K, J)
Next J
Y(I) -= Y(K)
End If
Next I
Next K
For I = N - 2 To 0 Step -1
For J = N - 1 To I + 1 Step -1
Y(I) -= X(I, J) * Y(J)
Next J
Next I
End Sub
End Class
```
• Marked as answer by Thursday, April 16, 2009 9:31 AM
Saturday, April 11, 2009 8:15 PM
• So anyway if you're for some reason not happy with nobugz' or JohnWein's solution, you can find the math for calculating the coordinates of the circumcenter here:

http://en.wikipedia.org/wiki/Circumcircle#Cartesian_coordinates

(Ax, Ay, Bx, By, Cx, Cy are the coordinates of your three points, D is just a temporary variable and the formulas give you x and y coordinates of the center of the circle you're looking for.) I would recommend translating point A to the origin of the coordinate system just like the article suggests. This simplifies the formula a lot. You'll also need the radius of the circle but this is easy to find, you only need to calculate the distance of the center to any of the three points. Keep in mind than if D = 0, the points are collinear and therefore there is no circle going through all of them. (Unless you consider straight line a special case of circle with infinite radius.) Here's an implementation I came up with:
```    Private Sub DrawCircle(ByVal a As PointF, ByVal b As PointF, ByVal c As PointF, ByVal g As Graphics)
g.TranslateTransform(a.X, a.Y)
b.X -= a.X
b.Y -= a.Y
c.X -= a.X
c.Y -= a.Y
a.X = 0
a.Y = 0
Dim d As Single = 2 * (b.X * c.Y - b.Y * c.X)
If d = 0 Then
' Points a, b, c are collinear
g.DrawLine(Pens.Black, a.X, a.Y, b.X, b.Y)
g.DrawLine(Pens.Black, b.X, b.Y, c.X, c.Y)
g.DrawLine(Pens.Black, c.X, c.Y, a.X, a.Y)
Else
Dim center As New PointF((c.Y * (b.X * b.X + b.Y * b.Y) - b.Y * (c.X * c.X + c.Y * c.Y)) / d, (b.X * (c.X * c.X + c.Y * c.Y) - c.X * (b.X * b.X + b.Y * b.Y)) / d)
Dim radius As Single = CSng(Math.Sqrt(center.X * center.X + center.Y * center.Y))
g.FillEllipse(Brushes.Blue, center.X - 2, center.Y - 2, 4, 4)