Skip to content

Commit

Permalink
Clifford Wolf:
Browse files Browse the repository at this point in the history
	Added cgaladv.cc with advanced transformations via CGAL
	(as of now only 3d minkowksi sum is implemented but more is planned)



git-svn-id: http://svn.clifford.at/openscad/trunk@446 b57f626f-c46c-0410-a088-ec61d464b74c
  • Loading branch information
clifford committed Feb 20, 2010
1 parent 0b0aa7b commit 332e835
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 6 deletions.
1 change: 1 addition & 0 deletions openscad.pro
Expand Up @@ -113,6 +113,7 @@ SOURCES += src/openscad.cc \
src/transform.cc \
src/primitives.cc \
src/projection.cc \
src/cgaladv.cc \
src/surface.cc \
src/control.cc \
src/render.cc \
Expand Down
1 change: 1 addition & 0 deletions src/builtin.h
Expand Up @@ -19,6 +19,7 @@ extern void register_builtin_control();
extern void register_builtin_render();
extern void register_builtin_import();
extern void register_builtin_projection();
extern void register_builtin_cgaladv();
extern void register_builtin_dxf_linear_extrude();
extern void register_builtin_dxf_rotate_extrude();
extern void initialize_builtin_dxf_dim();
Expand Down
36 changes: 36 additions & 0 deletions src/cgal.h
Expand Up @@ -45,6 +45,42 @@ struct CGAL_Nef_polyhedron
p3 = p;
}

CGAL_Nef_polyhedron& operator+=(const CGAL_Nef_polyhedron &other) {
if (other.dim == 2) {
this->p2 += other.p2;
this->dim = 2;
}
if (other.dim == 3) {
this->p3 += other.p3;
this->dim = 3;
}
return *this;
}

CGAL_Nef_polyhedron& operator*=(const CGAL_Nef_polyhedron &other) {
if (other.dim == 2) {
this->p2 *= other.p2;
this->dim = 2;
}
if (other.dim == 3) {
this->p3 *= other.p3;
this->dim = 3;
}
return *this;
}

CGAL_Nef_polyhedron& operator-=(const CGAL_Nef_polyhedron &other) {
if (other.dim == 2) {
this->p2 -= other.p2;
this->dim = 2;
}
if (other.dim == 3) {
this->p3 -= other.p3;
this->dim = 3;
}
return *this;
}

int weight() {
if (dim == 2)
return p2.explorer().number_of_vertices();
Expand Down
224 changes: 224 additions & 0 deletions src/cgaladv.cc
@@ -0,0 +1,224 @@
/*
* 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.
*
* 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
*
*/

#include "module.h"
#include "node.h"
#include "context.h"
#include "builtin.h"
#include "printutils.h"
#include "cgal.h"

#include <CGAL/minkowski_sum_3.h>

enum cgaladv_type_e {
MINKOWSKI,
GLIDE,
SUBDIV
};

class CgaladvModule : public AbstractModule
{
public:
cgaladv_type_e type;
CgaladvModule(cgaladv_type_e type) : type(type) { }
virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
};

class CgaladvNode : public AbstractNode
{
public:
Value path;
QString subdiv_type;
int convexity, level;
cgaladv_type_e type;
CgaladvNode(const ModuleInstantiation *mi, cgaladv_type_e type) : AbstractNode(mi), type(type) {
convexity = 1;
}
#ifdef ENABLE_CGAL
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
#endif
virtual CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
virtual QString dump(QString indent) const;
};

AbstractNode *CgaladvModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
{
CgaladvNode *node = new CgaladvNode(inst, type);

QVector<QString> argnames;
QVector<Expression*> argexpr;

if (type == MINKOWSKI)
argnames = QVector<QString>() << "convexity";

if (type == GLIDE)
argnames = QVector<QString>() << "path" << "convexity";

if (type == SUBDIV)
argnames = QVector<QString>() << "type" << "level" << "convexity";

Context c(ctx);
c.args(argnames, argexpr, inst->argnames, inst->argvalues);

Value convexity, path, subdiv_type, level;

if (type == MINKOWSKI) {
convexity = c.lookup_variable("convexity", true);
}

if (type == GLIDE) {
convexity = c.lookup_variable("convexity", true);
path = c.lookup_variable("path", false);
}

if (type == SUBDIV) {
convexity = c.lookup_variable("convexity", true);
subdiv_type = c.lookup_variable("type", false);
level = c.lookup_variable("level", true);
}

node->convexity = (int)convexity.num;
node->path = path;
node->subdiv_type = subdiv_type.text;
node->level = (int)level.num;

if (node->level <= 1)
node->level = 1;

foreach (ModuleInstantiation *v, inst->children) {
AbstractNode *n = v->evaluate(inst->ctx);
if (n)
node->children.append(n);
}

return node;
}

void register_builtin_cgaladv()
{
builtin_modules["minkowski"] = new CgaladvModule(MINKOWSKI);
builtin_modules["glide"] = new CgaladvModule(GLIDE);
builtin_modules["subdiv"] = new CgaladvModule(SUBDIV);
}

#ifdef ENABLE_CGAL

CGAL_Nef_polyhedron CgaladvNode::render_cgal_nef_polyhedron() const
{
QString cache_id = mk_cache_id();
if (cgal_nef_cache.contains(cache_id)) {
progress_report();
PRINT(cgal_nef_cache[cache_id]->msg);
return cgal_nef_cache[cache_id]->N;
}

print_messages_push();
CGAL_Nef_polyhedron N;

if (type == MINKOWSKI)
{
bool first = true;
CGAL_Nef_polyhedron a, b;
foreach(AbstractNode * v, children) {
if (v->modinst->tag_background)
continue;
if (first) {
a = v->render_cgal_nef_polyhedron();
if (a.dim != 0)
first = false;
} else {
b += v->render_cgal_nef_polyhedron();
}
}
if (a.dim == 3 && b.dim == 3) {
N.dim = 3;
N.p3 = CGAL::minkowski_sum_3(a.p3, b.p3);
}
if (a.dim == 2 && b.dim == 2) {
PRINT("WARNING: minkowski() is not implemented yet for 2d objects!");
}
}

if (type == GLIDE)
{
PRINT("WARNING: subdiv() is not implemented yet!");
}

if (type == SUBDIV)
{
PRINT("WARNING: subdiv() is not implemented yet!");
}

cgal_nef_cache.insert(cache_id, new cgal_nef_cache_entry(N), N.weight());
print_messages_pop();
progress_report();

return N;
}

CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
if (type == MINKOWSKI)
return render_csg_term_from_nef(m, highlights, background, "minkowski", this->convexity);

if (type == GLIDE)
return render_csg_term_from_nef(m, highlights, background, "glide", this->convexity);

if (type == SUBDIV)
return render_csg_term_from_nef(m, highlights, background, "subdiv", this->convexity);

return NULL;
}

