From 90b4f35d7112647f929dd397aaf70d09d854d47f Mon Sep 17 00:00:00 2001 From: Marius Kintel Date: Sun, 10 Mar 2024 10:52:58 -0400 Subject: [PATCH] PolySet: Add setters for isTriangular --- src/RenderStatistic.cc | 18 ++++++++++++------ src/core/primitives.cc | 11 ++++++----- src/geometry/GeometryEvaluator.cc | 2 +- src/geometry/PolySet.cc | 7 +++++-- src/geometry/PolySet.h | 5 ++++- src/geometry/PolySetBuilder.cc | 8 ++++---- src/geometry/PolySetUtils.cc | 4 ++-- src/geometry/cgal/cgalutils.cc | 2 +- src/geometry/manifold/ManifoldGeometry.cc | 2 +- src/geometry/manifold/manifoldutils.cc | 4 ++-- src/io/export.cc | 4 +++- src/io/export_stl.cc | 2 +- 12 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/RenderStatistic.cc b/src/RenderStatistic.cc index b9da310b62..e1086b5d44 100644 --- a/src/RenderStatistic.cc +++ b/src/RenderStatistic.cc @@ -242,8 +242,14 @@ void LogVisitor::printBoundingBox3(const BoundingBox& bb) void LogVisitor::visit(const PolySet& ps) { assert(ps.getDimension() == 3); - LOG("Top level object is a 3D object:"); - LOG(" Facets: %1$6d", ps.numFacets()); + LOG("Top level object is a 3D object (PolySet):"); + LOG(" Convex: %1$s", (ps.isConvex() ? "yes" : "no")); + LOG(" Vertices: %1$6d", ps.numVertices()); + if (ps.isTriangular()) { + LOG(" Triangles: %1$6d", ps.numFacets()); + } else { + LOG(" Facets: %1$6d", ps.numFacets()); + } printBoundingBox3(ps.getBoundingBox()); } @@ -252,7 +258,7 @@ void LogVisitor::visit(const CGAL_Nef_polyhedron& nef) { if (nef.getDimension() == 3) { bool simple = nef.p3->is_simple(); - LOG("Top level object is a 3D object:"); + LOG("Top level object is a 3D object (Nef polyhedron):"); LOG(" Simple: %1$s", (simple ? "yes" : "no")); LOG(" Vertices: %1$6d", nef.p3->number_of_vertices()); LOG(" Halfedges: %1$6d", nef.p3->number_of_halfedges()); @@ -285,14 +291,12 @@ void LogVisitor::visit(const ManifoldGeometry& mani_geom) { LOG(" Top level object is a 3D object (manifold):"); auto &mani = mani_geom.getManifold(); - auto bbox = mani.BoundingBox(); LOG(" Status: %1$s", ManifoldUtils::statusToString(mani.Status())); LOG(" Genus: %1$d", mani.Genus()); LOG(" Vertices: %1$6d", mani.NumVert()); LOG(" Facets: %1$6d", mani.NumTri()); - LOG(" BBox.min: %1$f, %2$f, %3$f", bbox.min.x, bbox.min.y, bbox.min.z); - LOG(" BBox.max: %1$f, %2$f, %3$f", bbox.max.x, bbox.max.y, bbox.max.z); + printBoundingBox3(mani_geom.getBoundingBox()); } #endif // ENABLE_MANIFOLD @@ -355,6 +359,8 @@ void StreamVisitor::visit(const PolySet& ps) nlohmann::json geometryJson; geometryJson["dimensions"] = 3; geometryJson["convex"] = ps.isConvex(); + geometryJson["vertices"] = ps.numVertices(); + geometryJson["triangular"] = ps.isTriangular(); geometryJson["facets"] = ps.numFacets(); if (is_enabled(RenderStatistic::BOUNDING_BOX)) { geometryJson["bounding_box"] = getBoundingBox3(ps); diff --git a/src/core/primitives.cc b/src/core/primitives.cc index dc4a864d33..5853725e8c 100644 --- a/src/core/primitives.cc +++ b/src/core/primitives.cc @@ -129,7 +129,7 @@ std::unique_ptr CubeNode::createGeometry() const z2 = this->z; } int dimension = 3; - auto ps = std::make_unique(3, true); + auto ps = std::make_unique(3, /*convex*/true); for (int i = 0; i < 8; i++) { ps->vertices.emplace_back(i & 1 ? x2 : x1, i & 2 ? y2 : y1, i & 4 ? z2 : z1); @@ -194,7 +194,7 @@ std::unique_ptr SphereNode::createGeometry() const // if (num_rings % 2 == 0) num_rings++; // To ensure that the middle ring is at // phi == 0 degrees - auto polyset = std::make_unique(3, true); + auto polyset = std::make_unique(3, /*convex*/true); polyset->vertices.reserve(num_rings * num_fragments); // double offset = 0.5 * ((fragments / 2) % 2); @@ -408,13 +408,14 @@ std::unique_ptr PolyhedronNode::createGeometry() const p->setConvexity(this->convexity); p->vertices=this->points; p->indices=this->faces; - p->isTriangular = true; + bool is_triangular = true; for (auto &poly : p->indices) { std::reverse(poly.begin(),poly.end()); - if (p->isTriangular && poly.size() > 3) { - p->isTriangular = false; + if (is_triangular && poly.size() > 3) { + is_triangular = false; } } + p->setTriangular(is_triangular); return p; } diff --git a/src/geometry/GeometryEvaluator.cc b/src/geometry/GeometryEvaluator.cc index 55424cc63a..8aa3774a4c 100644 --- a/src/geometry/GeometryEvaluator.cc +++ b/src/geometry/GeometryEvaluator.cc @@ -76,7 +76,7 @@ std::shared_ptr GeometryEvaluator::evaluateGeometry(const Abstra ps = PolySetUtils::getGeometryAsPolySet(result); assert(ps && ps->getDimension() == 3); // We cannot render concave polygons, so tessellate any PolySets - if (!ps->isEmpty() && !ps->isTriangular) { + if (!ps->isEmpty() && !ps->isTriangular()) { // Since is_convex() doesn't handle non-planar faces, we need to tessellate // also in the indeterminate state so we cannot just use a boolean comparison. See #1061 bool convex = bool(ps->convexValue()); // bool is true only if tribool is true, (not indeterminate and not false) diff --git a/src/geometry/PolySet.cc b/src/geometry/PolySet.cc index 3361f3ba8d..97a6a8dc1d 100644 --- a/src/geometry/PolySet.cc +++ b/src/geometry/PolySet.cc @@ -46,7 +46,8 @@ */ -PolySet::PolySet(unsigned int dim, boost::tribool convex) : dim_(dim), convex_(convex) +PolySet::PolySet(unsigned int dim, boost::tribool convex) + : dim_(dim), convex_(convex) { } @@ -108,7 +109,9 @@ void PolySet::transform(const Transform3d& mat) bool PolySet::isConvex() const { if (convex_ || this->isEmpty()) return true; if (!convex_) return false; - return PolySetUtils::is_approximately_convex(*this); + bool is_convex = PolySetUtils::is_approximately_convex(*this); + convex_ = is_convex; + return is_convex; } void PolySet::resize(const Vector3d& newsize, const Eigen::Matrix& autosize) diff --git a/src/geometry/PolySet.h b/src/geometry/PolySet.h index cca728ee38..1b3e0f129f 100644 --- a/src/geometry/PolySet.h +++ b/src/geometry/PolySet.h @@ -34,11 +34,14 @@ class PolySet : public Geometry bool isConvex() const; boost::tribool convexValue() const { return convex_; } - bool isTriangular = false; + + bool isTriangular() const { return is_triangular_; } + void setTriangular(bool triangular) { is_triangular_ = triangular; } static std::unique_ptr createEmpty() { return std::make_unique(3); } private: + bool is_triangular_ = false; unsigned int dim_; mutable boost::tribool convex_; mutable BoundingBox bbox_; diff --git a/src/geometry/PolySetBuilder.cc b/src/geometry/PolySetBuilder.cc index fccb89044c..24c72c21c9 100644 --- a/src/geometry/PolySetBuilder.cc +++ b/src/geometry/PolySetBuilder.cc @@ -141,17 +141,17 @@ void PolySetBuilder::append(const PolySet& ps) std::unique_ptr PolySetBuilder::build() { - std::unique_ptr polyset; - polyset = std::make_unique(dim_, convex_); + auto polyset = std::make_unique(dim_, convex_); vertices_.copy(std::back_inserter(polyset->vertices)); polyset->indices = std::move(indices_); polyset->setConvexity(convexity_); - polyset->isTriangular = true; + bool is_triangular = true; for (const auto& face : polyset->indices) { if (face.size() > 3) { - polyset->isTriangular = false; + is_triangular = false; break; } } + polyset->setTriangular(is_triangular); return polyset; } diff --git a/src/geometry/PolySetUtils.cc b/src/geometry/PolySetUtils.cc index ebdda61a01..c5e89337c6 100644 --- a/src/geometry/PolySetUtils.cc +++ b/src/geometry/PolySetUtils.cc @@ -56,9 +56,9 @@ std::unique_ptr tessellate_faces(const PolySet& polyset) int degeneratePolygons = 0; auto result = std::make_unique(3, polyset.convexValue()); result->setConvexity(polyset.getConvexity()); - result->isTriangular = true; + result->setTriangular(true); // ideally this should not require a copy... - if (polyset.isTriangular) { + if (polyset.isTriangular()) { result->vertices = polyset.vertices; result->indices = polyset.indices; return result; diff --git a/src/geometry/cgal/cgalutils.cc b/src/geometry/cgal/cgalutils.cc index 1264a163b1..45df9107eb 100644 --- a/src/geometry/cgal/cgalutils.cc +++ b/src/geometry/cgal/cgalutils.cc @@ -384,7 +384,7 @@ std::unique_ptr createPolySetFromNefPolyhedron3(const CGAL::Nef_polyhed for (const auto& tri : allTriangles) { polyset->indices.push_back({tri[0], tri[1], tri[2]}); } - polyset->isTriangular = true; + polyset->setTriangular(true); #if 0 // For debugging std::cerr.precision(20); diff --git a/src/geometry/manifold/ManifoldGeometry.cc b/src/geometry/manifold/ManifoldGeometry.cc index 702625ee02..537b40490c 100644 --- a/src/geometry/manifold/ManifoldGeometry.cc +++ b/src/geometry/manifold/ManifoldGeometry.cc @@ -94,7 +94,7 @@ std::string ManifoldGeometry::dump() const { std::shared_ptr ManifoldGeometry::toPolySet() const { manifold::MeshGL mesh = getManifold().GetMeshGL(); auto ps = std::make_shared(3); - ps->isTriangular = true; + ps->setTriangular(true); ps->vertices.reserve(mesh.NumVert()); ps->indices.reserve(mesh.NumTri()); ps->setConvexity(convexity); diff --git a/src/geometry/manifold/manifoldutils.cc b/src/geometry/manifold/manifoldutils.cc index dcb8370205..d38803fc9d 100644 --- a/src/geometry/manifold/manifoldutils.cc +++ b/src/geometry/manifold/manifoldutils.cc @@ -36,9 +36,9 @@ const char* statusToString(Error status) { std::shared_ptr trustedPolySetToManifold(const PolySet& ps) { manifold::Mesh mesh; std::unique_ptr buffer; - if (!ps.isTriangular) + if (!ps.isTriangular()) buffer = PolySetUtils::tessellate_faces(ps); - const PolySet& triangulated = ps.isTriangular ? ps : *buffer; + const PolySet& triangulated = ps.isTriangular() ? ps : *buffer; auto numfaces = triangulated.indices.size(); const auto &vertices = triangulated.vertices; diff --git a/src/io/export.cc b/src/io/export.cc index 8f73121219..88a1ce9c90 100644 --- a/src/io/export.cc +++ b/src/io/export.cc @@ -195,7 +195,9 @@ struct LexographicLess { std::unique_ptr createSortedPolySet(const PolySet& ps) { - auto out = PolySet::createEmpty(); + auto out = std::make_unique(ps.getDimension(), ps.convexValue()); + out->setTriangular(ps.isTriangular()); + out->setConvexity(ps.getConvexity()); std::map vertexMap; diff --git a/src/io/export_stl.cc b/src/io/export_stl.cc index c4b1f72638..4914f7431f 100644 --- a/src/io/export_stl.cc +++ b/src/io/export_stl.cc @@ -102,7 +102,7 @@ uint64_t append_stl(std::shared_ptr polyset, std::ostream& output static_assert(sizeof(float) == 4, "Need 32 bit float"); std::shared_ptr ps = polyset; - if (!ps->isTriangular) { + if (!ps->isTriangular()) { ps = PolySetUtils::tessellate_faces(*ps); } if (Feature::ExperimentalPredictibleOutput.is_enabled()) {