def process(self): if not any(socket.is_linked for socket in self.outputs): return 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, )) points_out = [] t1_out = [] t2_out = [] for curve1s, curve2s in zip_long_repeat(curve1_s, curve2_s): new_points = [] new_t1 = [] new_t2 = [] for curve1, curve2 in self.match(curve1s, curve2s): curve1 = SvNurbsCurve.to_nurbs(curve1) if curve1 is None: raise Exception("Curve1 is not a NURBS") curve2 = SvNurbsCurve.to_nurbs(curve2) if curve2 is None: raise Exception("Curve2 is not a NURBS") if self.implementation == 'SCIPY': t1s, t2s, ps = self.process_native(curve1, curve2) else: t1s, t2s, ps = self.process_freecad(curve1, curve2) if self.check_intersection: if not ps: raise Exception("Some curves do not intersect!") if self.single: if len(ps) >= 1: ps = ps[0] t1s = t1s[0] t2s = t2s[0] new_points.append(ps) new_t1.append(t1s) new_t2.append(t2s) if self.split: n = len(curve1s) new_points = split_by_count(new_points, n) new_t1 = split_by_count(new_t1, n) new_t1 = transpose_list(new_t1) new_t2 = split_by_count(new_t2, n) points_out.append(new_points) t1_out.append(new_t1) t2_out.append(new_t2) self.outputs['Intersections'].sv_set(points_out) self.outputs['T1'].sv_set(t1_out) self.outputs['T2'].sv_set(t2_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 curve_s = self.inputs['Curve'].sv_get() knot_s = self.inputs['Knot'].sv_get() count_s = self.inputs['Count'].sv_get() input_level = get_data_nesting_level(curve_s, data_types=(SvCurve, )) flat_output = input_level < 2 curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, )) knot_s = ensure_nesting_level(knot_s, 3) count_s = ensure_nesting_level(count_s, 3) curves_out = [] for curves, knots_i, counts_i in zip_long_repeat( curve_s, knot_s, count_s): new_curves = [] for curve, knots, counts in zip_long_repeat( curves, knots_i, counts_i): curve = SvNurbsCurve.to_nurbs(curve) if curve is None: raise Exception("One of curves is not NURBS") for knot, count in zip_long_repeat(knots, counts): curve = curve.insert_knot(knot, count, if_possible=self.if_possible) new_curves.append(curve) if flat_output: curves_out.extend(new_curves) else: curves_out.append(new_curves) self.outputs['Curve'].sv_set(curves_out)
def deconstruct(self, curve): nurbs = SvNurbsCurve.to_nurbs(curve) if nurbs is None: nurbs = curve try: degree = nurbs.get_degree() except: degree = None if hasattr(nurbs, 'get_knotvector'): knots = nurbs.get_knotvector().tolist() else: knots = [] try: points = nurbs.get_control_points().tolist() except Exception as e: points = [] if hasattr(nurbs, 'get_weights'): weights = nurbs.get_weights().tolist() else: weights = [] return degree, knots, points, weights
def process(self): if not any(socket.is_linked for socket in self.outputs): return curve_s = self.inputs['Curve'].sv_get() input_level = get_data_nesting_level(curve_s, data_types=(SvCurve,)) flat_output = input_level < 2 curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve,)) tolerance = self.tolerance curves_out = [] for curves in curve_s: new_curves = [] for curve in curves: curve = SvNurbsCurve.to_nurbs(curve) if curve is None: raise Exception("One of curves is not NURBS") curve = remove_excessive_knots(curve, tolerance=tolerance) new_curves.append(curve) if flat_output: curves_out.extend(new_curves) else: curves_out.append(new_curves) self.outputs['Curve'].sv_set(curves_out)
def to_nurbs(self, curves): result = [] for i,c in enumerate(curves): nurbs = SvNurbsCurve.to_nurbs(c) if nurbs is None: raise Exception(f"Curve #{i} - {c} - can not be converted to NURBS!") result.append(nurbs) return result
def process(self): if not any(socket.is_linked for socket in self.outputs): return curve_s = self.inputs['Curve'].sv_get() field_s = self.inputs['Field'].sv_get() coeff_s = self.inputs['Coefficient'].sv_get() curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, )) field_s = ensure_nesting_level(field_s, 2, data_types=(SvVectorField, )) coeff_s = ensure_nesting_level(coeff_s, 2) curve_out = [] for curve_i, field_i, coeff_i in zip_long_repeat( curve_s, field_s, coeff_s): new_curves = [] for curve, field, coeff in zip_long_repeat(curve_i, field_i, coeff_i): if self.use_control_points: nurbs = SvNurbsCurve.to_nurbs(curve) if nurbs is not None: control_points = nurbs.get_control_points() else: raise Exception("Curve is not a NURBS!") cpt_xs = control_points[:, 0] cpt_ys = control_points[:, 1] cpt_zs = control_points[:, 2] cpt_dxs, cpt_dys, cpt_dzs = field.evaluate_grid( cpt_xs, cpt_ys, cpt_zs) xs = cpt_xs + coeff * cpt_dxs ys = cpt_ys + coeff * cpt_dys zs = cpt_zs + coeff * cpt_dzs control_points = np.stack((xs, ys, zs)).T knotvector = nurbs.get_knotvector() #old_t_min, old_t_max = curve.get_u_bounds() #knotvector = sv_knotvector.rescale(knotvector, old_t_min, old_t_max) new_curve = SvNurbsCurve.build( nurbs.get_nurbs_implementation(), nurbs.get_degree(), knotvector, control_points, nurbs.get_weights()) new_curve.u_bounds = nurbs.u_bounds else: new_curve = SvDeformedByFieldCurve(curve, field, coeff) new_curves.append(new_curve) if self.join: curve_out.extend(new_curves) else: curve_out.append(new_curves) self.outputs['Curve'].sv_set(curve_out)
def cut(self, face_surface, sv_curves, point, vector): # face_surface : SvFreeCadNurbsSurface nurbs = [SvNurbsCurve.to_nurbs(curve) for curve in sv_curves] if any(c is None for c in nurbs): raise Exception("One of curves is not a NURBS!") fc_nurbs_curves = [SvFreeCadNurbsCurve.from_any_nurbs(c) for c in nurbs] fc_nurbs = [c.curve for c in fc_nurbs_curves] if self.projection_type in {'PARALLEL', 'PERSPECTIVE', 'ORTHO'}: try: fc_edges = [Part.Edge(c) for c in fc_nurbs] except Exception as e: raise Exception(f"Can't build edges from {fc_nurbs}: {e}") fc_face = Part.Face(face_surface.surface) if self.projection_type == 'PARALLEL': vector = Base.Vector(*vector) projections = [fc_face.makeParallelProjection(edge, vector) for edge in fc_edges] projections = [p.Edges for p in projections] elif self.projection_type == 'PERSPECTIVE': point = Base.Vector(*point) projections = [fc_face.makePerspectiveProjection(edge, point).Edges for edge in fc_edges] elif self.projection_type == 'ORTHO': projections = [fc_face.project(fc_edges).Edges] else: # UV uv_curves = [c.to_2d() for c in fc_nurbs_curves] fc_nurbs_2d = [c.curve for c in uv_curves] projections = [[c.toShape(face_surface.surface) for c in fc_nurbs_2d]] projections = sum(projections, []) if not projections: words = f"along {vector}" if self.projection_type == 'PARALLEL' else f"from {point}" raise Exception(f"Projection {words} of {sv_curves} onto {face_surface} is empty for some reason") try: wire = Part.Wire(projections) except Exception as e: ps = [SvFreeCadNurbsCurve(p.Curve) for p in projections] raise Exception(f"Can't make a valid Wire out of curves {sv_curves} projected onto {face_surface}:\n{e}\nProjections are: {ps}") cut_fc_face = Part.Face(face_surface.surface, wire) cut_face_surface = SvFreeCadNurbsSurface(face_surface.surface, face=cut_fc_face) if self.projection_type != 'UV': uv_curves = [] for edge in cut_fc_face.OuterWire.Edges: trim,m,M = cut_fc_face.curveOnSurface(edge) trim = SvFreeCadCurve(trim, (m,M), ndim=2) uv_curves.append(trim) projections = [SvSolidEdgeCurve(p) for p in projections] return uv_curves, projections, cut_face_surface
def _cast_nurbs(self, curve, center, direction, radius, coeff): curve = SvNurbsCurve.to_nurbs(curve) if curve is None: raise Exception("Provided curve is not a NURBS") if self.form == 'PLANE': target = PlaneEquation.from_normal_and_point(direction, center) elif self.form == 'SPHERE': target = SphereEquation(center, radius) elif self.form == 'CYLINDER': target = CylinderEquation.from_point_direction_radius(center, direction, radius) else: raise Exception("Unsupported target form") return cast_nurbs_curve(curve, target, coeff=coeff)
def process(self): if not any(socket.is_linked for socket in self.outputs): return curves_s = self.inputs['Curve'].sv_get() point_s = self.inputs['Point'].sv_get() normal_s = self.inputs['Normal'].sv_get() curves_s = ensure_nesting_level(curves_s, 2, data_types=(SvCurve, )) points_out = [] t_out = [] tolerance = 10**(-self.accuracy) for curves, points, normals in zip_long_repeat( curves_s, point_s, normal_s): new_points = [] new_ts = [] for curve, point, normal in zip_long_repeat( curves, points, normals): method = EQUATION if self.use_nurbs: c = SvNurbsCurve.to_nurbs(curve) if c is not None: curve = c method = NURBS plane = PlaneEquation.from_normal_and_point(normal, point) ps = intersect_curve_plane(curve, plane, method=method, init_samples=self.samples, tolerance=tolerance) ts = [p[0] for p in ps] points = [p[1].tolist() for p in ps] if self.join: new_points.extend(points) new_ts.extend(ts) else: new_points.append(points) new_ts.append(ts) points_out.append(new_points) t_out.append(new_ts) self.outputs['Point'].sv_set(points_out) self.outputs['T'].sv_set(t_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return curve_s = self.inputs['Curve'].sv_get() init_cuts_s = self.inputs['InitCuts'].sv_get() tolerance_s = self.inputs['Tolerance'].sv_get() curve_s = ensure_nesting_level(curve_s, 2, data_types=(SvCurve, )) init_cuts_s = ensure_nesting_level(init_cuts_s, 2) tolerance_s = ensure_nesting_level(tolerance_s, 2) need_verts = self.outputs['Vertices'].is_linked verts_out = [] edges_out = [] ts_out = [] for params in zip_long_repeat(curve_s, init_cuts_s, tolerance_s): new_verts = [] new_edges = [] new_ts = [] for curve, init_cuts, tolerance in zip_long_repeat(*params): curve = SvNurbsCurve.to_nurbs(curve) if curve is None: raise Exception("Curve is not NURBS") ts = curve.calc_linear_segment_knots(splits=init_cuts, tolerance=tolerance) new_ts.append(ts.tolist()) if need_verts: verts = curve.evaluate_array(ts) new_verts.append(verts.tolist()) n = len(ts) edges = [(i, i + 1) for i in range(n - 1)] new_edges.append(edges) if self.join: verts_out.extend(new_verts) edges_out.extend(new_edges) ts_out.extend(new_ts) else: verts_out.append(new_verts) edges_out.append(new_edges) ts_out.append(new_ts) self.outputs['Vertices'].sv_set(verts_out) self.outputs['Edges'].sv_set(edges_out) self.outputs['T'].sv_set(ts_out)
def curve_to_freecad_nurbs(sv_curve): """ Convert SvCurve to FreeCAD's NURBS curve. Raise an exception if it is not possible. input: SvCurve output: SvFreeCadNurbsCurve """ nurbs = SvNurbsCurve.to_nurbs(sv_curve) if nurbs is None: raise TypeError(f"{sv_curve} is not a NURBS curve") fc_curve = SvNurbsMaths.build_curve(SvNurbsMaths.FREECAD, nurbs.get_degree(), nurbs.get_knotvector(), nurbs.get_control_points(), nurbs.get_weights()) return fc_curve
def process(self): if not any(socket.is_linked for socket in self.outputs): return curves_s = self.inputs['Curves'].sv_get() degrees_s = self.inputs['DegreeV'].sv_get() curves_s = ensure_nesting_level(curves_s, 3, data_types=(SvCurve, )) degrees_s = ensure_nesting_level(degrees_s, 2) surface_out = [] curves_out = [] v_curves_out = [] for curves_i, degrees in zip_long_repeat(curves_s, degrees_s): new_surfaces = [] new_curves = [] new_v_curves = [] for curves, degree_v in zip_long_repeat(curves_i, degrees): curves = [SvNurbsCurve.to_nurbs(c) for c in curves] if any(c is None for c in curves): raise Exception("Some of curves are not NURBS!") unified_curves, v_curves, new_surface = simple_loft( curves, degree_v=degree_v, knots_u=self.u_knots_mode, metric=self.metric, implementation=self.nurbs_implementation) new_surfaces.append(new_surface) new_curves.extend(unified_curves) new_v_curves.extend(v_curves) surface_out.append(new_surfaces) curves_out.append(new_curves) v_curves_out.append(new_v_curves) self.outputs['Surface'].sv_set(surface_out) self.outputs['UnifiedCurves'].sv_set(curves_out) self.outputs['VCurves'].sv_set(v_curves_out)
def coons_surface(curve1, curve2, curve3, curve4): curves = [curve1, curve2, curve3, curve4] nurbs_curves = [SvNurbsCurve.to_nurbs(c) for c in curves] if any(c is None for c in nurbs_curves): return SvCoonsSurface(*curves) try: nurbs_curves = [c.reparametrize(0, 1) for c in nurbs_curves] degrees = [c.get_degree() for c in nurbs_curves] implementation = nurbs_curves[0].get_nurbs_implementation() if degrees[0] > degrees[2]: nurbs_curves[2] = nurbs_curves[2].elevate_degree(delta=degrees[0] - degrees[2]) if degrees[2] > degrees[0]: nurbs_curves[0] = nurbs_curves[0].elevate_degree(delta=degrees[2] - degrees[0]) if degrees[1] > degrees[3]: nurbs_curves[3] = nurbs_curves[3].elevate_degree(delta=degrees[1] - degrees[3]) if degrees[3] > degrees[1]: nurbs_curves[1] = nurbs_curves[1].elevate_degree(delta=degrees[3] - degrees[1]) degree_u = nurbs_curves[0].get_degree() degree_v = nurbs_curves[1].get_degree() knotvectors = [c.get_knotvector() for c in nurbs_curves] if not sv_knotvector.equal(knotvectors[0], knotvectors[2]): nurbs_curves[0], nurbs_curves[2] = unify_two_curves( nurbs_curves[0], nurbs_curves[2]) if not sv_knotvector.equal(knotvectors[1], knotvectors[3]): nurbs_curves[1], nurbs_curves[3] = unify_two_curves( nurbs_curves[1], nurbs_curves[3]) nurbs_curves[0] = reverse_curve(nurbs_curves[0]) nurbs_curves[3] = reverse_curve(nurbs_curves[3]) ruled1 = nurbs_curves[0].make_ruled_surface(nurbs_curves[2], 0, 1) ruled2 = nurbs_curves[1].make_ruled_surface(nurbs_curves[3], 0, 1).swap_uv() ruled1 = ruled1.elevate_degree(SvNurbsSurface.V, target=degree_v) ruled2 = ruled2.elevate_degree(SvNurbsSurface.U, target=degree_u) diff_1to2 = sv_knotvector.difference(ruled1.get_knotvector_v(), ruled2.get_knotvector_v()) diff_2to1 = sv_knotvector.difference(ruled2.get_knotvector_u(), ruled1.get_knotvector_u()) for v, count in diff_1to2: #print(f"R1: insert V={v} {count} times") ruled1 = ruled1.insert_knot(SvNurbsSurface.V, v, count) for u, count in diff_2to1: #print(f"R2: insert U={u} {count} times") ruled2 = ruled2.insert_knot(SvNurbsSurface.U, u, count) #print(f"R1: {ruled1.get_control_points().shape}, R2: {ruled2.get_control_points().shape}") linear_kv = sv_knotvector.generate(1, 2) c1_t_min, c1_t_max = nurbs_curves[0].get_u_bounds() c3_t_min, c3_t_max = nurbs_curves[2].get_u_bounds() pt1 = nurbs_curves[0].evaluate(c1_t_min) pt2 = nurbs_curves[0].evaluate(c1_t_max) pt3 = nurbs_curves[2].evaluate(c3_t_min) pt4 = nurbs_curves[2].evaluate(c3_t_max) w1 = nurbs_curves[0].get_weights()[0] w2 = nurbs_curves[0].get_weights()[-1] w3 = nurbs_curves[2].get_weights()[0] w4 = nurbs_curves[2].get_weights()[-1] linear_pts = np.array([[pt1, pt3], [pt2, pt4]]) linear_weights = np.array([[w1, w3], [w2, w4]]) #linear_weights = np.array([[1,1], [1,1]]) bilinear = SvNurbsSurface.build(implementation, 1, 1, linear_kv, linear_kv, linear_pts, linear_weights) bilinear = bilinear.elevate_degree(SvNurbsSurface.U, target=degree_u) bilinear = bilinear.elevate_degree(SvNurbsSurface.V, target=degree_v) knotvector_u = ruled1.get_knotvector_u() knotvector_v = ruled2.get_knotvector_v() for u, count in sv_knotvector.get_internal_knots( knotvector_u, output_multiplicity=True): #print(f"B: insert U={u} {count} times") bilinear = bilinear.insert_knot(SvNurbsSurface.U, u, count) for v, count in sv_knotvector.get_internal_knots( knotvector_v, output_multiplicity=True): #print(f"B: insert V={v} {count} times") bilinear = bilinear.insert_knot(SvNurbsSurface.V, v, count) control_points = ruled1.get_control_points( ) + ruled2.get_control_points() - bilinear.get_control_points() weights = ruled1.get_weights() + ruled2.get_weights( ) - bilinear.get_weights() result = SvNurbsSurface.build(implementation, degree_u, degree_v, knotvector_u, knotvector_v, control_points, weights) return result except UnsupportedCurveTypeException as e: info("Can't create a native Coons surface from curves %s: %s", curves, e) return SvCoonsSurface(*curves)
def coons_surface(curve1, curve2, curve3, curve4, use_nurbs=NURBS_IF_POSSIBLE): curves = [curve1, curve2, curve3, curve4] nurbs_curves = [SvNurbsCurve.to_nurbs(c) for c in curves] if use_nurbs == GENERIC: return SvCoonsSurface(*curves) if any(c is None for c in nurbs_curves): if use_nurbs == NURBS_ONLY: raise UnsupportedCurveTypeException("Some of curves are not NURBS") else: return SvCoonsSurface(*curves) try: nurbs_curves = [c.reparametrize(0, 1) for c in nurbs_curves] degrees = [c.get_degree() for c in nurbs_curves] implementation = nurbs_curves[0].get_nurbs_implementation() nurbs_curves[0], nurbs_curves[2] = unify_curves( [nurbs_curves[0], nurbs_curves[2]]) nurbs_curves[1], nurbs_curves[3] = unify_curves( [nurbs_curves[1], nurbs_curves[3]]) degree_u = nurbs_curves[0].get_degree() degree_v = nurbs_curves[1].get_degree() nurbs_curves[0] = reverse_curve(nurbs_curves[0]) nurbs_curves[3] = reverse_curve(nurbs_curves[3]) ruled1 = nurbs_curves[0].make_ruled_surface(nurbs_curves[2], 0, 1) ruled2 = nurbs_curves[1].make_ruled_surface(nurbs_curves[3], 0, 1).swap_uv() linear_kv = sv_knotvector.generate(1, 2) c1_t_min, c1_t_max = nurbs_curves[0].get_u_bounds() c3_t_min, c3_t_max = nurbs_curves[2].get_u_bounds() pt1 = nurbs_curves[0].evaluate(c1_t_min) pt2 = nurbs_curves[0].evaluate(c1_t_max) pt3 = nurbs_curves[2].evaluate(c3_t_min) pt4 = nurbs_curves[2].evaluate(c3_t_max) w1 = nurbs_curves[0].get_weights()[0] w2 = nurbs_curves[0].get_weights()[-1] w3 = nurbs_curves[2].get_weights()[0] w4 = nurbs_curves[2].get_weights()[-1] linear_pts = np.array([[pt1, pt3], [pt2, pt4]]) linear_weights = np.array([[w1, w3], [w2, w4]]) #linear_weights = np.array([[1,1], [1,1]]) bilinear = SvNurbsSurface.build(implementation, 1, 1, linear_kv, linear_kv, linear_pts, linear_weights) ruled1, ruled2, bilinear = unify_nurbs_surfaces( [ruled1, ruled2, bilinear]) knotvector_u = ruled1.get_knotvector_u() knotvector_v = ruled1.get_knotvector_v() control_points = ruled1.get_control_points( ) + ruled2.get_control_points() - bilinear.get_control_points() weights = ruled1.get_weights() + ruled2.get_weights( ) - bilinear.get_weights() result = SvNurbsSurface.build(implementation, degree_u, degree_v, knotvector_u, knotvector_v, control_points, weights) return result except UnsupportedCurveTypeException as e: if use_nurbs == NURBS_ONLY: raise else: info("Can't create a native Coons surface from curves %s: %s", curves, e) return SvCoonsSurface(*curves)
def process(self): if not any(socket.is_linked for socket in self.outputs): return path1_s = self.inputs['Path1'].sv_get() path2_s = self.inputs['Path2'].sv_get() profile_s = self.inputs['Profile'].sv_get() if self.explicit_v: v1_s = self.inputs['V1'].sv_get() v1_s = ensure_nesting_level(v1_s, 3) v2_s = self.inputs['V2'].sv_get() v2_s = ensure_nesting_level(v2_s, 3) else: v1_s = [[[]]] v2_s = [[[]]] profiles_count_s = self.inputs['VSections'].sv_get() degree_v_s = self.inputs['DegreeV'].sv_get() path1_s = ensure_nesting_level(path1_s, 2, data_types=(SvCurve, )) path2_s = ensure_nesting_level(path2_s, 2, data_types=(SvCurve, )) profile_s = ensure_nesting_level(profile_s, 3, data_types=(SvCurve, )) profiles_count_s = ensure_nesting_level(profiles_count_s, 2) degree_v_s = ensure_nesting_level(degree_v_s, 2) surfaces_out = [] curves_out = [] v_curves_out = [] for params in zip_long_repeat(path1_s, path2_s, profile_s, v1_s, v2_s, profiles_count_s, degree_v_s): new_surfaces = [] new_curves = [] new_v_curves = [] new_profiles = [] for path1, path2, profiles, vs1, vs2, profiles_count, degree_v in zip_long_repeat( *params): path1 = SvNurbsCurve.to_nurbs(path1) if path1 is None: raise Exception("Path #1 is not a NURBS curve!") path2 = SvNurbsCurve.to_nurbs(path2) if path2 is None: raise Exception("Path #2 is not a NURBS curve!") profiles = [ SvNurbsCurve.to_nurbs(profile) for profile in profiles ] if any(p is None for p in profiles): raise Exception("Some of profiles are not NURBS curves!") if self.explicit_v: ts1 = np.array(vs1) ts2 = np.array(vs2) else: ts1 = None ts2 = None _, unified_curves, v_curves, surface = nurbs_birail( path1, path2, profiles, ts1=ts1, ts2=ts2, min_profiles=profiles_count, knots_u=self.u_knots_mode, degree_v=degree_v, metric=self.metric, scale_uniform=self.scale_uniform, implementation=self.nurbs_implementation) new_surfaces.append(surface) new_curves.extend(unified_curves) new_v_curves.extend(v_curves) surfaces_out.append(new_surfaces) curves_out.append(new_curves) v_curves_out.append(new_v_curves) self.outputs['Surface'].sv_set(surfaces_out) self.outputs['AllProfiles'].sv_set(curves_out) self.outputs['VCurves'].sv_set(v_curves_out)
def intersect_curve_surface(curve, surface, init_samples=10, raycast_samples=10, tolerance=1e-3, maxiter=50, raycast_method='hybr', support_nurbs=False): """ Intersect a curve with a surface. dependencies: scipy """ u_min, u_max = curve.get_u_bounds() is_nurbs = False c = SvNurbsCurve.to_nurbs(curve) if c is not None: curve = c is_nurbs = True raycaster = SurfaceRaycaster(surface) raycaster.init_bvh(raycast_samples) def do_raycast(point, tangent, sign=1): good_sign = sign raycast = raycaster.raycast([point], [sign * tangent], method=raycast_method, on_init_fail=RETURN_NONE) if raycast is None: good_sign = -sign raycast = raycaster.raycast([point], [-sign * tangent], method=raycast_method, on_init_fail=RETURN_NONE) return good_sign, raycast good_ranges = [] u_range = np.linspace(u_min, u_max, num=init_samples) points = curve.evaluate_array(u_range) tangents = curve.tangent_array(u_range) for u1, u2, p1, p2, tangent1, tangent2 in zip(u_range, u_range[1:], points, points[1:], tangents, tangents[1:]): raycast = raycaster.raycast([p1, p2], [tangent1, -tangent2], precise=False, calc_points=False, on_init_fail=RETURN_NONE) if raycast is None: continue good_ranges.append((u1, u2, raycast.points[0], raycast.points[1])) def to_curve(point, curve, u1, u2, raycast=None): if support_nurbs and is_nurbs and raycast is not None: segment = curve.cut_segment(u1, u2) surface_u, surface_v = raycast.us[0], raycast.vs[0] point_on_surface = raycast.points[0] surface_normal = surface.normal(surface_u, surface_v) plane = PlaneEquation.from_normal_and_point( surface_normal, point_on_surface) r = intersect_curve_plane_nurbs(segment, plane, init_samples=2, tolerance=tolerance, maxiter=maxiter) if not r: return None else: return r[0] else: ortho = ortho_project_curve(point, curve, subdomain=(u1, u2), init_samples=2, on_fail=RETURN_NONE) if ortho is None: return None else: return ortho.nearest_u, ortho.nearest result = [] for u1, u2, init_p1, init_p2 in good_ranges: tangent = curve.tangent(u1) point = curve.evaluate(u1) i = 0 sign = 1 prev_prev_point = None prev_point = init_p1 u_root = None point_found = False raycast = None while True: i += 1 if i > maxiter: raise Exception( "Maximum number of iterations is exceeded; last step {} - {} = {}" .format(prev_prev_point, point, step)) on_curve = to_curve(prev_point, curve, u1, u2, raycast=raycast) if on_curve is None: break u_root, point = on_curve if u_root < u1 or u_root > u2: break step = np.linalg.norm(point - prev_point) if step < tolerance and i > 1: debug("After ortho: Point {}, prev {}, iter {}".format( point, prev_point, i)) point_found = True break prev_point = point tangent = curve.tangent(u_root) sign, raycast = do_raycast(point, tangent, sign) if raycast is None: raise Exception( "Iteration #{}: Can't do a raycast with point {}, direction {} onto surface {}" .format(i, point, tangent, surface)) point = raycast.points[0] step = np.linalg.norm(point - prev_point) prev_prev_point = prev_point prev_point = point if point_found: result.append((u_root, point)) return result
def process(self): if not any(socket.is_linked for socket in self.outputs): return path_s = self.inputs['Path'].sv_get() profile_s = self.inputs['Profile'].sv_get() if self.explicit_v: v_s = self.inputs['V'].sv_get() v_s = ensure_nesting_level(v_s, 3) else: v_s = [[[]]] profiles_count_s = self.inputs['VSections'].sv_get() resolution_s = self.inputs['Resolution'].sv_get() normal_s = self.inputs['Normal'].sv_get() path_s = ensure_nesting_level(path_s, 2, data_types=(SvCurve,)) profile_s = ensure_nesting_level(profile_s, 3, data_types=(SvCurve,)) resolution_s = ensure_nesting_level(resolution_s, 2) normal_s = ensure_nesting_level(normal_s, 3) profiles_count_s = ensure_nesting_level(profiles_count_s, 2) surfaces_out = [] curves_out = [] v_curves_out = [] for params in zip_long_repeat(path_s, profile_s, v_s, profiles_count_s, resolution_s, normal_s): new_surfaces = [] new_curves = [] new_v_curves = [] new_profiles = [] for path, profiles, vs, profiles_count, resolution, normal in zip_long_repeat(*params): path = SvNurbsCurve.to_nurbs(path) if path is None: raise Exception("Path is not a NURBS curve!") profiles = [SvNurbsCurve.to_nurbs(profile) for profile in profiles] if any(p is None for p in profiles): raise Exception("Some of profiles are not NURBS curves!") if self.explicit_v: ts = np.array(vs) else: ts = None _, unified_curves, v_curves, surface = nurbs_sweep(path, profiles, ts = ts, min_profiles = profiles_count, algorithm = self.algorithm, knots_u = self.u_knots_mode, metric = self.metric, implementation = self.nurbs_implementation, resolution = resolution, normal = np.array(normal)) new_surfaces.append(surface) new_curves.extend(unified_curves) new_v_curves.extend(v_curves) surfaces_out.append(new_surfaces) curves_out.append(new_curves) v_curves_out.append(new_v_curves) self.outputs['Surface'].sv_set(surfaces_out) if 'AllProfiles' in self.outputs: self.outputs['AllProfiles'].sv_set(curves_out) if 'VCurves' in self.outputs: self.outputs['VCurves'].sv_set(v_curves_out)
def process(self): if not any(socket.is_linked for socket in self.outputs): return path_s = self.inputs['Path'].sv_get() profile_s = self.inputs['Profile'].sv_get() if self.inputs['Taper'].is_linked: scale_base = 'TAPER' taper_s = self.inputs['Taper'].sv_get() taper_s = ensure_nesting_level(taper_s, 2, data_types=(SvCurve, )) else: scale_base = 'PROFILE' taper_s = [[None]] resolution_s = self.inputs['Resolution'].sv_get() taper_samples_s = self.inputs['ProfileCopies'].sv_get() taper_refine_s = self.inputs['TaperRefine'].sv_get() profile_samples_s = self.inputs['TaperCopies'].sv_get() input_level = get_data_nesting_level(path_s, data_types=(SvCurve, )) path_s = ensure_nesting_level(path_s, 2, data_types=(SvCurve, )) profile_s = ensure_nesting_level(profile_s, 2, data_types=(SvCurve, )) orient_axis = self._get_orient_axis_idx() surface_out = [] cap_start_out = [] cap_end_out = [] for params in zip_long_repeat(path_s, profile_s, taper_s, resolution_s, taper_samples_s, taper_refine_s, profile_samples_s): new_surfaces = [] new_cap_start = [] new_cap_end = [] for path, profile, taper, resolution, taper_samples, taper_refine, profile_samples in zip_long_repeat( *params): if taper is None: taper = self._make_unit_taper(path, profile) if self.curve_mode == 'GENERIC': surface = generic_bevel_curve( path, profile, taper, algorithm=self.algorithm, path_axis=orient_axis, path_length_resolution=resolution, up_axis=self.up_axis, scale_base=scale_base) else: path = SvNurbsCurve.to_nurbs(path) profile = SvNurbsCurve.to_nurbs(profile) taper = SvNurbsCurve.to_nurbs(taper) if path is None: raise Exception("One of paths is not a NURBS curve") if profile is None: raise Exception("One of profiles is not a NURBS curve") if taper is None: raise Exception("One of tapers is not a NURBS curve") surface = nurbs_bevel_curve( path, profile, taper, algorithm=self.algorithm, path_axis='XYZ'.index(self.orient_axis), path_length_resolution=resolution, up_axis=self.up_axis, precision_method=self.precision_method, taper_samples=taper_samples, taper_refine=taper_refine, profile_samples=profile_samples) v_min, v_max = surface.get_v_min(), surface.get_v_max() cap_start = SvIsoUvCurve.take(surface, 'V', v_min) cap_end = SvIsoUvCurve.take(surface, 'V', v_max) new_surfaces.append(surface) new_cap_start.append(cap_start) new_cap_end.append(cap_end) if input_level < 2: surface_out.extend(new_surfaces) cap_start_out.extend(new_cap_start) cap_end_out.extend(new_cap_end) else: surface_out.append(new_surfaces) cap_start_out.append(new_cap_start) cap_end_out.append(new_cap_end) self.outputs['Surface'].sv_set(surface_out) if 'CapStart' in self.outputs: self.outputs['CapStart'].sv_set(cap_start_out) if 'CapEnd' in self.outputs: self.outputs['CapEnd'].sv_set(cap_end_out)
def check_nurbs(*curves): return [SvNurbsCurve.to_nurbs(c) for c in curves]