diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc index eddb747a..a974f5fd 100644 --- a/src/CGAL_Nef_polyhedron.cc +++ b/src/CGAL_Nef_polyhedron.cc @@ -9,6 +9,11 @@ CGAL_Nef_polyhedron::CGAL_Nef_polyhedron(CGAL_Nef_polyhedron3 *p) if (p) p3.reset(p); } +// Copy constructor +CGAL_Nef_polyhedron::CGAL_Nef_polyhedron(const CGAL_Nef_polyhedron &src) +{ + if (src.p3) this->p3.reset(new CGAL_Nef_polyhedron3(*src.p3)); +} CGAL_Nef_polyhedron& CGAL_Nef_polyhedron::operator+=(const CGAL_Nef_polyhedron &other) { @@ -79,12 +84,46 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const return ps; } -/*! - Deep copy -*/ -CGAL_Nef_polyhedron *CGAL_Nef_polyhedron::copy() const +void CGAL_Nef_polyhedron::resize(Vector3d newsize, + const Eigen::Matrix &autosize) { - CGAL_Nef_polyhedron *copy = new CGAL_Nef_polyhedron(*this); - if (copy->p3) copy->p3.reset(new CGAL_Nef_polyhedron3(*copy->p3)); - return copy; + // Based on resize() in Giles Bathgate's RapCAD (but not exactly) + if (this->isEmpty()) return; + + CGAL_Iso_cuboid_3 bb = CGALUtils::boundingBox(*this->p3); + + std::vector scale, bbox_size; + for (unsigned int i=0;i<3;i++) { + scale.push_back(NT3(1)); + bbox_size.push_back(bb.max_coord(i) - bb.min_coord(i)); + } + int newsizemax_index = 0; + for (unsigned int i=0;igetDimension();i++) { + if (newsize[i]) { + if (bbox_size[i] == NT3(0)) { + PRINT("WARNING: Resize in direction normal to flat object is not implemented"); + return; + } + else { + scale[i] = NT3(newsize[i]) / bbox_size[i]; + } + if (newsize[i] > newsize[newsizemax_index]) newsizemax_index = i; + } + } + + NT3 autoscale = NT3(1); + if (newsize[newsizemax_index] != 0) { + autoscale = NT3(newsize[newsizemax_index]) / bbox_size[newsizemax_index]; + } + for (unsigned int i=0;igetDimension();i++) { + if (autosize[i] && newsize[i]==0) scale[i] = autoscale; + } + + Eigen::Matrix4d t; + t << CGAL::to_double(scale[0]), 0, 0, 0, + 0, CGAL::to_double(scale[1]), 0, 0, + 0, 0, CGAL::to_double(scale[2]), 0, + 0, 0, 0, 1; + + this->transform(Transform3d(t)); } diff --git a/src/CGAL_Nef_polyhedron.h b/src/CGAL_Nef_polyhedron.h index 72f6b33d..c1346710 100644 --- a/src/CGAL_Nef_polyhedron.h +++ b/src/CGAL_Nef_polyhedron.h @@ -10,6 +10,7 @@ class CGAL_Nef_polyhedron : public Geometry { public: CGAL_Nef_polyhedron(CGAL_Nef_polyhedron3 *p = NULL); + CGAL_Nef_polyhedron(const CGAL_Nef_polyhedron &src); ~CGAL_Nef_polyhedron() {} virtual size_t memsize() const; @@ -19,14 +20,16 @@ public: virtual unsigned int getDimension() const { return 3; } // Empty means it is a geometric node which has zero area/volume virtual bool isEmpty() const { return !p3; } + virtual Geometry *copy() const { return new CGAL_Nef_polyhedron(*this); } void reset() { p3.reset(); } CGAL_Nef_polyhedron &operator+=(const CGAL_Nef_polyhedron &other); CGAL_Nef_polyhedron &operator*=(const CGAL_Nef_polyhedron &other); CGAL_Nef_polyhedron &operator-=(const CGAL_Nef_polyhedron &other); CGAL_Nef_polyhedron &minkowski(const CGAL_Nef_polyhedron &other); - CGAL_Nef_polyhedron *copy() const; class PolySet *convertToPolyset() const; void transform( const Transform3d &matrix ); + void resize(Vector3d newsize, const Eigen::Matrix &autosize); + shared_ptr p3; }; diff --git a/src/Geometry.h b/src/Geometry.h index ffe7bf22..866f0b5d 100644 --- a/src/Geometry.h +++ b/src/Geometry.h @@ -21,6 +21,7 @@ public: virtual std::string dump() const = 0; virtual unsigned int getDimension() const = 0; virtual bool isEmpty() const = 0; + virtual Geometry *copy() const = 0; unsigned int getConvexity() const { return convexity; } void setConvexity(int c) { this->convexity = c; } diff --git a/src/GeometryEvaluator.cc b/src/GeometryEvaluator.cc index 40365d6e..73848bcf 100644 --- a/src/GeometryEvaluator.cc +++ b/src/GeometryEvaluator.cc @@ -161,53 +161,6 @@ Geometry *GeometryEvaluator::applyHull3D(const AbstractNode &node) return NULL; } -void GeometryEvaluator::applyResize3D(CGAL_Nef_polyhedron &N, - const Vector3d &newsize, - const Eigen::Matrix &autosize) -{ - // Based on resize() in Giles Bathgate's RapCAD (but not exactly) - if (N.isEmpty()) return; - - CGAL_Iso_cuboid_3 bb = CGALUtils::boundingBox(*N.p3); - - std::vector scale, bbox_size; - for (unsigned int i=0;i<3;i++) { - scale.push_back(NT3(1)); - bbox_size.push_back(bb.max_coord(i) - bb.min_coord(i)); - } - int newsizemax_index = 0; - for (unsigned int i=0;i newsize[newsizemax_index]) newsizemax_index = i; - } - } - - NT3 autoscale = NT3(1); - if (newsize[newsizemax_index] != 0) { - autoscale = NT3(newsize[newsizemax_index]) / bbox_size[newsizemax_index]; - } - for (unsigned int i=0;i children = collectChildren2D(node); @@ -457,7 +410,7 @@ Response GeometryEvaluator::visit(State &state, const RenderNode &node) else if (shared_ptr N = dynamic_pointer_cast(geom)) { // If we got a const object, make a copy shared_ptr newN; - if (res.isConst()) newN.reset(N->copy()); + if (res.isConst()) newN.reset((CGAL_Nef_polyhedron*)N->copy()); else newN = dynamic_pointer_cast(res.ptr()); newN->setConvexity(node.convexity); geom = newN; @@ -594,7 +547,7 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node) assert(N); // If we got a const object, make a copy shared_ptr newN; - if (res.isConst()) newN.reset(N->copy()); + if (res.isConst()) newN.reset((CGAL_Nef_polyhedron*)N->copy()); else newN = dynamic_pointer_cast(res.ptr()); newN->transform(node.matrix); geom = newN; @@ -1005,40 +958,31 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node) case RESIZE: { ResultObject res = applyToChildren(node, OPENSCAD_UNION); geom = res.constptr(); - - shared_ptr N = dynamic_pointer_cast(res.constptr()); - if (N) { + if (geom) { + shared_ptr editablegeom; // If we got a const object, make a copy - shared_ptr newN; - if (res.isConst()) newN.reset(N->copy()); - else newN = dynamic_pointer_cast(res.ptr()); - applyResize3D(*newN, node.newsize, node.autosize); - geom = newN; - } - else { - shared_ptr poly = dynamic_pointer_cast(res.constptr()); - if (poly) { - // If we got a const object, make a copy - shared_ptr newpoly; - if (res.isConst()) newpoly.reset(new Polygon2d(*poly)); - else newpoly = dynamic_pointer_cast(res.ptr()); + if (res.isConst()) editablegeom.reset(geom->copy()); + else editablegeom = res.ptr(); + geom = editablegeom; - newpoly->resize(Vector2d(node.newsize[0], node.newsize[1]), - Eigen::Matrix(node.autosize[0], node.autosize[1])); + shared_ptr N = dynamic_pointer_cast(editablegeom); + if (N) { + N->resize(node.newsize, node.autosize); } else { - shared_ptr ps = dynamic_pointer_cast(res.constptr()); - if (ps) { - // If we got a const object, make a copy - shared_ptr newps; - if (res.isConst()) newps.reset(new PolySet(*ps)); - else newps = dynamic_pointer_cast(res.ptr()); - - newps->resize(node.newsize, node.autosize); - geom = newps; + shared_ptr poly = dynamic_pointer_cast(editablegeom); + if (poly) { + poly->resize(Vector2d(node.newsize[0], node.newsize[1]), + Eigen::Matrix(node.autosize[0], node.autosize[1])); } else { - assert(false); + shared_ptr ps = dynamic_pointer_cast(editablegeom); + if (ps) { + ps->resize(node.newsize, node.autosize); + } + else { + assert(false); + } } } } diff --git a/src/Polygon2d.h b/src/Polygon2d.h index cf28e74d..1a8bb78e 100644 --- a/src/Polygon2d.h +++ b/src/Polygon2d.h @@ -19,6 +19,7 @@ public: virtual std::string dump() const; virtual unsigned int getDimension() const { return 2; } virtual bool isEmpty() const; + virtual Geometry *copy() const { return new Polygon2d(*this); } void addOutline(const Outline2d &outline) { this->theoutlines.push_back(outline); } class PolySet *tessellate() const; diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 8c2567c6..e7265b9b 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -341,7 +341,7 @@ namespace CGALUtils { } // Initialize N with first expected geometric object if (!N) { - N = chN->copy(); + N = new CGAL_Nef_polyhedron(*chN); continue; } @@ -420,7 +420,7 @@ namespace CGALUtils { try { switch (op) { case OPENSCAD_UNION: - if (target.isEmpty()) target = *src.copy(); + if (target.isEmpty()) target = *new CGAL_Nef_polyhedron(src); else target += src; break; case OPENSCAD_INTERSECTION: diff --git a/src/polyset.h b/src/polyset.h index 852084ef..91d17453 100644 --- a/src/polyset.h +++ b/src/polyset.h @@ -26,6 +26,7 @@ public: virtual std::string dump() const; virtual unsigned int getDimension() const { return this->dim; } virtual bool isEmpty() const { return polygons.size() == 0; } + virtual Geometry *copy() const { return new PolySet(*this); } size_t numPolygons() const { return polygons.size(); } void append_poly();