Skip to content

Commit

Permalink
Rename --render=cgal to --render=force to force-convert to the curren…
Browse files Browse the repository at this point in the history
…t backend-specific geometry (#4822)

* Renamed createMutableManifold*() to createManifold*(): No need to create mutable objects
  • Loading branch information
kintel committed Feb 28, 2024
1 parent c58718a commit 8bff31d
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 94 deletions.
47 changes: 46 additions & 1 deletion src/geometry/GeometryUtils.cc
Expand Up @@ -2,9 +2,16 @@
#include "ext/libtess2/Include/tesselator.h"
#include "printutils.h"
#include "Reindexer.h"
#include <unordered_map>
#include "Feature.h"
#include "manifoldutils.h"
#include "PolySet.h"
#ifdef ENABLE_CGAL
#include "cgalutils.h"
#include "CGALHybridPolyhedron.h"
#endif
#include <string>
#include <cmath>
#include <memory>

#include <boost/functional/hash.hpp>

Expand Down Expand Up @@ -498,3 +505,41 @@ Transform3d GeometryUtils::getResizeTransform(const BoundingBox &bbox, const Vec

return t;
}

// Return or force creation of backend-specific geometry.
// Will prefer Manifold if multiple backends are enabled.
// geom must be a 3D PolySet or the correct backend-specific geometry.
std::shared_ptr<const Geometry> GeometryUtils::getBackendSpecificGeometry(const std::shared_ptr<const Geometry>& geom)
{
#if ENABLE_MANIFOLD
if (Feature::ExperimentalManifold.is_enabled()) {
if (const auto ps = std::dynamic_pointer_cast<const PolySet>(geom)) {
return ManifoldUtils::createManifoldFromPolySet(*ps);
} else if (auto mani = std::dynamic_pointer_cast<const ManifoldGeometry>(geom)) {
return geom;
} else {
assert(false && "Unexpected geometry");
}
}
#endif
#if ENABLE_CGAL
if (Feature::ExperimentalFastCsg.is_enabled()) {
if (auto ps = std::dynamic_pointer_cast<const PolySet>(geom)) {
return CGALUtils::createHybridPolyhedronFromPolySet(*ps);
} else if (auto poly = std::dynamic_pointer_cast<const CGALHybridPolyhedron>(geom)) {
return geom;
} else {
assert(false && "Unexpected geometry");
}
} else {
if (auto ps = std::dynamic_pointer_cast<const PolySet>(geom)) {
return CGALUtils::createNefPolyhedronFromPolySet(*ps);
} else if (auto poly = std::dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom)) {
return geom;
} else {
assert(false && "Unexpected geometry");
}
}
#endif
return nullptr;
}
5 changes: 5 additions & 0 deletions src/geometry/GeometryUtils.h
@@ -1,8 +1,10 @@
#pragma once

#include "linalg.h"
#include "Geometry.h"
#include <vector>
#include <boost/container/small_vector.hpp>
#include <memory>

using Polygon = std::vector<Vector3d>;
using Polygons = std::vector<Polygon>;
Expand All @@ -29,6 +31,7 @@ struct IndexedPolyMesh {
};

namespace GeometryUtils {

bool tessellatePolygon(const Polygon& polygon,
Polygons& triangles,
const Vector3f *normal = nullptr);
Expand All @@ -41,4 +44,6 @@ int findUnconnectedEdges(const std::vector<std::vector<IndexedFace>>& polygons);
int findUnconnectedEdges(const std::vector<IndexedTriangle>& triangles);

Transform3d getResizeTransform(const BoundingBox &bbox, const Vector3d& newsize, const Eigen::Matrix<bool, 3, 1>& autosize);
std::shared_ptr<const Geometry> getBackendSpecificGeometry(const std::shared_ptr<const Geometry>& geom);

}
49 changes: 34 additions & 15 deletions src/geometry/manifold/ManifoldGeometry.cc
Expand Up @@ -160,41 +160,60 @@ std::shared_ptr<Polyhedron> ManifoldGeometry::toPolyhedron() const
template std::shared_ptr<CGAL::Polyhedron_3<CGAL_Kernel3>> ManifoldGeometry::toPolyhedron() const;
#endif