#else // ENABLE_CGAL

CSGTerm *CgaladvNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
PRINT("WARNING: Found minkowski(), glide() or subdiv() statement but compiled without CGAL support!");
return NULL;
}

#endif // ENABLE_CGAL

QString CgaladvNode::dump(QString indent) const
{
if (dump_cache.isEmpty()) {
QString text;
if (type == MINKOWSKI)
text.sprintf("minkowski(convexity = %d) {\n", this->convexity);
if (type == GLIDE) {
text.sprintf(", convexity = %d) {\n", this->convexity);
text = QString("glide(path = ") + this->path.dump() + text;
}
if (type == SUBDIV)
text.sprintf("subdiv(level = %d, convexity = %d) {\n", this->level, this->convexity);
foreach (AbstractNode *v, this->children)
text += v->dump(indent + QString("\t"));
text += indent + "}\n";
((AbstractNode*)this)->dump_cache = indent + QString("n%1: ").arg(idx) + text;
}
return dump_cache;
}

2 changes: 1 addition & 1 deletion src/dxflinextrude.cc
Expand Up @@ -210,7 +210,7 @@ static void add_slice(PolySet *ps, DxfData::Path *pt, double rot1, double rot2,
}
}

PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e rm) const
PolySet *DxfLinearExtrudeNode::render_polyset(render_mode_e) const
{
QString key = mk_cache_id();
if (PolySet::ps_cache.contains(key)) {
Expand Down
2 changes: 1 addition & 1 deletion src/dxfrotextrude.cc
Expand Up @@ -113,7 +113,7 @@ void register_builtin_dxf_rotate_extrude()
builtin_modules["rotate_extrude"] = new DxfRotateExtrudeModule();
}

PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e rm) const
PolySet *DxfRotateExtrudeNode::render_polyset(render_mode_e) const
{
QString key = mk_cache_id();
if (PolySet::ps_cache.contains(key)) {
Expand Down
1 change: 1 addition & 0 deletions src/module.cc
Expand Up @@ -206,6 +206,7 @@ void initialize_builtin_modules()
register_builtin_render();
register_builtin_import();
register_builtin_projection();
register_builtin_cgaladv();
register_builtin_dxf_linear_extrude();
register_builtin_dxf_rotate_extrude();
}
Expand Down
1 change: 1 addition & 0 deletions src/node.h
Expand Up @@ -42,6 +42,7 @@ class AbstractNode
};
static QCache<QString, cgal_nef_cache_entry> cgal_nef_cache;
virtual CGAL_Nef_polyhedron render_cgal_nef_polyhedron() const;
class CSGTerm *render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const;
#endif
virtual class CSGTerm *render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const;
virtual QString dump(QString indent) const;
Expand Down
2 changes: 1 addition & 1 deletion src/projection.cc
Expand Up @@ -96,7 +96,7 @@ void register_builtin_projection()

#ifdef ENABLE_CGAL

PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
PolySet *ProjectionNode::render_polyset(render_mode_e) const
{
QString key = mk_cache_id();
if (PolySet::ps_cache.contains(key)) {
Expand Down
11 changes: 8 additions & 3 deletions src/render.cc
Expand Up @@ -125,7 +125,7 @@ CGAL_Nef_polyhedron RenderNode::render_cgal_nef_polyhedron() const
return N;
}

CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
CSGTerm *AbstractNode::render_csg_term_from_nef(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background, const char *statement, int convexity) const
{
QString key = mk_cache_id();
if (PolySet::ps_cache.contains(key)) {
Expand All @@ -145,7 +145,7 @@ CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights
}
else
{
PRINT_NOCACHE("Processing uncached render statement...");
PRINTF_NOCACHE("Processing uncached %s statement...", statement);
// PRINTA("Cache ID: %1", cache_id);
QApplication::processEvents();

Expand All @@ -172,7 +172,7 @@ CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights
if (N.dim == 3)
{
if (!N.p3.is_simple()) {
PRINTF("WARNING: Result of render() isn't valid 2-manifold! Modify your design..");
PRINTF("WARNING: Result of %s() isn't valid 2-manifold! Modify your design..", statement);
return NULL;
}

Expand Down Expand Up @@ -219,6 +219,11 @@ CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights
return NULL;
}

CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
{
return render_csg_term_from_nef(m, highlights, background, "render", this->convexity);
}

#else

CSGTerm *RenderNode::render_csg_term(double m[20], QVector<CSGTerm*> *highlights, QVector<CSGTerm*> *background) const
Expand Down

0 comments on commit 332e835

Please sign in to comment.