What is the algorithm for finding the center of a circle from three points?
Here's my Java port, dodging the error condition when the determinant disappears with a very elegant IllegalArgumentException
, my approach to coping with the "points are two far apart" or "points lie on a line" conditions. Also, this computes the radius (and copes with exceptional conditions) which your intersecting-slopes approach will not do.
public class CircleThree
{
static final double TOL = 0.0000001;
public static Circle circleFromPoints(final Point p1, final Point p2, final Point p3)
{
final double offset = Math.pow(p2.x,2) + Math.pow(p2.y,2);
final double bc = ( Math.pow(p1.x,2) + Math.pow(p1.y,2) - offset )/2.0;
final double cd = (offset - Math.pow(p3.x, 2) - Math.pow(p3.y, 2))/2.0;
final double det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x)* (p1.y - p2.y);
if (Math.abs(det) < TOL) { throw new IllegalArgumentException("Yeah, lazy."); }
final double idet = 1/det;
final double centerx = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet;
final double centery = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet;
final double radius =
Math.sqrt( Math.pow(p2.x - centerx,2) + Math.pow(p2.y-centery,2));
return new Circle(new Point(centerx,centery),radius);
}
static class Circle
{
final Point center;
final double radius;
public Circle(Point center, double radius)
{
this.center = center; this.radius = radius;
}
@Override
public String toString()
{
return new StringBuilder().append("Center= ").append(center).append(", r=").append(radius).toString();
}
}
static class Point
{
final double x,y;
public Point(double x, double y)
{
this.x = x; this.y = y;
}
@Override
public String toString()
{
return "("+x+","+y+")";
}
}
public static void main(String[] args)
{
Point p1 = new Point(0.0,1.0);
Point p2 = new Point(1.0,0.0);
Point p3 = new Point(2.0,1.0);
Circle c = circleFromPoints(p1, p2, p3);
System.out.println(c);
}
}
See algorithm from The Math Forum:
void circle_vvv(circle *c)
{
c->center.w = 1.0;
vertex *v1 = (vertex *)c->c.p1;
vertex *v2 = (vertex *)c->c.p2;
vertex *v3 = (vertex *)c->c.p3;
float bx = v1->xw; float by = v1->yw;
float cx = v2->xw; float cy = v2->yw;
float dx = v3->xw; float dy = v3->yw;
float temp = cx*cx+cy*cy;
float bc = (bx*bx + by*by - temp)/2.0;
float cd = (temp - dx*dx - dy*dy)/2.0;
float det = (bx-cx)*(cy-dy)-(cx-dx)*(by-cy);
if (fabs(det) < 1.0e-6) {
c->center.xw = c->center.yw = 1.0;
c->center.w = 0.0;
c->v1 = *v1;
c->v2 = *v2;
c->v3 = *v3;
return;
}
det = 1/det;
c->center.xw = (bc*(cy-dy)-cd*(by-cy))*det;
c->center.yw = ((bx-cx)*cd-(cx-dx)*bc)*det;
cx = c->center.xw; cy = c->center.yw;
c->radius = sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by));
}
It can be a rather in depth calculation. There is a simple step-by-step here: http://paulbourke.net/geometry/circlesphere/. Once you have the equation of the circle, you can simply put it in a form involving H and K. The point (h,k) will be the center.
(scroll down a little ways at the link to get to the equations)