""" Created on Sat Apr 8th 2017 Circle Intersection @PythonVer: Tested in 2.7.10 and 3.6 @Author: Matt Woodhead A note on angle convention: +y | / | / | / +ve Theta | / ) ±180 degrees -x ----------------- +ve x 0 degrees | \ ) | \ -ve Theta | \ | \ -y The outputs are ordered from the angle of the lines drawn from the intersection points to the centre of the first circle, from +180 degrees to -180 degrees. """ import math PRECISION = 5 # Decimal point precision class Circle(object): """ An OOP implementation of a circle as an object """ def __init__(self, xposition, yposition, radius): self.xpos = xposition self.ypos = yposition self.radius = radius def circle_intersect(self, circle2): """ Intersection points of two circles using the construction of triangles as proposed by Paul Bourke, 1997. http://paulbourke.net/geometry/circlesphere/ """ X1, Y1 = self.xpos, self.ypos X2, Y2 = circle2.xpos, circle2.ypos R1, R2 = self.radius, circle2.radius Dx = X2-X1 Dy = Y2-Y1 D = round(math.sqrt(Dx**2 + Dy**2), PRECISION) # Distance between circle centres if D > R1 + R2: return "The circles do not intersect" elif D < math.fabs(R2 - R1): return "No Intersect - One circle is contained within the other" elif D == 0 and R1 == R2: return "No Intersect - The circles are equal and coincident" else: if D == R1 + R2 or D == R1 - R2: CASE = "The circles intersect at a single point" else: CASE = "The circles intersect at two points" chorddistance = (R1**2 - R2**2 + D**2)/(2*D) # distance from 1st circle's centre to the chord between intersects halfchordlength = math.sqrt(R1**2 - chorddistance**2) chordmidpointx = X1 + (chorddistance*Dx)/D chordmidpointy = Y1 + (chorddistance*Dy)/D I1 = (round(chordmidpointx + (halfchordlength*Dy)/D, PRECISION), round(chordmidpointy - (halfchordlength*Dx)/D, PRECISION)) theta1 = round(math.degrees(math.atan2(I1[1]-Y1, I1[0]-X1)), PRECISION) I2 = (round(chordmidpointx - (halfchordlength*Dy)/D, PRECISION), round(chordmidpointy + (halfchordlength*Dx)/D, PRECISION)) theta2 = round(math.degrees(math.atan2(I2[1]-Y1, I2[0]-X1)), PRECISION) if theta2 > theta1: I1, I2 = I2, I1 return (I1, I2, CASE) # Main program: C1 = Circle(0, 0, 350) C2 = Circle(-130, 120, 250) print(C1.circle_intersect(C2))