def get_inputs(self): factor1_s = self.inputs['Factor1'].sv_get() factor2_s = self.inputs['Factor2'].sv_get() factor1_s = ensure_nesting_level(factor1_s, 2) factor2_s = ensure_nesting_level(factor2_s, 2) if self.mode == 'TWO': curve1_s = self.inputs['Curve1'].sv_get() curve2_s = self.inputs['Curve2'].sv_get() if isinstance(curve1_s[0], SvCurve): curve1_s = [curve1_s] if isinstance(curve2_s[0], SvCurve): curve2_s = [curve2_s] for curve1s, curve2s, factor1s, factor2s in zip_long_repeat(curve1_s, curve2_s, factor1_s, factor2_s): for curve1, curve2, factor1, factor2 in zip_long_repeat(curve1s, curve2s, factor1s, factor2s): yield curve1, curve2, factor1, factor2 else: curves_s = self.inputs['Curves'].sv_get() if isinstance(curves_s[0], SvCurve): curves_s = [curves_s] for curves, factor1s, factor2s in zip_long_repeat(curves_s, factor1_s, factor2_s): factor1s = repeat_last_for_length(factor1s, len(curves)) factor2s = repeat_last_for_length(factor2s, len(curves)) for curve1, curve2, factor1, factor2 in zip(curves, curves[1:], factor1s, factor2s): yield curve1, curve2, factor1, factor2 if self.cyclic: yield curves[-1], curves[0], factor1s[-1], factor2s[-1]
def generate_surface(self, solid, field, count, min_r, threshold, field_min, field_max, mask, seed): counts = self.distribute_faces(solid.Faces, count) new_verts = [] mask = repeat_last_for_length(mask, len(solid.Faces)) counts = repeat_last_for_length(counts, len(solid.Faces)) for face, ok, cnt in zip(solid.Faces, mask, counts): if not ok: continue def check(uv, vert): point = Base.Vector(vert) return face.isInside(point, self.get_tolerance(), True) surface = SvSolidFaceSurface(face) _, face_verts = populate_surface(surface, field, cnt, threshold, self.proportional, field_min, field_max, min_r, seed, predicate=check) new_verts.extend(face_verts) return new_verts
def process(self): if not any(socket.is_linked for socket in self.outputs): return surfaces_s = self.inputs['Surface'].sv_get() surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface,)) src_point_s = self.inputs['UVPoints'].sv_get(default=[[]]) src_point_s = ensure_nesting_level(src_point_s, 4) src_u_s = self.inputs['U'].sv_get() src_u_s = ensure_nesting_level(src_u_s, 3) src_v_s = self.inputs['V'].sv_get() src_v_s = ensure_nesting_level(src_v_s, 3) need_values = self.outputs['Curvature1'].is_linked or self.outputs['Curvature2'].is_linked need_directions = self.outputs['Dir1'].is_linked or self.outputs['Dir2'].is_linked need_gauss = self.outputs['Gauss'].is_linked need_mean = self.outputs['Mean'].is_linked need_matrix = self.outputs['Matrix'].is_linked c1_out = [] c2_out = [] dir1_out = [] dir2_out = [] mean_out = [] gauss_out = [] matrix_out = [] for surfaces, src_points_i, src_u_i, src_v_i in zip_long_repeat(surfaces_s, src_point_s, src_u_s, src_v_s): new_curvatures = [] for surface, src_points, src_us, src_vs in zip_long_repeat(surfaces, src_points_i, src_u_i, src_v_i): if self.input_mode == 'VERTICES': us, vs = self.parse_input(src_points) else: maxlen = max(len(src_us), len(src_vs)) src_us = repeat_last_for_length(src_us, maxlen) src_vs = repeat_last_for_length(src_vs, maxlen) us, vs = np.array(src_us), np.array(src_vs) data = surface.curvature_calculator(us, vs, order=self.order).calc(need_values, need_directions, need_gauss, need_mean, need_matrix) if need_values: c1_out.append(data.principal_value_1.tolist()) c2_out.append(data.principal_value_2.tolist()) if need_directions: dir1_out.append(data.principal_direction_1.tolist()) dir2_out.append(data.principal_direction_2.tolist()) if need_mean: mean_out.append(data.mean.tolist()) if need_gauss: gauss_out.append(data.gauss.tolist()) if need_matrix: matrix_out.extend(data.matrix) self.outputs['Curvature1'].sv_set(c1_out) self.outputs['Curvature2'].sv_set(c2_out) self.outputs['Dir1'].sv_set(dir1_out) self.outputs['Dir2'].sv_set(dir2_out) self.outputs['Mean'].sv_set(mean_out) self.outputs['Gauss'].sv_set(gauss_out) self.outputs['Matrix'].sv_set(matrix_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return surfaces_s = self.inputs['Surface'].sv_get() surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface, )) src_point_s = self.inputs['Source'].sv_get() src_point_s = ensure_nesting_level(src_point_s, 4) points_s = self.inputs['Point'].sv_get() points_s = ensure_nesting_level(points_s, 4) direction_s = self.inputs['Direction'].sv_get() direction_s = ensure_nesting_level(direction_s, 4) points_out = [] points_uv_out = [] for surfaces, src_points_i, points_i, directions_i in zip_long_repeat( surfaces_s, src_point_s, points_s, direction_s): for surface, src_points, points, directions in zip_long_repeat( surfaces, src_points_i, points_i, directions_i): u_min = surface.get_u_min() u_max = surface.get_u_max() v_min = surface.get_v_min() v_max = surface.get_v_max() new_uv = [] new_u = [] new_v = [] new_points = [] if self.project_mode == 'PARALLEL': directions = repeat_last_for_length( directions, len(points)) else: # CONIC src_points = repeat_last_for_length( src_points, len(points)) directions = (np.array(points) - np.array(src_points)).tolist() result = raycast_surface( surface, points, directions, samples=self.samples, precise=self.precise, calc_points=self.outputs['Point'].is_linked, method=self.method) new_uv = result.uvs new_points = result.points points_out.append(new_points) points_uv_out.append(new_uv) self.outputs['Point'].sv_set(points_out) self.outputs['UVPoint'].sv_set(points_uv_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return u_curves_s = self.inputs['CurvesU'].sv_get() v_curves_s = self.inputs['CurvesV'].sv_get() intersections_s = self.inputs['Intersections'].sv_get() if self.explicit_t_values: t1_s = self.inputs['T1'].sv_get() t2_s = self.inputs['T2'].sv_get() else: t1_s = [[[]]] t2_s = [[[]]] u_curves_s = ensure_nesting_level(u_curves_s, 2, data_types=(SvCurve,)) v_curves_s = ensure_nesting_level(v_curves_s, 2, data_types=(SvCurve,)) t1_s = ensure_nesting_level(t1_s, 3) t2_s = ensure_nesting_level(t2_s, 3) intersections_s = ensure_nesting_level(intersections_s, 4) surface_out = [] for u_curves, v_curves, t1s, t2s, intersections in zip_long_repeat(u_curves_s, v_curves_s, t1_s, t2_s, intersections_s): u_curves = [SvNurbsCurve.to_nurbs(c) for c in u_curves] if any(c is None for c in u_curves): raise Exception("Some of U curves are not NURBS!") v_curves = [SvNurbsCurve.to_nurbs(c) for c in v_curves] if any(c is None for c in v_curves): raise Exception("Some of V curves are not NURBS!") if self.explicit_t_values: if len(t1s) < len(u_curves): t1s = repeat_last_for_length(t1s, len(u_curves)) elif len(t1s) > len(u_curves): raise Exception(f"Number of items in T1 input {len(t1s)} > number of U-curves {len(u_curves)}") if len(t1s[0]) != len(v_curves): raise Exception(f"Length of items in T1 input {len(t1s[0])} != number of V-curves {len(v_curves)}") if len(t2s) < len(v_curves): t2s = repeat_last_for_length(t2s, len(v_curves)) elif len(t2s) > len(v_curves): raise Exception(f"Number of items in T2 input {len(t2s)} > number of V-curves {len(v_curves)}") if len(t2s[0]) != len(u_curves): raise Exception(f"Length of items in T2 input {len(t2s[0])} != number of U-curves {len(u_curves)}") if self.explicit_t_values: kwargs = {'u_knots': np.array(t1s), 'v_knots': np.array(t2s)} else: kwargs = dict() _, _, _, surface = gordon_surface(u_curves, v_curves, intersections, metric=self.metric, knotvector_accuracy = self.knotvector_accuracy, **kwargs) surface_out.append(surface) self.outputs['Surface'].sv_set(surface_out)
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(default=[[]]) faces_s = self.inputs['Faces'].sv_get(default=[[]]) masks_s = self.inputs['FaceMask'].sv_get(default=[[1]]) face_data_s = self.inputs['FaceData'].sv_get(default=[[]]) offset_s = self.inputs['Offset'].sv_get() verts_out = [] edges_out = [] faces_out = [] face_data_out = [] meshes = zip_long_repeat(vertices_s, edges_s, faces_s, offset_s, masks_s, face_data_s) for vertices, edges, faces, offset, masks, face_data in meshes: if isinstance(offset, (list, tuple)): offset = offset[0] masks = repeat_last_for_length(masks, len(faces)) if face_data: face_data = repeat_last_for_length(face_data, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True, markup_face_data=True) bm_faces = [face for mask, face in zip(masks, bm.faces[:]) if mask] bmesh.ops.poke(bm, faces=bm_faces, offset=offset, center_mode=self.mode, use_relative_offset=self.offset_relative) new_verts, new_edges, new_faces = pydata_from_bmesh(bm) if not face_data: new_face_data = [] else: new_face_data = face_data_from_bmesh_faces(bm, face_data) bm.free() verts_out.append(new_verts) edges_out.append(new_edges) faces_out.append(new_faces) face_data_out.append(new_face_data) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Edges'].sv_set(edges_out) self.outputs['Faces'].sv_set(faces_out) self.outputs['FaceData'].sv_set(face_data_out)
def get_inputs(self): factor1_s = self.inputs['Factor1'].sv_get() factor2_s = self.inputs['Factor2'].sv_get() params_s = self.inputs['Parameter'].sv_get() factor1_s = ensure_nesting_level(factor1_s, 2) factor2_s = ensure_nesting_level(factor2_s, 2) params_s = ensure_nesting_level(params_s, 2) if self.mode == 'TWO': curve1_s = self.inputs['Curve1'].sv_get() curve2_s = self.inputs['Curve2'].sv_get() curve1_s = ensure_nesting_level(curve1_s, 2, data_types=(SvCurve, )) curve2_s = ensure_nesting_level(curve2_s, 2, data_types=(SvCurve, )) results = [] for inputs in zip_long_repeat(curve1_s, curve2_s, factor1_s, factor2_s, params_s): results.append(zip_long_repeat(*inputs)) return results else: curves_s = self.inputs['Curves'].sv_get() curves_s = ensure_nesting_level(curves_s, 2, data_types=(SvCurve, )) results = [] for curves, factor1s, factor2s, params in zip_long_repeat( curves_s, factor1_s, factor2_s, params_s): factor1s = repeat_last_for_length(factor1s, len(curves)) factor2s = repeat_last_for_length(factor2s, len(curves)) params = repeat_last_for_length(params, len(curves)) item = list(zip(curves, curves[1:], factor1s, factor2s, params)) if self.cyclic: item.append((curves[-1], curves[0], factor1s[-1], factor2s[-1], params[-1])) results.append(item) return results
def get_selected_edges(use_mask, masks, bm_edges): if use_mask: if isinstance(masks, ndarray): mask_matched = numpy_full_list(masks, len(bm_edges)).tolist() else: mask_matched = repeat_last_for_length(masks, len(bm_edges)) edge_id = bm_edges.layers.int.get("initial_index") return [edge for edge in bm_edges if mask_matched[edge[edge_id]]] return bm_edges
def process(self): if not any(socket.is_linked for socket in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get() coeffs_s = self.inputs['Coefficient'].sv_get() fields_s = self.inputs['Field'].sv_get() iterations_s = self.inputs['Iterations'].sv_get() vertices_s = ensure_nesting_level(vertices_s, 4) coeffs_s = ensure_nesting_level(coeffs_s, 3) fields_s = ensure_nesting_level(fields_s, 2, data_types=(SvVectorField, )) verts_out = [] for fields, vertices_l, coeffs_l, iterations_l in zip_long_repeat( fields_s, vertices_s, coeffs_s, iterations_s): if not isinstance(iterations_l, (list, tuple)): iterations_l = [iterations_l] if not isinstance(fields, (list, tuple)): fields = [fields] for field, vertices, coeffs, iterations in zip_long_repeat( fields, vertices_l, coeffs_l, iterations_l): if len(vertices) == 0: new_verts = [] elif len(vertices) == 1: vertex = vertices[0] coeff = coeffs[0] for i in range(iterations): vector = field.evaluate(*vertex) vertex = (np.array(vertex) + coeff * vector).tolist() new_verts = [vertex] else: coeffs = repeat_last_for_length(coeffs, len(vertices)) vertices = np.array(vertices) for i in range(iterations): xs = vertices[:, 0] ys = vertices[:, 1] zs = vertices[:, 2] new_xs, new_ys, new_zs = field.evaluate_grid( xs, ys, zs) new_vectors = np.dstack( (new_xs[:], new_ys[:], new_zs[:])) new_vectors = np.array(coeffs)[ np.newaxis].T * new_vectors[0] vertices = vertices + new_vectors new_verts = vertices if self.output_numpy else vertices.tolist( ) verts_out.append(new_verts) self.outputs['Vertices'].sv_set(verts_out)
def extrude_edges_bmesh(vertices, edges, faces, edge_mask, face_data, matrices): if not matrices: matrices = [Matrix()] if face_data: face_data_matched = repeat_last_for_length(face_data, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True, markup_edge_data=True) if edge_mask: b_edges = bmesh_edges_from_edge_mask(bm, edge_mask) else: b_edges = bm.edges new_geom = bmesh.ops.extrude_edge_only(bm, edges=b_edges, use_select_history=False)['geom'] extruded_verts = [v for v in new_geom if isinstance(v, bmesh.types.BMVert)] if len(matrices) == 1: bmesh.ops.transform(bm, verts=extruded_verts, matrix=matrices[0], space=Matrix()) else: for vertex, matrix in zip( *match_long_repeat([extruded_verts, matrices])): bmesh.ops.transform(bm, verts=[vertex], matrix=matrix, space=Matrix()) extruded_verts = [tuple(v.co) for v in extruded_verts] extruded_edges = [e for e in new_geom if isinstance(e, bmesh.types.BMEdge)] extruded_edges = [ tuple(v.index for v in edge.verts) for edge in extruded_edges ] extruded_faces = [f for f in new_geom if isinstance(f, bmesh.types.BMFace)] extruded_faces = [[v.index for v in edge.verts] for edge in extruded_faces] if face_data: new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh( bm, face_data_matched) else: new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] bm.free() return (new_vertices, new_edges, new_faces, extruded_verts, extruded_edges, extruded_faces, new_face_data)
def flip_from_mask(mask, geom, reverse): """ this mode expects a mask list with an element corresponding to each polygon """ verts, edges, faces = geom mask_matched = repeat_last_for_length(mask, len(faces)) b_faces = [] for m, face in zip(mask_matched, faces): mask_val = bool(m) if not reverse else not bool(m) b_faces.append(face if mask_val else face[::-1]) return verts, edges, b_faces
def lloyd_relax(vertices, faces, iterations, mask=None, method=NORMAL, skip_boundary=True, use_axes={0,1,2}): """ supported shape preservation methods: NONE, NORMAL, LINEAR, BVH """ def do_iteration(bvh, bm): verts_out = [] face_centers = np.array([face.calc_center_median() for face in bm.faces]) for bm_vert in bm.verts: co = bm_vert.co if (skip_boundary and bm_vert.is_boundary) or (mask is not None and not mask[bm_vert.index]): new_vert = tuple(co) else: normal = bm_vert.normal cs = np.array([face_centers[face.index] for face in bm_vert.link_faces]) if method == NONE: new_vert = cs.mean(axis=0) elif method == NORMAL: median = mathutils.Vector(cs.mean(axis=0)) dv = median - co dv = dv - dv.project(normal) new_vert = co + dv elif method == LINEAR: approx = linear_approximation(cs) median = mathutils.Vector(approx.center) plane = approx.most_similar_plane() dist = plane.distance_to_point(bm_vert.co) new_vert = median + plane.normal.normalized() * dist elif method == BVH: median = mathutils.Vector(cs.mean(axis=0)) new_vert, normal, idx, dist = bvh.find_nearest(median) else: raise Exception("Unsupported volume preservation method") new_vert = tuple(new_vert) new_vert = mask_axes(tuple(co), new_vert, use_axes) verts_out.append(new_vert) return verts_out 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, [], faces, normal_update=True) vertices = do_iteration(bvh, bm) bm.free() return vertices
def generate_surface(self, solid, field, count, min_r, radius_field, threshold, field_min, field_max, mask): counts = self.distribute_faces(solid.Faces, count) new_verts = [] new_radiuses = [] mask = repeat_last_for_length(mask, len(solid.Faces)) counts = repeat_last_for_length(counts, len(solid.Faces)) done_spheres = [] for face, ok, cnt in zip(solid.Faces, mask, counts): if not ok: continue def check(uv, vert): point = Base.Vector(vert) return face.isInside(point, self.get_tolerance(), True) surface = SvSolidFaceSurface(face) _, face_verts, radiuses = populate_surface( surface, field, cnt, threshold, self.proportional, field_min, field_max, min_r=min_r, min_r_field=radius_field, random_radius=self.random_radius, avoid_spheres=done_spheres, seed=None, predicate=check) done_spheres.extend(list(zip(face_verts, radiuses))) new_verts.extend(face_verts) new_radiuses.extend(radiuses) return new_verts, new_radiuses
def process(self): if not (self.outputs['Vers'].is_linked and self.inputs['Vers'].is_linked): return vertices = Vector_generate(self.inputs['Vers'].sv_get(deepcopy=False)) faces = self.inputs['Pols'].sv_get(deepcopy=False) offset = self.inputs['Offset'].sv_get(deepcopy=False)[0] nsides = self.inputs['N sides'].sv_get(deepcopy=False)[0][0] radius = self.inputs['Radius'].sv_get(deepcopy=False)[0] outv = [] oute = [] outo = [] outn = [] # for each object for verts_obj, faces_obj in zip(vertices, faces): offset_m = repeat_last_for_length(offset, len(faces_obj)) radius_m = repeat_last_for_length(radius, len(faces_obj)) verlen = set(range(len(verts_obj))) bm = bmesh_from_pydata(verts_obj, [], faces_obj, normal_update=True) result = self.Offset_pols(bm, offset_m, radius_m, nsides, verlen) outv.append(result[0]) oute.append(result[1]) outo.append(result[2]) outn.append(result[3]) self.outputs['Vers'].sv_set(outv) self.outputs['Edgs'].sv_set(oute) self.outputs['OutPols'].sv_set(outo) self.outputs['InPols'].sv_set(outn)
def process(self): if not any(socket.is_linked for socket in self.outputs): 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) masks_s = self.inputs['FaceMask'].sv_get(default=[[1]], deepcopy=False) factors_s = self.inputs['Factor'].sv_get(deepcopy=False) iterations_s = self.inputs['Iterations'].sv_get(deepcopy=False) verts_out = [] edges_out = [] faces_out = [] meshes = match_long_repeat( [vertices_s, edges_s, faces_s, masks_s, factors_s, iterations_s]) for vertices, edges, faces, masks, factor, iterations in zip(*meshes): if isinstance(iterations, (list, tuple)): iterations = iterations[0] if isinstance(factor, (list, tuple)): factor = factor[0] masks_matched = repeat_last_for_length(masks, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True) bm_faces = [ face for mask, face in zip(masks_matched, bm.faces[:]) if mask ] bmesh.ops.planar_faces(bm, faces=bm_faces, iterations=iterations, factor=factor) new_verts, new_edges, new_faces = pydata_from_bmesh(bm) bm.free() verts_out.append(new_verts) edges_out.append(new_edges) faces_out.append(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 and self.inputs['Polygons'].is_linked): return if not (any(self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons'])): return vertices_s = self.inputs['Vertices'].sv_get(default=[[]], deepcopy=False) edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False) faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False) mask_s = self.inputs['Mask'].sv_get(default=[[True]], deepcopy=False) result_vertices = [] result_edges = [] result_faces = [] meshes = match_long_repeat([vertices_s, edges_s, faces_s, mask_s]) for vertices, edges, faces, mask in zip(*meshes): bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True) mask_matched = repeat_last_for_length(mask, len(faces)) b_faces = [] for m, face in zip(mask_matched, bm.faces): if m: b_faces.append(face) bmesh.ops.recalc_face_normals(bm, faces=b_faces) new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) bm.free() if self.invert: new_faces = [list(reversed(face)) for face in new_faces] result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) if self.outputs['Vertices'].is_linked: self.outputs['Vertices'].sv_set(result_vertices) if self.outputs['Edges'].is_linked: self.outputs['Edges'].sv_set(result_edges) if self.outputs['Polygons'].is_linked: self.outputs['Polygons'].sv_set(result_faces)
def process(self): if not any(socket.is_linked for socket in self.outputs): return verts_in = self.inputs['Vertices'].sv_get() faces_in = self.inputs['Faces'].sv_get() add_verts_in = self.inputs['AddVerts'].sv_get() if self.mode == 'INDEX': face_idxs_in = self.inputs['FaceIndex'].sv_get() else: face_idxs_in = [[[]]] tolerance = 10**(-self.accuracy) verts_out = [] edges_out = [] faces_out = [] for verts, faces, add_verts, face_idxs in zip_long_repeat( verts_in, faces_in, add_verts_in, face_idxs_in): if self.mode == 'INDEX': face_idxs = repeat_last_for_length(face_idxs, len(add_verts)) else: face_idxs = find_nearest_idxs(verts, faces, add_verts) add_verts_by_face = defaultdict(list) for add_vert, idx in zip(add_verts, face_idxs): add_verts_by_face[idx].append(add_vert) new_verts, new_edges, new_faces = mesh_insert_verts( verts, faces, add_verts_by_face, epsilon=tolerance, exclude_boundary=self.exclude_boundary, preserve_shape=self.preserve_shape, recalc_normals=self.recalc_normals) verts_out.append(new_verts) edges_out.append(new_edges) faces_out.append(new_faces) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Edges'].sv_set(edges_out) self.outputs['Faces'].sv_set(faces_out)
def make_solid(self, solid, thickness, mask): if not solid.isValid(): raise Exception("Solid is not valid") if self.mask_usage == 'REMOVE': mask = [not c for c in mask] if all(mask): self.info( "No faces are selected to be removed; the node will operate as `Offset' operation" ) if not any(mask): raise Exception("Invalid faces mask: all faces are to be removed") mask = repeat_last_for_length(mask, len(solid.Faces)) faces = [face for c, face in zip(mask, solid.Faces) if not c] try: shape = solid.makeThickness(faces, thickness, self.tolerance) return shape except Part.OCCError as e: raise Exception( f"FreeCAD API method failed: {e}. Incorrect faces mask?")
def subdiv_mesh_to_quads_np(vertices, polygons, iterations, normal_displace, random_f, random_normal, random_seed, smooth_f, vert_data, face_data, output_edges=True, output_vert_map=True): np.random.seed(int(random_seed)) np_verts = vertices if isinstance(vertices, np.ndarray) else np.array(vertices) if output_vert_map: vert_map = np.zeros(np_verts.shape[0], dtype=int) else: vert_map = np.array([], dtype=int) matched_vert_data = dict() if vert_data: for key in vert_data: matched_vert_data[key] = numpy_full_list(vert_data[key], np_verts.shape[0]) matched_face_data = dict() if face_data: for key in face_data: data = face_data[key] if isinstance(data, np.ndarray): matched_face_data[key] = numpy_full_list(data, len(polygons)) else: matched_face_data[key] = repeat_last_for_length(data, len(polygons)) flat_pols, pol_len, pol_end = np_pols(polygons) edges, unique_edges, eds_inverse_idx = pols_to_edges(flat_pols, pol_len, pol_end) return subdiv_mesh_to_quads_inner( np_verts, polygons, pol_len, pol_end, edges, unique_edges, eds_inverse_idx, iterations, normal_displace, random_f, random_normal, smooth_f, vert_map, matched_vert_data, matched_face_data, output_edges=output_edges, max_iterations=iterations)
def by_sphere(vertices, centers, radius): if len(centers) == 1: center = centers[0] out_verts_mask = np.linalg.norm( np.array(vertices) - np.array(center)[np.newaxis, :], axis=1) <= radius[0] else: # build KDTree tree = kdtree.KDTree(len(centers)) for i, v in enumerate(centers): tree.insert(v, i) tree.balance() out_verts_mask = [] rad = repeat_last_for_length(radius, len(centers)) for vertex in vertices: _, idx, rho = tree.find(vertex) mask = rho <= rad[idx] out_verts_mask.append(mask) return out_verts_mask
def process(self): if not any(socket.is_linked for socket in self.outputs): return size_x_s = self.inputs['Size X'].sv_get() size_y_s = self.inputs['Size Y'].sv_get() radius_s = self.inputs['Radius'].sv_get() size_x_s = ensure_nesting_level(size_x_s, 2) size_y_s = ensure_nesting_level(size_y_s, 2) radius_nesting = get_data_nesting_level(radius_s) if radius_nesting < 2 or radius_nesting > 3: raise TypeError( f"Radius input can only handle nesting level 2 or 3, got {radius_nesting}" ) radius_per_corner = (radius_nesting == 3) #if radius_nesting == 2: #radius_s = [[radiuses] for radiuses in radius_s] #radius_s = [[[r] for r in radiuses] for radiuses in radius_s] curves_out = [] centers_out = [] for size_x_i, size_y_i, radius_i in zip_long_repeat( size_x_s, size_y_s, radius_s): new_curves = [] new_centers = [] for size_x, size_y, radiuses in zip_long_repeat( size_x_i, size_y_i, radius_i): if not radius_per_corner: radiuses = [radiuses] radiuses = repeat_last_for_length(radiuses, 4) centers, curve = self.make_curve(size_x, size_y, radiuses) new_curves.append(curve) new_centers.append([tuple(c) for c in centers]) curves_out.append(new_curves) centers_out.extend(new_centers) self.outputs['Curve'].sv_set(curves_out) self.outputs['Centers'].sv_set(centers_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return verts_s = self.inputs['Vertices'].sv_get() radius_s = self.inputs['Radius'].sv_get() verts_s = ensure_nesting_level(verts_s, 3) radius_s = ensure_nesting_level(radius_s, 2) curves_out = [] centers_out = [] for vertices, radiuses in zip_long_repeat(verts_s, radius_s): if len(vertices) < 3: raise Exception("At least three vertices are required to make a fillet") radiuses = repeat_last_for_length(radiuses, len(vertices)) curve, centers = self.make_curve(vertices, radiuses) curves_out.append(curve) centers_out.append(centers) self.outputs['Curve'].sv_set(curves_out) self.outputs['Centers'].sv_set(centers_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get() weights_s = self.inputs['Weights'].sv_get(default=[[[None]]]) degree_s = self.inputs['Degree'].sv_get() points_cnt_s = self.inputs['PointsCnt'].sv_get() smoothing_s = self.inputs['Smoothing'].sv_get() input_level = get_data_nesting_level(vertices_s) vertices_s = ensure_nesting_level(vertices_s, 4) degree_s = ensure_nesting_level(degree_s, 2) points_cnt_s = ensure_nesting_level(points_cnt_s, 2) smoothing_s = ensure_nesting_level(smoothing_s, 2) has_weights = self.inputs['Weights'].is_linked if has_weights: weights_s = ensure_nesting_level(weights_s, 3) nested_output = input_level > 3 curves_out = [] points_out = [] knots_out = [] for params in zip_long_repeat(vertices_s, weights_s, degree_s, points_cnt_s, smoothing_s): new_curves = [] new_points = [] new_knots = [] for vertices, weights, degree, points_cnt, smoothing in zip_long_repeat( *params): if self.implementation == 'GEOMDL': kwargs = dict(centripetal=self.centripetal) if self.has_points_cnt: kwargs['ctrlpts_size'] = points_cnt curve = fitting.approximate_curve(vertices, degree, **kwargs) control_points = curve.ctrlpts knotvector = curve.knotvector curve = SvGeomdlCurve(curve) else: # SCIPY: points = np.array(vertices) if has_weights: weights = repeat_last_for_length( weights, len(vertices)) else: weights = None if not self.has_smoothing: smoothing = None if self.is_cyclic: if self.auto_cyclic: dv = np.linalg.norm(points[0] - points[-1]) is_cyclic = dv <= self.cyclic_threshold self.info("Dv %s, threshold %s => is_cyclic %s", dv, self.cyclic_threshold, is_cyclic) else: is_cyclic = True else: is_cyclic = False curve = scipy_nurbs_approximate( points, weights=weights, metric=self.metric, degree=degree, filter_doubles=None if not self.remove_doubles else self.threshold, smoothing=smoothing, is_cyclic=is_cyclic) control_points = curve.get_control_points().tolist() knotvector = curve.get_knotvector().tolist() new_curves.append(curve) new_points.append(control_points) new_knots.append(knotvector) if nested_output: curves_out.append(new_curves) points_out.append(new_points) knots_out.append(new_knots) else: curves_out.extend(new_curves) points_out.extend(new_points) knots_out.extend(new_knots) self.outputs['Curve'].sv_set(curves_out) self.outputs['ControlPoints'].sv_set(points_out) self.outputs['Knots'].sv_set(knots_out)
def process(self): inputs, outputs = self.inputs, self.outputs if self.dont_process(): return result_vertices, result_edges, result_faces, result_face_data = [], [], [], [] r_inner_vertices, r_inner_edges, r_inner_faces = [], [], [] r_split_vertices, r_split_edges, r_split_faces = [], [], [] use_mask = inputs['EdgeMask'].is_linked show_new = self.show_new and any(s.is_linked for s in outputs[4:7]) show_old = self.show_old and any(s.is_linked for s in outputs[7:]) use_face_data = inputs['FaceData'].is_linked and outputs['FaceData'].is_linked output_numpy = any(self.out_np) meshes = self.get_data() for vertices, edges, faces, face_data, masks, cuts, smooth, fractal, along_normal, seed in zip(*meshes): if cuts < 1: result_vertices.append(vertices) result_edges.append(edges) result_faces.append(faces) result_face_data.append(face_data) r_inner_vertices.append(vertices) r_inner_edges.append(edges) r_inner_faces.append(faces) r_split_vertices.append(vertices) r_split_edges.append(edges) r_split_faces.append(faces) continue if use_face_data and len(face_data) > 0: if isinstance(face_data, ndarray): face_data_matched = numpy_full_list(face_data, len(faces)).tolist() else: face_data_matched = repeat_last_for_length(face_data, len(faces)) else: face_data_matched =[] bm = bmesh_from_pydata( vertices, edges, faces, markup_face_data=use_face_data, markup_edge_data=use_mask, normal_update=True) selected_edges = get_selected_edges(use_mask, masks, bm.edges) geom = subdivide_edges( bm, edges=selected_edges, smooth=smooth, smooth_falloff=self.falloff_type, fractal=fractal, along_normal=along_normal, cuts=cuts, seed=seed, quad_corner_type=self.corner_type, use_grid_fill=self.grid_fill, use_single_edge=self.single_edge, use_only_quads=self.only_quads, use_smooth_even=self.smooth_even) if output_numpy: new_verts, new_edges, new_faces, new_face_data = numpy_data_from_bmesh(bm, self.out_np, face_data_matched) else: if use_face_data and len(face_data) > 0: new_verts, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data_matched) else: new_verts, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] result_vertices.append(new_verts) result_edges.append(new_edges) result_faces.append(new_faces) result_face_data.append(new_face_data) if show_new: inner_verts, inner_edges, inner_faces = get_partial_result_pydata(geom['geom_inner']) r_inner_vertices.append(inner_verts) r_inner_edges.append(inner_edges) r_inner_faces.append(inner_faces) if show_old: split_verts, split_edges, split_faces = get_partial_result_pydata(geom['geom_split']) r_split_vertices.append(split_verts) r_split_edges.append(split_edges) r_split_faces.append(split_faces) bm.free() outputs['Vertices'].sv_set(result_vertices) outputs['Edges'].sv_set(result_edges) outputs['Faces'].sv_set(result_faces) outputs['FaceData'].sv_set(result_face_data) outputs['NewVertices'].sv_set(r_inner_vertices) outputs['NewEdges'].sv_set(r_inner_edges) outputs['NewFaces'].sv_set(r_inner_faces) outputs['OldVertices'].sv_set(r_split_vertices) outputs['OldEdges'].sv_set(r_split_edges) outputs['OldFaces'].sv_set(r_split_faces)
def process(self): if not any(socket.is_linked for socket in self.outputs): return surfaces_s = self.inputs['Surface'].sv_get() surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface, )) src_point_s = self.inputs['Source'].sv_get() src_point_s = ensure_nesting_level(src_point_s, 4) points_s = self.inputs['Point'].sv_get() points_s = ensure_nesting_level(points_s, 4) direction_s = self.inputs['Direction'].sv_get() direction_s = ensure_nesting_level(direction_s, 4) points_out = [] points_uv_out = [] for surfaces, src_points_i, points_i, directions_i in zip_long_repeat( surfaces_s, src_point_s, points_s, direction_s): for surface, src_points, points, directions in zip_long_repeat( surfaces, src_points_i, points_i, directions_i): u_min = surface.get_u_min() u_max = surface.get_u_max() v_min = surface.get_v_min() v_max = surface.get_v_max() new_uv = [] new_u = [] new_v = [] new_points = [] if self.project_mode == 'PARALLEL': directions = repeat_last_for_length( directions, len(points)) else: # CONIC src_points = repeat_last_for_length( src_points, len(points)) directions = (np.array(points) - np.array(src_points)).tolist() init_us, init_vs, init_ts, init_points = init_guess( surface, points, directions, samples=self.samples) for point, direction, init_u, init_v, init_t, init_point in zip( points, directions, init_us, init_vs, init_ts, init_points): if self.precise: direction = np.array(direction) direction = direction / np.linalg.norm(direction) result = root(goal(surface, np.array(point), direction), x0=np.array([init_u, init_v, init_t]), method=self.method) if not result.success: raise Exception( "Can't find the projection for {}: {}". format(point, result.message)) u0, v0, t0 = result.x else: u0, v0 = init_u, init_v new_points.append(init_point) new_uv.append((u0, v0, 0)) new_u.append(u0) new_v.append(v0) if self.precise and self.outputs['Point'].is_linked: new_points = surface.evaluate_array( np.array(new_u), np.array(new_v)).tolist() points_out.append(new_points) points_uv_out.append(new_uv) self.outputs['Point'].sv_set(points_out) self.outputs['UVPoint'].sv_set(points_uv_out)
def process(self): inputs = self.inputs outputs = self.outputs if not (inputs['Vertices'].is_linked and inputs['Polygons'].is_linked): return if not any(socket.is_linked for socket in outputs): return need_mask_out = 'Mask' in outputs and outputs['Mask'].is_linked vector_in = self.scale_socket_type vertices_s = inputs['Vertices'].sv_get(deepcopy=False) edges_s = inputs['Edges'].sv_get(default=[[]], deepcopy=False) faces_s = inputs['Polygons'].sv_get(default=[[]], deepcopy=False) masks_s = inputs['Mask'].sv_get(default=[[1]], deepcopy=False) heights_s = inputs['Height'].sv_get(deepcopy=False) scales_s = inputs['Scale'].sv_get(deepcopy=False) if 'Matrix' in inputs: matrixes_s = inputs['Matrix'].sv_get(default=[[Matrix()]], deepcopy=False) else: matrixes_s = [[Matrix()]] if 'FaceData' in inputs: face_data_s = self.inputs['FaceData'].sv_get(default=[[]], deepcopy=False) else: face_data_s = [[]] if type(matrixes_s[0]) == Matrix: matrixes_s = [matrixes_s] linked_extruded_polygons = outputs['ExtrudedPolys'].is_linked linked_other_polygons = outputs['OtherPolys'].is_linked result_vertices = [] result_edges = [] result_faces = [] result_extruded_faces = [] result_other_faces = [] result_mask = [] result_face_data = [] meshes = match_long_repeat([ vertices_s, edges_s, faces_s, masks_s, heights_s, scales_s, matrixes_s, face_data_s ]) for vertices, edges, faces, masks_, heights_, scales_, matrixes_, face_data in zip( *meshes): new_extruded_faces = [] new_extruded_faces_append = new_extruded_faces.append heights, scales, matrixes, masks = make_repeaters( [heights_, scales_, matrixes_, masks_]) if face_data: face_data_matched = repeat_last_for_length( face_data, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True, normal_update=True) mask_layer = bm.faces.layers.int.new('mask') bm.faces.ensure_lookup_table() fill_faces_layer(bm, masks, 'mask', int, OUT) if self.mask_mode == 'NOEXTRUDE': faces_to_extrude = [ face for face, mask in zip(bm.faces, masks) if mask ] else: faces_to_extrude = bm.faces extruded_faces = bmesh.ops.extrude_discrete_faces( bm, faces=faces_to_extrude)['faces'] if self.mask_mode == 'NOEXTRUDE': extruded_face_items = zip(extruded_faces, heights, scales, matrixes) else: extruded_face_items = [ (face, height, scale, matrix) for (face, mask, height, scale, matrix) in zip( extruded_faces, masks, heights, scales, matrixes) if mask ] for face, height, scale, matrix in extruded_face_items: vec = scale if vector_in else (scale, scale, scale) # preparing matrix normal = face.normal if normal[0] == 0 and normal[1] == 0: m_r = Matrix() if normal[2] >= 0 else Matrix.Rotation( pi, 4, 'X') else: z_axis = normal x_axis = (Vector( (z_axis[1] * -1, z_axis[0], 0))).normalized() y_axis = (z_axis.cross(x_axis)).normalized() m_r = Matrix(list([*zip(x_axis[:], y_axis[:], z_axis[:]) ])).to_4x4() dr = face.normal * height center = face.calc_center_median() translation = Matrix.Translation(center) space = (translation @ m_r).inverted() if self.extrude_mode == 'NORMAL': # inset, scale and push operations bmesh.ops.scale(bm, vec=vec, space=space, verts=face.verts) bmesh.ops.translate(bm, verts=face.verts, vec=dr) else: bmesh.ops.transform(bm, matrix=matrix, space=space, verts=face.verts) if linked_extruded_polygons or linked_other_polygons: new_extruded_faces_append([v.index for v in face.verts]) if face_data: new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh( bm, face_data_matched) else: new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] new_other_faces = [ f for f in new_faces if f not in new_extruded_faces ] if linked_other_polygons else [] if need_mask_out: new_mask = self.get_out_mask(bm, extruded_faces) result_mask.append(new_mask) bm.free() result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) result_extruded_faces.append(new_extruded_faces) result_other_faces.append(new_other_faces) result_face_data.append(new_face_data) outputs['Vertices'].sv_set(result_vertices) outputs['Edges'].sv_set(result_edges) outputs['Polygons'].sv_set(result_faces) outputs['ExtrudedPolys'].sv_set(result_extruded_faces) outputs['OtherPolys'].sv_set(result_other_faces) if need_mask_out: outputs['Mask'].sv_set(result_mask) if 'FaceData' in outputs: outputs['FaceData'].sv_set(result_face_data)
def process(self): # inputs 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['Polygons'].sv_get(default=[[]], deepcopy=False) masks_s = self.inputs['Mask'].sv_get(default=[[1]], deepcopy=False) if self.transform_mode == "Matrix": matrices_s = [ self.inputs['Matrices'].sv_get(default=[Matrix()], deepcopy=False) ] heights_s = [0.0] scales_s = [1.0] else: matrices_s = [[]] heights_s = self.inputs['Height'].sv_get(deepcopy=False) scales_s = self.inputs['Scale'].sv_get(deepcopy=False) if 'FaceData' in self.inputs: face_data_s = self.inputs['FaceData'].sv_get(default=[[]], deepcopy=False) else: face_data_s = [[]] need_mask_out = 'Mask' in self.outputs and self.outputs[ 'Mask'].is_linked result_vertices = [] result_edges = [] result_faces = [] result_ext_vertices = [] result_ext_edges = [] result_ext_faces = [] result_face_data = [] result_mask = [] meshes = match_long_repeat([ vertices_s, edges_s, faces_s, masks_s, matrices_s, heights_s, scales_s, face_data_s ]) for vertices, edges, faces, masks, matrix_per_iteration, height_per_iteration, scale_per_iteration, face_data in zip( *meshes): if self.transform_mode == "Matrix": if not matrix_per_iteration: matrix_per_iteration = [Matrix()] if self.multiple: if self.transform_mode == "Matrix": n_iterations = len(matrix_per_iteration) else: n_iterations = max(len(height_per_iteration), len(scale_per_iteration)) height_per_iteration_matched = repeat_last_for_length( height_per_iteration, n_iterations) scale_per_iteration_matched = repeat_last_for_length( scale_per_iteration, n_iterations) else: n_iterations = 1 matrix_per_iteration = [matrix_per_iteration] mask_matched = repeat_last_for_length(masks, len(faces)) if face_data: face_data_matched = repeat_last_for_length( face_data, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, normal_update=True, markup_face_data=True) mask_layer = bm.faces.layers.int.new('mask') bm.faces.ensure_lookup_table() #fill_faces_layer(bm, masks, 'mask', int, MASK, invert_mask=True) b_faces = [] b_edges = set() b_verts = set() for mask, face in zip(mask_matched, bm.faces): if mask: b_faces.append(face) for edge in face.edges: b_edges.add(edge) for vert in face.verts: b_verts.add(vert) extrude_geom = b_faces + list(b_edges) + list(b_verts) extruded_verts_last = [] extruded_bm_verts_all = set() extruded_edges_last = [] extruded_faces_last = [] extruded_bm_faces_last = [] matrix_spaces = [Matrix()] for idx in range(n_iterations): for item in extrude_geom: if isinstance(item, bmesh.types.BMFace): item[mask_layer] = OUT if is_290: kwargs = { 'use_dissolve_ortho_edges': self.dissolve_ortho_edges } else: kwargs = {} new_geom = bmesh.ops.extrude_face_region( bm, geom=extrude_geom, edges_exclude=set(), use_keep_orig=self.keep_original, **kwargs)['geom'] extruded_verts = [ v for v in new_geom if isinstance(v, bmesh.types.BMVert) ] extruded_faces = [ f for f in new_geom if isinstance(f, bmesh.types.BMFace) ] if self.transform_mode == "Matrix": matrices = matrix_per_iteration[idx] if isinstance(matrices, Matrix): matrices = [matrices] matrix_spaces_matched = repeat_last_for_length( matrix_spaces, len(extruded_verts)) for vertex_idx, (vertex, matrix) in enumerate( zip(*match_long_repeat([extruded_verts, matrices ]))): bmesh.ops.transform( bm, verts=[vertex], matrix=matrix, space=matrix_spaces_matched[vertex_idx]) matrix_spaces_matched[vertex_idx] = matrix.inverted( ) @ matrix_spaces_matched[vertex_idx] else: height = height_per_iteration_matched[idx] scale = scale_per_iteration_matched[idx] normal = get_avg_normal(extruded_faces) dr = normal * height center = get_faces_center(extruded_faces) translation = Matrix.Translation(center) rotation = normal.rotation_difference( (0, 0, 1)).to_matrix().to_4x4() m = translation @ rotation bmesh.ops.scale(bm, vec=(scale, scale, scale), space=m.inverted(), verts=extruded_verts) bmesh.ops.translate(bm, verts=extruded_verts, vec=dr) extruded_bm_verts_all.update(extruded_verts) extruded_verts_last = [tuple(v.co) for v in extruded_verts] extruded_edges = [ e for e in new_geom if isinstance(e, bmesh.types.BMEdge) ] extruded_edges_last = [ tuple(v.index for v in edge.verts) for edge in extruded_edges ] extruded_bm_faces_last = extruded_faces extruded_faces_last = [[v.index for v in face.verts] for face in extruded_faces] extrude_geom = new_geom if face_data: new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh( bm, face_data_matched) else: new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] if need_mask_out: new_mask = self.get_out_mask(bm, extruded_bm_faces_last, extruded_bm_verts_all) result_mask.append(new_mask) bm.free() result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) result_ext_vertices.append(extruded_verts_last) result_ext_edges.append(extruded_edges_last) result_ext_faces.append(extruded_faces_last) result_face_data.append(new_face_data) self.outputs['Vertices'].sv_set(result_vertices) self.outputs['Edges'].sv_set(result_edges) self.outputs['Polygons'].sv_set(result_faces) self.outputs['NewVertices'].sv_set(result_ext_vertices) self.outputs['NewEdges'].sv_set(result_ext_edges) self.outputs['NewFaces'].sv_set(result_ext_faces) if 'Mask' in self.outputs: self.outputs['Mask'].sv_set(result_mask) if 'FaceData' in self.outputs: self.outputs['FaceData'].sv_set(result_face_data)
def process(self): if not (self.inputs['Vertices'].is_linked and self.inputs['Polygons'].is_linked): return if not (any( self.outputs[name].is_linked for name in ['Vertices', 'Edges', 'Polygons', 'NewEdges', 'NewPolys'])): return vertices_s = self.inputs['Vertices'].sv_get(default=[[]], deepcopy=False) edges_s = self.inputs['Edges'].sv_get(default=[[]], deepcopy=False) faces_s = self.inputs['Polygons'].sv_get(default=[[]], deepcopy=False) if 'FaceData' in self.inputs: face_data_s = self.inputs['FaceData'].sv_get(default=[[]], deepcopy=False) else: face_data_s = [[]] mask_s = self.inputs['Mask'].sv_get(default=[[True]], deepcopy=False) result_vertices = [] result_edges = [] result_faces = [] result_face_data = [] result_new_edges = [] result_new_faces = [] meshes = match_long_repeat( [vertices_s, edges_s, faces_s, face_data_s, mask_s]) for vertices, edges, faces, face_data, mask in zip(*meshes): if face_data: face_data_matched = repeat_last_for_length( face_data, len(faces)) bm = bmesh_from_pydata(vertices, edges, faces, markup_face_data=True) mask_matched = repeat_last_for_length(mask, len(faces)) b_faces = [] for m, face in zip(mask_matched, bm.faces): if m: b_faces.append(face) res = bmesh.ops.triangulate(bm, faces=b_faces, quad_method=self.quad_mode, ngon_method=self.ngon_mode) b_new_edges = [ tuple(v.index for v in edge.verts) for edge in res['edges'] ] b_new_faces = [[v.index for v in face.verts] for face in res['faces']] if face_data: new_vertices, new_edges, new_faces, new_face_data = pydata_from_bmesh( bm, face_data_matched) else: new_vertices, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] bm.free() result_vertices.append(new_vertices) result_edges.append(new_edges) result_faces.append(new_faces) result_face_data.append(new_face_data) result_new_edges.append(b_new_edges) result_new_faces.append(b_new_faces) self.outputs['Vertices'].sv_set(result_vertices) self.outputs['Edges'].sv_set(result_edges) self.outputs['Polygons'].sv_set(result_faces) if 'FaceData' in self.outputs: self.outputs['FaceData'].sv_set(result_face_data) self.outputs['NewEdges'].sv_set(result_new_edges) self.outputs['NewPolys'].sv_set(result_new_faces)
def process(self): vertices_s = self.inputs['ControlPoints'].sv_get() has_weights = self.inputs['Weights'].is_linked weights_s = self.inputs['Weights'].sv_get(default=[[1.0]]) u_size_s = self.inputs['USize'].sv_get() knots_u_s = self.inputs['KnotsU'].sv_get(default=[[]]) knots_v_s = self.inputs['KnotsV'].sv_get(default=[[]]) degree_u_s = self.inputs['DegreeU'].sv_get() degree_v_s = self.inputs['DegreeV'].sv_get() if self.input_mode == '1D': vertices_s = ensure_nesting_level(vertices_s, 3) else: vertices_s = ensure_nesting_level(vertices_s, 4) surfaces_out = [] inputs = zip_long_repeat(vertices_s, weights_s, knots_u_s, knots_v_s, degree_u_s, degree_v_s, u_size_s) for vertices, weights, knots_u, knots_v, degree_u, degree_v, u_size in inputs: if isinstance(degree_u, (tuple, list)): degree_u = degree_u[0] if isinstance(degree_v, (tuple, list)): degree_v = degree_v[0] if isinstance(u_size, (list, tuple)): u_size = u_size[0] if self.surface_mode != 'NURBS': weights = None if self.surface_mode == 'NURBS': if self.input_mode == '1D': weights = repeat_last_for_length(weights, len(vertices), deepcopy=True) else: if isinstance(weights[0], (int, float)): weights = [weights] weights = repeat_last_for_length(weights, len(vertices), deepcopy=True) for verts_u, weights_u in zip(vertices, weights): fullList_deep_copy(weights_u, len(verts_u)) if self.input_mode == '1D': n_v = u_size n_u = len(vertices) // n_v vertices = split_by_count(vertices, n_u) if self.surface_mode == 'NURBS': weights = split_by_count(weights, n_u) if self.knot_mode == 'AUTO': if self.is_cyclic_v: for row_idx in range(len(vertices)): vertices[row_idx].extend(vertices[row_idx][:degree_v + 1]) if self.surface_mode == 'NURBS': weights[row_idx].extend( weights[row_idx][:degree_v + 1]) if self.is_cyclic_u: vertices.extend(vertices[:degree_u + 1]) if self.surface_mode == 'NURBS': weights.extend(weights[:degree_u + 1]) self.debug("UxV: %s x %s", len(vertices), len(vertices[0])) n_u_total = len(vertices) n_v_total = len(vertices[0]) if self.knot_mode == 'AUTO': if self.is_cyclic_u: knots_u = list(range(n_u_total + degree_u + 1)) else: knots_u = sv_knotvector.generate(degree_u, n_u_total) self.debug("Auto knots U: %s", knots_u) surf_knotvector_u = knots_u if self.is_cyclic_v: knots_v = list(range(n_v_total + degree_v + 1)) else: knots_v = sv_knotvector.generate(degree_v, n_v_total) self.debug("Auto knots V: %s", knots_v) surf_knotvector_v = knots_v else: surf_knotvector_u = knots_u surf_knotvector_v = knots_v new_surf = SvNurbsSurface.build(self.implementation, degree_u, degree_v, surf_knotvector_u, surf_knotvector_v, vertices, weights, self.normalize_knots) surf_knotvector_u = new_surf.get_knotvector_u().tolist() surf_knotvector_v = new_surf.get_knotvector_v().tolist() if self.is_cyclic_u: u_min = surf_knotvector_u[degree_u] u_max = surf_knotvector_u[-degree_u - 2] new_surf.u_bounds = u_min, u_max #print("U:",new_surf.u_bounds) else: u_min = min(surf_knotvector_u) u_max = max(surf_knotvector_u) new_surf.u_bounds = u_min, u_max if self.is_cyclic_v: v_min = surf_knotvector_v[degree_v] v_max = surf_knotvector_v[-degree_v - 2] new_surf.v_bounds = v_min, v_max #print("V:",new_surf.v_bounds) else: v_min = min(surf_knotvector_v) v_max = max(surf_knotvector_v) new_surf.v_bounds = v_min, v_max surfaces_out.append(new_surf) self.outputs['Surface'].sv_set(surfaces_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return surfaces_s = self.inputs['Surface'].sv_get() surface_level = get_data_nesting_level(surfaces_s, data_types=(SvSurface, )) surfaces_s = ensure_nesting_level(surfaces_s, 2, data_types=(SvSurface, )) src_point_s = self.inputs['UVPoints'].sv_get(default=[[]]) src_point_s = ensure_nesting_level(src_point_s, 4) src_u_s = self.inputs['U'].sv_get() src_u_s = ensure_nesting_level(src_u_s, 3) src_v_s = self.inputs['V'].sv_get() src_v_s = ensure_nesting_level(src_v_s, 3) normal_out = [] tangent_u_out = [] tangent_v_out = [] matrix_out = [] area_out = [] du_out = [] dv_out = [] for surfaces, src_points_i, src_u_i, src_v_i in zip_long_repeat( surfaces_s, src_point_s, src_u_s, src_v_s): new_normals = [] new_tangent_u = [] new_tangent_v = [] new_area = [] new_du = [] new_dv = [] for surface, src_points, src_us, src_vs in zip_long_repeat( surfaces, src_points_i, src_u_i, src_v_i): if self.input_mode == 'VERTICES': us, vs = self.parse_input(src_points) else: maxlen = max(len(src_us), len(src_vs)) src_us = repeat_last_for_length(src_us, maxlen) src_vs = repeat_last_for_length(src_vs, maxlen) us, vs = np.array(src_us), np.array(src_vs) data = surface.derivatives_data_array(us, vs) new_normals.append(data.unit_normals().tolist()) du, dv = data.unit_tangents() new_tangent_u.append(du.tolist()) new_tangent_v.append(dv.tolist()) normals_len = [n[0] for n in data.normals_len().tolist()] new_area.append(normals_len) du_len, dv_len = data.tangent_lens() du_len = [n[0] for n in du_len.tolist()] dv_len = [n[0] for n in dv_len.tolist()] new_du.append(du_len) new_dv.append(dv_len) matrix_out.extend(data.matrices(as_mathutils=True)) normal_out.append(new_normals) tangent_u_out.append(new_tangent_u) tangent_v_out.append(new_tangent_v) area_out.append(new_area) if surface_level == 2: du_out.append(new_du) dv_out.append(new_dv) else: du_out.extend(new_du) dv_out.extend(new_dv) self.outputs['Normal'].sv_set(normal_out) self.outputs['TangentU'].sv_set(tangent_u_out) self.outputs['TangentV'].sv_set(tangent_v_out) self.outputs['Matrix'].sv_set(matrix_out) self.outputs['AreaStretch'].sv_set(area_out) self.outputs['StretchU'].sv_set(du_out) self.outputs['StretchV'].sv_set(dv_out)