Source code for petrify.plane.line

from .util import _intersect_line2_line2, _intersect_line2_circle, _connect_circle_line2, _connect_point2_line2

from .planar import Planar
from .point import Point, Point2, Vector, Vector2
from ..geometry import Geometry, tau, valid_scalar

[docs]class Line2(Geometry, Planar): """ Represents an infinite line: >>> Line(Point(0, 0), Vector(1, 1)) Line(Point(0, 0), Vector(1, 1)) >>> Line(Point(0, 0), Point(1, 1)) Line(Point(0, 0), Vector(1, 1)) Implements many built-in methods: >>> Line(Point(1, 1), Point(2, 1)) + Vector(1, 1) Line(Point(2, 2), Vector(1, 0)) """ __slots__ = ['p', 'v'] def __init__(self, *args): if len(args) == 3: assert isinstance(args[0], Point2) and \ isinstance(args[1], Vector2) and \ valid_scalar(args[2]) self.p = args[0].copy() self.v = args[1] * args[2] / abs(args[1]) elif len(args) == 2: if isinstance(args[0], Point2) and isinstance(args[1], Point2): self.p = args[0].copy() self.v = args[1] - args[0] elif isinstance(args[0], Point2) and isinstance(args[1], Vector2): self.p = args[0].copy() self.v = args[1].copy() else: raise AttributeError('%r' % (args,)) elif len(args) == 1: if isinstance(args[0], Line2): self.p = args[0].p.copy() self.v = args[0].v.copy() else: raise AttributeError('%r' % (args,)) else: raise AttributeError('%r' % (args,)) if not self.v: raise AttributeError('Line has zero-length vector') def __add__(self, v): return self.__class__(self.p + v, self.v) def __mul__(self, v): return self.__class__(self.p * v, self.v * v) __rmul__ = __mul__ def __neg__(self): return self.__class__(self.p2, self.p1) def __hash__(self): return hash((self.p, self.v)) def __eq__(self, other): return self.p == other.p and self.v == other.v def __copy__(self): return self.__class__(self.p, self.v) copy = __copy__ def __repr__(self): return 'Line({0!r}, {1!r})'.format(self.p, self.v) p1 = property(lambda self: self.p) p2 = property(lambda self: Point2(self.p.x + self.v.x, self.p.y + self.v.y)) def _apply_transform(self, t): self.p = t * self.p self.v = t * self.v def _u_in(self, u): return True
[docs] def normalized(self): """ Normalizes this line: >>> Line(Point(0, 0), Point(2, 0)).normalized() Line(Point(0, 0), Vector(1.0, 0.0)) """ return self.__class__(self.p, self.v.normalized())
[docs] def intersect(self, other): """ Finds the intersection of this object and another: >>> l = Line(Point(0, 2), Vector(0, -2)) >>> l.intersect(Line(Point(2, 0), Vector(-2, 0))) Point(0.0, 0.0) >>> l.intersect(Line(Point(1, 2), Vector(0, -2))) is None True >>> from petrify.plane import Circle >>> l.intersect(Circle(Point(0, 0), 1)) LineSegment(Point(0.0, -1.0), Point(0.0, 1.0)) """ return other._intersect_line2(self)
def _intersect_line2(self, other): return _intersect_line2_line2(self, other) def _intersect_circle(self, other): return _intersect_line2_circle(self, other)
[docs] def connect(self, other): """ Finds the closest connecting line segment between this object and another: >>> l = Line(Point(0, 2), Vector(0, -2)) >>> l.connect(Point(1, 0)) LineSegment(Point(0.0, 0.0), Point(1.0, 0.0)) >>> from petrify.plane import Circle >>> l.connect(Circle(Point(2, 0), 1)) LineSegment(Point(0.0, 0.0), Point(1.0, 0.0)) """ return other._connect_line2(self)
def _connect_point2(self, other): return _connect_point2_line2(other, self) def _connect_line2(self, other): return _connect_line2_line2(other, self) def _connect_circle(self, other): return _connect_circle_line2(other, self)
Line = Line2
[docs]class Ray2(Line2): """ Represents a line with an origin point that extends forever: >>> Ray(Point(0, 0), Vector(1, 1)) Ray(Point(0, 0), Vector(1, 1)) """ def __repr__(self): return 'Ray({0!r}, {1!r})'.format(self.p, self.v) def _u_in(self, u): return u >= 0.0
Ray = Ray2
[docs]class LineSegment2(Line2): """ Represents a line segment: >>> LineSegment(Point(0, 0), Vector(1, 1)) LineSegment(Point(0, 0), Point(1, 1)) """ def __repr__(self): return 'LineSegment({0!r}, {1!r})'.format(self.p, self.p2) def _u_in(self, u): return u >= 0.0 and u <= 1.0 def __abs__(self): return abs(self.v) def magnitude_squared(self): return self.v.magnitude_squared() def _swap(self): # used by connect methods to switch order of points self.p = self.p2 self.v *= -1 return self length = property(lambda self: abs(self.v))
LineSegment = LineSegment2