summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2010-01-30 07:41:55 (GMT)
committerclifford <clifford@b57f626f-c46c-0410-a088-ec61d464b74c>2010-01-30 07:41:55 (GMT)
commitfc1914a43c9aca1f236715a57cbe1526bc34aa43 (patch)
treea44f89764ed72c5710100b5ee9c6eba7e9ce580e
parentb67fc38872af0d99da3558739b945109dc88bcb9 (diff)
Clifford Wolf:
Added projection() statement git-svn-id: http://svn.clifford.at/openscad/trunk@372 b57f626f-c46c-0410-a088-ec61d464b74c
-rw-r--r--examples/example021.scad32
-rw-r--r--openscad.pro1
-rw-r--r--src/builtin.h1
-rw-r--r--src/export.cc36
-rw-r--r--src/export.h1
-rw-r--r--src/module.cc1
-rw-r--r--src/openscad.cc2
-rw-r--r--src/projection.cc282
8 files changed, 354 insertions, 2 deletions
diff --git a/examples/example021.scad b/examples/example021.scad
new file mode 100644
index 0000000..f5dfb78
--- /dev/null
+++ b/examples/example021.scad
@@ -0,0 +1,32 @@
+
+module thing()
+{
+ $fa = 30;
+ difference() {
+ sphere(r = 25);
+ cylinder(h = 62.5, r1 = 12.5, r2 = 6.25, center = true);
+ rotate(90, [ 1, 0, 0 ]) cylinder(h = 62.5,
+ r1 = 12.5, r2 = 6.25, center = true);
+ rotate(90, [ 0, 1, 0 ]) cylinder(h = 62.5,
+ r1 = 12.5, r2 = 6.25, center = true);
+ }
+}
+
+module demo_proj()
+{
+ linear_extrude(center = true, height = 0.5) projection(cut = false) thing();
+ % thing();
+}
+
+module demo_cut()
+{
+ for (i=[-20:5:+20]) {
+ rotate(-30, [ 1, 1, 0 ]) translate([ 0, 0, -i ])
+ linear_extrude(center = true, height = 0.5) projection(cut = true)
+ translate([ 0, 0, i ]) rotate(+30, [ 1, 1, 0 ]) thing();
+ }
+ % thing();
+}
+
+translate([ -30, 0, 0 ]) demo_proj();
+translate([ +30, 0, 0 ]) demo_cut();
diff --git a/openscad.pro b/openscad.pro
index 7546667..cb8afe7 100644
--- a/openscad.pro
+++ b/openscad.pro
@@ -94,6 +94,7 @@ SOURCES += src/openscad.cc \
src/csgops.cc \
src/transform.cc \
src/primitives.cc \
+ src/projection.cc \
src/surface.cc \
src/control.cc \
src/render.cc \
diff --git a/src/builtin.h b/src/builtin.h
index dbdd818..9156adc 100644
--- a/src/builtin.h
+++ b/src/builtin.h
@@ -18,6 +18,7 @@ extern void register_builtin_surface();
extern void register_builtin_control();
extern void register_builtin_render();
extern void register_builtin_import();
+extern void register_builtin_projection();
extern void register_builtin_dxf_linear_extrude();
extern void register_builtin_dxf_rotate_extrude();
extern void initialize_builtin_dxf_dim();
diff --git a/src/export.cc b/src/export.cc
index 99419aa..840525c 100644
--- a/src/export.cc
+++ b/src/export.cc
@@ -29,6 +29,42 @@
#ifdef ENABLE_CGAL
#include "cgal.h"
+void cgal_nef3_to_polyset(PolySet *ps, CGAL_Nef_polyhedron *root_N)
+{
+ CGAL_Polyhedron P;
+ root_N->p3.convert_to_Polyhedron(P);
+
+ typedef CGAL_Polyhedron::Vertex Vertex;
+ typedef CGAL_Polyhedron::Vertex_const_iterator VCI;
+ typedef CGAL_Polyhedron::Facet_const_iterator FCI;
+ typedef CGAL_Polyhedron::Halfedge_around_facet_const_circulator HFCC;
+
+ for (FCI fi = P.facets_begin(); fi != P.facets_end(); ++fi) {
+ HFCC hc = fi->facet_begin();
+ HFCC hc_end = hc;
+ Vertex v1, v2, v3;
+ v1 = *VCI((hc++)->vertex());
+ v3 = *VCI((hc++)->vertex());
+ do {
+ v2 = v3;
+ v3 = *VCI((hc++)->vertex());
+ double x1 = CGAL::to_double(v1.point().x());
+ double y1 = CGAL::to_double(v1.point().y());
+ double z1 = CGAL::to_double(v1.point().z());
+ double x2 = CGAL::to_double(v2.point().x());
+ double y2 = CGAL::to_double(v2.point().y());
+ double z2 = CGAL::to_double(v2.point().z());
+ double x3 = CGAL::to_double(v3.point().x());
+ double y3 = CGAL::to_double(v3.point().y());
+ double z3 = CGAL::to_double(v3.point().z());
+ ps->append_poly();
+ ps->append_vertex(x1, y1, z1);
+ ps->append_vertex(x2, y2, z2);
+ ps->append_vertex(x3, y3, z3);
+ } while (hc != hc_end);
+ }
+}
+
void export_stl(CGAL_Nef_polyhedron *root_N, QString filename, QProgressDialog *pd)
{
CGAL_Polyhedron P;
diff --git a/src/export.h b/src/export.h
index 49319ba..619d9e0 100644
--- a/src/export.h
+++ b/src/export.h
@@ -2,6 +2,7 @@
#define EXPORT_H_
#ifdef ENABLE_CGAL
+void cgal_nef3_to_polyset(PolySet *ps, CGAL_Nef_polyhedron *root_N);
void export_stl(class CGAL_Nef_polyhedron *root_N, QString filename, class QProgressDialog *pd);
void export_off(CGAL_Nef_polyhedron *root_N, QString filename, QProgressDialog *pd);
void export_dxf(CGAL_Nef_polyhedron *root_N, QString filename, QProgressDialog *pd);
diff --git a/src/module.cc b/src/module.cc
index 6352658..f2c6e94 100644
--- a/src/module.cc
+++ b/src/module.cc
@@ -194,6 +194,7 @@ void initialize_builtin_modules()
register_builtin_control();
register_builtin_render();
register_builtin_import();
+ register_builtin_projection();
register_builtin_dxf_linear_extrude();
register_builtin_dxf_rotate_extrude();
}
diff --git a/src/openscad.cc b/src/openscad.cc
index 8c0db68..09e6f8c 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -18,8 +18,6 @@
*
*/
-#define INCLUDE_ABSTRACT_NODE_DETAILS
-
#include "openscad.h"
#include "MainWindow.h"
#include "node.h"
diff --git a/src/projection.cc b/src/projection.cc
new file mode 100644
index 0000000..d2f417c
--- /dev/null
+++ b/src/projection.cc
@@ -0,0 +1,282 @@
+/*
+ * 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
+ *
+ */
+
+#include "module.h"
+#include "node.h"
+#include "context.h"
+#include "printutils.h"
+#include "builtin.h"
+#include "dxfdata.h"
+#include "dxftess.h"
+#include "polyset.h"
+#include "export.h"
+#include "openscad.h" // get_fragments_from_r()
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include <QApplication>
+#include <QTime>
+#include <QProgressDialog>
+
+class ProjectionModule : public AbstractModule
+{
+public:
+ ProjectionModule() { }
+ virtual AbstractNode *evaluate(const Context *ctx, const ModuleInstantiation *inst) const;
+};
+
+class ProjectionNode : public AbstractPolyNode
+{
+public:
+ int convexity;
+ bool cut_mode;
+ ProjectionNode(const ModuleInstantiation *mi) : AbstractPolyNode(mi) {
+ cut_mode = false;
+ }
+ virtual PolySet *render_polyset(render_mode_e mode) const;
+ virtual QString dump(QString indent) const;
+};
+
+AbstractNode *ProjectionModule::evaluate(const Context *ctx, const ModuleInstantiation *inst) const
+{
+ ProjectionNode *node = new ProjectionNode(inst);
+
+ QVector<QString> argnames = QVector<QString>() << "cut";
+ QVector<Expression*> argexpr;
+
+ Context c(ctx);
+ c.args(argnames, argexpr, inst->argnames, inst->argvalues);
+
+ Value convexity = c.lookup_variable("convexity", true);
+ Value cut = c.lookup_variable("cut", true);
+
+ node->convexity = (int)convexity.num;
+
+ if (cut.type == Value::BOOL)
+ node->cut_mode = cut.b;
+
+ foreach (ModuleInstantiation *v, inst->children) {
+ AbstractNode *n = v->evaluate(inst->ctx);
+ if (n)
+ node->children.append(n);
+ }
+
+ return node;
+}
+
+void register_builtin_projection()
+{
+ builtin_modules["projection"] = new ProjectionModule();
+}
+
+static void report_func(const class AbstractNode*, void *vp, int mark)
+{
+ QProgressDialog *pd = (QProgressDialog*)vp;
+ int v = (int)((mark*100.0) / progress_report_count);
+ pd->setValue(v < 100 ? v : 99);
+ QString label;
+ label.sprintf("Rendering Polygon Mesh using CGAL (%d/%d)", mark, progress_report_count);
+ pd->setLabelText(label);
+ QApplication::processEvents();
+}
+
+PolySet *ProjectionNode::render_polyset(render_mode_e rm) const
+{
+ QString key = mk_cache_id();
+ if (PolySet::ps_cache.contains(key)) {
+ PRINT(PolySet::ps_cache[key]->msg);
+ return PolySet::ps_cache[key]->ps->link();
+ }
+
+ print_messages_push();
+
+ QTime t;
+ QProgressDialog *pd = NULL;
+
+ if (rm == RENDER_OPENCSG)
+ {
+ PRINT_NOCACHE("Processing uncached projection body...");
+ QApplication::processEvents();
+
+ t.start();
+ pd = new QProgressDialog("Rendering Polygon Mesh using CGAL...", QString(), 0, 100);
+ pd->setValue(0);
+ pd->setAutoClose(false);
+ pd->show();
+ QApplication::processEvents();
+
+ progress_report_prep((AbstractNode*)this, report_func, pd);
+ }
+
+ CGAL_Nef_polyhedron N;
+ N.dim = 3;
+ foreach(AbstractNode *v, this->children) {
+ if (v->modinst->tag_background)
+ continue;
+ N.p3 += v->render_cgal_nef_polyhedron().p3;
+ }
+
+ if (rm == RENDER_OPENCSG) {
+ progress_report_fin();
+ int s = t.elapsed() / 1000;
+ PRINTF_NOCACHE("..rendering time: %d hours, %d minutes, %d seconds", s / (60*60), (s / 60) % 60, s % 60);
+ delete pd;
+ }
+
+ PolySet *ps = new PolySet();
+ ps->convexity = this->convexity;
+ ps->is2d = true;
+
+ if (cut_mode)
+ {
+ PolySet *cube = new PolySet();
+ double infval = 1e8, eps = 0.1;
+ double x1 = -infval, x2 = +infval, y1 = -infval, y2 = +infval, z1 = 0, z2 = eps;
+
+ cube->append_poly(); // top
+ cube->append_vertex(x1, y1, z2);
+ cube->append_vertex(x2, y1, z2);
+ cube->append_vertex(x2, y2, z2);
+ cube->append_vertex(x1, y2, z2);
+
+ cube->append_poly(); // bottom
+ cube->append_vertex(x1, y2, z1);
+ cube->append_vertex(x2, y2, z1);
+ cube->append_vertex(x2, y1, z1);
+ cube->append_vertex(x1, y1, z1);
+
+ cube->append_poly(); // side1
+ cube->append_vertex(x1, y1, z1);
+ cube->append_vertex(x2, y1, z1);
+ cube->append_vertex(x2, y1, z2);
+ cube->append_vertex(x1, y1, z2);
+
+ cube->append_poly(); // side2
+ cube->append_vertex(x2, y1, z1);
+ cube->append_vertex(x2, y2, z1);
+ cube->append_vertex(x2, y2, z2);
+ cube->append_vertex(x2, y1, z2);
+
+ cube->append_poly(); // side3
+ cube->append_vertex(x2, y2, z1);
+ cube->append_vertex(x1, y2, z1);
+ cube->append_vertex(x1, y2, z2);
+ cube->append_vertex(x2, y2, z2);
+
+ cube->append_poly(); // side4
+ cube->append_vertex(x1, y2, z1);
+ cube->append_vertex(x1, y1, z1);
+ cube->append_vertex(x1, y1, z2);
+ cube->append_vertex(x1, y2, z2);
+ CGAL_Nef_polyhedron Ncube = cube->render_cgal_nef_polyhedron();
+ cube->unlink();
+
+ PolySet *ps3 = new PolySet();
+ // N.p3 *= CGAL_Nef_polyhedron3(CGAL_Plane(0, 0, 1, 0), CGAL_Nef_polyhedron3::INCLUDED);
+ N.p3 *= Ncube.p3;
+ cgal_nef3_to_polyset(ps3, &N);
+ for (int i = 0; i < ps3->polygons.size(); i++) {
+ for (int j = 0; j < ps3->polygons[i].size(); j++) {
+ if (ps3->polygons[i][j].z != 0)
+ goto next_ps3_polygon_cut_mode;
+ }
+ ps->append_poly();
+ for (int j = 0; j < ps3->polygons[i].size(); j++) {
+ ps->insert_vertex(ps3->polygons[i][j].x, ps3->polygons[i][j].y);
+ }
+ next_ps3_polygon_cut_mode:;
+ }
+ ps3->unlink();
+ }
+ else
+ {
+ PolySet *ps3 = new PolySet();
+ cgal_nef3_to_polyset(ps3, &N);
+ CGAL_Nef_polyhedron np;
+ np.dim = 2;
+ for (int i = 0; i < ps3->polygons.size(); i++)
+ {
+ int min_x_p = -1;
+ double min_x_val = 0;
+ for (int j = 0; j < ps3->polygons[i].size(); j++) {
+ double x = ps3->polygons[i][j].x;
+ if (min_x_p < 0 || x < min_x_val) {
+ min_x_p = j;
+ min_x_val = x;
+ }
+ }
+ int min_x_p1 = (min_x_p+1) % ps3->polygons[i].size();
+ int min_x_p2 = (min_x_p+ps3->polygons[i].size()-1) % ps3->polygons[i].size();
+ double ax = ps3->polygons[i][min_x_p1].x - ps3->polygons[i][min_x_p].x;
+ double ay = ps3->polygons[i][min_x_p1].y - ps3->polygons[i][min_x_p].y;
+ double at = atan2(ay, ax);
+ double bx = ps3->polygons[i][min_x_p2].x - ps3->polygons[i][min_x_p].x;
+ double by = ps3->polygons[i][min_x_p2].y - ps3->polygons[i][min_x_p].y;
+ double bt = atan2(by, bx);
+
+ double eps = 0.000001;
+ if (fabs(at - bt) < eps || (fabs(ax) < eps && fabs(ay) < eps) ||
+ (fabs(bx) < eps && fabs(by) < eps)) {
+ // this triangle is degenerated in projection
+ continue;
+ }
+
+ std::list<CGAL_Nef_polyhedron2::Point> plist;
+ for (int j = 0; j < ps3->polygons[i].size(); j++) {
+ double x = ps3->polygons[i][j].x;
+ double y = ps3->polygons[i][j].y;
+ CGAL_Nef_polyhedron2::Point p = CGAL_Nef_polyhedron2::Point(x, y);
+ if (at > bt)
+ plist.push_front(p);
+ else
+ plist.push_back(p);
+ }
+ np.p2 += CGAL_Nef_polyhedron2(plist.begin(), plist.end(),
+ CGAL_Nef_polyhedron2::INCLUDED);
+ }
+ DxfData dxf(np);
+ dxf_tesselate(ps, &dxf, 0, true, false, 0);
+ dxf_border_to_ps(ps, &dxf);
+ ps3->unlink();
+ }
+
+ PolySet::ps_cache.insert(key, new PolySet::ps_cache_entry(ps->link()));
+ print_messages_pop();
+
+ return ps;
+}
+
+QString ProjectionNode::dump(QString indent) const
+{
+ if (dump_cache.isEmpty()) {
+ QString text;
+ text.sprintf("projection(cut = %s, convexity = %d) {\n",
+ this->cut_mode ? "true" : "false", 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;
+}
+
contact: Jan Huwald // Impressum