raw math

Create a circle out of three points

Robert Eisele

A circle is a set of infinite points in two dimensions. However, a circle is clearly described by three of such points. The opposite direction is also correct as long as not all three points are on a straight line.

The question now is, how can we find the center \(C\) and radius \(r\) of a circle, given three points \(P_1, P_2\) and \(P_3\)? Typically, a circle at position \((x', y')\) with radius \(r'\) can be described with the equation

\[(x-x')^2+(y-y')^2=r'^2\]

When multiplied out, we get the following form:

\[\underbrace{1}_{=a} \cdot (x^2 + y^2) + \underbrace{(- 2x')}_{=b}x + \underbrace{( - 2y')}_{=c}y + \underbrace{(x'^2 + y'^2 - r'^2)}_{=d} = 0\]

From which is clear, that we can parametrize a circle in the general way with

\[a(x^2+y^2)+bx+cy+d=0\]

If we now bring the given points \(P_1, P_2\) and \(P_3\) with their points \((x_1, y_1), (x_2, y_2)\) and \( (x_3, y_3)\) in the following set of equations:

\[\left|\begin{array}{cccc} x^2+y^2 & x & y & 1\\ x_1^2+y_1^2 & x_1 & y_1 & 1\\ x_2^2+y_2^2 & x_2 & y_2 & 1\\ x_3^2+y_3^2 & x_3 & y_3 & 1\\ \end{array}\right| = 0\]

it can be shown, that the circle can be parametrized using Laplace expansion as follows:

\[ a = \left|\begin{array}{ccc} x_1 & y_1 & 1\\ x_2 & y_2 & 1\\ x_3 & y_3 & 1\\ \end{array}\right|, b = -\left|\begin{array}{ccc} x_1^2 + y_1^2 & y_1 & 1\\ x_2^2 + y_2^2 & y_2 & 1\\ x_3^2 + y_3^2 & y_3 & 1\\ \end{array}\right|, c = \left|\begin{array}{ccc} x_1^2 + y_1^2 & x_1 & 1\\ x_2^2 + y_2^2 & x_2 & 1\\ x_3^2 + y_3^2 & x_3 & 1\\ \end{array}\right|, d = -\left|\begin{array}{ccc} x_1^2 + y_1^2 & x_1 & y_1\\ x_2^2 + y_2^2 & x_2 & y_2\\ x_3^2 + y_3^2 & x_3 & y_3\\ \end{array}\right|\]

After solving the determinants, we get the following equations:

\[\begin{array}{rl} a =& x_1(y_2-y_3)-y_1(x_2-x_3)+x_2y_3-x_3y_2\\ b =& (x_1^2+y_1^2)(y_3-y_2)+(x_2^2+y_2^2)(y_1-y_3)+(x_3^2+y_3^2)(y_2-y_1)\\ c =& (x_1^2+y_1^2)(x_2-x_3)+(x_2^2+y_2^2)(x_3-x_1)+(x_3^2+y_3^2)(x_1-x_2)\\ d =& (x_1^2+y_1^2)(x_3y_2-x_2y_3)+(x_2^2+y_2^2)(x_1y_3-x_3y_1)+(x_3^2+y_3^2)(x_2y_1-x_1y_2) \end{array}\]

The center \(C\) with its coordinate \((x,y)\) and radius \(r\), calculated by the three points \((x_1, y_1), (x_2, y_2)\) and \((x_3, y_3)\) is now:

\[\begin{array}{rll} x =& \frac{(x_1^2+y_1^2)(y_2-y_3)+(x_2^2+y_2^2)(y_3-y_1)+(x_3^2+y_3^2)(y_1-y_2)}{2(x_1(y_2-y_3)-y_1(x_2-x_3)+x_2y_3-x_3y_2)} &= -\frac{b}{2a}\\ y =& \frac{(x_1^2+y_1^2)(x_3-x_2)+(x_2^2+y_2^2)(x_1-x_3)+(x_3^2+y_3^2)(x_2-x_1)}{2(x_1(y_2-y_3)-y_1(x_2-x_3)+x_2y_3-x_3y_2)} &= -\frac{c}{2a}\\ r =& \sqrt{(x-x_1)^2 + (y-y_1)^2} &= \sqrt{\frac{b^2+c^2-4ad}{4a^2}} \end{array}\]

This top-down attempt works totally fine and can be implemeted straight ahead and is now part of Circle.js.

function circleFromThreePoints(p1, p2, p3) {

  var x1 = p1.x;
  var y1 = p1.y;
  var x2 = p2.x;
  var y2 = p2.y;
  var x3 = p3.x;
  var y3 = p3.y;

  var a = x1 * (y2 - y3) - y1 * (x2 - x3) + x2 * y3 - x3 * y2;

  var b = (x1 * x1 + y1 * y1) * (y3 - y2) 
        + (x2 * x2 + y2 * y2) * (y1 - y3)
        + (x3 * x3 + y3 * y3) * (y2 - y1);
 
  var c = (x1 * x1 + y1 * y1) * (x2 - x3) 
        + (x2 * x2 + y2 * y2) * (x3 - x1) 
        + (x3 * x3 + y3 * y3) * (x1 - x2);
 
  var x = -b / (2 * a);
  var y = -c / (2 * a);

  return {
    x: x,
    y: y,
    r: Math.hypot(x - x1, y - y1)
  };
}

Geometric solution

An alternative way of deriving the solution is this: If we draw a line \(a\) through points \(P_1\) and \(P_2\) and another line \(b\) through points \(P_2\) and \(P_3\), it is obvious that their perpendicular lines crossing them at the middle of the points will meet exactly in the midpoint of the circle. The problem with this approach is, that the slope of the lines is \(m_a = \frac{y_2-y_1}{x_2-x_1}\) and \( m_b = \frac{y_3-y_2}{x_3-x_2}\). Therefore for the lines \(y_a = m_a (x - x_1) + y_1\) and \(y_b=m_b(x-x_2)+y_2\) and their perpendicular counter parts

\[\begin{array}{rl} y_{a'} = -\frac{1}{m_a}\left(x-\frac{x_1+x_2}{2}\right) + \frac{y_1+y_2}{2}\\ y_{b'} = -\frac{1}{m_b}\left(x-\frac{x_2+x_3}{2}\right) + \frac{y_2+y_3}{2}\\ \end{array}\]

we have discontinuities as long as we don't simplify the equation for \(x =\frac{m_am_b(y_1-y_3) + m_b(x_1 + x_2) - m_a(x_2 + x_3)}{2(m_b-m_a)}\), which we got by setting the two equations equal. If we simplify the equations with Wolframalpha, we arrive at the same equations as as with the determinant solution.