def is_parallel(self, line, atol=1e-6): if not isinstance(line, Line): raise unexpected_type_error("line", Line, line) my_normal = self.normal() mirror = -my_normal other_normal = line.normal() return my_normal.approx(other_normal, atol) or mirror.approx(other_normal, atol)
def intersection(self, line): if not isinstance(line, Line): raise unexpected_type_error("line", Line, line) det = self._cx * line._cy - self._cy * line._cx if det == 0: return None return P2( (line._cy * self._c - self._cy * line._c) / det, (self._cx * line._c - line._cx * self._c) / det, )
def does_intersect(self, line_segment): if not isinstance(line_segment, LineSegment): raise unexpected_type_error("line_segment", LineSegment, line_segment) ccw1 = P2.CCW(self._p1, self._p2, line_segment._p1) ccw2 = P2.CCW(self._p1, self._p2, line_segment._p2) if ccw1 * ccw2 > 0: return False ccw1 = P2.CCW(line_segment._p1, line_segment._p2, self._p1) ccw2 = P2.CCW(line_segment._p1, line_segment._p2, self._p2) if ccw1 * ccw2 > 0: return False return True
def contains(self, point, atol=1e-6): if not isinstance(point, P2): raise unexpected_type_error("point", P2, point) if approx(self._p1, point, atol): return True if approx(self._p2, point, atol): return True line_vector = self.vector() test_vector = point - self._p1 if not line_vector.is_parallel(test_vector, atol): return False return 0 <= line_vector.dot(test_vector) <= line_vector.dot(line_vector)
def does_intersect(self, circle): if not isinstance(circle, Circle): raise unexpected_type_error("circle", Circle, circle) if self == circle: raise ValueError("Test circles are identical.") vector = circle.center - self.center magnitude = vector.magnitude() if magnitude > self.radius + circle.radius: return False if magnitude < abs(self.radius - circle.radius): return False return True
def approx(self, other, atol=1e-6): if not isinstance(other, V3): raise unexpected_type_error("other", V3, other) return abs(self - other) <= atol
def dot(self, other): if not isinstance(other, V3): raise unexpected_type_error("other", V3, other) return self.x * other.x + self.y * other.y + self.z * other.z
def cross(self, other): if not isinstance(other, V2): raise unexpected_type_error("other", V2, other) return cross2(self, other)
def dot(self, other): if not isinstance(other, V2): raise unexpected_type_error("other", V2, other) return dot2(self, other)
def approx(self, other, atol=1e-6): if not isinstance(other, P2): raise unexpected_type_error("other", P2, other) return (self - other).magnitude() < atol
def _equation(self, point): if not isinstance(point, P3): raise unexpected_type_error("point", P3, point) return self.cx * point.x + self.cy * point.y + self.cz * point.z