Skip to content

Commit 3258152

Browse files
authored
Add MinGap function (#765)
* Add tests for intersection * Add POC MinGap implementation and tests * Add tests where closest point falls on the triangle's face or on one of the edges * Create TriangleDistance declaration * Delete intersect tests * Add stub MinGap definition * Add triangle distance impl * Add comments * Fix tests * Fix build * Use collider * Collider exploration * Collider impl, cleanup * Use par transform * Revert settings.json, add comments * Add comments * Move tri_dist to utils * Delete unnecessary include * Create lambda for bounding box expansion * Move duplicate logic to lambda * Cleanup * Use floats instead of doubles, use glm::clamp instead of own implementation * User ternaries * Remove DistanceTriangleTriangleSquared out params * Move MinGap impl to Impl * Use std::array instead of C-style * Modify MinGap test cases for clarity, add overlapping tri_dist test * Add c, wasm, python bindings * Fix formatting * Clean up comments * Test whether faceboxes need to be sorted * Add min_gap example to all_apis.py * Fix formatting * Clean up python binding * Fix edge to edge test case * Test BVH culling * Remove sorting of other manifold's boxes * Use collider_ member, remove sorting * Move tests to manifold_test.cpp * Remove whitespace * Rename some tests for clarity * Remove redundant test, modify test for edge to edge test for clarity * Fix comments * Parallelize narrow phase * Reduce sphere res in test case to not cause out of memory error * Add complex test case * Remove unnecessary cast * Refactor functor is lambda
1 parent 7872959 commit 3258152

File tree

14 files changed

+470
-2
lines changed

14 files changed

+470
-2
lines changed

.vscode/settings.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,4 @@
150150
},
151151
"python.formatting.provider": "none",
152152
"clang-format.executable": "clang-format",
153-
}
153+
}

bindings/c/include/manifoldc.h

+2
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ ManifoldManifold *manifold_set_properties(
192192
void (*fun)(float *new_prop, ManifoldVec3 position, const float *old_prop));
193193
ManifoldManifold *manifold_calculate_curvature(void *mem, ManifoldManifold *m,
194194
int gaussian_idx, int mean_idx);
195+
float manifold_min_gap(ManifoldManifold *m, ManifoldManifold *other,
196+
float searchLength);
195197
ManifoldManifold *manifold_calculate_normals(void *mem, ManifoldManifold *m,
196198
int normal_idx,
197199
int min_sharp_angle);

bindings/c/manifoldc.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,11 @@ ManifoldManifold *manifold_calculate_curvature(void *mem, ManifoldManifold *m,
556556
return to_c(new (mem) Manifold(man));
557557
}
558558

