def get_matrix(self, tangent, scale):
        x = Vector((1.0, 0.0, 0.0))
        y = Vector((0.0, 1.0, 0.0))
        z = Vector((0.0, 0.0, 1.0))

        if self.orient_axis == 0:
            ax1, ax2, ax3 = x, y, z
        elif self.orient_axis == 1:
            ax1, ax2, ax3 = y, x, z
        else:
            ax1, ax2, ax3 = z, x, y

        if self.scale_all:
            scale_matrix = Matrix.Scale(1 / scale, 4, ax1) * Matrix.Scale(
                scale, 4, ax2) * Matrix.Scale(scale, 4, ax3)
        else:
            scale_matrix = Matrix.Identity(4)

        if self.algorithm == 'householder':
            rot = autorotate_householder(ax1, tangent).inverted()
        elif self.algorithm == 'track':
            rot = autorotate_track(self.orient_axis_, tangent, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(tangent, ax1)
        else:
            raise Exception("Unsupported algorithm")

        return rot * scale_matrix
示例#2
0
 def calc_rotation(self, curve, src, dst, plane=None):
     # Some hacks.
     # Problem: if src and/or dst are exactly parallel to
     # one of coordinate axes, then Vector.rotation_difference
     # sometimes returns a matrix that rotates our vector in
     # completely different plane.
     # For example, if whole figure lays in XY plane, and
     # we are trying to rotate src = (0, 1, 0) into dst = (1, 0, 0),
     # then rotation_difference might return us a matrix, which
     # rotates (-1, 0, 0) into (0, 0, -1), which is out of XY plane
     # ("because why no? it still rotates src into dst").
     # Solution (hack): if whole figure lays in XY plane, then do
     # not use general rotation_difference method, calculate
     # rotation along Z axis only.
     if plane == 'XY':
         # Another unobvious hack: Vector.angle_signed method
         # works with 2D vectors only. Fortunately, in this particular
         # case our vectors are actually 2D.
         dst = Vector((dst[0], dst[1]))
         src = Vector((src[0], src[1]))
         angle = dst.angle_signed(src)
         return Matrix.Rotation(angle, 4, 'Z')
     elif plane == 'YZ':
         dst = Vector((dst[1], dst[2]))
         src = Vector((src[1], src[2]))
         angle = dst.angle_signed(src)
         return Matrix.Rotation(angle, 4, 'X')
     elif plane == 'XZ':
         dst = Vector((dst[2], dst[0]))
         src = Vector((src[2], src[0]))
         angle = dst.angle_signed(src)
         return Matrix.Rotation(angle, 4, 'Y')
     else:
         return autorotate_diff(dst, src)
示例#3
0
    def get_matrix(self, tangent, scale):
        x = Vector((1.0, 0.0, 0.0))
        y = Vector((0.0, 1.0, 0.0))
        z = Vector((0.0, 0.0, 1.0))

        if self.axis == 0:
            ax1, ax2, ax3 = x, y, z
        elif self.axis == 1:
            ax1, ax2, ax3 = y, x, z
        else:
            ax1, ax2, ax3 = z, x, y

        if self.scale_all:
            scale_matrix = Matrix.Scale(1 / scale, 4, ax1) @ Matrix.Scale(
                scale, 4, ax2) @ Matrix.Scale(scale, 4, ax3)
        else:
            scale_matrix = Matrix.Scale(1 / scale, 4, ax1)
        scale_matrix = np.array(scale_matrix.to_3x3())

        tangent = Vector(tangent)
        if self.algorithm == 'householder':
            rot = autorotate_householder(ax1, tangent).inverted()
        elif self.algorithm == 'track':
            axis = "XYZ"[self.axis]
            rot = autorotate_track(axis, tangent, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(tangent, ax1)
        else:
            raise Exception("Unsupported algorithm")
        rot = np.array(rot.to_3x3())

        return np.matmul(rot, scale_matrix)
示例#4
0
    def get_matrix(self, tangent, twist_value, scale_x, scale_y):
        x = Vector((1.0, 0.0, 0.0))
        y = Vector((0.0, 1.0, 0.0))
        z = Vector((0.0, 0.0, 1.0))

        if self.orient_axis_idx == 0:
            ax1, ax2, ax3 = x, y, z
        elif self.orient_axis_idx == 1:
            ax1, ax2, ax3 = y, x, z
        else:
            ax1, ax2, ax3 = z, x, y

        scale_matrix = Matrix.Scale(1, 4, ax1) @ Matrix.Scale(scale_x, 4, ax2) @ Matrix.Scale(scale_y, 4, ax3)

        twist_matrix = Matrix.Rotation(twist_value, 4, ax1)

        if self.algorithm == 'householder':
            rot = autorotate_householder(ax1, tangent).inverted()
        elif self.algorithm == 'track':
            rot = autorotate_track(self.orient_axis, tangent, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(tangent, ax1)
        else:
            raise Exception("Unsupported algorithm")

        return rot @ scale_matrix @ twist_matrix
示例#5
0
    def get_matrix(self, tangent, scale):
        x = Vector((1.0, 0.0, 0.0))
        y = Vector((0.0, 1.0, 0.0))
        z = Vector((0.0, 0.0, 1.0))

        if self.orient_axis == 0:
            ax1, ax2, ax3 = x, y, z
        elif self.orient_axis == 1:
            ax1, ax2, ax3 = y, x, z
        else:
            ax1, ax2, ax3 = z, x, y

        if self.scale_all:
            scale_matrix = Matrix.Scale(1/scale, 4, ax1) * Matrix.Scale(scale, 4, ax2) * Matrix.Scale(scale, 4, ax3)
        else:
            scale_matrix = Matrix.Identity(4)

        if self.algorithm == 'householder':
            rot = autorotate_householder(ax1, tangent).inverted()
        elif self.algorithm == 'track':
            rot = autorotate_track(self.orient_axis_, tangent, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(tangent, ax1)
        else:
            raise Exception("Unsupported algorithm")

        return rot * scale_matrix
示例#6
0
 def calc_rotation(self, curve, src, dst, plane=None):
     # Some hacks.
     # Problem: if src and/or dst are exactly parallel to
     # one of coordinate axes, then Vector.rotation_difference
     # sometimes returns a matrix that rotates our vector in
     # completely different plane.
     # For example, if whole figure lays in XY plane, and
     # we are trying to rotate src = (0, 1, 0) into dst = (1, 0, 0),
     # then rotation_difference might return us a matrix, which
     # rotates (-1, 0, 0) into (0, 0, -1), which is out of XY plane
     # ("because why no? it still rotates src into dst").
     # Solution (hack): if whole figure lays in XY plane, then do
     # not use general rotation_difference method, calculate
     # rotation along Z axis only.
     if plane == 'XY':
         # Another unobvious hack: Vector.angle_signed method
         # works with 2D vectors only (this is not stated in
         # it's documentation!). Fortunately, in this particular
         # case our vectors are actually 2D.
         dst = Vector((dst[0], dst[1]))
         src = Vector((src[0], src[1]))
         angle = dst.angle_signed(src)
         return Matrix.Rotation(angle, 4, 'Z')
     elif plane == 'YZ':
         dst = Vector((dst[1], dst[2]))
         src = Vector((src[1], src[2]))
         angle = dst.angle_signed(src)
         return Matrix.Rotation(angle, 4, 'X')
     elif plane == 'XZ':
         dst = Vector((dst[2], dst[0]))
         src = Vector((src[2], src[0]))
         angle = dst.angle_signed(src)
         return Matrix.Rotation(angle, 4, 'Y')
     else:
         return autorotate_diff(dst, src)
示例#7
0
    def duplicate_vertices(self, v1, v2, vertices, edges, faces, count, p):
        direction = v2 - v1
        edge_length = (1.0 - 2 * p) * direction.length
        one_item_length = edge_length / count
        actual_length = diameter(vertices, self.orient_axis)
        if actual_length != 0.0:
            x_scale = one_item_length / actual_length
        else:
            x_scale = 1.0
        x = all_axes[self.orient_axis]
        # for actual_length = 1.0 and edge_length = 3.0, let origins be [0.5, 1.5, 2.5]
        u = direction.normalized()
        alphas = np.linspace(0.0, 1.0, count + 1)
        origins = [
            v1 + (1 - 2 * p) * direction * alpha + p * direction +
            0.5 * one_item_length * u for alpha in alphas
        ][:-1]
        assert len(origins) == count

        if self.scale_off:
            scale = None
        else:
            if self.scale_all:
                scale = Matrix.Scale(x_scale, 4)
            else:
                scale = Matrix.Scale(x_scale, 4, x)

        need_flip = False
        if self.algorithm == 'householder':
            rot = autorotate_householder(x, direction).inverted()
            # Since Householder transformation is reflection, we need to reflect things back
            need_flip = True
        elif self.algorithm == 'track':
            rot = autorotate_track(self.orient_axis_, direction, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(x, direction).inverted()
        else:
            raise Exception("Unsupported algorithm")

        if need_flip:
            flip = Matrix([[-1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0],
                           [0, 0, 0, 1]])
        else:
            flip = Matrix.Identity(4)
        if scale is None:
            matrices = [Matrix.Translation(o) * rot * flip for o in origins]
        else:
            matrices = [
                Matrix.Translation(o) * rot * scale * flip for o in origins
            ]

        if self.apply_matrices:
            result_vertices = [[m * vertex for vertex in vertices]
                               for m in matrices]
        else:
            result_vertices = [vertices] * count
        return matrices, result_vertices
示例#8
0
    def duplicate_vertices(self, v1, v2, vertices, edges, faces, count, p):
        direction = v2 - v1
        edge_length = (1.0 - 2*p) * direction.length
        one_item_length = edge_length / count
        actual_length = diameter(vertices, self.orient_axis)
        if actual_length != 0.0:
            x_scale = one_item_length / actual_length
        else:
            x_scale = 1.0
        x = all_axes[self.orient_axis]
        # for actual_length = 1.0 and edge_length = 3.0, let origins be [0.5, 1.5, 2.5]
        u = direction.normalized()
        alphas = np.linspace(0.0, 1.0, count+1)
        origins = [v1 + (1-2*p)*direction*alpha + p*direction + 0.5*one_item_length*u for alpha in alphas][:-1]
        assert len(origins) == count

        if self.scale_off:
            scale = None
        else:
            if self.scale_all:
                scale = Matrix.Scale(x_scale, 4)
            else:
                scale = Matrix.Scale(x_scale, 4, x)

        need_flip = False
        if self.algorithm == 'householder':
            rot = autorotate_householder(x, direction).inverted()
            # Since Householder transformation is reflection, we need to reflect things back
            need_flip = True
        elif self.algorithm == 'track':
            rot = autorotate_track(self.orient_axis_, direction, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(x, direction).inverted()
        else:
            raise Exception("Unsupported algorithm")

        if need_flip:
            flip = Matrix([[-1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]])
        else:
            flip = Matrix.Identity(4)
        if scale is None:
            matrices = [Matrix.Translation(o)*rot*flip for o in origins]
        else:
            matrices = [Matrix.Translation(o)*rot*scale*flip for o in origins]

        if self.apply_matrices:
            result_vertices = [[m * vertex for vertex in vertices] for m in matrices]
        else:
            result_vertices = [vertices] * count
        return matrices, result_vertices
示例#9
0
    def get_matrix(cls,
                   tangent,
                   scale,
                   axis,
                   algorithm,
                   scale_all=True,
                   up_axis='X'):
        """
        Calculate matrix required to rotate object according to `tangent` vector.
        inputs:
            * tangent - np.array of shape (3,)
            * scale - float
            * axis - int, 0 - X, 1 - Y, 2 - Z
            * algorithm - one of HOUSEHOLDER, TRACK, DIFF
            * scale_all - True to scale along all axes, False to scale along tangent only
            * up_axis - string, "X", "Y" or "Z", for algorithm == TRACK only.
        output:
            np.array of shape (3,3).
        """
        x = Vector((1.0, 0.0, 0.0))
        y = Vector((0.0, 1.0, 0.0))
        z = Vector((0.0, 0.0, 1.0))

        if axis == 0:
            ax1, ax2, ax3 = x, y, z
        elif axis == 1:
            ax1, ax2, ax3 = y, x, z
        else:
            ax1, ax2, ax3 = z, x, y

        if scale_all:
            scale_matrix = Matrix.Scale(1 / scale, 4, ax1) @ Matrix.Scale(
                scale, 4, ax2) @ Matrix.Scale(scale, 4, ax3)
        else:
            scale_matrix = Matrix.Scale(1 / scale, 4, ax1)
        scale_matrix = np.array(scale_matrix.to_3x3())

        tangent = Vector(tangent)
        if algorithm == HOUSEHOLDER:
            rot = autorotate_householder(ax1, tangent).inverted()
        elif algorithm == TRACK:
            axis = "XYZ"[axis]
            rot = autorotate_track(axis, tangent, up_axis)
        elif algorithm == DIFF:
            rot = autorotate_diff(tangent, ax1)
        else:
            raise Exception("Unsupported algorithm")
        rot = np.array(rot.to_3x3())

        return np.matmul(rot, scale_matrix)
示例#10
0
    def get_matrix(self, tangent):
        x = Vector((1.0, 0.0, 0.0))
        y = Vector((0.0, 1.0, 0.0))
        z = Vector((0.0, 0.0, 1.0))

        if self.orient_axis == 'X':
            ax1, ax2, ax3 = x, y, z
        elif self.orient_axis == 'Y':
            ax1, ax2, ax3 = y, x, z
        else:
            ax1, ax2, ax3 = z, x, y

        if self.algorithm == 'householder':
            rot = autorotate_householder(ax1, tangent).inverted()
        elif self.algorithm == 'track':
            rot = autorotate_track(self.orient_axis, tangent, self.up_axis)
        elif self.algorithm == 'diff':
            rot = autorotate_diff(tangent, ax1)
        else:
            raise Exception("Unsupported algorithm")

        return rot