def test_from_nurbs_python_curve_to_ezdxf_bspline(): from geomdl.fitting import interpolate_curve curve = interpolate_curve([(0, 0), (0, 10), (10, 10), (10, 0)], degree=3) bspline = BSpline.from_nurbs_python_curve(curve) assert bspline.degree == 3 assert len(bspline.control_points) == 4 assert len(bspline.knots()) == 8 # count + order
def process(self): if not any(socket.is_linked for socket in self.outputs): return vertices_s = self.inputs['Vertices'].sv_get() degree_s = self.inputs['Degree'].sv_get() curves_out = [] points_out = [] knots_out = [] for vertices, degree in zip_long_repeat(vertices_s, degree_s): if isinstance(degree, (tuple, list)): degree = degree[0] curve = fitting.interpolate_curve(vertices, degree, centripetal=self.centripetal) points_out.append(curve.ctrlpts) knots_out.append(curve.knotvector) curve = SvGeomdlCurve(curve) curves_out.append(curve) self.outputs['Curve'].sv_set(curves_out) self.outputs['ControlPoints'].sv_set(points_out) self.outputs['Knots'].sv_set(knots_out)
def set_npoints(r, n): ''' Set the number of contour points. Notes: * The new contour points are calculated using NURBS interpolation. * The new contour points will be spaced equally from parametric position 0 to 1 around the contour. Inputs: * r : a single source contour as an (n,2) array or multiple source contours as an (m,) or (m,n,2) array * n : int, desired number of contour points Outputs: * r_new : contour shape(s) with n points, as an (n,2) or (m,n,2) array References: https://nurbs-python.readthedocs.io/en/latest/module_fitting.html ''' pcurve = fitting.interpolate_curve(list(r), 3) pcurve.sample_size = n return np.asarray( pcurve.evalpts )
def interpolate(cls, degree, points, metric='DISTANCE'): if metric not in {'DISTANCE', 'CENTRIPETAL'}: raise Exception("Unsupported metric") centripetal = metric == 'CENTRIPETAL' curve = fitting.interpolate_curve(points.tolist(), degree, centripetal=centripetal) return SvGeomdlCurve(curve)
def _recalculate(self) -> None: if len(self.points) >= 3: self.t = np.linspace(0, 1, num=self.samples, endpoint=True) print(self.t.shape) self.curve = fitting.interpolate_curve( [point.to_tuple() for point in self.points], 2 ) self.curve_points = np.array( self.curve.evaluate_list(self.t) ).astype(np.int32).reshape((-1, 2)) self.kd = spatial.KDTree(self.curve_points)
def interpolate_list(cls, degree, points, metric='DISTANCE'): if metric not in {'DISTANCE', 'CENTRIPETAL'}: raise Exception("Unsupported metric") centripetal = metric == 'CENTRIPETAL' curves = [] for curve_points in points: curve = fitting.interpolate_curve(curve_points.tolist(), degree, centripetal=centripetal) curve = SvGeomdlCurve(curve) curves.append(curve) return curves
def manual_init(points, radius, pn=20, qn=8): trace = interpolate_curve(points, 3) rad_curve = interp1d([p[0] for p in points], radius) params = np.linspace(0, 1, pn).tolist() trace_binormal = np.array(trace.binormal(params)) trace_tangent = np.array(trace.tangent(params)) trace_points = [] for tbi, tt in zip(trace_binormal, trace_tangent): for angle in np.linspace(0, 2 * np.pi, pn).tolist(): r = R.from_rotvec(angle * tt[1]) p = tbi[0] + rad_curve(tbi[0][0]) * r.apply(tbi[1]) trace_points.append(p.tolist()) return approximate_surface(trace_points, pn, pn, 3, 3, ctrlpts_size_u=qn, ctrlpts_size_v=qn)
Examples for the NURBS-Python Package Released under MIT License Developed by Onur Rauf Bingol (c) 2018 2-dimensional curve fitting by global interpolation """ from geomdl import fitting from geomdl.visualization import VisMPL as vis # The NURBS Book Ex9.1 points = ((0, 0), (3, 4), (-1, 4), (-4, 0), (-4, -3)) degree = 3 # cubic curve # Do global curve interpolation curve = fitting.interpolate_curve(points, degree) # Plot the interpolated curve curve.delta = 0.01 curve.vis = vis.VisCurve2D() curve.render() # # Visualize data and evaluated points together # import numpy as np # import matplotlib.pyplot as plt # evalpts = np.array(curve.evalpts) # pts = np.array(points) # plt.plot(evalpts[:, 0], evalpts[:, 1]) # plt.scatter(pts[:, 0], pts[:, 1], color="red") # plt.show()
def interpolate_tow_points(self, target=None): """Takes in array of points, and interpolates in between them using geomdl package Interpoaltes to a level such that the distance between points is roughly equal to $target_length (by default is t.w/2). Interpolates in batches, as large arrays can cause errors Parameters ---------- target : float, optional target distance for point spacing, by default None """ self.prev_pts = self.new_pts if target: target_length = target #w/4 else: target_length = self.interp_dist n_pts = len(self.new_pts[2]) points = np.copy(self.new_pts) # Batch up sections for large tows batch = [] batch_combine = [[], [], [], [], []] i = 0 batch_sz = 200 while (i + batch_sz < n_pts): tmp = points[:, i:i + batch_sz] batch.append(points[:, i:i + batch_sz]) i += batch_sz - 1 batch.append(points[:, i:]) for b in batch: if len(b[2]) <= 2: # If only two points - linear interpolation order = 1 elif len(b[2]) == 3: # If 3 poits - quadratic interpolation order = 2 else: # if > 3 pts - cubic interpolation order = 3 # Get length of batch curve. Use middle line as basis v1s = np.array(b[2][1:]) v2s = np.array(b[2][:-1]) diff = v2s - v1s lengths = [np.linalg.norm(x) for x in diff] length = sum([np.linalg.norm(x) for x in diff ]) #Get total length of distances between each point # Delta dictates how many 'evenly' spaced points the interpolation funciton will output. # Roughly equal to 1/n_points-1 - (e.g. delta = 0.01 --> 1/100 --> 101 points). # Delta must be < 1, so min() statement is too ensure this (bit hacky atm) delta = min(target_length / length, 0.99) # call the interpolate curve function for j in range(len(b)): curve = fit.interpolate_curve(b[j].tolist(), order) curve.delta = delta evalpts = curve.evalpts #evalpts is the new list of interpolated points batch_combine[ j] += evalpts #stich batches back together as created # Recheck new lengths for debugging v1s = np.array(batch_combine[2][1:]) v2s = np.array(batch_combine[2][:-1]) diff = v2s - v1s lengths = [np.linalg.norm(x) for x in diff] # Evalpts is of type list, need to return as numpy array self.new_pts = np.array(batch_combine)
def make(vertices): curve = fitting.interpolate_curve(vertices, degree, centripetal=self.centripetal) return SvGeomdlCurve(curve)