Example #1
0
    def test_basic(self):
        mesh_a = self.sphere_r1.copy()
        mesh_a_save = self.sphere_r1.copy()

        mesh_b = self.sphere_r2.copy()
        mesh_b_save = self.sphere_r2.copy()

        tmp = sdst.angle_difference(mesh_a, mesh_b)

        assert (mesh_a.vertices == mesh_a_save.vertices).all()
        assert (mesh_a.faces == mesh_a_save.faces).all()

        assert (mesh_b.vertices == mesh_b_save.vertices).all()
        assert (mesh_b.faces == mesh_b_save.faces).all()

        tmp = sdst.area_difference(mesh_a, mesh_b)

        assert (mesh_a.vertices == mesh_a_save.vertices).all()
        assert (mesh_a.faces == mesh_a_save.faces).all()

        assert (mesh_b.vertices == mesh_b_save.vertices).all()
        assert (mesh_b.faces == mesh_b_save.faces).all()

        tmp = sdst.edge_length_difference(mesh_a, mesh_b)

        assert (mesh_a.vertices == mesh_a_save.vertices).all()
        assert (mesh_a.faces == mesh_a_save.faces).all()

        assert (mesh_b.vertices == mesh_b_save.vertices).all()
        assert (mesh_b.faces == mesh_b_save.faces).all()
Example #2
0
    def test_correctness_area(self):

        precisionA = .001

        n_sub = 5

        mesh_a = trimesh.creation.icosphere(subdivisions=n_sub, radius=1)
        mesh_b = trimesh.creation.icosphere(subdivisions=n_sub, radius=2)

        area_diff_estim = sdst.area_difference(mesh_a, mesh_b)

        area_diff_estim = sum(abs(area_diff_estim))

        area_diff_analytical = 4 * np.pi * 2 * 2 - 4 * np.pi * 1 * 1

        assert (np.isclose(area_diff_estim, area_diff_analytical, precisionA))
Example #3
0
################################################################################
# Visualization of the original mesh
visb_sc = splt.visbrain_plot(mesh=mesh, caption='original mesh')
visb_sc.preview()

###############################################################################
# Visualization of the smoothed mesh
visb_sc = splt.visbrain_plot(mesh=mesh_s,
                             caption='smoothed mesh',
                             visb_sc=visb_sc)
visb_sc.preview()

###############################################################################
# Computation of the angle difference between each faces of mesh and mesh_s
angle_diff = sdst.angle_difference(mesh, mesh_s)
angle_diff

###############################################################################
#
face_angle_dist = np.sum(np.abs(angle_diff), 1)
face_angle_dist

###############################################################################
# Computation of the area difference between each faces of mesh and mesh_s
area_diff = sdst.area_difference(mesh, mesh_s)
area_diff

