diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CocoaUtils.h | 3 | ||||
-rw-r--r-- | src/CocoaUtils.mm | 4 | ||||
-rw-r--r-- | src/PlatformUtils.cc | 2 | ||||
-rw-r--r-- | src/QGLView.cc | 16 | ||||
-rw-r--r-- | src/dxfdata.h | 4 | ||||
-rw-r--r-- | src/linalg.h | 5 | ||||
-rw-r--r-- | src/openscad.cc | 108 | ||||
-rw-r--r-- | src/primitives.cc | 48 |
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(); } |