Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/vertex_components.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include <igl/vertex_components.h>
#include <nanobind/nanobind.h>
#include <nanobind/eigen/dense.h>
#include <nanobind/eigen/sparse.h>
#include <nanobind/stl/tuple.h>

namespace nb = nanobind;
using namespace nb::literals;
Expand All @@ -16,6 +18,16 @@ namespace pyigl
igl::vertex_components(F, C);
return C;
}

// Wrapper for vertex_components with adjacency matrix
auto vertex_components_from_adjacency_matrix(
const Eigen::SparseMatrixI &adjacency)
{
Eigen::VectorXI c;
Eigen::VectorXI counts;
igl::vertex_components(adjacency, c, counts);
return std::make_tuple(c, counts);
}
}

// Bind the wrappers to the Python module
Expand All @@ -30,4 +42,13 @@ void bind_vertex_components(nb::module_ &m)

@param[in] F #F by 3 matrix of triangle (face) indices
@return Vector C of per-vertex connected-component ids)");

m.def(
"vertex_components_from_adjacency_matrix",
&pyigl::vertex_components_from_adjacency_matrix,
"adjacency"_a,
R"(Compute the connected components of a graph using an adjacency matrix, returning component IDs and counts.

@param[in] adjacency n by n sparse adjacency matrix
@return A tuple (c, counts) where c is an array of component ids (starting with 0) and counts is a #components array of counts for each component)");
}
21 changes: 21 additions & 0 deletions tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -1791,3 +1791,24 @@ def test_resolve_duplicated_faces():
F = np.array([[0, 1, 2], [0, 1, 2], [0, 1, 2], [3, 4, 5]], dtype=np.int64)
F2, J = igl.resolve_duplicated_faces(F)
assert set(map(tuple, F2.tolist())) == {(3, 4, 5)}


def test_vertex_components_from_adjacency_matrix():
# Two disconnected components: a triangle {0,1,2} and an edge {3,4}.
edges = [(0, 1), (1, 2), (0, 2), (3, 4)]
n = 5
rows, cols = [], []
for i, j in edges:
rows += [i, j]
cols += [j, i]
A = scipy.sparse.csr_matrix(
(np.ones(len(rows)), (rows, cols)), shape=(n, n)).astype(np.int64)
c, counts = igl.vertex_components_from_adjacency_matrix(A)
assert c.shape[0] == n
# vertices in the same component share an id; different components differ
assert c[0] == c[1] == c[2]
assert c[3] == c[4]
assert c[0] != c[3]
# counts is per-component and sums to the number of vertices
assert counts.sum() == n
assert sorted(counts.ravel().tolist()) == [2, 3]
Loading