scaleValue function

double scaleValue({
  1. required double value,
  2. required double fromDomainMin,
  3. required double fromDomainMax,
  4. required double toDomainMin,
  5. required double toDomainMax,
})

Scale the value that must be from the scale given by fromDomainMin - fromDomainMax to the "to scale" given by toDomainMin - toDomainMax.

The calculations are rather pig headed and should be made more terse; also could be separated by caching the scales which do not change unless data change.

Implementation

double scaleValue({
  required double value,
  required double fromDomainMin,
  required double fromDomainMax,
  required double toDomainMin,
  required double toDomainMax,
}) {
  var fromDomainLength = fromDomainMax - fromDomainMin;
  var toDomainLength = toDomainMax - toDomainMin;
  // Handle degenerate cases:
  // 1. If exactly one of the scales is zero length, exception.
  if (exactlyOneHasValue(
    one: fromDomainLength,
    two: toDomainLength,
    value: 0.0,
  )) {
    if (fromDomainLength == 0.0 && value == fromDomainMin) {
      // OK to have own scale degenerate, if value is the same as the degenerate min/max
      return toDomainMin;
      // all other cases (it is the axisY which is degenerate, or value is outside dataYsEnvelope
    } else {
      throw StateError(
          'Cannot convert value $value between scales $fromDomainMin, $fromDomainMax and $toDomainMin $toDomainMax');
    }
    // 2. If both scales are zero length:
  } else if (bothHaveValue(
    one: fromDomainLength,
    two: toDomainLength,
    value: 0.0,
  )) {
    // if value != dataYsEnvelopeMin (same as dataYsEnvelopeMax), exception
    if (value != fromDomainMin) {
      throw StateError('Value is not on own scale: $fromDomainMin, $fromDomainMax and $toDomainMin $toDomainMax');
      //  else return axisYMin (same as axisYMax)
    } else {
      return toDomainMin;
    }
  }
  // first move scales to be both starting at 0; also move value equivalently.
  // Naming the 0 based coordinates ending with 0
  double value0 = value - fromDomainMin;
  /*
  double dataYsEnvelopeMin0 = 0.0;
  double dataYsEnvelopeMax0 = fromDomainLength;
  double axisYMin0 = 0.0;
  double axisYMax0 = toDomainLength;
  */

  // Next scale the value to the 0 - 1 segment
  double value0ScaledTo01 = value0 / fromDomainLength;

  // Then scale value0Scaled01 to the 0 based axisY0
  double valueOnAxisY0 = value0ScaledTo01 * toDomainLength;

  // And finally shift the valueOnAxisY0 to a non-0 start on "to scale"

  double scaled = valueOnAxisY0 + toDomainMin;

  collectTestData('for_scaleValue_test', [value, fromDomainMin, fromDomainMax, toDomainMin, toDomainMax], scaled);

  return scaled;
}