mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[shared/interactive_curve_view_range] Change normalization tolerance
The loss of significance that occurs when subtracting the bounds of the axes must be taken into account when asserting whether the range is orthonormal.
This commit is contained in:
committed by
EmilieNumworks
parent
e09bd0a18c
commit
ea4770fc81
@@ -157,12 +157,8 @@ void InteractiveCurveViewRange::normalize(bool forceChangeY) {
|
||||
m_yRange.setMin(newYMin, k_lowerMaxFloat, k_upperMaxFloat);
|
||||
MemoizedCurveViewRange::protectedSetYMax(newYMax, k_lowerMaxFloat, k_upperMaxFloat);
|
||||
|
||||
/* When the coordinates reach 10^6, the float type is not precise enough to
|
||||
* properly normalize. */
|
||||
// FIXME : Fine a more precise way to filter the edge cases
|
||||
constexpr float limit = 1e6f;
|
||||
assert(isOrthonormal() || xMin() < -limit || xMax() > limit || yMin() < -limit || yMax() > limit);
|
||||
(void) limit; // Silence compilation warning about unused variable.
|
||||
/* The range should be close to orthonormal, unless it has been clipped because the maximum bounds have been reached. */
|
||||
assert(isOrthonormal() || xMin() <= - k_lowerMaxFloat || xMax() >= k_lowerMaxFloat || yMin() <= - k_lowerMaxFloat || yMax() >= k_lowerMaxFloat);
|
||||
setZoomNormalize(isOrthonormal());
|
||||
}
|
||||
|
||||
@@ -281,8 +277,17 @@ void InteractiveCurveViewRange::panToMakePointVisible(float x, float y, float to
|
||||
}
|
||||
|
||||
bool InteractiveCurveViewRange::isOrthonormal(float tolerance) const {
|
||||
if (tolerance == 0.f) {
|
||||
float xr = std::fabs(xMin()) > std::fabs(xMax()) ? xMax() / xMin() : xMin() / xMax();
|
||||
float yr = std::fabs(yMin()) > std::fabs(yMax()) ? yMax() / yMin() : yMin() / yMax();
|
||||
/* The subtraction x - y induces a loss of significance of -log2(1-x/y)
|
||||
* bits. Since normalizing requires computing xMax - xMin and yMax - yMin,
|
||||
* the ratio of the normalized range will deviate from the Normal ratio. We
|
||||
* add an extra two lost bits to account for loss of precision from other
|
||||
* sources. */
|
||||
tolerance = std::pow(2.f, - std::log2(std::min(1.f - xr, 1.f - yr)) - 23.f + 2.f);
|
||||
}
|
||||
float ratio = (yMax() - yMin()) / (xMax() - xMin());
|
||||
float ratioDifference = std::fabs(std::log(ratio / NormalYXRatio()));
|
||||
return ratioDifference <= tolerance;
|
||||
return ratio <= NormalYXRatio() + tolerance && ratio >= NormalYXRatio() - tolerance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ public:
|
||||
}
|
||||
|
||||
static constexpr float NormalYXRatio() { return NormalizedYHalfRange(1.f) / NormalizedXHalfRange(1.f); }
|
||||
/* A tolerance of 0.001 is necessary to cover the imprecision with the
|
||||
* largest ranges, around 10^7 */
|
||||
bool isOrthonormal(float tolerance = 1e-3f) const;
|
||||
/* If the tolerance is null, isOrthonormal will adapt the tolerance to take
|
||||
* the loss of significance when changing the ratio into account. */
|
||||
bool isOrthonormal(float tolerance = 0.f) const;
|
||||
|
||||
void setDelegate(InteractiveCurveViewRangeDelegate * delegate);
|
||||
uint32_t rangeChecksum() override;
|
||||
@@ -62,7 +62,7 @@ protected:
|
||||
constexpr static float k_lowerMaxFloat = 9E+7f;
|
||||
constexpr static float k_maxRatioPositionRange = 1E5f;
|
||||
/* The tolerance is chosen to normalize sqrt(x) */
|
||||
constexpr static float k_orthonormalTolerance = 0.7f;
|
||||
constexpr static float k_orthonormalTolerance = 0.24f;
|
||||
static float clipped(float x, bool isMax) { return Range1D::clipped(x, isMax, k_lowerMaxFloat, k_upperMaxFloat); }
|
||||
/* In normalized settings, we put each axis so that 1cm = 2 units. For now,
|
||||
* the screen has size 43.2mm * 57.6mm.
|
||||
|
||||
Reference in New Issue
Block a user