Esempio n. 1
0
    def tangent(self, t):
        """Compute the tangent vector at a point on the curve.

        Parameters
        ----------
        t : float
            The value of the curve parameter. Must be between 0 and 1.

        Returns
        -------
        Vector
            The corresponding tangent vector.

        Examples
        --------
        >>> curve = Bezier([[0.0, 0.0, 0.0], [0.5, 1.0, 0.0], [1.0, 0.0, 0.0]])
        >>> curve.tangent(0.5)
        Vector(1.000, 0.000, 0.000)
        """
        n = self.degree
        v = Vector(0, 0, 0)
        for i, p in enumerate(self.points):
            a = bernstein(n - 1, i - 1, t)
            b = bernstein(n - 1, i, t)
            c = n * (a - b)
            v += p * c
        v.unitize()
        return v
Esempio n. 2
0
    def from_data(cls, data):
        """Construct a frame from its data representation.

        Parameters
        ----------
        data : dict
            The data dictionary.

        Returns
        -------
        :class:`compas.geometry.Frame`
            The constructed frame.

        Examples
        --------
        >>> data = {'point': [0.0, 0.0, 0.0], 'xaxis': [1.0, 0.0, 0.0], 'yaxis': [0.0, 1.0, 0.0]}
        >>> frame = Frame.from_data(data)
        >>> frame.point
        Point(0.000, 0.000, 0.000)
        >>> frame.xaxis
        Vector(1.000, 0.000, 0.000)
        >>> frame.yaxis
        Vector(0.000, 1.000, 0.000)

        """
        frame = cls(Point.from_data(data['point']), Vector.from_data(data['xaxis']), Vector.from_data(data['yaxis']))
        return frame
Esempio n. 3
0
    def represent_vector_in_global_coordinates(self, vector):
        """Represents a vector in local coordinates in the world coordinate system.

        Parameters
        ----------
        vector: :obj:`list` of :obj:`float` or :class:`Vector`
            A vector in local coordinates.

        Returns
        -------
        :class:`Vector`
            A vector in the world coordinate system.

        Examples
        --------
        >>> from compas.geometry import Frame
        >>> f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15])
        >>> pw1 = [2, 2, 2]
        >>> pf = f.represent_vector_in_local_coordinates(pw1)
        >>> pw2 = f.represent_vector_in_global_coordinates(pf)
        >>> allclose(pw1, pw2)
        True

        """
        T = matrix_from_frame(self)
        vec = Vector(*vector)
        vec.transform(T)
        return vec
Esempio n. 4
0
 def basis_vectors(self):
     """Returns the basis vectors from the ``Rotation`` component of the
         ``Transformation``.
     """
     sc, sh, a, t, p = decompose_matrix(self.matrix)
     R = matrix_from_euler_angles(a, static=True, axes='xyz')
     xv, yv = basis_vectors_from_matrix(R)
     return Vector(*xv), Vector(*yv)
Esempio n. 5
0
 def compute_tangent(self, t):
     n = self.degree
     v = Vector(0, 0, 0)
     for i, p in enumerate(self.points):
         a = bernstein(n - 1, i - 1, t)
         b = bernstein(n - 1, i, t)
         c = n * (a - b)
         v += p * c
     v.unitize()
     return v
Esempio n. 6
0
    def basis_vectors(self):
        """Returns the basis vectors from the ``Rotation`` component of the ``Transformation``.
        """
        # this has to be here to avoid circular import
        from compas.geometry.primitives import Vector

        sc, sh, a, t, p = decompose_matrix(self.matrix)
        R = matrix_from_euler_angles(a, static=True, axes='xyz')
        xv, yv = basis_vectors_from_matrix(R)
        return Vector(*xv), Vector(*yv)
Esempio n. 7
0
    def basis_vectors(self):
        """Returns the basis vectors of the ``Rotation``.

        Returns
        -------
        tuple: (:class:`Vector`, :class:`Vector`)

        """
        from compas.geometry.primitives import Vector
        xaxis, yaxis = basis_vectors_from_matrix(self.matrix)
        return Vector(*xaxis), Vector(*yaxis)
