def process(self): if not self.outputs[0].is_linked: return X_ = self.inputs['pols'].sv_get() X = dataCorrect(X_) result = polygons_to_edges(X, self.unique_edges) self.outputs['edgs'].sv_set(result)
def polygons_to_edges_np(obj, unique_edges=False, output_numpy=False): result = [] for pols in obj: regular_mesh = True try: np_pols = array(pols, dtype=int32) except ValueError: regular_mesh = False if not regular_mesh: if output_numpy: result.append(concatenate([pol_to_edges(p) for p in pols])) else: result.append(polygons_to_edges([pols], unique_edges)[0]) else: edges = empty(list(np_pols.shape) + [2], 'i') edges[:, :, 0] = np_pols edges[:, 1:, 1] = np_pols[:, :-1] edges[:, 0, 1] = np_pols[:, -1] edges = edges.reshape(-1, 2) if output_numpy: if unique_edges: result.append(unique(sort(edges), axis=0)) else: result.append(edges) else: if unique_edges: result.append(unique(sort(edges), axis=0).tolist()) else: result.append(edges.tolist()) return result
def get_delaunay_triangulation(verts_in): pt_list = [Site(pt[0], pt[1]) for pt in verts_in] res = computeDelaunayTriangulation(pt_list) polys_in = [tri for tri in res if -1 not in tri] #all faces hase normals -Z, should be reversed polys_in = [pol[::-1] for pol in polys_in] edges_in = polygons_to_edges([polys_in], unique_edges=True)[0] return edges_in, polys_in
def process(self): if not self.outputs[0].is_linked: return polygons_ = self.inputs['pols'].sv_get(deepcopy=False) polygons = dataCorrect_np(polygons_) if self.output_numpy or isinstance(polygons[0], ndarray) or self.regular_pols: result = polygons_to_edges_np(polygons, self.unique_edges, self.output_numpy) else: result = polygons_to_edges(polygons, self.unique_edges) self.outputs['edgs'].sv_set(result)
def process(self): if not any(socket.is_linked for socket in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get() clipping_s = self.inputs['Clipping'].sv_get() verts_out = [] edges_out = [] faces_out = [] for sites, clipping in zip_long_repeat(vertices_s, clipping_s): if isinstance(clipping, (list, tuple)): clipping = clipping[0] diagram = Voronoi(sites) if self.do_clip: bounds = self.calc_bounds(sites, clipping) if self.out_mode == 'RIDGES': new_verts = diagram.vertices.tolist() new_faces = [e for e in diagram.ridge_vertices if not -1 in e] new_edges = polygons_to_edges([new_faces], True)[0] if self.join: if self.do_clip: new_verts, new_edges, new_faces = self.clip_mesh(bounds, new_verts, new_edges, new_faces, fill=False) verts_out.append(new_verts) edges_out.append(new_edges) faces_out.append(new_faces) else: new_verts, new_edges, new_faces = self.split_ridges(new_verts, new_edges, new_faces) if self.do_clip: new_verts, new_edges, new_faces = self.clip_mesh(bounds, new_verts, new_edges, new_faces, fill=False, iterate=True) verts_out.extend(new_verts) edges_out.extend(new_edges) faces_out.extend(new_faces) else: # REGIONS new_verts, new_edges, new_faces = self.make_regions(diagram) if self.join: new_verts, new_edges, new_faces = mesh_join(new_verts, new_edges, new_faces) new_verts = [new_verts] new_edges = [new_edges] new_faces = [new_faces] if self.do_clip: new_verts, new_edges, new_faces = self.clip_mesh(bounds, new_verts, new_edges, new_faces, fill=True) verts_out.extend(new_verts) edges_out.extend(new_edges) faces_out.extend(new_faces) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Edges'].sv_set(edges_out) self.outputs['Faces'].sv_set(faces_out)
def process(self): if not self.inputs['Vertices'].is_linked: return vertices_s = self.inputs['Vertices'].sv_get(deepcopy=False) edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False) faces_s = self.inputs['Faces'].sv_get(default=[[]], deepcopy=False) verts1_out = [] verts2_out = [] verts_out = [] edges_out = [] for vertices, edges, faces in zip_long_repeat(vertices_s, edges_s, faces_s): new_verts1 = [] new_verts2 = [] if not edges: edges = polygons_to_edges([faces], unique_edges=True)[0] obj_verts = [] obj_edges = [] for i1, i2 in edges: new_verts = [] new_edges = [] if self.sort: if i1 > i2: i1, i2 = i2, i1 v1, v2 = vertices[i1], vertices[i2] new_verts1.append(v1) new_verts2.append(v2) new_verts.append(v1) new_verts.append(v2) new_edges.append([0, 1]) obj_verts.append(new_verts) obj_edges.append(new_edges) if self.separate: verts_out.append(obj_verts) edges_out.append(obj_edges) else: verts_out.extend(obj_verts) edges_out.extend(obj_edges) verts1_out.append(new_verts1) verts2_out.append(new_verts2) self.outputs['Vertex1'].sv_set(verts1_out) self.outputs['Vertex2'].sv_set(verts2_out) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Edges'].sv_set(edges_out)
def process(self): if not any(s.is_linked for s in self.outputs): return verts_out, edges_out, polys_out = [], [], [] params = self.get_data() get_edges = self.outputs['Edges'].is_linked for p in zip(*params): p = match_long_repeat(p) for p2 in zip(*p): size, vTrunc, eTrunc = p2 verts, faces = createSolid(self.source, vTrunc, eTrunc, self.dual, self.snub) # resize to normal size, or if keepSize, make sure all verts are of length 'size' if self.keepSize: rad = size / verts[-1 if self.dual else 0].length else: rad = size verts = [list(i * rad) for i in verts] verts_out.append(verts) polys_out.append(faces) if get_edges: edges_out.append( polygons_to_edges([faces], unique_edges=True)[0]) if self.outputs['Vertices'].is_linked: self.outputs['Vertices'].sv_set(verts_out) if get_edges: self.outputs['Edges'].sv_set(edges_out) if self.outputs['Polygons'].is_linked: self.outputs['Polygons'].sv_set(polys_out)
def order(verts, edges, verts_o, k): for i in edges: if k in i: # this is awesome !! k = i[int(not i.index(k))] verts_o.append(verts[k]) return k, i return False, False if verts_A and verts_B and edges_A and edges_B: # pols2edges if len(edges_A[0][0]) > 2: edges_A = polygons_to_edges(edges_A, unique_edges=True) if len(edges_B[0][0]) > 2: edges_B = polygons_to_edges(edges_B, unique_edges=True) # ordering sort edges chain def ordering(in_verts, in_edges): ed = 1 vout = [] for edges, verts in zip(in_edges, in_verts): verts_o = [] k = 0 while True: k, ed = order(verts, edges, verts_o, k) if ed: edges.remove(ed) if not ed:
def pols_edges(obj, unique_edges=False): return polygons_to_edges(obj, unique_edges)
def process(self): verts = self.inputs['Vertices'].sv_get() if self.inputs['PolyEdge'].is_linked: poly_edge = self.inputs['PolyEdge'].sv_get() poly_in = True else: poly_in = False poly_edge = repeat_last([[]]) verts_out = [] poly_edge_out = [] item_order = [] poly_output = poly_in and self.outputs['PolyEdge'].is_linked order_output = self.outputs['Item order'].is_linked vert_output = self.outputs['Vertices'].is_linked if not any((vert_output, order_output, poly_output)): return if self.mode == 'XYZ': # should be user settable op_order = [(0, self.reverse_x), (1, self.reverse_y), (2, self.reverse_z)] for v, p in zip(verts, poly_edge): s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) for item_index, rev in op_order: s_v = sorted(s_v, key=itemgetter(item_index), reverse=rev) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) elif self.mode == 'AXYZ': for v, p in zip(verts, poly_edge): matrix = linear_approximation( v).most_similar_plane().get_matrix().inverted() s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) def key(item): x, y, z = matrix @ Vector(item[:3]) if self.reverse_x: x = -x if self.reverse_y: y = -y if self.reverse_z: z = -z return x, y, z # def by_axis(i): # def key(item): # v = matrix @ Vector(item[:3]) # return v[i] # return key s_v = sorted(s_v, key=key) # for i in [2,1,0]: # s_v = sorted(s_v, key=by_axis(i)) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) elif self.mode == 'ADIR': for v, p in zip(verts, poly_edge): direction = linear_approximation( v).most_similar_line().direction s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) def key(item): return Vector(item[:3]).dot(direction) s_v = sorted(s_v, key=key) if self.reverse: s_v = reversed(s_v) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) elif self.mode == 'ACYL': for v, p in zip(verts, poly_edge): data = linear_approximation(v) matrix = data.most_similar_plane().get_matrix().inverted() center = Vector(data.center) s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) def key(item): v = matrix @ (Vector(item[:3]) - center) rho, phi, z = to_cylindrical(v) return (phi, z, rho) s_v = sorted(s_v, key=key) if self.reverse: s_v = reversed(s_v) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'DIST': base_points = self.inputs['Base Point'].sv_get() bp_iter = repeat_last(base_points[0]) for v, p, v_base in zip(verts, poly_edge, bp_iter): s_v = sorted(((v_c, i) for i, v_c in enumerate(v)), key=lambda v: distK(v[0], v_base)) verts_out.append([vert[0] for vert in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'AXIS': if self.inputs['Mat'].is_linked: mat = Matrix_generate(self.inputs['Mat'].sv_get()) else: mat = [Matrix.Identity(4)] mat_iter = repeat_last(mat) def f(axis, q): if axis.dot(q.axis) > 0: return q.angle else: return -q.angle for v, p, m in zip(Vector_generate(verts), poly_edge, mat_iter): axis = m @ Vector((0, 0, 1)) axis_norm = m @ Vector((1, 0, 0)) base_point = m @ Vector((0, 0, 0)) intersect_d = [ intersect_point_line(v_c, base_point, axis) for v_c in v ] rotate_d = [ f(axis, (axis_norm + v_l[0]).rotation_difference(v_c)) for v_c, v_l in zip(v, intersect_d) ] s_v = ((data[0][1], data[1], i) for i, data in enumerate(zip(intersect_d, rotate_d))) s_v = sorted(s_v, key=itemgetter(0, 1)) verts_out.append([v[i[-1]].to_tuple() for i in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'USER': if self.inputs['Index Data'].is_linked: index = self.inputs['Index Data'].sv_get() else: return for v, p, i in zip(verts, poly_edge, index): s_v = sorted([(data[0], data[1], i) for i, data in enumerate(zip(i, v))], key=itemgetter(0)) verts_out.append([obj[1] for obj in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([[v_index[k] for k in pe] for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'CONNEX': if self.inputs['PolyEdge'].is_linked: edges = self.inputs['PolyEdge'].sv_get() for v, p in zip(verts, edges): pols = [] if len(p[0]) > 2: pols = [p[:]] p = polygons_to_edges([p], True)[0] vect_new, pol_edge_new, index_new = sort_vertices_by_connexions( v, p, self.limit_mode) if len(pols) > 0: new_pols = [] for pol in pols[0]: new_pol = [] for i in pol: new_pol.append(index_new.index(i)) new_pols.append(new_pol) pol_edge_new = [new_pols] verts_out.append(vect_new) poly_edge_out.append(pol_edge_new) item_order.append(index_new) if vert_output: self.outputs['Vertices'].sv_set(verts_out) if poly_output: self.outputs['PolyEdge'].sv_set(poly_edge_out) if order_output: self.outputs['Item order'].sv_set(item_order)
def edges_relax(vertices, edges, faces, iterations, k, mask=None, method=NONE, target=AVERAGE, skip_boundary=True, use_axes={0,1,2}): """ supported shape preservation methods: NONE, NORMAL, BVH """ def do_iteration(bvh, bm, verts): verts = np.asarray(verts) v1s = verts[edges[:,0]] v2s = verts[edges[:,1]] edge_vecs = v2s - v1s edge_lens = np.linalg.norm(edge_vecs, axis=1) if target == MINIMUM: target_len = np.min(edge_lens) elif target == MAXIMUM: target_len = np.max(edge_lens) elif target == AVERAGE: target_len = np.mean(edge_lens) else: raise Exception("Unsupported target edge length type") forces = defaultdict(lambda: np.zeros((3,))) counts = defaultdict(int) for edge_idx, (v1_idx, v2_idx) in enumerate(edges): edge_vec = edge_vecs[edge_idx] edge_len = edge_lens[edge_idx] d_len = (edge_len - target_len)/2.0 dv1 = d_len * edge_vec dv2 = - d_len * edge_vec forces[v1_idx] += dv1 forces[v2_idx] += dv2 counts[v1_idx] += 1 counts[v2_idx] += 1 target_verts = verts.copy() for v_idx in range(len(verts)): if skip_boundary and bm.verts[v_idx].is_boundary: continue if mask is not None and not mask[v_idx]: continue count = counts[v_idx] if count: forces[v_idx] /= count target_verts[v_idx] += k*forces[v_idx] if method == NONE: verts_out = target_verts.tolist() elif method == NORMAL: verts_out = [] for bm_vert in bm.verts: normal = bm_vert.normal dv = mathutils.Vector(target_verts[bm_vert.index]) - bm_vert.co dv = dv - dv.project(normal) new_vert = tuple(bm_vert.co + dv) verts_out.append(new_vert) elif method == BVH: verts_out = [] for vert in target_verts: new_vert, normal, idx, dist = bvh.find_nearest(vert) verts_out.append(tuple(new_vert)) else: raise Exception("Unsupported shape preservation method") return map_mask_axes(verts, verts_out, use_axes) if not edges or not edges[0]: edges = polygons_to_edges([faces], unique_edges=True)[0] edges = np.array(edges) if mask is not None: mask = repeat_last_for_length(mask, len(vertices)) bvh = BVHTree.FromPolygons(vertices, faces) for i in range(iterations): bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True) vertices = do_iteration(bvh, bm, vertices) bm.free() return vertices
def make_bevel(self, curve, bevel_verts, bevel_edges, bevel_faces, taper, twist, steps): spline = self.build_spline(curve, self.bevel_mode, self.is_cyclic) t_values = np.linspace(0.0, 1.0, num = steps) if self.is_cyclic: t_values = t_values[:-1] if self.flip_curve: t_for_curve = 1.0 - t_values else: t_for_curve = t_values if self.flip_taper: t_for_taper = 1.0 - t_values else: t_for_taper = t_values if self.flip_twist: t_for_twist = 1.0 - t_values else: t_for_twist = t_values spline_vertices = [Vector(v) for v in spline.eval(t_for_curve).tolist()] spline_tangents = [Vector(v) for v in spline.tangent(t_for_curve, h=self.tangent_precision).tolist()] taper_values = [self.get_taper_scale(v) for v in taper.eval(t_for_taper).tolist()] twist_values = [self.get_twist_value(v) for v in twist.eval(t_for_twist).tolist()] if bevel_faces: bevel_faces = ensure_nesting_level(bevel_faces, 2) if not bevel_edges and bevel_faces: bevel_edges = polygons_to_edges([bevel_faces], True)[0] mesh = bmesh.new() prev_level_vertices = None first_level_vertices = None for spline_vertex, spline_tangent, taper_value, twist_value in zip(spline_vertices, spline_tangents, taper_values, twist_values): # Scaling and rotation matrix scale_x, scale_y = taper_value matrix = self.get_matrix(spline_tangent, twist_value, scale_x, scale_y) level_vertices = [] for bevel_vertex in bevel_verts: new_vertex = matrix @ Vector(bevel_vertex) + spline_vertex level_vertices.append(mesh.verts.new(new_vertex)) if prev_level_vertices is not None: for i,j in bevel_edges: v1 = prev_level_vertices[i] v2 = level_vertices[i] v3 = level_vertices[j] v4 = prev_level_vertices[j] mesh.faces.new([v4, v3, v2, v1]) if first_level_vertices is None: first_level_vertices = level_vertices prev_level_vertices = level_vertices if not self.is_cyclic: if self.cap_start: if not bevel_faces: mesh.faces.new(list(reversed(first_level_vertices))) else: for face in bevel_faces: cap = [first_level_vertices[i] for i in reversed(face)] mesh.faces.new(cap) if self.cap_end and prev_level_vertices is not None: if not bevel_faces: mesh.faces.new(prev_level_vertices) else: for face in bevel_faces: cap = [prev_level_vertices[i] for i in face] mesh.faces.new(cap) else: for i,j in bevel_edges: v1 = first_level_vertices[i] v2 = prev_level_vertices[i] v3 = prev_level_vertices[j] v4 = first_level_vertices[j] mesh.faces.new([v1, v2, v3, v4]) mesh.verts.index_update() mesh.verts.ensure_lookup_table() mesh.faces.index_update() mesh.edges.index_update() return mesh
def faces_relax(vertices, edges, faces, iterations, k, mask=None, method=NONE, target=AVERAGE, skip_boundary=True, use_axes={0,1,2}): """ supported shape preservation methods: NONE, NORMAL, BVH """ def do_iteration(bvh, bm): areas = np.array([face.calc_area() for face in bm.faces]) vert_cos = np.array([tuple(vert.co) for vert in bm.verts]) if target == MINIMUM: target_area = areas.min() elif target == MAXIMUM: target_area = areas.max() elif target == AVERAGE: target_area = areas.mean() else: raise Exception("Unsupported target face area type") forces = defaultdict(lambda: np.zeros((3,))) counts = defaultdict(int) for bm_face in bm.faces: face_vert_idxs = [vert.index for vert in bm_face.verts] face_verts = vert_cos[face_vert_idxs] mean = face_verts.mean(axis=0) face_verts_0 = face_verts - mean src_area = areas[bm_face.index] scale = sqrt(target_area / src_area) dvs = (scale - 1) * face_verts_0 for vert_idx, dv in zip(face_vert_idxs, dvs): forces[vert_idx] += dv counts[vert_idx] += 1 target_verts = vert_cos.copy() for bm_vert in bm.verts: idx = bm_vert.index if skip_boundary and bm_vert.is_boundary: continue if mask is not None and not mask[idx]: continue count = counts[idx] if count: forces[idx] /= count force = forces[idx] target_verts[idx] += k*force if method == NONE: verts_out = target_verts.tolist() elif method == NORMAL: verts_out = [] for bm_vert in bm.verts: idx = bm_vert.index dv = mathutils.Vector(target_verts[idx]) - bm_vert.co normal = bm_vert.normal dv = dv - dv.project(normal) new_vert = tuple(bm_vert.co + dv) verts_out.append(new_vert) elif method == BVH: verts_out = [] for bm_vert in bm.verts: new_vert, normal, idx, dist = bvh.find_nearest(bm_vert.co) verts_out.append(tuple(new_vert)) else: raise Exception("Unsupported shape preservation method") return map_mask_axes(vert_cos, verts_out, use_axes) if mask is not None: mask = repeat_last_for_length(mask, len(vertices)) if not edges or not edges[0]: edges = polygons_to_edges([faces], unique_edges=True)[0] bvh = BVHTree.FromPolygons(vertices, faces) for i in range(iterations): bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True) vertices = do_iteration(bvh, bm) bm.free() return vertices
def process(self): if 'vecLine' in self.inputs and \ 'vecPlane' in self.inputs and \ 'edgPlane' in self.inputs: print(self.name, 'is starting') if self.inputs['vecLine'].links and \ self.inputs['vecPlane'].links and \ self.inputs['edgPlane'].links: if self.bindCircle: circle = [ (Vector((sin(radians(i)),cos(radians(i)),0))*self.circle_rad)/4 \ for i in range(0,360,30) ] vec = self.inputs['vecLine'].sv_get() vecplan = self.inputs['vecPlane'].sv_get() edgplan = self.inputs['edgPlane'].sv_get() if len(edgplan[0][0]) > 2: edgplan = polygons_to_edges(edgplan) thick = self.inputs['thick'].sv_get()[0][0] threshold_coplanar = 0.005 sinuso60 = 0.8660254037844386 sinuso60_minus = 0.133974596 sinuso30 = 0.5 sinuso45 = 0.7071067811865475 thick_2 = thick/2 thick_3 = thick/3 thick_6 = thick/6 threshold = self.threshold if 'vecContr' in self.inputs and self.inputs['vecContr'].links: vecont = self.inputs['vecContr'].sv_get() #edgcont = self.inputs['edgContr'].sv_get() vec_cont = Vector_generate(vecont) loc_cont = [ [ i[0] ] for i in vec_cont ] norm_cont = [ [ NM(i[0],i[len(i)//2], i[-1]) ] for i in vec_cont ] # довести до ума else: vec_cont = [] if 'vecTube' in self.inputs and self.inputs['vecTube'].links: vectube = self.inputs['vecTube'].sv_get() vec_tube = Vector_generate(vectube) tube_radius = self.inputs['radTube'].sv_get()[0][0] circle_tube = [ (Vector((sin(radians(i)),cos(radians(i)),0))*tube_radius) \ for i in range(0,360,15) ] else: vec_tube = [] outeup = [] outelo = [] vupper = [] vlower = [] centers = [] vec_ = Vector_generate(vec) vecplan_ = Vector_generate(vecplan) for centersver, vecp, edgp in zip(vecplan,vecplan_,edgplan): tubes_flag_bed_solution_i_know = False newinds1 = [list(e) for e in edgp] newinds2 = newinds1.copy() vupperob = vecp.copy() vlowerob = vecp.copy() deledges1 = [] deledges2 = [] # to define bounds x = [i[0] for i in vecp] y = [i[1] for i in vecp] z = [i[2] for i in vecp] m1x,m2x,m1y,m2y,m1z,m2z = max(x), min(x), max(y), min(y), max(z), min(z) l = Vector((sum(x)/len(x),sum(y)/len(y),sum(z)/len(z))) n_select = [vecp[0],vecp[len(vecp)//2], vecp[-1]] # довести до ума n_select.sort(key=lambda x: sum(x[:]), reverse=False) n_ = NM(n_select[0],n_select[1],n_select[2]) n_.normalize() # а виновта ли нормаль? if n_[0] < 0: n = n_ * -1 else: n = n_ cen = [sum(i) for i in zip(*centersver)] centers.append(Vector(cen)/len(centersver)) k = 0 lenvep = len(vecp) # KDtree collections closest to join edges to sockets tree = KDT.KDTree(lenvep) for i,v in enumerate(vecp): tree.insert(v,i) tree.balance() # vertical edges iterations # every edge is object - two points, one edge for v in vec_: if not v: continue # sort vertices by Z value # find two vertices - one lower, two upper vlist = [v[0],v[1]] vlist.sort(key=lambda x: x[2], reverse=False) # flip if coplanar to enemy plane # flip plane coplanar if vec_cont: fliped = self.get_coplanar(v[0], loc_cont,norm_cont, vec_cont) else: fliped = False shortedge = (vlist[1]-vlist[0]).length if fliped: two, one = vlist else: one, two = vlist # coplanar to owner cop = abs(D2P(one,l,n)) # defining bounds inside = one[0]<m1x and one[0]>m2x and one[1]<m1y and one[1]>m2y \ and one[2]<=m1z and one[2]>=m2z # if in bounds and coplanar do: #print(self.name,l, cop, inside) if cop < threshold_coplanar and inside and shortedge > thick*threshold: ''' huge calculations. if we can reduce... ''' # find shift for thickness in sockets diry = two - one diry.normalize() # solution for vertical wafel - cool but not in diagonal case # angle = radians(degrees(atan(n.y/n.x))+90) dirx_ = self.rotation_on_axis(diry, n, radians(90)) dirx = dirx_*thick_2 # вектор, индекс, расстояние # запоминаем порядок находим какие удалить рёбра # делаем выборку левая-правая точка nearv_1, near_1 = tree.find(one)[:2] nearv_2, near_2 = tree.find(two)[:2] # indexes of two nearest points # удалить рёбра что мешают спать заодно try: en_0, en_1, de1 = self.calc_indexes(edgp, near_1) deledges1.extend(de1) en_2, en_3, de2 = self.calc_indexes(edgp, near_2) deledges2.extend(de2) except: print('Waffel Wrong crossection node') break # print(vecp, one, dirx, en_0, en_1) # left-right indexes and vectors # с учётом интерполяций по высоте l1, r1, lz1, rz1 = \ self.calc_leftright(vecp, one, dirx, en_0, en_1, thick_2, diry) l2, r2, lz2, rz2 = \ self.calc_leftright(vecp, two, dirx, en_2, en_3, thick_2, diry) # print(left2, right2, l2, r2, lz2, rz2) # средняя точка и её смещение по толщине материала three = (one-two)/2 + two # rounded section if self.rounded: '''рёбра''' # пазы формируем независимо от верх низ # outeob1 = [[lenvep+k+8,lenvep+k],[lenvep+k+1,lenvep+k+2], # [lenvep+k+2,lenvep+k+3],[lenvep+k+3,lenvep+k+4], # [lenvep+k+4,lenvep+k+5],[lenvep+k+5,lenvep+k+6], # [lenvep+k+6,lenvep+k+7],[lenvep+k+7,lenvep+k+8], # [lenvep+k+9,lenvep+k+1]] # outeob2 = [[lenvep+k,lenvep+k+1],[lenvep+k+1,lenvep+k+2], # [lenvep+k+2,lenvep+k+3],[lenvep+k+3,lenvep+k+4], # [lenvep+k+4,lenvep+k+5],[lenvep+k+5,lenvep+k+6], # [lenvep+k+6,lenvep+k+7],[lenvep+k+7,lenvep+k+8], # [lenvep+k+8,lenvep+k+9]] outeob1 = [[lenvep+k+8,lenvep+k]] outeob1.extend([[lenvep+k+i,lenvep+k+i+1] for i in range(1,10,1)]) outeob1.append([lenvep+k+9,lenvep+k+1]) outeob2 = [[lenvep+k+i,lenvep+k+i+1] for i in range(0,10,1)] # наполнение списков lenvep = length(vecp) newinds1.extend([[l1, lenvep+k], [lenvep+k+9, r1]]) newinds2.extend([[l2, lenvep+k+9], [lenvep+k, r2]]) '''Вектора''' round1 = diry*thick_3 round2 = diry*thick_3*sinuso30 round2_= dirx/3 + dirx*(2*sinuso60/3) round3 = diry*thick_3*sinuso60_minus round3_= dirx/3 + dirx*(2*sinuso30/3) round4 = dirx/3 vupperob.extend([lz2, three+round1-dirx, three+round2-round2_, three+round3-round3_, three-round4, three+round4, three+round3+round3_, three+round2+round2_, three+round1+dirx, rz2]) vlowerob.extend([rz1, three-round1-dirx, three-round2-round2_, three-round3-round3_, three-round4, three+round4, three-round3+round3_, three-round2+round2_, three-round1+dirx, lz1]) k += 10 elif self.rounded_outside: '''рёбра вовнешнее''' # пазы формируем независимо от верх низ outeob1 = [[lenvep+k+28,lenvep+k]] outeob1.extend([[lenvep+k+i,lenvep+k+i+1] for i in range(1,30,1)]) outeob1.append([lenvep+k+29,lenvep+k+1]) outeob2 = [[lenvep+k+i,lenvep+k+i+1] for i in range(0,30,1)] # наполнение списков lenvep = length(vecp) newinds1.extend([[l1, lenvep+k], [lenvep+k+29, r1]]) newinds2.extend([[l2, lenvep+k+29], [lenvep+k, r2]]) '''Вектора''' round1 = diry*thick_3 round2 = diry*thick_3*sinuso30 round2_= dirx/3 + dirx*(2*sinuso60/3) round3 = diry*thick_3*sinuso60_minus round3_= dirx/3 + dirx*(2*sinuso30/3) round4 = dirx/3 vupperob.extend([lz2, three+round1-dirx, three+round2-round2_, three+round3-round3_, three-round4, three+round4, three+round3+round3_, three+round2+round2_, three+round1+dirx, rz2]) vlowerob.extend([rz1, three-round1-dirx, three-round2-round2_, three-round3-round3_, three-round4, three+round4, three-round3+round3_, three-round2+round2_, three-round1+dirx, lz1]) k += 10 # streight section else: '''рёбра''' # пазы формируем независимо от верх низ outeob1 = [[lenvep+k,lenvep+k+1],[lenvep+k+1,lenvep+k+2],[lenvep+k+2,lenvep+k+3]] outeob2 = [[lenvep+k,lenvep+k+1],[lenvep+k+1,lenvep+k+2],[lenvep+k+2,lenvep+k+3]] # наполнение списков lenvep = length(vecp) newinds1.extend([[l1, lenvep+k], [lenvep+k+3, r1]]) newinds2.extend([[l2, lenvep+k+3], [lenvep+k, r2]]) '''Вектора''' vupperob.extend([lz2, three-dirx, three+dirx, rz2]) vlowerob.extend([rz1, three+dirx, three-dirx, lz1]) k += 4 newinds1.extend(outeob1) newinds2.extend(outeob2) # circles to bing panels section if self.bindCircle: CP = self.circl_place if CP == 'Midl': crcl_cntr = IL2P(one, two, Vector((0,0,0)), Vector((0,0,-1))) elif CP == 'Up' and not fliped: crcl_cntr = two - diry*self.circle_rad*2 elif CP == 'Down' and not fliped: crcl_cntr = one + diry*self.circle_rad*2 elif CP == 'Up' and fliped: crcl_cntr = one + diry*self.circle_rad*2 elif CP == 'Down' and fliped: crcl_cntr = two - diry*self.circle_rad*2 # forgot howto 'else' in line iteration? outeob1 = [ [lenvep+k+i,lenvep+k+i+1] for i in range(0,11) ] outeob1.append([lenvep+k,lenvep+k+11]) outeob2 = [ [lenvep+k+i,lenvep+k+i+1] for i in range(12,23) ] outeob2.append([lenvep+k+12,lenvep+k+23]) newinds1.extend(outeob1+outeob2) newinds2.extend(outeob1+outeob2) mat_rot_cir = n.rotation_difference(Vector((0,0,1))).to_matrix().to_4x4() circle_to_add_1 = [vecir*mat_rot_cir+crcl_cntr+ \ dirx_*self.circle_rad for vecir in circle ] circle_to_add_2 = [vecir*mat_rot_cir+crcl_cntr- \ dirx_*self.circle_rad for vecir in circle ] vupperob.extend(circle_to_add_1+circle_to_add_2) vlowerob.extend(circle_to_add_1+circle_to_add_2) k += 24 # TUBE section if vec_tube and not tubes_flag_bed_solution_i_know: for v in vec_tube: tubeverlength = len(v) if tubeverlength == 2: crcl_cntr = IL2P(v[0], v[1], l, n) if crcl_cntr: inside = crcl_cntr[0]<m1x and crcl_cntr[0]>m2x and crcl_cntr[1]<m1y \ and crcl_cntr[1]>m2y and crcl_cntr[2]<=m1z and crcl_cntr[2]>=m2z if inside: outeob = [ [lenvep+k+i,lenvep+k+i+1] for i in range(0,23) ] outeob.append([lenvep+k,lenvep+k+23]) newinds1.extend(outeob) newinds2.extend(outeob) mat_rot_cir = n.rotation_difference(Vector((0,0,1))).to_matrix().to_4x4() circle_to_add = [ vecir*mat_rot_cir+crcl_cntr for vecir in circle_tube ] vupperob.extend(circle_to_add) vlowerob.extend(circle_to_add) k += 24 else: tubeshift = tubeverlength//2 crcl_cntr = IL2P(v[0], v[tubeshift], l, n) if crcl_cntr: inside = crcl_cntr[0]<m1x and crcl_cntr[0]>m2x and crcl_cntr[1]<m1y \ and crcl_cntr[1]>m2y and crcl_cntr[2]<=m1z and crcl_cntr[2]>=m2z if inside: outeob = [ [lenvep+k+i,lenvep+k+i+1] for i in range(tubeshift-1) ] outeob.append([lenvep+k,lenvep+k+tubeshift-1]) newinds1.extend(outeob) newinds2.extend(outeob) for tubevert in range(tubeshift): tubevert_out = IL2P(v[tubevert], v[tubevert+tubeshift], l, n) vupperob.append(tubevert_out) vlowerob.append(tubevert_out) k += tubeshift tubes_flag_bed_solution_i_know = True elif cop < threshold_coplanar and inside and shortedge <= thick*threshold: vupperob.extend([one,two]) vlowerob.extend([one,two]) newinds1.append([lenvep+k,lenvep+k+1]) newinds2.append([lenvep+k,lenvep+k+1]) k += 2 del tree for e in deledges1: if e in newinds1: newinds1.remove(e) for e in deledges2: if e in newinds2: newinds2.remove(e) if vupperob or vlowerob: outeup.append(newinds2) outelo.append(newinds1) vupper.append(vupperob) vlower.append(vlowerob) vupper = Vector_degenerate(vupper) vlower = Vector_degenerate(vlower) centers = Vector_degenerate([centers]) if 'vert' in self.outputs: if self.out_up_down == 'Up': out = dataCorrect(vupper) else: out = dataCorrect(vlower) self.outputs['vert'].sv_set(out) if 'edge' in self.outputs and self.outputs['edge'].links: if self.out_up_down == 'Up': self.outputs['edge'].sv_set(outeup) else: self.outputs['edge'].sv_set(outelo) if 'centers' in self.outputs and self.outputs['centers'].links: self.outputs['centers'].sv_set(centers) print(self.name, 'is finishing')
def process(self): verts = self.inputs['Vertices'].sv_get() if self.inputs['PolyEdge'].is_linked: poly_edge = self.inputs['PolyEdge'].sv_get() poly_in = True else: poly_in = False poly_edge = repeat_last([[]]) verts_out = [] poly_edge_out = [] item_order = [] poly_output = poly_in and self.outputs['PolyEdge'].is_linked order_output = self.outputs['Item order'].is_linked vert_output = self.outputs['Vertices'].is_linked if not any((vert_output, order_output, poly_output)): return if self.mode == 'XYZ': # should be user settable op_order = [(0, False), (1, False), (2, False)] for v, p in zip(verts, poly_edge): s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v)) for item_index, rev in op_order: s_v = sorted(s_v, key=itemgetter(item_index), reverse=rev) verts_out.append([v[:3] for v in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'DIST': if self.inputs['Base Point'].is_linked: base_points = self.inputs['Base Point'].sv_get() bp_iter = repeat_last(base_points[0]) else: bp = [(0, 0, 0)] bp_iter = repeat_last(bp) for v, p, v_base in zip(verts, poly_edge, bp_iter): s_v = sorted(((v_c, i) for i, v_c in enumerate(v)), key=lambda v: distK(v[0], v_base)) verts_out.append([vert[0] for vert in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'AXIS': if self.inputs['Mat'].is_linked: mat = Matrix_generate(self.inputs['Mat'].sv_get()) else: mat = [Matrix.Identity(4)] mat_iter = repeat_last(mat) def f(axis, q): if axis.dot(q.axis) > 0: return q.angle else: return -q.angle for v, p, m in zip(Vector_generate(verts), poly_edge, mat_iter): axis = m @ Vector((0, 0, 1)) axis_norm = m @ Vector((1, 0, 0)) base_point = m @ Vector((0, 0, 0)) intersect_d = [ intersect_point_line(v_c, base_point, axis) for v_c in v ] rotate_d = [ f(axis, (axis_norm + v_l[0]).rotation_difference(v_c)) for v_c, v_l in zip(v, intersect_d) ] s_v = ((data[0][1], data[1], i) for i, data in enumerate(zip(intersect_d, rotate_d))) s_v = sorted(s_v, key=itemgetter(0, 1)) verts_out.append([v[i[-1]].to_tuple() for i in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append( [list(map(lambda n: v_index[n], pe)) for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'USER': if self.inputs['Index Data'].is_linked: index = self.inputs['Index Data'].sv_get() else: return for v, p, i in zip(verts, poly_edge, index): s_v = sorted([(data[0], data[1], i) for i, data in enumerate(zip(i, v))], key=itemgetter(0)) verts_out.append([obj[1] for obj in s_v]) if poly_output: v_index = {item[-1]: j for j, item in enumerate(s_v)} poly_edge_out.append([[v_index[k] for k in pe] for pe in p]) if order_output: item_order.append([i[-1] for i in s_v]) if self.mode == 'CONNEX': if self.inputs['PolyEdge'].is_linked: edges = self.inputs['PolyEdge'].sv_get() for v, p in zip(verts, edges): pols = [] if len(p[0]) > 2: pols = [p[:]] p = polygons_to_edges([p], True)[0] vect_new, pol_edge_new, index_new = sort_vertices_by_connexions( v, p, self.limit_mode) if len(pols) > 0: new_pols = [] for pol in pols[0]: new_pol = [] for i in pol: new_pol.append(index_new.index(i)) new_pols.append(new_pol) pol_edge_new = [new_pols] verts_out.append(vect_new) poly_edge_out.append(pol_edge_new) item_order.append(index_new) if vert_output: self.outputs['Vertices'].sv_set(verts_out) if poly_output: self.outputs['PolyEdge'].sv_set(poly_edge_out) if order_output: self.outputs['Item order'].sv_set(item_order)
def process(self): n_id = node_id(self) nvBGL.callback_disable(n_id) inputs = self.inputs # end early if not self.activate: return if self.mode == 'Number': if not inputs['Number'].is_linked: return numbers = inputs['Number'].sv_get(default=[[]]) elif self.mode == 'Curve': if not inputs['Curve'].is_linked: return curves = inputs['Curve'].sv_get(default=[[]]) else: if not inputs['Vecs'].is_linked: return vecs = inputs['Vecs'].sv_get(default=[[]]) edges = inputs['Edges'].sv_get(default=[[]]) polygons = inputs['Polygons'].sv_get(default=[[]]) vector_color = inputs['Vector Color'].sv_get(default=[[self.vector_color]]) edge_color = inputs['Edge Color'].sv_get(default=[[self.edge_color]]) poly_color = inputs['Polygon Color'].sv_get(default=[[self.polygon_color]]) seed_set(self.random_seed) x, y, config = self.create_config() config.vector_color = vector_color config.edge_color = edge_color config.poly_color = poly_color config.edges = edges if self.mode == 'Number': config.size = self.drawing_size geom = generate_number_geom(config, numbers) elif self.mode == 'Path': geom = generate_graph_geom(config, vecs) elif self.mode == 'Curve': paths = [] for curve in curves: t_min, t_max = curve.get_u_bounds() ts = np_linspace(t_min, t_max, num=self.curve_samples, dtype=np_float64) paths.append(curve.evaluate_array(ts).tolist()) geom = generate_graph_geom(config, paths) else: config.polygons = polygons if not inputs['Edges'].is_linked and self.edge_toggle: config.edges = polygons_to_edges(polygons, unique_edges=True) geom = generate_mesh_geom(config, vecs) draw_data = { 'mode': 'custom_function', 'tree_name': self.id_data.name[:], 'loc': (x, y), 'custom_function': view_2d_geom, 'args': (geom, config) } nvBGL.callback_enable(n_id, draw_data)
def process(self): if not any(socket.is_linked for socket in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get() edges_s = self.inputs['Edges'].sv_get() faces_s = self.inputs['Faces'].sv_get() vertex_weight_s = self.inputs['VertexWeight'].sv_get() edge_weight_s = self.inputs['EdgeWeight'].sv_get() face_weight_s = self.inputs['FaceWeight'].sv_get() tangent_weight_s = self.inputs['TangentWeight'].sv_get() degree_u_s = self.inputs['DegreeU'].sv_get() degree_v_s = self.inputs['DegreeV'].sv_get() surface_out = [] control_points_out = [] weights_out = [] inputs = zip_long_repeat(vertices_s, edges_s, faces_s, degree_u_s, degree_v_s, vertex_weight_s, edge_weight_s, face_weight_s, tangent_weight_s) for vertices, edges, faces, degree_u, degree_v, vertex_weights, edge_weights, face_weights, tangent_weights in inputs: fullList(degree_u, len(faces)) fullList(degree_v, len(faces)) if not edges: edges = polygons_to_edges([faces], True)[0] fullList(vertex_weights, len(vertices)) fullList(tangent_weights, len(vertices)) fullList(edge_weights, len(edges)) fullList(face_weights, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True, markup_edge_data=True) normals = [vertex.normal for vertex in bm.verts] edge_planes_dict = dict() for edge in bm.edges: edge_v = edge.verts[1].co - edge.verts[0].co edge_c = (edge.verts[0].co + edge.verts[1].co) / 2.0 edge_ort_plane = PlaneEquation.from_normal_and_point( edge_v, edge_c) face_normals = [face.normal for face in edge.link_faces] faces_normal = sum(face_normals, Vector()) projected_faces_normal = edge_ort_plane.projection_of_point( faces_normal) #print("EV: %s, No.sum: %s, Pr.N: %s" % (edge_v, faces_normal, projected_faces_normal)) edge_plane = PlaneEquation.from_normal_and_point( projected_faces_normal, edge_c) edge_planes_dict[(edge.verts[0].index, edge.verts[1].index)] = edge_plane edge_planes_dict[(edge.verts[1].index, edge.verts[0].index)] = edge_plane bm.free() vert_planes = [ PlaneEquation.from_normal_and_point(normal, point) for normal, point in zip(normals, vertices) ] edge_weights_dict = dict() #edge_planes_dict = dict() for (i, j), edge_weight in zip(edges, edge_weights): edge_weights_dict[(i, j)] = edge_weight edge_weights_dict[(j, i)] = edge_weight #edge_planes_dict[(i, j)] = edge_plane #edge_planes_dict[(j, i)] = edge_plane for i, (face, degree_u, degree_v, face_weight) in enumerate( zip(faces, degree_u, degree_v, face_weights)): if len(face) != 4: self.info("Face #%s is not a Quad, skip it", i) continue face_verts = [vertices[i] for i in face] face_planes = [vert_planes[i] for i in face] face_vert_weights = [vertex_weights[i] for i in face] face_tangent_weights = [tangent_weights[i] for i in face] #face_edges = list(zip(face, face[1:])) + [(face[-1], face[0])] #face_edge_weights = [edge_weights_dict[edge] for edge in face_edges] surface, ctrlpts, weights = self.make_surface( face, degree_u, degree_v, face_verts, face_planes, face_vert_weights, face_tangent_weights, face_weight, edge_weights_dict, edge_planes_dict) surface_out.append(surface) control_points_out.append(list(map(tuple, ctrlpts))) weights_out.append(weights) self.outputs['Surfaces'].sv_set(surface_out) self.outputs['ControlPoints'].sv_set(control_points_out) self.outputs['Weights'].sv_set(weights_out)
def process(self): if bpy.app.background: return self.handle_attr_socket() if not (self.id_data.sv_show and self.activate): callback_disable(node_id(self)) return n_id = node_id(self) callback_disable(n_id) inputs = self.inputs # end early if not self.activate: return if not any([inputs['Vertices'].is_linked, inputs['Matrix'].is_linked]): return if inputs['Vertices'].is_linked: vecs = inputs['Vertices'].sv_get(default=[[]]) edges = inputs['Edges'].sv_get(default=[[]]) polygons = inputs['Polygons'].sv_get(default=[[]]) matrix = inputs['Matrix'].sv_get(default=[[]]) vector_color = inputs['Vector Color'].sv_get( default=[[self.vector_color]]) edge_color = inputs['Edge Color'].sv_get( default=[[self.edge_color]]) poly_color = inputs['Polygon Color'].sv_get( default=[[self.polygon_color]]) seed_set(self.random_seed) config = self.create_config() config.vector_color = vector_color config.edge_color = edge_color config.poly_color = poly_color config.edges = edges if self.use_dashed: add_dashed_shader(config) config.polygons = polygons config.matrix = matrix if not inputs['Edges'].is_linked and self.display_edges: config.edges = polygons_to_edges(polygons, unique_edges=True) geom = generate_mesh_geom(config, vecs) draw_data = { 'tree_name': self.id_data.name[:], 'custom_function': view_3d_geom, 'args': (geom, config) } callback_enable(n_id, draw_data) elif inputs['Matrix'].is_linked: matrices = inputs['Matrix'].sv_get(deepcopy=False, default=[Matrix()]) gl_instructions = { 'tree_name': self.id_data.name[:], 'custom_function': draw_matrix, 'args': (matrices, self.matrix_draw_scale) } callback_enable(n_id, gl_instructions)
def voronoi3d_layer(n_src_sites, all_sites, make_regions, do_clip, clipping, skip_added=True): diagram = Voronoi(all_sites) src_sites = all_sites[:n_src_sites] region_verts = dict() region_verts_map = dict() n_sites = n_src_sites if skip_added else len(all_sites) for site_idx in range(n_sites): region_idx = diagram.point_region[site_idx] region = diagram.regions[region_idx] vertices = [tuple(diagram.vertices[i, :]) for i in region] region_verts[site_idx] = vertices region_verts_map[site_idx] = { vert_idx: i for i, vert_idx in enumerate(region) } open_sites = set() region_faces = defaultdict(list) for ridge_idx, sites in enumerate(diagram.ridge_points): site_from, site_to = sites ridge = diagram.ridge_vertices[ridge_idx] if -1 in ridge: open_sites.add(site_from) open_sites.add(site_to) site_from_ok = not skip_added or site_from < n_src_sites site_to_ok = not skip_added or site_to < n_src_sites if make_regions: if site_from_ok: face_from = [region_verts_map[site_from][i] for i in ridge] region_faces[site_from].append(face_from) if site_to_ok: face_to = [region_verts_map[site_to][i] for i in ridge] region_faces[site_to].append(face_to) else: if site_from_ok and site_to_ok: face_from = [region_verts_map[site_from][i] for i in ridge] region_faces[site_from].append(face_from) face_to = [region_verts_map[site_to][i] for i in ridge] region_faces[site_to].append(face_to) verts = [region_verts[i] for i in range(n_sites) if i not in open_sites] faces = [region_faces[i] for i in range(n_sites) if i not in open_sites] empty_faces = [len(f) == 0 for f in faces] verts = [vs for vs, mask in zip(verts, empty_faces) if not mask] faces = [fs for fs, mask in zip(faces, empty_faces) if not mask] edges = polygons_to_edges(faces, True) if not make_regions: verts_n, edges_n, faces_n = [], [], [] for verts_i, edges_i, faces_i in zip(verts, edges, faces): used_verts = set(sum(faces_i, [])) mask = [i in used_verts for i in range(len(verts_i))] verts_i, edges_i, faces_i = mask_vertices(verts_i, edges_i, faces_i, mask) verts_n.append(verts_i) edges_n.append(edges_i) faces_n.append(faces_i) verts, edges, faces = verts_n, edges_n, faces_n if do_clip: verts_n, edges_n, faces_n = [], [], [] bounds = calc_bounds(src_sites, clipping) for verts_i, edges_i, faces_i in zip(verts, edges, faces): bm = bmesh_from_pydata(verts_i, edges_i, faces_i) bmesh_clip(bm, bounds, fill=True) verts_i, edges_i, faces_i = pydata_from_bmesh(bm) bm.free() verts_n.append(verts_i) edges_n.append(edges_i) faces_n.append(faces_i) verts, edges, faces = verts_n, edges_n, faces_n return verts, edges, faces