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])
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
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)