bugfix: don't crash on empty resize(). refactoring: added virtual copy() to geometry, moved resize() to CGAL_Nef_polyhedron. Fixes #862

master
Marius Kintel 2014-07-17 17:03:03 -04:00
parent aadb85d86e
commit f87ee92755
7 changed files with 76 additions and 87 deletions

View File

@ -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<bool,3,1> &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<NT3> 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<this->getDimension();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;i<this->getDimension();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));
}

View File

@ -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<bool,3,1> &autosize);
shared_ptr<CGAL_Nef_polyhedron3> p3;
};

View File

@ -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; }

View File

@ -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<bool,3,1> &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<NT3> 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<N.getDimension();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;i<N.getDimension();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;
N.transform(Transform3d(t));
return;
}
Polygon2d *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
{
std::vector<const Polygon2d *> children = collectChildren2D(node);
@ -457,7 +410,7 @@ Response GeometryEvaluator::visit(State &state, const RenderNode &node)
else if (shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom)) {
// If we got a const object, make a copy
shared_ptr<CGAL_Nef_polyhedron> newN;
if (res.isConst()) newN.reset(N->copy());
if (res.isConst()) newN.reset((CGAL_Nef_polyhedron*)N->copy());
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(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<CGAL_Nef_polyhedron> newN;
if (res.isConst()) newN.reset(N->copy());
if (res.isConst()) newN.reset((CGAL_Nef_polyhedron*)N->copy());
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(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<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(res.constptr());
if (N) {
if (geom) {
shared_ptr<Geometry> editablegeom;
// If we got a const object, make a copy
shared_ptr<CGAL_Nef_polyhedron> newN;
if (res.isConst()) newN.reset(N->copy());
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
applyResize3D(*newN, node.newsize, node.autosize);
geom = newN;
}
else {
shared_ptr<const Polygon2d> poly = dynamic_pointer_cast<const Polygon2d>(res.constptr());
if (poly) {
// If we got a const object, make a copy
shared_ptr<Polygon2d> newpoly;
if (res.isConst()) newpoly.reset(new Polygon2d(*poly));
else newpoly = dynamic_pointer_cast<Polygon2d>(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<bool,2,1>(node.autosize[0], node.autosize[1]));
shared_ptr<CGAL_Nef_polyhedron> N = dynamic_pointer_cast<CGAL_Nef_polyhedron>(editablegeom);
if (N) {
N->resize(node.newsize, node.autosize);
}
else {
shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(res.constptr());
if (ps) {
// If we got a const object, make a copy
shared_ptr<PolySet> newps;
if (res.isConst()) newps.reset(new PolySet(*ps));
else newps = dynamic_pointer_cast<PolySet>(res.ptr());
newps->resize(node.newsize, node.autosize);
geom = newps;
shared_ptr<Polygon2d> poly = dynamic_pointer_cast<Polygon2d>(editablegeom);
if (poly) {
poly->resize(Vector2d(node.newsize[0], node.newsize[1]),
Eigen::Matrix<bool,2,1>(node.autosize[0], node.autosize[1]));
}
else {
assert(false);
shared_ptr<PolySet> ps = dynamic_pointer_cast<PolySet>(editablegeom);
if (ps) {
ps->resize(node.newsize, node.autosize);
}
else {
assert(false);
}
}
}
}

View File

@ -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;

View File

@ -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:

View File

@ -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();