559+
float manifold_min_gap(ManifoldManifold *m, ManifoldManifold *other,
560+
float searchLength) {
561+
return from_c(m)->MinGap(*from_c(other), searchLength);
562+
}
563+
559564
ManifoldManifold *manifold_calculate_normals(void *mem, ManifoldManifold *m,
560565
int normal_idx,
561566
int min_sharp_angle) {

bindings/python/examples/all_apis.py

+3
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ def all_manifold():
112112
m = m.trim_by_plane((0, 0, 1), 0)
113113
m = m.warp(lambda p: (p[0] + 1, p[1] / 2, p[2] * 2))
114114
m = m.warp_batch(lambda ps: ps * [1, 0.5, 2] + [1, 0, 0])
115+
m = Manifold.cube()
116+
m2 = Manifold.cube().translate([2, 0, 0])
117+
d = m.min_gap(m2, 2)
115118

116119

117120
def run():

bindings/python/manifold3d.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,10 @@ NB_MODULE(manifold3d, m) {
315315
.def("calculate_curvature", &Manifold::CalculateCurvature,
316316
nb::arg("gaussian_idx"), nb::arg("mean_idx"),
317317
manifold__calculate_curvature__gaussian_idx__mean_idx)
318+
.def("min_gap", &Manifold::MinGap, nb::arg("other"),
319+
nb::arg("search_length"),
320+
"Returns the minimum gap between two manifolds."
321+
"Returns a float between 0 and searchLength.")
318322
.def("calculate_normals", &Manifold::CalculateNormals,
319323
nb::arg("normal_idx"), nb::arg("min_sharp_angle") = 60,
320324
manifold__calculate_normals__normal_idx__min_sharp_angle)

bindings/wasm/bindings.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ EMSCRIPTEN_BINDINGS(whatever) {
166166
.function("precision", &Manifold::Precision)
167167
.function("genus", &Manifold::Genus)
168168
.function("getProperties", &Manifold::GetProperties)
169+
.function("minGap", &Manifold::MinGap)
169170
.function("calculateCurvature", &Manifold::CalculateCurvature)
170171
.function("calculateNormals", &Manifold::CalculateNormals)
171172
.function("originalID", &Manifold::OriginalID)

bindings/wasm/manifold-encapsulated-types.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,13 @@ export class Manifold {
858858
*/
859859
getProperties(): Properties;
860860

861+
862+
/*
863+
* Returns the minimum gap between two manifolds. Returns a float between
864+
* 0 and searchLength.
865+
*/
866+
minGap(other: Manifold, searchLength: number): number;
867+
861868
// Export
862869

863870
/**

src/manifold/include/manifold.h

+1
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ class Manifold {
218218
float Precision() const;
219219
int Genus() const;
220220
Properties GetProperties() const;
221+
float MinGap(const Manifold& other, float searchLength) const;
221222
///@}
222223

223224
/** @name Mesh ID

src/manifold/src/impl.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "mesh_fixes.h"
2424
#include "par.h"
2525
#include "svd.h"
26+
#include "tri_dist.h"
2627

2728
namespace {
2829
using namespace manifold;
@@ -902,4 +903,48 @@ SparseIndices Manifold::Impl::VertexCollisionsZ(
902903
else
903904
return collider_.Collisions<false, false>(vertsIn);
904905
}
906+
907+
/*
908+
* Returns the minimum gap between two manifolds. Returns a float between
909+
* 0 and searchLength.
910+
*/
911+
float Manifold::Impl::MinGap(const Manifold::Impl& other,
912+
float searchLength) const {
913+
ZoneScoped;
914+
Vec<Box> faceBoxOther;
915+
Vec<uint32_t> faceMortonOther;
916+
917+
other.GetFaceBoxMorton(faceBoxOther, faceMortonOther);
918+
919+
transform(autoPolicy(faceBoxOther.size()), faceBoxOther.begin(),
920+
faceBoxOther.end(), faceBoxOther.begin(),
921+
[searchLength](const Box& box) {
922+
return Box(box.min - glm::vec3(searchLength),
923+
box.max + glm::vec3(searchLength));
924+
});
925+
926+
SparseIndices collisions = collider_.Collisions(faceBoxOther.cview());
927+
928+
float minDistanceSquared = transform_reduce<float>(
929+
autoPolicy(collisions.size()), thrust::counting_iterator<int>(0),
930+
thrust::counting_iterator<int>(collisions.size()),
931+
[&collisions, this, &other](int i) {
932+
const int tri = collisions.Get(i, 1);
933+
const int triOther = collisions.Get(i, 0);
934+
935+
std::array<glm::vec3, 3> p;
936+
std::array<glm::vec3, 3> q;
937+
938+
for (const int j : {0, 1, 2}) {
939+
p[j] = vertPos_[halfedge_[3 * tri + j].startVert];
940+
q[j] = other.vertPos_[other.halfedge_[3 * triOther + j].startVert];
941+
}
942+
943+
return DistanceTriangleTriangleSquared(p, q);
944+
},
945+
searchLength * searchLength, thrust::minimum<float>());
946+
947+
return sqrt(minDistanceSquared);
948+
};
949+
905950
} // namespace manifold

src/manifold/src/impl.h

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ struct Manifold::Impl {
104104
SparseIndices EdgeCollisions(const Impl& B, bool inverted = false) const;
105105
SparseIndices VertexCollisionsZ(VecView<const glm::vec3> vertsIn,
106106
bool inverted = false) const;
107+
float MinGap(const Impl& other, float searchLength) const;
107108

108109
bool IsEmpty() const { return NumVert() == 0; }
109110
int NumVert() const { return vertPos_.size(); }

src/manifold/src/manifold.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "csg_tree.h"
2222
#include "impl.h"
2323
#include "par.h"
24+
#include "tri_dist.h"
2425

2526
namespace {
2627
using namespace manifold;
@@ -945,4 +946,21 @@ Manifold Manifold::Hull() const { return Hull(GetMesh().vertPos); }
945946
Manifold Manifold::Hull(const std::vector<Manifold>& manifolds) {
946947
return Compose(manifolds).Hull();
947948
}
949+
950+
/**
951+
* Returns the minimum gap between two manifolds. Returns a float between
952+
* 0 and searchLength.
953+
*
954+
* @param other The other manifold to compute the minimum gap to.
955+
* @param searchLength The maximum distance to search for a minimum gap.
956+
*/
957+
float Manifold::MinGap(const Manifold& other, float searchLength) const {
958+
auto intersect = *this ^ other;
959+
auto prop = intersect.GetProperties();
960+
961+
if (prop.volume != 0) return 0.0f;
962+
963+
return GetCsgLeafNode().GetImpl()->MinGap(*other.GetCsgLeafNode().GetImpl(),
964+
searchLength);
965+
}
948966
} // namespace manifold

src/utilities/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,4 @@ endif()
8383
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17)
8484

8585
install(TARGETS ${PROJECT_NAME} EXPORT manifoldTargets)
86-
install(FILES include/public.h include/vec_view.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME})
86+
install(FILES include/public.h include/vec_view.h include/tri_dist.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME})

0 commit comments

Comments
 (0)