niceDomain function
d3-style nice domain: dataMin, dataMax widened to round tick
boundaries. throughZero pins the domain to include zero (the
React cartesian rule); scatter axes pass false. pixelsPerTick
sets the target tick density (40 for value axes, 60 for the
wider bottom labels).
Implementation
YDomain niceDomain(double dataMin, double dataMax, double plotSize, {bool throughZero = true, double pixelsPerTick = 40}) {
var lo = throughZero ? math.min(0, dataMin) : dataMin;
var hi = throughZero ? math.max(0, dataMax) : dataMax;
if (lo == hi) hi = lo + 1;
final target = math.max(2, (plotSize / pixelsPerTick).floor());
final span = hi - lo;
var step = math.pow(10, (math.log(span / target) / math.ln10).floorToDouble()).toDouble();
final err = (span / target) / step;
if (err >= math.sqrt(50)) {
step *= 10;
} else if (err >= math.sqrt(10)) {
step *= 5;
} else if (err >= math.sqrt(2)) {
step *= 2;
}
final niceMin = (lo / step).floor() * step;
final niceMax = (hi / step).ceil() * step;
final count = ((niceMax - niceMin) / step).round();
return (min: niceMin, max: niceMax, ticks: [for (var i = 0; i <= count; i++) niceMin + i * step]);
}