Skip to content

Commit

Permalink
optimized connected component computation (#569)
Browse files Browse the repository at this point in the history
* use union find for graph connected components

* update readme

* remove graphlite dep
  • Loading branch information
pca006132 authored Oct 5, 2023
1 parent 206871a commit d51ee70
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 1,766 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ System Dependencies (note that we will automatically download the dependency if
- [`gtest`](https://github.com/google/googletest/): Google test library (only when test is enabled, i.e. `MANIFOLD_TEST=ON`)

Other dependencies:
- [`graphlite`](https://github.com/haasdo95/graphlite): connected components algorithm.
- [`Clipper2`](https://github.com/AngusJohnson/Clipper2j): provides our 2D subsystem
- [`Clipper2`](https://github.com/AngusJohnson/Clipper2): provides our 2D subsystem
- [`quickhull`](https://github.com/akuukka/quickhull): 3D convex hull algorithm.

## What's here
Expand Down
2 changes: 1 addition & 1 deletion bindings/c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ endif()

target_link_libraries(
${PROJECT_NAME}
PRIVATE manifold sdf graphlite cross_section
PRIVATE manifold sdf cross_section
)

target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
Expand Down
2 changes: 1 addition & 1 deletion src/manifold/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ add_library(${PROJECT_NAME} ${SOURCE_FILES})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(${PROJECT_NAME}
PUBLIC utilities cross_section
PRIVATE collider polygon ${MANIFOLD_INCLUDE} graphlite Clipper2 quickhull
PRIVATE collider polygon ${MANIFOLD_INCLUDE} Clipper2 quickhull
)

target_compile_options(${PROJECT_NAME} PRIVATE ${MANIFOLD_FLAGS})
Expand Down
12 changes: 4 additions & 8 deletions src/manifold/src/constructors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

#include "cross_section.h"
#include "csg_tree.h"
#include "graph.h"
#include "impl.h"
#include "par.h"
#include "polygon.h"
Expand Down Expand Up @@ -465,17 +464,14 @@ Manifold Manifold::Compose(const std::vector<Manifold>& manifolds) {
* containing a copy of the original. It is the inverse operation of Compose().
*/
std::vector<Manifold> Manifold::Decompose() const {
Graph graph;
UnionFind<> uf(NumVert());
// Graph graph;
auto pImpl_ = GetCsgLeafNode().GetImpl();
for (int i = 0; i < NumVert(); ++i) {
graph.add_nodes(i);
}
for (const Halfedge& halfedge : pImpl_->halfedge_) {
if (halfedge.IsForward())
graph.add_edge(halfedge.startVert, halfedge.endVert);
if (halfedge.IsForward()) uf.unionXY(halfedge.startVert, halfedge.endVert);
}
std::vector<int> componentIndices;
const int numComponents = ConnectedComponents(componentIndices, graph);
const int numComponents = uf.connectedComponents(componentIndices);

if (numComponents == 1) {
std::vector<Manifold> meshes(1);
Expand Down
27 changes: 10 additions & 17 deletions src/manifold/src/impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include <map>
#include <numeric>

#include "graph.h"
#include "hashtable.h"
#include "mesh_fixes.h"
#include "par.h"
Expand Down Expand Up @@ -272,11 +271,11 @@ struct CheckCoplanarity {
VecView<int> comp2tri;
VecView<const Halfedge> halfedge;
VecView<const glm::vec3> vertPos;
VecView<const int> components;
std::vector<int>* components;
const float precision;

void operator()(int tri) {
const int component = components[tri];
const int component = (*components)[tri];
const int referenceTri = comp2tri[component];
if (referenceTri < 0 || referenceTri == tri) return;

Expand Down Expand Up @@ -310,17 +309,13 @@ struct EdgeBox {

int GetLabels(std::vector<int>& components,
const Vec<thrust::pair<int, int>>& edges, int numNodes) {
Graph graph;
for (int i = 0; i < numNodes; ++i) {
graph.add_nodes(i);
}
for (int i = 0; i < edges.size(); ++i) {
const thrust::pair<int, int> edge = edges[i];
if (edge.first < 0) continue;
graph.add_edge(edge.first, edge.second);
UnionFind<> uf(numNodes);
for (auto edge : edges) {
if (edge.first == -1 || edge.second == -1) continue;
uf.unionXY(edge.first, edge.second);
}

return ConnectedComponents(components, graph);
return uf.connectedComponents(components);
}

void DedupePropVerts(manifold::Vec<glm::ivec3>& triProp,
Expand Down Expand Up @@ -639,7 +634,7 @@ void Manifold::Impl::CreateFaces(const std::vector<float>& propertyTolerance) {
std::vector<int> components;
const int numComponent = GetLabels(components, face2face, NumTri());

std::vector<int> comp2tri(numComponent, -1);
Vec<int> comp2tri(numComponent, -1);
for (int tri = 0; tri < NumTri(); ++tri) {
const int comp = components[tri];
const int current = comp2tri[comp];
Expand All @@ -649,15 +644,13 @@ void Manifold::Impl::CreateFaces(const std::vector<float>& propertyTolerance) {
}
}

Vec<int> componentsD(components);
Vec<int> comp2triD(comp2tri);
for_each_n(autoPolicy(halfedge_.size()), countAt(0), NumTri(),
CheckCoplanarity(
{comp2triD, halfedge_, vertPos_, componentsD, precision_}));
{comp2tri, halfedge_, vertPos_, &components, precision_}));

Vec<TriRef>& triRef = meshRelation_.triRef;
for (int tri = 0; tri < NumTri(); ++tri) {
const int referenceTri = comp2triD[components[tri]];
const int referenceTri = comp2tri[components[tri]];
if (referenceTri >= 0) {
triRef[tri].tri = referenceTri;
}
Expand Down
23 changes: 6 additions & 17 deletions src/manifold/src/sort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <numeric>
#include <set>

#include "graph.h"
#include "impl.h"
#include "par.h"

Expand Down Expand Up @@ -583,30 +582,20 @@ bool MeshGL::Merge() {
Collider collider(vertBox, vertMorton);
SparseIndices toMerge = collider.Collisions<true>(vertBox.cview());

Graph graph;
for (int i = 0; i < numVert; ++i) {
graph.add_nodes(i);
}
UnionFind<> uf(numVert);
for (int i = 0; i < mergeFromVert.size(); ++i) {
graph.add_edge(static_cast<int>(mergeFromVert[i]),
static_cast<int>(mergeToVert[i]));
uf.unionXY(static_cast<int>(mergeFromVert[i]),
static_cast<int>(mergeToVert[i]));
}
for (int i = 0; i < toMerge.size(); ++i) {
graph.add_edge(openVerts[toMerge.Get(i, false)],
openVerts[toMerge.Get(i, true)]);
}

std::vector<int> vertLabels;
const int numLabels = ConnectedComponents(vertLabels, graph);
std::vector<int> label2vert(numLabels);
for (int v = 0; v < numVert; ++v) {
label2vert[vertLabels[v]] = v;
uf.unionXY(openVerts[toMerge.Get(i, false)],
openVerts[toMerge.Get(i, true)]);
}

mergeToVert.clear();
mergeFromVert.clear();
for (int v = 0; v < numVert; ++v) {
const int mergeTo = label2vert[vertLabels[v]];
const int mergeTo = uf.find(v);
if (mergeTo != v) {
mergeFromVert.push_back(v);
mergeToVert.push_back(mergeTo);
Expand Down
2 changes: 0 additions & 2 deletions src/third_party/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
add_subdirectory(graphlite)

set(CLIPPER2_UTILS OFF)
set(CLIPPER2_EXAMPLES OFF)
set(CLIPPER2_TESTS OFF)
Expand Down
10 changes: 0 additions & 10 deletions src/third_party/graphlite/CMakeLists.txt

This file was deleted.

7 changes: 0 additions & 7 deletions src/third_party/graphlite/LICENSE.txt

This file was deleted.

27 changes: 0 additions & 27 deletions src/third_party/graphlite/include/graph.h

This file was deleted.

Loading

0 comments on commit d51ee70

Please sign in to comment.