Skip to content

Commit

Permalink
Allow 2D objects in 3D hull and minkowski
Browse files Browse the repository at this point in the history
Allow 2D objects in 3D hull and minkowski operations by promoting the
2D object to a 3D object positioned on the XY plane.
  • Loading branch information
bneuen committed Dec 28, 2024
1 parent 5cb4ccf commit 114a05f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
30 changes: 22 additions & 8 deletions src/geometry/GeometryEvaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,13 @@ bool GeometryEvaluator::isValidDim(const Geometry::GeometryItem& item, unsigned

GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren(const AbstractNode& node, OpenSCADOperator op)
{
const bool allowMultiDim = (op == OpenSCADOperator::MINKOWSKI) || (op == OpenSCADOperator::HULL);
unsigned int dim = 0;
for (const auto& item : this->visitedchildren[node.index()]) {
if (!isValidDim(item, dim)) break;
unsigned int tmp = allowMultiDim ? 0 : dim;
if (!isValidDim(item, tmp))
break;
dim = (allowMultiDim && (dim > tmp)) ? dim : tmp;
}
if (dim == 2) return ResultObject::mutableResult(std::shared_ptr<Geometry>(applyToChildren2D(node, op)));
else if (dim == 3) return applyToChildren3D(node, op);
Expand All @@ -128,7 +132,8 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren(const Abstrac
*/
GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const AbstractNode& node, OpenSCADOperator op)
{
Geometry::Geometries children = collectChildren3D(node);
const bool promoteTo3d = (op == OpenSCADOperator::MINKOWSKI) || (op == OpenSCADOperator::HULL);
Geometry::Geometries children = collectChildren3D(node, promoteTo3d);
if (children.empty()) return {};

if (op == OpenSCADOperator::HULL) {
Expand Down Expand Up @@ -256,7 +261,7 @@ std::unique_ptr<Polygon2d> GeometryEvaluator::applyFill2D(const AbstractNode& no

std::unique_ptr<Geometry> GeometryEvaluator::applyHull3D(const AbstractNode& node)
{
Geometry::Geometries children = collectChildren3D(node);
Geometry::Geometries children = collectChildren3D(node, true);

auto P = PolySet::createEmpty();
return applyHull(children);
Expand Down Expand Up @@ -356,7 +361,7 @@ std::shared_ptr<const Geometry> GeometryEvaluator::smartCacheGet(const AbstractN
Returns a list of 3D Geometry children of the given node.
May return empty geometries, but not nullptr objects
*/
Geometry::Geometries GeometryEvaluator::collectChildren3D(const AbstractNode& node)
Geometry::Geometries GeometryEvaluator::collectChildren3D(const AbstractNode& node, const bool promoteTo3d)
{
Geometry::Geometries children;
for (const auto& item : this->visitedchildren[node.index()]) {
Expand All @@ -370,12 +375,21 @@ Geometry::Geometries GeometryEvaluator::collectChildren3D(const AbstractNode& no
// sibling object.
smartCacheInsert(*chnode, chgeom);

if (chgeom && chgeom->getDimension() == 2) {
LOG(message_group::Warning, item.first->modinst->location(), this->tree.getDocumentPath(), "Ignoring 2D child object for 3D operation");
children.push_back(std::make_pair(item.first, nullptr)); // replace 2D geometry with empty geometry
} else {
if (!chgeom || chgeom->getDimension() == 3) {
// Add children if geometry is 3D OR null/empty
children.push_back(item);
} else if (promoteTo3d) {
// Not 3D, so if promotion is allowed, then promote to 3D to add
LOG(message_group::Trace, item.first->modinst->location(), this->tree.getDocumentPath(), "Promoting %1$dD child object for 3D operation", chgeom->getDimension());
const Polygon2d *p = dynamic_cast<const Polygon2d *>(chgeom.get());
assert(p);
PolySetBuilder builder(0, 0, 3, p->is_convex());
builder.setConvexity(chgeom->getConvexity());
builder.appendPolySet(*p->tessellate());
children.push_back(std::make_pair(item.first, builder.build()));
} else {
LOG(message_group::Warning, item.first->modinst->location(), this->tree.getDocumentPath(), "Ignoring %1$dD child object for 3D operation", chgeom->getDimension());
children.push_back(std::make_pair(item.first, nullptr)); // replace 2D geometry with empty geometry
}
}
return children;
Expand Down
2 changes: 1 addition & 1 deletion src/geometry/GeometryEvaluator.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class GeometryEvaluator : public NodeVisitor
bool isSmartCached(const AbstractNode& node);
bool isValidDim(const Geometry::GeometryItem& item, unsigned int& dim) const;
std::vector<std::shared_ptr<const Polygon2d>> collectChildren2D(const AbstractNode& node);
Geometry::Geometries collectChildren3D(const AbstractNode& node);
Geometry::Geometries collectChildren3D(const AbstractNode& node, const bool promoteTo3d);
std::unique_ptr<Polygon2d> applyMinkowski2D(const AbstractNode& node);
std::unique_ptr<Polygon2d> applyHull2D(const AbstractNode& node);
std::unique_ptr<Polygon2d> applyFill2D(const AbstractNode& node);
Expand Down

0 comments on commit 114a05f

Please sign in to comment.