summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/csgtermnormalizer.cc43
-rw-r--r--src/csgtermnormalizer.h11
-rw-r--r--src/lexer.l4
-rw-r--r--src/mainwin.cc10
-rw-r--r--src/openscad.cc1
-rw-r--r--src/parsersettings.cc36
-rw-r--r--src/parsersettings.h4
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
contact: Jan Huwald // Impressum