Fixing float nullable config vals and sla override apply func

This commit is contained in:
tamasmeszaros 2023-12-12 16:03:21 +01:00 committed by YuSanka
parent 7143190779
commit 91e67e2e16
6 changed files with 179 additions and 51 deletions

View File

@ -61,9 +61,9 @@ namespace Slic3r {
template<class Archive> void serialize(Archive& ar) { ar(this->value); ar(this->percent); } template<class Archive> void serialize(Archive& ar) { ar(this->value); ar(this->percent); }
}; };
inline bool operator==(const FloatOrPercent& l, const FloatOrPercent& r) throw() { return l.value == r.value && l.percent == r.percent; } inline bool operator==(const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return l.value == r.value && l.percent == r.percent; }
inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) throw() { return !(l == r); } inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return !(l == r); }
inline bool operator< (const FloatOrPercent& l, const FloatOrPercent& r) throw() { return l.value < r.value || (l.value == r.value && int(l.percent) < int(r.percent)); } inline bool operator< (const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return l.value < r.value || (l.value == r.value && int(l.percent) < int(r.percent)); }
} }
namespace std { namespace std {
@ -320,6 +320,54 @@ public:
typedef ConfigOption* ConfigOptionPtr; typedef ConfigOption* ConfigOptionPtr;
typedef const ConfigOption* ConfigOptionConstPtr; typedef const ConfigOption* ConfigOptionConstPtr;
// Nill value will be defined in specializations
template<class T, class En = void> struct NilValueTempl
{
using NilType = T;
static_assert(always_false<T>::value, "Type has no well defined nil value");
};
template<class T> struct NilValueTempl<T, std::enable_if_t<std::is_integral_v<T>, void>> {
using NilType = T;
static constexpr auto value = std::numeric_limits<T>::max();
};
template<> struct NilValueTempl<bool> : public NilValueTempl<int>{};
// For enums the nil is the max value of the underlying type.
template<class T>
struct NilValueTempl<T, std::enable_if_t<std::is_enum_v<T>, void>>
{
using NilType = T;
static constexpr auto value = static_cast<T>(std::numeric_limits<std::underlying_type_t<T>>::max());
};
template<class T> struct NilValueTempl<T, std::enable_if_t<std::is_floating_point_v<T>, void>> {
using NilType = T;
static constexpr auto value = std::numeric_limits<T>::quiet_NaN();
};
template<>
struct NilValueTempl<FloatOrPercent> : public NilValueTempl<double> {};
template<> struct NilValueTempl<std::string> {
using NilType = const char *;
static constexpr const char* value = "";
};
template<int N, class T> struct NilValueTempl<Vec<N, T>> {
using NilType = Vec<N, T>;
// No constexpr for Vec<N, T>
static inline const Vec<N, T> value = Vec<N, T>::Ones() * NilValueTempl<remove_cvref_t<T>>::value;
};
template<class T> using NilType = typename NilValueTempl<remove_cvref_t<T>>::NilType;
// Define shortcut as a function instead of a static const var so that it can be constexpr
// even if the NilValueTempl::value is not constexpr.
template<class T> static constexpr NilType<T> NilValue() noexcept { return NilValueTempl<remove_cvref_t<T>>::value; }
// Value of a single valued option (bool, int, float, string, point, enum) // Value of a single valued option (bool, int, float, string, point, enum)
template <class T, bool NULLABLE = false> template <class T, bool NULLABLE = false>
class ConfigOptionSingle : public ConfigOption { class ConfigOptionSingle : public ConfigOption {
@ -357,12 +405,12 @@ public:
throw ConfigurationError("Cannot override a nullable ConfigOption."); throw ConfigurationError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionVector.overriden_by() applied to different types."); throw ConfigurationError("ConfigOptionVector.overriden_by() applied to different types.");
auto rhs_vec = static_cast<const ConfigOptionSingle*>(rhs); auto rhs_co = static_cast<const ConfigOptionSingle*>(rhs);
if (! rhs->nullable()) if (! rhs->nullable())
// Overridding a non-nullable object with another non-nullable object. // Overridding a non-nullable object with another non-nullable object.
return this->value != rhs_vec->value; return this->value != rhs_co->value;
return false; return !rhs_co->is_nil() && rhs_co->value != this->value;
} }
// Apply an override option, possibly a nullable one. // Apply an override option, possibly a nullable one.
bool apply_override(const ConfigOption *rhs) override { bool apply_override(const ConfigOption *rhs) override {
@ -370,27 +418,37 @@ public:
throw ConfigurationError("Cannot override a nullable ConfigOption."); throw ConfigurationError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw ConfigurationError("ConfigOptionVector.apply_override() applied to different types."); throw ConfigurationError("ConfigOptionVector.apply_override() applied to different types.");
auto rhs_vec = static_cast<const ConfigOptionSingle*>(rhs); auto rhs_co = static_cast<const ConfigOptionSingle*>(rhs);
if (! rhs->nullable()) { if (! rhs->nullable()) {
// Overridding a non-nullable object with another non-nullable object. // Overridding a non-nullable object with another non-nullable object.
if (this->value != rhs_vec->value) { if (this->value != rhs_co->value) {
this->value = rhs_vec->value; this->value = rhs_co->value;
return true; return true;
} }
return false; return false;
} }
if (!rhs_co->is_nil() && rhs_co->value != this->value) {
this->value = rhs_co->value;
return true;
}
return false; return false;
} }
bool nullable() const override { return NULLABLE; } bool nullable() const override { return NULLABLE; }
static T nil_value() { return std::numeric_limits<T>::min(); } static constexpr NilType<T> nil_value() { return NilValue<T>(); }
// A scalar is nil, or all values of a vector are nil. // A scalar is nil, or all values of a vector are nil.
bool is_nil() const override bool is_nil() const override
{ {
return this->value == nil_value(); bool ret = false;
if constexpr (NULLABLE)
ret = this->value == nil_value();
return ret;
} }
private: private:
@ -636,7 +694,18 @@ public:
std::string serialize() const override std::string serialize() const override
{ {
std::ostringstream ss; std::ostringstream ss;
ss << this->value; double v = this->value;
if (std::isfinite(v))
ss << v;
else if (std::isnan(v)) {
if (NULLABLE)
ss << "nil";
else
throw ConfigurationError("Serializing NaN");
} else
throw ConfigurationError("Serializing invalid number");
return ss.str(); return ss.str();
} }
@ -644,7 +713,16 @@ public:
{ {
UNUSED(append); UNUSED(append);
std::istringstream iss(str); std::istringstream iss(str);
iss >> this->value;
if (str == "nil") {
if (NULLABLE)
this->value = this->nil_value();
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
} else {
iss >> this->value;
}
return !iss.fail(); return !iss.fail();
} }
@ -654,6 +732,11 @@ public:
return *this; return *this;
} }
bool is_nil() const override
{
return std::isnan(this->value);
}
private: private:
friend class cereal::access; friend class cereal::access;
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double, NULLABLE>>(this)); } template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionSingle<double, NULLABLE>>(this)); }
@ -805,7 +888,14 @@ public:
std::string serialize() const override std::string serialize() const override
{ {
std::ostringstream ss; std::ostringstream ss;
ss << this->value; if (this->value == this->nil_value()) {
if (NULLABLE)
ss << "nil";
else
throw ConfigurationError("Serializing NaN");
} else
ss << this->value;
return ss.str(); return ss.str();
} }
@ -813,7 +903,16 @@ public:
{ {
UNUSED(append); UNUSED(append);
std::istringstream iss(str); std::istringstream iss(str);
iss >> this->value;
if (str == "nil") {
if (NULLABLE)
this->value = this->nil_value();
else
throw ConfigurationError("Deserializing nil into a non-nullable object");
} else {
iss >> this->value;
}
return !iss.fail(); return !iss.fail();
} }