Esempio n. 8
0
 def from_bounding_box(cls, bbox):
     a = bbox[0]
     b = bbox[1]
     d = bbox[3]
     e = bbox[4]
     xaxis = Vector(*subtract_vectors(d, a))
     yaxis = Vector(*subtract_vectors(b, a))
     zaxis = Vector(*subtract_vectors(e, a))
     xsize = xaxis.length
     ysize = yaxis.length
     zsize = zaxis.length
     frame = Frame(a, xaxis, yaxis)
     return cls(frame, xsize, ysize, zsize)
Esempio n. 9
0
def test_basis_vectors():
    trans1 = [1, 2, 3]
    angle1 = [-2.142, 1.141, -0.142]
    scale1 = [0.123, 2, 0.5]
    T1 = Translation(trans1)
    R1 = Rotation.from_euler_angles(angle1)
    S1 = Scale(scale1)
    M = (T1 * R1) * S1
    x, y = M.basis_vectors
    assert np.allclose(
        x,
        Vector(0.41249169135312663, -0.05897071585157175, -0.9090506362335324))
    assert np.allclose(
        y,
        Vector(-0.8335562904208867, -0.4269749553355485, -0.35053715668381935))
Esempio n. 10
0
 def from_bounding_box(cls, bbox):
     # this should put the frame at the centroid of the box
     # not at the bottom left corner
     a = bbox[0]
     b = bbox[1]
     d = bbox[3]
     e = bbox[4]
     xaxis = Vector(*subtract_vectors(d, a))
     yaxis = Vector(*subtract_vectors(b, a))
     zaxis = Vector(*subtract_vectors(e, a))
     xsize = xaxis.length
     ysize = yaxis.length
     zsize = zaxis.length
     frame = Frame(a, xaxis, yaxis)
     frame.point += frame.xaxis * 0.5 * xsize + frame.yaxis * 0.5 * ysize + frame.zaxis * 0.5 * zsize
     return cls(frame, xsize, ysize, zsize)
Esempio n. 11
0
    def from_point_and_two_vectors(cls, point, u, v):
        """Construct a plane from a base point and two vectors.

        Parameters
        ----------
        point : [float, float, float] | :class:`compas.geometry.Point`
            The base point.
        u : [float, float, float] | :class:`compas.geometry.Vector`
            The first vector.
        v : [float, float, float] | :class:`compas.geometry.Vector`
            The second vector.

        Returns
        -------
        :class:`compas.geometry.Plane`
            A plane with base point `point` and normal vector defined as the unitized
            cross product of vectors `u` and `v`.

        Examples
        --------
        >>> plane = Plane.from_three_points([0.0, 0.0, 0.0], [2.0, 1.0, 0.0], [0.0, 3.0, 0.0])
        >>> plane.point
        Point(0.000, 0.000, 0.000)
        >>> plane.normal
        Vector(0.000, 0.000, 1.000)

        """
        normal = Vector.cross(u, v)
        return cls(point, normal)
Esempio n. 12
0
    def from_three_points(cls, a, b, c):
        """Construct a plane from three points in three-dimensional space.

        Parameters
        ----------
        a : [float, float, float] | :class:`compas.geometry.Point`
            The first point.
        b : [float, float, float] | :class:`compas.geometry.Point`
            The second point.
        c : [float, float, float] | :class:`compas.geometry.Point`
            The second point.

        Returns
        -------
        :class:`compas.geometry.Plane`
            A plane with base point `a` and normal vector defined as the unitized
            cross product of the vectors `ab` and `ac`.

        Examples
        --------
        >>> plane = Plane.from_three_points([0.0, 0.0, 0.0], [2.0, 1.0, 0.0], [0.0, 3.0, 0.0])
        >>> plane.point
        Point(0.000, 0.000, 0.000)
        >>> plane.normal
        Vector(0.000, 0.000, 1.000)

        """
        a = Point(*a)
        b = Point(*b)
        c = Point(*c)
        normal = Vector.cross(b - a, c - a)
        return cls(a, normal)
