diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/csgtermnormalizer.cc | 43 | ||||
-rw-r--r-- | src/csgtermnormalizer.h | 11 | ||||
-rw-r--r-- | src/lexer.l | 4 | ||||
-rw-r--r-- | src/mainwin.cc | 10 | ||||
-rw-r--r-- | src/openscad.cc | 1 | ||||
-rw-r--r-- | src/parsersettings.cc | 36 | ||||
-rw-r--r-- | src/parsersettings.h | 4 |
7 files changed, 71 insertions, 38 deletions
diff --git a/src/csgtermnormalizer.cc b/src/csgtermnormalizer.cc index 6600758..e2474e9 100644 --- a/src/csgtermnormalizer.cc +++ b/src/csgtermnormalizer.cc @@ -5,25 +5,29 @@ /*! NB! for e.g. empty intersections, this can normalize a tree to nothing and return NULL. */ -shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root, - size_t limit) +shared_ptr<CSGTerm> CSGTermNormalizer::normalize(const shared_ptr<CSGTerm> &root) { shared_ptr<CSGTerm> temp = root; while (1) { + this->rootnode = temp; + this->nodecount = 0; shared_ptr<CSGTerm> n = normalizePass(temp); if (!n) return n; // If normalized to nothing if (temp == n) break; temp = n; - unsigned int num = count(temp); -#ifdef DEBUG - PRINTB("Normalize count: %d\n", num); -#endif - if (num > limit) { - PRINTB("WARNING: Normalized tree is growing past %d elements. Aborting normalization.\n", limit); - return root; + if (this->nodecount > this->limit) { + 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) { + tmproot = newroot; + newroot = collapse_null_terms(tmproot); + } + return newroot; } } + this->rootnode.reset(); return temp; } @@ -42,7 +46,11 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term) } do { - while (term && normalize_tail(term)) { } + while (term && match_and_replace(term)) { } + this->nodecount++; + if (nodecount > this->limit) { + 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 && @@ -51,6 +59,11 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term) term->right = normalizePass(term->right); // FIXME: Do we need to take into account any transformation of item here? + return collapse_null_terms(term); +} + +shared_ptr<CSGTerm> CSGTermNormalizer::collapse_null_terms(const shared_ptr<CSGTerm> &term) +{ if (!term->right) { if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_DIFFERENCE) return term->left; else return term->right; @@ -59,13 +72,14 @@ shared_ptr<CSGTerm> CSGTermNormalizer::normalizePass(shared_ptr<CSGTerm> term) if (term->type == CSGTerm::TYPE_UNION) return term->right; else return term->left; } - return term; } -bool CSGTermNormalizer::normalize_tail(shared_ptr<CSGTerm> &term) +bool CSGTermNormalizer::match_and_replace(shared_ptr<CSGTerm> &term) { - if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_PRIMITIVE) return false; + if (term->type == CSGTerm::TYPE_UNION || term->type == CSGTerm::TYPE_PRIMITIVE) { + return false; + } // Part A: The 'x . (y . z)' expressions @@ -149,8 +163,9 @@ bool CSGTermNormalizer::normalize_tail(shared_ptr<CSGTerm> &term) return false; } +// Counts all non-leaf nodes unsigned int CSGTermNormalizer::count(const shared_ptr<CSGTerm> &term) const { if (!term) return 0; - return term->type == CSGTerm::TYPE_PRIMITIVE ? 1 : 0 + count(term->left) + count(term->right); + return term->type == CSGTerm::TYPE_PRIMITIVE ? 0 : 1 + count(term->left) + count(term->right); } diff --git a/src/csgtermnormalizer.h b/src/csgtermnormalizer.h index e5a2eca..c331f11 100644 --- a/src/csgtermnormalizer.h +++ b/src/csgtermnormalizer.h @@ -6,15 +6,20 @@ class CSGTermNormalizer { public: - CSGTermNormalizer() {} + CSGTermNormalizer(size_t limit) : limit(limit) {} ~CSGTermNormalizer() {} - shared_ptr<class CSGTerm> normalize(const shared_ptr<CSGTerm> &term, size_t limit); + shared_ptr<class CSGTerm> normalize(const shared_ptr<CSGTerm> &term); private: shared_ptr<CSGTerm> normalizePass(shared_ptr<CSGTerm> term) ; - bool normalize_tail(shared_ptr<CSGTerm> &term); + bool match_and_replace(shared_ptr<CSGTerm> &term); + shared_ptr<CSGTerm> collapse_null_terms(const shared_ptr<CSGTerm> &term); unsigned int count(const shared_ptr<CSGTerm> &term) const; + + size_t limit; + size_t nodecount; + shared_ptr<class CSGTerm> rootnode; }; #endif diff --git a/src/lexer.l b/src/lexer.l index 188046f..f939330 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -118,7 +118,7 @@ use[ \t\r\n>]*"<" { BEGIN(cond_use); } else { usepath = sourcepath() / filename; if (!fs::exists(usepath)) { - usepath = boosty::absolute(fs::path(get_librarydir()) / filename); + usepath = locate_file(filename); } } /* Only accept regular files which exists */ @@ -214,7 +214,7 @@ void includefile() fs::path finfo = dirinfo / filename; if (!exists(finfo)) { - finfo = fs::path(get_librarydir()) / filepath / filename; + finfo = locate_file((fs::path(filepath) / filename).string()); } filepath.clear(); diff --git a/src/mainwin.cc b/src/mainwin.cc index ecbe271..3fdee6b 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -721,9 +721,9 @@ void MainWindow::compileCSG(bool procevents) if (procevents) QApplication::processEvents(); - CSGTermNormalizer normalizer; size_t normalizelimit = 2 * Preferences::inst()->getValue("advanced/openCSGLimit").toUInt(); - this->root_norm_term = normalizer.normalize(this->root_raw_term, normalizelimit); + CSGTermNormalizer normalizer(normalizelimit); + this->root_norm_term = normalizer.normalize(this->root_raw_term); if (this->root_norm_term) { this->root_chain = new CSGChain(); this->root_chain->import(this->root_norm_term); @@ -743,7 +743,7 @@ void MainWindow::compileCSG(bool procevents) highlights_chain = new CSGChain(); for (unsigned int i = 0; i < highlight_terms.size(); i++) { - highlight_terms[i] = normalizer.normalize(highlight_terms[i], normalizelimit); + highlight_terms[i] = normalizer.normalize(highlight_terms[i]); highlights_chain->import(highlight_terms[i]); } } @@ -756,7 +756,7 @@ void MainWindow::compileCSG(bool procevents) background_chain = new CSGChain(); for (unsigned int i = 0; i < background_terms.size(); i++) { - background_terms[i] = normalizer.normalize(background_terms[i], normalizelimit); + background_terms[i] = normalizer.normalize(background_terms[i]); background_chain->import(background_terms[i]); } } @@ -1359,7 +1359,7 @@ void MainWindow::actionExportSTLorOFF(bool) } if (!this->root_N->p3->is_simple()) { - PRINT("Object isn't a valid 2-manifold! Modify your design.."); + PRINT("Object isn't a valid 2-manifold! Modify your design. See http://en.wikibooks.org/wiki/OpenSCAD_User_Manual/STL_Import_and_Export"); clearCurrentOutput(); return; } diff --git a/src/openscad.cc b/src/openscad.cc index 798bdec..f508b80 100644 --- a/src/openscad.cc +++ b/src/openscad.cc @@ -294,6 +294,7 @@ int main(int argc, char **argv) PRINTB("Can't open file \"%s\" for export", csg_output_file); } else { + fs::current_path(fparent); // Force exported filenames to be relative to document path fstream << tree.getString(*root_node) << "\n"; fstream.close(); } diff --git a/src/parsersettings.cc b/src/parsersettings.cc index 134514c..53b34f4 100644 --- a/src/parsersettings.cc +++ b/src/parsersettings.cc @@ -1,30 +1,42 @@ #include "parsersettings.h" #include <boost/filesystem.hpp> - -using namespace boost::filesystem; +#include <boost/foreach.hpp> #include "boosty.h" +#include <qglobal.h> // Needed for Q_ defines - move the offending code somewhere else + +namespace fs = boost::filesystem; -std::string librarydir; +std::vector<std::string> librarypath; -void set_librarydir(const std::string &libdir) +void add_librarydir(const std::string &libdir) { - librarydir = libdir; + librarypath.push_back(libdir); } -const std::string &get_librarydir() +/*! + Searces for the given file in library paths and returns the full path if found. + Returns an empty path if file cannot be found. +*/ +std::string locate_file(const std::string &filename) { - return librarydir; + BOOST_FOREACH(const std::string &dir, librarypath) { + fs::path usepath = fs::path(dir) / filename; + if (fs::exists(usepath)) return usepath.string(); + } + return std::string(); } void parser_init(const std::string &applicationpath) { + // FIXME: Append paths from OPENSCADPATH before adding built-in paths + std::string librarydir; - path libdir(applicationpath); - path tmpdir; -#ifdef __APPLE__ + fs::path libdir(applicationpath); + fs::path tmpdir; +#ifdef Q_WS_MAC libdir /= "../Resources"; // Libraries can be bundled if (!is_directory(libdir / "libraries")) libdir /= "../../.."; -#elif !defined(WIN32) +#elif defined(Q_OS_UNIX) if (is_directory(tmpdir = libdir / "../share/openscad/libraries")) { librarydir = boosty::stringy( tmpdir ); } else if (is_directory(tmpdir = libdir / "../../share/openscad/libraries")) { @@ -36,5 +48,5 @@ void parser_init(const std::string &applicationpath) if (is_directory(tmpdir = libdir / "libraries")) { librarydir = boosty::stringy( tmpdir ); } - set_librarydir(librarydir); + if (!librarydir.empty()) add_librarydir(librarydir); } diff --git a/src/parsersettings.h b/src/parsersettings.h index a5dc939..007aa9c 100644 --- a/src/parsersettings.h +++ b/src/parsersettings.h @@ -6,7 +6,7 @@ extern int parser_error_pos; void parser_init(const std::string &applicationpath); -void set_librarydir(const std::string &libdir); -const std::string &get_librarydir(); +void add_librarydir(const std::string &libdir); +std::string locate_file(const std::string &filename); #endif |