scaleValue function
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;
}