Answered by:
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.
Please any one who has idea or suggestion please guide me.
Thanks
Bye
Regards Rajat.
Rajat Solanki makes I M P.Friday, April 10, 2009 8:03 AM
Answers

This is Pascal code from a CAD program I wrote several lifetimes 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 := (y2y1)*(x3x1)  (y3y1)*(x2x1);
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+(x3x1)*(x3x2)/(y3y1))/2;
p1.ccur := arcseg;
end
else
begin {Normal case}
cx := (y2y1)*(y3*y3+x3*x3)+(y3y2)*(y1*y1+x1*x1)+(y1y3)*(y2*y2+x2*x2);
cy := (x1x2)*(y3*y3+x3*x3)+(x2x3)*(y1*y1+x1*x1)+(x3x1)*(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 (cxx1) + sqr (cyy1));
end;
if (p1.radius < MAXRADIUS) and (p1.ccur = arcseg) then
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 := ((y2y1)*x3+y1*x2y2*x1)/(x2x1);
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 ZhiXin Ye 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 ZhiXin Ye 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) g.DrawEllipse(Pens.Black, center.X  radius, center.Y  radius, 2 * radius, 2 * radius) 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 ZhiXin Ye 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 click
float y = ..;// y point where use click
float circleSize = 10;// required circle size graphics.DrawEllipse(new Pen(Brushes.DeepSkyBlue), x, y, circleSize, circleSize);
RegardsFriday, 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); }
RegardsFriday, 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 rubberband 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?
Please guide me.
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 lifetimes 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 := (y2y1)*(x3x1)  (y3y1)*(x2x1);
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+(x3x1)*(x3x2)/(y3y1))/2;
p1.ccur := arcseg;
end
else
begin {Normal case}
cx := (y2y1)*(y3*y3+x3*x3)+(y3y2)*(y1*y1+x1*x1)+(y1y3)*(y2*y2+x2*x2);
cy := (x1x2)*(y3*y3+x3*x3)+(x2x3)*(y1*y1+x1*x1)+(x3x1)*(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 (cxx1) + sqr (cyy1));
end;
if (p1.radius < MAXRADIUS) and (p1.ccur = arcseg) then
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 := ((y2y1)*x3+y1*x2y2*x1)/(x2x1);
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 ZhiXin Ye 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 ZhiXin Ye 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) g.DrawEllipse(Pens.Black, center.X  radius, center.Y  radius, 2 * radius, 2 * radius) 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 ZhiXin Ye Thursday, April 16, 2009 9:31 AM
Monday, April 13, 2009 1:04 PM 
Oh yes and actually, there is always only one circle that fits three points, I don't know what gave nobugz the idea that there could be multiple. (Or perhaps you have some picture that would explain this? I hope I'm not forgetting some special case...)Monday, April 13, 2009 1:07 PM

Yes, my mistake. There are two when you've got two points and a radius.
Hans Passant.Monday, April 13, 2009 1:10 PM