Exemple #1
0
    def test_close_mesh(self):
        mesh_a = self.cutSphere_C.copy()

        boundary_prev = stop.mesh_boundary(mesh_a)

        # Correctness
        assert (len(boundary_prev) == 2)

        mesh_a_closed, nvertices_added = stop.close_mesh(mesh_a)

        # Coherence
        assert (len(mesh_a_closed.vertices) == len(mesh_a.vertices) +
                nvertices_added)

        boundary_closed = stop.mesh_boundary(mesh_a_closed)

        # Mesh is now closed
        assert (len(boundary_closed) == 0)

        # Non modification of the vertices which are not on the boundaries
        sbase = (set(range(len(mesh_a.vertices))))
        sbound1 = (set(boundary_prev[0]))
        sbound2 = (set(boundary_prev[1]))
        sbound = sbound1.union(sbound2)
        snot_bound = (sbase.difference(sbound))

        for i in snot_bound:
            assert (mesh_a.vertices[i] == mesh_a_closed.vertices[i]).all()
Exemple #2
0
    def test_boundaries_triangles(self):

        mesh_a = distinct_triangles(5)
        mesh_b = random_triangles(5)

        open_mesh_boundary_a = stop.mesh_boundary(mesh_a)
        open_mesh_boundary_b = stop.mesh_boundary(mesh_b)

        iterable_a = list(itertools.combinations(open_mesh_boundary_a, 2))
        iterable_b = list(itertools.combinations(open_mesh_boundary_b, 2))

        # Uniqueness
        for b1, b2 in iterable_a:
            assert set(b1).intersection(set(b2)) == set()
        for b1, b2 in iterable_b:
            assert set(b1).intersection(set(b2)) == set()
Exemple #3
0
def disk_conformal_mapping(mesh,
                           lap_type='conformal',
                           boundary=None,
                           boundary_coords=None):
    """
    Computes comformal mapping of a mesh to a disk, see the following references:
    Ulrich Pinkall and Konrad Polthier, “Computing Discrete Minimal Surfaces and
    Their Conjugates,” Experimental Mathematics, 1993, 1–33.
    and
    Mathieu Desbrun, Mark Meyer, and Pierre Alliez, “Intrinsic Parameterizations
    of Surface Meshes,” Computer Graphics Forum 21, no. 3 (2002): 209–18,
    https://doi.org/10.1111/1467-8659.00580.
    :param mesh: a trimesh object
    :param lap_type: type of mesh Laplacian to be used,
    see the function differential_geometry/compute_mesh_weights for more
    informations
    :param boundary: boundary of the mesh, resulting from the function
    topology/mesh_boundary
    :param boundary_coords: coordindates of the boundary vertices on the
    output disk, if None then uniform sampling
    :return: a trimesh object, planar disk representation of the input mesh
    """
    if boundary is None:
        boundary_t = stop.mesh_boundary(mesh)
        boundary = boundary_t[0]
    boundary = np.array(boundary)
    if boundary_coords is None:
        p = boundary.size
        t = np.arange(0, 2 * np.math.pi, (2 * np.math.pi / p))
        boundary_coords = np.array([np.cos(t), np.sin(t)])
    L, LB = sdg.compute_mesh_laplacian(mesh, lap_type=lap_type)
    Nv = len(mesh.vertices)  # np.array(mesh.vertex()).shape[0]
    print('Boundary Size:', boundary.shape)
    print('Laplacian Size:', L.shape)
    for i in boundary:
        L[i, :] = 0
        L[i, i] = 1
    L = L.tocsr()

    Rx = np.zeros(Nv)
    Ry = np.zeros(Nv)
    Rx[boundary] = boundary_coords[0, :]
    Ry[boundary] = boundary_coords[1, :]

    x, info = lgmres(L, Rx, tol=solver_tolerance)
    y, info = lgmres(L, Ry, tol=solver_tolerance)
    z = np.zeros(Nv)

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=np.array([x, y, z]).T,
                           metadata=mesh.metadata,
                           process=False)
