diff --git a/src/scales/scale.linearbase.js b/src/scales/scale.linearbase.js index 568a67535b4..d504d54b568 100644 --- a/src/scales/scale.linearbase.js +++ b/src/scales/scale.linearbase.js @@ -17,8 +17,8 @@ function generateTicks(generationOptions, dataRange) { // "nice number" algorithm. See https://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks // for details. - var MAX_PRECISION = 1e14; - var MIN_SPACING = 2e-15; + // Minimum spacing between ticks + var MIN_SPACING = 1e-14; var stepSize = generationOptions.stepSize; var unit = stepSize || 1; var maxNumSpaces = generationOptions.maxTicks - 1; @@ -27,21 +27,26 @@ function generateTicks(generationOptions, dataRange) { var precision = generationOptions.precision; var spacing, factor, niceMin, niceMax, numSpaces; - // sanitize dataRangee to MAX_PRECISION - var rmin = Math.floor(dataRange.min * MAX_PRECISION) / MAX_PRECISION; - var rmax = Math.ceil(dataRange.max * MAX_PRECISION) / MAX_PRECISION; + var rmin = dataRange.min; + var rmax = dataRange.max; + var isNullOrUndef = helpers.isNullOrUndef; // spacing is set to a nice number of the dataRange divided by maxNumSpaces. // stepSize is used as a minimum unit if it is specified. - // use MIN_SPACING as lower bound to avoid uneven steps with tiny numbers - spacing = Math.max(helpers.niceNum((rmax - rmin) / maxNumSpaces / unit) * unit, MIN_SPACING); + spacing = helpers.niceNum((rmax - rmin) / maxNumSpaces / unit) * unit; + + // In case of really small numbers and min / max are undefined, default to rmin / rmax + if (spacing < MIN_SPACING && isNullOrUndef(min) && isNullOrUndef(max)) { + return [rmin, rmax]; + } + numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing); if (numSpaces > maxNumSpaces) { // If the calculated num of spaces exceeds maxNumSpaces, recalculate it spacing = helpers.niceNum(numSpaces * spacing / maxNumSpaces / unit) * unit; } - if (stepSize || helpers.isNullOrUndef(precision)) { + if (stepSize || isNullOrUndef(precision)) { // If a precision is not specified, calculate factor based on spacing factor = Math.pow(10, helpers.decimalPlaces(spacing)); } else { @@ -56,10 +61,10 @@ function generateTicks(generationOptions, dataRange) { // If min, max and stepSize is set and they make an evenly spaced scale use it. if (stepSize) { // If very close to our whole number, use it. - if (!helpers.isNullOrUndef(min) && helpers.almostWhole(min / spacing, spacing / 1000)) { + if (!isNullOrUndef(min) && helpers.almostWhole(min / spacing, spacing / 1000)) { niceMin = min; } - if (!helpers.isNullOrUndef(max) && helpers.almostWhole(max / spacing, spacing / 1000)) { + if (!isNullOrUndef(max) && helpers.almostWhole(max / spacing, spacing / 1000)) { niceMax = max; } } @@ -71,13 +76,14 @@ function generateTicks(generationOptions, dataRange) { } else { numSpaces = Math.ceil(numSpaces); } + niceMin = Math.round(niceMin * factor) / factor; niceMax = Math.round(niceMax * factor) / factor; - ticks.push(helpers.isNullOrUndef(min) ? niceMin : min); + ticks.push(isNullOrUndef(min) ? niceMin : min); for (var j = 1; j < numSpaces; ++j) { ticks.push(Math.round((niceMin + j * spacing) * factor) / factor); } - ticks.push(helpers.isNullOrUndef(max) ? niceMax : max); + ticks.push(isNullOrUndef(max) ? niceMax : max); return ticks; }