###############################################################################
# Computation of the length difference between each edges of mesh and mesh_s
edge_diff = sdst.edge_length_difference(mesh, mesh_s)
edge_diff
Example #4
0
def spherical_mapping(mesh,
                      mapping_type='laplacian_eigenvectors',
                      conformal_w=1,
                      authalic_w=1,
                      dt=0.01,
                      nb_it=10):
    """
    ADD REF
    :param mesh:
    :param mapping_type:
    :param conformal_w:
    :param authalic_w:
    :param dt:
    :param nb_it:
    :return:
    """
    # computing spherical mapping based on laplacian eigenvectors
    sph_vert = sdg.mesh_laplacian_eigenvectors(mesh, nb_vectors=3)
    norm_sph_vert = np.sqrt(np.sum(sph_vert * sph_vert, 1))
    sphere_vertices = sph_vert / np.tile(norm_sph_vert, (3, 1)).T
    if mapping_type == 'laplacian_eigenvectors':
        return trimesh.Trimesh(faces=mesh.faces,
                               vertices=sphere_vertices,
                               metadata=mesh.metadata,
                               process=False)

    if mapping_type == 'conformal':
        """
        Desbrun, M., Meyer, M., & Alliez, P. (2002).
        Intrinsic parameterizations of surface meshes.
        Computer Graphics Forum, 21(3), 209–218.
        https://doi.org/10.1111/1467-8659.00580
        """

        # options.symmetrize = 0;
        # options.normalize = 1;
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')

    if mapping_type == 'authalic':
        # options.symmetrize = 0;
        # options.normalize = 1;
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')

    if mapping_type == 'combined':
        # options.symmetrize = 0;
        # options.normalize = 1;
        Lconf, Bconf = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')
        Laut, Baut = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')
        L = conformal_w * Lconf + authalic_w * Laut
    # continue the spherical mappig by minimizig the energy
    evol = list()
    for it in range(nb_it):
        sphere_vertices = sphere_vertices - dt * L.dot(sphere_vertices)
        # sphere_vertices * L
        norm_sph_vert = np.sqrt(np.sum(sphere_vertices * sphere_vertices, 1))
        sphere_vertices = sphere_vertices / np.tile(norm_sph_vert, (3, 1)).T
        if it % 10 == 0:
            sph = trimesh.Trimesh(faces=mesh.faces,
                                  vertices=sphere_vertices,
                                  process=False)
            angle_diff = sdst.angle_difference(sph, mesh)
            area_diff = sdst.area_difference(sph, mesh)
            edge_diff = sdst.edge_length_difference(sph, mesh)
            evol.append([
                np.sum(np.abs(angle_diff.flatten())),
                np.sum(np.abs(area_diff.flatten())),
                np.sum(np.abs(edge_diff.flatten()))
            ])

    # ind = 0;
    # for it=1:nb_it
    # % it = 1;
    # % while sum(I(: ) < 0)
    # % it = it + 1;
    # % vertex1 = vertex1 * L;
    # vertex1 = vertex1 - eta * vertex1 * L;
    # vertex1 = vertex1. / repmat(sqrt(sum(vertex1. ^ 2, 1)), [3 1]);
    # if mod(it, 100) == 0
    #     ind = ind + 1;
    #     NFV.vertices = vertex1
    #     ';
    #     [nb_inward, inward] = reversed_faces(NFV, 'sphere');
    #     bil_inward(ind) = nb_inward;
    #     w = zeros(1, m);
    #     E = zeros(1, m);
    #     for i=1:3
    #     i1 = mod(i, 3) + 1;
    #     % directed
    #     edge
    #     u = vertex1(:, faces(i,:)) - vertex1(:, faces(i1,:));
    #     % norm
    #     squared
    #     u = sum(u. ^ 2);
    #     % weights
    #     between
    #     the
    #     vertices
    #     for j=1:m
    #     w(j) = L(faces(i, j), faces(i1, j));
    # end
    # % w = W(faces(i,:) + (faces(i1,:) - 1)*n);
    # E = E + w. * u;
    #
    #
    # end
    #
    # bil_E(ind) = sum(E);
    # if ind > 2
    #     disp(['Ratio of inverted triangles:' num2str(100 * nb_inward / m, 3)
    #           '% energy decrease:' num2str(bil_E(end - 1) - bil_E(end), 3)]);
    # end
    # end
    # end

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=sphere_vertices,
                           metadata=mesh.metadata,
                           process=False), evol