Esempio n. 13
0
    def from_corner_corner_height(cls, corner1, corner2, height):
        """Construct a box from the opposite corners of its base and its height.

        Parameters
        ----------
        corner1 : point
            The XYZ coordinates of the bottom left corner of the base of the box.
        corner2 : point
            The XYZ coordinates of the top right corner of the base of the box.
        height : float
            The height of the box.

        Returns
        -------
        Box
            The resulting box.

        Examples
        --------
        >>> box = Box.from_corner_corner_height([0.0, 0.0, 0.0], [1.0, 1.0, 0.0], 1.0)

        """
        # this should put the frame at the centroid of the box
        # not at the bottom left corner
        if height == 0:
            raise Exception('The box should have a height.')

        x1, y1, z1 = corner1
        x2, y2, z2 = corner2

        xaxis = Vector(x2 - x1, 0, 0)
        yaxis = Vector(0, y2 - y1, 0)
        width = xaxis.length
        depth = yaxis.length

        if z1 != z2:
            raise Exception('Corners should be in the same horizontal plane.')

        frame = Frame(corner1, xaxis, yaxis)
        frame.point += frame.xaxis * 0.5 * width + frame.yaxis * 0.5 * depth + frame.zaxis * 0.5 * height
        return cls(frame, width, depth, height)
Esempio n. 14
0
    def from_diagonal(cls, diagonal):
        """Construct a box from its main diagonal.

        Parameters
        ----------
        diagonal : segment
            The diagonal of the box, represented by a pair of points in space.

        Returns
        -------
        Box
            The resulting box.

        Examples
        --------
        >>> diagonal = [0.0, 0.0, 0.0], [1.0, 1.0, 1.0]
        >>> box = Box.from_diagonal(diagonal)

        """
        # this should put the frame at the centroid of the box
        # not at the bottom left corner
        d1, d2 = diagonal

        x1, y1, z1 = d1
        x2, y2, z2 = d2

        if z1 == z2:
            raise Exception('The box has no height.')

        xaxis = Vector(x2 - x1, 0, 0)
        yaxis = Vector(0, y2 - y1, 0)
        zaxis = Vector(0, 0, z2 - z1)
        width = xaxis.length
        depth = yaxis.length
        height = zaxis.length

        frame = Frame(d1, xaxis, yaxis)
        frame.point += frame.xaxis * 0.5 * width + frame.yaxis * 0.5 * depth + frame.zaxis * 0.5 * height
        return cls(frame, width, depth, height)
Esempio n. 15
0
    def from_plane(cls, plane):
        """Constructs a frame from a plane.

        Xaxis and yaxis are arbitrarily selected based on the plane's normal.

        Parameters
        ----------
        plane : :class:`compas.geometry.Plane`
            A plane.

        Returns
        -------
        :class:`compas.geometry.Frame`
            The constructed frame.

        Examples
        --------
        >>> plane = Plane([0,0,0], [0,0,1])
        >>> frame = Frame.from_plane(plane)
        >>> allclose(frame.normal, plane.normal)
        True
        """

        # plane equation: a*x + b*y + c*z = d
        d = Vector(*plane.point).dot(plane.normal)

        # select 2 arbitrary points in the plane from which we create the xaxis

        coeffs = list(plane.normal)  # a, b, c
        # select a coeff with a value != 0
        coeffs_abs = [math.fabs(x) for x in coeffs]
        idx = coeffs_abs.index(max(coeffs_abs))

        # first point
        coords = [0, 0, 0]  # x, y, z
        # z = (d - a*0 + b*0)/c, if idx == 2
        v = d / coeffs[idx]
        coords[idx] = v
        pt1_in_plane = Point(*coords)

        # second point
        coords = [1, 1, 1]  # x, y, z
        coords[idx] = 0
        # z = (d - a*1 + b*1)/c, if idx == 2
        v = (d - sum([a * x for a, x in zip(coeffs, coords)])) / coeffs[idx]
        coords[idx] = v
        pt2_in_plane = Point(*coords)

        xaxis = pt2_in_plane - pt1_in_plane
        yaxis = plane.normal.cross(xaxis)
        return cls(plane.point, xaxis, yaxis)
