summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarius Kintel <marius@kintel.net>2013-12-09 04:12:13 (GMT)
committerMarius Kintel <marius@kintel.net>2013-12-09 04:12:13 (GMT)
commit462d4d447885594629fefb8a658f9f1d079bcc44 (patch)
tree6690951e4f814b87a1a372a913b75ceda1f6cc1a /src
parent435e0c021c5018ee5de69d3218c3e31c8ab75be5 (diff)
parent33c34b6f7c43d19bbfa3bf91e7b577bcc062e5bd (diff)
Merge branch 'master' into travis
Diffstat (limited to 'src')
-rw-r--r--src/AboutDialog.html2
-rw-r--r--src/CGALEvaluator.cc18
-rw-r--r--src/CGAL_Nef3_workaround.h352
-rw-r--r--src/CGAL_Nef_polyhedron.cc19
-rw-r--r--src/CocoaUtils.mm4
-rw-r--r--src/MainWindow.h1
-rw-r--r--src/MainWindow.ui7
-rw-r--r--src/PlatformUtils.cc2
-rw-r--r--src/PolySetCGALEvaluator.cc9
-rw-r--r--src/QGLView.cc11
-rw-r--r--src/QGLView.h1
-rw-r--r--src/cgal.h8
-rw-r--r--src/control.cc24
-rw-r--r--src/dxfdata.h4
-rw-r--r--src/editor.cc14
-rw-r--r--src/editor.h2
-rw-r--r--src/export.cc10
-rw-r--r--src/expr.cc23
-rw-r--r--src/linalg.h5
-rw-r--r--src/mainwin.cc8
-rw-r--r--src/modcontext.cc2
-rw-r--r--src/openscad.cc9
-rw-r--r--src/parser.y2
-rw-r--r--src/stl-utils.cc2
-rw-r--r--src/value.cc102
-rw-r--r--src/value.h76
-rw-r--r--src/version_check.h14
27 files changed, 655 insertions, 76 deletions
diff --git a/src/AboutDialog.html b/src/AboutDialog.html
index b5a5d7c..99e7c3b 100644
--- a/src/AboutDialog.html
+++ b/src/AboutDialog.html
@@ -47,7 +47,7 @@ Please visit this link for a copy of the license: <a href="http://www.gnu.org/li
<li><a href="http://gmplib.org/">GNU GMP</a>
<li><a href="http://www.mpfr.org/">GNU MPFR</a>
<li><a href="http://www.cgal.org">CGAL</a>
-<li><a href="http://eigen.tuxfamily.org">Eigen2</a>
+<li><a href="http://eigen.tuxfamily.org">Eigen</a>
<li><a href="http://www.opencsg.org">OpenCSG</a>
<li><a href="http://www.opengl.org/">OpenGL</a>
<li><a href="http://glew.sourceforge.net">GLEW</a>
diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc
index ec01315..86118d7 100644
--- a/src/CGALEvaluator.cc
+++ b/src/CGALEvaluator.cc
@@ -159,9 +159,21 @@ CGAL_Nef_polyhedron CGALEvaluator::applyHull(const CgaladvNode &node)
PRINT("Hull() currently requires a valid 2-manifold. Please modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export");
}
else {
- chN.p3->convert_to_Polyhedron(P);
- std::transform(P.vertices_begin(), P.vertices_end(), std::back_inserter(points3d),
- boost::bind(static_cast<const CGAL_Polyhedron::Vertex::Point_3&(CGAL_Polyhedron::Vertex::*)() const>(&CGAL_Polyhedron::Vertex::point), _1));
+ bool err = false;
+ std::string errmsg("");
+ try {
+ err = nefworkaround::convert_to_Polyhedron<CGAL_Kernel3>( *(chN.p3), P );
+ //chN.p3->convert_to_Polyhedron(P);
+ } catch (const CGAL::Failure_exception &e) {
+ err = true;
+ errmsg = std::string(e.what());
+ }
+ if (err) {
+ PRINTB("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed. %s", errmsg);
+ } else {
+ std::transform(P.vertices_begin(), P.vertices_end(), std::back_inserter(points3d),
+ boost::bind(static_cast<const CGAL_Polyhedron::Vertex::Point_3&(CGAL_Polyhedron::Vertex::*)() const>(&CGAL_Polyhedron::Vertex::point), _1));
+ }
}
}
chnode->progress_report();
diff --git a/src/CGAL_Nef3_workaround.h b/src/CGAL_Nef3_workaround.h
new file mode 100644
index 0000000..c2482ac
--- /dev/null
+++ b/src/CGAL_Nef3_workaround.h
@@ -0,0 +1,352 @@
+// Copyright (c) 1997-2002,2005 Max-Planck-Institute Saarbruecken (Germany).
+// All rights reserved.
+//
+// This file is part of CGAL (www.cgal.org).
+// 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 3 of the License, or (at your option) any later version.
+//
+// Licensees holding a valid commercial license may use this file in
+// accordance with the commercial license agreement provided with the software.
+//
+// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/releases/CGAL-4.0-branch/Nef_3/include/CGAL/Nef_helper_3.h $
+// $Id: Nef_helper_3.h 67117 2012-01-13 18:14:48Z lrineau $
+//
+//
+// Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
+// Miguel Granados <granados@mpi-sb.mpg.de>
+// Susan Hert <hert@mpi-sb.mpg.de>
+// Lutz Kettner <kettner@mpi-sb.mpg.de>
+// Ralf Osbild <osbild@mpi-sb.mpg.de>
+// Peter Hachenberger <hachenberger@mpi-sb.mpg.de>
+
+/*
+ modified by don bright for OpenSCAD, 2013.
+
+This works around issue #410, where CGAL's Nef_Polyhedron3.convert_to_Polyhedron
+throws an uncatchable exception, due to an CGAL_Assertion being thrown in
+Polyhedron Incremental Builder's destructor while a Triangulation exception
+is still active, resulting in program termination (crashing).
+
+The purpose here is not to improve/change the way CGAL's Nef code works,
+but instead to tweak it slightly to prevent OpenSCAD from crashing. The
+behavior of the code should otherwise be exactly the same as CGAL's standard
+code.
+
+This file was created by copying three sections
+from CGAL's Nef_polyhedron3.h that were protected/private:
+
+ Triangulation_handler2
+ Build_Polyhedron
+ convert_to_polyhedron
+
+Very small code changes have been made. First, there are many template
+type specifiers added to enable the movement of the code to the outside
+of the Nef Polyhedron class. Second, there is a try{}catch(...){} block
+added in the Builder around the Triangulation code. Third, there is an error
+variable added for non-Exception communication with the caller.
+
+Eventually, if CGAL itself is updated and the update is widely
+distributed, this file may become obsolete and can be deleted from OpenSCAD
+
+*/
+
+
+#ifndef _CGAL_NEF3_WORKAROUND_H
+#define _CGAL_NEF3_WORKAROUND_H
+
+#include <CGAL/Polyhedron_incremental_builder_3.h>
+#include <CGAL/Polyhedron_3.h>
+#include <CGAL/assertions.h>
+
+#include <CGAL/Constrained_triangulation_2.h>
+#include <CGAL/Triangulation_data_structure_2.h>
+#include <CGAL/Projection_traits_xy_3.h>
+#include <CGAL/Projection_traits_yz_3.h>
+#include <CGAL/Projection_traits_xz_3.h>
+#include <CGAL/Constrained_triangulation_face_base_2.h>
+
+#include "printutils.h"
+
+namespace nefworkaround {
+
+template<typename Kernel, typename Nef>
+class Triangulation_handler2 {
+
+ typedef typename CGAL::Triangulation_vertex_base_2<Kernel> Vb;
+ typedef typename CGAL::Constrained_triangulation_face_base_2<Kernel> Fb;
+ typedef typename CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
+ typedef typename CGAL::Constrained_triangulation_2<Kernel,TDS> CT;
+
+ typedef typename CT::Face_handle Face_handle;
+ typedef typename CT::Vertex_handle CTVertex_handle;
+ typedef typename CT::Finite_faces_iterator Finite_face_iterator;
+ typedef typename CT::Edge Edge;
+ CT ct;
+ CGAL::Unique_hash_map<Face_handle, bool> visited;
+ CGAL::Unique_hash_map<CTVertex_handle, typename Nef::Vertex_const_handle> ctv2v;
+ Finite_face_iterator fi;
+ typename Nef::Plane_3 supporting_plane;
+
+ public:
+ Triangulation_handler2(typename Nef::Halffacet_const_handle f) :
+ visited(false), supporting_plane(f->plane()) {
+
+ typename Nef::Halffacet_cycle_const_iterator fci;
+ for(fci=f->facet_cycles_begin(); fci!=f->facet_cycles_end(); ++fci) {
+ if(fci.is_shalfedge()) {
+ typename Nef::SHalfedge_around_facet_const_circulator sfc(fci), send(sfc);
+ CGAL_For_all(sfc,send) {
+ CGAL_NEF_TRACEN(" insert point" << sfc->source()->source()->point());
+ CTVertex_handle ctv = ct.insert(sfc->source()->source()->point());
+ ctv2v[ctv] = sfc->source()->source();
+ }
+ }
+ }
+
+ for(fci=f->facet_cycles_begin(); fci!=f->facet_cycles_end(); ++fci) {
+ if(fci.is_shalfedge()) {
+ typename Nef::SHalfedge_around_facet_const_circulator sfc(fci), send(sfc);
+ CGAL_For_all(sfc,send) {
+ CGAL_NEF_TRACEN(" insert constraint" << sfc->source()->source()->point()
+ << "->" << sfc->source()->twin()->source()->point());
+ ct.insert_constraint(sfc->source()->source()->point(),
+ sfc->source()->twin()->source()->point());
+ }
+ }
+ }
+ CGAL_assertion(ct.is_valid());
+
+ CGAL_NEF_TRACEN("number of finite triangles " << ct.number_of_faces());
+
+ typename CT::Face_handle infinite = ct.infinite_face();
+ typename CT::Vertex_handle ctv = infinite->vertex(1);
+ if(ct.is_infinite(ctv)) ctv = infinite->vertex(2);
+ CGAL_assertion(!ct.is_infinite(ctv));
+
+ typename CT::Face_handle opposite;
+ typename CT::Face_circulator vc(ctv,infinite);
+ do { opposite = vc++;
+ } while(!ct.is_constrained(typename CT::Edge(vc,vc->index(opposite))));
+ typename CT::Face_handle first = vc;
+
+ CGAL_assertion(!ct.is_infinite(first));
+ traverse_triangulation(first, first->index(opposite));
+
+ fi = ct.finite_faces_begin();
+ }
+
+ void traverse_triangulation(Face_handle f, int parent) {
+ visited[f] = true;
+ if(!ct.is_constrained(Edge(f,ct.cw(parent))) && !visited[f->neighbor(ct.cw(parent))]) {
+ Face_handle child(f->neighbor(ct.cw(parent)));
+ traverse_triangulation(child, child->index(f));
+ }
+ if(!ct.is_constrained(Edge(f,ct.ccw(parent))) && !visited[f->neighbor(ct.ccw(parent))]) {
+ Face_handle child(f->neighbor(ct.ccw(parent)));
+ traverse_triangulation(child, child->index(f));
+ }
+ }
+
+ template<typename Triangle_3>
+ bool get_next_triangle(Triangle_3& tr) {
+ while(fi != ct.finite_faces_end() && visited[fi] == false) ++fi;
+ if(fi == ct.finite_faces_end()) return false;
+ tr = Triangle_3(fi->vertex(0)->point(), fi->vertex(1)->point(), fi->vertex(2)->point());
+ ++fi;
+ return true;
+ }
+
+ bool same_orientation(typename Nef::Plane_3 p1) const {
+ if(p1.a() != 0)
+ return CGAL::sign(p1.a()) == CGAL::sign(supporting_plane.a());
+ if(p1.b() != 0)
+ return CGAL::sign(p1.b()) == CGAL::sign(supporting_plane.b());
+ return CGAL::sign(p1.c()) == CGAL::sign(supporting_plane.c());
+ }
+
+ template<typename PIB, typename Index>
+ void handle_triangles(PIB& pib, Index& VI) {
+ while(fi != ct.finite_faces_end() && visited[fi] == false) ++fi;
+ while(fi != ct.finite_faces_end()) {
+ typename Nef::Plane_3 plane(fi->vertex(0)->point(),
+ fi->vertex(1)->point(),
+ fi->vertex(2)->point());
+ pib.begin_facet();
+ if(same_orientation(plane)) {
+ pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(0)]]);
+ pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(1)]]);
+ pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(2)]]);
+ } else {
+ pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(0)]]);
+ pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(2)]]);
+ pib.add_vertex_to_facet(VI[ctv2v[fi->vertex(1)]]);
+ }
+ pib.end_facet();
+ do {
+ ++fi;
+ } while(fi != ct.finite_faces_end() && visited[fi] == false);
+ }
+ }
+};
+
+
+
+
+
+
+
+
+template <class HDS, typename Kernel, typename Nef>
+class Build_polyhedron : public CGAL::Modifier_base<HDS> {
+public:
+ bool error; // added for OpenSCAD
+ class Visitor {
+ typedef typename CGAL::Projection_traits_xy_3<Kernel> XY;
+ typedef typename CGAL::Projection_traits_yz_3<Kernel> YZ;
+ typedef typename CGAL::Projection_traits_xz_3<Kernel> XZ;
+
+ const CGAL::Object_index<typename Nef::Vertex_const_iterator>& VI;
+ CGAL::Polyhedron_incremental_builder_3<HDS>& B;
+ const typename Nef::SNC_const_decorator& D;
+
+ public:
+ bool error;//added for OpenSCAD
+ Visitor(CGAL::Polyhedron_incremental_builder_3<HDS>& BB,
+ const typename Nef::SNC_const_decorator& sd,
+ CGAL::Object_index<typename Nef::Vertex_const_iterator>& vi) : VI(vi), B(BB), D(sd), error(false) {}
+
+ void visit(typename Nef::Halffacet_const_handle opposite_facet) {
+
+ CGAL_NEF_TRACEN("Build_polyhedron: visit facet " << opposite_facet->plane());
+
+ CGAL_assertion(Nef::Infi_box::is_standard(opposite_facet->plane()));
+
+ typename Nef::SHalfedge_const_handle se;
+ typename Nef::Halffacet_cycle_const_iterator fc;
+
+ typename Nef::Halffacet_const_handle f = opposite_facet->twin();
+
+ typename Nef::SHalfedge_around_facet_const_circulator
+ sfc1(f->facet_cycles_begin()), sfc2(sfc1);
+
+ if(++f->facet_cycles_begin() != f->facet_cycles_end() ||
+ ++(++(++sfc1)) != sfc2) {
+ typename Nef::Vector_3 orth = f->plane().orthogonal_vector();
+ int c = CGAL::abs(orth[0]) > CGAL::abs(orth[1]) ? 0 : 1;
+ c = CGAL::abs(orth[2]) > CGAL::abs(orth[c]) ? 2 : c;
+
+ try{ // added for OpenSCAD
+ if(c == 0) {
+ Triangulation_handler2<YZ,Nef> th(f);
+ th.handle_triangles(B, VI);
+ } else if(c == 1) {
+ Triangulation_handler2<XZ,Nef> th(f);
+ th.handle_triangles(B, VI);
+ } else if(c == 2) {
+ Triangulation_handler2<XY,Nef> th(f);
+ th.handle_triangles(B, VI);
+ } else
+ CGAL_error_msg( "wrong value");
+ } catch(...) { // added for OpenSCAD
+ PRINT("ERROR: CGAL NefPolyhedron Triangulation failed"); // added for OpenSCAD
+ this->error=true; //added for OpenSCAD
+ } // added for OpenSCAD
+ } else {
+
+ B.begin_facet();
+ fc = f->facet_cycles_begin();
+ se = typename Nef::SHalfedge_const_handle(fc);
+ CGAL_assertion(se!=0);
+ typename Nef::SHalfedge_around_facet_const_circulator hc_start(se);
+ typename Nef::SHalfedge_around_facet_const_circulator hc_end(hc_start);
+ CGAL_For_all(hc_start,hc_end) {
+ CGAL_NEF_TRACEN(" add vertex " << hc_start->source()->center_vertex()->point());
+ B.add_vertex_to_facet(VI[hc_start->source()->center_vertex()]);
+ }
+ B.end_facet();
+ }
+ }
+
+ void visit(typename Nef::SFace_const_handle) {}
+ void visit(typename Nef::Halfedge_const_handle) {}
+ void visit(typename Nef::Vertex_const_handle) {}
+ void visit(typename Nef::SHalfedge_const_handle) {}
+ void visit(typename Nef::SHalfloop_const_handle) {}
+ };
+
+ public:
+
+ const typename Nef::SNC_const_decorator& scd;
+ CGAL::Object_index<typename Nef::Vertex_const_iterator> VI;
+
+ Build_polyhedron(const typename Nef::SNC_const_decorator& s) : error(false),
+ scd(s), VI(s.vertices_begin(),s.vertices_end(),'V') {}
+
+ void operator()( HDS& hds) {
+ CGAL::Polyhedron_incremental_builder_3<HDS> B(hds, true);
+
+ int skip_volumes;
+ if(Nef::Infi_box::extended_kernel()) {
+ B.begin_surface(scd.number_of_vertices()-8,
+ scd.number_of_facets()-6,
+ scd.number_of_edges()-12);
+ skip_volumes = 2;
+ }
+ else {
+ B.begin_surface(scd.number_of_vertices(),
+ 2*scd.number_of_vertices()-4,
+ 3*scd.number_of_vertices()-6);
+ skip_volumes = 1;
+ }
+
+ int vertex_index = 0;
+ typename Nef::Vertex_const_iterator v;
+ CGAL_forall_vertices(v,scd) {
+ if(Nef::Infi_box::is_standard(v->point())) {
+ VI[v]=vertex_index++;
+ B.add_vertex(v->point());
+ }
+ }
+
+ Visitor V(B,scd,VI);
+ typename Nef::Volume_const_handle c;
+ CGAL_forall_volumes(c,scd)
+ if(skip_volumes-- <= 0) {
+ scd.visit_shell_objects(typename Nef:: SFace_const_handle(c->shells_begin()),V);
+ }
+ B.end_surface();
+ this->error=B.error()||V.error; // added for OpenSCAD
+ if (B.error()) B.rollback(); // added for OpenSCAD
+ }
+
+};
+
+template <typename Kernel>
+bool convert_to_Polyhedron( const CGAL::Nef_polyhedron_3<Kernel> &N, CGAL::Polyhedron_3<Kernel> &P )
+{
+ // several lines here added for OpenSCAD
+ typedef typename CGAL::Nef_polyhedron_3<Kernel> Nef3;
+ typedef typename CGAL::Polyhedron_3<Kernel> Polyhedron;
+ typedef typename Polyhedron::HalfedgeDS HalfedgeDS;
+ CGAL_precondition(N.is_simple());
+ P.clear();
+ Build_polyhedron<HalfedgeDS,Kernel,Nef3> bp(N);
+ P.delegate(bp);
+ return bp.error;
+}
+
+
+
+
+
+} //namespace nefworkaround
+
+
+
+
+#endif
+
diff --git a/src/CGAL_Nef_polyhedron.cc b/src/CGAL_Nef_polyhedron.cc
index 440f4ed..49b9a53 100644
--- a/src/CGAL_Nef_polyhedron.cc
+++ b/src/CGAL_Nef_polyhedron.cc
@@ -96,13 +96,22 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset()
}
else if (this->dim == 3) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
+ bool err = true;
+ std::string errmsg("");
+ CGAL_Polyhedron P;
try {
- CGAL_Polyhedron P;
- this->p3->convert_to_Polyhedron(P);
- ps = createPolySetFromPolyhedron(P);
+ err = nefworkaround::convert_to_Polyhedron<CGAL_Kernel3>( *(this->p3), P );
+ //this->p3->convert_to_Polyhedron(P);
+ }
+ catch (const CGAL::Failure_exception &e) {
+ err = true;
+ errmsg = std::string(e.what());
}
- catch (const CGAL::Precondition_exception &e) {
- PRINTB("CGAL error in CGAL_Nef_polyhedron::convertToPolyset(): %s", e.what());
+ if (err) {
+ PRINT("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed.");
+ if (errmsg!="") PRINTB("ERROR: %s",errmsg);
+ } else {
+ ps = createPolySetFromPolyhedron(P);
}
CGAL::set_error_behaviour(old_behaviour);
}
diff --git a/src/CocoaUtils.mm b/src/CocoaUtils.mm
index 92640fd..9856b3d 100644
--- a/src/CocoaUtils.mm
+++ b/src/CocoaUtils.mm
@@ -8,7 +8,7 @@ void CocoaUtils::endApplication()
object:nil];
}
-void CocoaUtils::nslog(const std::string &str, void *userdata)
+void CocoaUtils::nslog(const std::string &str, void * /* userdata */)
{
- NSLog([NSString stringWithUTF8String: str.c_str()]);
+ NSLog(@"%s", str.c_str());
}
diff --git a/src/MainWindow.h b/src/MainWindow.h
index 4f88fbf..ac999bf 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -164,6 +164,7 @@ public slots:
void viewCenter();
void viewPerspective();
void viewOrthogonal();
+ void viewResetView();
void hideConsole();
void animateUpdateDocChanged();
void animateUpdate();
diff --git a/src/MainWindow.ui b/src/MainWindow.ui
index 68bc064..4cb043f 100644
--- a/src/MainWindow.ui
+++ b/src/MainWindow.ui
@@ -213,6 +213,8 @@
<addaction name="viewActionDiagonal"/>
<addaction name="viewActionCenter"/>
<addaction name="separator"/>
+ <addaction name="viewActionResetView"/>
+ <addaction name="separator"/>
<addaction name="viewActionPerspective"/>
<addaction name="viewActionOrthogonal"/>
<addaction name="separator"/>
@@ -697,6 +699,11 @@
<string>Show Library Folder...</string>
</property>
</action>
+ <action name="viewActionResetView">
+ <property name="text">
+ <string>Reset View</string>
+ </property>
+ </action>
</widget>
<customwidgets>
<customwidget>
diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc
index cfa5731..b02b822 100644
--- a/src/PlatformUtils.cc
+++ b/src/PlatformUtils.cc
@@ -84,7 +84,7 @@ std::string PlatformUtils::info()
#ifdef QT_VERSION
std::string qtVersion = qVersion();
#else
- std::string qtVersion = "Qt disabled";
+ std::string qtVersion = "Qt disabled - Commandline Test Version";
#endif
#ifdef ENABLE_CGAL
diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc
index bc9206f..599fd7f 100644
--- a/src/PolySetCGALEvaluator.cc
+++ b/src/PolySetCGALEvaluator.cc
@@ -457,7 +457,14 @@ PolySet *PolySetCGALEvaluator::rotateDxfData(const RotateExtrudeNode &node, DxfD
{
double max_x = 0;
for (size_t j = 0; j < dxf.paths[i].indices.size(); j++) {
- max_x = fmax(max_x, dxf.points[dxf.paths[i].indices[j]][0]);
+ double point_x = dxf.points[dxf.paths[i].indices[j]][0];
+ if (point_x < 0) {
+ PRINT("ERROR: all points for rotate_extrude() must have non-negative X coordinates");
+ PRINTB("[Point %d on path %d has X coordinate %f]", j % i % point_x);
+ delete ps;
+ return NULL;
+ }
+ max_x = fmax(max_x, point_x);
}
int fragments = get_fragments_from_r(max_x, node.fn, node.fs, node.fa);
diff --git a/src/QGLView.cc b/src/QGLView.cc
index 5cb2e1b..6ffd586 100644
--- a/src/QGLView.cc
+++ b/src/QGLView.cc
@@ -64,9 +64,7 @@ static bool running_under_wine = false;
void QGLView::init()
{
cam.type = Camera::GIMBAL;
- cam.object_rot << 35, 0, -25;
- cam.object_trans << 0, 0, 0;
- cam.viewer_distance = 500;
+ resetView();
this->mouse_drag_active = false;
this->statusLabel = NULL;
@@ -83,6 +81,13 @@ void QGLView::init()
#endif
}
+void QGLView::resetView()
+{
+ cam.object_rot << 35, 0, -25;
+ cam.object_trans << 0, 0, 0;
+ cam.viewer_distance = 500;
+}
+
void QGLView::initializeGL()
{
GLenum err = glewInit();
diff --git a/src/QGLView.h b/src/QGLView.h
index f3e3681..12be085 100644
--- a/src/QGLView.h
+++ b/src/QGLView.h
@@ -41,6 +41,7 @@ public:
}
std::string getRendererInfo() const;
bool save(const char *filename);
+ void resetView();
public:
QLabel *statusLabel;
diff --git a/src/cgal.h b/src/cgal.h
index 45228be..69c8c27 100644
--- a/src/cgal.h
+++ b/src/cgal.h
@@ -27,6 +27,7 @@ using boost::uintmax_t;
#include <CGAL/Cartesian.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Nef_polyhedron_3.h>
+#include <CGAL_Nef3_workaround.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polygon_2.h>
@@ -48,9 +49,10 @@ typedef CGAL::Exact_predicates_exact_constructions_kernel CGAL_ExactKernel2;
typedef CGAL::Polygon_2<CGAL_ExactKernel2> CGAL_Poly2;
typedef CGAL::Polygon_with_holes_2<CGAL_ExactKernel2> CGAL_Poly2h;
- //typedef CGAL::Cartesian<NT> CGAL_Kernel3;
-typedef CGAL::Exact_predicates_exact_constructions_kernel CGAL_Kernel3;
-typedef CGAL::Exact_predicates_exact_constructions_kernel::FT NT3;
+typedef CGAL::Gmpq NT3;
+typedef CGAL::Cartesian<NT3> CGAL_Kernel3;
+//typedef CGAL::Exact_predicates_exact_constructions_kernel::FT NT3;
+//typedef CGAL::Exact_predicates_exact_constructions_kernel CGAL_Kernel3;
typedef CGAL::Nef_polyhedron_3<CGAL_Kernel3> CGAL_Nef_polyhedron3;
typedef CGAL_Nef_polyhedron3::Aff_transformation_3 CGAL_Aff_transformation;
diff --git a/src/control.cc b/src/control.cc
index 10aadf0..d5f664e 100644
--- a/src/control.cc
+++ b/src/control.cc
@@ -78,12 +78,14 @@ void ControlModule::for_eval(AbstractNode &node, const ModuleInstantiation &inst
Context c(ctx);
if (it_values.type() == Value::RANGE) {
Value::RangeType range = it_values.toRange();
- range.normalize();
- if (range.nbsteps()<10000) {
- for (double i = range.begin; i <= range.end; i += range.step) {
- c.set_variable(it_name, Value(i));
- for_eval(node, inst, l+1, &c, evalctx);
- }
+ uint32_t steps = range.nbsteps();
+ if (steps >= 10000) {
+ PRINTB("WARNING: Bad range parameter in for statement: too many elements (%lu).", steps);
+ } else {
+ for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
+ c.set_variable(it_name, Value(*it));
+ for_eval(node, inst, l+1, &c, evalctx);
+ }
}
}
else if (it_values.type() == Value::VECTOR) {
@@ -227,13 +229,13 @@ AbstractNode *ControlModule::instantiate(const Context* /*ctx*/, const ModuleIns
else if (value.type() == Value::RANGE) {
AbstractNode* node = new AbstractNode(inst);
Value::RangeType range = value.toRange();
- range.normalize();
- if (range.nbsteps()>=10000) {
- PRINTB("WARNING: Bad range parameter for children: too many elements (%d).", (int)((range.begin-range.end)/range.step));
+ uint32_t steps = range.nbsteps();
+ if (steps >= 10000) {
+ PRINTB("WARNING: Bad range parameter for children: too many elements (%lu).", steps);
return NULL;
}
- for (double i = range.begin; i <= range.end; i += range.step) {
- AbstractNode* childnode = getChild(Value(i),modulectx); // with error cases
+ for (Value::RangeType::iterator it = range.begin();it != range.end();it++) {
+ AbstractNode* childnode = getChild(Value(*it),modulectx); // with error cases
if (childnode==NULL) continue; // error
node->children.push_back(childnode);
}
diff --git a/src/dxfdata.h b/src/dxfdata.h
index 64853dc..ac7260c 100644
--- a/src/dxfdata.h
+++ b/src/dxfdata.h
@@ -28,11 +28,7 @@ public:
}
};
-#ifdef __APPLE__
- std::vector<Vector2d, Eigen::aligned_allocator<Vector2d> > points;
-#else
std::vector<Vector2d> points;
-#endif
std::vector<Path> paths;
std::vector<Dim> dims;
diff --git a/src/editor.cc b/src/editor.cc
index 08bf005..069101f 100644
--- a/src/editor.cc
+++ b/src/editor.cc
@@ -108,3 +108,17 @@ void Editor::wheelEvent ( QWheelEvent * event )
}
}
+void Editor::setPlainText(const QString &text)
+{
+ int y = verticalScrollBar()->sliderPosition();
+ // Save current cursor position
+ QTextCursor cursor = textCursor();
+ int n = cursor.position();
+ QTextEdit::setPlainText(text);
+ // Restore cursor position
+ if (n < text.length()) {
+ cursor.setPosition(n);
+ setTextCursor(cursor);
+ verticalScrollBar()->setSliderPosition(y);
+ }
+}
diff --git a/src/editor.h b/src/editor.h
index 09484f5..8d092a9 100644
--- a/src/editor.h
+++ b/src/editor.h
@@ -2,6 +2,7 @@
#include <QString>
#include <QWidget>
#include <QWheelEvent>
+#include <QScrollBar>
#include <QTextEdit>
class Editor : public QTextEdit
@@ -9,6 +10,7 @@ class Editor : public QTextEdit
Q_OBJECT
public:
Editor(QWidget *parent) : QTextEdit(parent) { setAcceptRichText(false); }
+ void setPlainText(const QString &text);
public slots:
void zoomIn();
void zoomOut();
diff --git a/src/export.cc b/src/export.cc
index ec6e576..cef323e 100644
--- a/src/export.cc
+++ b/src/export.cc
@@ -42,7 +42,12 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output)
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CGAL_Polyhedron P;
- root_N->p3->convert_to_Polyhedron(P);
+ //root_N->p3->convert_to_Polyhedron(P);
+ bool err = nefworkaround::convert_to_Polyhedron<CGAL_Kernel3>( *(root_N->p3), P );
+ if (err) {
+ PRINT("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed");
+ return;
+ }
typedef CGAL_Polyhedron::Vertex Vertex;
typedef CGAL_Polyhedron::Vertex_const_iterator VCI;
@@ -114,6 +119,9 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output)
catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in CGAL_Nef_polyhedron3::convert_to_Polyhedron(): %s", e.what());
}
+ catch (...) {
+ PRINT("CGAL unknown error in CGAL_Nef_polyhedron3::convert_to_Polyhedron()");
+ }
CGAL::set_error_behaviour(old_behaviour);
}
diff --git a/src/expr.cc b/src/expr.cc
index 594fccf..08615ba 100644
--- a/src/expr.cc
+++ b/src/expr.cc
@@ -117,11 +117,18 @@ Value Expression::evaluate(const Context *context) const
if (this->type == "R") {
Value v1 = this->children[0]->evaluate(context);
Value v2 = this->children[1]->evaluate(context);
- Value v3 = this->children[2]->evaluate(context);
- if (v1.type() == Value::NUMBER && v2.type() == Value::NUMBER && v3.type() == Value::NUMBER) {
- Value::RangeType range(v1.toDouble(), v2.toDouble(), v3.toDouble());
- return Value(range);
- }
+ if (this->children.size() == 2) {
+ if (v1.type() == Value::NUMBER && v2.type() == Value::NUMBER) {
+ Value::RangeType range(v1.toDouble(), v2.toDouble());
+ return Value(range);
+ }
+ } else {
+ Value v3 = this->children[2]->evaluate(context);
+ if (v1.type() == Value::NUMBER && v2.type() == Value::NUMBER && v3.type() == Value::NUMBER) {
+ Value::RangeType range(v1.toDouble(), v2.toDouble(), v3.toDouble());
+ return Value(range);
+ }
+ }
return Value();
}
if (this->type == "V") {
@@ -192,7 +199,11 @@ std::string Expression::toString() const
stream << this->const_value;
}
else if (this->type == "R") {
- stream << "[" << *this->children[0] << " : " << *this->children[1] << " : " << *this->children[2] << "]";
+ stream << "[" << *this->children[0] << " : " << *this->children[1];
+ if (this->children.size() > 2) {
+ stream << " : " << *this->children[2];
+ }
+ stream << "]";
}
else if (this->type == "V") {
stream << "[";
diff --git a/src/linalg.h b/src/linalg.h
index 1f9ed30..cb82452 100644
--- a/src/linalg.h
+++ b/src/linalg.h
@@ -4,10 +4,13 @@
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <Eigen/Dense>
+#include<Eigen/StdVector>
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d)
using Eigen::Vector2d;
+EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector3d)
using Eigen::Vector3d;
-using Eigen::Vector3f;
+
typedef Eigen::AlignedBox<double, 3> BoundingBox;
using Eigen::Matrix3f;
using Eigen::Matrix3d;
diff --git a/src/mainwin.cc b/src/mainwin.cc
index 65c511f..1ad8bc8 100644
--- a/src/mainwin.cc
+++ b/src/mainwin.cc
@@ -334,6 +334,7 @@ MainWindow::MainWindow(const QString &filename)
connect(this->viewActionBack, SIGNAL(triggered()), this, SLOT(viewAngleBack()));
connect(this->viewActionDiagonal, SIGNAL(triggered()), this, SLOT(viewAngleDiagonal()));
connect(this->viewActionCenter, SIGNAL(triggered()), this, SLOT(viewCenter()));
+ connect(this->viewActionResetView, SIGNAL(triggered()), this, SLOT(viewResetView()));
connect(this->viewActionPerspective, SIGNAL(triggered()), this, SLOT(viewPerspective()));
connect(this->viewActionOrthogonal, SIGNAL(triggered()), this, SLOT(viewOrthogonal()));
connect(this->viewActionHide, SIGNAL(triggered()), this, SLOT(hideConsole()));
@@ -503,6 +504,7 @@ MainWindow::openFile(const QString &new_filename)
}
#endif
setFileName(actual_filename);
+ editor->setPlainText("");
fileChangedOnDisk(); // force cached autoReloadId to update
refreshDocument();
@@ -1772,6 +1774,12 @@ void MainWindow::viewOrthogonal()
this->qglview->updateGL();
}
+void MainWindow::viewResetView()
+{
+ this->qglview->resetView();
+ this->qglview->updateGL();
+}
+
void MainWindow::hideConsole()
{
QSettings settings;
diff --git a/src/modcontext.cc b/src/modcontext.cc
index 5b48009..7941cf5 100644
--- a/src/modcontext.cc
+++ b/src/modcontext.cc
@@ -162,7 +162,7 @@ void ModuleContext::dump(const AbstractModule *mod, const ModuleInstantiation *i
#endif
FileContext::FileContext(const class FileModule &module, const Context *parent)
- : usedlibs(module.usedlibs), ModuleContext(parent)
+ : ModuleContext(parent), usedlibs(module.usedlibs)
{
if (!module.modulePath().empty()) this->document_path = module.modulePath();
}
diff --git a/src/openscad.cc b/src/openscad.cc
index 6bbaedb..ab84235 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -453,7 +453,7 @@ int cmdline(const char *deps_output_file, const std::string &filename, Camera &c
// Only if "fileName" is not absolute, prepend the "absoluteBase".
static QString assemblePath(const fs::path& absoluteBase,
const string& fileName) {
- return QDir(QString::fromStdString((const string&) absoluteBase))
+ return fileName.empty() ? "" : QDir(QString::fromStdString((const string&) absoluteBase))
.absoluteFilePath(QString::fromStdString(fileName));
}
@@ -474,6 +474,13 @@ bool QtUseGUI()
int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv)
{
+#ifdef Q_OS_MACX
+ if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) {
+ // fix Mac OS X 10.9 (mavericks) font issue
+ // https://bugreports.qt-project.org/browse/QTBUG-32789
+ QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
+ }
+#endif
QApplication app(argc, argv, true); //useGUI);
#ifdef Q_WS_MAC
app.installEventFilter(new EventFilter(&app));
diff --git a/src/parser.y b/src/parser.y
index 5645104..6446e82 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -325,11 +325,9 @@ expr:
}
| '[' expr ':' expr ']'
{
- Expression *e_one = new Expression(Value(1.0));
$$ = new Expression();
$$->type = "R";
$$->children.push_back($2);
- $$->children.push_back(e_one);
$$->children.push_back($4);
}
| '[' expr ':' expr ':' expr ']'
diff --git a/src/stl-utils.cc b/src/stl-utils.cc
index 790fd17..027339c 100644
--- a/src/stl-utils.cc
+++ b/src/stl-utils.cc
@@ -1,4 +1,4 @@
-#if defined(__APPLE__) && defined(__GNUC__)
+#if defined(__APPLE__) && defined(__GNUC__) && !defined(__clang__)
#include <iostream>
diff --git a/src/value.cc b/src/value.cc
index ac33a3b..5afb650 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -232,7 +232,7 @@ public:
}
std::string operator()(const Value::RangeType &v) const {
- return (boost::format("[%1% : %2% : %3%]") % v.begin % v.step % v.end).str();
+ return (boost::format("[%1% : %2% : %3%]") % v.begin_val % v.step_val % v.end_val).str();
}
};
@@ -600,9 +600,9 @@ public:
Value operator()(const Value::RangeType &range, const double &idx) const {
switch(int(idx)) {
- case 0: return Value(range.begin);
- case 1: return Value(range.step);
- case 2: return Value(range.end);
+ case 0: return Value(range.begin_val);
+ case 1: return Value(range.step_val);
+ case 2: return Value(range.end_val);
}
return Value::undefined;
}
@@ -617,3 +617,97 @@ Value Value::operator[](const Value &v)
{
return boost::apply_visitor(bracket_visitor(), this->value, v.value);
}
+
+void Value::RangeType::normalize() {
+ if ((step_val>0) && (end_val < begin_val)) {
+ std::swap(begin_val,end_val);
+ PRINT("DEPRECATED: Using ranges of the form [begin:end] with begin value greater than the end value is deprecated.");
+ }
+}
+
+uint32_t Value::RangeType::nbsteps() const {
+ if (begin_val == end_val) {
+ return 0;
+ }
+
+ if (step_val == 0) {
+ return std::numeric_limits<uint32_t>::max();
+ }
+
+ double steps;
+ if (step_val < 0) {
+ if (begin_val < end_val) {
+ return 0;
+ }
+ steps = (begin_val - end_val) / (-step_val);
+ } else {
+ if (begin_val > end_val) {
+ return 0;
+ }
+ steps = (end_val - begin_val) / step_val;
+ }
+
+ return steps;
+}
+
+Value::RangeType::iterator::iterator(Value::RangeType &range, type_t type) : range(range), val(range.begin_val)
+{
+ this->type = type;
+ update_type();
+}
+
+void Value::RangeType::iterator::update_type()
+{
+ if (range.step_val == 0) {
+ type = RANGE_TYPE_END;
+ } else if (range.step_val < 0) {
+ if (val < range.end_val) {
+ type = RANGE_TYPE_END;
+ }
+ } else {
+ if (val > range.end_val) {
+ type = RANGE_TYPE_END;
+ }
+ }
+}
+
+Value::RangeType::iterator::reference Value::RangeType::iterator::operator*()
+{
+ return val;
+}
+
+Value::RangeType::iterator::pointer Value::RangeType::iterator::operator->()
+{
+ return &(operator*());
+}
+
+Value::RangeType::iterator::self_type Value::RangeType::iterator::operator++()
+{
+ if (type < 0) {
+ type = RANGE_TYPE_RUNNING;
+ }
+ val += range.step_val;
+ update_type();
+ return *this;
+}
+
+Value::RangeType::iterator::self_type Value::RangeType::iterator::operator++(int)
+{
+ self_type tmp(*this);
+ operator++();
+ return tmp;
+}
+
+bool Value::RangeType::iterator::operator==(const self_type &other) const
+{
+ if (type == RANGE_TYPE_RUNNING) {
+ return (type == other.type) && (val == other.val) && (range == other.range);
+ } else {
+ return (type == other.type) && (range == other.range);
+ }
+}
+
+bool Value::RangeType::iterator::operator!=(const self_type &other) const
+{
+ return !(*this == other);
+}
diff --git a/src/value.h b/src/value.h
index 388b721..75dff2b 100644
--- a/src/value.h
+++ b/src/value.h
@@ -11,6 +11,7 @@
#include <boost/variant.hpp>
#include <boost/lexical_cast.hpp>
#endif
+#include <boost/cstdint.hpp>
class QuotedString : public std::string
{
@@ -31,33 +32,64 @@ std::ostream &operator<<(std::ostream &stream, const Filename &filename);
class Value
{
public:
- struct RangeType {
+ class RangeType {
+ private:
+ double begin_val;
+ double step_val;
+ double end_val;
+
+ /// inverse begin/end if begin is upper than end
+ void normalize();
+
+ public:
+ typedef enum { RANGE_TYPE_BEGIN, RANGE_TYPE_RUNNING, RANGE_TYPE_END } type_t;
+
+ class iterator {
+ public:
+ typedef iterator self_type;
+ typedef double value_type;
+ typedef double& reference;
+ typedef double* pointer;
+ typedef std::forward_iterator_tag iterator_category;
+ typedef double difference_type;
+ iterator(RangeType &range, type_t type);
+ self_type operator++();
+ self_type operator++(int junk);
+ reference operator*();
+ pointer operator->();
+ bool operator==(const self_type& other) const;
+ bool operator!=(const self_type& other) const;
+ private:
+ RangeType &range;
+ double val;
+ type_t type;
+
+ void update_type();
+ };
+
+ RangeType(double begin, double end)
+ : begin_val(begin), step_val(1.0), end_val(end)
+ {
+ normalize();
+ }
+
RangeType(double begin, double step, double end)
- : begin(begin), step(step), end(end) {}
+ : begin_val(begin), step_val(step), end_val(end) {}
bool operator==(const RangeType &other) const {
- return this->begin == other.begin &&
- this->step == other.step &&
- this->end == other.end;
+ return this->begin_val == other.begin_val &&
+ this->step_val == other.step_val &&
+ this->end_val == other.end_val;
}
- /// inverse begin/end if begin is upper than end
- void normalize() {
- if ((step>0) && (end < begin)) {
- std::swap(begin,end);
- }
- }
- /// return number of steps, max int value if step is null
- int nbsteps() const {
- if (step<=0) {
- return std::numeric_limits<int>::max();
- }
- return (int)((begin-end)/step);
- }
-
- double begin;
- double step;
- double end;
+ iterator begin() { return iterator(*this, RANGE_TYPE_BEGIN); }
+ iterator end() { return iterator(*this, RANGE_TYPE_END); }
+
+ /// return number of steps, max uint32_t value if step is 0
+ uint32_t nbsteps() const;
+
+ friend class tostring_visitor;
+ friend class bracket_visitor;
};
typedef std::vector<Value> VectorType;
diff --git a/src/version_check.h b/src/version_check.h
index 6e07208..be52e61 100644
--- a/src/version_check.h
+++ b/src/version_check.h
@@ -35,8 +35,8 @@ a time, to avoid confusion.
#include <Eigen/Core>
-#if not EIGEN_VERSION_AT_LEAST( 2,0,13 )
-#error eigen2 library missing or version too old. See README.md. To force compile, run qmake CONFIG+=skip-version-check
+#if not EIGEN_VERSION_AT_LEAST( 3,0,0 )
+#error eigen library missing or version too old. See README.md. To force compile, run qmake CONFIG+=skip-version-check
#else
@@ -104,9 +104,17 @@ a time, to avoid confusion.
#endif // ENABLE_CGAL
#endif // Boost
-#endif // Eigen2
+#endif // Eigen
#endif // MPFR
#endif // GMP
+// see github issue #552
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+#if GCC_VERSION == 40802
+#error "OpenSCAD isnt compatible with gcc 4.8.2. Please try a different version"
+#endif
+
#endif // OPENSCAD_SKIP_VERSION_CHECK
contact: Jan Huwald // Impressum