From 68acf19c09fde9085453d4bd41b13cc48a9a74bf Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 18 Oct 2016 10:22:34 +0200 Subject: [PATCH] New --scale-to-fit option in slic3r.cpp --- src/slic3r.cpp | 3 ++ xs/src/libslic3r/Config.cpp | 2 ++ xs/src/libslic3r/Config.hpp | 53 +++++++++++++++++++++++++++++--- xs/src/libslic3r/Model.cpp | 14 +++++++++ xs/src/libslic3r/Model.hpp | 2 ++ xs/src/libslic3r/PrintConfig.cpp | 6 ++++ xs/src/libslic3r/PrintConfig.hpp | 2 ++ xs/src/perlglue.cpp | 3 ++ xs/xsp/Config.xsp | 2 +- 9 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/slic3r.cpp b/src/slic3r.cpp index 8a75564cdb..2ea600f4b9 100644 --- a/src/slic3r.cpp +++ b/src/slic3r.cpp @@ -63,6 +63,9 @@ main(const int argc, const char **argv) // apply command line transform options for (ModelObjectPtrs::iterator o = model.objects.begin(); o != model.objects.end(); ++o) { + if (cli_config.scale_to_fit.is_positive_volume()) + (*o)->scale_to_fit(cli_config.scale_to_fit.value); + (*o)->scale(cli_config.scale.value); (*o)->rotate(cli_config.rotate.value, Z); } diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index 372b7b1b03..2426a491f3 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -283,6 +283,8 @@ DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) { opt = new ConfigOptionFloatOrPercent (); } else if (optdef->type == coPoint) { opt = new ConfigOptionPoint (); + } else if (optdef->type == coPoint3) { + opt = new ConfigOptionPoint3 (); } else if (optdef->type == coPoints) { opt = new ConfigOptionPoints (); } else if (optdef->type == coBool) { diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index ff9762a2e6..48c6bbd89d 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "libslic3r.h" #include "Point.hpp" @@ -352,15 +354,55 @@ class ConfigOptionPoint : public ConfigOptionSingle }; bool deserialize(std::string str, bool append = false) { - std::istringstream iss(str); - iss >> this->value.x; - iss.ignore(std::numeric_limits::max(), ','); - iss.ignore(std::numeric_limits::max(), 'x'); - iss >> this->value.y; + std::vector tokens(2); + boost::split(tokens, str, boost::is_any_of(",x")); + try { + this->value.x = boost::lexical_cast(tokens[0]); + this->value.y = boost::lexical_cast(tokens[1]); + } catch (boost::bad_lexical_cast &e){ + std::cout << "Exception caught : " << e.what() << std::endl; + return false; + } return true; }; }; +class ConfigOptionPoint3 : public ConfigOptionSingle +{ + public: + ConfigOptionPoint3() : ConfigOptionSingle(Pointf3(0,0,0)) {}; + ConfigOptionPoint3(Pointf3 _value) : ConfigOptionSingle(_value) {}; + ConfigOptionPoint3* clone() const { return new ConfigOptionPoint3(this->value); }; + + std::string serialize() const { + std::ostringstream ss; + ss << this->value.x; + ss << ","; + ss << this->value.y; + ss << ","; + ss << this->value.z; + return ss.str(); + }; + + bool deserialize(std::string str, bool append = false) { + std::vector tokens(3); + boost::split(tokens, str, boost::is_any_of(",x")); + try { + this->value.x = boost::lexical_cast(tokens[0]); + this->value.y = boost::lexical_cast(tokens[1]); + this->value.z = boost::lexical_cast(tokens[2]); + } catch (boost::bad_lexical_cast &e){ + std::cout << "Exception caught : " << e.what() << std::endl; + return false; + } + return true; + }; + + bool is_positive_volume () { + return this->value.x > 0 && this->value.y > 0 && this->value.z > 0; + }; +}; + class ConfigOptionPoints : public ConfigOptionVector { public: @@ -526,6 +568,7 @@ enum ConfigOptionType { coPercent, coFloatOrPercent, coPoint, + coPoint3, coPoints, coBool, coBools, diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 6c4cbdfaef..9175995bf0 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -609,6 +609,20 @@ ModelObject::scale(const Pointf3 &versor) this->invalidate_bounding_box(); } +void +ModelObject::scale_to_fit(const Sizef3 &size) +{ + Sizef3 orig_size = this->bounding_box().size(); + float factor = fminf( + size.x / orig_size.x, + fminf( + size.y / orig_size.y, + size.z / orig_size.z + ) + ); + this->scale(factor); +} + void ModelObject::rotate(float angle, const Axis &axis) { diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 6d4ab1bfc4..aeb784b0b2 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -2,6 +2,7 @@ #define slic3r_Model_hpp_ #include "libslic3r.h" +#include "BoundingBox.hpp" #include "PrintConfig.hpp" #include "Layer.hpp" #include "Point.hpp" @@ -129,6 +130,7 @@ class ModelObject void translate(coordf_t x, coordf_t y, coordf_t z); void scale(float factor); void scale(const Pointf3 &versor); + void scale_to_fit(const Sizef3 &size); void rotate(float angle, const Axis &axis); void mirror(const Axis &axis); size_t materials_count() const; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 461981cdaf..8bf65dea66 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -1412,6 +1412,12 @@ CLIConfigDef::CLIConfigDef() def->tooltip = "Scaling factor (default: 1)."; def->cli = "scale"; def->default_value = new ConfigOptionFloat(1); + + def = this->add("scale_to_fit", coPoint3); + def->label = "Scale to Fit"; + def->tooltip = "Scale to fit the given volume."; + def->cli = "scale-to-fit"; + def->default_value = new ConfigOptionPoint3(Pointf3(0,0,0)); } CLIConfigDef cli_config_def; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index 762aa4c976..e943e058db 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -526,6 +526,7 @@ class CLIConfig ConfigOptionFloat rotate; ConfigOptionString save; ConfigOptionFloat scale; + ConfigOptionPoint3 scale_to_fit; CLIConfig() : ConfigBase(), StaticConfig() { this->def = &cli_config_def; @@ -542,6 +543,7 @@ class CLIConfig OPT_PTR(rotate); OPT_PTR(save); OPT_PTR(scale); + OPT_PTR(scale_to_fit); return NULL; }; diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index 55e00bc3a6..d8621ac915 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -115,6 +115,9 @@ ConfigOption_to_SV(const ConfigOption &opt, const ConfigOptionDef &def) { } else if (def.type == coPoint) { const ConfigOptionPoint* optv = dynamic_cast(&opt); return perl_to_SV_clone_ref(optv->value); + } else if (def.type == coPoint3) { + const ConfigOptionPoint3* optv = dynamic_cast(&opt); + return perl_to_SV_clone_ref(optv->value); } else if (def.type == coPoints) { const ConfigOptionPoints* optv = dynamic_cast(&opt); AV* av = newAV(); diff --git a/xs/xsp/Config.xsp b/xs/xsp/Config.xsp index 496269a73e..056f1e1fdb 100644 --- a/xs/xsp/Config.xsp +++ b/xs/xsp/Config.xsp @@ -118,7 +118,7 @@ print_config_def() opt_type = "s"; } else if (optdef->type == coStrings) { opt_type = "s@"; - } else if (optdef->type == coPoint || optdef->type == coPoints) { + } else if (optdef->type == coPoint || optdef->type == coPoint3 || optdef->type == coPoints) { opt_type = "point"; } else if (optdef->type == coBool || optdef->type == coBools) { opt_type = "bool";