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
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)
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)
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
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
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)
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
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
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)
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