std::shared_ptr<manifold::Manifold> binOp(ManifoldGeometry& lhs, ManifoldGeometry& rhs, manifold::OpType opType) {
return std::make_shared<manifold::Manifold>(lhs.getManifold().Boolean(rhs.getManifold(), opType));
std::shared_ptr<manifold::Manifold> binOp(const manifold::Manifold& lhs, const manifold::Manifold& rhs, manifold::OpType opType) {
return std::make_shared<manifold::Manifold>(lhs.Boolean(rhs, opType));
}

ManifoldGeometry ManifoldGeometry::operator+(const ManifoldGeometry& other) const {
return {binOp(*this->manifold_, *other.manifold_, manifold::OpType::Add)};
}

void ManifoldGeometry::operator+=(ManifoldGeometry& other) {
manifold_ = binOp(*this, other, manifold::OpType::Add);
manifold_ = binOp(*this->manifold_, *other.manifold_, manifold::OpType::Add);
}

ManifoldGeometry ManifoldGeometry::operator*(const ManifoldGeometry& other) const {
return {binOp(*this->manifold_, *other.manifold_, manifold::OpType::Intersect)};
}

void ManifoldGeometry::operator*=(ManifoldGeometry& other) {
manifold_ = binOp(*this, other, manifold::OpType::Intersect);
manifold_ = binOp(*this->manifold_, *other.manifold_, manifold::OpType::Intersect);
}

ManifoldGeometry ManifoldGeometry::operator-(const ManifoldGeometry& other) const {
return {binOp(*this->manifold_, *other.manifold_, manifold::OpType::Subtract)};
}

void ManifoldGeometry::operator-=(ManifoldGeometry& other) {
manifold_ = binOp(*this, other, manifold::OpType::Subtract);
manifold_ = binOp(*this->manifold_, *other.manifold_, manifold::OpType::Subtract);
}

void ManifoldGeometry::minkowski(ManifoldGeometry& other) {
std::shared_ptr<manifold::Manifold> minkowskiOp(const ManifoldGeometry& lhs, const ManifoldGeometry& rhs) {
// FIXME: How to deal with operation not supported?
#ifdef ENABLE_CGAL
auto lhs = std::shared_ptr<CGAL_Nef_polyhedron>(CGALUtils::createNefPolyhedronFromPolySet(*this->toPolySet()));
auto rhs = std::shared_ptr<CGAL_Nef_polyhedron>(CGALUtils::createNefPolyhedronFromPolySet(*other.toPolySet()));
if (lhs->isEmpty() || rhs->isEmpty()) {
clear();
return;
auto lhs_nef = std::shared_ptr<CGAL_Nef_polyhedron>(CGALUtils::createNefPolyhedronFromPolySet(*lhs.toPolySet()));
auto rhs_nef = std::shared_ptr<CGAL_Nef_polyhedron>(CGALUtils::createNefPolyhedronFromPolySet(*rhs.toPolySet()));
if (lhs_nef->isEmpty() || rhs_nef->isEmpty()) {
return {};
}
lhs->minkowski(*rhs);
lhs_nef->minkowski(*rhs_nef);

auto ps = PolySetUtils::getGeometryAsPolySet(lhs);
if (!ps) clear();
auto ps = PolySetUtils::getGeometryAsPolySet(lhs_nef);
if (!ps) return {};
else {
manifold_ = ManifoldUtils::trustedPolySetToManifold(*ps);
return ManifoldUtils::trustedPolySetToManifold(*ps);
}
#endif
}

void ManifoldGeometry::minkowski(ManifoldGeometry& other) {
manifold_ = minkowskiOp(*this, other);
}

ManifoldGeometry ManifoldGeometry::minkowski(const ManifoldGeometry& other) const {
return {minkowskiOp(*this, other)};
}

void ManifoldGeometry::transform(const Transform3d& mat) {
glm::mat4x3 glMat(
// Column-major ordering
Expand Down
13 changes: 12 additions & 1 deletion src/geometry/manifold/ManifoldGeometry.h
Expand Up @@ -47,6 +47,17 @@ class ManifoldGeometry : public Geometry
void operator-=(ManifoldGeometry& other);
/*! In-place minkowksi operation. */
void minkowski(ManifoldGeometry& other);

/*! union. */
ManifoldGeometry operator+(const ManifoldGeometry& other) const;
/*! intersection. */
ManifoldGeometry operator*(const ManifoldGeometry& other) const;
/*! difference. */
ManifoldGeometry operator-(const ManifoldGeometry& other) const;
/*! minkowksi operation. */
ManifoldGeometry minkowski(const ManifoldGeometry& other) const;


void transform(const Transform3d& mat) override;
void resize(const Vector3d& newsize, const Eigen::Matrix<bool, 3, 1>& autosize) override;

Expand All @@ -56,5 +67,5 @@ class ManifoldGeometry : public Geometry
const manifold::Manifold& getManifold() const;

private:
std::shared_ptr<manifold::Manifold> manifold_;
std::shared_ptr<const manifold::Manifold> manifold_;
};
8 changes: 4 additions & 4 deletions src/geometry/manifold/manifold-applyops-minkowski.cc
Expand Up @@ -111,9 +111,9 @@ std::shared_ptr<const Geometry> applyMinkowskiManifold(const Geometry::Geometrie
std::vector<Hull_kernel::Point_3> minkowski_points;

minkowski_points.reserve(points0.size() * points1.size());
for (size_t i = 0; i < points0.size(); ++i) {
for (size_t j = 0; j < points1.size(); ++j) {
minkowski_points.push_back(points0[i] + (points1[j] - CGAL::ORIGIN));
for (const auto& p0 : points0) {
for (const auto p1 : points1) {
minkowski_points.push_back(p0 + (p1 - CGAL::ORIGIN));
}
}

Expand Down Expand Up @@ -175,7 +175,7 @@ std::shared_ptr<const Geometry> applyMinkowskiManifold(const Geometry::Geometrie
t.reset();

CGALUtils::triangulateFaces(mesh);
return ManifoldUtils::createMutableManifoldFromSurfaceMesh(mesh);
return ManifoldUtils::createManifoldFromSurfaceMesh(mesh);
};

std::vector<std::shared_ptr<const ManifoldGeometry>> result_parts(part_points[0].size() * part_points[1].size());
Expand Down
22 changes: 11 additions & 11 deletions src/geometry/manifold/manifold-applyops.cc
Expand Up @@ -22,52 +22,52 @@ Location getLocation(const std::shared_ptr<const AbstractNode>& node)
*/
std::shared_ptr<const ManifoldGeometry> applyOperator3DManifold(const Geometry::Geometries& children, OpenSCADOperator op)
{
auto N = std::make_shared<ManifoldGeometry>();
std::shared_ptr<ManifoldGeometry> geom;

bool foundFirst = false;

for (const auto& item : children) {
auto chN = item.second ? createMutableManifoldFromGeometry(item.second) : nullptr;
auto chN = item.second ? createManifoldFromGeometry(item.second) : nullptr;

// Intersecting something with nothing results in nothing
if (!chN || chN->isEmpty()) {
if (op == OpenSCADOperator::INTERSECTION) {
N = nullptr;
geom = nullptr;
break;
}
if (op == OpenSCADOperator::DIFFERENCE && !foundFirst) {
N = nullptr;
geom = nullptr;
break;
}
continue;
}

// Initialize N with first expected geometric object
// Initialize geom with first expected geometric object
if (!foundFirst) {
N = chN;
geom = std::make_shared<ManifoldGeometry>(*chN);
foundFirst = true;
continue;
}

switch (op) {
case OpenSCADOperator::UNION:
*N += *chN;
*geom = *geom + *chN;
break;
case OpenSCADOperator::INTERSECTION:
*N *= *chN;
*geom = *geom * *chN;
break;
case OpenSCADOperator::DIFFERENCE:
*N -= *chN;
*geom = *geom - *chN;
break;
case OpenSCADOperator::MINKOWSKI:
N->minkowski(*chN);
*geom = geom->minkowski(*chN);
break;
default:
LOG(message_group::Error, "Unsupported CGAL operator: %1$d", static_cast<int>(op));
}
if (item.first) item.first->progress_report();
}
return N;
return geom;
}

}; // namespace ManifoldUtils
Expand Down
21 changes: 9 additions & 12 deletions src/geometry/manifold/manifoldutils.cc
Expand Up @@ -66,7 +66,7 @@ std::shared_ptr<manifold::Manifold> trustedPolySetToManifold(const PolySet& ps)
}

template <class TriangleMesh>
std::shared_ptr<ManifoldGeometry> createMutableManifoldFromSurfaceMesh(const TriangleMesh& tm)
std::shared_ptr<const ManifoldGeometry> createManifoldFromSurfaceMesh(const TriangleMesh& tm)
{
typedef typename TriangleMesh::Vertex_index vertex_descriptor;

Expand Down Expand Up @@ -102,11 +102,11 @@ std::shared_ptr<ManifoldGeometry> createMutableManifoldFromSurfaceMesh(const Tri
}

#ifdef ENABLE_CGAL
template std::shared_ptr<ManifoldGeometry> createMutableManifoldFromSurfaceMesh(const CGAL::Surface_mesh<CGAL::Point_3<CGAL::Epick>> &tm);
template std::shared_ptr<ManifoldGeometry> createMutableManifoldFromSurfaceMesh(const CGAL_DoubleMesh &tm);
template std::shared_ptr<const ManifoldGeometry> createManifoldFromSurfaceMesh(const CGAL::Surface_mesh<CGAL::Point_3<CGAL::Epick>> &tm);
template std::shared_ptr<const ManifoldGeometry> createManifoldFromSurfaceMesh(const CGAL_DoubleMesh &tm);
#endif

std::shared_ptr<ManifoldGeometry> createMutableManifoldFromPolySet(const PolySet& ps)
std::shared_ptr<const ManifoldGeometry> createManifoldFromPolySet(const PolySet& ps)
{
#ifdef ENABLE_CGAL
PolySet psq(ps);
Expand Down Expand Up @@ -141,22 +141,19 @@ std::shared_ptr<ManifoldGeometry> createMutableManifoldFromPolySet(const PolySet
}
}

return createMutableManifoldFromSurfaceMesh(m);
return createManifoldFromSurfaceMesh(m);
#else
return std::make_shared<ManifoldGeometry>();
#endif
}

std::shared_ptr<ManifoldGeometry> createMutableManifoldFromGeometry(const std::shared_ptr<const Geometry>& geom) {
std::shared_ptr<const ManifoldGeometry> createManifoldFromGeometry(const std::shared_ptr<const Geometry>& geom) {
if (auto mani = std::dynamic_pointer_cast<const ManifoldGeometry>(geom)) {
return std::make_shared<ManifoldGeometry>(*mani);
return mani;
}

auto ps = PolySetUtils::getGeometryAsPolySet(geom);
if (ps) {
return createMutableManifoldFromPolySet(*ps);
if (auto ps = PolySetUtils::getGeometryAsPolySet(geom)) {
return createManifoldFromPolySet(*ps);
}

return nullptr;
}

Expand Down
8 changes: 4 additions & 4 deletions src/geometry/manifold/manifoldutils.h
Expand Up @@ -16,14 +16,14 @@ namespace ManifoldUtils {

const char* statusToString(manifold::Manifold::Error status);

/*! If the PolySet isn't trusted, use createMutableManifoldFromPolySet which will triangulate and reorient it. */
/*! If the PolySet isn't trusted, use createManifoldFromPolySet which will triangulate and reorient it. */
std::shared_ptr<manifold::Manifold> trustedPolySetToManifold(const PolySet& ps);

std::shared_ptr<ManifoldGeometry> createMutableManifoldFromPolySet(const PolySet& ps);
std::shared_ptr<ManifoldGeometry> createMutableManifoldFromGeometry(const std::shared_ptr<const Geometry>& geom);
std::shared_ptr<const ManifoldGeometry> createManifoldFromPolySet(const PolySet& ps);
std::shared_ptr<const ManifoldGeometry> createManifoldFromGeometry(const std::shared_ptr<const Geometry>& geom);

template <class TriangleMesh>
std::shared_ptr<ManifoldGeometry> createMutableManifoldFromSurfaceMesh(const TriangleMesh& mesh);
std::shared_ptr<const ManifoldGeometry> createManifoldFromSurfaceMesh(const TriangleMesh& mesh);

std::shared_ptr<const ManifoldGeometry> applyOperator3DManifold(const Geometry::Geometries& children, OpenSCADOperator op);

Expand Down
2 changes: 1 addition & 1 deletion src/io/export.h
Expand Up @@ -115,7 +115,7 @@ void export_nef3(const std::shared_ptr<const Geometry>& geom, std::ostream& outp


enum class Previewer { OPENCSG, THROWNTOGETHER };
enum class RenderType { GEOMETRY, CGAL, OPENCSG, THROWNTOGETHER };
enum class RenderType { GEOMETRY, BACKEND_SPECIFIC, OPENCSG, THROWNTOGETHER };

struct ExportFileFormatOptions {
const std::map<const std::string, FileFormat> exportFileFormats{
Expand Down

0 comments on commit 8bff31d

Please sign in to comment.