def represent_in_local_coordinates(self, point): """Represents a point in the frame's local coordinate system. Parameters ---------- point : :obj:`list` of :obj:`float` A point in world XY. Returns ------- :obj:`list` of :obj:`float` A point in the local coordinate system of the frame. Examples -------- >>> f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) >>> pw1 = [2, 2, 2] >>> pf = f.represent_in_local_coordinates(pw1) >>> pw2 = f.represent_in_global_coordinates(pf) >>> allclose(pw1, pw2) True """ pt = Point(*subtract_vectors(point, self.point)) T = inverse(matrix_from_basis_vectors(self.xaxis, self.yaxis)) pt.transform(T) return pt
def represent_in_global_coordinates(self, point): """Represents a point from local coordinates in the world coordinate system. Parameters ---------- point : :obj:`list` of :obj:`float` A point in local coordinates. Returns ------- :obj:`list` of :obj:`float` A point in the world coordinate system. Examples -------- >>> f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) >>> pw1 = [2, 2, 2] >>> pf = f.represent_in_local_coordinates(pw1) >>> pw2 = f.represent_in_global_coordinates(pf) >>> allclose(pw1, pw2) True """ T = matrix_from_frame(self) pt = Point(*point) pt.transform(T) return pt
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 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 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 from_three_points(cls, a, b, c): """Construct a plane from three points in three-dimensional space. Parameters ---------- a : point The first point. b : point The second point. c : point The second point. Returns ------- Plane A plane with base point ``a`` and normal vector defined as the unitized cross product of the vectors ``ab`` and ``ac``. """ a = Point(*a) b = Point(*b) c = Point(*c) normal = Vector.cross(b - a, c - a) return cls(a, normal)
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. Notes ----- For more info on lines and linear equations, see [1]_. For convenience, this class implements the following *magic* methods: * ``__repr__`` * ``__len__`` * ``__getitem__`` * ``__setitem__`` * ``__iter__`` * ``__mul__`` * ``__imul__`` References ---------- .. [1] Wikipedia. *Linear equation*. Available at: https://en.wikipedia.org/wiki/Linear_equation. 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'> """ def __init__(self, p1, p2): self.start = Point(* p1) self.end = Point(* p2) # ========================================================================== # factory # ========================================================================== # ========================================================================== # 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) # ========================================================================== # representation # ========================================================================== def __repr__(self): return '({0}, {1})'.format(self.start, self.end) def __len__(self): return 2 # ========================================================================== # access # ========================================================================== 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]) # ========================================================================== # comparison # ========================================================================== # ========================================================================== # operators # ========================================================================== 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) # ========================================================================== # inplace operators # ========================================================================== def __imul__(self, n): v = self.direction * (n * self.length) self.end = self.start + v return self # ========================================================================== # methods # ========================================================================== # ========================================================================== # 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. Notes: This is an alias for self \*= n """ self *= n
def points(self, points): if points: self._points = [Point(*point) for point in points]
def from_point_and_normal(cls, point, normal): plane = cls() plane.point = Point(*point) plane.normal = Vector(*normal) plane.normal.unitize() return plane
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 end(self, point): self._end = Point(*point)
# ========================================================================== # transformations # ========================================================================== # ============================================================================== # Main # ============================================================================== if __name__ == '__main__': from compas.viewers import Viewer from compas.viewers import xdraw_points from compas.viewers 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) points = [{'pos': base, 'color': (1.0, 0.0, 0.0), 'size': 10.0}] lines = [] for vector in plane.basis + [plane.normal]: lines.append({ 'start': base, 'end': base + vector, 'color': (0.0, 0.0, 0.0), 'width': 3.0 })
def start(self, point): self._start = Point(*point)
def __init__(self, p1, p2): self.start = Point(* p1) self.end = Point(* p2)
def center(self): """Point: The center (of mass) of the polygon.""" return Point(* center_of_mass_polygon(self.points))
def point(self, point): self._point = Point(*point)
ea2 = f.euler_angles() print(allclose(ea1, ea2)) q1 = [0.945, -0.021, -0.125, 0.303] f = Frame.from_quaternion(q1, point=[1., 1., 1.]) q2 = f.quaternion print(allclose(q1, q2, tol=1e-03)) aav1 = [-0.043, -0.254, 0.617] f = Frame.from_axis_angle_vector(aav1, point=[0, 0, 0]) aav2 = f.axis_angle_vector print(allclose(aav1, aav2)) ea1 = 1.4, 0.5, 2.3 f = Frame.from_euler_angles(ea1, static=True, axes='xyz') ea2 = f.euler_angles(static=True, axes='xyz') print(allclose(ea1, ea2)) f1 = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame(f1) f2 = Frame.worldXY() f2.transform(T) print(f1 == f2) f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) pw1 = [2, 2, 2] pw1 = Point(*pw1) pf = f.represent_in_local_coordinates(pw1) pw2 = f.represent_in_global_coordinates(pf) print(allclose(pw1, pw2))
def centroid(self): """int: The centroid of the polygon.""" return Point(* centroid_points(self.points))
f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame(f) Tinv = T.inverse() I = Transformation() print(I == T * Tinv) f1 = Frame([2, 2, 2], [0.12, 0.58, 0.81], [-0.80, 0.53, -0.26]) f2 = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame_to_frame(f1, f2) f1.transform(T) print(f1 == f2) f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame(f) p = Point(0, 0, 0) p.transform(T) print(allclose(f.point, p)) f1 = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame(f1) points = [[1.0, 1.0, 1.0], [1.68, 1.68, 1.27], [0.33, 1.73, 0.85]] points = transform_points(points, T) trans1 = [1, 2, 3] angle1 = [-2.142, 1.141, -0.142] scale1 = [0.123, 2, 0.5] T = matrix_from_translation(trans1) R = matrix_from_euler_angles(angle1) S = matrix_from_scale_factors(scale1) M = multiply_matrices(multiply_matrices(T, R), S)