Fix: Fixed the values comparison for Float-based config options (#12478)

This commit is contained in:
Valerii Bokhan 2026-02-26 13:28:45 +01:00 committed by GitHub
parent 3a61fefa3a
commit 76436bb29a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 9 deletions

View file

@ -37,9 +37,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 is_approx(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) throw() { return l.value < r.value || (is_approx(l.value, r.value) && int(l.percent) < int(r.percent)); }
}
namespace std {
@ -762,8 +762,8 @@ public:
ConfigOptionType type() const override { return static_type(); }
double getFloat() const override { return this->value; }
ConfigOption* clone() const override { return new ConfigOptionFloat(*this); }
bool operator==(const ConfigOptionFloat &rhs) const throw() { return this->value == rhs.value; }
bool operator< (const ConfigOptionFloat &rhs) const throw() { return this->value < rhs.value; }
bool operator==(const ConfigOptionFloat &rhs) const throw() { return is_approx(this->value, rhs.value); }
bool operator< (const ConfigOptionFloat &rhs) const throw() { return this->value < rhs.value; }
std::string serialize() const override
{
@ -780,6 +780,14 @@ public:
return !iss.fail();
}
bool operator==(const ConfigOption &rhs) const override
{
if (rhs.type() != this->type())
throw ConfigurationError("ConfigOptionFloat: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionFloat*>(&rhs));
return *this == *static_cast<const ConfigOptionFloat*>(&rhs);
}
ConfigOptionFloat& operator=(const ConfigOption *opt)
{
this->set(opt);
@ -906,7 +914,7 @@ protected:
if (v1.size() != v2.size())
return false;
for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end(); ++ it1, ++ it2)
if (! ((std::isnan(*it1) && std::isnan(*it2)) || *it1 == *it2))
if (! ((std::isnan(*it1) && std::isnan(*it2)) || is_approx(*it1, *it2)))
return false;
return true;
} else
@ -1258,11 +1266,11 @@ public:
return *this == *static_cast<const ConfigOptionFloatOrPercent*>(&rhs);
}
bool operator==(const ConfigOptionFloatOrPercent &rhs) const throw()
{ return this->value == rhs.value && this->percent == rhs.percent; }
{ return is_approx(this->value, rhs.value) && this->percent == rhs.percent; }
size_t hash() const throw() override
{ size_t seed = std::hash<double>{}(this->value); return this->percent ? seed ^ 0x9e3779b9 : seed; }
bool operator< (const ConfigOptionFloatOrPercent &rhs) const throw()
{ return this->value < rhs.value || (this->value == rhs.value && int(this->percent) < int(rhs.percent)); }
{ return this->value < rhs.value || (is_approx(this->value, rhs.value) && int(this->percent) < int(rhs.percent)); }
double get_abs_value(double ratio_over) const
{ return this->percent ? (ratio_over * this->value / 100) : this->value; }

View file

@ -883,13 +883,18 @@ bool TextCtrl::value_was_changed()
case coInt:
return boost::any_cast<int>(m_value) != boost::any_cast<int>(val);
case coPercent:
case coPercents:
case coPercents: {
if (m_opt.nullable && std::isnan(boost::any_cast<double>(m_value)) &&
std::isnan(boost::any_cast<double>(val)))
return false;
return boost::any_cast<double>(m_value) != boost::any_cast<double>(val);
}
case coFloats:
case coFloat: {
if (m_opt.nullable && std::isnan(boost::any_cast<double>(m_value)) &&
std::isnan(boost::any_cast<double>(val)))
return false;
return boost::any_cast<double>(m_value) != boost::any_cast<double>(val);
return !is_approx(boost::any_cast<double>(m_value), boost::any_cast<double>(val));
}
case coString:
case coStrings: