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); }
};
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) throw() { 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.percent == r.percent; }
inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r) noexcept { return !(l == r); }
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 {
@ -320,6 +320,54 @@ public:
typedef ConfigOption* ConfigOptionPtr;
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)
template <class T, bool NULLABLE = false>
class ConfigOptionSingle : public ConfigOption {
@ -357,12 +405,12 @@ public:
throw ConfigurationError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type())
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())
// 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.
bool apply_override(const ConfigOption *rhs) override {
@ -370,27 +418,37 @@ public:
throw ConfigurationError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type())
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()) {
// Overridding a non-nullable object with another non-nullable object.
if (this->value != rhs_vec->value) {
this->value = rhs_vec->value;
if (this->value != rhs_co->value) {
this->value = rhs_co->value;
return true;
}
return false;
}
if (!rhs_co->is_nil() && rhs_co->value != this->value) {
this->value = rhs_co->value;
return true;
}
return false;
}
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.
bool is_nil() const override
{
return this->value == nil_value();
bool ret = false;
if constexpr (NULLABLE)
ret = this->value == nil_value();
return ret;
}
private:
@ -636,7 +694,18 @@ public:
std::string serialize() const override
{
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();
}
@ -644,7 +713,16 @@ public:
{
UNUSED(append);
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();
}
@ -654,6 +732,11 @@ public:
return *this;
}
bool is_nil() const override
{
return std::isnan(this->value);
}
private:
friend class cereal::access;
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::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();
}
@ -813,7 +903,16 @@ public:
{
UNUSED(append);
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();
}

View File

@ -45,8 +45,9 @@ namespace {
std::string to_ini(const ConfMap &m)
{
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;
}

View File

@ -1117,6 +1117,14 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, material_correction_y))
((ConfigOptionFloat, material_correction_z))
((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(

View File

@ -203,14 +203,24 @@ std::vector<ObjectID> SLAPrint::print_object_ids() const
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,
DynamicPrintConfig &material_overrides)
{
using namespace std::string_view_literals;
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_";
@ -260,12 +270,15 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
config.option("printer_settings_id", true);
config.option("physical_printer_settings_id", true);
// Collect changes to print config.
DynamicPrintConfig mat_overrides;
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 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);
config.apply(mat_overrides, true);
// Do not use the ApplyStatus as we will use the max function when updating apply_status.
unsigned int apply_status = APPLY_STATUS_UNCHANGED;
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_weight"sv,
"material_density"sv,
// "material_ow_support_pillar_diameter"sv,
// "material_ow_support_head_front_diameter"sv,
// "material_ow_support_head_penetration"sv,
// "material_ow_support_head_width"sv,
// "material_ow_branchingsupport_pillar_diameter"sv,
// "material_ow_branchingsupport_head_front_diameter"sv,
// "material_ow_branchingsupport_head_penetration"sv,
// "material_ow_branchingsupport_head_width"sv,
// "material_ow_elefant_foot_compensation"sv,
// "material_ow_support_points_density_relative"sv,
// "material_ow_relative_correction"sv
"material_ow_support_pillar_diameter"sv,
"material_ow_support_head_front_diameter"sv,
"material_ow_support_head_penetration"sv,
"material_ow_support_head_width"sv,
"material_ow_branchingsupport_pillar_diameter"sv,
"material_ow_branchingsupport_head_front_diameter"sv,
"material_ow_branchingsupport_head_penetration"sv,
"material_ow_branchingsupport_head_width"sv,
"material_ow_elefant_foot_compensation"sv,
"material_ow_support_points_density_relative"sv,
"material_ow_relative_correction"sv
};
std::vector<SLAPrintStep> steps;

View File

@ -868,7 +868,11 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
switch (opt->type)
{
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;
case coInt:
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") {
for (auto& prefix : { "", "branching" }) {
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);
}
}
else if (key == "relative_correction") {
for (auto& axis : { "x", "y", "z" }) {
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);
}
}
else {
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);
}
// m_overrides_options[key]->Enable(is_checked);
// m_overrides_options[key]->Enable(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) {
update_line_with_near_label_widget(*optgroup, key, false);
continue;
update_line_with_near_label_widget(*optgroup, key);
// // 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") {
for (auto& prefix : { "", "branching" })
update_line_with_near_label_widget(*optgroup, preprefix + prefix + key, is_checked);
}
else if (key == "relative_correction") {
for (auto& axis : { "x", "y", "z" })
update_line_with_near_label_widget(*optgroup, preprefix + key + "_" + char(axis[0]), is_checked);
}
else
update_line_with_near_label_widget(*optgroup, preprefix + key, is_checked);
// if (title == "Support head" || title == "Support pillar") {
// for (auto& prefix : { "", "branching" }) {
// update_line_with_near_label_widget(*optgroup, preprefix + prefix + key);
// }
// }
// else if (key == "relative_correction") {
// 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);
// }
}
}
}