def test_203_Bingol_3D_surface(self): """Tests creation and plotting of BSpline surface, compared to GitHub repository orbingol https://nurbs-python.readthedocs.io/en/5.x/visualization-3.py Example usage: $ conda activate nurbspyenv $ cd nurbspy/ $ python > from geomdl import BSpline > from geomdl.visualization import VisMPL as vis > > surf = BSpline.Surface() > > surf.degree_u = 3 > surf.degree_v = 3 > > control_points = [ [ [-25.0, -25.0, -10.0], [-25.0, -15.0, -5.0], [-25.0, -5.0, 0.0], [-25.0, 5.0, 0.0], [-25.0, 15.0, -5.0], [-25.0, 25.0, -10.0] ], [ [-15.0, -25.0, -8.0], [-15.0, -15.0, -4.0], [-15.0, -5.0, -4.0], [-15.0, 5.0, -4.0], [-15.0, 15.0, -4.0], [-15.0, 25.0, -8.0] ], [ [-5.0, -25.0, -5.0], [-5.0, -15.0, -3.0], [-5.0, -5.0, -8.0], [-5.0, 5.0, -8.0], [-5.0, 15.0, -3.0], [-5.0, 25.0, -5.0] ], [ [5.0, -25.0, -3.0], [5.0, -15.0, -2.0], [5.0, -5.0, -8.0], [5.0, 5.0, -8.0], [5.0, 15.0, -2.0], [5.0, 25.0, -3.0] ], [ [15.0, -25.0, -8.0], [15.0, -15.0, -4.0], [15.0, -5.0, -4.0], [15.0, 5.0, -4.0], [15.0, 15.0, -4.0], [15.0, 25.0, -8.0] ], [ [25.0, -25.0, -10.0], [25.0, -15.0, -5.0], [25.0, -5.0, 2.0], [25.0, 5.0, 2.0], [25.0, 15.0, -5.0], [25.0, 25.0, -10.0] ] ] > surf.ctrlpts2d = control_points > surf.knotvector_u = [0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0, 3.0] > surf.knotvector_v = [0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0, 3.0] > surf.delta = 1.0/7.0 # seven intervals for testing, originally 0.025 for smoothness > surf.evaluate() > surf.vis = vis.VisSurface(vis.VisConfig(alpha=0.8)) > > surface_points = surf.evalpts > surf.render() # delta of 1.0 / 7.0 # gives a matrix of [7x7] evalution (x, y, z) points found by > surf.evalpts > len(surf.evalpts) # is 49, a 7x7 grid """ kv_t = tuple(map(float, [0, 0, 0, 0, 1, 2, 3, 3, 3, 3])) # cubic kv_u = tuple(map(float, [0, 0, 0, 0, 1, 2, 3, 3, 3, 3])) # cubic control_points = ( ( (-25.0, -25.0, -10.0), (-25.0, -15.0, -5.0), (-25.0, -5.0, 0.0), (-25.0, 5.0, 0.0), (-25.0, 15.0, -5.0), (-25.0, 25.0, -10.0), ), ( (-15.0, -25.0, -8.0), (-15.0, -15.0, -4.0), (-15.0, -5.0, -4.0), (-15.0, 5.0, -4.0), (-15.0, 15.0, -4.0), (-15.0, 25.0, -8.0), ), ( (-5.0, -25.0, -5.0), (-5.0, -15.0, -3.0), (-5.0, -5.0, -8.0), (-5.0, 5.0, -8.0), (-5.0, 15.0, -3.0), (-5.0, 25.0, -5.0), ), ( (5.0, -25.0, -3.0), (5.0, -15.0, -2.0), (5.0, -5.0, -8.0), (5.0, 5.0, -8.0), (5.0, 15.0, -2.0), (5.0, 25.0, -3.0), ), ( (15.0, -25.0, -8.0), (15.0, -15.0, -4.0), (15.0, -5.0, -4.0), (15.0, 5.0, -4.0), (15.0, 15.0, -4.0), (15.0, 25.0, -8.0), ), ( (25.0, -25.0, -10.0), (25.0, -15.0, -5.0), (25.0, -5.0, 2.0), (25.0, 5.0, 2.0), (25.0, 15.0, -5.0), (25.0, 25.0, -10.0), ), ) degree_t = 3 # cubic degree_u = 3 # cubic nbi = 1 # number of bisections per knot interval S = bsp.Surface( kv_t, kv_u, control_points, degree_t, degree_u, n_bisections=nbi, verbose=True, ) ( calc_surface_evaluations_x, calc_surface_evaluations_y, calc_surface_evaluations_z, ) = S.evaluations known_surface_evaluation_points = np.array([ [-25.0, -25.0, -10.0], [-25.0, -13.229166666666668, -4.21875], [-25.0, -5.833333333333334, -1.25], [-24.999999999999993, 4.440892098500626e-16, -0.3124999999999999], [-25.0, 5.833333333333331, -1.2499999999999996], [-25.0, 13.22916666666667, -4.218750000000002], [-25.0, 25.0, -10.0], [-13.229166666666668, -25.0, -7.364583333333334], [-13.229166666666668, -13.229166666666668, -4.4912109375], [-13.229166666666668, -5.833333333333334, -4.424479166666667], [-13.229166666666664, 4.440892098500626e-16, -4.574869791666666], [-13.229166666666666, 5.833333333333331, -4.424479166666667], [-13.229166666666668, 13.22916666666667, -4.491210937500001], [-13.229166666666668, 25.0, -7.364583333333334], [-5.833333333333334, -25.0, -5.416666666666667], [-5.833333333333334, -13.229166666666668, -4.476562500000001], [-5.833333333333334, -5.833333333333334, -6.020833333333333], [-5.833333333333333, 4.440892098500626e-16, -6.755208333333332], [-5.833333333333333, 5.833333333333332, -6.020833333333333], [-5.833333333333334, 13.229166666666671, -4.4765625], [-5.833333333333334, 25.0, -5.416666666666667], [4.440892098500626e-16, -24.999999999999993, -4.249999999999999], [4.440892098500626e-16, -13.229166666666666, -4.2509765625], [4.440892098500626e-16, -5.833333333333333, -6.460937499999998], [ 3.3306690738754696e-16, 4.440892098500625e-16, -7.4277343749999964 ], [3.3306690738754696e-16, 5.83333333333333, -6.460937499999998], [4.440892098500626e-16, 13.229166666666668, -4.250976562499999], [4.440892098500626e-16, 24.999999999999993, -4.249999999999999], [5.833333333333331, -25.0, -4.583333333333332], [5.833333333333332, -13.229166666666666, -4.125], [5.833333333333331, -5.833333333333333, -5.916666666666666], [5.83333333333333, 4.4408920985006257e-16, -6.729166666666664], [5.83333333333333, 5.83333333333333, -5.916666666666666], [5.833333333333331, 13.229166666666668, -4.124999999999999], [5.833333333333331, 25.0, -4.583333333333332], [13.22916666666667, -25.0, -6.885416666666668], [13.22916666666667, -13.229166666666668, -4.21875], [13.22916666666667, -5.833333333333334, -4.177083333333332], [13.229166666666668, 4.440892098500626e-16, -4.325520833333332], [13.229166666666668, 5.833333333333331, -4.177083333333332], [13.22916666666667, 13.22916666666667, -4.218750000000001], [13.22916666666667, 25.0, -6.885416666666668], [25.0, -25.0, -10.0], [25.0, -13.229166666666668, -3.65625], [25.0, -5.833333333333334, 0.25000000000000006], [24.999999999999993, 4.440892098500626e-16, 1.5624999999999998], [25.0, 5.833333333333331, 0.25000000000000044], [25.0, 13.22916666666667, -3.6562500000000013], [25.0, 25.0, -10.0], ]) ix, iy, iz = 0, 1, 2 # index for x, y, z self.assertTrue( self.same( known_surface_evaluation_points[:, ix], calc_surface_evaluations_x.flatten(), )) self.assertTrue( self.same( known_surface_evaluation_points[:, iy], calc_surface_evaluations_y.flatten(), )) self.assertTrue( self.same( known_surface_evaluation_points[:, iz], calc_surface_evaluations_z.flatten(), ))
def test_202_Bingol_3D_surface(self): """Tests creation and plotting of BSpline surface, compared to GitHub repository orbingol https://github.com/orbingol/NURBS-Python/blob/5.x/geomdl/BSpline.py Example usage: $ conda activate nurbspyenv $ cd nurbspy/ $ python > from geomdl import BSpline > from geomdl.visualization import VisMPL as vis > > surf = BSpline.Surface() > surf.degree_u = 3 > surf.degree_v = 2 > control_points = [ [0, 0, 0], [0, 4, 0], [0, 8, -3], [2, 0, 6], [2, 4, 0], [2, 8, 0], [4, 0, 0], [4, 4, 0], [4, 8, 3], [6, 0, 0], [6, 4, -3], [6, 8, 0] ] > surf.set_ctrlpts(control_points, 4, 3) > surf.knotvector_u = [0, 0, 0, 0, 1, 1, 1, 1] > surf.knotvector_v = [0, 0, 0, 1, 1, 1] > surf.delta = 0.20 # 0.20 for testing, was originally 0.05 for smoothness > surf.vis = vis.VisSurface() # or alternatively, for a transparent surface, set the alpha to non-unity > surf.vis = vis.VisSurface(vis.VisConfig(alpha=0.8)) > > surface_points = surf.evalpts > surf.render() # 0.20, with 1.0 / 0.20 = 5.0, # gives a matrix of [5x5] evalution (x, y, z) points found by > surf.evalpts """ kv_t = tuple(map(float, [0, 0, 0, 0, 1, 1, 1, 1])) # cubic kv_u = tuple(map(float, [0, 0, 0, 1, 1, 1])) # quadratic control_points = ( ((0, 0, 0), (0, 4, 0), (0, 8, -3)), ((2, 0, 6), (2, 4, 0), (2, 8, 0)), ((4, 0, 0), (4, 4, 0), (4, 8, 3)), ((6, 0, 0), (6, 4, -3), (6, 8, 0)), ) degree_t = 3 # cubic degree_u = 2 # quadratic nbi = 2 # number of bisections per knot interval S = bsp.Surface( kv_t, kv_u, control_points, degree_t, degree_u, n_bisections=nbi, verbose=True, ) ( calc_surface_evaluations_x, calc_surface_evaluations_y, calc_surface_evaluations_z, ) = S.evaluations known_surface_evaluation_points = np.array([ [ [0.0, 0.0, 0.0], [0.0, 2.0, -0.1875], [0.0, 4.0, -0.75], [0.0, 6.0, -1.6875], [0.0, 8.0, -3.0], ], [ [1.5, 0.0, 2.53125], [1.5, 2.0, 1.353515625], [1.5, 4.0, 0.3984375], [1.5, 6.0, -0.333984375], [1.5, 8.0, -0.84375], ], [ [3.0, 0.0, 2.25], [3.0, 2.0, 1.171875], [3.0, 4.0, 0.5625], [3.0, 6.0, 0.421875], [3.0, 8.0, 0.75], ], [ [4.5, 0.0, 0.84375], [4.5, 2.0, 0.076171875], [4.5, 4.0, -0.1171875], [4.5, 6.0, 0.263671875], [4.5, 8.0, 1.21875], ], [ [6.0, 0.0, 0.0], [6.0, 2.0, -1.125], [6.0, 4.0, -1.5], [6.0, 6.0, -1.125], [6.0, 8.0, 0.0], ], ]) ix, iy, iz = 0, 1, 2 # index for x, y, z known_surface_evaluation_points_x = known_surface_evaluation_points[:, :, ix].flatten( ) known_surface_evaluation_points_y = known_surface_evaluation_points[:, :, iy].flatten( ) known_surface_evaluation_points_z = known_surface_evaluation_points[:, :, iz].flatten( ) self.assertTrue( self.same(known_surface_evaluation_points_x, calc_surface_evaluations_x.flatten())) self.assertTrue( self.same(known_surface_evaluation_points_y, calc_surface_evaluations_y.flatten())) self.assertTrue( self.same(known_surface_evaluation_points_z, calc_surface_evaluations_z.flatten()))
def test_201_recover_bezier_bilinear_B00_p1_surface(self): kv_t = (0.0, 0.0, 1.0, 1.0) # knot vector for t parameter kv_u = (0.0, 0.0, 1.0, 1.0) # knot vector for u parameter # control_points = [ # [[-15.0, -10.0, 1.0], [-15.0, 10.0, 1.0]], # [[15.0, -10.0, 1.0], [15.0, 10.0, 1.0]], # ] control_points = ( ((0.0, 0.0, 1.0), (0.0, 1.0, 0.0)), ((1.0, 0.0, 0.0), (1.0, 1.0, 0.0)), ) degree_t = 1 # linear degree_u = 1 # linear nbi = 1 # number of bisections per knot interval S = bsp.Surface( kv_t, kv_u, control_points, degree_t, degree_u, n_bisections=nbi, verbose=True, ) ( calc_surface_evaluations_x, calc_surface_evaluations_y, calc_surface_evaluations_z, ) = S.evaluations known_surface_evaluations_x = np.array( ((0.0, 0.0, 0.0), (0.5, 0.5, 0.5), (1.0, 1.0, 1.0))) known_surface_evaluations_y = np.array( ((0.0, 0.5, 1.0), (0.0, 0.5, 1.0), (0.0, 0.5, 1.0))) known_surface_evaluations_z = np.array( ((1.0, 0.5, 0.0), (0.5, 0.25, 0.0), (0.0, 0.0, 0.0))) difference_matrix_x = calc_surface_evaluations_x - known_surface_evaluations_x difference_matrix_y = calc_surface_evaluations_y - known_surface_evaluations_y difference_matrix_z = calc_surface_evaluations_z - known_surface_evaluations_z Frobenius_norm_x = np.linalg.norm(difference_matrix_x, ord="fro") Frobenius_norm_y = np.linalg.norm(difference_matrix_y, ord="fro") Frobenius_norm_z = np.linalg.norm(difference_matrix_z, ord="fro") self.assertTrue(Frobenius_norm_x < self.tol) self.assertTrue(Frobenius_norm_y < self.tol) self.assertTrue(Frobenius_norm_z < self.tol) known_evaluation_times_t = (0.0, 0.5, 1.0) known_evaluation_times_u = (0.0, 0.5, 1.0) calc_evaluation_times_t = S.evaluation_times_t calc_evaluation_times_u = S.evaluation_times_u self.assertTrue( self.same(known_evaluation_times_t, calc_evaluation_times_t)) self.assertTrue( self.same(known_evaluation_times_u, calc_evaluation_times_u))
if control_points_shown: cp_x = np.array(surfaces)[:, :, :, ix].flatten() # control points x-coordinates cp_y = np.array(surfaces)[:, :, :, iy].flatten() # control points y-coordinates cp_z = np.array(surfaces)[:, :, :, iz].flatten() # control points z-coordinates ax.plot3D(cp_x, cp_y, cp_z, **vbsp.defaults["control_points_kwargs"]) for control_points in surfaces: S = bsp.Surface( kv_t, kv_u, control_points, degree_t, degree_u, n_bisections=nbi, verbose=True, ) (surf_x, surf_y, surf_z) = S.evaluations ax.plot3D( surf_x.flatten(), surf_y.flatten(), surf_z.flatten(), **vbsp.defaults["evaluation_points_kwargs"], ) u, t = np.meshgrid(S.evaluation_times_u, S.evaluation_times_t) u, t = u.flatten(), t.flatten()
def __init__(self, **kwargs): super().__init__(**kwargs) self.plot3d = True # overwrite the base class COEF = kwargs.get( "coefficients", None ) # None is basis, not None is curve, surface, or volume assert COEF is not None _NSD = len(COEF[0][0]) # number of space dimensions assert _NSD == 3 # only 2D curves implemented for now, do 3D later # plot B-spline curve, assume 2D for now self.fig = plt.figure(dpi=self.dpi) # ax = self.fig.gca() ax = self.fig.add_subplot(111, projection="3d") # avoid "magic" numbers, assign (0, 1, 2) to variables idx, idy, idz = (0, 1, 2) # self.control_net_alpha = kwargs.get("control_net_alpha", 0.5) # self.control_net_color = kwargs.get("control_net_color", "magenta") # self.control_net_linestyle = kwargs.get("control_net_linestyle", "dashed") # self.control_net_linewidth = kwargs.get("control_net_linewidth", 1) # self.control_net_shown = kwargs.get("control_net_shown", True) if self.control_net_shown: # create control net object cn = ControlNet(COEF) # draw control net rows _row_points = cn.rows for r in _row_points: ax.plot3D( r[:, idx], r[:, idy], r[:, idz], alpha=self.control_net_alpha, color=self.control_net_color, linestyle=self.control_net_linestyle, linewidth=self.control_net_linewidth, ) # draw control net columns _col_points = cn.columns for c in _col_points: ax.plot3D( c[:, idx], c[:, idy], c[:, idz], alpha=self.control_net_alpha, color=self.control_net_color, linestyle=self.control_net_linestyle, linewidth=self.control_net_linewidth, ) if self.control_points_shown: # plot control points _cp_x = np.array(COEF)[:, :, idx].flatten() # control points x-coordinates _cp_y = np.array(COEF)[:, :, idy].flatten() # control points y-coordinates _cp_z = np.array(COEF)[:, :, idz].flatten() # control points z-coordinates ax.plot3D( _cp_x, _cp_y, _cp_z, alpha=self.control_points_alpha, color=self.control_points_color, linestyle=self.control_points_linestyle, linewidth=self.control_points_linewidth, marker=self.control_points_marker, markerfacecolor=self.control_points_marker_facecolor, markersize=self.control_points_marker_size, ) if self.evaluation_points_shown or self.surface_triangulation: kv_t = kwargs.get("knot_vector_t") kv_u = kwargs.get("knot_vector_u") # control_poiknts argument already exists as COEF variable # S = bsp.Surface( # kv_t, kv_u, COEF, self.degree_t, self.degree_u, verbose=self.verbosity # ) S = bsp.Surface( knot_vector_t=kv_t, knot_vector_u=kv_u, coefficients=COEF, degree_t=self.degree_t, degree_u=self.degree_u, n_bisections=self.nbi, verbose=self.verbosity, ) (_surf_x, _surf_y, _surf_z) = S.evaluations if self.evaluation_points_shown: ax.plot3D( _surf_x.flatten(), _surf_y.flatten(), _surf_z.flatten(), alpha=self.evaluation_points_alpha, color=self.evaluation_points_color, linestyle=self.evaluation_points_linestyle, linewidth=self.evaluation_points_linewidth, marker=self.evaluation_points_marker, markersize=self.evaluation_points_marker_size, ) # markerfacecolor=self.evaluation_points_marker_facecolor, if self.surface_triangulation: # convention here is reverse of the (x, y) convention of # mesh grid, see # https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html u, t = np.meshgrid(S.evaluation_times_u, S.evaluation_times_t) u, t = u.flatten(), t.flatten() tri = mtri.Triangulation(u, t) ax.plot_trisurf( _surf_x.flatten(), _surf_y.flatten(), _surf_z.flatten(), alpha=self.surface_triangulation_alpha, triangles=tri.triangles, ) # color=self.surface_triangulation_color, xlabel = kwargs.get("xlabel", "x") ylabel = kwargs.get("ylabel", "y") zlabel = kwargs.get("zlabel", "z") # ax.set_xlabel(r"$x$") # ax.set_ylabel(r"$y$") ax.set_xlabel(r"" + xlabel + "") ax.set_ylabel(r"" + ylabel + "") ax.set_zlabel(r"" + zlabel + "") if self.xlim: ax.set_xlim(self.xlim) if self.ylim: ax.set_ylim(self.ylim) if self.zlim: ax.set_zlim(self.zlim) # finish figure by calling method with common figure functions ViewBSplineFigure(self)
pass if control_points_shown: for p in patches: cp_x = np.array(p.coefficients)[:, :, ix].flatten() cp_y = np.array(p.coefficients)[:, :, iy].flatten() cp_z = np.array(p.coefficients)[:, :, iz].flatten() ax.plot3D(cp_x, cp_y, cp_z, **vbsp.defaults["control_points_kwargs"]) for p in patches: S = bsp.Surface( knot_vector_t=p.knot_vector_t, knot_vector_u=p.knot_vector_u, coefficients=p.coefficients, degree_t=p.degree_t, degree_u=p.degree_u, n_bisections=p.n_bisections, ) (surf_x, surf_y, surf_z) = S.evaluations ax.plot3D( surf_x.flatten(), surf_y.flatten(), surf_z.flatten(), **vbsp.defaults["evaluation_points_kwargs"], ) u, t = np.meshgrid(S.evaluation_times_u, S.evaluation_times_t) u, t = u.flatten(), t.flatten() tri = mtri.Triangulation(u, t)