def __setitem__(self, key, value): if key == 0: self.start = Point(value) return if key == 1: self.end = Point(value) return raise KeyError
def from_three_points(cls, p1, p2, p3): p1 = Point(*p1) p2 = Point(*p2) p3 = Point(*p3) v1 = p2 - p1 v2 = p3 - p1 plane = cls() plane.point = p1 plane.normal = Vector.cross(v1, v2) plane.normal.unitize() return plane
def points(self, points): self.points = [Point(xyz) for xyz in points] self.p = len(points) self.lines = [ Line(self.points[i], self.points[i + 1]) for i in range(0, self.p - 1) ] self.l = len(self.lines)
def from_point_and_two_vectors(cls, point, v1, v2): v1 = Vector(*v1) v2 = Vector(*v2) n = Vector.cross(v1, v2) n.unitize() plane = cls() plane.point = Point(*point) plane.normal = n return plane
def compute_point(self, t): """Compute a point on the curve. Parameters: t (float): The value of the curve parameter. Must be between 0 and 1. Returns: Point: the corresponding point on the curve. """ n = self.degree point = Point([0, 0, 0]) for i, p in enumerate(self.points): b = bernstein(n, i, t) point += p * b return point
def points(self, points): if points: self.points = [Point(point) for point in points]
def centroid(self): """The centroid of the polygon.""" return Point(centroid_points(self.points))
def points(self, points): if points[-1] == points[0]: del points[-1] self.points = [Point(xyz) for xyz in points] self.lines = [Line(self.points[i], self.points[i + 1]) for i in range(-1, len(points) - 1)]
def center(self): """The center (of mass) of the polygon.""" return Point(center_of_mass_polygon(self.points))
def __init__(self, p1, p2): self.start = Point(p1) self.end = Point(p2)
def rotate(self, angle, origin=None): """Rotate the line around the origin, or around a specified origin.""" if not origin: origin = [0, 0, 0] origin = Point(origin)
class Line(object): r"""A line object is defined by two points in three-dimensional space. Parameters: p1 (tuple, list, Point): The xyz coordinates of the first point. p2 (tuple, list, Point): The xyz coordinates of the second point. Attributes: start (Point): The start point. end (Point): The end point. length (float): (**read-only**) The length of the line between start and end. midpoint (Point): (**read-only**) The midpoint between start and end. direction (Vector): (**read-only**) A unit vector pointing from start to end. Note: For convenience, this class implements the following *magic* methods: * ``__repr__`` * ``__len__`` * ``__getitem__`` * ``__setitem__`` * ``__iter__`` * ``__mul__`` * ``__imul__`` Examples: >>> line = Line([0,0,0], [1,1,1]) >>> line.midpoint [0.5, 0.5, 0.0] >>> line.length 1.73205080757 >>> line.direction [0.57735026919, 0.57735026919, 0.57735026919] >>> type(line.start) <class 'point.Point'> >>> type(line.midpoint) <class 'point.Point'> >>> type(line.direction) <class 'vector.Vector'> References: https://en.wikipedia.org/wiki/Linear_equation """ def __init__(self, p1, p2): self.start = Point(p1) self.end = Point(p2) def __repr__(self): return '({0}, {1})'.format(self.start, self.end) def __len__(self): return 2 def __getitem__(self, key): if key == 0: return self.start if key == 1: return self.end raise KeyError def __setitem__(self, key, value): if key == 0: self.start = Point(value) return if key == 1: self.end = Point(value) return raise KeyError def __iter__(self): return iter([self.start, self.end]) def __mul__(self, n): """Create a line with the same start point and direction, but scaled length. Parameters: n (int, float): The scaling factor. Returns: Line: A line with the same start point and direction, but scaled length. """ v = self.direction * (n * self.length) return Line(self.start, self.start + v) def __imul__(self, n): v = self.direction * (n * self.length) self.end = self.start + v return self # -------------------------------------------------------------------------- # descriptors # -------------------------------------------------------------------------- @property def vector(self): """A vector pointing from start to end. Returns: Vector: The vector. """ return self.end - self.start @property def length(self): """The length of the vector from start to end. Returns: float: The length. """ return self.vector.length @property def midpoint(self): """The midpoint between start and end. Returns: Point: The midpoint. """ v = self.direction * (0.5 * self.length) return self.start + v @property def direction(self): """A unit vector pointing from start and end. Returns: Vector: The direction. """ return self.vector * (1 / self.length) # -------------------------------------------------------------------------- # transformations # -------------------------------------------------------------------------- def translate(self, vector): """Translate the line by a vector.""" self.start.translate(vector) self.end.translate(vector) def rotate(self, angle, origin=None): """Rotate the line around the origin, or around a specified origin.""" if not origin: origin = [0, 0, 0] origin = Point(origin) def scale(self, n): """Increase the distance between start and end by a factor n, while keeping the start point fixed. Parameters: n (int, float): The scaling factor. Note: This is an alias for self \*= n """ self *= n
def from_point_and_normal(cls, point, normal): plane = cls() plane.point = Point(*point) plane.normal = Vector(*normal) plane.normal.unitize() return plane
Vector(*vector, unitize=True) for vector in orthonormalise_vectors([u, v]) ] # ============================================================================== # Debugging # ============================================================================== if __name__ == '__main__': from compas.visualization.viewers.viewer import Viewer from compas.visualization.viewers.core.drawing import xdraw_points from compas.visualization.viewers.core.drawing import xdraw_lines base = Point(1.0, 0.0, 0.0) normal = Vector(1.0, 1.0, 1.0) plane = Plane.from_point_and_normal(base, normal) basis = plane.basis() points = [{'pos': base, 'color': (1.0, 0.0, 0.0), 'size': 10.0}] lines = [] for vector in basis + [plane.normal]: lines.append({ 'start': base, 'end': base + vector, 'color': (0.0, 0.0, 0.0),