Fix: positionKey() didn't sort coordinates numerically

Plain fixed-precision formatting ("%.4f") produces strings that don't
compare in numeric order once the integer part has a different digit
count -- e.g. "15.0000" sorts before "5.0000" as text, even though
15 > 5. That silently broke the determinism goal of this branch for
any diagram with coordinates spanning more than one digit width.

Shift into a non-negative range and zero-pad to a fixed width instead,
so the formatted string sorts the same way the number does, including
negative values.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-09-07 20:13:05 +12:00
parent 0d08a4e265
commit b2f4ef5d25
+16 -5
View File
@@ -45,13 +45,24 @@
#include <math.h>
namespace {
/// Format a position as a string that sorts the same way the numbers do
/// (fixed precision, so "-" and decimals compare correctly as text).
/// Format a coordinate as a string that sorts the same way the number
/// does. Plain fixed-precision formatting ("%.4f") does NOT do this --
/// e.g. "15.0000" sorts before "5.0000" as text even though 15 > 5 --
/// so shift into a non-negative range and zero-pad to a fixed width
/// before comparing.
QString coordinateKey(double v)
{
//Diagram coordinates are nowhere near this range; the offset and
//width just need to be big enough that shifted values are always
//non-negative and always the same digit count.
constexpr double offset = 1e9;
qint64 scaled = qint64(qRound64((v + offset) * 10000.0));
return QStringLiteral("%1").arg(scaled, 20, 10, QLatin1Char('0'));
}
QString positionKey(const QPointF &pos)
{
return QStringLiteral("%1|%2")
.arg(pos.x(), 0, 'f', 4)
.arg(pos.y(), 0, 'f', 4);
return coordinateKey(pos.x()) + QLatin1Char('|') + coordinateKey(pos.y());
}
/// Sort key for Diagram::toXml()'s <elements> block: the element's own