Example #5
0
    all_area_diff = list()
    plane_proj_mesh = sphmap.stereo_projection(sphere_mesh, invert=False)
    for i in range(8):
        t += step
        all_steps.append(t)
        a = complex(t, 0)

        plan_complex_transfo = sphmap.mobius_transformation(
            a, b, c, d, plane_proj_mesh)
        sphere_transformed_mesh = sphmap.inverse_stereo_projection(
            plan_complex_transfo, invert=False)
        all_spheres.append(sphere_transformed_mesh)
        angle_diff = sdst.angle_difference(sphere_mesh,
                                           sphere_transformed_mesh)
        all_angle_diff.append(angle_diff)
        area_diff = sdst.area_difference(sphere_mesh, sphere_transformed_mesh)
        all_area_diff.append(area_diff)
        poly_angles = meshPolygonAngles(sphere_transformed_mesh.vertices,
                                        sphere_transformed_mesh.faces)
        print(np.max(sphere_transformed_mesh.face_angles - poly_angles))
        poly_areas = meshPolygonArea(sphere_transformed_mesh.vertices,
                                     sphere_transformed_mesh.faces)
        print(np.max(sphere_transformed_mesh.area_faces - poly_areas))
    splt.pyglet_plot(sphere_transformed_mesh,
                     z_coord_texture,
                     caption="moebius transformed sphere")

    int_area = [np.sum(np.abs(v)) for v in all_area_diff]
    int_angle = [np.sum(np.abs(angle_diff).flatten()) for v in all_angle_diff]
    fig, ax = plt.subplots(1, 1)
    ax.set_xlabel('moebius scaling parameter')
Example #6
0
        pp = pp / np.vstack((nopp, np.vstack((nopp, nopp)))).transpose()
        qq = qq / np.vstack((noqq, np.vstack((noqq, noqq)))).transpose()
        angles_out[:, i] = np.arccos(np.sum(pp * qq, 1))
    return angles_out


if __name__ == '__main__':
    mesh = sio.load_mesh('data/example_mesh.gii')
    sph, evol = smap.spherical_mapping(mesh,
                                       mapping_type='conformal',
                                       dt=0.01,
                                       nb_it=3000)
    sph.show()

    angle_diff = sdst.angle_difference(sph, mesh)
    area_diff = sdst.area_difference(sph, mesh)
    edge_diff = sdst.edge_length_difference(sph, mesh)

    aevol = np.array(evol)
    f, ax = plt.subplots(1, 3)
    ax[0].set_title('angles')
    # ax[0].hist(angle_diff.flatten())
    ax[0].plot(aevol[:, 0])
    ax[0].grid(True)
    ax[1].set_title('areas')
    # ax[1].hist(area_diff.flatten())
    ax[1].plot(aevol[:, 1])
    ax[1].grid(True)
    ax[2].set_title('edges')
    # ax[2].hist(edge_diff.flatten())
    ax[2].plot(aevol[:, 2])
