niceDomain function

YDomain niceDomain(
  1. double dataMin,
  2. double dataMax,
  3. double plotSize, {
  4. bool throughZero = true,
  5. double pixelsPerTick = 40,
})

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]);
}