Esempio n. 16
0
    def from_plane(cls, plane):
        """Constructs a frame from a plane.

        Xaxis and yaxis are arbitrarily selected based on the plane's normal.

        Parameters
        ----------
        plane : :class:`compas.geometry.Plane`
            A plane.

        Returns
        -------
        :class:`compas.geometry.Frame`
            The constructed frame.

        Examples
        --------
        >>> from compas.geometry import Plane
        >>> plane = Plane([0,0,0], [0,0,1])
        >>> frame = Frame.from_plane(plane)
        >>> allclose(frame.normal, plane.normal)
        True
        """
        point, normal = plane
        # To construct a frame we need to find a vector v that is perpendicular
        # to the plane's normal. This means that the dot-product of v with the
        # normal must be equal to 0, which is true for the following vectors:
        vectors = [
            Vector(-normal[1], normal[0], 0),
            Vector(0, -normal[2], normal[1]),
            Vector(normal[2], 0, -normal[0])
        ]
        # But if we are unlucky, one of these vectors is (0, 0, 0), so we
        # choose the vector with the longest length as xaxis.
        idx = argmax([v.length for v in vectors])
        xaxis = vectors[idx]
        yaxis = cross_vectors(normal, xaxis)
        return cls(point, xaxis, yaxis)
Esempio n. 17
0
    def from_diagonal(cls, diagonal):
        """Construct a box from its main diagonal.

        Parameters
        ----------
        diagonal : segment
            The diagonal of the box, represented by a pair of points in space.

        Returns
        -------
        Box
            The resulting box.

        Examples
        --------
        >>> from compas.geometry import Box
        >>> diagonal = [0.0, 0.0, 0.0], [1.0, 1.0, 1.0]
        >>> box = Box.from_diagonal(diagonal)

        """
        d1, d2 = diagonal

        x1, y1, z1 = d1
        x2, y2, z2 = d2

        if z1 == z2:
            raise Exception('The box has no height.')

        xaxis = Vector(x2 - x1, 0, 0)
        yaxis = Vector(0, y2 - y1, 0)
        zaxis = Vector(0, 0, z2 - z1)
        width = xaxis.length
        depth = yaxis.length
        height = zaxis.length

        frame = Frame(d1, xaxis, yaxis)
        return cls(frame, width, depth, height)
Esempio n. 18
0
 def normal(self):
     o = self.centroid
     points = self.points
     a2 = 0
     normals = []
     for i in range(-1, len(points) - 1):
         p1 = points[i]
         p2 = points[i + 1]
         u = [p1[_] - o[_] for _ in range(3)]
         v = [p2[_] - o[_] for _ in range(3)]
         w = cross_vectors(u, v)
         a2 += sum(w[_]**2 for _ in range(3))**0.5
         normals.append(w)
     n = [sum(axis) / a2 for axis in zip(*normals)]
     n = Vector(*n)
     return n
Esempio n. 19
0
 def normal(self):
     """:class:`compas.geometry.Vector` : The (average) normal of the polygon."""
     o = self.centroid
     points = self.points
     a2 = 0
     normals = []
     for i in range(-1, len(points) - 1):
         p1 = points[i]
         p2 = points[i + 1]
         u = [p1[_] - o[_] for _ in range(3)]
         v = [p2[_] - o[_] for _ in range(3)]
         w = cross_vectors(u, v)
         a2 += sum(w[_] ** 2 for _ in range(3)) ** 0.5
         normals.append(w)
     n = [sum(axis) / a2 for axis in zip(*normals)]
     n = Vector(* n)
     return n
