diff options
author | remi durand <remi-j.durand@thalesgroup.com> | 2021-01-09 19:11:12 +0300 |
---|---|---|
committer | remi durand <remi-j.durand@thalesgroup.com> | 2021-01-09 19:11:12 +0300 |
commit | ca3d8239c4213d4fa2e034a72b7ca530c9210eff (patch) | |
tree | 6e7e8a26e7c980e266a03dda7a0c4c0b6fe204f1 /src/libslic3r/Config.hpp | |
parent | 2f1a754f709aa4a5ff051c2a785fb5ee7b765c18 (diff) | |
parent | 1076e077ce9da0bdc6daa3ab98c135de7cfc00b3 (diff) |
Merge remote-tracking branch 'remotes/prusa/master'
Diffstat (limited to 'src/libslic3r/Config.hpp')
-rw-r--r-- | src/libslic3r/Config.hpp | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp index 4396da666..bd7c32f8e 100644 --- a/src/libslic3r/Config.hpp +++ b/src/libslic3r/Config.hpp @@ -134,6 +134,8 @@ enum ConfigOptionType { coPercents = coPercent + coVectorType, // a fraction or an absolute value coFloatOrPercent = 5, + // vector of the above + coFloatsOrPercents = coFloatOrPercent + coVectorType, // single 2d point (Point2f). Currently not used. coPoint = 6, // vector of 2d points (Point2f). Currently used for the definition of the print bed and for the extruder offsets. @@ -963,6 +965,143 @@ private: template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionPercent>(this), percent); } }; + +struct FloatOrPercent +{ + double value; + bool percent; + +private: + friend class cereal::access; + template<class Archive> void serialize(Archive & ar) { ar(this->value); ar(this->percent); } +}; + +inline bool operator==(const FloatOrPercent &l, const FloatOrPercent &r) +{ + return l.value == r.value && l.percent == r.percent; +} + +inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) +{ + return !(l == r); +} + +template<bool NULLABLE> +class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector<FloatOrPercent> +{ +public: + ConfigOptionFloatsOrPercentsTempl() : ConfigOptionVector<FloatOrPercent>() {} + explicit ConfigOptionFloatsOrPercentsTempl(size_t n, FloatOrPercent value) : ConfigOptionVector<FloatOrPercent>(n, value) {} + explicit ConfigOptionFloatsOrPercentsTempl(std::initializer_list<FloatOrPercent> il) : ConfigOptionVector<FloatOrPercent>(std::move(il)) {} + explicit ConfigOptionFloatsOrPercentsTempl(const std::vector<FloatOrPercent> &vec) : ConfigOptionVector<FloatOrPercent>(vec) {} + explicit ConfigOptionFloatsOrPercentsTempl(std::vector<FloatOrPercent> &&vec) : ConfigOptionVector<FloatOrPercent>(std::move(vec)) {} + + static ConfigOptionType static_type() { return coFloatsOrPercents; } + ConfigOptionType type() const override { return static_type(); } + ConfigOption* clone() const override { return new ConfigOptionFloatsOrPercentsTempl(*this); } + bool operator==(const ConfigOptionFloatsOrPercentsTempl &rhs) const { return vectors_equal(this->values, rhs.values); } + bool operator==(const ConfigOption &rhs) const override { + if (rhs.type() != this->type()) + throw Slic3r::RuntimeError("ConfigOptionFloatsOrPercentsTempl: Comparing incompatible types"); + assert(dynamic_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs)); + return vectors_equal(this->values, static_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs)->values); + } + // Could a special "nil" value be stored inside the vector, indicating undefined value? + bool nullable() const override { return NULLABLE; } + // Special "nil" value to be stored into the vector if this->supports_nil(). + static FloatOrPercent nil_value() { return { std::numeric_limits<double>::quiet_NaN(), false }; } + // A scalar is nil, or all values of a vector are nil. + bool is_nil() const override { for (auto v : this->values) if (! std::isnan(v.value)) return false; return true; } + bool is_nil(size_t idx) const override { return std::isnan(this->values[idx].value); } + + std::string serialize() const override + { + std::ostringstream ss; + for (const FloatOrPercent &v : this->values) { + if (&v != &this->values.front()) + ss << ","; + serialize_single_value(ss, v); + } + return ss.str(); + } + + std::vector<std::string> vserialize() const override + { + std::vector<std::string> vv; + vv.reserve(this->values.size()); + for (const FloatOrPercent &v : this->values) { + std::ostringstream ss; + serialize_single_value(ss, v); + vv.push_back(ss.str()); + } + return vv; + } + + bool deserialize(const std::string &str, bool append = false) override + { + if (! append) + this->values.clear(); + std::istringstream is(str); + std::string item_str; + while (std::getline(is, item_str, ',')) { + boost::trim(item_str); + if (item_str == "nil") { + if (NULLABLE) + this->values.push_back(nil_value()); + else + throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object"); + } else { + bool percent = item_str.find_first_of("%") != std::string::npos; + std::istringstream iss(item_str); + double value; + iss >> value; + this->values.push_back({ value, percent }); + } + } + return true; + } + + ConfigOptionFloatsOrPercentsTempl& operator=(const ConfigOption *opt) + { + this->set(opt); + return *this; + } + +protected: + void serialize_single_value(std::ostringstream &ss, const FloatOrPercent &v) const { + if (std::isfinite(v.value)) { + ss << v.value; + if (v.percent) + ss << "%"; + } else if (std::isnan(v.value)) { + if (NULLABLE) + ss << "nil"; + else + throw Slic3r::RuntimeError("Serializing NaN"); + } else + throw Slic3r::RuntimeError("Serializing invalid number"); + } + static bool vectors_equal(const std::vector<FloatOrPercent> &v1, const std::vector<FloatOrPercent> &v2) { + if (NULLABLE) { + if (v1.size() != v2.size()) + return false; + for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end(); ++ it1, ++ it2) + if (! ((std::isnan(it1->value) && std::isnan(it2->value)) || *it1 == *it2)) + return false; + return true; + } else + // Not supporting nullable values, the default vector compare is cheaper. + return v1 == v2; + } + +private: + friend class cereal::access; + template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<FloatOrPercent>>(this)); } +}; + +using ConfigOptionFloatsOrPercents = ConfigOptionFloatsOrPercentsTempl<false>; +using ConfigOptionFloatsOrPercentsNullable = ConfigOptionFloatsOrPercentsTempl<true>; + class ConfigOptionPoint : public ConfigOptionSingle<Vec2d> { public: |