summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CocoaUtils.h3
-rw-r--r--src/CocoaUtils.mm4
-rw-r--r--src/PlatformUtils.cc2
-rw-r--r--src/QGLView.cc16
-rw-r--r--src/dxfdata.h4
-rw-r--r--src/linalg.h5
-rw-r--r--src/openscad.cc108
-rw-r--r--src/primitives.cc48
8 files changed, 125 insertions, 65 deletions
diff --git a/src/CocoaUtils.h b/src/CocoaUtils.h
index 8543d84..35e8c28 100644
--- a/src/CocoaUtils.h
+++ b/src/CocoaUtils.h
@@ -1,10 +1,13 @@
#ifndef COCOAUTILS_H_
#define COCOAUTILS_H_
+#include <string>
+
class CocoaUtils
{
public:
static void endApplication();
+ static void nslog(const std::string &str, void *userdata);
};
#endif
diff --git a/src/CocoaUtils.mm b/src/CocoaUtils.mm
index b72583c..92640fd 100644
--- a/src/CocoaUtils.mm
+++ b/src/CocoaUtils.mm
@@ -8,3 +8,7 @@ void CocoaUtils::endApplication()
object:nil];
}
+void CocoaUtils::nslog(const std::string &str, void *userdata)
+{
+ NSLog([NSString stringWithUTF8String: str.c_str()]);
+}
diff --git a/src/PlatformUtils.cc b/src/PlatformUtils.cc
index 5059b78..cfa5731 100644
--- a/src/PlatformUtils.cc
+++ b/src/PlatformUtils.cc
@@ -114,7 +114,7 @@ std::string PlatformUtils::info()
<< "\nOpenCSG version: " << OPENCSG_VERSION_STRING
<< "\nQt version: " << qtVersion
<< "\nMingW build: " << mingwstatus
- << "\nOPENSCADPATH: " << getenv("OPENSCADPATH")
+ << "\nOPENSCADPATH: " << getenv("OPENSCADPATH") << "\n"
;
return s.str();
}
diff --git a/src/QGLView.cc b/src/QGLView.cc
index 25ed323..6ffd586 100644
--- a/src/QGLView.cc
+++ b/src/QGLView.cc
@@ -172,15 +172,20 @@ void QGLView::paintGL()
void QGLView::keyPressEvent(QKeyEvent *event)
{
- if (event->key() == Qt::Key_Plus) {
+ switch (event->key()) {
+ case Qt::Key_Plus: // On many keyboards, this requires to press Shift-equals
+ case Qt::Key_Equal: // ...so simplify this a bit.
cam.viewer_distance *= 0.9;
updateGL();
- return;
- }
- if (event->key() == Qt::Key_Minus) {
+ break;
+ case Qt::Key_Minus:
cam.viewer_distance /= 0.9;
updateGL();
- return;
+ break;
+ case Qt::Key_C: // 'center'
+ cam.object_trans << 0, 0, 0;
+ updateGL();
+ break;
}
}
@@ -192,6 +197,7 @@ void QGLView::wheelEvent(QWheelEvent *event)
void QGLView::mousePressEvent(QMouseEvent *event)
{
+ setFocus();
mouse_drag_active = true;
last_mouse = event->globalPos();
}
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/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/openscad.cc b/src/openscad.cc
index e5eb69f..6bbaedb 100644
--- a/src/openscad.cc
+++ b/src/openscad.cc
@@ -37,6 +37,7 @@
#include "rendersettings.h"
#include "PlatformUtils.h"
#include "nodedumper.h"
+#include "CocoaUtils.h"
#include <string>
#include <vector>
@@ -99,15 +100,19 @@ public:
static void help(const char *progname)
{
- int tab = int(strlen(progname))+8;
- fprintf(stderr,"Usage: %s [ -o output_file [ -d deps_file ] ]\\\n"
- "%*s[ -m make_command ] [ -D var=val [..] ] \\\n"
- "%*s[ --camera=translatex,y,z,rotx,y,z,dist | \\\n"
- "%*s --camera=eyex,y,z,centerx,y,z ] \\\n"
- "%*s[ --imgsize=width,height ] [ --projection=(o)rtho|(p)ersp] \\\n"
- "%*s[ --render | --preview[=throwntogether] ] \\\n"
- "%*sfilename\n",
- progname, tab, "", tab, "", tab, "", tab, "", tab, "", tab, "");
+ int tablen = strlen(progname)+8;
+ char tabstr[tablen+1];
+ for (int i=0;i<tablen;i++) tabstr[i] = ' ';
+ tabstr[tablen] = '\0';
+
+ PRINTB("Usage: %1% [ -o output_file [ -d deps_file ] ]\\\n"
+ "%2%[ -m make_command ] [ -D var=val [..] ] \\\n"
+ "%2%[ --camera=translatex,y,z,rotx,y,z,dist | \\\n"
+ "%2% --camera=eyex,y,z,centerx,y,z ] \\\n"
+ "%2%[ --imgsize=width,height ] [ --projection=(o)rtho|(p)ersp] \\\n"
+ "%2%[ --render | --preview[=throwntogether] ] \\\n"
+ "%2%filename\n",
+ progname % (const char *)tabstr);
exit(1);
}
@@ -115,7 +120,7 @@ static void help(const char *progname)
#define TOSTRING(x) STRINGIFY(x)
static void version()
{
- printf("OpenSCAD version %s\n", TOSTRING(OPENSCAD_VERSION));
+ PRINTB("OpenSCAD version %s\n", TOSTRING(OPENSCAD_VERSION));
exit(1);
}
@@ -127,7 +132,7 @@ static void info()
try {
csgInfo.glview = new OffscreenView(512,512);
} catch (int error) {
- fprintf(stderr,"Can't create OpenGL OffscreenView. Code: %i. Exiting.\n", error);
+ PRINTB("Can't create OpenGL OffscreenView. Code: %i. Exiting.\n", error);
exit(1);
}
@@ -149,8 +154,8 @@ Camera get_camera( po::variables_map vm )
cam_parameters.push_back(lexical_cast<double>(s));
camera.setup( cam_parameters );
} else {
- fprintf(stderr,"Camera setup requires either 7 numbers for Gimbal Camera\n");
- fprintf(stderr,"or 6 numbers for Vector Camera\n");
+ PRINT("Camera setup requires either 7 numbers for Gimbal Camera\n");
+ PRINT("or 6 numbers for Vector Camera\n");
exit(1);
}
}
@@ -166,7 +171,7 @@ Camera get_camera( po::variables_map vm )
else if (proj=="p" || proj=="perspective")
camera.projection = Camera::PERSPECTIVE;
else {
- fprintf(stderr,"projection needs to be 'o' or 'p' for ortho or perspective\n");
+ PRINT("projection needs to be 'o' or 'p' for ortho or perspective\n");
exit(1);
}
}
@@ -177,7 +182,7 @@ Camera get_camera( po::variables_map vm )
vector<string> strs;
split(strs, vm["imgsize"].as<string>(), is_any_of(","));
if ( strs.size() != 2 ) {
- fprintf(stderr,"Need 2 numbers for imgsize\n");
+ PRINT("Need 2 numbers for imgsize\n");
exit(1);
} else {
w = lexical_cast<int>( strs[0] );
@@ -190,8 +195,14 @@ Camera get_camera( po::variables_map vm )
return camera;
}
-int cmdline(const std::string &application_path, const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, char ** argv )
+int cmdline(const char *deps_output_file, const std::string &filename, Camera &camera, const char *output_file, const fs::path &original_path, Render::type renderer, int argc, char ** argv )
{
+#ifdef OPENSCAD_QTGUI
+ QCoreApplication app(argc, argv);
+ const std::string application_path = QApplication::instance()->applicationDirPath().toLocal8Bit().constData();
+#else
+ const std::string application_path = boosty::stringy(boosty::absolute(boost::filesystem::path(argv[0]).parent_path()));
+#endif
parser_init(application_path, false);
Tree tree;
#ifdef ENABLE_CGAL
@@ -219,7 +230,7 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
else if (suffix == ".term") term_output_file = output_file;
else if (suffix == ".echo") echo_output_file = output_file;
else {
- fprintf(stderr, "Unknown suffix for output file %s\n", output_file);
+ PRINTB("Unknown suffix for output file %s\n", output_file);
return 1;
}
@@ -243,7 +254,7 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
std::ifstream ifs(filename.c_str());
if (!ifs.is_open()) {
- fprintf(stderr, "Can't open input file '%s'!\n", filename.c_str());
+ PRINTB("Can't open input file '%s'!\n", filename.c_str());
return 1;
}
std::string text((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
@@ -252,7 +263,7 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
std::string parentpath = boosty::stringy(abspath.parent_path());
root_module = parse(text.c_str(), parentpath.c_str(), false);
if (!root_module) {
- fprintf(stderr, "Can't parse file '%s'!\n", filename.c_str());
+ PRINTB("Can't parse file '%s'!\n", filename.c_str());
return 1;
}
root_module->handleDependencies();
@@ -347,11 +358,11 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
if (stl_output_file) {
if (root_N.dim != 3) {
- fprintf(stderr, "Current top level object is not a 3D object.\n");
+ PRINT("Current top level object is not a 3D object.\n");
return 1;
}
if (!root_N.p3->is_simple()) {
- fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n");
+ PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
return 1;
}
std::ofstream fstream(stl_output_file);
@@ -366,11 +377,11 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
if (off_output_file) {
if (root_N.dim != 3) {
- fprintf(stderr, "Current top level object is not a 3D object.\n");
+ PRINT("Current top level object is not a 3D object.\n");
return 1;
}
if (!root_N.p3->is_simple()) {
- fprintf(stderr, "Object isn't a valid 2-manifold! Modify your design.\n");
+ PRINT("Object isn't a valid 2-manifold! Modify your design.\n");
return 1;
}
std::ofstream fstream(off_output_file);
@@ -385,7 +396,7 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
if (dxf_output_file) {
if (root_N.dim != 2) {
- fprintf(stderr, "Current top level object is not a 2D object.\n");
+ PRINT("Current top level object is not a 2D object.\n");
return 1;
}
std::ofstream fstream(dxf_output_file);
@@ -415,7 +426,7 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
}
}
#else
- fprintf(stderr, "OpenSCAD has been compiled without CGAL support!\n");
+ PRINT("OpenSCAD has been compiled without CGAL support!\n");
return 1;
#endif
}
@@ -439,6 +450,13 @@ int cmdline(const std::string &application_path, const char *deps_output_file, c
#include <QString>
#include <QDir>
+// 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))
+ .absoluteFilePath(QString::fromStdString(fileName));
+}
+
bool QtUseGUI()
{
#ifdef Q_WS_X11
@@ -454,7 +472,7 @@ bool QtUseGUI()
return useGUI;
}
-int gui(const std::string &application_path, vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv)
+int gui(vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv)
{
QApplication app(argc, argv, true); //useGUI);
#ifdef Q_WS_MAC
@@ -466,7 +484,9 @@ int gui(const std::string &application_path, vector<string> &inputFiles, const f
QCoreApplication::setApplicationName("OpenSCAD");
QCoreApplication::setApplicationVersion(TOSTRING(OPENSCAD_VERSION));
- QDir exdir(QApplication::instance()->applicationDirPath());
+ const QString &app_path = app.applicationDirPath();
+
+ QDir exdir(app_path);
QString qexamplesdir;
#ifdef Q_WS_MAC
exdir.cd("../Resources"); // Examples can be bundled
@@ -486,7 +506,7 @@ int gui(const std::string &application_path, vector<string> &inputFiles, const f
qexamplesdir = exdir.path();
}
MainWindow::setExamplesDir(qexamplesdir);
- parser_init(application_path, true);
+ parser_init(app_path.toLocal8Bit().constData(), true);
#ifdef Q_WS_MAC
installAppleEventHandlers();
@@ -508,20 +528,20 @@ int gui(const std::string &application_path, vector<string> &inputFiles, const f
if (!inputFiles.size()) inputFiles.push_back("");
#ifdef ENABLE_MDI
BOOST_FOREACH(const string &infile, inputFiles) {
- new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / infile).c_str()));
+ new MainWindow(assemblePath(original_path, infile));
}
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
#else
- MainWindow *m = new MainWindow(QString::fromLocal8Bit(boosty::stringy(original_path / inputFiles[0]).c_str()));
+ MainWindow *m = new MainWindow(assemblePath(original_path, inputFiles[0]));
app.connect(m, SIGNAL(destroyed()), &app, SLOT(quit()));
#endif
return app.exec();
}
#else // OPENSCAD_QTGUI
bool QtUseGUI() { return false; }
-int gui(const std::string &application_path, const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv)
+int gui(const vector<string> &inputFiles, const fs::path &original_path, int argc, char ** argv)
{
- fprintf(stderr,"Error: compiled without QT, but trying to run GUI\n");
+ PRINT("Error: compiled without QT, but trying to run GUI\n");
return 1;
}
#endif // OPENSCAD_QTGUI
@@ -529,7 +549,9 @@ int gui(const std::string &application_path, const vector<string> &inputFiles, c
int main(int argc, char **argv)
{
int rc = 0;
-
+#ifdef Q_WS_MAC
+ set_output_handler(CocoaUtils::nslog, NULL);
+#endif
#ifdef ENABLE_CGAL
// Causes CGAL errors to abort directly instead of throwing exceptions
// (which we don't catch). This gives us stack traces without rerunning in gdb.
@@ -572,10 +594,10 @@ int main(int argc, char **argv)
po::variables_map vm;
try {
- po::store(po::command_line_parser(argc, argv).options(all_options).positional(p).run(), vm);
+ po::store(po::command_line_parser(argc, argv).options(all_options).allow_unregistered().positional(p).run(), vm);
}
catch(const std::exception &e) { // Catches e.g. unknown options
- fprintf(stderr, "%s\n", e.what());
+ PRINTB("%s\n", e.what());
help(argv[0]);
}
@@ -596,12 +618,12 @@ int main(int argc, char **argv)
output_file = vm["o"].as<string>().c_str();
}
if (vm.count("s")) {
- fprintf(stderr, "DEPRECATED: The -s option is deprecated. Use -o instead.\n");
+ PRINT("DEPRECATED: The -s option is deprecated. Use -o instead.\n");
if (output_file) help(argv[0]);
output_file = vm["s"].as<string>().c_str();
}
if (vm.count("x")) {
- fprintf(stderr, "DEPRECATED: The -x option is deprecated. Use -o instead.\n");
+ PRINT("DEPRECATED: The -x option is deprecated. Use -o instead.\n");
if (output_file) help(argv[0]);
output_file = vm["x"].as<string>().c_str();
}
@@ -645,21 +667,15 @@ int main(int argc, char **argv)
cmdlinemode = true;
if (!inputFiles.size()) help(argv[0]);
}
- const std::string application_path =
-#ifdef OPENSCAD_QTGUI
- QApplication::instance()->applicationDirPath().toLocal8Bit().constData();
-#else
- boosty::stringy(boosty::absolute(boost::filesystem::path(argv[0]).parent_path()));
-#endif
if (cmdlinemode) {
- rc = cmdline(application_path, deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argv);
+ rc = cmdline(deps_output_file, inputFiles[0], camera, output_file, original_path, renderer, argc, argv);
}
else if (QtUseGUI()) {
- rc = gui(application_path, inputFiles, original_path, argc, argv);
+ rc = gui(inputFiles, original_path, argc, argv);
}
else {
- fprintf(stderr, "Requested GUI mode but can't open display!\n");
+ PRINT("Requested GUI mode but can't open display!\n");
help(argv[0]);
}
diff --git a/src/primitives.cc b/src/primitives.cc
index 13a6794..a587d43 100644
--- a/src/primitives.cc
+++ b/src/primitives.cc
@@ -57,6 +57,8 @@ public:
primitive_type_e type;
PrimitiveModule(primitive_type_e type) : type(type) { }
virtual AbstractNode *instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const;
+private:
+ Value lookup_radius(const Context &ctx, const std::string &radius_var, const std::string &diameter_var) const;
};
class PrimitiveNode : public AbstractPolyNode
@@ -105,6 +107,35 @@ public:
virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const;
};
+/**
+ * Return a radius value by looking up both a diameter and radius variable.
+ * The diameter has higher priority, so if found an additionally set radius
+ * value is ignored.
+ *
+ * @param ctx data context with variable values.
+ * @param radius_var name of the variable to lookup for the radius value.
+ * @param diameter_var name of the variable to lookup for the diameter value.
+ * @return radius value of type Value::NUMBER or Value::UNDEFINED if both
+ * variables are invalid or not set.
+ */
+Value PrimitiveModule::lookup_radius(const Context &ctx, const std::string &diameter_var, const std::string &radius_var) const
+{
+ const Value d = ctx.lookup_variable(diameter_var, true);
+ const Value r = ctx.lookup_variable(radius_var, true);
+ const bool r_defined = (r.type() == Value::NUMBER);
+
+ if (d.type() == Value::NUMBER) {
+ if (r_defined) {
+ PRINTB("WARNING: Ignoring radius variable '%s' as diameter '%s' is defined too.", radius_var % diameter_var);
+ }
+ return Value(d.toDouble() / 2.0);
+ } else if (r_defined) {
+ return r;
+ } else {
+ return Value();
+ }
+}
+
AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInstantiation *inst, const EvalContext *evalctx) const
{
PrimitiveNode *node = new PrimitiveNode(inst, this->type);
@@ -170,22 +201,21 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
}
if (type == SPHERE) {
- Value r = c.lookup_variable("r");
+ const Value r = lookup_radius(c, "d", "r");
if (r.type() == Value::NUMBER) {
node->r1 = r.toDouble();
}
}
if (type == CYLINDER) {
- Value h = c.lookup_variable("h");
- Value r, r1, r2;
- r1 = c.lookup_variable("r1");
- r2 = c.lookup_variable("r2");
- r = c.lookup_variable("r", true); // silence warning since r has no default value
- Value center = c.lookup_variable("center");
+ const Value h = c.lookup_variable("h");
if (h.type() == Value::NUMBER) {
node->h = h.toDouble();
}
+
+ const Value r = lookup_radius(c, "d", "r");
+ const Value r1 = lookup_radius(c, "d1", "r1");
+ const Value r2 = lookup_radius(c, "d2", "r2");
if (r.type() == Value::NUMBER) {
node->r1 = r.toDouble();
node->r2 = r.toDouble();
@@ -196,6 +226,8 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
if (r2.type() == Value::NUMBER) {
node->r2 = r2.toDouble();
}
+
+ const Value center = c.lookup_variable("center");
if (center.type() == Value::BOOL) {
node->center = center.toBool();
}
@@ -218,7 +250,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
}
if (type == CIRCLE) {
- Value r = c.lookup_variable("r");
+ const Value r = lookup_radius(c, "d", "r");
if (r.type() == Value::NUMBER) {
node->r1 = r.toDouble();
}
contact: Jan Huwald // Impressum