From 2f545c0557d1a97909183e070e6bbf14cc675f8e Mon Sep 17 00:00:00 2001 From: David Alban Date: Mon, 2 May 2022 18:05:08 +0100 Subject: [PATCH] Update logarithmicScale (used when forceNiceScale=false) to respect yMin andyMax limits without changing them, and provide a useful log scale between them. --- src/modules/Scales.js | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/modules/Scales.js b/src/modules/Scales.js index 67eecf9cc..617424d84 100644 --- a/src/modules/Scales.js +++ b/src/modules/Scales.js @@ -183,22 +183,40 @@ export default class Range { } logarithmicScale(yMin, yMax, base) { + // Basic validation to avoid for loop starting at -inf. + if (yMax <= 0) yMax = Math.max(yMin, base) + if (yMin <= 0) yMin = Math.min(yMax, base) + const logs = [] - const ticks = Math.ceil(Math.log(yMax) / Math.log(base)) + 1 // Get powers of base up to our max, and then one more + // Get the logarithmic range. + const logMax = Math.log(yMax) / Math.log(base) + const logMin = Math.log(yMin) / Math.log(base) - for (let i = 0; i < ticks; i++) { - logs.push(Math.pow(base, i)) - } + // Get the exact logarithmic range. + // (This is the exact number of multiples of the base there are between yMin and yMax). + const logRange = logMax - logMin - if (yMin === 0) { - logs.unshift(yMin) + // Round the logarithmic range to get the number of ticks we will create. + // If the chosen min/max values are multiples of each other WRT the base, this will be neat. + // If the chosen min/max aren't, we will at least still provide USEFUL ticks. + const ticks = Math.round(logRange) + + // Get the logarithmic spacing between ticks. + const logTickSpacing = logRange / ticks + + // Create as many ticks as there is range in the logs. + for (let i = 0, logTick = logMin; i < ticks; i++, logTick += logTickSpacing) { + logs.push(Math.pow(base, logTick)) } + // Add a final tick at the yMax. + logs.push(Math.pow(base, logMax)) + return { result: logs, - niceMin: logs[0], - niceMax: logs[logs.length - 1] + niceMin: yMin, + niceMax: yMax } }