""" circle_intersection.py Authors: Tiffany Lin, Presha Goel, Peter Mawhorter Functions for finding intersection points of circles. """ import math from typing import Tuple, TypeAlias, Union Number: 'TypeAlias' = Union[int, float] def distance(a: Tuple[Number, Number], b: Tuple[Number, Number]) -> float: """ Calculates the distance between two points, using the distance formula in 2 dimensions. For example: >>> distance((0, 0), (0, 3)) 3.0 >>> distance((0, 0), (3, 0)) 3.0 >>> distance((0, 0), (3, 4)) 5.0 """ x1, y1 = a x2, y2 = b return (((x2 - x1) ** 2) + ((y2 - y1) ** 2)) ** 0.5 def isATriangle(x: Number, y: Number, z: Number) -> bool: """ Checks whether three side lengths can form a triangle. For example: >>> isATriangle(3, 4, 5) True >>> isATriangle(1, 1, 1) True >>> isATriangle(100, 99, 1) True >>> isATriangle(1, 100, 99) True >>> isATriangle(99, 1, 100) True >>> isATriangle(3, 2, 10) False >>> isATriangle(5, 1, 1) False >>> isATriangle(9, 18.01, 9) False """ return ((x + y > z) and (y + z > x) and (z + x > y)) def circleIntersection(a, b, a_radius, b_radius): """ Calculates the intersection(s) between two circles. """ x1, y1 = a x2, y2 = b r1 = a_radius r2 = b_radius d = distance(a,b) if d > r1 + r2: return [] elif d < abs(r1 - r2): return bestFitIntersection(a, b, a_radius, b_radius) a = (r1**2 - r2**2 + d**2) / (2 * d) h = math.sqrt(r1**2 - a**2) x0 = x1 + a * (x2 - x1) / d y0 = y1 + a * (y2 - y1) / d x3 = x0 + h * (y2 - y1) / d y3 = y0 - h * (x2 - x1) / d x4 = x0 - h * (y2 - y1) / d y4 = y0 + h * (x2 - x1) / d return [(x3, y3), (x4, y4)] #ab_distance = distance(a,b) #bc_distance = distance(a,b) #ca_disatnce = distance(a,b) #The function below calculates the midpoint from a set of two tuples (coordinates). def mid(a): x1, y1 = a[0] x2, y2 = a[1] return((x1+x2)/2 ,(y1+y2)/2) #The function below find the best fit intersection given two circles def bestFitIntersection(a,b,a_rad,b_rad): d = b-a dist_centers = distance(a,b) x = a + (d / dist_centers) * a_rad y = b - (d / dist_centers) * b_rad #The function below finds the closest point, in situations where one circle encapsulates the other def closest_points_encapsulated_circles(center1, radius1, center2, radius2): # Assume center1 and radius1 are for the larger circle, center2 and radius2 for the smaller circle d = center2 - center1 # Vector from the larger circle center to the smaller circle center # Distance between centers dist_centers = (d[0]**2 + d[1]**2)**0.5 # Normalize the direction vector direction = d / dist_centers # Closest point on the boundary of the larger circle (moving toward the smaller circle center) point_on_large_circle = center1 + direction * radius1 # Closest point on the boundary of the smaller circle (moving away from the larger circle center) point_on_small_circle = center2 - direction * radius2 return point_on_large_circle, point_on_small_circle #The function below is our main where we are first testing whether or not we have a triangle, and then calculating the circle intersections and then the midpoint. def main(a,b,c, a_radius, b_radius, c_radius): #rename if isATriangle(distance(a,b),distance(c,b),distance(a,c)) == False: return ("Not a Triangle") x1,y1 = mid(circleIntersection(a, b, a_radius, b_radius)) x2,y2 = mid(circleIntersection(c, b, c_radius, b_radius)) x3,y3 = mid(circleIntersection(a, c, a_radius, c_radius)) return ((round((x1+x2+x3)/3)), (round((y1+y2+y3)/3))) print(circleIntersection((0,0),(100,0),60,70)) print(circleIntersection((0,0),(50,87),60,78)) print(circleIntersection((100,0),(50,87),70,78)) print(main((0,0),(100, 0),(50,87),60,70,78))