def reorder(edges1, edges2): min_sum_rho = None best = None for i in range(len(edges1)): rotated2 = rotate_list(edges2, i) sum_rho = calc_rho(edges1, rotated2) if min_sum_rho is None or sum_rho < min_sum_rho: best = rotated2 min_sum_rho = sum_rho return edges1, best
def make_edges(nsides, shift, divs): vs = range(nsides * divs) edges = list(zip(vs, rotate_list(vs, shift + 1))) return edges
def _process_face(self, map_mode, output, recpt_face_data, donor, zcoef, zoffset, angle, wcoef, facerot): X, Y = self.get_other_axes() Z = self.normal_axis_idx() #self.info(f"Face: {len(recpt_face_data.vertices_co)}, mode: {map_mode}") if map_mode == 'ASIS': # Leave this recipient's face as it was - as a single face. verts = recpt_face_data.vertices_co[:] n = len(verts) output.verts_out.append(verts) output.faces_out.append([list(range(n))]) output.vert_recpt_idx_out.append([recpt_face_data.index for i in verts]) output.face_recpt_idx_out.append([recpt_face_data.index for i in range(n)]) elif map_mode == 'TRI': # Tris processing mode. # # As interpolate_tri_3d is based on barycentric_transform, # here we do not have to manually map donor vertices to the # unit triangle. i0, i1, i2 = rotate_list(self.tri_vert_idxs, facerot) if self.z_scale == 'AUTO': zcoef = self.calc_z_scale( [recpt_face_data.vertices_co[i0], recpt_face_data.vertices_co[i1], recpt_face_data.vertices_co[i2]], [donor.tri_vert_1/wcoef, donor.tri_vert_2/wcoef, donor.tri_vert_3/wcoef] ) * zcoef new_verts = [] for v in donor.verts_v: new_verts.append(self.interpolate_tri_3d( recpt_face_data.vertices_co[i0], recpt_face_data.vertices_co[i1], recpt_face_data.vertices_co[i2], recpt_face_data.vertices_normal[i0], recpt_face_data.vertices_normal[i1], recpt_face_data.vertices_normal[i2], donor.tri_vert_1/wcoef, donor.tri_vert_2/wcoef, donor.tri_vert_3/wcoef, recpt_face_data.normal, v, zcoef, zoffset)) output.verts_out.append(new_verts) output.faces_out.append(donor.faces_i) output.face_data_out.append(donor.face_data_i) output.vert_recpt_idx_out.append([recpt_face_data.index for i in new_verts]) output.face_recpt_idx_out.append([recpt_face_data.index for i in donor.faces_i]) elif map_mode == 'QUAD': # Quads processing mode. # # It can process Tris, but it will look strange: # triangle will be processed as degenerated Quad, # where third and fourth vertices coincide. # In Tissue addon, this is the only mode possible for Quads. # Someone may like that behaivour, so we allow it with setting... # # This can process NGons in even worse way: # it will take first three vertices and the last one # and consider that as a Quad. i0, i1, i2, i3 = rotate_list(self.quad_vert_idxs, facerot) if self.z_scale == 'AUTO': corner1 = self.from2d(donor.min_x, donor.min_y) corner2 = self.from2d(donor.min_x, donor.max_y) corner3 = self.from2d(donor.max_x, donor.max_y) corner4 = self.from2d(donor.max_x, donor.min_y) zcoef = self.calc_z_scale( [recpt_face_data.vertices_co[i0], recpt_face_data.vertices_co[i1], recpt_face_data.vertices_co[i2], recpt_face_data.vertices_co[i3]], [corner1, corner2, corner3, corner4] ) * zcoef new_verts = [] #self.info("Donor: %s", len(donor.verts_v)) for v in donor.verts_v: if self.xy_mode == 'BOUNDS': # Map the `v` vertex's X, Y coordinates # from it's bounding square to # [-1/2; 1/2] square. # Leave Z coordinate as it was. x = self.map_bounds(donor.min_x, donor.max_x, v[X]) y = self.map_bounds(donor.min_y, donor.max_y, v[Y]) z = v[Z] v = Vector((0, 0, 0)) v[X] = x v[Y] = y v[Z] = z new_verts.append(self.interpolate_quad_3d( recpt_face_data.vertices_co[i0], recpt_face_data.vertices_co[i1], recpt_face_data.vertices_co[i2], recpt_face_data.vertices_co[i3], recpt_face_data.vertices_normal[i0], recpt_face_data.vertices_normal[i1], recpt_face_data.vertices_normal[i2], recpt_face_data.vertices_normal[i3], recpt_face_data.normal, v, wcoef, wcoef, zcoef, zoffset)) output.verts_out.append(new_verts) output.faces_out.append(donor.faces_i) output.face_data_out.append(donor.face_data_i) output.vert_recpt_idx_out.append([recpt_face_data.index for i in new_verts]) output.face_recpt_idx_out.append([recpt_face_data.index for i in donor.faces_i]) elif map_mode == 'FRAME': is_fan = abs(recpt_face_data.frame_width - 1.0) < 1e-6 n = len(recpt_face_data.vertices_co) if self.map_mode == 'QUADS': sub_map_mode = 'QUAD' else: if is_fan: sub_map_mode = 'TRI' else: sub_map_mode = 'QUAD' if is_fan: tri_faces = [(recpt_face_data.vertices_co[i], recpt_face_data.vertices_co[i+1], recpt_face_data.center) for i in range(n-1)] tri_faces.append((recpt_face_data.vertices_co[-1], recpt_face_data.vertices_co[0], recpt_face_data.center)) if self.use_shell_factor: face_normal = sum(recpt_face_data.vertices_normal, Vector()) / n else: face_normal = recpt_face_data.normal tri_normals = [(recpt_face_data.vertices_normal[i], recpt_face_data.vertices_normal[i+1], face_normal) for i in range(n-1)] tri_normals.append((recpt_face_data.vertices_normal[-1], recpt_face_data.vertices_normal[0], face_normal)) for tri_face, tri_normal in zip(tri_faces, tri_normals): sub_recpt = recpt_face_data.copy() sub_recpt.vertices_co = tri_face sub_recpt.vertices_normal = tri_normal sub_recpt.vertices_idxs = [0, 1, 2] self._process_face(sub_map_mode, output, sub_recpt, donor, zcoef, zoffset, angle, wcoef, facerot) else: inner_verts = [vert.lerp(recpt_face_data.center, recpt_face_data.frame_width) for vert in recpt_face_data.vertices_co] if self.use_shell_factor: inner_normals = [normal.lerp(recpt_face_data.normal, recpt_face_data.frame_width) for normal in recpt_face_data.vertices_normal] else: face_normal = sum(recpt_face_data.vertices_normal, Vector()) / n inner_normals = [normal.lerp(face_normal, recpt_face_data.frame_width) for normal in recpt_face_data.vertices_normal] quad_faces = [(recpt_face_data.vertices_co[i], recpt_face_data.vertices_co[i+1], inner_verts[i+1], inner_verts[i]) for i in range(n-1)] quad_faces.append((recpt_face_data.vertices_co[-1], recpt_face_data.vertices_co[0], inner_verts[0], inner_verts[-1])) quad_normals = [(recpt_face_data.vertices_normal[i], recpt_face_data.vertices_normal[i+1], inner_normals[i+1], inner_normals[i]) for i in range(n-1)] quad_normals.append((recpt_face_data.vertices_normal[-1], recpt_face_data.vertices_normal[0], inner_normals[0], inner_normals[-1])) for quad_face, quad_normal in zip(quad_faces, quad_normals): sub_recpt = recpt_face_data.copy() sub_recpt.vertices_co = quad_face sub_recpt.vertices_normal = quad_normal sub_recpt.vertices_idxs = [0, 1, 2, 3] self._process_face(sub_map_mode, output, sub_recpt, donor, zcoef, zoffset, angle, wcoef, facerot)
def is_on_face_edge(pt, face_verts, epsilon=1e-6): for v1, v2 in zip(face_verts, rotate_list(face_verts)): if is_on_edge(pt, v1, v2, epsilon): return True return False
def process(self): verts = self.inputs['Vertices'].sv_get(default=[]) edges = self.inputs['Edges'].sv_get(default=[]) faces = self.inputs['Faces'].sv_get(default=[]) e_mask = self.inputs['EdgeMask'].sv_get(deepcopy=False, default=[[True]]) factor = self.inputs['Factor'].sv_get(deepcopy=False) cuts = self.inputs['Cuts'].sv_get(deepcopy=False) if faces and not edges: edges = polygons_to_edges_np(faces, True, False) obj_n = max(len(verts), len(e_mask), len(factor), len(cuts)) out_v = [] out_e = [] out_f = [] def vec(arr): return fixed_iter(arr, obj_n, []) for v, e, face, m, fact, c in zip(vec(verts), vec(edges), vec(faces), vec(e_mask), vec(factor), vec(cuts)): if not all((v, e)): break new_faces = list(face) faces_per_edge = defaultdict(list) for face_idx, f in enumerate(new_faces): for i, j in zip(f, rotate_list(f)): faces_per_edge[(i, j)].append((i, False, face_idx)) faces_per_edge[(j, i)].append((j, True, face_idx)) def insert_after(_face, _vert_idx, _new_vert_idx): idx = _face.index(_vert_idx) _face.insert(idx + 1, _new_vert_idx) def insert_before(_face, _vert_idx, _new_vert_idx): idx = _face.index(_vert_idx) _face.insert(idx, _new_vert_idx) # sanitize the input input_f = list(map(lambda _f: min(1, max(0, _f)), fact)) counts = repeat_last_for_length(c, len(e)) mask = repeat_last_for_length(m, len(e)) params = match_long_repeat([e, mask, input_f, counts]) offset = len(v) new_verts = list(v) new_edges = [] i = 0 for edge, ok, factor, count in zip(*params): if not ok: new_edges.append(edge) continue i0 = edge[0] i1 = edge[1] v0 = v[i0] v1 = v[i1] if self.mode == 'MIRROR': factor = factor / 2 vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) vx = v0[0] * factor + v1[0] * (1 - factor) vy = v0[1] * factor + v1[1] * (1 - factor) vz = v0[2] * factor + v1[2] * (1 - factor) vb = [vx, vy, vz] new_verts.append(vb) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, offset + i + 1]) # va - vb new_edges.append([offset + i + 1, i1]) # vb - v1 for vert_idx, before, face_idx in faces_per_edge[tuple( edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) insert_before(new_faces[face_idx], offset + i, offset + i + 1) else: insert_after(new_faces[face_idx], vert_idx, offset + i) insert_after(new_faces[face_idx], offset + i, offset + i + 1) i = i + 2 elif self.mode == 'SIMPLE': vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, i1]) # va - v1 for vert_idx, before, face_idx in faces_per_edge[tuple( edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) else: insert_after(new_faces[face_idx], vert_idx, offset + i) i = i + 1 else: # MULTI if count > 0: new_vert_idxs = [] j = offset + i for p in np.linspace(0.0, 1.0, num=count + 1, endpoint=False)[1:]: vx = v0[0] * (1 - p) + v1[0] * p vy = v0[1] * (1 - p) + v1[1] * p vz = v0[2] * (1 - p) + v1[2] * p va = [vx, vy, vz] new_verts.append(va) new_vert_idxs.append(j) j += 1 if new_vert_idxs: vert_idxs = [i0] + new_vert_idxs[:] edges = list(zip(vert_idxs, vert_idxs[1:])) edges.append((vert_idxs[-1], i1)) new_edges.extend(edges) for vert_idx, before, face_idx in faces_per_edge[ tuple(edge)]: prev_vert_idx = vert_idx for new_vert_idx in new_vert_idxs: if before: insert_before(new_faces[face_idx], prev_vert_idx, new_vert_idx) else: insert_after(new_faces[face_idx], prev_vert_idx, new_vert_idx) prev_vert_idx = new_vert_idx else: new_edges.append(edge) i = i + count out_v.append(new_verts) out_e.append(new_edges) out_f.append(new_faces) self.outputs['Vertices'].sv_set(out_v) self.outputs['Edges'].sv_set(out_e) self.outputs['Faces'].sv_set(out_f)
def process(self): new_faces = list(node.inputs.faces) faces_per_edge = defaultdict(list) for face_idx, face in enumerate(new_faces): for i, j in zip(face, rotate_list(face)): faces_per_edge[(i, j)].append((i, False, face_idx)) faces_per_edge[(j, i)].append((j, True, face_idx)) def insert_after(face, vert_idx, new_vert_idx): idx = face.index(vert_idx) face.insert(idx + 1, new_vert_idx) def insert_before(face, vert_idx, new_vert_idx): idx = face.index(vert_idx) face.insert(idx, new_vert_idx) # sanitize the input input_f = list( map(lambda factor: min(1, max(0, factor)), node.inputs.factors)) counts = repeat_last_for_length(node.inputs.count, len(node.inputs.edges)) mask = repeat_last_for_length(node.inputs.mask, len(node.inputs.edges)) params = match_long_repeat([node.inputs.edges, mask, input_f, counts]) offset = len(node.inputs.verts) new_verts = list(node.inputs.verts) new_edges = [] i = 0 for edge, ok, factor, count in zip(*params): if not ok: new_edges.append(edge) continue i0 = edge[0] i1 = edge[1] v0 = node.inputs.verts[i0] v1 = node.inputs.verts[i1] if node.props.mode == 'MIRROR': factor = factor / 2 vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) vx = v0[0] * factor + v1[0] * (1 - factor) vy = v0[1] * factor + v1[1] * (1 - factor) vz = v0[2] * factor + v1[2] * (1 - factor) vb = [vx, vy, vz] new_verts.append(vb) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, offset + i + 1]) # va - vb new_edges.append([offset + i + 1, i1]) # vb - v1 for vert_idx, before, face_idx in faces_per_edge[tuple(edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) insert_before(new_faces[face_idx], offset + i, offset + i + 1) else: insert_after(new_faces[face_idx], vert_idx, offset + i) insert_after(new_faces[face_idx], offset + i, offset + i + 1) i = i + 2 elif node.props.mode == 'SIMPLE': vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, i1]) # va - v1 for vert_idx, before, face_idx in faces_per_edge[tuple(edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) else: insert_after(new_faces[face_idx], vert_idx, offset + i) i = i + 1 else: # MULTI if count > 0: new_vert_idxs = [] j = offset + i for p in np.linspace(0.0, 1.0, num=count + 1, endpoint=False)[1:]: vx = v0[0] * (1 - p) + v1[0] * p vy = v0[1] * (1 - p) + v1[1] * p vz = v0[2] * (1 - p) + v1[2] * p va = [vx, vy, vz] new_verts.append(va) new_vert_idxs.append(j) j += 1 if new_vert_idxs: vert_idxs = [i0] + new_vert_idxs[:] edges = list(zip(vert_idxs, vert_idxs[1:])) edges.append((vert_idxs[-1], i1)) new_edges.extend(edges) for vert_idx, before, face_idx in faces_per_edge[tuple( edge)]: prev_vert_idx = vert_idx for new_vert_idx in new_vert_idxs: if before: insert_before(new_faces[face_idx], prev_vert_idx, new_vert_idx) else: insert_after(new_faces[face_idx], prev_vert_idx, new_vert_idx) prev_vert_idx = new_vert_idx else: new_edges.append(edge) i = i + count node.outputs.verts = new_verts node.outputs.edges = new_edges node.outputs.faces = new_faces
def process(self): verts = self.inputs['Vertices'].sv_get(default=[]) edges = self.inputs['Edges'].sv_get(default=[]) faces = self.inputs['Faces'].sv_get(default=[]) e_mask = self.inputs['EdgeMask'].sv_get(deepcopy=False, default=[]) factor = self.inputs['Factor'].sv_get(deepcopy=False) obj_n = max(len(verts), len(e_mask), len(factor)) out_v = [] out_e = [] out_f = [] def vec(arr): return fixed_iter(arr, obj_n, []) def insert_after(_face, _vert_idx, _new_vert_idx): idx = _face.index(_vert_idx) _face.insert(idx + 1, _new_vert_idx) def insert_before(_face, _vert_idx, _new_vert_idx): idx = _face.index(_vert_idx) _face.insert(idx, _new_vert_idx) for v, e, face, m, fact in zip(vec(verts), vec(edges), vec(faces), vec(e_mask), vec(factor)): if not all((v, e)): break new_faces = list(face) faces_per_edge = defaultdict(list) for face_idx, f in enumerate(new_faces): for i, j in zip(f, rotate_list(f)): faces_per_edge[(i, j)].append((i, False, face_idx)) faces_per_edge[(j, i)].append((j, True, face_idx)) # sanitize the input input_f = list(map(lambda _f: min(1, max(0, _f)), fact)) mask = repeat_last_for_length(m, len(e)) params = match_long_repeat([e, mask, input_f]) offset = len(v) new_verts = list(v) new_edges = [] i = 0 for edge, ok, factor in zip(*params): if not ok: new_edges.append(edge) continue i0 = edge[0] i1 = edge[1] v0 = v[i0] v1 = v[i1] if self.mirror: factor = factor / 2 vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) vx = v0[0] * factor + v1[0] * (1 - factor) vy = v0[1] * factor + v1[1] * (1 - factor) vz = v0[2] * factor + v1[2] * (1 - factor) vb = [vx, vy, vz] new_verts.append(vb) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, offset + i + 1]) # va - vb new_edges.append([offset + i + 1, i1]) # vb - v1 for vert_idx, before, face_idx in faces_per_edge[tuple( edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) insert_before(new_faces[face_idx], offset + i, offset + i + 1) else: insert_after(new_faces[face_idx], vert_idx, offset + i) insert_after(new_faces[face_idx], offset + i, offset + i + 1) i = i + 2 else: vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, i1]) # va - v1 for vert_idx, before, face_idx in faces_per_edge[tuple( edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) else: insert_after(new_faces[face_idx], vert_idx, offset + i) i = i + 1 out_v.append(new_verts) out_e.append(new_edges) out_f.append(new_faces) self.outputs['Vertices'].sv_set(out_v) self.outputs['Edges'].sv_set(out_e) self.outputs['Faces'].sv_set(out_f)
def process(self): new_faces = list(node.inputs.faces) faces_per_edge = defaultdict(list) for face_idx, face in enumerate(new_faces): for i, j in zip(face, rotate_list(face)): faces_per_edge[(i, j)].append((i, False, face_idx)) faces_per_edge[(j, i)].append((j, True, face_idx)) def insert_after(face, vert_idx, new_vert_idx): idx = face.index(vert_idx) face.insert(idx + 1, new_vert_idx) def insert_before(face, vert_idx, new_vert_idx): idx = face.index(vert_idx) face.insert(idx, new_vert_idx) # sanitize the input input_f = list( map(lambda factor: min(1, max(0, factor)), node.inputs.factors)) mask = repeat_last_for_length(node.inputs.mask, len(node.inputs.edges)) params = match_long_repeat([node.inputs.edges, mask, input_f]) offset = len(node.inputs.verts) new_verts = list(node.inputs.verts) new_edges = [] i = 0 for edge, ok, factor in zip(*params): if not ok: new_edges.append(edge) continue i0 = edge[0] i1 = edge[1] v0 = node.inputs.verts[i0] v1 = node.inputs.verts[i1] if node.props.mirror: factor = factor / 2 vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) vx = v0[0] * factor + v1[0] * (1 - factor) vy = v0[1] * factor + v1[1] * (1 - factor) vz = v0[2] * factor + v1[2] * (1 - factor) vb = [vx, vy, vz] new_verts.append(vb) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, offset + i + 1]) # va - vb new_edges.append([offset + i + 1, i1]) # vb - v1 for vert_idx, before, face_idx in faces_per_edge[tuple(edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) insert_before(new_faces[face_idx], offset + i, offset + i + 1) else: insert_after(new_faces[face_idx], vert_idx, offset + i) insert_after(new_faces[face_idx], offset + i, offset + i + 1) i = i + 2 else: vx = v0[0] * (1 - factor) + v1[0] * factor vy = v0[1] * (1 - factor) + v1[1] * factor vz = v0[2] * (1 - factor) + v1[2] * factor va = [vx, vy, vz] new_verts.append(va) new_edges.append([i0, offset + i]) # v0 - va new_edges.append([offset + i, i1]) # va - v1 for vert_idx, before, face_idx in faces_per_edge[tuple(edge)]: if before: insert_before(new_faces[face_idx], vert_idx, offset + i) else: insert_after(new_faces[face_idx], vert_idx, offset + i) i = i + 1 node.outputs.verts = new_verts node.outputs.edges = new_edges node.outputs.faces = new_faces