Esempio n. 20
0
    def __sub__(self, other):
        """Return a vector` that is the the difference between this point
        and another point.

        Parameters
        ----------
        other : :class:`compas.geometry.Point` or list
            The point to subtract.

        Returns
        -------
        :class:`compas.geometry.Vector`
            A vector from other to self.
        """
        x = self.x - other[0]
        y = self.y - other[1]
        z = self.z - other[2]
        return Vector(x, y, z)
Esempio n. 21
0
    def __sub__(self, other):
        """Return a ``Vector`` that is the the difference between this ``Point``
        and another point.

        Parameters
        ----------
        other : point
            The point to subtract.

        Returns
        -------
        Vector
            A vector from other to self.

        """
        x = self.x - other[0]
        y = self.y - other[1]
        z = self.z - other[2]
        return Vector(x, y, z)
Esempio n. 22
0
    def from_point_and_two_vectors(cls, point, u, v):
        """Construct a plane from a base point and two vectors.

        Parameters
        ----------
        point : point
            The base point.
        u : vector
            The first vector.
        v : vector
            The second vector.

        Returns
        -------
        Plane
            A plane with base point ``point`` and normal vector defined as the unitized
            cross product of vectors ``u`` and ``v``.

        """
        normal = Vector.cross(u, v)
        return cls(point, normal)
Esempio n. 23
0
    def axis_and_angle(self):
        """Returns the axis and the angle of the ``Rotation``.

        Returns
        -------
        tuple: (:class:`Vector`, float)

        Examples
        --------
        >>> axis1 = normalize_vector([-0.043, -0.254, 0.617])
        >>> angle1 = 0.1
        >>> R = Rotation.from_axis_and_angle(axis1, angle1)
        >>> axis2, angle2 = R.axis_and_angle
        >>> allclose(axis1, axis2)
        True
        >>> allclose([angle1], [angle2])
        True
        """
        from compas.geometry.primitives import Vector
        axis, angle = axis_and_angle_from_matrix(self.matrix)
        return Vector(*axis), angle
Esempio n. 24
0
    def from_data(cls, data):
        """Construct a plane from its data representation.

        Parameters
        ----------
        data : dict
            The data dictionary.

        Returns
        -------
        :class:`compas.geometry.Plane`
            The constructed plane.

        Examples
        --------
        >>> plane = Plane.from_data({'point': [0.0, 0.0, 0.0], 'normal': [0.0, 0.0, 1.0]})
        >>> plane.point
        Point(0.000, 0.000, 0.000)
        >>> plane.normal
        Vector(0.000, 0.000, 1.000)

        """
        return cls(Point.from_data(data['point']), Vector.from_data(data['normal']))
Esempio n. 25
0
    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)
Esempio n. 26
0
 def axis_angle_vector(self):
     """:class:`compas.geometry.Vector` : The axis-angle vector representing the rotation of the frame."""
     R = matrix_from_basis_vectors(self.xaxis, self.yaxis)
     return Vector(*axis_angle_vector_from_matrix(R))
Esempio n. 27
0
 def normal(self):
     """:class:`compas.geometry.Vector` : The normal of the base plane of the frame."""
     return Vector(*cross_vectors(self.xaxis, self.yaxis))
Esempio n. 28
0
 def yaxis(self, vector):
     yaxis = Vector(*vector)
     yaxis.unitize()
     zaxis = Vector.cross(self.xaxis, yaxis)
     zaxis.unitize()
     self._yaxis = Vector.cross(zaxis, self.xaxis)
Esempio n. 29
0
 def xaxis(self, vector):
     xaxis = Vector(*vector)
     xaxis.unitize()
     self._xaxis = xaxis
Esempio n. 30
0
 def data(self, data):
     self.point = Point.from_data(data['point'])
     self.normal = Vector.from_data(data['normal'])