diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/AboutDialog.html | 2 | ||||
-rw-r--r-- | src/Preferences.cc | 8 | ||||
-rw-r--r-- | src/control.cc | 6 | ||||
-rw-r--r-- | src/csgtermnormalizer.cc | 9 | ||||
-rw-r--r-- | src/csgtermnormalizer.h | 1 | ||||
-rw-r--r-- | src/dxftess-cgal.cc | 10 | ||||
-rw-r--r-- | src/func.cc | 8 | ||||
-rw-r--r-- | src/import.cc | 89 | ||||
-rw-r--r-- | src/mainwin.cc | 17 | ||||
-rw-r--r-- | src/openscad.cc | 10 | ||||
-rw-r--r-- | src/svg.cc | 3 | ||||
-rw-r--r-- | src/winconsole.c | 84 |
12 files changed, 204 insertions, 43 deletions
diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 34e8127..6203e83 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -115,7 +115,7 @@ Brett Sutton, hmnapier, Eero af Heurlin, caliston, 5263, ghost, 42loop, uniqx, Michael Thomson, Michael Ivko, Pierre Doucet, myglc2, Alan Cox, Peter Falke, Michael Ambrus, Gordon Wrigley, Ed Nisley, Stony Smith, Pasca Andrei, David Goodenough, William A Adams, mrrobinson, 1i7, -benhowes ... and many others +benhowes, 5263, Craig Trader, Miro HronĨok, ... and many others <p> <b>Hosting & resources</b> diff --git a/src/Preferences.cc b/src/Preferences.cc index e70a2a1..ec66094 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -30,7 +30,9 @@ #include <QKeyEvent> #include <QSettings> #include "PolySetCache.h" +#ifdef ENABLE_CGAL #include "CGALCache.h" +#endif Preferences *Preferences::instance = NULL; @@ -75,7 +77,9 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) this->defaultmap["advanced/opencsg_show_warning"] = true; this->defaultmap["advanced/enable_opencsg_opengl1x"] = true; this->defaultmap["advanced/polysetCacheSize"] = uint(PolySetCache::instance()->maxSize()); +#ifdef ENABLE_CGAL this->defaultmap["advanced/cgalCacheSize"] = uint(CGALCache::instance()->maxSize()); +#endif this->defaultmap["advanced/openCSGLimit"] = 2000; this->defaultmap["advanced/forceGoldfeather"] = false; @@ -126,7 +130,9 @@ Preferences::Preferences(QWidget *parent) : QMainWindow(parent) // Advanced pane QValidator *validator = new QIntValidator(this); +#ifdef ENABLE_CGAL this->cgalCacheSizeEdit->setValidator(validator); +#endif this->polysetCacheSizeEdit->setValidator(validator); this->opencsgLimitEdit->setValidator(validator); @@ -198,7 +204,9 @@ void Preferences::on_cgalCacheSizeEdit_textChanged(const QString &text) { QSettings settings; settings.setValue("advanced/cgalCacheSize", text); +#ifdef ENABLE_CGAL CGALCache::instance()->setMaxSize(text.toULong()); +#endif } void Preferences::on_polysetCacheSizeEdit_textChanged(const QString &text) diff --git a/src/control.cc b/src/control.cc index bdd0f40..44847f5 100644 --- a/src/control.cc +++ b/src/control.cc @@ -96,8 +96,10 @@ AbstractNode *ControlModule::evaluate(const Context*, const ModuleInstantiation size_t n = 0; if (inst->argvalues.size() > 0) { double v; - if (inst->argvalues[0].getDouble(v)) - n = v; + if (inst->argvalues[0].getDouble(v)) { + if (v < 0) return NULL; // Disallow negative child indices + n = trunc(v); + } } for (int i = Context::ctx_stack.size()-1; i >= 0; i--) { const Context *c = Context::ctx_stack[i]; diff --git a/src/csgtermnormalizer.cc b/src/csgtermnormalizer.cc index e2474e9..461e965 100644 --- a/src/csgtermnormalizer.cc +++ b/src/csgtermnormalizer.cc @@ -7,6 +7,7 @@ */ shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root) { + this->aborted = false; shared_ptr<CSGTerm> temp = root; while (1) { this->rootnode = temp; @@ -20,7 +21,7 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", this->limit); // Clean up any partially evaluated terms shared_ptr<CSGTerm> newroot = root, tmproot; - while (newroot != tmproot) { + while (newroot && newroot != tmproot) { tmproot = newroot; newroot = collapse_null_terms(tmproot); } @@ -49,14 +50,16 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term) while (term && match_and_replace(term)) { } this->nodecount++; if (nodecount > this->limit) { + PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", this->limit); + this->aborted = true; return shared_ptr<CSGTerm>(); } if (!term || term->type == CSGTerm::TYPE_PRIMITIVE) return term; if (term->left) term->left = normalizePass(term->left); - } while (term->type != CSGTerm::TYPE_UNION && + } while (!this->aborted && term->type != CSGTerm::TYPE_UNION && ((term->right && term->right->type != CSGTerm::TYPE_PRIMITIVE) || (term->left && term->left->type == CSGTerm::TYPE_UNION))); - term->right = normalizePass(term->right); + if (!this->aborted) term->right = normalizePass(term->right); // FIXME: Do we need to take into account any transformation of item here? return collapse_null_terms(term); diff --git a/src/csgtermnormalizer.h b/src/csgtermnormalizer.h index c331f11..f7a444f 100644 --- a/src/csgtermnormalizer.h +++ b/src/csgtermnormalizer.h @@ -17,6 +17,7 @@ private: shared_ptr<CSGTerm> collapse_null_terms(const shared_ptr<CSGTerm> &term); unsigned int count(const shared_ptr<CSGTerm> &term) const; + bool aborted; size_t limit; size_t nodecount; shared_ptr<class CSGTerm> rootnode; diff --git a/src/dxftess-cgal.cc b/src/dxftess-cgal.cc index d01c1d5..0197473 100644 --- a/src/dxftess-cgal.cc +++ b/src/dxftess-cgal.cc @@ -24,7 +24,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Triangulation_vertex_base_2<K> Vb; typedef CGAL::Delaunay_mesh_face_base_2<K> Fb; typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds; -typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds> CDT; +typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, CGAL::Exact_predicates_tag > CDT; //typedef CGAL::Delaunay_mesh_criteria_2<CDT> Criteria; typedef CDT::Vertex_handle Vertex_handle; @@ -109,6 +109,7 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool /* do_tr Grid2d<point_info_t> point_info(GRID_FINE); boost::unordered_map<edge_t,int> edge_to_triangle; boost::unordered_map<edge_t,int> edge_to_path; + int duplicate_vertices = 0; CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION); try { @@ -131,7 +132,7 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool /* do_tr // ..maybe it would be better to assert here. But this would // break compatibility with the glu tesselator that handled such // cases just fine. - PRINT( "WARNING: Duplicate vertex found during Tessellation. Render may be incorrect." ); + duplicate_vertices++; continue; } @@ -165,6 +166,11 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, bool up, bool /* do_tr } } + if ( duplicate_vertices > 0 ) { + PRINT( "WARNING: Duplicate vertices and/or intersecting lines found during DXF Tessellation." ); + PRINT( "WARNING: Modify the polygon to be a Simple Polygon. Render is incomplete." ); + } + } catch (const CGAL::Assertion_exception &e) { PRINTB("CGAL error in dxf_tesselate(): %s", e.what()); diff --git a/src/func.cc b/src/func.cc index 5dcb3e9..791e957 100644 --- a/src/func.cc +++ b/src/func.cc @@ -43,7 +43,7 @@ */ #include <boost/random/mersenne_twister.hpp> -#include <boost/random/uniform_real_distribution.hpp> +#include <boost/random/uniform_real.hpp> #ifdef __WIN32__ #include <process.h> @@ -54,8 +54,8 @@ int process_id = _getpid(); int process_id = getpid(); #endif -boost::random::mt19937 deterministic_rng; -boost::random::mt19937 lessdeterministic_rng( std::time(0) + process_id ); +boost::mt19937 deterministic_rng; +boost::mt19937 lessdeterministic_rng( std::time(0) + process_id ); AbstractFunction::~AbstractFunction() { @@ -167,7 +167,7 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std: double min = std::min( args[0].toDouble(), args[1].toDouble() ); double max = std::max( args[0].toDouble(), args[1].toDouble() ); - boost::random::uniform_real_distribution<> distributor( min, max ); + boost::uniform_real<> distributor( min, max ); Value::VectorType vec; for (int i=0; i<args[2].toDouble(); i++) { if ( deterministic ) { diff --git a/src/import.cc b/src/import.cc index 40d34fa..8980448 100644 --- a/src/import.cc +++ b/src/import.cc @@ -52,6 +52,9 @@ namespace fs = boost::filesystem; using namespace boost::assign; // bring 'operator+=()' into scope #include "boosty.h" +#include <boost/detail/endian.hpp> +#include <boost/cstdint.hpp> + class ImportModule : public AbstractModule { public: @@ -112,6 +115,47 @@ AbstractNode *ImportModule::evaluate(const Context *ctx, const ModuleInstantiati return node; } +#define STL_FACET_NUMBYTES 4*3*4+2 +// as there is no 'float32_t' standard, we assume the systems 'float' +// is a 'binary32' aka 'single' standard IEEE 32-bit floating point type +union stl_facet { + uint8_t data8[ STL_FACET_NUMBYTES ]; + uint32_t data32[4*3]; + struct facet_data { + float i, j, k; + float x1, y1, z1; + float x2, y2, z2; + float x3, y3, z3; + uint16_t attribute_byte_count; + } data; +}; + +void uint32_byte_swap( uint32_t &x ) +{ +#if defined(__GNUC__) || defined(__clang__) + x = __builtin_bswap32( x ); +#elif defined(_MSC_VER) + x = _byteswap_ulong( x ); +#else + uint32_t b1 = ( 0x000000FF & x ) << 24; + uint32_t b2 = ( 0x0000FF00 & x ) << 8; + uint32_t b3 = ( 0x00FF0000 & x ) >> 8; + uint32_t b4 = ( 0xFF000000 & x ) >> 24; + x = b1 | b2 | b3 | b4; +#endif +} + +void read_stl_facet( std::ifstream &f, stl_facet &facet ) +{ + f.read( (char*)facet.data8, STL_FACET_NUMBYTES ); +#ifdef BOOST_BIG_ENDIAN + for ( int i = 0; i < 12; i++ ) { + uint32_byte_swap( facet.data32[ i ] ); + } + // we ignore attribute byte count +#endif +} + PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const { PolySet *p = NULL; @@ -119,7 +163,8 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const if (this->type == TYPE_STL) { handle_dep((std::string)this->filename); - std::ifstream f(this->filename.c_str(), std::ios::in | std::ios::binary); + // 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 p; @@ -132,9 +177,22 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const boost::regex ex_vertex("vertex"); boost::regex ex_vertices("\\s*vertex\\s+([^\\s]+)\\s+([^\\s]+)\\s+([^\\s]+)"); + bool binary = false; + int file_size = f.tellg(); + f.seekg(80); + if (!f.eof()) { + uint32_t facenum = 0; + f.read((char *)&facenum, sizeof(uint32_t)); +#ifdef BOOST_BIG_ENDIAN + uint32_byte_swap( facenum ); +#endif + if (file_size == 80 + 4 + 50*facenum) binary = true; + } + f.seekg(0); + char data[5]; f.read(data, 5); - if (!f.eof() && !memcmp(data, "solid", 5)) { + if (!binary && !f.eof() && !memcmp(data, "solid", 5)) { int i = 0; double vdata[3][3]; std::string line; @@ -175,30 +233,13 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const { f.ignore(80-5+4); while (1) { -#ifdef _MSC_VER -#pragma pack(push,1) -#endif - struct { - float i, j, k; - float x1, y1, z1; - float x2, y2, z2; - float x3, y3, z3; - unsigned short acount; - } -#ifdef __GNUC__ - __attribute__ ((packed)) -#endif - stldata; -#ifdef _MSC_VER -#pragma pack(pop) -#endif - - f.read((char*)&stldata, sizeof(stldata)); + stl_facet facet; + read_stl_facet( f, facet ); if (f.eof()) break; p->append_poly(); - p->append_vertex(stldata.x1, stldata.y1, stldata.z1); - p->append_vertex(stldata.x2, stldata.y2, stldata.z2); - p->append_vertex(stldata.x3, stldata.y3, stldata.z3); + p->append_vertex(facet.data.x1, facet.data.y1, facet.data.z1); + p->append_vertex(facet.data.x2, facet.data.y2, facet.data.z2); + p->append_vertex(facet.data.x3, facet.data.y3, facet.data.z3); } } } diff --git a/src/mainwin.cc b/src/mainwin.cc index 251c6e1..17b9ef7 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -89,6 +89,10 @@ #include "cgal.h" #include "cgalworker.h" +#else + +#include "PolySetEvaluator.h" + #endif // ENABLE_CGAL #ifndef OPENCSG_VERSION_STRING @@ -153,9 +157,11 @@ MainWindow::MainWindow(const QString &filename) { setupUi(this); +#ifdef ENABLE_CGAL this->cgalworker = new CGALWorker(); connect(this->cgalworker, SIGNAL(done(CGAL_Nef_polyhedron *)), this, SLOT(actionRenderCGALDone(CGAL_Nef_polyhedron *))); +#endif register_builtin(root_ctx); @@ -410,8 +416,10 @@ MainWindow::loadDesignSettings() } uint polySetCacheSize = Preferences::inst()->getValue("advanced/polysetCacheSize").toUInt(); PolySetCache::instance()->setMaxSize(polySetCacheSize); +#ifdef ENABLE_CGAL uint cgalCacheSize = Preferences::inst()->getValue("advanced/cgalCacheSize").toUInt(); CGALCache::instance()->setMaxSize(cgalCacheSize); +#endif } MainWindow::~MainWindow() @@ -677,8 +685,12 @@ void MainWindow::compileCSG(bool procevents) progress_report_prep(this->root_node, report_func, this); try { +#ifdef ENABLE_CGAL CGALEvaluator cgalevaluator(this->tree); PolySetCGALEvaluator psevaluator(cgalevaluator); +#else + PolySetEvaluator psevaluator(this->tree); +#endif CSGTermEvaluator csgrenderer(this->tree, &psevaluator); this->root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); if (!root_raw_term) { @@ -687,7 +699,9 @@ void MainWindow::compileCSG(bool procevents) QApplication::processEvents(); } PolySetCache::instance()->print(); +#ifdef ENABLE_CGAL CGALCache::instance()->print(); +#endif } catch (const ProgressCancelException &e) { PRINT("CSG generation cancelled."); @@ -1196,8 +1210,9 @@ void MainWindow::actionRenderCGALDone(CGAL_Nef_polyhedron *root_N) if (root_N) { PolySetCache::instance()->print(); +#ifdef ENABLE_CGAL CGALCache::instance()->print(); - +#endif if (!root_N->isNull()) { if (root_N->dim == 2) { PRINT(" Top level object is a 2D object:"); diff --git a/src/openscad.cc b/src/openscad.cc index 472b5d4..880aa0d 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -255,7 +255,6 @@ int main(int argc, char **argv) if (!filename) help(argv[0]); -#ifdef ENABLE_CGAL Context root_ctx; register_builtin(root_ctx); @@ -299,6 +298,7 @@ int main(int argc, char **argv) } } else { +#ifdef ENABLE_CGAL CGAL_Nef_polyhedron root_N = cgalevaluator.evaluateCGALMesh(*tree.root()); fs::current_path(original_path); @@ -373,12 +373,12 @@ int main(int argc, char **argv) fstream.close(); } } - } - delete root_node; #else - fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n"); - exit(1); + fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n"); + exit(1); #endif + } + delete root_node; } else if (useGUI) { @@ -1,3 +1,4 @@ +#ifdef ENABLE_CGAL #include "cgalutils.h" #include "svg.h" #include <boost/algorithm/string.hpp> @@ -246,4 +247,4 @@ std::string dump_svg( const CGAL_Nef_polyhedron3 &N ) } // namespace - +#endif // ENABLE_CGAL diff --git a/src/winconsole.c b/src/winconsole.c new file mode 100644 index 0000000..de8e682 --- /dev/null +++ b/src/winconsole.c @@ -0,0 +1,84 @@ +/* + Enable easy piping under Windows(TM) command line. + + We use the 'devenv'(TM) method, which means we have two binary files: + + openscad.com, with IMAGE_SUBSYSTEM_WINDOWS_CUI flag set + openscad.exe, with IMAGE_SUBSYSTEM_WINDOWS_GUI flag set + + The .com version is a 'wrapper' for the .exe version. If you call + 'openscad' with no extension from a script or shell, the .com version + is prioritized by the OS and feeds the GUI stdout to the console. We use + pure C to minimize binary size when cross-compiling (~10kbytes). See Also: + + http://stackoverflow.com/questions/493536/can-one-executable-be-both-a-console-and-gui-app + http://blogs.msdn.com/b/oldnewthing/archive/2009/01/01/9259142.aspx + http://blogs.msdn.com/b/junfeng/archive/2004/02/06/68531.aspx + http://msdn.microsoft.com/en-us/library/aa298534%28v=vs.60%29.aspx + http://cournape.wordpress.com/2008/07/29/redirecting-stderrstdout-in-cmdexe/ + Open Group popen() documentation + inkscapec by Jos Hirth work at http://kaioa.com + Nop Head's OpenSCAD_cl at github.com + + TODO: + Work with unicode: http://www.i18nguy.com/unicode/c-unicode.html +*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define MAXCMDLEN 64000 +#define BUFFSIZE 42 + +int main( int argc, char * argv[] ) +{ + FILE *cmd_stdout; + char cmd[MAXCMDLEN]; + char buffer[BUFFSIZE]; + char *fgets_result; + int eof = 0; + int pclose_result; + int i; + int result = 0; + + strcat( cmd, "\0" ); + strcat( cmd, "openscad.exe" ); + for ( i = 1 ; i < argc ; ++i ) { + strcat( cmd, " " ); + strcat( cmd, argv[i] ); + } + strcat( cmd, " "); + strcat( cmd, " 2>&1"); // capture stderr and stdout + + cmd_stdout = _popen( cmd, "rt" ); + if ( cmd_stdout == NULL ) { + printf( "Error opening _popen for command: %s", cmd ); + perror( "Error message:" ); + return 1; + } + + while ( !eof ) + { + fgets_result = fgets( buffer, BUFFSIZE, cmd_stdout ); + if ( fgets_result == NULL ) { + if ( ferror( cmd_stdout ) ) { + printf("Error reading from stdout of %s\n", cmd); + result = 1; + } + if ( feof( cmd_stdout ) ) { + eof = 1; + } + } else { + fprintf( stdout, "%s", buffer ); + } + } + + pclose_result = _pclose( cmd_stdout ); + if ( pclose_result < 0 ) { + perror("Error while closing stdout for command:"); + result = 1; + } + + return result; +} |