From b2f4ef5d25e6d134b8edcabdeab2c6c2434a128c Mon Sep 17 00:00:00 2001 From: ispyisail Date: Mon, 7 Sep 2026 20:13:05 +1200 Subject: [PATCH] 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 --- sources/diagram.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 271e0713f..3c673c86c 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -45,13 +45,24 @@ #include 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 block: the element's own