Exemple #4
0
 def test_remove_mesh_boundary_faces(self):
     mesh_a = self.cutSphere_A.copy()
     mesh_a_save = mesh_a.copy()
     boundary = stop.mesh_boundary(mesh_a)
     mesh_processed = stop.remove_mesh_boundary_faces(mesh_a,
                                                      face_vertex_number=1)
     # Non modification
     assert (mesh_a.vertices == mesh_a_save.vertices).all()
     # Correctness
     # check that when removing all faces with any vertex on the boundary,
     # all the boundary vertices are removed from the mesh
     print(len(boundary[0]))
     print(len(mesh_a.vertices))
     print(len(mesh_processed.vertices))
     assert (len(mesh_processed.vertices) == len(mesh_a.vertices) -
             len(boundary[0]))
Exemple #5
0
def disk_conformal_mapping(mesh,
                           lap_type='conformal',
                           boundary=None,
                           boundary_coords=None):
    """
    compute comformal mapping of a mesh to a disk
    ADD ref
    :param mesh: a trimesh object
    :param lap_type: type of mesh Laplacian to be used,
    see the function differential_geometry/compute_mesh_weights for more
    informations
    :param boundary: boundary of the mesh, resulting from the function
    topology/mesh_boundary
    :param boundary_coords: coordindates of the boundary vertices on the
    output disk, if None then uniform sampling
    :return: a trimesh object, planar disk representation of the input mesh
    """
    if boundary is None:
        boundary_t = stop.mesh_boundary(mesh)
        boundary = boundary_t[0]
    boundary = np.array(boundary)
    if boundary_coords is None:
        p = boundary.size
        t = np.arange(0, 2 * np.math.pi, (2 * np.math.pi / p))
        boundary_coords = np.array([np.cos(t), np.sin(t)])
    L, LB = sdg.compute_mesh_laplacian(mesh, lap_type=lap_type)
    Nv = len(mesh.vertices)  # np.array(mesh.vertex()).shape[0]
    print('Boundary Size:', boundary.shape)
    print('Laplacian Size:', L.shape)
    for i in boundary:
        L[i, :] = 0
        L[i, i] = 1
    L = L.tocsr()

    Rx = np.zeros(Nv)
    Ry = np.zeros(Nv)
    Rx[boundary] = boundary_coords[0, :]
    Ry[boundary] = boundary_coords[1, :]

    x, info = lgmres(L, Rx, tol=solver_tolerance)
    y, info = lgmres(L, Ry, tol=solver_tolerance)
    z = np.zeros(Nv)

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=np.array([x, y, z]).T,
                           metadata=mesh.metadata,
                           process=False)
Exemple #6
0
    def test_boundaries_concat_copy(self):
        mesh_a = self.cutSphere_A

        boundary = stop.mesh_boundary(mesh_a)
        b1_save = boundary[0].copy()
        b1 = boundary[0]
        b2 = boundary[1]

        concat = stop.cat_boundary(b1, b2)

        # Non modification
        # assert(len(b1) == len(b1_save))
        # assert((b1==b1_save))

        inter_1 = stop.boundaries_intersection([concat, b2])
        inter_1 = inter_1[0][2]

        assert (set(inter_1) == set(b2))
Exemple #7
0
    def test_angle_norm_boundary(self):

        ### CREATE A DISK IN 3D

        radius = 2
        mesh_a = trimesh.path.creation.circle(radius)

        coords2D, faces = mesh_a.triangulate()
        coords3D = []
        for i, v in enumerate(coords2D):
            coords3D.append([v[0], v[1], 0])

        coords3D = np.array(coords3D)

        mesh_a = trimesh.Trimesh(faces=faces, vertices=coords3D, process=False)

        ### COMPUTE BOUNDARY

        boundary = stop.mesh_boundary(mesh_a)

        assert (len(boundary) == 1)

        ### COMPUTE ANGLES AND NORM VARIATIONS

        angles, norms = stop.boundary_angles(boundary[0], coords3D)
        angles = abs(180 - angles)

        sum_angles, sum_norms = sum(angles), sum(norms)

        three_angles, three_norms = stop.boundary_angles([0, 1, 2], coords3D)
        three_angles = abs(180 - three_angles)

        perimeter = radius * np.pi * 2
        precision_A = .001
        precision_B = .001

        assert (np.isclose(three_norms[1], perimeter / len(coords3D),
                           precision_A))
        assert (np.isclose(three_angles[1], 360 / len(coords3D), precision_B))

        assert (np.isclose(sum_angles, 360, precision_A))
        assert (np.isclose(sum_norms, perimeter, precision_B))
