def is_point_on_segment(point, segment, tol=1e-6): """Determine if a point lies on a given line segment. Parameters ---------- point : [float, float, float] | :class:`compas.geometry.Point` A point. segment : [point, point] | :class:`compas.geometry.Line` A line segment. tol : float, optional A tolerance for membership verification. Returns ------- bool True if the point is on the line segment. False otherwise. """ a, b = segment d_ab = distance_point_point(a, b) if d_ab == 0: return False if not is_point_on_line(point, (a, b), tol=tol): return False d_pa = distance_point_point(a, point) d_pb = distance_point_point(b, point) if d_pa + d_pb <= d_ab + tol: return True return False
def is_point_on_polyline(point, polyline, tol=1e-6): """Determine if a point is on a polyline. Parameters ---------- point : [float, float, float] | :class:`compas.geometry.Point` A point. polyline : sequence[point] | :class:`compas.geometry.Polyline` A polyline. tol : float, optional The tolerance for membership verification. Returns ------- bool True if the point is on the polyline. False otherwise. """ for i in range(len(polyline) - 1): a = polyline[i] b = polyline[i + 1] c = closest_point_on_segment(point, (a, b)) if distance_point_point(point, c) <= tol: return True return False
def is_point_on_polyline(point, polyline, tol=1e-6): """Determine if a point is on a polyline. Parameters ---------- point : sequence of float XYZ coordinates. polyline : sequence of sequence of float XYZ coordinates of the points of the polyline. tol : float, optional The tolerance for membership verification. Default is ``1e-6``. Returns ------- bool ``True`` if the point is on the polyline. ``False`` otherwise. """ for i in range(len(polyline) - 1): a = polyline[i] b = polyline[i + 1] c = closest_point_on_segment(point, (a, b)) if distance_point_point(point, c) <= tol: return True return False
def is_point_on_polyline(point, polyline, tol=1e-6): """Determine if a point is on a polyline. Parameters ---------- point : [x, y, z] or :class:`compas.geometry.Point` A point. polyline : list of points or :class:`compas.geometry.Polyline` A polyline. tol : float, optional The tolerance for membership verification. Default is ``1e-6``. Returns ------- bool ``True`` if the point is on the polyline. ``False`` otherwise. """ for i in range(len(polyline) - 1): a = polyline[i] b = polyline[i + 1] c = closest_point_on_segment(point, (a, b)) if distance_point_point(point, c) <= tol: return True return False
def is_point_on_segment(point, segment, tol=1e-6): """Determine if a point lies on a given line segment. Parameters ---------- point : sequence of float XYZ coordinates. segment : tuple Two points defining the line segment. tol : float, optional A tolerance for membership verification. Default is ``1e-6``. Returns ------- bool ``True`` if the point is on the line segment. ``False`` otherwise. """ a, b = segment if not is_point_on_line(point, segment, tol=tol): return False d_ab = distance_point_point(a, b) if d_ab == 0: return False d_pa = distance_point_point(a, point) d_pb = distance_point_point(b, point) if d_pa + d_pb <= d_ab + tol: return True return False
def is_point_in_circle(point, circle): """Determine if a point lies in a circle. Parameters ---------- point : [float, float, float] | :class:`compas.geometry.Point` A point. circle : [plane, float] | :class:`compas.geometry.Circle` A circle. Returns ------- bool True if the point lies in the circle. False otherwise. """ plane, radius = circle if is_point_on_plane(point, plane): return distance_point_point(point, plane[0]) <= radius return False
def is_point_in_circle(point, circle): """Determine if a point lies in a circle. Parameters ---------- point : sequence of float XYZ coordinates of a 3D point. circle : tuple center, radius, normal Returns ------- bool ``True`` if the point lies in the circle. ``False`` otherwise. """ plane, radius = circle if is_point_on_plane(point, plane): return distance_point_point(point, plane[0]) <= radius return False
def is_point_in_circle(point, circle): """Determine if a point lies in a circle. Parameters ---------- point : [x, y, z] or :class:`compas.geometry.Point` A point. circle : [point, float, vector] A circle. Returns ------- bool ``True`` if the point lies in the circle. ``False`` otherwise. """ plane, radius = circle if is_point_on_plane(point, plane): return distance_point_point(point, plane[0]) <= radius return False
def intersection_sphere_sphere(sphere1, sphere2): """Computes the intersection of 2 spheres. There are 4 cases of sphere-sphere intersection : 1) the spheres intersect in a circle, 2) they intersect in a point, 3) they overlap, 4) they do not intersect. Parameters ---------- sphere1 : tuple center, radius of the sphere. sphere2 : tuple center, radius of the sphere. Returns ------- case : str `point`, `circle`, or `sphere` result : tuple - point: xyz coordinates - circle: center, radius, normal - sphere: center, radius Examples -------- >>> sphere1 = (3.0, 7.0, 4.0), 10.0 >>> sphere2 = (7.0, 4.0, 0.0), 5.0 >>> result = intersection_sphere_sphere(sphere1, sphere2) >>> if result: ... case, res = result ... if case == "circle": ... center, radius, normal = res ... elif case == "point": ... point = res ... elif case == "sphere": ... center, radius = res References -------- https://gamedev.stackexchange.com/questions/75756/sphere-sphere-intersection-and-circle-sphere-intersection """ center1, radius1 = sphere1 center2, radius2 = sphere2 distance = distance_point_point(center1, center2) # Case 4: No intersection if radius1 + radius2 < distance: return None # Case 4: No intersection, sphere is within the other sphere elif distance + min(radius1, radius2) < max(radius1, radius2): return None # Case 3: sphere's overlap elif radius1 == radius2 and distance == 0: return "sphere", sphere1 # Case 2: point intersection elif radius1 + radius2 == distance: ipt = subtract_vectors(center2, center1) ipt = scale_vector(ipt, radius1/distance) ipt = add_vectors(center1, ipt) return "point", ipt # Case 2: point intersection, smaller sphere is within the bigger elif distance + min(radius1, radius2) == max(radius1, radius2): if radius1 > radius2: ipt = subtract_vectors(center2, center1) ipt = scale_vector(ipt, radius1/distance) ipt = add_vectors(center1, ipt) else: ipt = subtract_vectors(center1, center2) ipt = scale_vector(ipt, radius2/distance) ipt = add_vectors(center2, ipt) return "point", ipt # Case 1: circle intersection h = 0.5 + (radius1**2 - radius2**2)/(2 * distance**2) ci = subtract_vectors(center2, center1) ci = scale_vector(ci, h) ci = add_vectors(center1, ci) ri = sqrt(radius1**2 - h**2 * distance**2) normal = scale_vector(subtract_vectors(center2, center1), 1/distance) return "circle", (ci, ri, normal)