Added Geometry::isEmpty, some cleanups of CGAL_Nef_polyhedron, fixed some 2D-3D-mix issues

527olive
Marius Kintel 2013-12-28 21:37:08 -05:00
parent 211e3bc66d
commit b5928655e3
20 changed files with 327 additions and 440 deletions

View File

@ -388,7 +388,6 @@ SOURCES += src/cgalutils.cc \
src/CGALRenderer.cc \
src/CGAL_Nef_polyhedron.cc \
src/CGAL_Nef_polyhedron_DxfData.cc \
src/cgaladv_minkowski2.cc \
src/cgalworker.cc \
src/Polygon2d-CGAL.cc
}

View File

@ -34,8 +34,6 @@ CGAL_Nef_polyhedron& CGAL_Nef_polyhedron::operator-=(const CGAL_Nef_polyhedron &
return *this;
}
extern CGAL_Nef_polyhedron2 minkowski2(const CGAL_Nef_polyhedron2 &a, const CGAL_Nef_polyhedron2 &b);
CGAL_Nef_polyhedron &CGAL_Nef_polyhedron::minkowski(const CGAL_Nef_polyhedron &other)
{
if (this->dim == 3) (*this->p3) = CGAL::minkowski_sum_3(*this->p3, *other.p3);
@ -44,7 +42,7 @@ CGAL_Nef_polyhedron &CGAL_Nef_polyhedron::minkowski(const CGAL_Nef_polyhedron &o
size_t CGAL_Nef_polyhedron::memsize() const
{
if (this->isNull()) return 0;
if (this->isEmpty()) return 0;
size_t memsize = sizeof(CGAL_Nef_polyhedron);
if (this->dim == 3) memsize += this->p3->bytes();
@ -58,11 +56,11 @@ size_t CGAL_Nef_polyhedron::memsize() const
*/
PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
{
if (this->isNull()) return new PolySet();
if (this->isEmpty()) return new PolySet(this->dim);
PolySet *ps = NULL;
if (this->dim == 3) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
ps = new PolySet();
ps = new PolySet(3);
ps->setConvexity(this->convexity);
bool err = true;
std::string errmsg("");
@ -92,9 +90,9 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
/*!
Deep copy
*/
CGAL_Nef_polyhedron CGAL_Nef_polyhedron::copy() const
CGAL_Nef_polyhedron *CGAL_Nef_polyhedron::copy() const
{
CGAL_Nef_polyhedron copy = *this;
if (copy.p3) copy.p3.reset(new CGAL_Nef_polyhedron3(*copy.p3));
CGAL_Nef_polyhedron *copy = new CGAL_Nef_polyhedron(*this);
if (copy->p3) copy->p3.reset(new CGAL_Nef_polyhedron3(*copy->p3));
return copy;
}

View File

@ -19,17 +19,15 @@ public:
virtual BoundingBox getBoundingBox() const { assert(false && "not implemented"); }
virtual std::string dump() const;
virtual unsigned int getDimension() const { return this->dim; }
// Empty means it is a geometric node which has zero area/volume
bool isEmpty() const { return (dim > 0 && !p3); }
// Null means the node doesn't contain any geometry (for whatever reason)
bool isNull() const { return !p3; }
virtual bool isEmpty() const { return !p3; }
void reset() { dim=0; 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;
CGAL_Nef_polyhedron *copy() const;
class PolySet *convertToPolyset() const;
void transform( const Transform3d &matrix );
shared_ptr<CGAL_Nef_polyhedron3> p3;

View File

@ -47,7 +47,7 @@ std::string CGAL_Nef_polyhedron::dump() const
void CGAL_Nef_polyhedron::transform( const Transform3d &matrix )
{
if (!this->isNull()) {
if (!this->isEmpty()) {
if (this->dim == 3) {
if (matrix.matrix().determinant() == 0) {
PRINT("Warning: Scaling a 3D object with 0 - removing object");

View File

@ -21,6 +21,8 @@ public:
virtual BoundingBox getBoundingBox() const = 0;
virtual std::string dump() const = 0;
virtual unsigned int getDimension() const = 0;
virtual bool isEmpty() const = 0;
unsigned int getConvexity() const { return convexity; }
void setConvexity(int c) { this->convexity = c; }

View File

@ -97,7 +97,7 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr
// Only one child -> this is a noop
if (children.size() == 1) return ResultObject(children.front().second);
CGAL_Nef_polyhedron *N = new CGAL_Nef_polyhedron;
CGAL_Nef_polyhedron *N = NULL;
BOOST_FOREACH(const Geometry::ChildItem &item, children) {
const shared_ptr<const Geometry> &chgeom = item.second;
shared_ptr<const CGAL_Nef_polyhedron> chN;
@ -112,9 +112,9 @@ GeometryEvaluator::ResultObject GeometryEvaluator::applyToChildren3D(const Abstr
}
}
if (N) CGALUtils::applyBinaryOperator(*N, *chN, op);
// Initialize N on first iteration with first expected geometric object
if (N->isNull() && !N->isEmpty()) *N = chN->copy();
else CGALUtils::applyBinaryOperator(*N, *chN, op);
else if (chN) N = chN->copy();
item.first->progress_report();
}
@ -168,7 +168,7 @@ void GeometryEvaluator::applyResize3D(CGAL_Nef_polyhedron &N,
const Eigen::Matrix<bool,3,1> &autosize)
{
// Based on resize() in Giles Bathgate's RapCAD (but not exactly)
if (N.isNull() || N.isEmpty()) return;
if (N.isEmpty()) return;
CGAL_Iso_cuboid_3 bb = CGALUtils::boundingBox(*N.p3);
@ -237,6 +237,10 @@ Polygon2d *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
return NULL;
}
/*!
Returns a list of Polygon2d children of the given node.
May return empty Polygon2d object, but not NULL objects
*/
std::vector<const class Polygon2d *> GeometryEvaluator::collectChildren2D(const AbstractNode &node)
{
std::vector<const Polygon2d *> children;
@ -254,13 +258,15 @@ std::vector<const class Polygon2d *> GeometryEvaluator::collectChildren2D(const
GeometryCache::instance()->insert(this->tree.getIdString(*chnode), chgeom);
}
if (chgeom && chgeom->getDimension() == 2) {
if (chgeom) {
if (chgeom->getDimension() == 2) {
const Polygon2d *polygons = dynamic_cast<const Polygon2d *>(chgeom.get());
assert(polygons);
children.push_back(polygons);
}
else {
PRINT("WARNING: Ignoring 3D child object for 2D operation");
}
else {
PRINT("WARNING: Ignoring 3D child object for 2D operation");
}
}
}
return children;
@ -286,6 +292,10 @@ void GeometryEvaluator::smartCache(const AbstractNode &node,
}
}
/*!
Returns a list of 3D Geometry children of the given node.
May return empty geometries, but not NULL objects
*/
Geometry::ChildList GeometryEvaluator::collectChildren3D(const AbstractNode &node)
{
Geometry::ChildList children;
@ -301,13 +311,13 @@ Geometry::ChildList GeometryEvaluator::collectChildren3D(const AbstractNode &nod
// sibling object.
smartCache(*chnode, chgeom);
if (chgeom && chgeom->getDimension() == 3) {
if (chgeom) {
if (chgeom->isEmpty() || chgeom->getDimension() == 3) {
children.push_back(item);
}
else {
PRINT("ERROR: Only 3D children are supported by this operation!");
shared_ptr<const Geometry> nullp;
children.push_back(Geometry::ChildItem(item.first, nullp));
}
else {
PRINT("WARNING: Ignoring 2D child object for 3D operation");
}
}
}
return children;
@ -609,7 +619,7 @@ static void add_slice(PolySet *ps, const Polygon2d &poly,
*/
static Geometry *extrudePolygon(const LinearExtrudeNode &node, const Polygon2d &poly)
{
PolySet *ps = new PolySet();
PolySet *ps = new PolySet(3);
ps->setConvexity(node.convexity);
if (node.height <= 0) return ps;
@ -714,7 +724,7 @@ static void fill_ring(std::vector<Vector3d> &ring, const Outline2d &o, double a)
*/
static Geometry *rotatePolygon(const RotateExtrudeNode &node, const Polygon2d &poly)
{
PolySet *ps = new PolySet();
PolySet *ps = new PolySet(3);
ps->setConvexity(node.convexity);
BOOST_FOREACH(const Outline2d &o, poly.outlines()) {
@ -886,7 +896,7 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
if (!Nptr) {
Nptr.reset(createNefPolyhedronFromGeometry(*newgeom));
}
if (!Nptr->isNull()) {
if (!Nptr->isEmpty()) {
Polygon2d *poly = CGALUtils::project(*Nptr, node.cut_mode);
assert(poly);
poly->setConvexity(node.convexity);

View File

@ -106,7 +106,6 @@ mark_domains(CDT &cdt)
PolySet *Polygon2d::tessellate() const
{
PolySet *polyset = new PolySet(*this);
polyset->is2d = true;
Polygon2DCGAL::CDT cdt; // Uses a constrained Delaunay triangulator.
OPENSCAD_CGAL_ERROR_BEGIN;

View File

@ -47,6 +47,11 @@ std::string Polygon2d::dump() const
return out.str();
}
bool Polygon2d::isEmpty() const
{
return this->theoutlines.empty();
}
void Polygon2d::transform(const Transform2d &mat)
{
BOOST_FOREACH(Outline2d &o, this->theoutlines) {

View File

@ -19,6 +19,7 @@ public:
virtual BoundingBox getBoundingBox() const;
virtual std::string dump() const;
virtual unsigned int getDimension() const { return 2; }
virtual bool isEmpty() const;
void addOutline(const Outline2d &outline) { this->theoutlines.push_back(outline); }
class PolySet *tessellate() const;

View File

@ -1,137 +0,0 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifdef ENABLE_CGAL
#include "printutils.h"
#include "grid.h"
#include "cgal.h"
extern CGAL_Poly2 nef2p2(CGAL_Nef_polyhedron2 p);
//-----------------------------------------------------------------------------
// Pretty-print a CGAL polygon.
//
template<class Kernel, class Container>
void print_polygon (const CGAL::Polygon_2<Kernel, Container>& P)
{
typename CGAL::Polygon_2<Kernel, Container>::Vertex_const_iterator vit;
std::cout << "[ " << P.size() << " vertices:";
for (vit = P.vertices_begin(); vit != P.vertices_end(); ++vit)
std::cout << " (" << *vit << ')';
std::cout << " ]" << std::endl;
}
//-----------------------------------------------------------------------------
// Pretty-print a polygon with holes.
//
template<class Kernel, class Container>
void print_polygon_with_holes (const CGAL::Polygon_with_holes_2<Kernel, Container>& pwh) {
if (! pwh.is_unbounded()) {
std::cout << "{ Outer boundary = ";
print_polygon (pwh.outer_boundary());
} else
std::cout << "{ Unbounded polygon." << std::endl;
typename CGAL::Polygon_with_holes_2<Kernel,Container>::Hole_const_iterator hit;
unsigned int k = 1;
std::cout << " " << pwh.number_of_holes() << " holes:" << std::endl;
for (hit = pwh.holes_begin(); hit != pwh.holes_end(); ++hit, ++k) {
std::cout << " Hole #" << k << " = ";
print_polygon (*hit);
}
std::cout << " }" << std::endl;
return;
}
CGAL_Poly2 nef2p2(CGAL_Nef_polyhedron2 p)
{
std::list<CGAL_ExactKernel2::Point_2> points;
Grid2d<int> grid(GRID_COARSE);
typedef CGAL_Nef_polyhedron2::Explorer Explorer;
typedef Explorer::Face_const_iterator fci_t;
typedef Explorer::Halfedge_around_face_const_circulator heafcc_t;
Explorer E = p.explorer();
for (fci_t fit = E.faces_begin(), facesend = E.faces_end(); fit != facesend; ++fit)
{
if (!E.mark(fit)) {
continue;
}
//if (fit != E.faces_begin()) {
if (points.size() != 0) {
PRINT("WARNING: minkowski() and hull() is not implemented for 2d objects with holes!");
break;
}
heafcc_t fcirc(E.halfedge(fit)), fend(fcirc);
CGAL_For_all(fcirc, fend) {
if (E.is_standard(E.target(fcirc))) {
Explorer::Point ep = E.point(E.target(fcirc));
double x = to_double(ep.x()), y = to_double(ep.y());
grid.align(x, y);
points.push_back(CGAL_ExactKernel2::Point_2(x, y));
}
}
}
return CGAL_Poly2(points.begin(), points.end());
}
static CGAL_Nef_polyhedron2 p2nef2(CGAL_Poly2 p2) {
std::list<CGAL_Nef_polyhedron2::Point> points;
for (size_t j = 0; j < p2.size(); j++) {
double x = to_double(p2[j].x());
double y = to_double(p2[j].y());
CGAL_Nef_polyhedron2::Point p = CGAL_Nef_polyhedron2::Point(x, y);
points.push_back(p);
}
return CGAL_Nef_polyhedron2(points.begin(), points.end(), CGAL_Nef_polyhedron2::INCLUDED);
}
CGAL_Nef_polyhedron2 minkowski2(const CGAL_Nef_polyhedron2 &a, const CGAL_Nef_polyhedron2 &b)
{
CGAL_Poly2 ap = nef2p2(a), bp = nef2p2(b);
if (ap.size() == 0) {
PRINT("WARNING: minkowski() could not get any points from object 1!");
return CGAL_Nef_polyhedron2();
} else if (bp.size() == 0) {
PRINT("WARNING: minkowski() could not get any points from object 2!");
return CGAL_Nef_polyhedron2();
} else {
CGAL_Poly2h x = minkowski_sum_2(ap, bp);
// Make a CGAL_Nef_polyhedron2 out of just the boundary for starters
return p2nef2(x.outer_boundary());
}
}
#endif

View File

@ -85,7 +85,7 @@ namespace CGALUtils {
try {
switch (op) {
case OPENSCAD_UNION:
if (target.isEmpty()) target = src.copy();
if (target.isEmpty()) target = *src.copy();
else target += src;
break;
case OPENSCAD_INTERSECTION:
@ -402,7 +402,7 @@ void ZRemover::visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet )
static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps)
{
assert(ps.getDimension() == 3);
if (ps.empty()) return new CGAL_Nef_polyhedron(3);
if (ps.isEmpty()) return new CGAL_Nef_polyhedron(3);
CGAL_Nef_polyhedron3 *N = NULL;
bool plane_error = false;
@ -423,7 +423,7 @@ static CGAL_Nef_polyhedron *createNefPolyhedronFromPolySet(const PolySet &ps)
}
}
if (plane_error) try {
PolySet ps2;
PolySet ps2(3);
CGAL_Polyhedron P;
PolysetUtils::tessellate_faces(ps, ps2);
bool err = createPolyhedronFromPolySet(ps2,P);

View File

@ -109,8 +109,9 @@ shared_ptr<CSGTerm> CSGTerm::createCSGTerm(type_e type, CSGTerm *left, CSGTerm *
}
CSGTerm::CSGTerm(const shared_ptr<const Geometry> &geom, const Transform3d &matrix, const Color4f &color, const std::string &label)
: type(TYPE_PRIMITIVE), geom(geom), label(label), flag(CSGTerm::FLAG_NONE), m(matrix), color(color)
: type(TYPE_PRIMITIVE), label(label), flag(CSGTerm::FLAG_NONE), m(matrix), color(color)
{
if (geom && !geom->isEmpty()) this->geom = geom;
initBoundingBox();
}

View File

@ -74,7 +74,7 @@ void exportFile(const class Geometry *root_geom, std::ostream &output, FileForma
void export_stl(const PolySet *ps, std::ostream &output)
{
PolySet triangulated;
PolySet triangulated(3);
PolysetUtils::tessellate_faces(*ps, triangulated);
setlocale(LC_NUMERIC, "C"); // Ensure radix is . (not ,) in output

View File

@ -182,22 +182,26 @@ void read_stl_facet( std::ifstream &f, stl_facet &facet )
#endif
}
/*!
Will return an empty geometry if the import failed, but not NULL
*/
Geometry *ImportNode::createGeometry() const
{
Geometry *g = NULL;
if (this->type == TYPE_STL)
{
switch (this->type) {
case TYPE_STL: {
PolySet *p = new PolySet(3);
g = p;
handle_dep((std::string)this->filename);
// Open file and position at the end
std::ifstream f(this->filename.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
if (!f.good()) {
PRINTB("WARNING: Can't open import file '%s'.", this->filename);
return NULL;
return g;
}
PolySet *p = new PolySet();
boost::regex ex_sfe("solid|facet|endloop");
boost::regex ex_outer("outer loop");
boost::regex ex_vertex("vertex");
@ -270,11 +274,11 @@ Geometry *ImportNode::createGeometry() const
p->append_vertex(facet.data.x3, facet.data.y3, facet.data.z3);
}
}
g = p;
}
else if (this->type == TYPE_OFF)
{
break;
case TYPE_OFF: {
PolySet *p = new PolySet(3);
g = p;
#ifdef ENABLE_CGAL
CGAL_Polyhedron poly;
std::ifstream file(this->filename.c_str(), std::ios::in | std::ios::binary);
@ -285,24 +289,21 @@ Geometry *ImportNode::createGeometry() const
file >> poly;
file.close();
PolySet *p = new PolySet();
bool err = createPolySetFromPolyhedron(poly, *p);
if (err) delete p;
else g = p;
}
#else
PRINT("WARNING: OFF import requires CGAL.");
#endif
}
else if (this->type == TYPE_DXF)
{
break;
case TYPE_DXF: {
DxfData dd(this->fn, this->fs, this->fa, this->filename, this->layername, this->origin_x, this->origin_y, this->scale);
g = dd.toPolygon2d();
}
else
{
break;
default:
PRINTB("ERROR: Unsupported file format while trying to import file '%s'", this->filename);
g = new PolySet(0);
}
if (g) g->setConvexity(this->convexity);

View File

@ -1315,7 +1315,7 @@ void MainWindow::actionRenderDone(shared_ptr<const Geometry> root_geom)
PRINTB("Total rendering time: %d hours, %d minutes, %d seconds", (s / (60*60)) % ((s / 60) % 60) % (s % 60));
if (const CGAL_Nef_polyhedron *N = dynamic_cast<const CGAL_Nef_polyhedron *>(root_geom.get())) {
if (!N->isNull()) {
if (!N->isEmpty()) {
if (N->getDimension() == 3) {
PRINT(" Top level object is a 3D object:");
PRINTB(" Simple: %6s", (N->p3->is_simple() ? "yes" : "no"));

View File

@ -44,11 +44,11 @@
*/
PolySet::PolySet() : is2d(false)
PolySet::PolySet(unsigned int dim) : dim(dim)
{
}
PolySet::PolySet(const Polygon2d &origin) : is2d(true), polygon(origin)
PolySet::PolySet(const Polygon2d &origin) : polygon(origin), dim(2)
{
}
@ -60,7 +60,7 @@ std::string PolySet::dump() const
{
std::stringstream out;
out << "PolySet:"
<< "\n dimensions:" << std::string( this->is2d ? "2" : "3" )
<< "\n dimensions:" << this->dim
<< "\n convexity:" << this->convexity
<< "\n num polygons: " << polygons.size()
<< "\n num outlines: " << polygon.outlines().size()
@ -165,7 +165,7 @@ void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m,
glUniform1f(shaderinfo[8], shaderinfo[10]);
}
#endif /* ENABLE_OPENCSG */
if (this->is2d) {
if (this->dim == 2) {
// Render 2D objects 1mm thick, but differences slightly larger
double zbase = 1 + (csgmode & CSGMODE_DIFFERENCE_FLAG) * 0.1;
glBegin(GL_TRIANGLES);
@ -241,7 +241,7 @@ void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m,
}
}
glEnd();
} else {
} else if (this->dim == 3) {
for (size_t i = 0; i < polygons.size(); i++) {
const Polygon *poly = &polygons[i];
glBegin(GL_TRIANGLES);
@ -269,6 +269,9 @@ void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m,
glEnd();
}
}
else {
assert(false && "Cannot render object with no dimension");
}
}
/*! This is used in throwntogether and CGAL mode
@ -280,7 +283,7 @@ void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m,
void PolySet::render_edges(Renderer::csgmode_e csgmode) const
{
glDisable(GL_LIGHTING);
if (this->is2d) {
if (this->dim == 2) {
if (csgmode == Renderer::CSGMODE_NONE) {
// Render only outlines
BOOST_FOREACH(const Outline2d &o, polygon.outlines()) {
@ -313,7 +316,7 @@ void PolySet::render_edges(Renderer::csgmode_e csgmode) const
glEnd();
}
}
} else {
} else if (dim == 3) {
for (size_t i = 0; i < polygons.size(); i++) {
const Polygon *poly = &polygons[i];
glBegin(GL_LINE_LOOP);
@ -324,6 +327,9 @@ void PolySet::render_edges(Renderer::csgmode_e csgmode) const
glEnd();
}
}
else {
assert(false && "Cannot render object with no dimension");
}
glEnable(GL_LIGHTING);
}

View File

@ -15,18 +15,16 @@ public:
typedef std::vector<Vector3d> Polygon;
std::vector<Polygon> polygons;
bool is2d;
PolySet();
PolySet(unsigned int dim);
PolySet(const Polygon2d &origin);
virtual ~PolySet();
virtual size_t memsize() const;
virtual BoundingBox getBoundingBox() const;
virtual std::string dump() const;
virtual unsigned int getDimension() const { return this->is2d ? 2 : 3; }
virtual unsigned int getDimension() const { return this->dim; }
virtual bool isEmpty() const { return polygons.size() == 0; }
bool empty() const { return polygons.size() == 0; }
size_t numPolygons() const { return polygons.size(); }
void append_poly();
void append_vertex(double x, double y, double z = 0.0);
@ -43,6 +41,7 @@ public:
private:
Polygon2d polygon;
unsigned int dim;
};
#endif

View File

@ -292,202 +292,206 @@ static void generate_circle(point2d *circle, double r, int fragments)
/*!
Creates geometry for this node.
May return NULL if geometry creation failed.
*/
May return an empty Geometry creation failed, but will not return NULL.
*/
Geometry *PrimitiveNode::createGeometry() const
{
Geometry *g = NULL;
if (this->type == CUBE && this->x > 0 && this->y > 0 && this->z > 0)
{
PolySet *p = new PolySet();
switch (this->type) {
case CUBE: {
PolySet *p = new PolySet(3);
g = p;
double x1, x2, y1, y2, z1, z2;
if (this->center) {
x1 = -this->x/2;
x2 = +this->x/2;
y1 = -this->y/2;
y2 = +this->y/2;
z1 = -this->z/2;
z2 = +this->z/2;
} else {
x1 = y1 = z1 = 0;
x2 = this->x;
y2 = this->y;
z2 = this->z;
if (this->x > 0 && this->y > 0 && this->z > 0) {
double x1, x2, y1, y2, z1, z2;
if (this->center) {
x1 = -this->x/2;
x2 = +this->x/2;
y1 = -this->y/2;
y2 = +this->y/2;
z1 = -this->z/2;
z2 = +this->z/2;
} else {
x1 = y1 = z1 = 0;
x2 = this->x;
y2 = this->y;
z2 = this->z;
}
p->append_poly(); // top
p->append_vertex(x1, y1, z2);
p->append_vertex(x2, y1, z2);
p->append_vertex(x2, y2, z2);
p->append_vertex(x1, y2, z2);
p->append_poly(); // bottom
p->append_vertex(x1, y2, z1);
p->append_vertex(x2, y2, z1);
p->append_vertex(x2, y1, z1);
p->append_vertex(x1, y1, z1);
p->append_poly(); // side1
p->append_vertex(x1, y1, z1);
p->append_vertex(x2, y1, z1);
p->append_vertex(x2, y1, z2);
p->append_vertex(x1, y1, z2);
p->append_poly(); // side2
p->append_vertex(x2, y1, z1);
p->append_vertex(x2, y2, z1);
p->append_vertex(x2, y2, z2);
p->append_vertex(x2, y1, z2);
p->append_poly(); // side3
p->append_vertex(x2, y2, z1);
p->append_vertex(x1, y2, z1);
p->append_vertex(x1, y2, z2);
p->append_vertex(x2, y2, z2);
p->append_poly(); // side4
p->append_vertex(x1, y2, z1);
p->append_vertex(x1, y1, z1);
p->append_vertex(x1, y1, z2);
p->append_vertex(x1, y2, z2);
}
p->append_poly(); // top
p->append_vertex(x1, y1, z2);
p->append_vertex(x2, y1, z2);
p->append_vertex(x2, y2, z2);
p->append_vertex(x1, y2, z2);
p->append_poly(); // bottom
p->append_vertex(x1, y2, z1);
p->append_vertex(x2, y2, z1);
p->append_vertex(x2, y1, z1);
p->append_vertex(x1, y1, z1);
p->append_poly(); // side1
p->append_vertex(x1, y1, z1);
p->append_vertex(x2, y1, z1);
p->append_vertex(x2, y1, z2);
p->append_vertex(x1, y1, z2);
p->append_poly(); // side2
p->append_vertex(x2, y1, z1);
p->append_vertex(x2, y2, z1);
p->append_vertex(x2, y2, z2);
p->append_vertex(x2, y1, z2);
p->append_poly(); // side3
p->append_vertex(x2, y2, z1);
p->append_vertex(x1, y2, z1);
p->append_vertex(x1, y2, z2);
p->append_vertex(x2, y2, z2);
p->append_poly(); // side4
p->append_vertex(x1, y2, z1);
p->append_vertex(x1, y1, z1);
p->append_vertex(x1, y1, z2);
p->append_vertex(x1, y2, z2);
}
if (this->type == SPHERE && this->r1 > 0)
{
PolySet *p = new PolySet();
break;
case SPHERE: {
PolySet *p = new PolySet(3);
g = p;
struct ring_s {
point2d *points;
double z;
};
if (this->r1 > 0) {
struct ring_s {
point2d *points;
double z;
};
int fragments = Calc::get_fragments_from_r(r1, fn, fs, fa);
int rings = (fragments+1)/2;
int fragments = Calc::get_fragments_from_r(r1, fn, fs, fa);
int rings = (fragments+1)/2;
// Uncomment the following three lines to enable experimental sphere tesselation
// if (rings % 2 == 0) rings++; // To ensure that the middle ring is at phi == 0 degrees
ring_s *ring = new ring_s[rings];
ring_s *ring = new ring_s[rings];
// double offset = 0.5 * ((fragments / 2) % 2);
for (int i = 0; i < rings; i++) {
for (int i = 0; i < rings; i++) {
// double phi = (M_PI * (i + offset)) / (fragments/2);
double phi = (M_PI * (i + 0.5)) / rings;
double r = r1 * sin(phi);
ring[i].z = r1 * cos(phi);
ring[i].points = new point2d[fragments];
generate_circle(ring[i].points, r, fragments);
}
double phi = (M_PI * (i + 0.5)) / rings;
double r = r1 * sin(phi);
ring[i].z = r1 * cos(phi);
ring[i].points = new point2d[fragments];
generate_circle(ring[i].points, r, fragments);
}
p->append_poly();
for (int i = 0; i < fragments; i++)
p->append_vertex(ring[0].points[i].x, ring[0].points[i].y, ring[0].z);
p->append_poly();
for (int i = 0; i < fragments; i++)
p->append_vertex(ring[0].points[i].x, ring[0].points[i].y, ring[0].z);
for (int i = 0; i < rings-1; i++) {
ring_s *r1 = &ring[i];
ring_s *r2 = &ring[i+1];
int r1i = 0, r2i = 0;
while (r1i < fragments || r2i < fragments)
{
if (r1i >= fragments)
goto sphere_next_r2;
if (r2i >= fragments)
goto sphere_next_r1;
if ((double)r1i / fragments <
(double)r2i / fragments)
for (int i = 0; i < rings-1; i++) {
ring_s *r1 = &ring[i];
ring_s *r2 = &ring[i+1];
int r1i = 0, r2i = 0;
while (r1i < fragments || r2i < fragments)
{
sphere_next_r1:
p->append_poly();
int r1j = (r1i+1) % fragments;
p->insert_vertex(r1->points[r1i].x, r1->points[r1i].y, r1->z);
p->insert_vertex(r1->points[r1j].x, r1->points[r1j].y, r1->z);
p->insert_vertex(r2->points[r2i % fragments].x, r2->points[r2i % fragments].y, r2->z);
r1i++;
} else {
sphere_next_r2:
p->append_poly();
int r2j = (r2i+1) % fragments;
p->append_vertex(r2->points[r2i].x, r2->points[r2i].y, r2->z);
p->append_vertex(r2->points[r2j].x, r2->points[r2j].y, r2->z);
p->append_vertex(r1->points[r1i % fragments].x, r1->points[r1i % fragments].y, r1->z);
r2i++;
if (r1i >= fragments)
goto sphere_next_r2;
if (r2i >= fragments)
goto sphere_next_r1;
if ((double)r1i / fragments <
(double)r2i / fragments)
{
sphere_next_r1:
p->append_poly();
int r1j = (r1i+1) % fragments;
p->insert_vertex(r1->points[r1i].x, r1->points[r1i].y, r1->z);
p->insert_vertex(r1->points[r1j].x, r1->points[r1j].y, r1->z);
p->insert_vertex(r2->points[r2i % fragments].x, r2->points[r2i % fragments].y, r2->z);
r1i++;
} else {
sphere_next_r2:
p->append_poly();
int r2j = (r2i+1) % fragments;
p->append_vertex(r2->points[r2i].x, r2->points[r2i].y, r2->z);
p->append_vertex(r2->points[r2j].x, r2->points[r2j].y, r2->z);
p->append_vertex(r1->points[r1i % fragments].x, r1->points[r1i % fragments].y, r1->z);
r2i++;
}
}
}
p->append_poly();
for (int i = 0; i < fragments; i++)
p->insert_vertex(ring[rings-1].points[i].x,
ring[rings-1].points[i].y,
ring[rings-1].z);
delete[] ring;
}
p->append_poly();
for (int i = 0; i < fragments; i++)
p->insert_vertex(ring[rings-1].points[i].x, ring[rings-1].points[i].y, ring[rings-1].z);
delete[] ring;
}
if (this->type == CYLINDER &&
this->h > 0 && this->r1 >=0 && this->r2 >= 0 && (this->r1 > 0 || this->r2 > 0))
{
PolySet *p = new PolySet();
break;
case CYLINDER: {
PolySet *p = new PolySet(3);
g = p;
int fragments = Calc::get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa);
if (this->h > 0 && this->r1 >=0 && this->r2 >= 0 && (this->r1 > 0 || this->r2 > 0)) {
int fragments = Calc::get_fragments_from_r(fmax(this->r1, this->r2), this->fn, this->fs, this->fa);
double z1, z2;
if (this->center) {
z1 = -this->h/2;
z2 = +this->h/2;
} else {
z1 = 0;
z2 = this->h;
}
point2d *circle1 = new point2d[fragments];
point2d *circle2 = new point2d[fragments];
generate_circle(circle1, r1, fragments);
generate_circle(circle2, r2, fragments);
for (int i=0; i<fragments; i++) {
int j = (i+1) % fragments;
if (r1 == r2) {
p->append_poly();
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
p->insert_vertex(circle2[j].x, circle2[j].y, z2);
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
double z1, z2;
if (this->center) {
z1 = -this->h/2;
z2 = +this->h/2;
} else {
if (r1 > 0) {
z1 = 0;
z2 = this->h;
}
point2d *circle1 = new point2d[fragments];
point2d *circle2 = new point2d[fragments];
generate_circle(circle1, r1, fragments);
generate_circle(circle2, r2, fragments);
for (int i=0; i<fragments; i++) {
int j = (i+1) % fragments;
if (r1 == r2) {
p->append_poly();
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
}
if (r2 > 0) {
p->append_poly();
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
p->insert_vertex(circle2[j].x, circle2[j].y, z2);
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
} else {
if (r1 > 0) {
p->append_poly();
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
}
if (r2 > 0) {
p->append_poly();
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
p->insert_vertex(circle2[j].x, circle2[j].y, z2);
p->insert_vertex(circle1[j].x, circle1[j].y, z1);
}
}
}
}
if (this->r1 > 0) {
p->append_poly();
for (int i=0; i<fragments; i++)
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
}
if (this->r1 > 0) {
p->append_poly();
for (int i=0; i<fragments; i++)
p->insert_vertex(circle1[i].x, circle1[i].y, z1);
}
if (this->r2 > 0) {
p->append_poly();
for (int i=0; i<fragments; i++)
p->append_vertex(circle2[i].x, circle2[i].y, z2);
}
if (this->r2 > 0) {
p->append_poly();
for (int i=0; i<fragments; i++)
p->append_vertex(circle2[i].x, circle2[i].y, z2);
}
delete[] circle1;
delete[] circle2;
delete[] circle1;
delete[] circle2;
}
}
if (this->type == POLYHEDRON)
{
PolySet *p = new PolySet();
break;
case POLYHEDRON: {
PolySet *p = new PolySet(3);
g = p;
p->setConvexity(this->convexity);
for (size_t i=0; i<this->faces.toVector().size(); i++)
@ -503,87 +507,89 @@ sphere_next_r2:
}
}
}
if (this->type == SQUARE && this->x > 0 && this->y > 0)
{
break;
case SQUARE: {
Polygon2d *p = new Polygon2d();
g = p;
Vector2d v1(0, 0);
Vector2d v2(this->x, this->y);
if (this->center) {
v1 -= Vector2d(this->x/2, this->y/2);
v2 -= Vector2d(this->x/2, this->y/2);
}
Outline2d o;
o.vertices.resize(4);
o.vertices[0] = v1;
o.vertices[1] = Vector2d(v2[0], v1[1]);
o.vertices[2] = v2;
o.vertices[3] = Vector2d(v1[0], v2[1]);
p->addOutline(o);
p->setSanitized(true);
}
if (this->type == CIRCLE && this->r1 > 0)
{
Polygon2d *p = new Polygon2d();
g = p;
int fragments = Calc::get_fragments_from_r(this->r1, this->fn, this->fs, this->fa);
Outline2d o;
o.vertices.resize(fragments);
for (int i=0; i < fragments; i++) {
double phi = (M_PI*2*i) / fragments;
o.vertices[i] = Vector2d(this->r1*cos(phi), this->r1*sin(phi));
}
p->addOutline(o);
p->setSanitized(true);
}
if (this->type == POLYGON)
{
Polygon2d *p = new Polygon2d();
g = p;
Outline2d outline;
double x,y;
const Value::VectorType &vec = this->points.toVector();
for (int i=0;i<vec.size();i++) {
const Value &val = vec[i];
if (!val.getVec2(x, y)) {
PRINTB("ERROR: Unable to convert point %s at index %d to a vec2 of numbers",
val.toString() % i);
delete p;
return NULL;
if (this->x > 0 && this->y > 0) {
Vector2d v1(0, 0);
Vector2d v2(this->x, this->y);
if (this->center) {
v1 -= Vector2d(this->x/2, this->y/2);
v2 -= Vector2d(this->x/2, this->y/2);
}
outline.vertices.push_back(Vector2d(x, y));
}
if (this->paths.toVector().size() == 0 && outline.vertices.size() > 2) {
p->addOutline(outline);
Outline2d o;
o.vertices.resize(4);
o.vertices[0] = v1;
o.vertices[1] = Vector2d(v2[0], v1[1]);
o.vertices[2] = v2;
o.vertices[3] = Vector2d(v1[0], v2[1]);
p->addOutline(o);
p->setSanitized(true);
}
else {
BOOST_FOREACH(const Value &polygon, this->paths.toVector()) {
Outline2d curroutline;
BOOST_FOREACH(const Value &index, polygon.toVector()) {
unsigned int idx = index.toDouble();
if (idx < outline.vertices.size()) {
curroutline.vertices.push_back(outline.vertices[idx]);
}
// FIXME: Warning on out of bounds?
}
break;
case CIRCLE: {
Polygon2d *p = new Polygon2d();
g = p;
if (this->r1 > 0) {
int fragments = Calc::get_fragments_from_r(this->r1, this->fn, this->fs, this->fa);
Outline2d o;
o.vertices.resize(fragments);
for (int i=0; i < fragments; i++) {
double phi = (M_PI*2*i) / fragments;
o.vertices[i] = Vector2d(this->r1*cos(phi), this->r1*sin(phi));
}
p->addOutline(o);
p->setSanitized(true);
}
}
break;
case POLYGON: {
Polygon2d *p = new Polygon2d();
g = p;
Outline2d outline;
double x,y;
const Value::VectorType &vec = this->points.toVector();
for (int i=0;i<vec.size();i++) {
const Value &val = vec[i];
if (!val.getVec2(x, y)) {
PRINTB("ERROR: Unable to convert point %s at index %d to a vec2 of numbers",
val.toString() % i);
delete p;
return NULL;
}
outline.vertices.push_back(Vector2d(x, y));
}
if (this->paths.toVector().size() == 0 && outline.vertices.size() > 2) {
p->addOutline(outline);
}
else {
BOOST_FOREACH(const Value &polygon, this->paths.toVector()) {
Outline2d curroutline;
BOOST_FOREACH(const Value &index, polygon.toVector()) {
unsigned int idx = index.toDouble();
if (idx < outline.vertices.size()) {
curroutline.vertices.push_back(outline.vertices[idx]);
}
// FIXME: Warning on out of bounds?
}
p->addOutline(curroutline);
}
p->addOutline(curroutline);
}
}
if (p->outlines().size() == 0) {
delete p;
g = NULL;
}
else {
p->setConvexity(convexity);
}
if (p->outlines().size() == 0) {
delete p;
g = NULL;
}
else {
p->setConvexity(convexity);
}
}
}
return g;

View File

@ -108,7 +108,7 @@ Geometry *SurfaceNode::createGeometry() const
return NULL;
}
PolySet *p = new PolySet();
PolySet *p = new PolySet(3);
int lines = 0, columns = 0;
boost::unordered_map<std::pair<int,int>,double> data;
double min_val = 0;

View File

@ -556,7 +556,6 @@ set(CGAL_SOURCES
../src/cgalutils.cc
../src/CGALCache.cc
../src/CGAL_Nef_polyhedron_DxfData.cc
../src/cgaladv_minkowski2.cc
../src/Polygon2d-CGAL.cc
../src/polyset-utils.cc
../src/svg.cc