diff --git a/openscad.pro b/openscad.pro index 913a5d3d..5ac92f81 100644 --- a/openscad.pro +++ b/openscad.pro @@ -233,6 +233,8 @@ HEADERS += src/typedefs.h \ src/rendernode.h \ src/openscad.h \ src/handle_dep.h \ + src/Geometry.h \ + src/Polygon2d.h \ src/polyset.h \ src/printutils.h \ src/fileutils.h \ @@ -245,7 +247,7 @@ HEADERS += src/typedefs.h \ src/nodecache.h \ src/nodedumper.h \ src/ModuleCache.h \ - src/PolySetCache.h \ + src/GeometryCache.h \ src/PolySetEvaluator.h \ src/CSGTermEvaluator.h \ src/Tree.h \ @@ -286,6 +288,8 @@ SOURCES += src/version_check.cc \ src/evalcontext.cc \ src/csgterm.cc \ src/csgtermnormalizer.cc \ + src/Geometry.cc \ + src/Polygon2d.cc \ src/polyset.cc \ src/csgops.cc \ src/transform.cc \ @@ -312,7 +316,7 @@ SOURCES += src/version_check.cc \ src/traverser.cc \ src/PolySetEvaluator.cc \ src/ModuleCache.cc \ - src/PolySetCache.cc \ + src/GeometryCache.cc \ src/Tree.cc \ \ src/rendersettings.cc \ diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index 37d4fd8c..d5f9b3f1 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -353,12 +353,14 @@ Response CGALEvaluator::visit(State &state, const AbstractPolyNode &node) CGAL_Nef_polyhedron N; if (!isCached(node)) { // Apply polyset operation - shared_ptr ps = this->psevaluator.getPolySet(node, false); + shared_ptr geom = this->psevaluator.getGeometry(node, false); + shared_ptr ps = dynamic_pointer_cast(geom); if (ps) { N = evaluateCGALMesh(*ps); // print_messages_pop(); node.progress_report(); } + // else FIXME: Support other Geometry instances } else { N = CGALCache::instance()->get(this->tree.getIdString(node)); diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc index 647a3dc8..7e4abbb8 100644 --- a/src/CSGTermEvaluator.cc +++ b/src/CSGTermEvaluator.cc @@ -10,6 +10,7 @@ #include "cgaladvnode.h" #include "printutils.h" #include "PolySetEvaluator.h" +#include "polyset.h" #include #include @@ -111,8 +112,12 @@ Response CSGTermEvaluator::visit(State &state, const AbstractPolyNode &node) if (state.isPrefix()) { shared_ptr t1; if (this->psevaluator) { - shared_ptr ps = this->psevaluator->getPolySet(node, true); - if (ps) { + shared_ptr geom = this->psevaluator->getGeometry(node, true); + if (geom) { + shared_ptr ps = dynamic_pointer_cast(geom); + if (!ps) { + // FIXME: Convert geom to polyset. Refacting may resume here + } t1 = evaluate_csg_term_from_ps(state, this->highlights, this->background, ps, node.modinst, node); node.progress_report(); @@ -178,7 +183,8 @@ Response CSGTermEvaluator::visit(State &state, const RenderNode &node) shared_ptr t1; shared_ptr ps; if (this->psevaluator) { - ps = this->psevaluator->getPolySet(node, true); + shared_ptr geom = this->psevaluator->getGeometry(node, true); + ps = dynamic_pointer_cast(geom); node.progress_report(); } if (ps) { @@ -198,7 +204,8 @@ Response CSGTermEvaluator::visit(State &state, const CgaladvNode &node) // FIXME: Calling evaluator directly since we're not a PolyNode. Generalize this. shared_ptr ps; if (this->psevaluator) { - ps = this->psevaluator->getPolySet(node, true); + shared_ptr geom = this->psevaluator->getGeometry(node, true); + ps = dynamic_pointer_cast(geom); } if (ps) { t1 = evaluate_csg_term_from_ps(state, this->highlights, this->background, diff --git a/src/Geometry.cc b/src/Geometry.cc new file mode 100644 index 00000000..e7f7f604 --- /dev/null +++ b/src/Geometry.cc @@ -0,0 +1 @@ +#include "Geometry.h" diff --git a/src/Geometry.h b/src/Geometry.h new file mode 100644 index 00000000..424a7159 --- /dev/null +++ b/src/Geometry.h @@ -0,0 +1,16 @@ +#ifndef GEOMETRY_H_ +#define GEOMETRY_H_ + +#include +#include +#include "linalg.h" + +class Geometry +{ +public: + virtual size_t memsize() const = 0; + virtual BoundingBox getBoundingBox() const = 0; + virtual std::string dump() const = 0; +}; + +#endif diff --git a/src/GeometryCache.cc b/src/GeometryCache.cc new file mode 100644 index 00000000..6be82d88 --- /dev/null +++ b/src/GeometryCache.cc @@ -0,0 +1,31 @@ +#include "GeometryCache.h" +#include "printutils.h" +#include "geometry.h" + +GeometryCache *GeometryCache::inst = NULL; + +void GeometryCache::insert(const std::string &id, const shared_ptr &ps) +{ + this->cache.insert(id, new cache_entry(ps), ps ? ps->memsize() : 0); +} + +size_t GeometryCache::maxSize() const +{ + return this->cache.maxCost(); +} + +void GeometryCache::setMaxSize(size_t limit) +{ + this->cache.setMaxCost(limit); +} + +void GeometryCache::print() +{ + PRINTB("Geometrys in cache: %d", this->cache.size()); + PRINTB("Geometry cache size in bytes: %d", this->cache.totalCost()); +} + +GeometryCache::cache_entry::cache_entry(const shared_ptr &ps) : ps(ps) +{ + if (print_messages_stack.size() > 0) this->msg = print_messages_stack.back(); +} diff --git a/src/GeometryCache.h b/src/GeometryCache.h new file mode 100644 index 00000000..f6dd7b97 --- /dev/null +++ b/src/GeometryCache.h @@ -0,0 +1,36 @@ +#ifndef GEOMETRYCACHE_H_ +#define GEOMETRYCACHE_H_ + +#include "cache.h" +#include "memory.h" +#include "Geometry.h" + +class GeometryCache +{ +public: + GeometryCache(size_t memorylimit = 100*1024*1024) : cache(memorylimit) {} + + static GeometryCache *instance() { if (!inst) inst = new GeometryCache; return inst; } + + bool contains(const std::string &id) const { return this->cache.contains(id); } + shared_ptr get(const std::string &id) const { return this->cache[id]->ps; } + void insert(const std::string &id, const shared_ptr &ps); + size_t maxSize() const; + void setMaxSize(size_t limit); + void clear() { cache.clear(); } + void print(); + +private: + static GeometryCache *inst; + + struct cache_entry { + shared_ptr ps; + std::string msg; + cache_entry(const shared_ptr &ps); + ~cache_entry() { } + }; + + Cache cache; +}; + +#endif diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index 0b57de16..21a15ec4 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -14,6 +14,7 @@ #include "dxftess.h" #include "module.h" #include "calc.h" +#include "polyset.h" #include "svg.h" #include "printutils.h" @@ -25,7 +26,7 @@ PolySetCGALEvaluator::PolySetCGALEvaluator(CGALEvaluator &cgalevaluator) { } -PolySet *PolySetCGALEvaluator::evaluatePolySet(const ProjectionNode &node) +Geometry *PolySetCGALEvaluator::evaluateGeometry(const ProjectionNode &node) { //openscad_loglevel = 6; logstream log(5); @@ -286,14 +287,14 @@ static void add_slice(PolySet *ps, const DxfData &dxf, DxfData::Path &path, } } -PolySet *PolySetCGALEvaluator::evaluatePolySet(const LinearExtrudeNode &node) +Geometry *PolySetCGALEvaluator::evaluateGeometry(const LinearExtrudeNode &node) { DxfData *dxf; if (node.filename.empty()) { // Before extruding, union all (2D) children nodes - // to a single DxfData, then tesselate this into a PolySet + // to a single DxfData, then tesselate this into a Geometry CGAL_Nef_polyhedron sum; BOOST_FOREACH (AbstractNode * v, node.getChildren()) { if (v->modinst->isBackground()) continue; @@ -315,12 +316,12 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const LinearExtrudeNode &node) dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale_x); } - PolySet *ps = extrudeDxfData(node, *dxf); + Geometry *geom = extrudeDxfData(node, *dxf); delete dxf; - return ps; + return geom; } -PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, DxfData &dxf) +Geometry *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, DxfData &dxf) { PolySet *ps = new PolySet(); ps->convexity = node.convexity; @@ -386,7 +387,7 @@ PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, Dxf return ps; } -PolySet *PolySetCGALEvaluator::evaluatePolySet(const RotateExtrudeNode &node) +Geometry *PolySetCGALEvaluator::evaluateGeometry(const RotateExtrudeNode &node) { DxfData *dxf; @@ -415,12 +416,12 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const RotateExtrudeNode &node) dxf = new DxfData(node.fn, node.fs, node.fa, node.filename, node.layername, node.origin_x, node.origin_y, node.scale); } - PolySet *ps = rotateDxfData(node, *dxf); + Geometry *geom = rotateDxfData(node, *dxf); delete dxf; - return ps; + return geom; } -PolySet *PolySetCGALEvaluator::evaluatePolySet(const CgaladvNode &node) +Geometry *PolySetCGALEvaluator::evaluateGeometry(const CgaladvNode &node) { CGAL_Nef_polyhedron N = this->cgalevaluator.evaluateCGALMesh(node); PolySet *ps = NULL; @@ -432,7 +433,7 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const CgaladvNode &node) return ps; } -PolySet *PolySetCGALEvaluator::evaluatePolySet(const RenderNode &node) +Geometry *PolySetCGALEvaluator::evaluateGeometry(const RenderNode &node) { CGAL_Nef_polyhedron N = this->cgalevaluator.evaluateCGALMesh(node); PolySet *ps = NULL; @@ -448,7 +449,7 @@ PolySet *PolySetCGALEvaluator::evaluatePolySet(const RenderNode &node) return ps; } -PolySet *PolySetCGALEvaluator::rotateDxfData(const RotateExtrudeNode &node, DxfData &dxf) +Geometry *PolySetCGALEvaluator::rotateDxfData(const RotateExtrudeNode &node, DxfData &dxf) { PolySet *ps = new PolySet(); ps->convexity = node.convexity; diff --git a/src/PolySetCGALEvaluator.h b/src/PolySetCGALEvaluator.h index 00e79f16..9673981c 100644 --- a/src/PolySetCGALEvaluator.h +++ b/src/PolySetCGALEvaluator.h @@ -4,23 +4,23 @@ #include "PolySetEvaluator.h" /*! - This is a PolySet evaluator which uses the CGALEvaluator to support building - polysets. + This is a Geometry evaluator which uses the CGALEvaluator to support building + geometrys. */ class PolySetCGALEvaluator : public PolySetEvaluator { public: PolySetCGALEvaluator(class CGALEvaluator &cgalevaluator); virtual ~PolySetCGALEvaluator() { } - virtual PolySet *evaluatePolySet(const ProjectionNode &node); - virtual PolySet *evaluatePolySet(const LinearExtrudeNode &node); - virtual PolySet *evaluatePolySet(const RotateExtrudeNode &node); - virtual PolySet *evaluatePolySet(const CgaladvNode &node); - virtual PolySet *evaluatePolySet(const RenderNode &node); + virtual Geometry *evaluateGeometry(const ProjectionNode &node); + virtual Geometry *evaluateGeometry(const LinearExtrudeNode &node); + virtual Geometry *evaluateGeometry(const RotateExtrudeNode &node); + virtual Geometry *evaluateGeometry(const CgaladvNode &node); + virtual Geometry *evaluateGeometry(const RenderNode &node); bool debug; protected: - PolySet *extrudeDxfData(const LinearExtrudeNode &node, class DxfData &dxf); - PolySet *rotateDxfData(const RotateExtrudeNode &node, class DxfData &dxf); + Geometry *extrudeDxfData(const LinearExtrudeNode &node, class DxfData &dxf); + Geometry *rotateDxfData(const RotateExtrudeNode &node, class DxfData &dxf); CGALEvaluator &cgalevaluator; }; diff --git a/src/PolySetCache.cc b/src/PolySetCache.cc deleted file mode 100644 index 04f41272..00000000 --- a/src/PolySetCache.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include "PolySetCache.h" -#include "printutils.h" -#include "polyset.h" - -PolySetCache *PolySetCache::inst = NULL; - -void PolySetCache::insert(const std::string &id, const shared_ptr &ps) -{ - this->cache.insert(id, new cache_entry(ps), ps ? ps->memsize() : 0); -} - -size_t PolySetCache::maxSize() const -{ - return this->cache.maxCost(); -} - -void PolySetCache::setMaxSize(size_t limit) -{ - this->cache.setMaxCost(limit); -} - -void PolySetCache::print() -{ - PRINTB("PolySets in cache: %d", this->cache.size()); - PRINTB("PolySet cache size in bytes: %d", this->cache.totalCost()); -} - -PolySetCache::cache_entry::cache_entry(const shared_ptr &ps) : ps(ps) -{ - if (print_messages_stack.size() > 0) this->msg = print_messages_stack.back(); -} diff --git a/src/PolySetCache.h b/src/PolySetCache.h deleted file mode 100644 index d69f2e28..00000000 --- a/src/PolySetCache.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef POLYSETCACHE_H_ -#define POLYSETCACHE_H_ - -#include "cache.h" -#include "memory.h" - -class PolySetCache -{ -public: - PolySetCache(size_t memorylimit = 100*1024*1024) : cache(memorylimit) {} - - static PolySetCache *instance() { if (!inst) inst = new PolySetCache; return inst; } - - bool contains(const std::string &id) const { return this->cache.contains(id); } - shared_ptr get(const std::string &id) const { return this->cache[id]->ps; } - void insert(const std::string &id, const shared_ptr &ps); - size_t maxSize() const; - void setMaxSize(size_t limit); - void clear() { cache.clear(); } - void print(); - -private: - static PolySetCache *inst; - - struct cache_entry { - shared_ptr ps; - std::string msg; - cache_entry(const shared_ptr &ps); - ~cache_entry() { } - }; - - Cache cache; -}; - -#endif diff --git a/src/PolySetEvaluator.cc b/src/PolySetEvaluator.cc index e8a2c0c8..80b27a89 100644 --- a/src/PolySetEvaluator.cc +++ b/src/PolySetEvaluator.cc @@ -1,35 +1,35 @@ -#include "PolySetCache.h" +#include "GeometryCache.h" #include "PolySetEvaluator.h" #include "printutils.h" #include "polyset.h" #include "Tree.h" /*! - The task of PolySetEvaluator is to create, keep track of and cache PolySet instances. + The task of PolySetEvaluator is to create, keep track of and cache Geometry instances. - All instances of PolySet which are not strictly temporary should be + All instances of Geometry which are not strictly temporary should be requested through this class. */ /*! - Factory method returning a PolySet from the given node. If the - node is already cached, the cached PolySet will be returned - otherwise a new PolySet will be created from the node. If cache is - true, the newly created PolySet will be cached. + Factory method returning a Geometry from the given node. If the + node is already cached, the cached Geometry will be returned + otherwise a new Geometry will be created from the node. If cache is + true, the newly created Geometry will be cached. */ -shared_ptr PolySetEvaluator::getPolySet(const AbstractNode &node, bool cache) +shared_ptr PolySetEvaluator::getGeometry(const AbstractNode &node, bool cache) { std::string cacheid = this->tree.getIdString(node); - if (PolySetCache::instance()->contains(cacheid)) { + if (GeometryCache::instance()->contains(cacheid)) { #ifdef DEBUG // For cache debugging - PRINTB("PolySetCache hit: %s", cacheid.substr(0, 40)); + PRINTB("GeometryCache hit: %s", cacheid.substr(0, 40)); #endif - return PolySetCache::instance()->get(cacheid); + return GeometryCache::instance()->get(cacheid); } - shared_ptr ps(node.evaluate_polyset(this)); - if (cache) PolySetCache::instance()->insert(cacheid, ps); - return ps; + shared_ptr geom(node.evaluate_geometry(this)); + if (cache) GeometryCache::instance()->insert(cacheid, geom); + return geom; } diff --git a/src/PolySetEvaluator.h b/src/PolySetEvaluator.h index 348cbba7..702755ba 100644 --- a/src/PolySetEvaluator.h +++ b/src/PolySetEvaluator.h @@ -11,13 +11,13 @@ public: const Tree &getTree() const { return this->tree; } - virtual shared_ptr getPolySet(const class AbstractNode &, bool cache); + virtual shared_ptr getGeometry(const class AbstractNode &, bool cache); - virtual PolySet *evaluatePolySet(const class ProjectionNode &) { return NULL; } - virtual PolySet *evaluatePolySet(const class LinearExtrudeNode &) { return NULL; } - virtual PolySet *evaluatePolySet(const class RotateExtrudeNode &) { return NULL; } - virtual PolySet *evaluatePolySet(const class CgaladvNode &) { return NULL; } - virtual PolySet *evaluatePolySet(const class RenderNode &) { return NULL; } + virtual Geometry *evaluateGeometry(const class ProjectionNode &) { return NULL; } + virtual Geometry *evaluateGeometry(const class LinearExtrudeNode &) { return NULL; } + virtual Geometry *evaluateGeometry(const class RotateExtrudeNode &) { return NULL; } + virtual Geometry *evaluateGeometry(const class CgaladvNode &) { return NULL; } + virtual Geometry *evaluateGeometry(const class RenderNode &) { return NULL; } private: const Tree &tree; diff --git a/src/Polygon2d.cc b/src/Polygon2d.cc new file mode 100644 index 00000000..7915f110 --- /dev/null +++ b/src/Polygon2d.cc @@ -0,0 +1,60 @@ +#include "Polygon2d.h" +#include + +size_t Polygon2d::memsize() const +{ + size_t mem = 0; + BOOST_FOREACH(const Outline2d &o, this->outlines) { + mem += o.size() * sizeof(Vector2d) + sizeof(Outline2d); + } + mem += sizeof(Polygon2d); + return mem; +} + +BoundingBox Polygon2d::getBoundingBox() const +{ + BoundingBox bbox; + BOOST_FOREACH(const Outline2d &o, this->outlines) { + BOOST_FOREACH(const Vector2d &v, o) { + bbox.extend(Vector3d(v[0], v[1], 0)); + } + } + return bbox; +} + +std::string Polygon2d::dump() const +{ + std::stringstream out; + out << "Polygon2d:"; +//FIXME: Implement +/* + << "\n convexity:" << this->convexity + << "\n num polygons: " << polygons.size() + << "\n num borders: " << borders.size() + << "\n polygons data:"; + for (size_t i = 0; i < polygons.size(); i++) { + out << "\n polygon begin:"; + const Polygon *poly = &polygons[i]; + for (size_t j = 0; j < poly->size(); j++) { + Vector3d v = poly->at(j); + out << "\n vertex:" << v.transpose(); + } + } + out << "\n borders data:"; + for (size_t i = 0; i < borders.size(); i++) { + out << "\n border polygon begin:"; + const Polygon *poly = &borders[i]; + for (size_t j = 0; j < poly->size(); j++) { + Vector3d v = poly->at(j); + out << "\n vertex:" << v.transpose(); + } + } + out << "\nPolySet end"; +*/ + return out.str(); +} + +// PolySet *Polygon2d::tessellate() +// { +// return NULL; +// } diff --git a/src/Polygon2d.h b/src/Polygon2d.h new file mode 100644 index 00000000..46542900 --- /dev/null +++ b/src/Polygon2d.h @@ -0,0 +1,23 @@ +#ifndef POLYGON2D_H_ +#define POLYGON2D_H_ + +#include "Geometry.h" +#include "linalg.h" +#include + +typedef std::vector Outline2d; + +class Polygon2d : public Geometry +{ +public: + virtual size_t memsize() const; + virtual BoundingBox getBoundingBox() const; + virtual std::string dump() const; + + void addOutline(const Outline2d &outline); +// class PolySet *tessellate(); +private: + std::vector outlines; +}; + +#endif diff --git a/src/Preferences.cc b/src/Preferences.cc index 92f11c7d..421e778b 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -31,7 +31,7 @@ #include #include #include -#include "PolySetCache.h" +#include "GeometryCache.h" #include "AutoUpdater.h" #include "feature.h" #ifdef ENABLE_CGAL @@ -84,7 +84,7 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) this->defaultmap["3dview/colorscheme"] = this->colorSchemeChooser->currentItem()->text(); this->defaultmap["advanced/opencsg_show_warning"] = true; this->defaultmap["advanced/enable_opencsg_opengl1x"] = true; - this->defaultmap["advanced/polysetCacheSize"] = uint(PolySetCache::instance()->maxSize()); + this->defaultmap["advanced/polysetCacheSize"] = uint(GeometryCache::instance()->maxSize()); #ifdef ENABLE_CGAL this->defaultmap["advanced/cgalCacheSize"] = uint(CGALCache::instance()->maxSize()); #endif @@ -348,7 +348,7 @@ void Preferences::on_polysetCacheSizeEdit_textChanged(const QString &text) { QSettings settings; settings.setValue("advanced/polysetCacheSize", text); - PolySetCache::instance()->setMaxSize(text.toULong()); + GeometryCache::instance()->setMaxSize(text.toULong()); } void Preferences::on_opencsgLimitEdit_textChanged(const QString &text) diff --git a/src/cgaladv.cc b/src/cgaladv.cc index 8fd030ac..43e60f82 100644 --- a/src/cgaladv.cc +++ b/src/cgaladv.cc @@ -29,6 +29,7 @@ #include "evalcontext.h" #include "builtin.h" #include "PolySetEvaluator.h" +#include "polyset.h" #include #include #include @@ -116,9 +117,9 @@ AbstractNode *CgaladvModule::instantiate(const Context *ctx, const ModuleInstant return node; } -PolySet *CgaladvNode::evaluate_polyset(PolySetEvaluator *ps) const +Geometry *CgaladvNode::evaluate_geometry(PolySetEvaluator *ps) const { - return ps->evaluatePolySet(*this); + return ps->evaluateGeometry(*this); } std::string CgaladvNode::name() const diff --git a/src/cgaladvnode.h b/src/cgaladvnode.h index d3aa5252..f3b4db97 100644 --- a/src/cgaladvnode.h +++ b/src/cgaladvnode.h @@ -26,7 +26,7 @@ public: } virtual std::string toString() const; virtual std::string name() const; - PolySet *evaluate_polyset(class PolySetEvaluator *ps) const; + Geometry *evaluate_geometry(class PolySetEvaluator *ps) const; Value path; std::string subdiv_type; diff --git a/src/import.cc b/src/import.cc index 3c2cce11..786f3fae 100644 --- a/src/import.cc +++ b/src/import.cc @@ -182,7 +182,7 @@ void read_stl_facet( std::ifstream &f, stl_facet &facet ) #endif } -PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const +Geometry *ImportNode::evaluate_geometry(class PolySetEvaluator *) const { PolySet *p = NULL; diff --git a/src/importnode.h b/src/importnode.h index bcb229f9..0f85ce4d 100644 --- a/src/importnode.h +++ b/src/importnode.h @@ -28,7 +28,7 @@ public: int convexity; double fn, fs, fa; double origin_x, origin_y, scale; - virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; + virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const; }; #endif diff --git a/src/linearextrude.cc b/src/linearextrude.cc index 1812504a..e1f9ec78 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -127,7 +127,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI return node; } -class PolySet *LinearExtrudeNode::evaluate_polyset(PolySetEvaluator *evaluator) const +class Geometry *LinearExtrudeNode::evaluate_geometry(PolySetEvaluator *evaluator) const { if (!evaluator) { PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name()); @@ -136,7 +136,7 @@ class PolySet *LinearExtrudeNode::evaluate_polyset(PolySetEvaluator *evaluator) print_messages_push(); - PolySet *ps = evaluator->evaluatePolySet(*this); + Geometry *ps = evaluator->evaluateGeometry(*this); print_messages_pop(); diff --git a/src/linearextrudenode.h b/src/linearextrudenode.h index 6ff8c56b..5f5f5c03 100644 --- a/src/linearextrudenode.h +++ b/src/linearextrudenode.h @@ -27,7 +27,7 @@ public: bool center, has_twist; Filename filename; std::string layername; - virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; + virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const; }; #endif diff --git a/src/mainwin.cc b/src/mainwin.cc index c2a7b7e1..13ce4ef6 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -24,7 +24,7 @@ * */ -#include "PolySetCache.h" +#include "GeometryCache.h" #include "ModuleCache.h" #include "MainWindow.h" #include "parsersettings.h" @@ -81,7 +81,6 @@ #include #include #include -#include #include #ifdef ENABLE_CGAL @@ -436,7 +435,7 @@ MainWindow::loadDesignSettings() designActionAutoReload->setChecked(true); } uint polySetCacheSize = Preferences::inst()->getValue("advanced/polysetCacheSize").toUInt(); - PolySetCache::instance()->setMaxSize(polySetCacheSize); + GeometryCache::instance()->setMaxSize(polySetCacheSize); #ifdef ENABLE_CGAL uint cgalCacheSize = Preferences::inst()->getValue("advanced/cgalCacheSize").toUInt(); CGALCache::instance()->setMaxSize(cgalCacheSize); @@ -803,7 +802,7 @@ void MainWindow::compileCSG(bool procevents) if (!root_raw_term) { PRINT("ERROR: CSG generation failed! (no top level object found)"); } - PolySetCache::instance()->print(); + GeometryCache::instance()->print(); #ifdef ENABLE_CGAL CGALCache::instance()->print(); #endif @@ -1312,7 +1311,7 @@ void MainWindow::actionRenderCGALDone(CGAL_Nef_polyhedron *root_N) progress_report_fin(); if (root_N) { - PolySetCache::instance()->print(); + GeometryCache::instance()->print(); #ifdef ENABLE_CGAL CGALCache::instance()->print(); #endif @@ -1582,7 +1581,7 @@ void MainWindow::actionExportImage() void MainWindow::actionFlushCaches() { - PolySetCache::instance()->clear(); + GeometryCache::instance()->clear(); #ifdef ENABLE_CGAL CGALCache::instance()->clear(); #endif diff --git a/src/memory.h b/src/memory.h index cd8878af..01668465 100644 --- a/src/memory.h +++ b/src/memory.h @@ -3,5 +3,6 @@ #include using boost::shared_ptr; +using boost::dynamic_pointer_cast; #endif diff --git a/src/node.h b/src/node.h index 0b2221dc..3b894b32 100644 --- a/src/node.h +++ b/src/node.h @@ -35,10 +35,10 @@ public: overloaded to provide specialization for e.g. CSG nodes, primitive nodes etc. Used for human-readable output. */ virtual std::string name() const; - /*! Should return a PolySet of the given geometry. Returns NULL if smth. goes wrong. - This is only called by PolySetEvaluator, to make sure polysets are inserted into - the cache*/ - virtual class PolySet *evaluate_polyset(class PolySetEvaluator *) const { return NULL; } + /*! Should return a Geometry instance describing the node. Returns NULL 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 NULL; } const std::vector &getChildren() const { return this->children; diff --git a/src/polyset.cc b/src/polyset.cc index e601585d..059dcde7 100644 --- a/src/polyset.cc +++ b/src/polyset.cc @@ -35,9 +35,12 @@ FIXME: It's a bit messy and is a prime target for refactoring. 1) Store 2D and 3D polygon meshes from all origins - 2) Store 2D outlines, used for rendering edges + 2) Store 2D outlines, used for rendering edges (2D only) 3) Rendering of polygons and edges + + PolySet must only contain convex polygons + */ PolySet::PolySet() : grid(GRID_FINE), is2d(false), convexity(1) diff --git a/src/polyset.h b/src/polyset.h index 2ff817a3..c85533e2 100644 --- a/src/polyset.h +++ b/src/polyset.h @@ -1,13 +1,14 @@ #ifndef POLYSET_H_ #define POLYSET_H_ +#include "Geometry.h" #include "system-gl.h" #include "grid.h" #include "linalg.h" #include #include -class PolySet +class PolySet : public Geometry { public: typedef std::vector Polygon; @@ -21,12 +22,15 @@ public: PolySet(); ~PolySet(); + virtual size_t memsize() const; + virtual BoundingBox getBoundingBox() const; + virtual std::string dump() const; + bool empty() const { return polygons.size() == 0; } void append_poly(); void append_vertex(double x, double y, double z = 0.0); void insert_vertex(double x, double y, double z = 0.0); size_t memsize() const; - BoundingBox getBoundingBox() const; #define CSGMODE_DIFFERENCE_FLAG 0x10 @@ -42,7 +46,6 @@ public: void render_surface(csgmode_e csgmode, const Transform3d &m, GLint *shaderinfo = NULL) const; void render_edges(csgmode_e csgmode) const; - std::string dump() const; }; #endif diff --git a/src/primitives.cc b/src/primitives.cc index 53b2e196..a3697d52 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -28,6 +28,7 @@ #include "node.h" #include "polyset.h" #include "evalcontext.h" +#include "Polygon2d.h" #include "dxfdata.h" #include "dxftess.h" #include "builtin.h" @@ -37,6 +38,7 @@ #include "calc.h" #include #include +#include #include using namespace boost::assign; // bring 'operator+=()' into scope @@ -105,7 +107,7 @@ public: primitive_type_e type; int convexity; Value points, paths, faces; - virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; + virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const; }; /** @@ -188,8 +190,8 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta node->fa = F_MINIMUM; } - - if (type == CUBE) { + switch (this->type) { + case CUBE: { Value size = c.lookup_variable("size"); Value center = c.lookup_variable("center"); size.getDouble(node->x); @@ -199,16 +201,16 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta if (center.type() == Value::BOOL) { node->center = center.toBool(); } + break; } - - if (type == SPHERE) { + case SPHERE: { const Value r = lookup_radius(c, "d", "r"); if (r.type() == Value::NUMBER) { node->r1 = r.toDouble(); } + break; } - - if (type == CYLINDER) { + case CYLINDER: { const Value h = c.lookup_variable("h"); if (h.type() == Value::NUMBER) { node->h = h.toDouble(); @@ -232,21 +234,20 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta if (center.type() == Value::BOOL) { node->center = center.toBool(); } + break; } - - if (type == POLYHEDRON) { + case POLYHEDRON: { node->points = c.lookup_variable("points"); node->faces = c.lookup_variable("faces"); if (node->faces.type() == Value::UNDEFINED) { - // backwards compatable + // backwards compatible node->faces = c.lookup_variable("triangles"); if (node->faces.type() != Value::UNDEFINED) { PRINT("DEPRECATED: polyhedron(triangles=[]) will be removed in future releases. Use polyhedron(faces=[]) instead."); } } } - - if (type == SQUARE) { + case SQUARE: { Value size = c.lookup_variable("size"); Value center = c.lookup_variable("center"); size.getDouble(node->x); @@ -255,18 +256,20 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta if (center.type() == Value::BOOL) { node->center = center.toBool(); } + break; } - - if (type == CIRCLE) { + case CIRCLE: { const Value r = lookup_radius(c, "d", "r"); if (r.type() == Value::NUMBER) { node->r1 = r.toDouble(); } + break; } - - if (type == POLYGON) { + case POLYGON: { node->points = c.lookup_variable("points"); node->paths = c.lookup_variable("paths"); + break; + } } node->convexity = c.lookup_variable("convexity", true).toDouble(); @@ -289,12 +292,14 @@ static void generate_circle(point2d *circle, double r, int fragments) } } -PolySet *PrimitiveNode::evaluate_polyset(class PolySetEvaluator *) const +Geometry *PrimitiveNode::evaluate_geometry(class PolySetEvaluator *) const { - PolySet *p = new PolySet(); + Geometry *g = NULL; if (this->type == CUBE && this->x > 0 && this->y > 0 && this->z > 0) { + PolySet *p = new PolySet(); + g = p; double x1, x2, y1, y2, z1, z2; if (this->center) { x1 = -this->x/2; @@ -349,6 +354,8 @@ PolySet *PrimitiveNode::evaluate_polyset(class PolySetEvaluator *) const if (this->type == SPHERE && this->r1 > 0) { + PolySet *p = new PolySet(); + g = p; struct ring_s { point2d *points; double z; @@ -417,6 +424,8 @@ sphere_next_r2: if (this->type == CYLINDER && this->h > 0 && this->r1 >=0 && this->r2 >= 0 && (this->r1 > 0 || this->r2 > 0)) { + PolySet *p = new PolySet(); + g = p; int fragments = Calc::get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa); double z1, z2; @@ -476,6 +485,8 @@ sphere_next_r2: if (this->type == POLYHEDRON) { + PolySet *p = new PolySet(); + g = p; p->convexity = this->convexity; for (size_t i=0; ifaces.toVector().size(); i++) { @@ -493,6 +504,30 @@ sphere_next_r2: if (this->type == SQUARE && x > 0 && y > 0) { +/* + Polygon2d *p = new Polygon2d(); + g = p; + double x1, x2, y1, y2; + if (this->center) { + x1 = -this->x/2; + x2 = +this->x/2; + y1 = -this->y/2; + y2 = +this->y/2; + } else { + x1 = y1 = 0; + x2 = this->x; + y2 = this->y; + } + + Outline2d o(4); + o.push_back(Vector2d(x1, y1)); + o.push_back(Vector2d(x2, y1)); + o.push_back(Vector2d(x2, y2)); + o.push_back(Vector2d(x1, y2)); +*/ + + PolySet *p = new PolySet(); + g = p; double x1, x2, y1, y2; if (this->center) { x1 = -this->x/2; @@ -515,6 +550,8 @@ sphere_next_r2: if (this->type == CIRCLE) { + PolySet *p = new PolySet(); + g = p; int fragments = Calc::get_fragments_from_r(this->r1, this->fn, this->fs, this->fa); p->is2d = true; @@ -528,6 +565,8 @@ sphere_next_r2: if (this->type == POLYGON) { + PolySet *p = new PolySet(); + g = p; DxfData dd; for (size_t i=0; ipoints.toVector().size(); i++) { @@ -580,9 +619,54 @@ sphere_next_r2: p->convexity = convexity; dxf_tesselate(p, dd, 0, Vector2d(1,1), true, false, 0); dxf_border_to_ps(p, dd); + +/* + Polygon2D *p = new Polygon2D(); + g = p; + // Collect vertices + std::vector vertices; + for (size_t i=0; ipoints.toVector().size(); i++) { + double x,y; + if (!this->points.toVector()[i].getVec2(x, y)) { + PRINTB("ERROR: Unable to convert point at index %d to a vec2 of numbers", i); + delete p; + return NULL; + } + vertices.push_back(Vector2d(x, y)); + } + + Polygon2d polygon; + + // If no indices, assume one single polygon + if (this->paths.toVector().size() == 0) { + assert(vertices.size() >= 3); // FIXME: Fail gracefully + Outline2d outline; + BOOST_FOREACH(const Vector2d &p, vertices) outline.push_back(p); + polygon.addOutline(outline); + } + else { + BOOST_FOREACH(const Value &val, this->paths.toVector()) { + Outline2d outline; + BOOST_FOREACH(const Value &idxval, val.toVector()) { + unsigned int idx = idxval.toDouble(); + if (idx < vertices.size()) outline.push_back(vertices[idx]); + } + polygon.addOutline(outline); + } + } + + ScadPolygon::tessellate(polygons); + ScadPolygon::createPolyset(*p, polygons); + p->is2d = true; + p->convexity = convexity; +// dxf_tesselate(p, dd, 0, true, false, 0); +// dxf_border_to_ps(p, dd); +*/ } - return p; + // FIXME: IF the above failed, create an empty polyset as that's required later on + if (!g) g = new PolySet(); + return g; } std::string PrimitiveNode::toString() const diff --git a/src/projection.cc b/src/projection.cc index 8d8cee6b..ca93bbb4 100644 --- a/src/projection.cc +++ b/src/projection.cc @@ -31,6 +31,7 @@ #include "builtin.h" #include "visitor.h" #include "PolySetEvaluator.h" +#include "polyset.h" #include #include @@ -68,7 +69,7 @@ AbstractNode *ProjectionModule::instantiate(const Context *ctx, const ModuleInst return node; } -PolySet *ProjectionNode::evaluate_polyset(PolySetEvaluator *evaluator) const +Geometry *ProjectionNode::evaluate_geometry(PolySetEvaluator *evaluator) const { if (!evaluator) { PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name()); @@ -77,7 +78,7 @@ PolySet *ProjectionNode::evaluate_polyset(PolySetEvaluator *evaluator) const print_messages_push(); - PolySet *ps = evaluator->evaluatePolySet(*this); + Geometry *ps = evaluator->evaluateGeometry(*this); print_messages_pop(); diff --git a/src/projectionnode.h b/src/projectionnode.h index 41cca7cc..39ad85e9 100644 --- a/src/projectionnode.h +++ b/src/projectionnode.h @@ -19,7 +19,7 @@ public: int convexity; bool cut_mode; - virtual PolySet *evaluate_polyset(class PolySetEvaluator *evaluator) const; + virtual class Geometry *evaluate_geometry(class PolySetEvaluator *evaluator) const; }; #endif diff --git a/src/render.cc b/src/render.cc index 50976615..2b9b1bbc 100644 --- a/src/render.cc +++ b/src/render.cc @@ -29,6 +29,7 @@ #include "evalcontext.h" #include "builtin.h" #include "PolySetEvaluator.h" +#include "polyset.h" #include #include @@ -61,9 +62,9 @@ AbstractNode *RenderModule::instantiate(const Context *ctx, const ModuleInstanti return node; } -class PolySet *RenderNode::evaluate_polyset(PolySetEvaluator *ps) const +class Geometry *RenderNode::evaluate_geometry(PolySetEvaluator *ps) const { - return ps->evaluatePolySet(*this); + return ps->evaluateGeometry(*this); } std::string RenderNode::toString() const diff --git a/src/rendernode.h b/src/rendernode.h index 9e49baf2..f6ee3963 100644 --- a/src/rendernode.h +++ b/src/rendernode.h @@ -14,7 +14,7 @@ public: } virtual std::string toString() const; virtual std::string name() const { return "render"; } - PolySet *evaluate_polyset(class PolySetEvaluator *ps) const; + Geometry *evaluate_geometry(class PolySetEvaluator *ps) const; int convexity; }; diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index a79b92e1..b86498b1 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -92,7 +92,7 @@ AbstractNode *RotateExtrudeModule::instantiate(const Context *ctx, const ModuleI return node; } -PolySet *RotateExtrudeNode::evaluate_polyset(PolySetEvaluator *evaluator) const +Geometry *RotateExtrudeNode::evaluate_geometry(PolySetEvaluator *evaluator) const { if (!evaluator) { PRINTB("WARNING: No suitable PolySetEvaluator found for %s module!", this->name()); @@ -101,7 +101,7 @@ PolySet *RotateExtrudeNode::evaluate_polyset(PolySetEvaluator *evaluator) const print_messages_push(); - PolySet *ps = evaluator->evaluatePolySet(*this); + Geometry *ps = evaluator->evaluateGeometry(*this); print_messages_pop(); diff --git a/src/rotateextrudenode.h b/src/rotateextrudenode.h index 86da3565..4eedd4a7 100644 --- a/src/rotateextrudenode.h +++ b/src/rotateextrudenode.h @@ -24,7 +24,7 @@ public: double origin_x, origin_y, scale; Filename filename; std::string layername; - virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; + virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const; }; #endif diff --git a/src/surface.cc b/src/surface.cc index 7987b999..71c843fb 100644 --- a/src/surface.cc +++ b/src/surface.cc @@ -67,7 +67,7 @@ public: Filename filename; bool center; int convexity; - virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const; + virtual Geometry *evaluate_geometry(class PolySetEvaluator *) const; }; AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const @@ -98,7 +98,7 @@ AbstractNode *SurfaceModule::instantiate(const Context *ctx, const ModuleInstant return node; } -PolySet *SurfaceNode::evaluate_polyset(class PolySetEvaluator *) const +Geometry *SurfaceNode::evaluate_geometry(class PolySetEvaluator *) const { handle_dep(filename); std::ifstream stream(filename.c_str()); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index daf7c1e5..3ab20111 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -521,6 +521,8 @@ set(CORE_SOURCES ../src/feature.cc ../src/csgterm.cc ../src/csgtermnormalizer.cc + ../src/Geometry.cc + ../src/Polygon2d.cc ../src/polyset.cc ../src/csgops.cc ../src/transform.cc @@ -565,7 +567,7 @@ set(COMMON_SOURCES ../src/nodedumper.cc ../src/traverser.cc ../src/PolySetEvaluator.cc - ../src/PolySetCache.cc + ../src/GeometryCache.cc ../src/Tree.cc ../src/lodepng.cpp)