def test_error_drop_curvature_quadric(self): """ Asserts the error drops when the mesh resolution is increased""" out = [] for j in range(3): K = [1, 1] # Increase of the number of points quadric = sgps.generate_quadric(K, nstep=[20 + 10 * j, 20 + 10 * j], ax=3, ay=1, random_sampling=False, ratio=0.3, random_distribution_type='gamma') # Computation of estimated curvatures p_curv, d1, d2 = scurv.curvatures_and_derivatives(quadric) k1_estim, k2_estim = p_curv[0, :], p_curv[1, :] # k_gauss_estim = k1_estim * k2_estim k_mean_estim = .5 * (k1_estim + k2_estim) # Computation of analytical curvatures k_mean_analytic = sgps.quadric_curv_mean(K)(np.array( quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) k_gauss_analytic = sgps.quadric_curv_gauss(K)(np.array( quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) k1_analytic = np.zeros((len(k_mean_analytic))) k2_analytic = np.zeros((len(k_mean_analytic))) for i in range(len(k_mean_analytic)): a, b = np.roots( (1, -2 * k_mean_analytic[i], k_gauss_analytic[i])) k1_analytic[i] = min(a, b) k2_analytic[i] = max(a, b) # /// STATS # k_mean_relative_change = abs( # (k_mean_analytic - k_mean_estim) / k_mean_analytic) k_mean_absolute_change = abs((k_mean_analytic - k_mean_estim)) # k1_relative_change = abs((k1_analytic - k1_estim) / k1_analytic) # k1_absolute_change = abs((k1_analytic - k1_estim)) out += [np.round(np.mean(k_mean_absolute_change), 6)] # Assert the absolute mean error decreases as we increase the number of # points assert (sorted(out, reverse=True) == out)
def test_correctness_direction_quadric(self): # Generate a paraboloid K = [1, 0] # Increase of the number of points quadric = sgps.generate_quadric(K, nstep=[20, 20], ax=3, ay=3, random_sampling=False, ratio=0.3, random_distribution_type='gamma', equilateral=True) # ESTIMATED Principal curvature, Direction1, Direction2 p_curv_estim, d1_estim, d2_estim = scurv.curvatures_and_derivatives( quadric) # ANALYTICAL directions analytical_directions = sgps.compute_all_principal_directions_3D( K, quadric.vertices) estimated_directions = np.zeros(analytical_directions.shape) estimated_directions[:, :, 0] = d1_estim estimated_directions[:, :, 1] = d2_estim angular_error_0, dotprods = ut.compare_analytic_estimated_directions( analytical_directions[:, :, 0], estimated_directions) angular_error_0 = 180 * angular_error_0 / np.pi # CORRECTNESS DIRECTION 1 # Number of vertices where the angular error is lower than 20 degrees n_low_error = np.sum(angular_error_0 < 15) # Percentage of vertices where the angular error is lower than 20 # degrees percentage_low_error = (n_low_error / angular_error_0.shape[0]) assert (percentage_low_error > .75) # CORRECTNESS DIRECTION 2 angular_error_1, dotprods = ut.compare_analytic_estimated_directions( analytical_directions[:, :, 1], estimated_directions) angular_error_1 = 180 * angular_error_1 / np.pi # Number of vertices where the angular error is lower than 20 degrees n_low_error = np.sum(angular_error_1 < 15) # Percentage of vertices where the angular error is lower than 20 # degrees percentage_low_error = (n_low_error / angular_error_1.shape[0]) assert (percentage_low_error > .75)
def test_correctness_decomposition_quadric(self): # Precision on the shapeIndex calculation precisionA = 0.000001 # Precision on the curvedness calculation precisionB = 0.000001 set_of_tests = [ # Set = [K, correct shapeIndex, correct curvedness] # For example, on a quadric generated by K=[1,1], the shapeIndex # is +-1 at the center and the curvedness is +-2 [[1, 1], 1, 2], [[-1, -1], 1, 2], [[.5, .5], 1, 1], [[1, 0], .5, np.sqrt(2)], ] for i in range(len(set_of_tests)): current_test = set_of_tests[i] K = current_test[0] # Correct values of shapeIndex and curvedness on the vertex at the # center of the mesh correct_shape_index = current_test[1] correct_curvedness = current_test[2] with self.subTest(i): # Generate quadric quadric = sgps.generate_quadric( K, nstep=[20, 20], ax=3, ay=1, random_sampling=False, ratio=0.3, ) # Computation of analytical k_mean, k_gauss, k_1 and k_2 k_mean_analytic = sgps.quadric_curv_mean(K)(np.array( quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) k_gauss_analytic = sgps.quadric_curv_gauss(K)(np.array( quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) k1_analytic = np.zeros((len(k_mean_analytic))) k2_analytic = np.zeros((len(k_mean_analytic))) for i in range(len(k_mean_analytic)): a, b = np.roots( (1, -2 * k_mean_analytic[i], k_gauss_analytic[i])) k1_analytic[i] = min(a, b) k2_analytic[i] = max(a, b) # Decomposition of the curvature shapeIndex, curvedness = scurv.decompose_curvature( np.array((k1_analytic, k2_analytic))) # Find the index of the vertex which is the closest to the # center def mag(p): """Distance to the center for the point p, not considering the z axis""" x = p[0] y = p[1] return np.sqrt(x * x + y * y) min_i = 0 min_m = mag(quadric.vertices[0]) for i, v in enumerate(quadric.vertices): mg = mag(v) if mg < min_m: min_i = i min_m = mg # Correctness computed_shapeIndex = shapeIndex[min_i] computed_curvedness = curvedness[min_i] assert (np.isclose(computed_shapeIndex, correct_shape_index, precisionA) | np.isclose(computed_shapeIndex, -correct_shape_index, precisionA)) assert (np.isclose(computed_curvedness, correct_curvedness, precisionB) | np.isclose(computed_curvedness, -correct_curvedness, precisionB))
def test_correctness_curvature_quadric(self): K = [1, 1] quadric = sgps.generate_quadric(K, nstep=[20, 20], ax=3, ay=1, random_sampling=True, ratio=0.3, random_distribution_type='gamma') # Computation of estimated curvatures p_curv, d1, d2 = scurv.curvatures_and_derivatives(quadric) k1_estim, k2_estim = p_curv[0, :], p_curv[1, :] # k_gauss_estim = k1_estim * k2_estim k_mean_estim = .5 * (k1_estim + k2_estim) # Computation of analytical curvatures k_mean_analytic = sgps.quadric_curv_mean(K)(np.array( quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) k_gauss_analytic = sgps.quadric_curv_gauss(K)(np.array( quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) k1_analytic = np.zeros((len(k_mean_analytic))) k2_analytic = np.zeros((len(k_mean_analytic))) for i in range(len(k_mean_analytic)): a, b = np.roots((1, -2 * k_mean_analytic[i], k_gauss_analytic[i])) k1_analytic[i] = min(a, b) k2_analytic[i] = max(a, b) # /// STATS k_mean_relative_change = abs( (k_mean_analytic - k_mean_estim) / k_mean_analytic) k_mean_absolute_change = abs((k_mean_analytic - k_mean_estim)) k1_relative_change = abs((k1_analytic - k1_estim) / k1_analytic) # k1_absolute_change = abs((k1_analytic - k1_estim)) a = [] a += [ [ "K_MEAN", "mean", "relative change", np.mean(k_mean_relative_change * 100), "%" ], ("K_MEAN", "std", "relative change", np.std(k_mean_relative_change * 100), "%"), ("K_MEAN", "max", "relative change", np.max(k_mean_relative_change * 100), "%"), [ "K_MEAN", "mean", "absolute change", np.mean(k_mean_absolute_change) ], [ "K_MEAN", "std", "absolute change", np.std(k_mean_absolute_change) ], [ "K_MEAN", "max", "absolute change", np.max(k_mean_absolute_change) ], (" K1", "mean", "relative change", np.mean(k1_relative_change * 100), "%"), (" K1", "std", "relative change", np.std(k1_relative_change * 100), "%"), (" K1", "max", "relative change", np.max(k1_relative_change * 100), "%"), (" K1", "mean", "absolute change", np.mean(k_mean_absolute_change)), (" K1", "std", "absolute change", np.std(k_mean_absolute_change)), (" K1", "max", "absolute change", np.max(k_mean_absolute_change)), ] # PRINT STATS print("----------------------------------------") for i, v in enumerate(a): numeric_value = np.round(v[3], decimals=3) if i == 6: print("----------------------------------------") if len(v) > 4: print('{0:10} {1:5} {2:16} {3:2} {4} {5}'.format( v[0], v[1], v[2], "=", numeric_value, v[4])) else: print('{0:10} {1:5} {2:16} {3:2} {4}'.format( v[0], v[1], v[2], "=", numeric_value)) print("----------------------------------------")
# sphinx_gallery_thumbnail_number = 2 ############################################################################### # Importation of slam modules import slam.generate_parametric_surfaces as sgps import slam.plot as splt import numpy as np ############################################################################### # Generating a quadrix surface K = [1, 1] quadric = sgps.generate_quadric(K, nstep=20, ax=3, ay=1, random_sampling=True, ratio=0.3, random_distribution_type='gamma') quadric_mean_curv = \ sgps.quadric_curv_mean(K)(np.array(quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) visb_sc = splt.visbrain_plot(mesh=quadric, tex=quadric_mean_curv, caption='quadric', cblabel='mean curvature') visb_sc.preview() ###############################################################################
# import matplotlib # matplotlib.use('TkAgg') # import matplotlib.pyplot as plt import trimesh import slam.io as sio import slam.topology as stop # import slam.plot as splt import slam.generate_parametric_surfaces as sps import numpy as np if __name__ == '__main__': # here is how to get the vertices that define the boundary of an open mesh Ks = [[1, 1]] X, Y, faces, Zs = sps.generate_quadric(Ks, nstep=10) Z = Zs[0] coords = np.array([X, Y, Z]).transpose() open_mesh = trimesh.Trimesh(faces=faces, vertices=coords, process=False) open_mesh_boundary = stop.mesh_boundary(open_mesh) print(open_mesh_boundary) scene_list = [open_mesh] for bound in open_mesh_boundary: points = open_mesh.vertices[bound] cloud_boundary = trimesh.points.PointCloud(points) cloud_colors = np.array( [trimesh.visual.random_color() for i in points]) cloud_boundary.vertices_color = cloud_colors scene_list.append(cloud_boundary) scene = trimesh.Scene(scene_list) scene.show()
############################################################################### # importation of slam modules import slam.io as sio import slam.topology as stop import slam.plot as splt import slam.generate_parametric_surfaces as sps import numpy as np from vispy.scene import Line from visbrain.objects import VispyObj, SourceObj ############################################################################### # here is how to get the vertices that define the boundary of an open mesh K = [-1, -1] open_mesh = sps.generate_quadric(K, nstep=5) ############################################################################### # Identify the vertices lying on the boundary of the mesh and order # them to get a path traveling across boundary vertices # The output is a list of potentially more than one boudaries # depending on the topology of the input mesh. # Here the mesh has a single boundary open_mesh_boundary = stop.mesh_boundary(open_mesh) print(open_mesh_boundary) ############################################################################### # show the result # WARNING : BrainObj should be added first before visb_sc = splt.visbrain_plot(mesh=open_mesh, caption='open mesh')
import slam.generate_parametric_surfaces as sgps import slam.plot as splt import numpy as np if __name__ == '__main__': # Quadric K = [1, 1] quadric = sgps.generate_quadric(K, nstep=[40, 40], ax=3, ay=1, random_sampling=False, ratio=0.3, random_distribution_type='gamma') quadric.show() quadric2 = \ sgps.generate_paraboloid_regular(A=1, nstep=40, ax=3, ay=1, random_sampling=True, ratio=0.1, random_distribution_type='gamma') quadric2.show() quadric_mean_curv = \ sgps.quadric_curv_mean(K)(np.array(quadric.vertices[:, 0]), np.array(quadric.vertices[:, 1])) # print(np.min(quadric.vertices, 0)) # print(np.max(quadric.vertices, 0)) # Ellipsoid Parameters nstep = 50 randomSampling = True a = 2 b = 1 ellips = sgps.generate_ellipsiod(a, b, nstep, randomSampling)
colors=colors) return fig ############################################################################### # Create quadric mesh nstep = 20 equilateral = True K = [1, 0.5] quadric_mesh = sgps.generate_quadric(K, nstep=[int(nstep), int(nstep)], equilateral=equilateral, ax=1, ay=1, random_sampling=False, ratio=0.2, random_distribution_type='gaussian') ############################################################################### # Compute principal directions of curvature PrincipalCurvatures, PrincipalDir1, PrincipalDir2 = scurv.curvatures_and_derivatives( quadric_mesh) ############################################################################### # Visualization visualize(quadric_mesh, PrincipalDir1) plt.show()
visb_sc = splt.visbrain_plot(mesh=mesh, tex=curvedness, caption='Curvedness', cblabel='Curvedness', cmap='hot') visb_sc.preview() ############################################################################### # Estimation error on the principal curvature length K = [1, 0] quadric = sgps.generate_quadric(K, nstep=[20, 20], ax=3, ay=3, random_sampling=False, ratio=0.3, random_distribution_type='gamma', equilateral=True) ############################################################################### # Estimated computation of the Principal curvature, K_gauss, K_mean p_curv, d1_estim, d2_estim = scurv.curvatures_and_derivatives(quadric) k1_estim, k2_estim = p_curv[0, :], p_curv[1, :] k_gauss_estim = k1_estim * k2_estim k_mean_estim = .5 * (k1_estim + k2_estim) ###############################################################################