diff --git a/src/geometry/manifold/manifoldutils.cc b/src/geometry/manifold/manifoldutils.cc index 6c887252424..716742a095c 100644 --- a/src/geometry/manifold/manifoldutils.cc +++ b/src/geometry/manifold/manifoldutils.cc @@ -1,6 +1,7 @@ // Portions of this file are Copyright 2023 Google LLC, and licensed under GPL2+. See COPYING. #include "manifoldutils.h" #include "ManifoldGeometry.h" +#include "PolySetBuilder.h" #include "manifold.h" #include "printutils.h" #ifdef ENABLE_CGAL @@ -113,7 +114,23 @@ std::shared_ptr createManifoldFromPolySet(const PolySet& ps) return mani; } - // FIXME: Should we suppress this warning, as it may not be very actionable? + // Before announcing that the conversion failed, let's try to fix the most common + // causes of a non-manifold topology: + // Polygon soup of manifold topology with co-incident vertices having identical vertex positions + // + // Note: This causes us to lose the ability to represent manifold topologies with duplicate + // vertex positions (touching cubes, donut with vertex in the center etc.) + PolySetBuilder builder(ps.vertices.size(), ps.indices.size(), + ps.getDimension(), ps.convexValue()); + builder.appendPolySet(ps); + std::unique_ptr rebuilt_ps = builder.build(); + rebuilt_ps->setTriangular(ps.isTriangular()); + mani = createManifoldFromTriangularPolySet(*rebuilt_ps); + if (mani->getManifold().Status() == Error::NoError) { + return mani; + } + + // FIXME: Should we attempt merging vertices within epsilon distance before issuing this warning? LOG(message_group::Warning,"PolySet -> Manifold conversion failed: %1$s\n" "Trying to repair and reconstruct mesh..", ManifoldUtils::statusToString(mani->getManifold().Status())); diff --git a/tests/data/scad/3D/features/polyhedron-soup.scad b/tests/data/scad/3D/features/polyhedron-soup.scad new file mode 100644 index 00000000000..b70203cc6e8 --- /dev/null +++ b/tests/data/scad/3D/features/polyhedron-soup.scad @@ -0,0 +1,20 @@ +polyhedron(points = [ + [1,0,0], [0,0,1], [0,1,0], + [1,0,0], [0,1,0], [0,0,-1], + [1,0,0], [0,-1,0], [0,0,1], + [1,0,0], [0,0,-1], [0,-1,0], + [-1,0,0], [0,1,0], [0,0,1], + [-1,0,0], [0,0,-1], [0,1,0], + [-1,0,0], [0,0,1], [0,-1,0], + [-1,0,0], [0,-1,0], [0,0,-1], +], +faces = [ + [0,1,2], + [3,4,5], + [6,7,8], + [9,10,11], + [12,13,14], + [15,16,17], + [18,19,20], + [21,22,23] +]); diff --git a/tests/regression/cgalpngtest/polyhedron-soup-expected.png b/tests/regression/cgalpngtest/polyhedron-soup-expected.png new file mode 100644 index 00000000000..7f027528262 Binary files /dev/null and b/tests/regression/cgalpngtest/polyhedron-soup-expected.png differ diff --git a/tests/regression/dumptest/polyhedron-soup-expected.csg b/tests/regression/dumptest/polyhedron-soup-expected.csg new file mode 100644 index 00000000000..8898f2eff3e --- /dev/null +++ b/tests/regression/dumptest/polyhedron-soup-expected.csg @@ -0,0 +1,2 @@ +polyhedron(points = [[1, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 0], [0, 0, -1], [1, 0, 0], [0, -1, 0], [0, 0, 1], [1, 0, 0], [0, 0, -1], [0, -1, 0], [-1, 0, 0], [0, 1, 0], [0, 0, 1], [-1, 0, 0], [0, 0, -1], [0, 1, 0], [-1, 0, 0], [0, 0, 1], [0, -1, 0], [-1, 0, 0], [0, -1, 0], [0, 0, -1]], faces = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14], [15, 16, 17], [18, 19, 20], [21, 22, 23]], convexity = 1); + diff --git a/tests/regression/opencsgtest/polyhedron-soup-expected.png b/tests/regression/opencsgtest/polyhedron-soup-expected.png new file mode 100644 index 00000000000..7f027528262 Binary files /dev/null and b/tests/regression/opencsgtest/polyhedron-soup-expected.png differ diff --git a/tests/regression/throwntogethertest/polyhedron-soup-expected.png b/tests/regression/throwntogethertest/polyhedron-soup-expected.png new file mode 100644 index 00000000000..7f027528262 Binary files /dev/null and b/tests/regression/throwntogethertest/polyhedron-soup-expected.png differ