Clifford Wolf:

Preps for OpenCSG interface
	Invented AbstractPolyNode



git-svn-id: http://svn.clifford.at/openscad/trunk@15 b57f626f-c46c-0410-a088-ec61d464b74c
stl_dim
clifford 2009-06-24 10:59:15 +00:00
parent 12e8d77bc0
commit ba42e6c30b
10 changed files with 599 additions and 118 deletions

9
README
View File

@ -22,9 +22,18 @@ may not work as well..
* CGAL (3.4):
http://www.cgal.org/
* boost (1.35, required by CGAL)
http://www.boost.org/
* cmake (2.6.2, required by CGAL)
http://www.cmake.org/
* OpenCSG (1.1.0):
http://www.opencsg.org/
* GLEW (bundled with OpenCSG)
http://glew.sourceforge.net/
* GCC C++ Compiler (4.3.1):
http://gcc.gnu.org/

29
csg.cc
View File

@ -43,6 +43,9 @@ public:
CsgNode(csg_type_e type) : type(type) { }
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
#ifdef ENABLE_OPENCSG
CSGTerm *render_csg_term(double m[16]) const;
#endif
virtual QString dump(QString indent) const;
};
@ -82,9 +85,33 @@ CGAL_Nef_polyhedron CsgNode::render_cgal_nef_polyhedron() const
#endif /* ENABLE_CGAL */
#ifdef ENABLE_OPENCSG
CSGTerm *CsgNode::render_csg_term(double m[16]) const
{
CSGTerm *t1 = NULL;
foreach (AbstractNode *v, children) {
CSGTerm *t2 = v->render_csg_term(m);
if (t2 && !t1) {
t1 = t2;
} else if (t2 && t1) {
if (type == UNION) {
t1 = new CSGTerm(CSGTerm::UNION, t1, t2);
} else if (type == DIFFERENCE) {
t1 = new CSGTerm(CSGTerm::DIFFERENCE, t1, t2);
} else if (type == INTERSECTION) {
t1 = new CSGTerm(CSGTerm::INTERSECTION, t1, t2);
}
}
}
return t1;
}
#endif /* ENABLE_OPENCSG */
QString CsgNode::dump(QString indent) const
{
QString text = indent;
QString text = indent + QString("n%1: ").arg(idx);
if (type == UNION)
text += "union() {\n";
if (type == DIFFERENCE)

155
csgterm.cc Normal file
View File

@ -0,0 +1,155 @@
/*
* OpenSCAD (www.openscad.at)
* Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
*
* 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.
*
* 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
*
*/
#define INCLUDE_ABSTRACT_NODE_DETAILS
#include "openscad.h"
CSGTerm::CSGTerm(PolySet *polyset, double m[16])
{
this->type = PRIMITIVE;
this->polyset = polyset;
this->left = NULL;
this->right = NULL;
for (int i=0; i<16; i++)
this->m[i] = m[i];
refcounter = 1;
}
CSGTerm::CSGTerm(type_e type, CSGTerm *left, CSGTerm *right)
{
this->type = type;
this->polyset = NULL;
this->left = left;
this->right = right;
for (int i=0; i<16; i++)
this->m[i] = 0;
refcounter = 1;
}
CSGTerm *CSGTerm::normalize(bool &changed)
{
// This function implements the CSG normalization
// Reference: Florian Kirsch, Juergen Doeller,
// OpenCSG: A Library for Image-Based CSG Rendering,
// University of Potsdam, Hasso-Plattner-Institute, Germany
// http://www.opencsg.org/data/csg_freenix2005_paper.pdf
if (type == PRIMITIVE)
return link();
CSGTerm *x, *y, *z;
x = left->normalize(changed);
left->unlink();
left = x;
x = right->normalize(changed);
right->unlink();
right = x;
// Part A: The 'x . (y . z)' expressions
x = left;
y = right->left;
z = right->right;
// 1. x - (y + z) -> (x - y) - z
if (type == DIFFERENCE && right->type == UNION) {
changed = true;
return new CSGTerm(DIFFERENCE, new CSGTerm(DIFFERENCE, x->link(), y->link()), z->link());
}
// 2. x * (y + z) -> (x * y) + (x * z)
if (type == INTERSECTION && right->type == UNION) {
changed = true;
return new CSGTerm(UNION, new CSGTerm(INTERSECTION, x->link(), y->link()), new CSGTerm(INTERSECTION, x->link(), z->link()));
}
// 3. x - (y * z) -> (x - y) + (x - z)
if (type == DIFFERENCE && right->type == INTERSECTION) {
changed = true;
return new CSGTerm(UNION, new CSGTerm(DIFFERENCE, x->link(), y->link()), new CSGTerm(DIFFERENCE, x->link(), z->link()));
}
// 4. x * (y * z) -> (x * y) * z
if (type == INTERSECTION && right->type == INTERSECTION) {
changed = true;
return new CSGTerm(INTERSECTION, new CSGTerm(INTERSECTION, x->link(), y->link()), z->link());
}
// 5. x - (y - z) -> (x - y) + (x * z)
if (type == DIFFERENCE && right->type == DIFFERENCE) {
changed = true;
return new CSGTerm(UNION, new CSGTerm(DIFFERENCE, x->link(), y->link()), new CSGTerm(INTERSECTION, x->link(), z->link()));
}
// 6. x * (y - z) -> (x * y) - z
if (type == INTERSECTION && right->type == DIFFERENCE) {
changed = true;
return new CSGTerm(DIFFERENCE, new CSGTerm(INTERSECTION, x->link(), y->link()), z->link());
}
// Part B: The '(x . y) . z' expressions
x = left->left;
y = left->right;
z = right;
// 7. (x - y) * z -> (x * z) - y
if (left->type == DIFFERENCE && type == INTERSECTION) {
changed = true;
return new CSGTerm(DIFFERENCE, new CSGTerm(INTERSECTION, x->link(), z->link()), y->link());
}
// 8. (x + y) - z -> (x - z) + (y - z)
if (left->type == UNION && type == DIFFERENCE) {
changed = true;
return new CSGTerm(UNION, new CSGTerm(DIFFERENCE, x->link(), z->link()), new CSGTerm(DIFFERENCE, y->link(), z->link()));
}
// 9. (x + y) * z -> (x * z) + (y * z)
if (left->type == UNION && type == INTERSECTION) {
changed = true;
return new CSGTerm(UNION, new CSGTerm(INTERSECTION, x->link(), z->link()), new CSGTerm(INTERSECTION, y->link(), z->link()));
}
return this;
}
CSGTerm *CSGTerm::link()
{
refcounter++;
return this;
}
void CSGTerm::unlink()
{
if (--refcounter <= 0) {
if (polyset)
delete polyset;
if (left)
left->unlink();
if (right)
right->unlink();
delete this;
}
}

View File

@ -35,7 +35,9 @@ MainWindow::MainWindow(const char *filename)
root_module = NULL;
root_node = NULL;
#ifdef ENABLE_CGAL
root_N = NULL;
#endif
if (filename) {
this->filename = QString(filename);
@ -60,7 +62,8 @@ MainWindow::MainWindow(const char *filename)
menu->addAction("Compile and &Render (CGAL)", this, SLOT(actionRenderCGAL()));
#endif
menu->addAction("Display &AST...", this, SLOT(actionDisplayAST()));
menu->addAction("Display &CSG...", this, SLOT(actionDisplayCSG()));
menu->addAction("Display CSG &Tree...", this, SLOT(actionDisplayCSGTree()));
menu->addAction("Display CSG &Products...", this, SLOT(actionDisplayCSGProducts()));
menu->addAction("Export as &STL...", this, SLOT(actionExportSTL()));
menu->addAction("Export as &OFF...", this, SLOT(actionExportOFF()));
}
@ -135,8 +138,10 @@ MainWindow::~MainWindow()
delete root_module;
if (root_node)
delete root_node;
#ifdef ENABLE_CGAL
if (root_N)
delete root_N;
#endif
}
void MainWindow::actionNew()
@ -215,8 +220,9 @@ void MainWindow::actionCompile()
root_node = NULL;
}
console->append("Compiling design (CSG generation)...");
console->append("Compiling design (CSG Tree generation)...");
QApplication::processEvents();
AbstractNode::idx_counter = 1;
root_node = root_module->evaluate(&root_ctx, QVector<QString>(), QVector<Value>(), QVector<AbstractNode*>());
if (!root_node) {
@ -287,7 +293,7 @@ void MainWindow::actionDisplayAST()
e->resize(600, 400);
}
void MainWindow::actionDisplayCSG()
void MainWindow::actionDisplayCSGTree()
{
QTextEdit *e = new QTextEdit(NULL);
e->setTabStopWidth(30);
@ -301,6 +307,20 @@ void MainWindow::actionDisplayCSG()
e->resize(600, 400);
}
void MainWindow::actionDisplayCSGProducts()
{
QTextEdit *e = new QTextEdit(NULL);
e->setTabStopWidth(30);
e->setWindowTitle("CSG Dump");
if (root_node) {
e->setPlainText("Fixme!");
} else {
e->setPlainText("No CSG to dump. Please try compiling first...");
}
e->show();
e->resize(600, 400);
}
void MainWindow::actionExportSTL()
{
console->append(QString("Function %1 is not implemented yet!").arg(QString(__PRETTY_FUNCTION__)));

View File

@ -192,6 +192,13 @@ void destroy_builtin_modules()
builtin_modules.clear();
}
int AbstractNode::idx_counter;
AbstractNode::AbstractNode()
{
idx = idx_counter++;
}
AbstractNode::~AbstractNode()
{
foreach (AbstractNode *v, children)
@ -211,9 +218,27 @@ CGAL_Nef_polyhedron AbstractNode::render_cgal_nef_polyhedron() const
#endif /* ENABLE_CGAL */
#ifdef ENABLE_OPENCSG
CSGTerm *AbstractNode::render_csg_term(double m[16]) const
{
CSGTerm *t1 = NULL;
foreach(AbstractNode * v, children) {
CSGTerm *t2 = v->render_csg_term(m);
if (t2 && !t1) {
t1 = t2;
} else if (t2 && t1) {
t1 = new CSGTerm(CSGTerm::UNION, t1, t2);
}
}
return t1;
}
#endif /* ENABLE_OPENCSG */
QString AbstractNode::dump(QString indent) const
{
QString text = indent + "group() {\n";
QString text = indent + QString("n%1: group() {\n").arg(idx);
foreach (AbstractNode *v, children)
text += v->dump(indent + QString("\t"));
return text + indent + "}\n";

View File

@ -21,6 +21,16 @@
#ifndef OPENSCAD_H
#define OPENSCAD_H
// this must be defined as early as possible
// so QHash<> and friends can see it..
#include <qglobal.h>
static inline uint qHash(double v) {
// not beauty but good enough..
union { double d; uint u[2]; } x;
x.u[0] = 0; x.u[1] = 0; x.d = v;
return x.u[0] ^ x.u[1];
}
#include <QHash>
#include <QVector>
#include <QMainWindow>
@ -261,6 +271,58 @@ typedef CGAL_Nef_polyhedron::Point_3 CGAL_Point;
#endif /* ENABLE_CGAL */
class PolySet
{
public:
struct Point {
double x, y, z;
Point() : x(0), y(0), z(0) { }
Point(double x, double y, double z) : x(x), y(y), z(z) { }
};
typedef QList<Point> Polygon;
QVector<Polygon> polygons;
PolySet();
void append_poly();
void append_vertex(double x, double y, double z);
void insert_vertex(double x, double y, double z);
void render_opengl() const;
#ifdef ENABLE_CGAL
CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
};
#ifdef ENABLE_OPENCSG
class CSGTerm
{
public:
enum type_e {
PRIMITIVE,
UNION,
INTERSECTION,
DIFFERENCE
};
type_e type;
PolySet *polyset;
CSGTerm *left;
CSGTerm *right;
int refcounter;
double m[16];
CSGTerm(PolySet *polyset, double m[16]);
CSGTerm(type_e type, CSGTerm *left, CSGTerm *right);
CSGTerm *normalize(bool &changed);
CSGTerm *link();
void unlink();
};
#endif
class AbstractNode
{
public:
@ -270,13 +332,36 @@ public:
void progress_prepare();
void progress_report() const;
int idx;
static int idx_counter;
AbstractNode();
virtual ~AbstractNode();
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
#ifdef ENABLE_OPENCSG
virtual CSGTerm *render_csg_term(double m[16]) const;
#endif
virtual QString dump(QString indent) const;
};
class AbstractPolyNode : public AbstractNode
{
public:
enum render_mode_e {
RENDER_CGAL,
RENDER_OPENCSG
};
virtual PolySet *render_polyset(render_mode_e mode) const;
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
#ifdef ENABLE_OPENCSG
virtual CSGTerm *render_csg_term(double m[16]) const;
#endif
};
extern int progress_report_count;
extern void (*progress_report_f)(const class AbstractNode*, void*, int);
extern void *progress_report_vp;
@ -286,6 +371,7 @@ void progress_report_fin();
#else
// Needed for Mainwin::root_N
// this is a bit hackish - but a pointer is a pointer..
struct CGAL_Nef_polyhedron;
@ -359,7 +445,8 @@ private slots:
void actionRenderCGAL();
#endif
void actionDisplayAST();
void actionDisplayCSG();
void actionDisplayCSGTree();
void actionDisplayCSGProducts();
void actionExportSTL();
void actionExportOFF();
};

View File

@ -5,13 +5,17 @@ TEMPLATE = app
DEFINES += "ENABLE_CGAL=1"
LIBS += -lCGAL -lmpfr
DEFINES += "ENABLE_OPENCSG=1"
LIBS += -lopencsg -lGLEW
LEXSOURCES += lexer.l
YACCSOURCES += parser.y
HEADERS += openscad.h
SOURCES += openscad.cc mainwin.cc glview.cc
SOURCES += value.cc expr.cc func.cc module.cc context.cc
SOURCES += csg.cc trans.cc primitive.cc
SOURCES += csgterm.cc polyset.cc csg.cc trans.cc
SOURCES += primitive.cc
QT += opengl

154
polyset.cc Normal file
View File

@ -0,0 +1,154 @@
/*
* OpenSCAD (www.openscad.at)
* Copyright (C) 2009 Clifford Wolf <clifford@clifford.at>
*
* 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.
*
* 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
*
*/
#define INCLUDE_ABSTRACT_NODE_DETAILS
#include "openscad.h"
PolySet::PolySet()
{
}
void PolySet::append_poly()
{
polygons.append(Polygon());
}
void PolySet::append_vertex(double x, double y, double z)
{
polygons.last().append(Point(x, y, z));
}
void PolySet::insert_vertex(double x, double y, double z)
{
polygons.last().insert(0, Point(x, y, z));
}
void PolySet::render_opengl() const
{
for (int i = 0; i < polygons.size(); i++) {
const Polygon *poly = &polygons[i];
glBegin(GL_POLYGON);
for (int j = 0; j < poly->size(); j++) {
const Point *p = &poly->at(j);
glVertex3d(p->x, p->y, p->z);
}
glEnd();
}
}
#ifdef ENABLE_CGAL
class CGAL_Build_PolySet : public CGAL::Modifier_base<CGAL_HDS>
{
public:
typedef CGAL_HDS::Vertex::Point Point;
const PolySet *ps;
CGAL_Build_PolySet(const PolySet *ps) : ps(ps) { }
void operator()(CGAL_HDS& hds)
{
CGAL_Polybuilder B(hds, true);
typedef QPair<QPair<double,double>,double> PointKey_t;
#define PointKey(_x,_y,_z) PointKey_t(QPair<double,double>(_x,_y),_z)
QVector<PolySet::Point> vertices;
QHash<PointKey_t,int> vertices_idx;
for (int i = 0; i < ps->polygons.size(); i++) {
const PolySet::Polygon *poly = &ps->polygons[i];
for (int j = 0; j < poly->size(); j++) {
const PolySet::Point *p = &poly->at(j);
PointKey_t pk = PointKey(p->x, p->y, p->z);
if (!vertices_idx.contains(pk)) {
vertices_idx[pk] = vertices.size();
vertices.append(*p);
}
}
}
B.begin_surface(vertices.size(), ps->polygons.size());
for (int i = 0; i < vertices.size(); i++) {
const PolySet::Point *p = &vertices[i];
B.add_vertex(Point(p->x, p->y, p->z));
}
for (int i = 0; i < ps->polygons.size(); i++) {
const PolySet::Polygon *poly = &ps->polygons[i];
B.begin_facet();
for (int j = 0; j < poly->size(); j++) {
const PolySet::Point *p = &poly->at(j);
PointKey_t pk = PointKey(p->x, p->y, p->z);
B.add_vertex_to_facet(vertices_idx[pk]);
}
B.end_facet();
}
B.end_surface();
#undef PointKey
}
};
CGAL_Nef_polyhedron PolySet::render_cgal_nef_polyhedron() const
{
CGAL_Polyhedron P;
CGAL_Build_PolySet builder(this);
P.delegate(builder);
#if 0
std::cout << P;
#endif
CGAL_Nef_polyhedron N(P);
return N;
}
#endif /* ENABLE_CGAL */
PolySet *AbstractPolyNode::render_polyset(render_mode_e) const
{
return NULL;
}
#ifdef ENABLE_CGAL
CGAL_Nef_polyhedron AbstractPolyNode::render_cgal_nef_polyhedron() const
{
PolySet *ps = render_polyset(RENDER_CGAL);
CGAL_Nef_polyhedron N = ps->render_cgal_nef_polyhedron();
progress_report();
delete ps;
return N;
}
#endif /* ENABLE_CGAL */
#ifdef ENABLE_OPENCSG
CSGTerm *AbstractPolyNode::render_csg_term(double m[16]) const
{
PolySet *ps = render_polyset(RENDER_OPENCSG);
return new CSGTerm(ps, m);
}
#endif /* ENABLE_OPENCSG */

View File

@ -36,16 +36,14 @@ public:
virtual AbstractNode *evaluate(const Context *ctx, const QVector<QString> &call_argnames, const QVector<Value> &call_argvalues, const QVector<AbstractNode*> child_nodes) const;
};
class PrimitiveNode : public AbstractNode
class PrimitiveNode : public AbstractPolyNode
{
public:
bool center;
double x, y, z, h, r1, r2;
primitive_type_e type;
PrimitiveNode(primitive_type_e type) : type(type) { }
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
virtual PolySet *render_polyset(render_mode_e mode) const;
virtual QString dump(QString indent) const;
};
@ -134,124 +132,126 @@ void register_builtin_primitive()
builtin_modules["cylinder"] = new PrimitiveModule(CYLINDER);
}
#ifdef ENABLE_CGAL
static int cube_facets[6][4] = {
{ 0, 1, 2, 3 },
{ 7, 6, 5, 4 },
{ 4, 5, 1, 0 },
{ 5, 6, 2, 1 },
{ 6, 7, 3, 2 },
{ 7, 4, 0, 3 }
};
class CGAL_Build_cube : public CGAL::Modifier_base<CGAL_HDS>
PolySet *PrimitiveNode::render_polyset(render_mode_e mode) const
{
public:
typedef CGAL_HDS::Vertex::Point Point;
PolySet *p = new PolySet();
const PrimitiveNode *n;
CGAL_Build_cube(const PrimitiveNode *n) : n(n) { }
void operator()(CGAL_HDS& hds)
if (type == CUBE && x > 0 && y > 0 && z > 0)
{
CGAL_Polybuilder B(hds, true);
if (n->type == CUBE) {
B.begin_surface(8, 6, 24);
double x1, x2, y1, y2, z1, z2;
if (n->center) {
x1 = -n->x/2;
x2 = +n->x/2;
y1 = -n->y/2;
y2 = +n->y/2;
z1 = -n->z/2;
z2 = +n->z/2;
} else {
x1 = y1 = z1 = 0;
x2 = n->x;
y2 = n->y;
z2 = n->z;
}
B.add_vertex(Point(x1, y1, z2)); // 0
B.add_vertex(Point(x2, y1, z2)); // 1
B.add_vertex(Point(x2, y2, z2)); // 2
B.add_vertex(Point(x1, y2, z2)); // 3
B.add_vertex(Point(x1, y1, z1)); // 4
B.add_vertex(Point(x2, y1, z1)); // 5
B.add_vertex(Point(x2, y2, z1)); // 6
B.add_vertex(Point(x1, y2, z1)); // 7
for (int i = 0; i < 6; i++) {
B.begin_facet();
for (int j = 0; j < 4; j++)
B.add_vertex_to_facet(cube_facets[i][j]);
B.end_facet();
}
B.end_surface();
double x1, x2, y1, y2, z1, z2;
if (center) {
x1 = -x/2;
x2 = +x/2;
y1 = -y/2;
y2 = +y/2;
z1 = -z/2;
z2 = +z/2;
} else {
x1 = y1 = z1 = 0;
x2 = x;
y2 = y;
z2 = z;
}
if (n->type == SPHERE) {
/* FIXME */
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 (type == SPHERE && r1 > 0)
{
/* FIXME */
}
if (type == CYLINDER && h > 0 && r1 >=0 && r2 >= 0 && (r1 > 0 || r2 > 0))
{
int fragments = 10;
double z1, z2;
if (center) {
z1 = -h/2;
z2 = +h/2;
} else {
z1 = 0;
z2 = h;
}
if (n->type == CYLINDER) {
int fragments = 10;
B.begin_surface(fragments*2, fragments*2+2);
double z1, z2;
if (n->center) {
z1 = -n->h/2;
z2 = +n->h/2;
} else {
z1 = 0;
z2 = n->h;
}
for (int i=0; i<fragments; i++) {
double phi = (M_PI*2*i) / fragments;
B.add_vertex(Point(n->r1*cos(phi), n->r1*sin(phi), z1));
B.add_vertex(Point(n->r2*cos(phi), n->r2*sin(phi), z2));
}
for (int i=0; i<fragments; i++) {
B.begin_facet();
B.add_vertex_to_facet(i*2);
B.add_vertex_to_facet(i*2+1);
B.add_vertex_to_facet(((i+1)%fragments)*2);
B.end_facet();
B.begin_facet();
B.add_vertex_to_facet(i*2+1);
B.add_vertex_to_facet(((i+1)%fragments)*2+1);
B.add_vertex_to_facet(((i+1)%fragments)*2);
B.end_facet();
}
B.begin_facet();
for (int i=0; i<fragments; i++) {
B.add_vertex_to_facet(i*2);
}
B.end_facet();
B.begin_facet();
for (int i=fragments-1; i>=0; i--) {
B.add_vertex_to_facet(i*2+1);
}
B.end_facet();
B.end_surface();
struct point2d {
double x, y;
};
point2d circle1[fragments];
point2d circle2[fragments];
for (int i=0; i<fragments; i++) {
double phi = (M_PI*2*i) / fragments;
circle1[i].x = r1*cos(phi);
circle1[i].y = r1*sin(phi);
circle2[i].x = r2*cos(phi);
circle2[i].y = r2*sin(phi);
}
for (int i=0; i<fragments; i++) {
int j = (i+1) % fragments;
p->append_poly();
p->append_vertex(circle1[i].x, circle1[i].y, z1);
p->append_vertex(circle2[i].x, circle2[i].y, z2);
p->append_vertex(circle1[j].x, circle1[j].y, z1);
p->append_poly();
p->append_vertex(circle2[i].x, circle2[i].y, z2);
p->append_vertex(circle2[j].x, circle2[j].y, z2);
p->append_vertex(circle1[j].x, circle1[j].y, z1);
}
if (r1 > 0) {
p->append_poly();
for (int i=0; i<fragments; i++)
p->append_vertex(circle1[i].x, circle1[i].y, z1);
}
if (r2 > 0) {
p->append_poly();
for (int i=0; i<fragments; i++)
p->insert_vertex(circle2[i].x, circle2[i].y, z2);
}
}
};
CGAL_Nef_polyhedron PrimitiveNode::render_cgal_nef_polyhedron() const
{
CGAL_Polyhedron P;
CGAL_Build_cube builder(this);
P.delegate(builder);
#if 0
std::cout << P;
#endif
CGAL_Nef_polyhedron N(P);
progress_report();
return N;
return p;
}
#endif /* ENABLE_CGAL */
QString PrimitiveNode::dump(QString indent) const
{
QString text;
@ -261,6 +261,6 @@ QString PrimitiveNode::dump(QString indent) const
text.sprintf("sphere(r = %f);\n", r1);
if (type == CYLINDER)
text.sprintf("cylinder(h = %f, r1 = %f, r2 = %f, center = %s);\n", h, r1, r2, center ? "true" : "false");
return indent + text;
return indent + QString("n%1: ").arg(idx) + text;
}

View File

@ -73,7 +73,7 @@ CGAL_Nef_polyhedron TransNode::render_cgal_nef_polyhedron() const
QString TransNode::dump(QString indent) const
{
QString text;
text.sprintf("trans([%f %f %f])", x, y, z);
text.sprintf("n%d: trans([%f %f %f])", idx, x, y, z);
text = indent + text + " {\n";
foreach (AbstractNode *v, children)
text += v->dump(indent + QString("\t"));