diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/AboutDialog.html | 16 | ||||
-rw-r--r-- | src/CGALEvaluator.cc | 13 | ||||
-rw-r--r-- | src/CGAL_Nef_polyhedron.h | 2 | ||||
-rw-r--r-- | src/MainWindow.ui | 5 | ||||
-rw-r--r-- | src/ModuleCache.cc | 26 | ||||
-rw-r--r-- | src/ModuleCache.h | 1 | ||||
-rw-r--r-- | src/OffscreenContextWGL.cc | 33 | ||||
-rw-r--r-- | src/PolySetCGALEvaluator.cc | 1 | ||||
-rw-r--r-- | src/cgal.h | 10 | ||||
-rw-r--r-- | src/cgalutils.cc | 3 | ||||
-rw-r--r-- | src/cgalutils.h | 2 | ||||
-rw-r--r-- | src/csgterm.cc | 1 | ||||
-rw-r--r-- | src/highlighter.cc | 16 | ||||
-rw-r--r-- | src/linearextrude.cc | 6 | ||||
-rw-r--r-- | src/localscope.cc | 8 | ||||
-rw-r--r-- | src/mainwin.cc | 38 | ||||
-rw-r--r-- | src/modcontext.cc | 74 | ||||
-rw-r--r-- | src/modcontext.h | 3 | ||||
-rw-r--r-- | src/module.cc | 15 | ||||
-rw-r--r-- | src/module.h | 7 | ||||
-rw-r--r-- | src/openscad.cc | 1 | ||||
-rw-r--r-- | src/parser.y | 8 | ||||
-rw-r--r-- | src/parsersettings.cc | 6 | ||||
-rw-r--r-- | src/primitives.cc | 5 | ||||
-rw-r--r-- | src/rotateextrude.cc | 1 | ||||
-rw-r--r-- | src/svg.cc | 40 |
26 files changed, 224 insertions, 117 deletions
diff --git a/src/AboutDialog.html b/src/AboutDialog.html index 005f61f..b5a5d7c 100644 --- a/src/AboutDialog.html +++ b/src/AboutDialog.html @@ -7,7 +7,8 @@ make to do your testing. --> <head> - <meta name="qrichtext" content="1" /> + <meta charset="UTF-8"/> + <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> </head> @@ -74,18 +75,23 @@ Please visit this link for a copy of the license: <a href="http://www.gnu.org/li <b>OpenSCAD Github Project members (public)</b> </p> -<lu> +<ul> <li><a href="https://github.com/kintel">Marius Kintel </a> <li><a href="http://clifford.at">Clifford Wolf</a> <li><a href="http://www.github.com/GilesBathgate">Giles Bathgate</a> <li><a href="https://github.com/brad">Brad Pitcher</a> <li><a href="https://github.com/donbright">Don Bright</a> -</lu> +</ul> <p> -<b><a href="http://www.debian.org">Debian</a> maintainer:</b> - <a href="http://christian.amsuess.com/">chrysn</a> +<b>Package Maintainers</b> </p> +<ul> +<li><a href="http://www.debian.org">Debian</a> maintainer:</b> + <a href="http://christian.amsuess.com/">chrysn</a></lu> +<li><a href="http://fedoraproject.org/">Fedora</a> maintainer:</b> + <a href="http://hroncok.cz/">Miro HronĨok</a></lu> +</ul> <p> <b>Patches</b> diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index 686bde1..8e1b5eb 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -202,30 +202,31 @@ CGAL_Nef_polyhedron CGALEvaluator::applyResize(const CgaladvNode &node) if ( N.dim == 2 ) { CGAL_Iso_rectangle_2e bbox = bounding_box( *N.p2 ); CGAL_Point_2e min2(bbox.min()), max2(bbox.max()); - CGAL_Point_3 min3(min2.x(),min2.y(),0), max3(max2.x(),max2.y(),0); + CGAL_Point_3 min3(CGAL::to_double(min2.x()), CGAL::to_double(min2.y()), 0), + max3(CGAL::to_double(max2.x()), CGAL::to_double(max2.y()), 0); bb = CGAL_Iso_cuboid_3( min3, max3 ); } else { bb = bounding_box( *N.p3 ); } - std::vector<NT> scale, bbox_size; - for (int i=0;i<3;i++) scale.push_back( NT(1) ); + std::vector<NT3> scale, bbox_size; + for (int i=0;i<3;i++) scale.push_back( NT3(1) ); bbox_size.push_back( bb.xmax()-bb.xmin() ); bbox_size.push_back( bb.ymax()-bb.ymin() ); bbox_size.push_back( bb.zmax()-bb.zmin() ); for (int i=0;i<3;i++) { if (node.newsize[i]) { - if (bbox_size[i]==NT(0)) { + if (bbox_size[i]==NT3(0)) { PRINT("WARNING: Cannot resize in direction normal to flat object"); return N; } else { - scale[i] = NT(node.newsize[i]) / bbox_size[i]; + scale[i] = NT3(node.newsize[i]) / bbox_size[i]; } } } - NT autoscale = std::max( scale[0], std::max( scale[1], scale[2] )); + NT3 autoscale = std::max( scale[0], std::max( scale[1], scale[2] )); for (int i=0;i<3;i++) { if (node.autosize[i]) scale[i] = autoscale; } diff --git a/src/CGAL_Nef_polyhedron.h b/src/CGAL_Nef_polyhedron.h index cfab993..7f59861 100644 --- a/src/CGAL_Nef_polyhedron.h +++ b/src/CGAL_Nef_polyhedron.h @@ -1,7 +1,7 @@ #ifndef CGAL_NEF_POLYHEDRON_H_ #define CGAL_NEF_POLYHEDRON_H_ -#include "cgalfwd.h" +#include "cgal.h" #include "memory.h" #include <string> #include "linalg.h" diff --git a/src/MainWindow.ui b/src/MainWindow.ui index e9bd96e..68bc064 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -177,14 +177,17 @@ <addaction name="designActionReloadAndCompile"/> <addaction name="designActionCompile"/> <addaction name="designActionCompileAndRender"/> + <addaction name="separator"/> <addaction name="designActionDisplayAST"/> <addaction name="designActionDisplayCSGTree"/> <addaction name="designActionDisplayCSGProducts"/> + <addaction name="separator"/> <addaction name="designActionExportSTL"/> <addaction name="designActionExportOFF"/> <addaction name="designActionExportDXF"/> <addaction name="designActionExportCSG"/> <addaction name="designActionExportImage"/> + <addaction name="separator"/> <addaction name="designActionFlushCaches"/> </widget> <widget class="QMenu" name="menu_View"> @@ -622,7 +625,7 @@ </action> <action name="helpActionManual"> <property name="text"> - <string>OpenSCAD Manual</string> + <string>Documentation</string> </property> </action> <action name="fileActionClearRecent"> diff --git a/src/ModuleCache.cc b/src/ModuleCache.cc index 5ebd549..de9af01 100644 --- a/src/ModuleCache.cc +++ b/src/ModuleCache.cc @@ -30,25 +30,29 @@ ModuleCache *ModuleCache::inst = NULL; */ FileModule *ModuleCache::evaluate(const std::string &filename) { + FileModule *lib_mod = (this->entries.find(filename) != this->entries.end()) ? + &(*this->entries[filename].module) : NULL; + + // Don't try to recursively evaluate - if the file changes + // during evaluation, that would be really bad. + if (lib_mod && lib_mod->isHandlingDependencies()) return lib_mod; + bool shouldCompile = true; - FileModule *lib_mod = NULL; // Create cache ID struct stat st; memset(&st, 0, sizeof(struct stat)); bool valid = (stat(filename.c_str(), &st) == 0); - // If file isn't there, just return and let the cache retain the old module + // If file isn't there, just return and let the cache retain the old module if (!valid) return NULL; - + std::string cache_id = str(boost::format("%x.%x") % st.st_mtime % st.st_size); // Lookup in cache - if (this->entries.find(filename) != this->entries.end()) { - lib_mod = &(*this->entries[filename].module); + if (lib_mod) { if (this->entries[filename].cache_id == cache_id) { shouldCompile = false; - if (lib_mod->includesChanged()) { lib_mod = NULL; shouldCompile = true; @@ -104,7 +108,9 @@ FileModule *ModuleCache::evaluate(const std::string &filename) print_messages_pop(); } - if (lib_mod) lib_mod->handleDependencies(); + if (lib_mod) { + lib_mod->handleDependencies(); + } return lib_mod; } @@ -114,3 +120,9 @@ void ModuleCache::clear() this->entries.clear(); } +FileModule *ModuleCache::lookup(const std::string &filename) +{ + return (this->entries.find(filename) != this->entries.end()) ? + &(*this->entries[filename].module) : NULL; +} + diff --git a/src/ModuleCache.h b/src/ModuleCache.h index b8ded38..7795ab7 100644 --- a/src/ModuleCache.h +++ b/src/ModuleCache.h @@ -9,6 +9,7 @@ class ModuleCache public: static ModuleCache *instance() { if (!inst) inst = new ModuleCache; return inst; } class FileModule *evaluate(const std::string &filename); + class FileModule *lookup(const std::string &filename); size_t size() { return this->entries.size(); } void clear(); diff --git a/src/OffscreenContextWGL.cc b/src/OffscreenContextWGL.cc index 0ccd68d..6e657fe 100644 --- a/src/OffscreenContextWGL.cc +++ b/src/OffscreenContextWGL.cc @@ -108,15 +108,33 @@ bool create_wgl_dummy_context(OffscreenContext &ctx) wc.style = CS_OWNDC; wc.lpfnWndProc = WndProc; wc.hInstance = inst; - wc.lpszClassName = (LPCWSTR)"OpenSCAD"; - RegisterClass( &wc ); + wc.lpszClassName = L"OpenSCAD"; + ATOM class_atom = RegisterClassW( &wc ); - HWND window = CreateWindow( (LPCWSTR)"OpenSCAD", (LPCWSTR)"OpenSCAD", - WS_CAPTION | WS_POPUPWINDOW, //| WS_VISIBLE, - 0, 0, ctx.width, ctx.height, NULL, NULL, inst, NULL ); + if ( class_atom == 0 ) { + cerr << "MS GDI - RegisterClass failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; + return false; + } + + LPCTSTR lpClassName = L"OpenSCAD"; + LPCTSTR lpWindowName = L"OpenSCAD"; + DWORD dwStyle = WS_CAPTION | WS_POPUPWINDOW; // | WS_VISIBLE + int x = 0; + int y = 0; + int nWidth = ctx.width; + int nHeight = ctx.height; + HWND hWndParent = NULL; + HMENU hMenu = NULL; + HINSTANCE hInstance = inst; + LPVOID lpParam = NULL; + + HWND window = CreateWindowW( lpClassName, lpWindowName, dwStyle, x, y, + nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam ); if ( window==NULL ) { cerr << "MS GDI - CreateWindow failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; return false; } @@ -127,6 +145,7 @@ bool create_wgl_dummy_context(OffscreenContext &ctx) HDC dev_context = GetDC( window ); if ( dev_context == NULL ) { cerr << "MS GDI - GetDC failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; return false; } @@ -145,18 +164,21 @@ bool create_wgl_dummy_context(OffscreenContext &ctx) chosenformat = ChoosePixelFormat( dev_context, &pixformat ); if (chosenformat==0) { cerr << "MS GDI - ChoosePixelFormat failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; return false; } bool spfok = SetPixelFormat( dev_context, chosenformat, &pixformat ); if (!spfok) { cerr << "MS GDI - SetPixelFormat failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; return false; } HGLRC gl_render_context = wglCreateContext( dev_context ); if ( gl_render_context == NULL ) { cerr << "MS WGL - wglCreateContext failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; ReleaseDC( ctx.window, ctx.dev_context ); return false; } @@ -164,6 +186,7 @@ bool create_wgl_dummy_context(OffscreenContext &ctx) bool mcok = wglMakeCurrent( dev_context, gl_render_context ); if (!mcok) { cerr << "MS WGL - wglMakeCurrent failed\n"; + cerr << "last-error code: " << GetLastError() << "\n"; return false; } diff --git a/src/PolySetCGALEvaluator.cc b/src/PolySetCGALEvaluator.cc index f0c274f..bc9206f 100644 --- a/src/PolySetCGALEvaluator.cc +++ b/src/PolySetCGALEvaluator.cc @@ -324,6 +324,7 @@ PolySet *PolySetCGALEvaluator::extrudeDxfData(const LinearExtrudeNode &node, Dxf { PolySet *ps = new PolySet(); ps->convexity = node.convexity; + if (node.height <= 0) return ps; double h1, h2; @@ -39,8 +39,8 @@ using boost::uintmax_t; #include <CGAL/assertions_behaviour.h> #include <CGAL/exceptions.h> -typedef CGAL::Gmpq NT; -typedef CGAL::Extended_cartesian<NT> CGAL_Kernel2; +typedef CGAL::Gmpq NT2; +typedef CGAL::Extended_cartesian<NT2> CGAL_Kernel2; typedef CGAL::Nef_polyhedron_2<CGAL_Kernel2> CGAL_Nef_polyhedron2; typedef CGAL_Kernel2::Aff_transformation_2 CGAL_Aff_transformation2; @@ -48,7 +48,9 @@ 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::Cartesian<NT> CGAL_Kernel3; +typedef CGAL::Exact_predicates_exact_constructions_kernel CGAL_Kernel3; +typedef CGAL::Exact_predicates_exact_constructions_kernel::FT NT3; typedef CGAL::Nef_polyhedron_3<CGAL_Kernel3> CGAL_Nef_polyhedron3; typedef CGAL_Nef_polyhedron3::Aff_transformation_3 CGAL_Aff_transformation; @@ -63,7 +65,7 @@ typedef CGAL::Iso_cuboid_3<CGAL_Kernel3> CGAL_Iso_cuboid_3; // CGAL_Nef_polyhedron2::Explorer::Point which is different than // CGAL_Kernel2::Point. Hence the suffix 'e' typedef CGAL_Nef_polyhedron2::Explorer::Point CGAL_Point_2e; -typedef CGAL::Iso_rectangle_2< CGAL::Simple_cartesian<NT> > CGAL_Iso_rectangle_2e; +typedef CGAL::Iso_rectangle_2<CGAL::Simple_cartesian<NT2> > CGAL_Iso_rectangle_2e; #ifdef PREV_NDEBUG diff --git a/src/cgalutils.cc b/src/cgalutils.cc index 8b4c476..bb46f1c 100644 --- a/src/cgalutils.cc +++ b/src/cgalutils.cc @@ -193,7 +193,8 @@ void ZRemover::visit( CGAL_Nef_polyhedron3::Halffacet_const_handle hfacet ) std::vector<CGAL_Nef_polyhedron2::Explorer::Point> contour; CGAL_For_all( c1, cend ) { CGAL_Nef_polyhedron3::Point_3 point3d = c1->source()->target()->point(); - CGAL_Nef_polyhedron2::Explorer::Point point2d( point3d.x(), point3d.y() ); + CGAL_Nef_polyhedron2::Explorer::Point point2d(CGAL::to_double(point3d.x()), + CGAL::to_double(point3d.y())); contour.push_back( point2d ); } if (contour.size()==0) continue; diff --git a/src/cgalutils.h b/src/cgalutils.h index 6ea7711..d25fd4c 100644 --- a/src/cgalutils.h +++ b/src/cgalutils.h @@ -1,7 +1,7 @@ #ifndef CGALUTILS_H_ #define CGALUTILS_H_ -#include <cgalfwd.h> +#include <cgal.h> class PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p); CGAL_Polyhedron *createPolyhedronFromPolySet(const class PolySet &ps); CGAL_Iso_cuboid_3 bounding_box( const CGAL_Nef_polyhedron3 &N ); diff --git a/src/csgterm.cc b/src/csgterm.cc index 7852715..a0379e7 100644 --- a/src/csgterm.cc +++ b/src/csgterm.cc @@ -188,6 +188,7 @@ void CSGChain::import(shared_ptr<CSGTerm> term, CSGTerm::type_e type, CSGTerm::F if (term->type == CSGTerm::TYPE_PRIMITIVE) { this->objects.push_back(CSGChainObject(term->polyset, term->m, term->color, type, term->label, newflag)); } else { + assert(term->left && term->right); import(term->left, type, newflag); import(term->right, term->type, newflag); } diff --git a/src/highlighter.cc b/src/highlighter.cc index bf80bb4..4b4aa30 100644 --- a/src/highlighter.cc +++ b/src/highlighter.cc @@ -132,11 +132,14 @@ Highlighter::Highlighter(QTextDocument *parent) tokentypes["operator"] << "=" << "!" << "&&" << "||" << "+" << "-" << "*" << "/" << "%" << "!" << "#" << ";"; typeformats["operator"].setForeground(Qt::blue); - tokentypes["keyword"] << "module" << "function" << "for" << "intersection_for" << "if" << "assign"; + tokentypes["math"] << "abs" << "sign" << "acos" << "asin" << "atan" << "atan2" << "sin" << "cos" << "floor" << "round" << "ceil" << "ln" << "log" << "lookup" << "min" << "max" << "pow" << "sqrt" << "exp" << "rands"; + typeformats["math"].setForeground(Qt::green); + + tokentypes["keyword"] << "module" << "function" << "for" << "intersection_for" << "if" << "assign" << "echo"<< "search" << "str"; typeformats["keyword"].setForeground(QColor("Green")); typeformats["keyword"].setToolTip("Keyword"); - tokentypes["transform"] << "scale" << "translate" << "rotate" << "multmatrix" << "color" << "projection" << "hull" << "resize"; + tokentypes["transform"] << "scale" << "translate" << "rotate" << "multmatrix" << "color" << "projection" << "hull" << "resize" << "mirror" << "minkowski"; typeformats["transform"].setForeground(QColor("Indigo")); tokentypes["csgop"] << "union" << "intersection" << "difference" << "render"; @@ -148,7 +151,7 @@ Highlighter::Highlighter(QTextDocument *parent) tokentypes["prim2d"] << "square" << "polygon" << "circle"; typeformats["prim2d"].setForeground(QColor("MidnightBlue")); - tokentypes["import"] << "include" << "use" << "import_stl" << "import" << "import_dxf" << "dxf_dim" << "dxf_cross"; + tokentypes["import"] << "include" << "use" << "import_stl" << "import" << "import_dxf" << "dxf_dim" << "dxf_cross" << "surface"; typeformats["import"].setForeground(Qt::darkYellow); tokentypes["special"] << "$children" << "child" << "$fn" << "$fa" << "$fs" << "$t" << "$vpt" << "$vpr"; @@ -285,6 +288,7 @@ void Highlighter::highlightBlock(const QString &text) // Quoting and Comments. state_e state = (state_e) previousBlockState(); + int quote_esc_state = 0; for (int n = 0; n < text.size(); ++n){ if (state == NORMAL){ if (text[n] == '"'){ @@ -301,7 +305,11 @@ void Highlighter::highlightBlock(const QString &text) } } else if (state == QUOTE){ setFormat(n,1,quoteFormat); - if (text[n] == '"' && n-1 >=0 && text[n-1] != '\\') + if (quote_esc_state > 0) + quote_esc_state = 0; + else if (text[n] == '\\') + quote_esc_state = 1; + else if (text[n] == '"') state = NORMAL; } else if (state == COMMENT){ setFormat(n,1,commentFormat); diff --git a/src/linearextrude.cc b/src/linearextrude.cc index 9a7365b..c5d4529 100644 --- a/src/linearextrude.cc +++ b/src/linearextrude.cc @@ -88,7 +88,8 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI } node->layername = layer.isUndefined() ? "" : layer.toString(); - node->height = height.toDouble(); + node->height = 100; + height.getDouble(node->height); node->convexity = (int)convexity.toDouble(); origin.getVec2(node->origin_x, node->origin_y); node->scale_x = node->scale_y = 1; @@ -99,8 +100,7 @@ AbstractNode *LinearExtrudeModule::instantiate(const Context *ctx, const ModuleI if (center.type() == Value::BOOL) node->center = center.toBool(); - if (node->height <= 0) - node->height = 100; + if (node->height <= 0) node->height = 0; if (node->convexity <= 0) node->convexity = 1; diff --git a/src/localscope.cc b/src/localscope.cc index eecff91..dd40563 100644 --- a/src/localscope.cc +++ b/src/localscope.cc @@ -55,9 +55,11 @@ std::vector<AbstractNode*> LocalScope::instantiateChildren(const Context *evalct // c->functions_p = &this->functions; // c->modules_p = &this->modules; - BOOST_FOREACH (const Assignment &ass, this->assignments) { - c->set_variable(ass.first, ass.second->evaluate(c)); - } + // Uncommenting the following would allow assignments in local scopes, + // but would cause duplicate evaluation of module scopes + // BOOST_FOREACH (const Assignment &ass, this->assignments) { + // c->set_variable(ass.first, ass.second->evaluate(c)); + // } } std::vector<AbstractNode*> childnodes; diff --git a/src/mainwin.cc b/src/mainwin.cc index 597a094..3d50d6f 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -122,7 +122,7 @@ static char helptitle[] = #endif "\nhttp://www.openscad.org\n\n"; static char copyrighttext[] = - "Copyright (C) 2009-2013 Marius Kintel <marius@kintel.net> and Clifford Wolf <clifford@clifford.at>\n" + "Copyright (C) 2009-2013 The OpenSCAD Developers\n" "\n" "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 " @@ -470,7 +470,6 @@ void MainWindow::report_func(const class AbstractNode*, void *vp, int mark) MainWindow *thisp = static_cast<MainWindow*>(vp); int v = (int)((mark*1000.0) / progress_report_count); int permille = v < 1000 ? v : 999; - printf("Progress: %d\n", permille); if (permille > thisp->progresswidget->value()) { QMetaObject::invokeMethod(thisp->progresswidget, "setValue", Qt::QueuedConnection, Q_ARG(int, permille)); @@ -511,7 +510,7 @@ MainWindow::openFile(const QString &new_filename) } #endif setFileName(actual_filename); - + fileChangedOnDisk(); // force cached autoReloadId to update refreshDocument(); updateRecentFiles(); @@ -744,7 +743,11 @@ void MainWindow::instantiateRoot() if (this->procevents) QApplication::processEvents(); AbstractNode::resetIndexCounter(); - this->root_inst = ModuleInstantiation("group"); + + // split these two lines - gcc 4.7 bug + ModuleInstantiation mi = ModuleInstantiation( "group" ); + this->root_inst = mi; + this->absolute_root_node = this->root_module->instantiate(&top_ctx, &this->root_inst, NULL); if (this->absolute_root_node) { @@ -778,8 +781,7 @@ void MainWindow::compileCSG(bool procevents) { assert(this->root_node); PRINT("Compiling design (CSG Products generation)..."); - if (procevents) - QApplication::processEvents(); + if (procevents) QApplication::processEvents(); // Main CSG evaluation QTime t; @@ -797,16 +799,16 @@ void MainWindow::compileCSG(bool procevents) PolySetEvaluator psevaluator(this->tree); #endif CSGTermEvaluator csgrenderer(this->tree, &psevaluator); + if (procevents) QApplication::processEvents(); this->root_raw_term = csgrenderer.evaluateCSGTerm(*root_node, highlight_terms, background_terms); if (!root_raw_term) { PRINT("ERROR: CSG generation failed! (no top level object found)"); - if (procevents) - QApplication::processEvents(); } PolySetCache::instance()->print(); #ifdef ENABLE_CGAL CGALCache::instance()->print(); #endif + if (procevents) QApplication::processEvents(); } catch (const ProgressCancelException &e) { PRINT("CSG generation cancelled."); @@ -818,8 +820,7 @@ void MainWindow::compileCSG(bool procevents) if (root_raw_term) { PRINT("Compiling design (CSG Products normalization)..."); - if (procevents) - QApplication::processEvents(); + if (procevents) QApplication::processEvents(); size_t normalizelimit = 2 * Preferences::inst()->getValue("advanced/openCSGLimit").toUInt(); CSGTermNormalizer normalizer(normalizelimit); @@ -831,15 +832,13 @@ void MainWindow::compileCSG(bool procevents) else { this->root_chain = NULL; PRINT("WARNING: CSG normalization resulted in an empty tree"); - if (procevents) - QApplication::processEvents(); + if (procevents) QApplication::processEvents(); } if (highlight_terms.size() > 0) { PRINTB("Compiling highlights (%d CSG Trees)...", highlight_terms.size()); - if (procevents) - QApplication::processEvents(); + if (procevents) QApplication::processEvents(); highlights_chain = new CSGChain(); for (unsigned int i = 0; i < highlight_terms.size(); i++) { @@ -851,8 +850,7 @@ void MainWindow::compileCSG(bool procevents) if (background_terms.size() > 0) { PRINTB("Compiling background (%d CSG Trees)...", background_terms.size()); - if (procevents) - QApplication::processEvents(); + if (procevents) QApplication::processEvents(); background_chain = new CSGChain(); for (unsigned int i = 0; i < background_terms.size(); i++) { @@ -881,8 +879,7 @@ void MainWindow::compileCSG(bool procevents) PRINT("CSG generation finished."); int s = t.elapsed() / 1000; PRINTB("Total rendering time: %d hours, %d minutes, %d seconds", (s / (60*60)) % ((s / 60) % 60) % (s % 60)); - if (procevents) - QApplication::processEvents(); + if (procevents) QApplication::processEvents(); } } @@ -1175,8 +1172,7 @@ void MainWindow::autoReloadSet(bool on) QSettings settings; settings.setValue("design/autoReload",designActionAutoReload->isChecked()); if (on) { - autoReloadId = ""; - autoReloadTimer->start(); + autoReloadTimer->start(200); } else { autoReloadTimer->stop(); } @@ -1829,7 +1825,7 @@ MainWindow::helpHomepage() void MainWindow::helpManual() { - QDesktopServices::openUrl(QUrl("http://en.wikibooks.org/wiki/OpenSCAD_User_Manual")); + QDesktopServices::openUrl(QUrl("http://www.openscad.org/documentation.html")); } #define STRINGIFY(x) #x diff --git a/src/modcontext.cc b/src/modcontext.cc index 3b957fd..5b48009 100644 --- a/src/modcontext.cc +++ b/src/modcontext.cc @@ -4,6 +4,7 @@ #include "function.h" #include "printutils.h" #include "builtin.h" +#include "ModuleCache.h" #include <boost/foreach.hpp> @@ -16,6 +17,51 @@ ModuleContext::~ModuleContext() { } +// Experimental code. See issue #399 +#if 0 +void ModuleContext::evaluateAssignments(const AssignmentList &assignments) +{ + // First, assign all simple variables + std::list<std::string> undefined_vars; + BOOST_FOREACH(const Assignment &ass, assignments) { + Value tmpval = ass.second->evaluate(this); + if (tmpval.isUndefined()) undefined_vars.push_back(ass.first); + else this->set_variable(ass.first, tmpval); + } + + // Variables which couldn't be evaluated in the first pass is attempted again, + // to allow for initialization out of order + + boost::unordered_map<std::string, Expression *> tmpass; + BOOST_FOREACH (const Assignment &ass, assignments) { + tmpass[ass.first] = ass.second; + } + + bool changed = true; + while (changed) { + changed = false; + std::list<std::string>::iterator iter = undefined_vars.begin(); + while (iter != undefined_vars.end()) { + std::list<std::string>::iterator curr = iter++; + boost::unordered_map<std::string, Expression *>::iterator found = tmpass.find(*curr); + if (found != tmpass.end()) { + const Expression *expr = found->second; + Value tmpval = expr->evaluate(this); + // FIXME: it's not enough to check for undefined; + // we need to check for any undefined variable in the subexpression + // For now, ignore this and revisit the validity and order of variable + // assignments later + if (!tmpval.isUndefined()) { + changed = true; + this->set_variable(*curr, tmpval); + undefined_vars.erase(curr); + } + } + } + } +} +#endif + void ModuleContext::initializeModule(const class Module &module) { this->setVariables(module.definition_arguments, evalctx); @@ -25,6 +71,8 @@ void ModuleContext::initializeModule(const class Module &module) BOOST_FOREACH(const Assignment &ass, module.scope.assignments) { this->set_variable(ass.first, ass.second->evaluate(this)); } +// Experimental code. See issue #399 +// evaluateAssignments(module.scope.assignments); } /*! @@ -125,17 +173,18 @@ Value FileContext::evaluate_function(const std::string &name, const EvalContext if (foundf) return foundf->evaluate(this, evalctx); BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) { - // m.second is NULL if the library wasn't be compiled (error or file-not-found) - if (m.second && - m.second->scope.functions.find(name) != m.second->scope.functions.end()) { - FileContext ctx(*m.second, this->parent); - ctx.initializeModule(*m.second); + // usedmod is NULL if the library wasn't be compiled (error or file-not-found) + FileModule *usedmod = ModuleCache::instance()->lookup(m); + if (usedmod && + usedmod->scope.functions.find(name) != usedmod->scope.functions.end()) { + FileContext ctx(*usedmod, this->parent); + ctx.initializeModule(*usedmod); // FIXME: Set document path #if 0 && DEBUG PRINTB("New lib Context for %s func:", name); ctx.dump(NULL, NULL); #endif - return m.second->scope.functions[name]->evaluate(&ctx, evalctx); + return usedmod->scope.functions[name]->evaluate(&ctx, evalctx); } } @@ -148,17 +197,18 @@ AbstractNode *FileContext::instantiate_module(const ModuleInstantiation &inst, c if (foundm) return foundm->instantiate(this, &inst, evalctx); BOOST_FOREACH(const FileModule::ModuleContainer::value_type &m, this->usedlibs) { - // m.second is NULL if the library wasn't be compiled (error or file-not-found) - if (m.second && - m.second->scope.modules.find(inst.name()) != m.second->scope.modules.end()) { - FileContext ctx(*m.second, this->parent); - ctx.initializeModule(*m.second); + FileModule *usedmod = ModuleCache::instance()->lookup(m); + // usedmod is NULL if the library wasn't be compiled (error or file-not-found) + if (usedmod && + usedmod->scope.modules.find(inst.name()) != usedmod->scope.modules.end()) { + FileContext ctx(*usedmod, this->parent); + ctx.initializeModule(*usedmod); // FIXME: Set document path #if 0 && DEBUG PRINT("New file Context:"); ctx.dump(NULL, &inst); #endif - return m.second->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); + return usedmod->scope.modules[inst.name()]->instantiate(&ctx, &inst, evalctx); } } diff --git a/src/modcontext.h b/src/modcontext.h index 0b3e48c..3a05a0c 100644 --- a/src/modcontext.h +++ b/src/modcontext.h @@ -36,6 +36,9 @@ public: #ifdef DEBUG virtual void dump(const class AbstractModule *mod, const ModuleInstantiation *inst); #endif +private: +// Experimental code. See issue #399 +// void evaluateAssignments(const AssignmentList &assignments); }; class FileContext : public ModuleContext diff --git a/src/module.cc b/src/module.cc index 046d0c4..9c0272d 100644 --- a/src/module.cc +++ b/src/module.cc @@ -264,34 +264,33 @@ bool FileModule::handleDependencies() // as it will have a relative path. // Iterating manually since we want to modify the container while iterating +<<<<<<< HEAD +======= std::vector<std::pair<std::string, FileModule*> > modified_modules; +>>>>>>> origin/issue181 FileModule::ModuleContainer::iterator iter = this->usedlibs.begin(); while (iter != this->usedlibs.end()) { FileModule::ModuleContainer::iterator curr = iter++; - FileModule *oldmodule = curr->second; bool wasmissing = false; // Get an absolute filename for the module - std::string filename = curr->first; + std::string filename = *curr; if (!boosty::is_absolute(filename)) { wasmissing = true; fs::path fullpath = find_valid_path(this->path, filename); if (!fullpath.empty()) filename = boosty::stringy(fullpath); } + FileModule *oldmodule = ModuleCache::instance()->lookup(filename); FileModule *newmodule = ModuleCache::instance()->evaluate(filename); // Detect appearance but not removal of files if (newmodule && oldmodule != newmodule) { changed = true; #ifdef DEBUG - PRINTB_NOCACHE(" %s: %p", filename % newmodule); + PRINTB_NOCACHE(" %s: %p -> %p", filename % oldmodule % newmodule); #endif } - if (newmodule) { - modified_modules.push_back(std::make_pair(filename, newmodule)); - this->usedlibs.erase(curr); - } - else { + if (!newmodule) { // Only print warning if we're not part of an automatic reload if (!oldmodule && !wasmissing) { PRINTB_NOCACHE("WARNING: Failed to compile library '%s'.", filename); diff --git a/src/module.h b/src/module.h index 682e65b..b5c58af 100644 --- a/src/module.h +++ b/src/module.h @@ -5,6 +5,7 @@ #include <vector> #include <list> #include <boost/unordered_map.hpp> +#include <boost/unordered_set.hpp> #include <time.h> #include <sys/stat.h> @@ -92,12 +93,11 @@ public: bool includesChanged() const; bool handleDependencies(); virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx = NULL) const; - bool hasIncludes() const { return !this->includes.empty(); } bool usesLibraries() const { return !this->usedlibs.empty(); } + bool isHandlingDependencies() const { return this->is_handling_dependencies; } - - typedef boost::unordered_map<std::string, class FileModule*> ModuleContainer; + typedef boost::unordered_set<std::string> ModuleContainer; ModuleContainer usedlibs; private: struct IncludeFile { @@ -110,7 +110,6 @@ private: typedef boost::unordered_map<std::string, struct IncludeFile> IncludeContainer; IncludeContainer includes; - bool is_handling_dependencies; std::string path; }; diff --git a/src/openscad.cc b/src/openscad.cc index 7c54762..bcde5e2 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -330,7 +330,6 @@ int main(int argc, char **argv) // Top context - this context only holds builtins ModuleContext top_ctx; top_ctx.registerBuiltin(); - PRINT("Root Context:"); #if 0 && DEBUG top_ctx.dump(NULL, NULL); #endif diff --git a/src/parser.y b/src/parser.y index 2b07f14..5b3d019 100644 --- a/src/parser.y +++ b/src/parser.y @@ -127,7 +127,7 @@ input: /* empty */ | -TOK_USE { rootmodule->usedlibs[$1] = NULL; } input | +TOK_USE { rootmodule->usedlibs.insert($1); } input | statement input ; inner_input: @@ -136,15 +136,17 @@ statement inner_input ; assignment: TOK_ID '=' expr ';' { + bool found = false; for (AssignmentList::iterator iter = scope_stack.top()->assignments.begin(); iter != scope_stack.top()->assignments.end(); iter++) { if (iter->first == $1) { - scope_stack.top()->assignments.erase(iter); + iter->second = $3; + found = true; break; } } - scope_stack.top()->assignments.push_back(Assignment($1, $3)); + if (!found) scope_stack.top()->assignments.push_back(Assignment($1, $3)); } ; statement: diff --git a/src/parsersettings.cc b/src/parsersettings.cc index 04c20ed..5ad30e1 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -30,8 +30,8 @@ fs::path search_libs(const fs::path &localpath) } // files must be 'ordinary' - they must exist and be non-directories -// FIXME: Don't print anything from this function as it's called repeatedly -// for the automatic reload function (FileModule::include_modified()) +// FIXME: We cannot print any output here since these function is called periodically +// from "Automatic reload and compile" static bool check_valid(const fs::path &p, const std::vector<std::string> *openfilenames) { if (p.empty()) { @@ -55,7 +55,7 @@ static bool check_valid(const fs::path &p, const std::vector<std::string> *openf if (openfilenames) { BOOST_FOREACH(const std::string &s, *openfilenames) { if (s == fullname) { - //PRINTB("WARNING: circular include file %s", fullname); +// PRINTB("WARNING: circular include file %s", fullname); return false; } } diff --git a/src/primitives.cc b/src/primitives.cc index 9b755ef..89c1573 100644 --- a/src/primitives.cc +++ b/src/primitives.cc @@ -242,9 +242,8 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta */ int get_fragments_from_r(double r, double fn, double fs, double fa) { - if (r < GRID_FINE) return 0; - if (fn > 0.0) - return (int)fn; + if (r < GRID_FINE) return 3; + if (fn > 0.0) return (int)(fn >= 3 ? fn : 3); return (int)ceil(fmax(fmin(360.0 / fa, r*2*M_PI / fs), 5)); } diff --git a/src/rotateextrude.cc b/src/rotateextrude.cc index e073a69..a79b92e 100644 --- a/src/rotateextrude.cc +++ b/src/rotateextrude.cc @@ -33,7 +33,6 @@ #include "polyset.h" #include "visitor.h" #include "PolySetEvaluator.h" -#include "openscad.h" // get_fragments_from_r() #include <sstream> #include <boost/assign/std/vector.hpp> @@ -70,29 +70,29 @@ std::string svg_axes() return out.str(); } -CGAL_Point_2e project_svg_3to2( CGAL_Point_3 p, CGAL_Iso_cuboid_3 bbox ) +CGAL_Nef_polyhedron2::Explorer::Point project_svg_3to2( CGAL_Point_3 p, CGAL_Iso_cuboid_3 bbox ) { - NT screenw(svg_px_width); - NT screenh(svg_px_height); - NT screenxc = screenw / 2; - NT screenyc = screenh / 2; - NT bboxx = ( bbox.xmax() - bbox.xmin() ); - NT bboxy = ( bbox.ymax() - bbox.ymin() ); - NT bboxz = ( bbox.zmax() - bbox.zmin() ); - NT largest_dim = CGAL::max( CGAL::max( bboxx, bboxy ), bboxz ); - NT bboxxc = bboxx / 2 + bbox.xmin(); - NT bboxyc = bboxy / 2 + bbox.ymin(); - NT bboxzc = bboxz / 2 + bbox.zmin(); - NT xinbox = ( p.x() - bboxxc ) / largest_dim; - NT yinbox = ( p.y() - bboxyc ) / largest_dim; - NT zinbox = ( p.z() - bboxzc ) / largest_dim; + CGAL_Kernel3::FT screenw(svg_px_width); + CGAL_Kernel3::FT screenh(svg_px_height); + CGAL_Kernel3::FT screenxc = screenw / 2; + CGAL_Kernel3::FT screenyc = screenh / 2; + CGAL_Kernel3::FT bboxx = ( bbox.xmax() - bbox.xmin() ); + CGAL_Kernel3::FT bboxy = ( bbox.ymax() - bbox.ymin() ); + CGAL_Kernel3::FT bboxz = ( bbox.zmax() - bbox.zmin() ); + CGAL_Kernel3::FT largest_dim = CGAL::max( CGAL::max( bboxx, bboxy ), bboxz ); + CGAL_Kernel3::FT bboxxc = bboxx / 2 + bbox.xmin(); + CGAL_Kernel3::FT bboxyc = bboxy / 2 + bbox.ymin(); + CGAL_Kernel3::FT bboxzc = bboxz / 2 + bbox.zmin(); + CGAL_Kernel3::FT xinbox = ( p.x() - bboxxc ) / largest_dim; + CGAL_Kernel3::FT yinbox = ( p.y() - bboxyc ) / largest_dim; + CGAL_Kernel3::FT zinbox = ( p.z() - bboxzc ) / largest_dim; // do simple fake paralell projection - NT tx = screenxc + xinbox * screenw / 1.618 + yinbox * screenh / 3.2; - NT ty = screenyc - zinbox * screenh / 1.618 - yinbox * screenh / 3.2; - return CGAL_Point_2e( tx, ty ); + CGAL_Kernel3::FT tx = screenxc + xinbox * screenw / 1.618 + yinbox * screenh / 3.2; + CGAL_Kernel3::FT ty = screenyc - zinbox * screenh / 1.618 - yinbox * screenh / 3.2; + return CGAL_Point_2e(CGAL::to_double(tx), CGAL::to_double(ty)); } -CGAL_Point_2e project_svg_2to2( CGAL_Point_2e p, CGAL_Iso_rectangle_2e bbox ) +CGAL_Point_2e project_svg_2to2(const CGAL_Point_2e &p, const CGAL_Iso_rectangle_2e &bbox) { double screenw = svg_px_width; double screenh = svg_px_height; @@ -122,7 +122,7 @@ std::string dump_cgal_nef_polyhedron2_face_svg( std::stringstream out; CGAL_For_all(c1, c2) { if ( explorer.is_standard( explorer.target(c1) ) ) { - CGAL_Point_2e source = explorer.point( explorer.source( c1 ) ); +CGAL_Nef_polyhedron2::Explorer::Point source = explorer.point( explorer.source( c1 ) ); CGAL_Point_2e target = explorer.point( explorer.target( c1 ) ); out << " <!-- Halfedge. Mark: " << c1->mark() << " -->\n"; std::string he_mark = boost::lexical_cast<std::string>(c1->mark()); |