-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Convex Decomposition and Minkowski Sum #663
Closed
Closed
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
ef30739
Add the Voro++ Library
zalo 56e026b
Add Basic Python Binding
zalo 804d29a
Get Fracture Operation Working
zalo 15579ef
Add Broken VoACD Implementation
zalo c039b8a
Fix late night typos and formatting
zalo 3f6248d
Get Basic VoCD Working
zalo a32be23
Formatting
zalo 2aef6ff
Formatting the Sequel
zalo 21f1daa
Formatting Part 3
zalo f0b9faf
Final Formatting
zalo ae5114d
After Final Formatting
zalo 595c933
Use the common form of glm::dvec
zalo 395e94b
Also dvec4
zalo 7e1fa10
Reformat again
zalo dfe8e62
Remove the non-submodule folder
zalo 1034970
Switch Voro to a Git Submodule
zalo 76ca0d9
Add a test
zalo 4921354
Add untested bindings
zalo d8fd65d
Minor Formatting
zalo 04ae42e
More formatting
zalo 7909f59
Dummy Commit
zalo 2505b15
Parallelize Voronoi Computation
zalo f86adc5
Add Early Exit
zalo c574580
Add a function for computing many convex hulls in parallel
zalo 1cb3a83
Add Minkowski Function
zalo e84e05c
Fix Formatting
zalo a4d20c0
Remove Extra Qualification
zalo 9c04c6d
added cgal convex decomposition test
pca006132 33c69d6
Merge branch 'master' into feat-voacd
zalo b6978bf
Update CGAL Test with Direct Comparison...
zalo 7ab872b
Add Minkowski Sum Test Too
zalo 3446bb0
Remove the need for Joggling
zalo 258612c
Add Non-Convex - Non-Convex Implementation
zalo 3dcd3a5
Handle alternate order submission
zalo 6a8a407
Finish Multithreading Naive Function
zalo c4537e7
Fix Formatting
zalo 19c58ca
Detect Degenerate Triangles
zalo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Copyright 2023 The Manifold Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h> | ||
#include <CGAL/Nef_polyhedron_3.h> | ||
#include <CGAL/Polyhedron_3.h> | ||
#include <CGAL/convex_decomposition_3.h> | ||
#include <CGAL/minkowski_sum_3.h> | ||
|
||
#include <chrono> | ||
#include <iostream> | ||
|
||
#include "manifold.h" | ||
|
||
using namespace manifold; | ||
|
||
using Kernel = CGAL::Epeck; | ||
using Polyhedron = CGAL::Polyhedron_3<Kernel>; | ||
using HalfedgeDS = Polyhedron::HalfedgeDS; | ||
using NefPolyhedron = CGAL::Nef_polyhedron_3<Kernel>; | ||
|
||
template <class HDS> | ||
class BuildFromManifold : public CGAL::Modifier_base<HDS> { | ||
public: | ||
using Vertex = typename HDS::Vertex; | ||
using Point = typename Vertex::Point; | ||
BuildFromManifold(const Manifold manifold) : manifold(manifold) {} | ||
void operator()(HDS &hds) { | ||
// Postcondition: hds is a valid polyhedral surface. | ||
CGAL::Polyhedron_incremental_builder_3<HDS> B(hds, true); | ||
auto mesh = manifold.GetMeshGL(); | ||
B.begin_surface(mesh.NumVert(), mesh.NumTri(), mesh.NumTri() * 3); | ||
|
||
for (size_t i = 0; i < mesh.vertProperties.size(); i += mesh.numProp) { | ||
B.add_vertex(Point(mesh.vertProperties[i], mesh.vertProperties[i + 1], | ||
mesh.vertProperties[i + 2])); | ||
} | ||
for (size_t i = 0; i < mesh.triVerts.size(); i += 3) { | ||
B.begin_facet(); | ||
for (const int j : {0, 1, 2}) B.add_vertex_to_facet(mesh.triVerts[i + j]); | ||
B.end_facet(); | ||
} | ||
B.end_surface(); | ||
} | ||
|
||
private: | ||
const Manifold manifold; | ||
}; | ||
|
||
int main(int argc, char **argv) { | ||
Manifold spherecube = | ||
Manifold::Cube(glm::vec3(1), true) - Manifold::Sphere(0.6, 100); | ||
Manifold smallsphere = Manifold::Sphere(0.1, 20); | ||
|
||
BuildFromManifold<HalfedgeDS> build(spherecube); | ||
std::cout << "nTri = " << spherecube.NumTri() << std::endl; | ||
|
||
auto start = std::chrono::high_resolution_clock::now(); | ||
Polyhedron poly; | ||
poly.delegate(build); | ||
std::cout << "to Polyhedron took " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
start = std::chrono::high_resolution_clock::now(); | ||
NefPolyhedron np(poly); | ||
std::cout << "conversion to Nef Polyhedron took " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
start = std::chrono::high_resolution_clock::now(); | ||
auto convexDecomposition = spherecube.ConvexDecomposition(); | ||
std::cout << "[MANIFOLD] decomposed into " << convexDecomposition.size() | ||
<< " parts in " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
start = std::chrono::high_resolution_clock::now(); | ||
auto generalMinkowskiSum = Manifold::Minkowski(spherecube, smallsphere); | ||
std::cout << "[MANIFOLD] general minkowski summed in " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
start = std::chrono::high_resolution_clock::now(); | ||
auto naiveMinkowskiSum = Manifold::Minkowski(spherecube, smallsphere, true); | ||
std::cout << "[MANIFOLD] naive minkowski summed in " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
start = std::chrono::high_resolution_clock::now(); | ||
CGAL::convex_decomposition_3(np); | ||
std::cout << "[CGAL] decomposed into " << np.number_of_volumes() | ||
<< " parts in " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
// Create the Small Sphere NEF Polyhedron for Minkowski Summing | ||
Polyhedron poly2; | ||
poly.delegate(BuildFromManifold<HalfedgeDS>(smallsphere)); | ||
NefPolyhedron np2(poly); | ||
|
||
start = std::chrono::high_resolution_clock::now(); | ||
CGAL::minkowski_sum_3(np, np2); | ||
std::cout << "[CGAL] minkowski summed in " | ||
<< (std::chrono::high_resolution_clock::now() - start).count() / 1e9 | ||
<< " sec" << std::endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -316,4 +316,33 @@ CrossSection Manifold::Impl::Project() const { | |
|
||
return CrossSection(polys).Simplify(precision_); | ||
} | ||
|
||
glm::dvec4 Manifold::Impl::Circumcircle(Vec<glm::dvec3> verts, int face) const { | ||
glm::dvec3 va = verts[this->halfedge_[(face * 3) + 0].startVert]; | ||
glm::dvec3 vb = verts[this->halfedge_[(face * 3) + 1].startVert]; | ||
glm::dvec3 vc = verts[this->halfedge_[(face * 3) + 2].startVert]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about a |
||
|
||
glm::dvec3 a = va - vc; | ||
glm::dvec3 b = vb - vc; | ||
glm::dvec3 c = va - vb; | ||
double a_length = glm::length(a); | ||
double b_length = glm::length(b); | ||
double c_length = glm::length(c); | ||
glm::dvec3 numerator = | ||
glm::cross((((a_length * a_length) * b) - ((b_length * b_length) * a)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we remove a few parens? |
||
glm::cross(a, b)); | ||
double crs = glm::length(glm::cross(a, b)); | ||
double denominator = 2.0 * (crs * crs); | ||
glm::dvec3 circumcenter = (numerator / denominator) + vc; | ||
double circumradius = glm::length(circumcenter - vc); | ||
|
||
double max_length = std::fmax(a_length, std::fmax(b_length, c_length)); | ||
double min_length = std::fmin(a_length, std::fmin(b_length, c_length)); | ||
if (max_length / min_length > 15.0) { | ||
circumradius *= -1.0; // Mark this triangle as degenerate | ||
} | ||
|
||
return glm::dvec4(circumcenter.x, circumcenter.y, circumcenter.z, | ||
circumradius); | ||
} | ||
} // namespace manifold |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is fracture really meant to be a public function, or is it just a means to ConvexDecomposition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's worth making it public because it's a non-trival operation that generalizes splitting a singular cutting plane by limiting the influence of each half-space. This can help make modelling cuts and edits more "local". Like, if you wanted to take a complicated, winding assembly, and break it apart into multiple pieces, it's nice to be able to make cuts with a localized area of effect to avoid mangling the model far from the cut.
Also, it's useful for people looking to implement their own approximate decompositions based on their particular speed and accuracy needs.
And it's good for modelling lattices and packings, which is one of the primary things Voro++ is used for... it could even help replicate NTopology lattice generation functionality if each cell is contracted and then subtracted from a solid region.
There's a universe with a dual version of this function, where the user directly specifies splitting planes and their relative area of influence. This could be implemented by inserting two voronoi cells right next to each other with the plane normal as the offset between them. Perhaps this would be more intuitive?