Skip to content

Commit

Permalink
PolySet Refactor: Remove Polygon2d features from PolySet (openscad#4933)
Browse files Browse the repository at this point in the history
* Render polygon outlines directly from Polygon2d instead of retaining polygon2d in a PolySet
* Remove polygon2d from PolySet
* Safer memory management of OpenCSGPrim
* Removed some unused code
  • Loading branch information
kintel authored Jan 20, 2024
1 parent d936fda commit f5d1bfa
Show file tree
Hide file tree
Showing 44 changed files with 760 additions and 999 deletions.
50 changes: 48 additions & 2 deletions src/core/CSGTreeEvaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
#include "printutils.h"
#include "GeometryEvaluator.h"
#include "PolySet.h"
#include "PolySetBuilder.h"

#include <string>
#include <map>
#include <list>
#include <cassert>
#include <cstddef>
#include <boost/range/adaptor/reversed.hpp>

/*!
\class CSGTreeEvaluator
Expand Down Expand Up @@ -168,16 +170,60 @@ Response CSGTreeEvaluator::visit(State& state, const class ListNode& node)

}

std::shared_ptr<const PolySet> polygon2dToPolySet(const Polygon2d &p2d) {
auto ps = p2d.tessellate();
// Estimating num vertices and polygons
PolySetBuilder builder(ps->vertices.size() * 2,
ps->indices.size() * 2 + ps->vertices.size(),
2, p2d.is_convex());
builder.setConvexity(p2d.getConvexity());

// Create bottom face.
for (const auto& poly : ps->indices) {
builder.appendPoly(poly.size());
// Flip vertex ordering for bottom polygon
for (const auto& ind: boost::adaptors::reverse(poly)) {
builder.appendVertex(ps->vertices[ind] - Vector3d(0, 0, 0.5));
}
}

// Create top face.
for (const auto& poly : ps->indices) {
builder.appendPoly(poly.size());
for (const auto& ind: poly) {
builder.appendVertex(ps->vertices[ind] + Vector3d(0, 0, 0.5));
}
}

// Create sides
for (const auto& o : p2d.outlines()) {
for (size_t i = 0; i < o.vertices.size(); ++i) {
const Vector2d &prev = o.vertices[i];
const Vector2d &curr = o.vertices[(i+1)%o.vertices.size()];
builder.appendPoly({
Vector3d(prev[0], prev[1], -0.5),
Vector3d(curr[0], curr[1], -0.5),
Vector3d(curr[0], curr[1], 0.5),
Vector3d(prev[0], prev[1], 0.5),
});
}
}

auto polyset = builder.build();
return polyset;
}


std::shared_ptr<CSGNode> CSGTreeEvaluator::evaluateCSGNodeFromGeometry(
State& state, const std::shared_ptr<const Geometry>& geom,
const ModuleInstantiation *modinst, const AbstractNode& node)
{
assert(geom);
// We cannot render Polygon2d directly, so we preprocess (tessellate) it here
// We cannot render Polygon2d directly, so we convert it to a PolySet here
std::shared_ptr<const PolySet> ps;
if (!geom->isEmpty()) {
if (auto p2d = std::dynamic_pointer_cast<const Polygon2d>(geom)) {
ps = p2d->tessellate();
ps = polygon2dToPolySet(*p2d);
}
// 3D PolySets are tessellated before inserting into Geometry cache, inside GeometryEvaluator::evaluateGeometry
else {
Expand Down
10 changes: 6 additions & 4 deletions src/core/Selection.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@
*/

#pragma once
#include <Eigen/Core>
#include <Eigen/Geometry>
#include "linalg.h"

enum { SELECTION_POINT, SELECTION_LINE};
enum class SelectionType {
SELECTION_POINT,
SELECTION_LINE
};

struct SelectedObject {
int type;
SelectionType type;
Vector3d p1;
Vector3d p2;
};
Expand Down
3 changes: 2 additions & 1 deletion src/core/SurfaceNode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ std::unique_ptr<const Geometry> SurfaceNode::createGeometry() const
double ox = center ? -(columns - 1) / 2.0 : 0;
double oy = center ? -(lines - 1) / 2.0 : 0;

PolySetBuilder builder(0, (lines - 1) * (columns - 1) * 4 + (lines - 1) * 2 + (columns - 1) * 2 + 1);
int num_indices = (lines - 1) * (columns - 1) * 4 + (lines - 1) * 2 + (columns - 1) * 2 + 1;
PolySetBuilder builder(0, num_indices);
builder.setConvexity(convexity);
// the bulk of the heightmap
for (int i = 1; i < lines; ++i)
Expand Down
4 changes: 0 additions & 4 deletions src/core/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ class AbstractNode : public BaseVisitable, public std::enable_shared_from_this<A
/*| When a more specific name for user interaction shall be used, such as module names,
the verbose name shall be overloaded. */
virtual std::string verbose_name() const { return this->name(); }
/*! Should return a Geometry instance describing the node. Returns nullptr if smth.
goes wrong. This is only called by PolySetEvaluator, to make sure polysets
are inserted into the cache*/
virtual class Geometry *evaluate_geometry(class PolySetEvaluator *) const { return nullptr; }

const std::vector<std::shared_ptr<AbstractNode>>& getChildren() const {
return this->children;
Expand Down
6 changes: 3 additions & 3 deletions src/core/primitives.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ std::unique_ptr<const Geometry> CubeNode::createGeometry() const
int cubeCorners=8;
int cubeFaces=6;
int dimension=3;
PolySetBuilder builder(cubeCorners,cubeFaces,dimension,true);
PolySetBuilder builder(cubeCorners, cubeFaces, dimension, true);
int corner[cubeCorners];
for(int i=0;i<cubeCorners;i++)
corner[i]=builder.vertexIndex(Vector3d(i&1?x2:x1,i&2?y2:y1,i&4?z2:z1));
Expand Down Expand Up @@ -196,7 +196,7 @@ std::unique_ptr<const Geometry> SphereNode::createGeometry() const

auto fragments = Calc::get_fragments_from_r(r, fn, fs, fa);
int rings = (fragments + 1) / 2;
PolySetBuilder builder(0,rings * fragments + 2,3,true);
PolySetBuilder builder(0, rings * fragments + 2, 3, true);
// Uncomment the following three lines to enable experimental sphere tessellation
// if (rings % 2 == 0) rings++; // To ensure that the middle ring is at phi == 0 degrees

Expand Down Expand Up @@ -307,7 +307,7 @@ std::unique_ptr<const Geometry> CylinderNode::createGeometry() const
generate_circle(circle1.data(), r1, fragments);
generate_circle(circle2.data(), r2, fragments);

PolySetBuilder builder(0,fragments * 2 + 2,3,true);
PolySetBuilder builder(0, fragments * 2 + 2, 3, true);

for (int i = 0; i < fragments; ++i) {
int j = (i + 1) % fragments;
Expand Down
8 changes: 6 additions & 2 deletions src/geometry/GeometryEvaluator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ GeometryEvaluator::GeometryEvaluator(const Tree& tree) : tree(tree) { }

/*!
Set allownef to false to force the result to _not_ be a Nef polyhedron
There are some guarantees on the returned geometry:
* 2D and 3D geometry cannot be mixed; we will return either _only_ 2D or _only_ 3D geometries
* PolySet geometries are always 3D. 2D Polysets are only created for special-purpose rendering operations downstream from here.
* Needs validation: Implementation-specific geometries shouldn't be mixed (Nef polyhedron, Manifold, CGAL Hybrid polyhedrons)
*/
std::shared_ptr<const Geometry> GeometryEvaluator::evaluateGeometry(const AbstractNode& node,
bool allownef)
Expand Down Expand Up @@ -1047,7 +1052,6 @@ static Outline2d splitOutlineByFn(
return o2;
}


/*!
Input to extrude should be sanitized. This means non-intersecting, correct winding order
etc., the input coming from a library like Clipper.
Expand All @@ -1058,7 +1062,7 @@ static std::unique_ptr<Geometry> extrudePolygon(const LinearExtrudeNode& node, c
boost::tribool isConvex{poly.is_convex()};
// Twist or non-uniform scale makes convex polygons into unknown polyhedrons
if (isConvex && non_linear) isConvex = unknown;
PolySetBuilder builder(0,0,3,isConvex);
PolySetBuilder builder(0, 0, 3, isConvex);
builder.setConvexity(node.convexity);
if (node.height <= 0) return std::make_unique<PolySet>(3);

Expand Down
8 changes: 0 additions & 8 deletions src/geometry/PolySet.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ PolySet::PolySet(unsigned int dim, boost::tribool convex) : dim(dim), convex(con
{
}

PolySet::PolySet(Polygon2d origin) : polygon(std::move(origin)), dim(2), convex(unknown), dirty(true)
{
}

std::unique_ptr<Geometry> PolySet::copy() const {
return std::make_unique<PolySet>(*this);
}
Expand All @@ -65,16 +61,13 @@ std::string PolySet::dump() const
<< "\n dimensions:" << this->dim
<< "\n convexity:" << this->convexity
<< "\n num polygons: " << indices.size()
<< "\n num outlines: " << polygon.outlines().size()
<< "\n polygons data:";
for (const auto& polygon : indices) {
out << "\n polygon begin:";
for (auto v : polygon) {
out << "\n vertex:" << this->vertices[v].transpose();
}
}
out << "\n outlines data:";
out << polygon.dump();
out << "\nPolySet end";
return out.str();
}
Expand All @@ -97,7 +90,6 @@ size_t PolySet::memsize() const
size_t mem = 0;
for (const auto& p : this->indices) mem += p.size() * sizeof(int);
for (const auto& p : this->vertices) mem += p.size() * sizeof(Vector3d);
mem += this->polygon.memsize() - sizeof(this->polygon);
mem += sizeof(PolySet);
return mem;
}
Expand Down
4 changes: 0 additions & 4 deletions src/geometry/PolySet.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ class PolySet : public Geometry
std::vector<Vector3d> vertices;

PolySet(unsigned int dim, boost::tribool convex = unknown);
PolySet(Polygon2d origin);

const Polygon2d& getPolygon() const { return polygon; }

size_t memsize() const override;
BoundingBox getBoundingBox() const override;
Expand All @@ -40,7 +37,6 @@ class PolySet : public Geometry
bool isTriangular = false;

private:
Polygon2d polygon;
unsigned int dim;
mutable boost::tribool convex;
mutable BoundingBox bbox;
Expand Down
17 changes: 3 additions & 14 deletions src/geometry/PolySetBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,12 @@
#endif

PolySetBuilder::PolySetBuilder(int vertices_count, int indices_count, int dim, boost::tribool convex)
: dim_(dim), convex_(convex)
: convex_(convex), dim_(dim)
{
if (vertices_count != 0) vertices_.reserve(vertices_count);
if (indices_count != 0) indices_.reserve(indices_count);
}

PolySetBuilder::PolySetBuilder(const Polygon2d& polygon2d)
: polygon2d_(polygon2d), dim_(2), convex_(unknown)
{
}


void PolySetBuilder::setConvexity(int convexity){
convexity_ = convexity;
}
Expand Down Expand Up @@ -94,7 +88,7 @@ void PolySetBuilder::appendGeometry(const std::shared_ptr<const Geometry>& geom)
append(*mani->toPolySet());
#endif
} else if (std::dynamic_pointer_cast<const Polygon2d>(geom)) { // NOLINT(bugprone-branch-clone)
assert(false && "Unsupported file format");
assert(false && "Unsupported geometry");
} else { // NOLINT(bugprone-branch-clone)
assert(false && "Not implemented");
}
Expand Down Expand Up @@ -148,12 +142,7 @@ void PolySetBuilder::append(const PolySet& ps)
std::unique_ptr<PolySet> PolySetBuilder::build()
{
std::unique_ptr<PolySet> polyset;
if (!polygon2d_.isEmpty()) {
polyset = std::make_unique<PolySet>(polygon2d_);
}
else {
polyset = std::make_unique<PolySet>(dim_, convex_);
}
polyset = std::make_unique<PolySet>(dim_, convex_);
vertices_.copy(std::back_inserter(polyset->vertices));
polyset->indices = std::move(indices_);
polyset->setConvexity(convexity_);
Expand Down
2 changes: 0 additions & 2 deletions src/geometry/PolySetBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class PolySetBuilder
{
public:
PolySetBuilder(int vertices_count = 0, int indices_count = 0, int dim = 3, boost::tribool convex = unknown);
PolySetBuilder(const Polygon2d& polygon2d);
void setConvexity(int n);
int vertexIndex(const Vector3d& coord);
int numVertices() const;
Expand All @@ -30,7 +29,6 @@ class PolySetBuilder
private:
Reindexer<Vector3d> vertices_;
PolygonIndices indices_;
Polygon2d polygon2d_;
int convexity_{1};
int dim_;
boost::tribool convex_;
Expand Down
4 changes: 2 additions & 2 deletions src/geometry/cgal/Polygon2d-CGAL.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ mark_domains(CDT& cdt)

/*!
Triangulates this polygon2d and returns a 2D-in-3D PolySet.
*/
*/
std::unique_ptr<PolySet> Polygon2d::tessellate() const
{
PRINTDB("Polygon2d::tessellate(): %d outlines", this->outlines().size());
PolySetBuilder builder(*this);
PolySetBuilder builder(0, 0, 2, unknown);

Polygon2DCGAL::CDT cdt; // Uses a constrained Delaunay triangulator.

Expand Down
2 changes: 1 addition & 1 deletion src/geometry/cgal/cgalutils-mesh.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ template bool createMeshFromPolySet(const PolySet& ps, CGAL_DoubleMesh& mesh);
template <class TriangleMesh>
std::unique_ptr<PolySet> createPolySetFromMesh(const TriangleMesh& mesh)
{
PolySetBuilder builder(0,mesh.number_of_faces()+ mesh.number_of_faces());
PolySetBuilder builder(0, mesh.number_of_faces()+ mesh.number_of_faces());
for (const auto& f : mesh.faces()) {
builder.appendPoly(mesh.degree(f));

Expand Down
2 changes: 1 addition & 1 deletion src/geometry/cgal/cgalutils-polyhedron.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ std::unique_ptr<PolySet> createPolySetFromPolyhedron(const Polyhedron& p)
using FCI = typename Polyhedron::Facet_const_iterator;
using HFCC = typename Polyhedron::Halfedge_around_facet_const_circulator;

PolySetBuilder builder(0,p.size_of_facets());
PolySetBuilder builder(0, p.size_of_facets());

for (FCI fi = p.facets_begin(); fi != p.facets_end(); ++fi) {
HFCC hc = fi->facet_begin();
Expand Down
2 changes: 1 addition & 1 deletion src/geometry/cgal/cgalutils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ std::unique_ptr<PolySet> createPolySetFromNefPolyhedron3(const CGAL::Nef_polyhed
LOG(message_group::Error, "Non-manifold mesh created: %1$d unconnected edges", unconnected2);
}

PolySetBuilder builder(verts.size(),allTriangles.size());
PolySetBuilder builder(verts.size(), allTriangles.size());
std::vector<int> indMap;
indMap.reserve(verts.size());
for (const auto &v : verts) {
Expand Down
4 changes: 2 additions & 2 deletions src/glview/GLView.cc
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ void GLView::showObject(const SelectedObject &obj, const Vector3d &eyedir)
{
auto vd = cam.zoomValue()/200.0;
switch(obj.type) {
case SELECTION_POINT:
case SelectionType::SELECTION_POINT:
{
double n=1/sqrt(3);
// create an octaeder
Expand All @@ -421,7 +421,7 @@ void GLView::showObject(const SelectedObject &obj, const Vector3d &eyedir)
glEnd();
}
break;
case SELECTION_LINE:
case SelectionType::SELECTION_LINE:
{
Vector3d diff=obj.p2-obj.p1;
Vector3d wdir=eyedir.cross(diff).normalized()*vd/2.0;
Expand Down
Loading

0 comments on commit f5d1bfa

Please sign in to comment.