Exemple #8
0
    def test_boundaries_intersection_copy(self):
        mesh_a = self.cutSphere_A

        boundary = stop.mesh_boundary(mesh_a)
        b1 = boundary[0]
        b2 = boundary[1]
        b2_save = b2.copy()

        concat = b1 + b2

        inter_1 = stop.boundaries_intersection([concat, b2])
        inter_1 = inter_1[0][2]

        # Non modification
        assert (b2 == b2_save)

        # Type
        assert (isinstance(inter_1, list))

        # Correctness
        assert (set(inter_1) == set(b2))
Exemple #9
0
    def test_angle_norm_boundary(self):

        # GET A DISK IN 3D

        radius = 2
        mesh_a = self.disk_radius_2
        coords3D = mesh_a.vertices

        # COMPUTE BOUNDARY

        boundary = stop.mesh_boundary(mesh_a)

        # Correctness
        assert (len(boundary) == 1)

        # COMPUTE ANGLE AND NORM VARIATIONS

        angles, norms = stop.boundary_angles(boundary[0], coords3D)
        angles = abs(180 - angles)

        sum_angles, sum_norms = sum(angles), sum(norms)

        # Computation on three arbitrary linked vertices
        three_angles, three_norms = stop.boundary_angles([0, 1, 2], coords3D)
        three_angles = abs(180 - three_angles)

        perimeter = radius * np.pi * 2
        precision_A = .001
        precision_B = .001

        # Coherence of the angle sum and norm sum
        assert (np.isclose(sum_angles, 360, precision_A))
        assert (np.isclose(sum_norms, perimeter, precision_B))

        # Coherence of a partial angle and a partial norm variation
        assert (np.isclose(three_angles[1], 360 / len(coords3D), precision_A))
        assert (np.isclose(three_norms[1], perimeter / len(coords3D),
                           precision_B))
Exemple #10
0
    def test_boundaries_basic(self):
        mesh_a = self.cutSphere_A

        mesh_a_save = mesh_a.copy()

        boundary = stop.mesh_boundary(mesh_a)

        # Non modification
        assert (mesh_a.vertices == mesh_a_save.vertices).all()
        assert (mesh_a.faces == mesh_a_save.faces).all()

        # Correctness
        assert (len(boundary) == 2)

        # Type
        assert (isinstance(boundary, list))
        assert (isinstance(boundary[0], list))

        iterable = list(itertools.combinations(boundary, 2))

        # Uniqueness
        for b1, b2 in iterable:
            assert set(b1).intersection(set(b2)) == set()
Exemple #11
0
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()

    # here is how to get the vertices that define the boundary of
    # a texture on a mesh
    mesh = sio.load_mesh('data/example_mesh.gii')
Exemple #12
0
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')
# create points with vispy
for bound in open_mesh_boundary:
    points = open_mesh.vertices[bound]
    s_rad = SourceObj('rad', points, color='red', symbol='square',
                      radius_min=10)
    visb_sc.add_to_subplot(s_rad)
    lines = Line(pos=open_mesh.vertices[bound], width=10, color='b')
    # wrap the vispy object using visbrain
Exemple #13
0
    def test_boundaries_concat_basic(self):
        mesh_a = self.cutSphere_A

        boundary = stop.mesh_boundary(mesh_a)

        assert (type(boundary) == list)