def nurbs_taper_sweep(profile, taper, point, direction, scale_base=SvTaperSweepSurface.UNIT): axis = LineEquation.from_direction_and_point(direction, point) taper_cpts = taper.get_control_points() taper_weights = taper.get_weights() taper_projections = axis.projection_of_points(taper_cpts) control_points = [] weights = [] if scale_base == SvTaperSweepSurface.TAPER: profile_t_min, profile_t_max = profile.get_u_bounds() profile_start = profile.evaluate(profile_t_min) profile_start_projection = axis.projection_of_point(profile_start) divisor = np.linalg.norm(profile_start - profile_start_projection) elif scale_base == SvTaperSweepSurface.PROFILE: taper_t_min, taper_t_max = taper.get_u_bounds() taper_start = taper.evaluate(taper_t_min) taper_start_projection = np.array( axis.projection_of_point(taper_start)) divisor = np.linalg.norm(taper_start_projection - taper_start) else: divisor = 1.0 profile_cpts = profile.get_control_points() n = len(profile_cpts) profile_knotvector = profile.get_knotvector() profile_weights = profile.get_weights() for taper_control_point, taper_projection, taper_weight in zip( taper_cpts, taper_projections, taper_weights): radius = np.linalg.norm(taper_control_point - taper_projection) if radius < 1e-8: parallel_points = np.empty((n, 3)) parallel_points[:] = taper_projection else: parallel_points = place_profile(profile_cpts, taper_projection, radius / divisor) parallel_weights = profile_weights * taper_weight control_points.append(parallel_points) weights.append(parallel_weights) control_points = np.array(control_points) control_points -= point weights = np.array(weights) degree_u = taper.get_degree() degree_v = profile.get_degree() return SvNurbsSurface.build(taper.get_nurbs_implementation(), degree_u, degree_v, taper.get_knotvector(), profile_knotvector, control_points, weights)
def process(self): if not any(socket.is_linked for socket in self.outputs): return surface_s = self.inputs['Surface'].sv_get() field_s = self.inputs['Field'].sv_get() coeff_s = self.inputs['Coefficient'].sv_get() surface_out = [] for surface, field, coeff in zip_long_repeat(surface_s, field_s, coeff_s): if isinstance(coeff, (list, tuple)): coeff = coeff[0] if self.use_control_points: nurbs = SvNurbsSurface.get(surface) if nurbs is not None: control_points = nurbs.get_control_points() else: raise Exception("Surface is not a NURBS!") m, n, _ = control_points.shape control_points = control_points.reshape((m * n, 3)) 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 control_points = control_points.reshape((m, n, 3)) new_surface = SvNurbsSurface.build( nurbs.get_nurbs_implementation(), nurbs.get_degree_u(), nurbs.get_degree_v(), nurbs.get_knotvector_u(), nurbs.get_knotvector_v(), control_points, nurbs.get_weights()) else: new_surface = SvDeformedByFieldSurface( surface, field, coeff, by_normal=self.by_normal) surface_out.append(new_surface) self.outputs['Surface'].sv_set(surface_out)
def nurbs_revolution_surface(curve, origin, axis, v_min=0, v_max=2 * pi, global_origin=True): my_control_points = curve.get_control_points() my_weights = curve.get_weights() control_points = [] weights = [] any_circle = SvCircle(Matrix(), 1) any_circle.u_bounds = (v_min, v_max) any_circle = any_circle.to_nurbs() # all circles with given (v_min, v_max) # actually always have the same knotvector # and the same number of control points n = len(any_circle.get_control_points()) circle_knotvector = any_circle.get_knotvector() circle_weights = any_circle.get_weights() # TODO: vectorize with numpy? Or better let it so for better readability? for my_control_point, my_weight in zip(my_control_points, my_weights): eq = CircleEquation3D.from_axis_point(origin, axis, my_control_point) if abs(eq.radius) < 1e-8: parallel_points = np.empty((n, 3)) parallel_points[:] = np.array(eq.center) #[np.newaxis].T else: circle = SvCircle.from_equation(eq) circle.u_bounds = (v_min, v_max) nurbs_circle = circle.to_nurbs() parallel_points = nurbs_circle.get_control_points() parallel_weights = circle_weights * my_weight control_points.append(parallel_points) weights.append(parallel_weights) control_points = np.array(control_points) if global_origin: control_points = control_points - origin weights = np.array(weights) degree_u = curve.get_degree() degree_v = 2 # circle return SvNurbsSurface.build(curve.get_nurbs_implementation(), degree_u, degree_v, curve.get_knotvector(), circle_knotvector, control_points, weights)
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 get_surface(self, spline, matrix): surface_degree_u = spline.order_u - 1 surface_degree_v = spline.order_v - 1 spline_points = split_by_count(spline.points, spline.point_count_u) if self.apply_matrix: control_points = [[list(matrix @ Vector(p.co[:3])) for p in row] for row in spline_points] else: control_points = [[tuple(p.co) for p in row] for row in spline_points] surface_weights = [[p.co[3] for p in row] for row in spline_points] if spline.use_cyclic_v: for row_idx in range(len(control_points)): control_points[row_idx].extend( control_points[row_idx][:spline.order_v]) if spline.use_cyclic_u: control_points.extend(control_points[:spline.order_u]) # Control points n_u_total = len(control_points) n_v_total = len(control_points[0]) if spline.use_cyclic_u: knots_u = list(range(n_u_total + spline.order_u)) else: knots_u = sv_knotvector.generate(surface_degree_u, n_u_total, clamped=spline.use_endpoint_u) self.debug("Auto knots U: %s", knots_u) if spline.use_cyclic_v: knots_v = list(range(n_v_total + spline.order_v)) else: knots_v = sv_knotvector.generate(surface_degree_v, n_v_total, clamped=spline.use_endpoint_v) self.debug("Auto knots V: %s", knots_v) surface_knotvector_u = knots_u surface_knotvector_v = knots_v new_surf = SvNurbsSurface.build(self.implementation, surface_degree_u, surface_degree_v, surface_knotvector_u, surface_knotvector_v, control_points, surface_weights, normalize_knots=True) if spline.use_cyclic_u: u_min = surface_knotvector_u[surface_degree_u] u_max = surface_knotvector_u[-surface_degree_u - 2] else: if spline.use_endpoint_u: u_min = min(surface_knotvector_u) u_max = max(surface_knotvector_u) else: u_min = surface_knotvector_u[surface_degree_u] u_max = surface_knotvector_u[-surface_degree_u - 1] if spline.use_cyclic_v: v_min = surface_knotvector_v[surface_degree_v] v_max = surface_knotvector_v[-surface_degree_v - 2] else: if spline.use_endpoint_v: v_min = min(surface_knotvector_v) v_max = max(surface_knotvector_v) else: v_min = surface_knotvector_v[surface_degree_v] v_max = surface_knotvector_v[-surface_degree_v - 1] new_surf.u_bounds = u_min, u_max new_surf.v_bounds = v_min, v_max return new_surf
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 gordon_surface(u_curves, v_curves, intersections, metric='POINTS', u_knots=None, v_knots=None, knotvector_accuracy=6, reparametrize_tolerance=1e-2): """ Generate a NURBS surface from a net of NURBS curves, by use of Gordon's algorithm. :param u_curves - list of NURBS curves along U direciton (length N) :param v_curves - list of NURBS curves along V direcion (length M) :param intersections - np.array of shape (N, M, 3): points of curves intersection :param metric - metric function that can be used to calculate T values of curves intersections from their positions. :param u_knots - np.array, T values of curves intersection for each curve from u_curves :param v_knots - np.array, T values of curves intersection for each curve from v_curves return value: a NURBS surface. See also: The NURBS Book, 2nd ed., p.10.5. """ if not u_curves or not v_curves: raise Exception("U or V curves are not provided") if (u_knots is None) != (v_knots is None): raise Exception( "u_knots and v_knots must be either both provided or both omited") if any(c.is_rational() for c in u_curves): raise Exception( "Some of U-curves are rational. Rational curves are not supported for Gordon surface." ) if any(c.is_rational() for c in v_curves): raise Exception( "Some of V-curves are rational. Rational curves are not supported for Gordon surface." ) intersections = np.array(intersections) if u_knots is not None: loft_u_kwargs = loft_v_kwargs = interpolate_kwargs = { 'metric': 'POINTS' } u_curves = [ reparametrize_by_segments(c, knots, reparametrize_tolerance) for c, knots in zip(u_curves, u_knots) ] v_curves = [ reparametrize_by_segments(c, knots, reparametrize_tolerance) for c, knots in zip(v_curves, v_knots) ] #print("U", u_curves) #print("V", v_curves) else: loft_u_kwargs = loft_v_kwargs = interpolate_kwargs = {'metric': metric} u_curves = unify_curves_degree(u_curves) u_curves = unify_curves(u_curves, accuracy=knotvector_accuracy) #, method='AVERAGE') v_curves = unify_curves_degree(v_curves) v_curves = unify_curves(v_curves, accuracy=knotvector_accuracy) #, method='AVERAGE') u_curves_degree = u_curves[0].get_degree() v_curves_degree = v_curves[0].get_degree() n = len(intersections) m = len(intersections[0]) loft_v_degree = min(len(u_curves) - 1, v_curves_degree) loft_u_degree = min(len(v_curves) - 1, u_curves_degree) _, _, lofted_v = simple_loft(u_curves, degree_v=loft_v_degree, knotvector_accuracy=knotvector_accuracy, **loft_v_kwargs) _, _, lofted_u = simple_loft(v_curves, degree_v=loft_u_degree, knotvector_accuracy=knotvector_accuracy, **loft_u_kwargs) lofted_u = lofted_u.swap_uv() int_degree_u = min(m - 1, u_curves_degree) int_degree_v = min(n - 1, v_curves_degree) interpolated = interpolate_nurbs_surface(int_degree_u, int_degree_v, intersections, **interpolate_kwargs) interpolated = interpolated.swap_uv() #print(f"Loft.U: {lofted_u}") #print(f"Loft.V: {lofted_v}") #print(f"Interp: {interpolated}") #print(f" {interpolated.get_knotvector_u()}") #print(f" {interpolated.get_knotvector_v()}") lofted_u, lofted_v, interpolated = unify_nurbs_surfaces( [lofted_u, lofted_v, interpolated], knotvector_accuracy=knotvector_accuracy) control_points = lofted_u.get_control_points() + \ lofted_v.get_control_points() - \ interpolated.get_control_points() surface = SvNurbsSurface.build(SvNurbsSurface.NATIVE, interpolated.get_degree_u(), interpolated.get_degree_v(), interpolated.get_knotvector_u(), interpolated.get_knotvector_v(), control_points, weights=None) #print(f"Result: {surface}") return lofted_u, lofted_v, interpolated, surface
def make_surface(self, face, degree_u, degree_v, vertices, planes, vert_weights, tangent_weights, face_weight, edge_weights_dict, edge_planes_dict): """ V0 ------ [E01] --- [E0C] --- [E02] --- V1 | | | | | | | | | | | | | | | [E11] --- [F1] ---- [E0F] --- [F2] --- [E21] | | | | | | | | | | | | | | | [E1C] --- [E1F] --- [CC] --- [E2F] --- [E2C] | | | | | | | | | | | | | | | [E12] --- [F3] ---- [E3F] --- [F4] --- [E22] | | | | | | | | | | | | | | | V3 ------ [E31] --- [E3C] --- [E32] --- V2 """ tangent_weights = [w / 3.0 for w in tangent_weights] vertices = [Vector(v) for v in vertices] def mk_edge_point(i, j): return (vertices[j] - vertices[i]) * tangent_weights[i] + vertices[i] def mk_face_corner_point(i, j, k): dv1 = (vertices[j] - vertices[i]) * tangent_weights[i] dv2 = (vertices[k] - vertices[i]) * tangent_weights[i] #m = face_weight return planes[i].projection_of_point(vertices[i] + dv1 + dv2) # edge planes e0p = edge_planes_dict[(face[0], face[1])] e1p = edge_planes_dict[(face[0], face[3])] e2p = edge_planes_dict[(face[1], face[2])] e3p = edge_planes_dict[(face[2], face[3])] def mk_edge_center_point(ep1, ep2): return (ep1 + ep2) / 2.0 def mk_face_edge_point(edge_plane, edge_point, edge_vec, vec1, vec2): length = (vec1.length + vec2.length) / 2.0 vec = edge_plane.normal.cross(edge_vec) #print("EV: %s, N: %s, L: %s, Res: %s" % (edge_vec, edge_plane.normal, length, vec)) vec = length * vec.normalized() return edge_point + vec e01 = planes[0].projection_of_point(mk_edge_point(0, 1)) e02 = planes[1].projection_of_point(mk_edge_point(1, 0)) e11 = planes[0].projection_of_point(mk_edge_point(0, 3)) e21 = planes[1].projection_of_point(mk_edge_point(1, 2)) f1 = mk_face_corner_point(0, 1, 3) f2 = mk_face_corner_point(1, 0, 2) e12 = planes[3].projection_of_point(mk_edge_point(3, 0)) e31 = planes[3].projection_of_point(mk_edge_point(3, 2)) e32 = planes[2].projection_of_point(mk_edge_point(2, 3)) e22 = planes[2].projection_of_point(mk_edge_point(2, 1)) f3 = mk_face_corner_point(3, 0, 2) f4 = mk_face_corner_point(2, 3, 1) e0c = mk_edge_center_point(e01, e02) e1c = mk_edge_center_point(e11, e12) e2c = mk_edge_center_point(e21, e22) e3c = mk_edge_center_point(e31, e32) e0f = mk_face_edge_point(e0p, e0c, (vertices[1] - vertices[0]), (f1 - e01), (f2 - e02)) e1f = mk_face_edge_point(e1p, e1c, (vertices[0] - vertices[3]), (f3 - e12), (f1 - e11)) e2f = mk_face_edge_point(e2p, e2c, (vertices[2] - vertices[1]), (f2 - e21), (f4 - e22)) e3f = mk_face_edge_point(e3p, e3c, (vertices[3] - vertices[2]), (f3 - e31), (f4 - e32)) cc = center([f1, e0f, f2, e2f, f4, e3f, f3, e1f]) control_points = [[vertices[0], e01, e0c, e02, vertices[1]], [e11, f1, e0f, f2, e21], [e1c, e1f, cc, e2f, e2c], [e12, f3, e3f, f4, e22], [vertices[3], e31, e3c, e32, vertices[2]]] # edge point weights e0w = edge_weights_dict[(face[0], face[1])] e1w = edge_weights_dict[(face[0], face[3])] e2w = edge_weights_dict[(face[1], face[2])] e3w = edge_weights_dict[(face[2], face[3])] weights = [[vert_weights[0], e0w, e0w, e0w, vert_weights[1]], [e1w, face_weight, face_weight, face_weight, e2w], [e1w, face_weight, face_weight, face_weight, e2w], [e1w, face_weight, face_weight, face_weight, e2w], [vert_weights[3], e3w, e3w, e3w, vert_weights[2]]] new_surf = SvNurbsSurface.build(self.implementation, degree_u, degree_v, sv_knotvector.generate(degree_u, 5), sv_knotvector.generate(degree_v, 5), np.array(control_points), np.array(weights)) return new_surf, control_points, weights
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)