View File

@ -45,8 +45,9 @@ namespace {
std::string to_ini(const ConfMap &m) std::string to_ini(const ConfMap &m)
{ {
std::string ret; std::string ret;
for (auto &param : m) ret += param.first + " = " + param.second + "\n"; for (auto &param : m)
ret += param.first + " = " + param.second + "\n";
return ret; return ret;
} }

View File

@ -1117,6 +1117,14 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, material_correction_y)) ((ConfigOptionFloat, material_correction_y))
((ConfigOptionFloat, material_correction_z)) ((ConfigOptionFloat, material_correction_z))
((ConfigOptionEnum<SLAMaterialSpeed>, material_print_speed)) ((ConfigOptionEnum<SLAMaterialSpeed>, material_print_speed))
((ConfigOptionFloatNullable, material_ow_support_pillar_diameter))
((ConfigOptionFloatNullable, material_ow_branchingsupport_pillar_diameter))
((ConfigOptionFloatNullable, material_ow_support_head_front_diameter))
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_front_diameter))
((ConfigOptionFloatNullable, material_ow_support_head_penetration))
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_penetration))
((ConfigOptionFloatNullable, material_ow_support_head_width))
((ConfigOptionFloatNullable, material_ow_branchingsupport_head_width))
) )
PRINT_CONFIG_CLASS_DEFINE( PRINT_CONFIG_CLASS_DEFINE(

View File

@ -203,14 +203,24 @@ std::vector<ObjectID> SLAPrint::print_object_ids() const
return out; return out;
} }
static t_config_option_keys print_config_diffs(const SLAPrintObjectConfig &current_config, static t_config_option_keys print_config_diffs(const StaticPrintConfig &current_config,
const DynamicPrintConfig &new_full_config, const DynamicPrintConfig &new_full_config,
DynamicPrintConfig &material_overrides) DynamicPrintConfig &material_overrides)
{ {
using namespace std::string_view_literals; using namespace std::string_view_literals;
static const constexpr StaticSet overriden_keys = { static const constexpr StaticSet overriden_keys = {
"support_pillar_diameter"sv "support_head_front_diameter"sv,
"support_head_penetration"sv,
"support_head_width"sv,
"support_pillar_diameter"sv,
"branchingsupport_head_front_diameter"sv,
"branchingsupport_head_penetration"sv,
"branchingsupport_head_width"sv,
"branchingsupport_pillar_diameter"sv,
"support_points_density_relative"sv,
"relative_correction"sv,
"elefant_foot_compensation"sv,
}; };
static constexpr auto material_ow_prefix = "material_ow_"; static constexpr auto material_ow_prefix = "material_ow_";
@ -260,12 +270,15 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
config.option("printer_settings_id", true); config.option("printer_settings_id", true);
config.option("physical_printer_settings_id", true); config.option("physical_printer_settings_id", true);
// Collect changes to print config. // Collect changes to print config.
DynamicPrintConfig mat_overrides;
t_config_option_keys print_diff = m_print_config.diff(config); t_config_option_keys print_diff = m_print_config.diff(config);
t_config_option_keys printer_diff = m_printer_config.diff(config); t_config_option_keys printer_diff = print_config_diffs(m_printer_config, config, mat_overrides);
t_config_option_keys material_diff = m_material_config.diff(config); t_config_option_keys material_diff = m_material_config.diff(config);
t_config_option_keys object_diff = m_default_object_config.diff(config); t_config_option_keys object_diff = print_config_diffs(m_default_object_config, config, mat_overrides);
t_config_option_keys placeholder_parser_diff = m_placeholder_parser.config_diff(config); t_config_option_keys placeholder_parser_diff = m_placeholder_parser.config_diff(config);
config.apply(mat_overrides, true);
// Do not use the ApplyStatus as we will use the max function when updating apply_status. // Do not use the ApplyStatus as we will use the max function when updating apply_status.
unsigned int apply_status = APPLY_STATUS_UNCHANGED; unsigned int apply_status = APPLY_STATUS_UNCHANGED;
auto update_apply_status = [&apply_status](bool invalidated) auto update_apply_status = [&apply_status](bool invalidated)
@ -838,17 +851,17 @@ bool SLAPrint::invalidate_state_by_config_options(const std::vector<t_config_opt
"bottle_volume"sv, "bottle_volume"sv,
"bottle_weight"sv, "bottle_weight"sv,
"material_density"sv, "material_density"sv,
// "material_ow_support_pillar_diameter"sv, "material_ow_support_pillar_diameter"sv,
// "material_ow_support_head_front_diameter"sv, "material_ow_support_head_front_diameter"sv,
// "material_ow_support_head_penetration"sv, "material_ow_support_head_penetration"sv,
// "material_ow_support_head_width"sv, "material_ow_support_head_width"sv,
// "material_ow_branchingsupport_pillar_diameter"sv, "material_ow_branchingsupport_pillar_diameter"sv,
// "material_ow_branchingsupport_head_front_diameter"sv, "material_ow_branchingsupport_head_front_diameter"sv,
// "material_ow_branchingsupport_head_penetration"sv, "material_ow_branchingsupport_head_penetration"sv,
// "material_ow_branchingsupport_head_width"sv, "material_ow_branchingsupport_head_width"sv,
// "material_ow_elefant_foot_compensation"sv, "material_ow_elefant_foot_compensation"sv,
// "material_ow_support_points_density_relative"sv, "material_ow_support_points_density_relative"sv,
// "material_ow_relative_correction"sv "material_ow_relative_correction"sv
}; };
std::vector<SLAPrintStep> steps; std::vector<SLAPrintStep> steps;

View File

@ -868,7 +868,11 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
switch (opt->type) switch (opt->type)
{ {
case coFloat: case coFloat:
ret = double_to_string(config.option<ConfigOptionFloatNullable>(opt_key)->value); if (config.option(opt_key)->is_nil())
ret = _L("N/A");
else
ret = double_to_string(config.option<ConfigOptionFloatNullable>(opt_key)->value);
break; break;
case coInt: case coInt:
ret = config.option<ConfigOptionIntNullable>(opt_key)->value; ret = config.option<ConfigOptionIntNullable>(opt_key)->value;

View File

@ -5581,24 +5581,24 @@ void TabSLAMaterial::update_line_with_near_label_widget(ConfigOptionsGroupShp op
if (optgroup->title == "Support head" || optgroup->title == "Support pillar") { if (optgroup->title == "Support head" || optgroup->title == "Support pillar") {
for (auto& prefix : { "", "branching" }) { for (auto& prefix : { "", "branching" }) {
std::string opt_key = preprefix + prefix + key; std::string opt_key = preprefix + prefix + key;
is_checked &= !m_config->option(opt_key)->is_nil(); is_checked = !m_config->option(opt_key)->is_nil();
opt_keys.push_back(opt_key); opt_keys.push_back(opt_key);
} }
} }
else if (key == "relative_correction") { else if (key == "relative_correction") {
for (auto& axis : { "x", "y", "z" }) { for (auto& axis : { "x", "y", "z" }) {
std::string opt_key = preprefix + key + "_" + char(axis[0]); std::string opt_key = preprefix + key + "_" + char(axis[0]);
is_checked &= !m_config->option(opt_key)->is_nil(); is_checked = !m_config->option(opt_key)->is_nil();
opt_keys.push_back(opt_key); opt_keys.push_back(opt_key);
} }
} }
else { else {
std::string opt_key = preprefix + key; std::string opt_key = preprefix + key;
is_checked &= !m_config->option(opt_key)->is_nil(); is_checked = !m_config->option(opt_key)->is_nil();
opt_keys.push_back(opt_key); opt_keys.push_back(opt_key);
} }
// m_overrides_options[key]->Enable(is_checked); // m_overrides_options[key]->Enable(is_checked);
CheckBox::SetValue(m_overrides_options[key], is_checked); CheckBox::SetValue(m_overrides_options[key], is_checked);
@ -5622,22 +5622,25 @@ void TabSLAMaterial::update_material_overrides_page()
} }
for (const std::string& key : keys) { for (const std::string& key : keys) {
update_line_with_near_label_widget(*optgroup, key, false); update_line_with_near_label_widget(*optgroup, key);
continue; // // update_line_with_near_label_widget(*optgroup, key, false);
bool is_checked{ true }; // const static std::string preprefix = "material_ow_";
const static std::string preprefix = "material_ow_"; // if (title == "Support head" || title == "Support pillar") {
if (title == "Support head" || title == "Support pillar") {
for (auto& prefix : { "", "branching" }) // for (auto& prefix : { "", "branching" }) {
update_line_with_near_label_widget(*optgroup, preprefix + prefix + key, is_checked); // update_line_with_near_label_widget(*optgroup, preprefix + prefix + key);
} // }
else if (key == "relative_correction") { // }
for (auto& axis : { "x", "y", "z" }) // else if (key == "relative_correction") {
update_line_with_near_label_widget(*optgroup, preprefix + key + "_" + char(axis[0]), is_checked); // for (auto& axis : { "x", "y", "z" }) {
} // update_line_with_near_label_widget(*optgroup, preprefix + key + "_" + char(axis[0]));
else // }
update_line_with_near_label_widget(*optgroup, preprefix + key, is_checked); // }
// else {
// update_line_with_near_label_widget(*optgroup, preprefix + key);
// }
} }
} }
} }