Example #7
0
def spherical_mapping(mesh,
                      mapping_type='laplacian_eigenvectors',
                      conformal_w=1,
                      authalic_w=1,
                      dt=0.01,
                      nb_it=10):
    """
    Computes the mapping between the input mesh and a sphere centered on 0 and of radius=1
    Several methods are implemented:
    -for laplacian eigenvectors, see:
    J. Lefèvre and G. Auzias, "Spherical Parameterization for Genus Zero Surfaces Using
    Laplace-Beltrami Eigenfunctions," in 2nd Conference on Geometric Science of
    Information, GSI, 2015, 121–29, https://doi.org/10.1007/978-3-319-25040-3_14.
    -for conformal mapping, see:
    Desbrun, M., Meyer, M., & Alliez, P., "Intrinsic parameterizations of surface meshes",
    Computer Graphics Forum, 21(3), 2002, 209–218. https://doi.org/10.1111/1467-8659.00580
    -for authalic and combined methods, see:
    Rachel a Yotter, Paul M. Thompson, and Christian Gaser, “Algorithms to Improve the
    Reparameterization of Spherical Mappings of Brain Surface Meshes.,” Journal of
    Neuroimaging 21, no. 2 (April 2011): e134-47, https://doi.org/10.1111/j.1552-6569.2010.00484.x.
    or
    Ilja Friedel, Peter Schröder, and Mathieu Desbrun, “Unconstrained Spherical Parameterization”,
    Journal of Graphics, GPU, and Game Tools 12, no. 1 (2007): 17–26.
    :param mesh: Trimesh object, input mesh to be mapped onto a sphere
    :param mapping_type: string, type of mapping method, possible options are:
    'laplacian_eigenvectors', 'conformal', 'authalic' or 'combined'
    :param conformal_w: Float, weight of the conformal constraint for the 'combined' method
    :param authalic_w: Float, weight of the authalic constraint for the 'combined' method
    :param dt: Float, discrtization step
    :param nb_it: Int, number of iterations
    :return: Trimesh object: the spherical representation of the input mesh, having the same
    adjacency (faces, edges, vertex indexing) as the input mesh.
    """
    # computing spherical mapping based on laplacian eigenvectors
    sph_vert = sdg.mesh_laplacian_eigenvectors(mesh, nb_vectors=3)
    norm_sph_vert = np.sqrt(np.sum(sph_vert * sph_vert, 1))
    sphere_vertices = sph_vert / np.tile(norm_sph_vert, (3, 1)).T
    if mapping_type == 'laplacian_eigenvectors':
        return trimesh.Trimesh(faces=mesh.faces,
                               vertices=sphere_vertices,
                               metadata=mesh.metadata,
                               process=False)

    if mapping_type == 'conformal':
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')

    if mapping_type == 'authalic':
        L, B = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')

    if mapping_type == 'combined':
        Lconf, Bconf = sdg.compute_mesh_laplacian(mesh, lap_type='conformal')
        Laut, Baut = sdg.compute_mesh_laplacian(mesh, lap_type='authalic')
        L = conformal_w * Lconf + authalic_w * Laut
    # continue the spherical mappig by minimizig the energy
    evol = list()
    for it in range(nb_it):
        sphere_vertices = sphere_vertices - dt * L.dot(sphere_vertices)
        # sphere_vertices * L
        norm_sph_vert = np.sqrt(np.sum(sphere_vertices * sphere_vertices, 1))
        sphere_vertices = sphere_vertices / np.tile(norm_sph_vert, (3, 1)).T
        if it % 10 == 0:
            sph = trimesh.Trimesh(faces=mesh.faces,
                                  vertices=sphere_vertices,
                                  process=False)
            angle_diff = sdst.angle_difference(sph, mesh)
            area_diff = sdst.area_difference(sph, mesh)
            edge_diff = sdst.edge_length_difference(sph, mesh)
            evol.append([
                np.sum(np.abs(angle_diff.flatten())),
                np.sum(np.abs(area_diff.flatten())),
                np.sum(np.abs(edge_diff.flatten()))
            ])

    return trimesh.Trimesh(faces=mesh.faces,
                           vertices=sphere_vertices,
                           metadata=mesh.metadata,
                           process=False), evol
Example #8
0
    visb_sc.add_to_subplot(l_obj)
visb_sc.preview()

###############################################################################
# Mapping onto a planar disk
disk_mesh = smap.disk_conformal_mapping(open_mesh)
# Visualization
visb_sc2 = splt.visbrain_plot(mesh=disk_mesh, caption='disk mesh')
for bound in open_mesh_boundary:
    points = disk_mesh.vertices[bound]
    s_rad = SourceObj('rad',
                      points,
                      color='red',
                      symbol='square',
                      radius_min=10)
    visb_sc2.add_to_subplot(s_rad)
    lines = Line(pos=disk_mesh.vertices[bound], width=10, color='b')
    # wrap the vispy object using visbrain
    l_obj = VispyObj('line', lines)
    visb_sc2.add_to_subplot(l_obj)
visb_sc2.preview()

###############################################################################
# Compute distortion measures between original and planar representations
angle_diff = sdst.angle_difference(disk_mesh, open_mesh)
area_diff = sdst.area_difference(disk_mesh, open_mesh)
edge_diff = sdst.edge_length_difference(disk_mesh, open_mesh)
print(np.mean(angle_diff))
print(np.mean(area_diff))
print(np.mean(edge_diff))