mirror of https://github.com/vitalif/openscad
bugfix: don't crash on empty resize(). refactoring: added virtual copy() to geometry, moved resize() to CGAL_Nef_polyhedron. Fixes #862
parent
aadb85d86e
commit
f87ee92755
|
@ -9,6 +9,11 @@ CGAL_Nef_polyhedron::CGAL_Nef_polyhedron(CGAL_Nef_polyhedron3 *p)
|
||||||
if (p) p3.reset(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)
|
CGAL_Nef_polyhedron& CGAL_Nef_polyhedron::operator+=(const CGAL_Nef_polyhedron &other)
|
||||||
{
|
{
|
||||||
|
@ -79,12 +84,46 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
void CGAL_Nef_polyhedron::resize(Vector3d newsize,
|
||||||
Deep copy
|
const Eigen::Matrix<bool,3,1> &autosize)
|
||||||
*/
|
|
||||||
CGAL_Nef_polyhedron *CGAL_Nef_polyhedron::copy() const
|
|
||||||
{
|
{
|
||||||
CGAL_Nef_polyhedron *copy = new CGAL_Nef_polyhedron(*this);
|
// Based on resize() in Giles Bathgate's RapCAD (but not exactly)
|
||||||
if (copy->p3) copy->p3.reset(new CGAL_Nef_polyhedron3(*copy->p3));
|
if (this->isEmpty()) return;
|
||||||
return copy;
|
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ class CGAL_Nef_polyhedron : public Geometry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CGAL_Nef_polyhedron(CGAL_Nef_polyhedron3 *p = NULL);
|
CGAL_Nef_polyhedron(CGAL_Nef_polyhedron3 *p = NULL);
|
||||||
|
CGAL_Nef_polyhedron(const CGAL_Nef_polyhedron &src);
|
||||||
~CGAL_Nef_polyhedron() {}
|
~CGAL_Nef_polyhedron() {}
|
||||||
|
|
||||||
virtual size_t memsize() const;
|
virtual size_t memsize() const;
|
||||||
|
@ -19,14 +20,16 @@ public:
|
||||||
virtual unsigned int getDimension() const { return 3; }
|
virtual unsigned int getDimension() const { return 3; }
|
||||||
// Empty means it is a geometric node which has zero area/volume
|
// Empty means it is a geometric node which has zero area/volume
|
||||||
virtual bool isEmpty() const { return !p3; }
|
virtual bool isEmpty() const { return !p3; }
|
||||||
|
virtual Geometry *copy() const { return new CGAL_Nef_polyhedron(*this); }
|
||||||
|
|
||||||
void reset() { p3.reset(); }
|
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 &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 &minkowski(const CGAL_Nef_polyhedron &other);
|
||||||
CGAL_Nef_polyhedron *copy() const;
|
|
||||||
class PolySet *convertToPolyset() const;
|
class PolySet *convertToPolyset() const;
|
||||||
void transform( const Transform3d &matrix );
|
void transform( const Transform3d &matrix );
|
||||||
|
void resize(Vector3d newsize, const Eigen::Matrix<bool,3,1> &autosize);
|
||||||
|
|
||||||
shared_ptr<CGAL_Nef_polyhedron3> p3;
|
shared_ptr<CGAL_Nef_polyhedron3> p3;
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@ public:
|
||||||
virtual std::string dump() const = 0;
|
virtual std::string dump() const = 0;
|
||||||
virtual unsigned int getDimension() const = 0;
|
virtual unsigned int getDimension() const = 0;
|
||||||
virtual bool isEmpty() const = 0;
|
virtual bool isEmpty() const = 0;
|
||||||
|
virtual Geometry *copy() const = 0;
|
||||||
|
|
||||||
unsigned int getConvexity() const { return convexity; }
|
unsigned int getConvexity() const { return convexity; }
|
||||||
void setConvexity(int c) { this->convexity = c; }
|
void setConvexity(int c) { this->convexity = c; }
|
||||||
|
|
|
@ -161,53 +161,6 @@ Geometry *GeometryEvaluator::applyHull3D(const AbstractNode &node)
|
||||||
return NULL;
|
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)
|
Polygon2d *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
|
||||||
{
|
{
|
||||||
std::vector<const Polygon2d *> children = collectChildren2D(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)) {
|
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
|
// If we got a const object, make a copy
|
||||||
shared_ptr<CGAL_Nef_polyhedron> newN;
|
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());
|
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
|
||||||
newN->setConvexity(node.convexity);
|
newN->setConvexity(node.convexity);
|
||||||
geom = newN;
|
geom = newN;
|
||||||
|
@ -594,7 +547,7 @@ Response GeometryEvaluator::visit(State &state, const TransformNode &node)
|
||||||
assert(N);
|
assert(N);
|
||||||
// If we got a const object, make a copy
|
// If we got a const object, make a copy
|
||||||
shared_ptr<CGAL_Nef_polyhedron> newN;
|
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());
|
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
|
||||||
newN->transform(node.matrix);
|
newN->transform(node.matrix);
|
||||||
geom = newN;
|
geom = newN;
|
||||||
|
@ -1005,40 +958,31 @@ Response GeometryEvaluator::visit(State &state, const CgaladvNode &node)
|
||||||
case RESIZE: {
|
case RESIZE: {
|
||||||
ResultObject res = applyToChildren(node, OPENSCAD_UNION);
|
ResultObject res = applyToChildren(node, OPENSCAD_UNION);
|
||||||
geom = res.constptr();
|
geom = res.constptr();
|
||||||
|
if (geom) {
|
||||||
shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(res.constptr());
|
shared_ptr<Geometry> editablegeom;
|
||||||
if (N) {
|
|
||||||
// If we got a const object, make a copy
|
// If we got a const object, make a copy
|
||||||
shared_ptr<CGAL_Nef_polyhedron> newN;
|
if (res.isConst()) editablegeom.reset(geom->copy());
|
||||||
if (res.isConst()) newN.reset(N->copy());
|
else editablegeom = res.ptr();
|
||||||
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
|
geom = editablegeom;
|
||||||
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());
|
|
||||||
|
|
||||||
newpoly->resize(Vector2d(node.newsize[0], node.newsize[1]),
|
shared_ptr<CGAL_Nef_polyhedron> N = dynamic_pointer_cast<CGAL_Nef_polyhedron>(editablegeom);
|
||||||
Eigen::Matrix<bool,2,1>(node.autosize[0], node.autosize[1]));
|
if (N) {
|
||||||
|
N->resize(node.newsize, node.autosize);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(res.constptr());
|
shared_ptr<Polygon2d> poly = dynamic_pointer_cast<Polygon2d>(editablegeom);
|
||||||
if (ps) {
|
if (poly) {
|
||||||
// If we got a const object, make a copy
|
poly->resize(Vector2d(node.newsize[0], node.newsize[1]),
|
||||||
shared_ptr<PolySet> newps;
|
Eigen::Matrix<bool,2,1>(node.autosize[0], node.autosize[1]));
|
||||||
if (res.isConst()) newps.reset(new PolySet(*ps));
|
|
||||||
else newps = dynamic_pointer_cast<PolySet>(res.ptr());
|
|
||||||
|
|
||||||
newps->resize(node.newsize, node.autosize);
|
|
||||||
geom = newps;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert(false);
|
shared_ptr<PolySet> ps = dynamic_pointer_cast<PolySet>(editablegeom);
|
||||||
|
if (ps) {
|
||||||
|
ps->resize(node.newsize, node.autosize);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ public:
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
virtual unsigned int getDimension() const { return 2; }
|
virtual unsigned int getDimension() const { return 2; }
|
||||||
virtual bool isEmpty() const;
|
virtual bool isEmpty() const;
|
||||||
|
virtual Geometry *copy() const { return new Polygon2d(*this); }
|
||||||
|
|
||||||
void addOutline(const Outline2d &outline) { this->theoutlines.push_back(outline); }
|
void addOutline(const Outline2d &outline) { this->theoutlines.push_back(outline); }
|
||||||
class PolySet *tessellate() const;
|
class PolySet *tessellate() const;
|
||||||
|
|
|
@ -341,7 +341,7 @@ namespace CGALUtils {
|
||||||
}
|
}
|
||||||
// Initialize N with first expected geometric object
|
// Initialize N with first expected geometric object
|
||||||
if (!N) {
|
if (!N) {
|
||||||
N = chN->copy();
|
N = new CGAL_Nef_polyhedron(*chN);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ namespace CGALUtils {
|
||||||
try {
|
try {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OPENSCAD_UNION:
|
case OPENSCAD_UNION:
|
||||||
if (target.isEmpty()) target = *src.copy();
|
if (target.isEmpty()) target = *new CGAL_Nef_polyhedron(src);
|
||||||
else target += src;
|
else target += src;
|
||||||
break;
|
break;
|
||||||
case OPENSCAD_INTERSECTION:
|
case OPENSCAD_INTERSECTION:
|
||||||
|
|
|
@ -26,6 +26,7 @@ public:
|
||||||
virtual std::string dump() const;
|
virtual std::string dump() const;
|
||||||
virtual unsigned int getDimension() const { return this->dim; }
|
virtual unsigned int getDimension() const { return this->dim; }
|
||||||
virtual bool isEmpty() const { return polygons.size() == 0; }
|
virtual bool isEmpty() const { return polygons.size() == 0; }
|
||||||
|
virtual Geometry *copy() const { return new PolySet(*this); }
|
||||||
|
|
||||||
size_t numPolygons() const { return polygons.size(); }
|
size_t numPolygons() const { return polygons.size(); }
|
||||||
void append_poly();
|
void append_poly();
|
||||||
|
|
Loading…
Reference in New Issue