summaryrefslogtreecommitdiffstats
path: root/generic/tkScale.c
diff options
context:
space:
mode:
authorjaspert <jaspert>2019-02-28 15:52:15 (GMT)
committerjaspert <jaspert>2019-02-28 15:52:15 (GMT)
commit7883dcdedb3af8454956e7599b139e350dbddfdf (patch)
treec71b83f34ce0163f89d54bbe2765f589098664a0 /generic/tkScale.c
parent31b66a6295cd71b19bc085fd8c1b6b660c327ad3 (diff)
downloadtk-7883dcdedb3af8454956e7599b139e350dbddfdf.zip
tk-7883dcdedb3af8454956e7599b139e350dbddfdf.tar.gz
tk-7883dcdedb3af8454956e7599b139e350dbddfdf.tar.bz2
Added a procedure to increase the number of digits in the tick values until
the maximum rounding error goes below a certain value, currently 0.2x the tick interval. Also fixed it to work with scales from larger to smaller values.
Diffstat (limited to 'generic/tkScale.c')
-rw-r--r--generic/tkScale.c54
1 files changed, 51 insertions, 3 deletions
diff --git a/generic/tkScale.c b/generic/tkScale.c
index 455c656..95cc399 100644
--- a/generic/tkScale.c
+++ b/generic/tkScale.c
@@ -759,6 +759,46 @@ ScaleWorldChanged(
TkEventuallyRedrawScale(scalePtr, REDRAW_ALL);
}
+
+
+ /*
+ *----------------------------------------------------------------------
+ *
+ * MaxTickRoundingError --
+ *
+ * Given the separation between values that can be displayed on ticks,
+ * this calculates the maximum magnitude of error for the displayed
+ * value. Tries to be clever by working out the increment in error
+ * between ticks rather than testing all of them, so may overestimate
+ * error if it is greater than 0.25 x the value separation.
+ *
+ * Results:
+ * Maximum error magnitude of tick numbers.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static double
+MaxTickRoundingError(
+ TkScale *scalePtr, /* Information about scale widget. */
+ double tickResolution) /* Separation between displayable values. */
+{
+ double tickPosn, firstTickError, lastTickError, intervalError;
+ int tickCount;
+
+ tickPosn = scalePtr->fromValue/tickResolution;
+ firstTickError = tickPosn - round(tickPosn);
+ tickPosn = scalePtr->tickInterval/tickResolution;
+ intervalError = tickPosn - round(tickPosn);
+ tickCount = (int)((scalePtr->toValue-scalePtr->fromValue) /
+ scalePtr->tickInterval); // not including first
+ lastTickError = fmin(fabs(firstTickError + tickCount*intervalError), 0.5);
+ return fmax(fabs(firstTickError),lastTickError)*tickResolution;
+}
+
/*
*----------------------------------------------------------------------
@@ -782,7 +822,7 @@ ComputeFormat(
TkScale *scalePtr, /* Information about scale widget. */
int forTicks) /* Do for ticks rather than value */
{
- double maxValue, x;
+ double maxValue, x, tickResolution;
int mostSigDigit, numDigits, leastSigDigit, afterDecimal;
int eDigits, fDigits;
@@ -807,8 +847,16 @@ ComputeFormat(
* values
*/
- if (scalePtr->tickInterval > 0) {
- numDigits = 1 + mostSigDigit - (int) floor(log10(scalePtr->tickInterval));
+ if (scalePtr->tickInterval != 0) {
+ leastSigDigit = (int) floor(log10(fabs(scalePtr->tickInterval)));
+ /*
+ * Now add more digits until max error is less than 0.2 intervals
+ */
+ while (MaxTickRoundingError(scalePtr, pow(10,leastSigDigit)) >
+ fabs(0.2*scalePtr->tickInterval))
+ --leastSigDigit;
+
+ numDigits = 1 + mostSigDigit - leastSigDigit;
} else {
numDigits = 1;
}