def test_bfs(self):
        a = igl.adjacency_matrix(self.f1)
        p, d = igl.bfs(a, 0)
        self.assertEqual(p.shape, (self.v1.shape[0],))
        self.assertEqual(p.shape, (self.v1.shape[0],))

        try:
            p, d, = igl.bfs(a, -1)
            self.assertTrue(False)
        except IndexError as e:
            pass

        a = csc.csc_matrix(np.zeros([0, 0], dtype=np.int32))
        try:
            p, d, = igl.bfs(a, 0)
            self.assertTrue(False)
        except ValueError as e:
            pass

        a = csc.csc_matrix(np.zeros([10, 11], dtype=np.int32))
        try:
            p, d, = igl.bfs(a, 0)
            self.assertTrue(False)
        except ValueError as e:
            pass

        a = csc.csc_matrix(np.zeros([10, 10], dtype=np.int32))
        p, d, = igl.bfs(a, 0)
        self.assertEqual(p.shape, ())
        self.assertTrue(np.array_equal(d, -np.ones(10)))
        self.assertTrue(p.flags.c_contiguous)
    def test_vertex_components(self):
        a = igl.adjacency_matrix(self.f1)
        c, count = igl.vertex_components_from_adjacency_matrix(a)
        self.assertEqual(c.shape[0], self.v1.shape[0])

        c = igl.vertex_components(self.f1)
        self.assertEqual(c.shape[0], self.v1.shape[0])
Esempio n. 3
0
def get_graph_laplacian(faces):
    """
    Return the Graph Laplacian of the surface described by faces
    """
    A = -igl.adjacency_matrix(faces)
    D = A.sum(axis=1)
    A.setdiag(-np.squeeze(np.asarray(D)))
    return A
Esempio n. 4
0
def smooth_data(v, f, w):
    # Smoothing = Minimize curvature
    #
    # min_{p*}{E(p*)}
    #
    # E(p*) = sum_{p in points on mesh}{A_p * ((Lp*)^2 + w(p* - p)^2)},
    # where A_p is the voronoi region around point p
    #
    # Solve dE(p*)/dp* = 0
    # => (L'ML + wM)p* = (wM)p ~= Ax = b
    #
    # L = M^(-1)L_w, w = cotangent[c]/uniform[u]/...
    #
    # L_c defined in slides 5 page 66
    # M and L defined in slides 6 page 23

    # Constructing the squared Laplacian and squared Hessian energy
    # NOTE L_c is sparse
    # L_c = igl.cotmatrix(v, f) # discrete laplacian

    # L_c.data[np.isnan(L_c.data)] = 0
    # L_c.data[L_c.data > 1e7] = 1e7
    # L_c.data[L_c.data < -1e7] = -1e7

    # Uniform laplacian
    # adopted from here:
    # https://libigl.github.io/libigl-python-bindings/igl_docs/#cotmatrix
    adj = igl.adjacency_matrix(f)
    # Sum each row = number of neighbours
    adj_sum = np.squeeze(np.asarray(np.sum(adj, axis=1)))
    # Convert row sums into diagonal of sparse matrix
    adj_diag = sp.sparse.diags(adj_sum)
    # Build uniform laplacian
    L_u = adj - adj_diag

    # NOTE M is sparse
    M = igl.massmatrix(v, f, igl.MASSMATRIX_TYPE_VORONOI)
    # Give corrupted triangles only very little weight
    mask = np.logical_or(np.isnan(M.data), M.data == 0)
    M.data[mask] = 1e-7

    M_inv = sp.sparse.diags(1 / M.diagonal())

    # NOTE L_c can become very weird when dealing with corrupted meshes
    # L = M_inv @ L_c
    L = M_inv @ L_u

    A = L.T @ M @ L + w * M
    # TODO lambda * ID ?
    A += sp.sparse.identity(A.shape[0])
    b = w * M @ v

    v_star = sp.sparse.linalg.spsolve(A, b)

    return v_star
 def test_adjacency_matrix(self):
     a = igl.adjacency_matrix(self.f)
     self.assertTrue(a.shape == (self.v.shape[0], self.v.shape[0]))
     self.assertTrue(a.dtype == self.f.dtype)
     self.assertTrue(type(a) == csc.csc_matrix)