12

Could somebody please show code which would do this quickly? Assume we get three points p1, p2, p3 in left-->right order. Thus, the solution should also check whether or not the circle is valid, ie (p1, p2, p3) are counter-clockwise.

themaestro
  • 13,750
  • 20
  • 56
  • 75

3 Answers3

14

To calculate the circle parameters, have a look at:

http://paulbourke.net/geometry/circlesphere/ Look for "Equation of a Circle from 3 Points (2 dimensions)"

to determine orientation, you can use the polygon area formula:

http://paulbourke.net/geometry/polygonmesh/ Look for "Calculating the area and centroid of a polygon"

Please tell me if you need this in an specific programming language.

Maple
  • 741
  • 13
  • 28
7
  • Connect any two points on the circle and you have a chord.

  • The perpendicular bisector of a chord must pass through the center.

  • The intersection of the bisectors of two chords will be the center.

Remainder (reduction to form for most efficient calculation) is left as an exercise for the reader...

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117
2

Here is a short function (Swift language) with only a single if.

enum Result {
    case circle(center: CGPoint, radius: CGFloat)
    case invalid
}

func circleTouching3Points(a: CGPoint, b: CGPoint, c: CGPoint) -> Result {
    let d1 = CGPoint(x: b.y - a.y, y: a.x - b.x)
    let d2 = CGPoint(x: c.y - a.y, y: a.x - c.x)
    let k: CGFloat = d2.x * d1.y - d2.y * d1.x
    guard k < -0.00001 || k > 0.00001 else {
        return Result.invalid
    }
    let s1 = CGPoint(x: (a.x + b.x) / 2, y: (a.y + b.y) / 2)
    let s2 = CGPoint(x: (a.x + c.x) / 2, y: (a.y + c.y) / 2)
    let l: CGFloat = d1.x * (s2.y - s1.y) - d1.y * (s2.x - s1.x)
    let m: CGFloat = l / k
    let center = CGPoint(x: s2.x + m * d2.x, y: s2.y + m * d2.y)
    let dx = center.x - a.x
    let dy = center.y - a.y
    let radius = sqrt(dx * dx + dy * dy)
    return Result.circle(center: center, radius: radius)
}
neoneye
  • 50,398
  • 25
  • 166
  • 151