Reputation: 3707
I'm working with 3d data and am provided with a list of vertices that are connected to each other. The data has the following format:
faces = [
(0, 1, 2),
(1, 3, 2),
(3, 5, 6),
(5, 7, 4),
(10, 11, 12),
(11, 12, 13),
(12, 13, 14)
]
Each item in the array consist of a 3-tuple where the number in each position represents the index of the vertices that are connected with each other. I've visualized this example in the picture to give a better understanding of how the vertices are connected.
What I'm looking for is a simple, easy to implement, algorithm that takes faces
as it's input and returns the following as it's output:
[
[0, 1, 2, 3, 4, 5, 6, 7],
[10, 11, 12, 13, 14]
]
Upvotes: 0
Views: 1511
Reputation: 20472
Assume that you want to separate the vertices into sets of vertices that are all reachable from each other, but not reachable from any vertice outside the set.
Here is the pseudo code for the algorithm
LOOP
CONSTRUCT empty current set
SELECT V arbitrary vertex
add V to current set
remove V from graph
LOOP // while set is growing
added_to_set = false
LOOP V over vertices in graph
LOOP Vset over current set
IF Vset connected to V
add V to current set
remove V from graph
added_to_set = true
break;
IF added_to_set == false
break; // the set is maximal
ADD current set to list of sets
IF graph has no remaining vertices
OUTPUT sets found
STOP
For a C++ implementation of this see code at https://github.com/JamesBremner/PathFinder2/blob/dbd6ff06edabd6a6d35d5eb10ed7972dc2d779a6/src/cPathFinder.cpp#L483
Upvotes: 0
Reputation: 1277
Surt's algorithm is one possible solution.
Since your graph is undirected and you are looking for something very simple, take a look at Breadth-first-search or Depth-first-search (they are the standard algorithms for graph theory which are very easy to understand and implement).
You basically search for every vertex that is reachable from a start vertex and label them to the same group. This process is repeated until every vertex has a group.
Upvotes: 0
Reputation: 16099
You could use union-find
I'll add a naive version of it here
untested code ahead
using face = std::array<int, 3>;
std::vector<face> faces = {
{0, 1, 2},
{1, 3, 2},
{3, 5, 6},
{5, 7, 4},
{10, 11, 12},
{11, 12, 13},
{12, 13, 14}
}
std::unordered_map<int> con;
int Find(int vert) {
while (vert != con[very])
vert = con[vert];
return vert;
}
for (auto triple : faces) {
for (int vert : triple) {
if (!con.count(vert)) {
con[vert]=vert; // i'm my own parent ...
} else {
con[vert] = Find(vert);
}
}
}
std::unordered_map<int, std::vector<int>> clusters
for (auto& pair : con) {
// reduce the search path for nodes that has pair as parent.
int cluster = Find(pair.second);
con[pair.second] = cluster;
clusters[cluster].push_back(pair.first);
}
return clusters; // or convert to vector of vectors
Note without path halving and effective union this will have a horrible runtime.
Upvotes: 2