def test_interpolate_1(self): "NURBS interpolation in 3D" points = np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0]], dtype=np.float64) degree = 2 curve = interpolate_nurbs_curve(SvNativeNurbsCurve, degree, points) ts = np.array([0, 0.5, 1]) result = curve.evaluate_array(ts) self.assert_numpy_arrays_equal(result, points, precision=6) ctrlpts = curve.get_control_points() expected_ctrlpts = np.array([[0.0, 0.0, 0.0], [1.5, -0.5, 0.0], [1.0, 1.0, 0.0]]) self.assert_numpy_arrays_equal(ctrlpts, expected_ctrlpts, precision=6)
def test_interpolate_2(self): "NURBS Interpolation in homogenous coordinates" points = np.array([[0, 0, 0, 1], [1, 0, 0, 2], [1, 1, 0, 1]], dtype=np.float64) degree = 2 curve = interpolate_nurbs_curve(SvNativeNurbsCurve, degree, points) ts = np.array([0, 0.5, 1]) result = curve.evaluate_array(ts) expected = np.array([[0, 0, 0], [0.5, 0, 0], [1, 1, 0]]) self.assert_numpy_arrays_equal(result, expected, precision=6) ctrlpts = curve.get_control_points() expected_ctrlpts = np.array([[0.0, 0.0, 0.0], [0.5, -0.16666667, 0.0], [1.0, 1.0, 0.0]]) self.assert_numpy_arrays_equal(ctrlpts, expected_ctrlpts, precision=6) weights = curve.get_weights() expected_weights = np.array([1, 3, 1]) self.assert_numpy_arrays_equal(weights, expected_weights, precision=6)
def interpolate(cls, degree, points, metric='DISTANCE'): return interpolate_nurbs_curve(cls, degree, points, metric)
def simple_loft(curves, degree_v=None, knots_u='UNIFY', metric='DISTANCE', tknots=None, implementation=SvNurbsSurface.NATIVE): """ Loft between given NURBS curves (a.k.a skinning). inputs: * degree_v - degree of resulting surface along V parameter; by default - use the same degree as provided curves * knots_u - one of: - 'UNIFY' - unify knotvectors of given curves by inserting additional knots - 'AVERAGE' - average knotvectors of given curves; this will work only if all curves have the same number of control points * metric - metric for interpolation; most useful are 'DISTANCE' and 'CENTRIPETAL' * implementation - NURBS maths implementation output: tuple: * list of curves - input curves after unification * list of NURBS curves along V direction * generated NURBS surface. """ if knots_u not in {'UNIFY', 'AVERAGE'}: raise Exception(f"Unsupported knots_u option: {knots_u}") curve_class = type(curves[0]) curves = unify_curves_degree(curves) if knots_u == 'UNIFY': curves = unify_curves(curves) else: kvs = [len(curve.get_control_points()) for curve in curves] max_kv, min_kv = max(kvs), min(kvs) if max_kv != min_kv: raise Exception( f"U knotvector averaging is not applicable: Curves have different number of control points: {kvs}" ) degree_u = curves[0].get_degree() if degree_v is None: degree_v = degree_u if degree_v > len(curves): raise Exception( f"V degree ({degree_v}) must be not greater than number of curves ({len(curves)}) minus 1" ) src_points = [curve.get_homogenous_control_points() for curve in curves] # lens = [len(pts) for pts in src_points] # max_len, min_len = max(lens), min(lens) # if max_len != min_len: # raise Exception(f"Unify error: curves have different number of control points: {lens}") src_points = np.array(src_points) #print("Src:", src_points) src_points = np.transpose(src_points, axes=(1, 0, 2)) v_curves = [ interpolate_nurbs_curve(curve_class, degree_v, points, metric=metric, tknots=tknots) for points in src_points ] control_points = [ curve.get_homogenous_control_points() for curve in v_curves ] control_points = np.array(control_points) #weights = [curve.get_weights() for curve in v_curves] #weights = np.array([curve.get_weights() for curve in curves]).T n, m, ndim = control_points.shape control_points = control_points.reshape((n * m, ndim)) control_points, weights = from_homogenous(control_points) control_points = control_points.reshape((n, m, 3)) weights = weights.reshape((n, m)) mean_v_vector = control_points.mean(axis=0) tknots_v = Spline.create_knots(mean_v_vector, metric=metric) knotvector_v = sv_knotvector.from_tknots(degree_v, tknots_v) if knots_u == 'UNIFY': knotvector_u = curves[0].get_knotvector() else: knotvectors = np.array([curve.get_knotvector() for curve in curves]) knotvector_u = knotvectors.mean(axis=0) surface = SvNurbsSurface.build(implementation, degree_u, degree_v, knotvector_u, knotvector_v, control_points, weights) surface.u_bounds = curves[0].get_u_bounds() return curves, v_curves, surface