def check_ray_circle_intersection(p1: Coordinates, p2: Coordinates, c_mid: Coordinates, c_radius: float): """ Check whether a ray intersects a circle. :param p1: starting point of ray :param p2: end point of ray :param c_mid: coordinates for the center of the circle :param c_radius: radius of the circle :return: True if intersection; False otherwise """ # Source: https://stackoverflow.com/a/1084899 # d is direction vector of ray, from start to end # f is direction Vector from center sphere to ray start d = Vector(p2.y - p1.y, p2.x - p1.x) f = Vector(p1.y - c_mid.y, p1.x - c_mid.x) a = d.dot_product(d) b = 2 * f.dot_product(d) c = f.dot_product(f) - c_radius**2 discriminant = b * b - 4 * a * c if discriminant < 0: return False else: discriminant = np.sqrt(discriminant) t1 = (-b - discriminant) / (2 * a) t2 = (-b + discriminant) / (2 * a) return (0 <= t1 <= 1) or (0 <= t2 <= 1)
def get_point_on_line_distance_from_point(line_start, line_end, point, distance) -> Coordinates: a_side = distance c_side = get_distance(line_start, point) v_point = Vector(point.x - line_start.x, point.y - line_start.y) v_line = Vector(line_end.x - line_start.x, line_end.y - line_start.y) dot = v_point.dot_product(v_line) a_angle = np.arccos(dot / v_point.get_magnitude() / v_line.get_magnitude()) from physics.trianglesolver import solve (a_side, b_side, c_side, a_angle, b_angle, c_angle) = solve(a=a_side, c=c_side, A=a_angle, ssa_flag='obtuse') assert a_angle + b_angle + c_angle == np.radians( 180), 'a_angle: {} \nb_angle: {}\nc_angle: {}\n'.format( a_angle, b_angle, c_angle) # Compute exact point angle = np.radians(get_angle(line_end, line_start)) x = line_start.x + b_side * np.cos(angle) y = line_start.y + b_side * np.sin(angle) return Coordinates(x, y)