[poincare/zoom] Detect explosions

Add a clause in InterestingRangesForDisplay to detect strong variations.
This improve the graph for x^x or x^2+x+1 for instance.

Change-Id: I74214c2382cfe4b0e2603556dd8c6cbd450effc0
This commit is contained in:
Gabriel Ozouf
2020-10-14 11:51:31 +02:00
committed by Émilie Feral
parent 8ce9f363ad
commit 1bfeeb5842
2 changed files with 12 additions and 1 deletions

View File

@@ -38,6 +38,7 @@ private:
static constexpr float k_maximalDistance = 1e5f;
static constexpr float k_minimalDistance = 1e-2f;
static constexpr float k_asymptoteThreshold = 2e-1f;
static constexpr float k_explosionThreshold = 1e1f;
static constexpr float k_stepFactor = 1.1f;
static constexpr float k_breathingRoom = 0.3f;
static constexpr float k_forceXAxisThreshold = 0.2f;

View File

@@ -11,6 +11,7 @@ constexpr float
Zoom::k_maximalDistance,
Zoom::k_minimalDistance,
Zoom::k_asymptoteThreshold,
Zoom::k_explosionThreshold,
Zoom::k_stepFactor,
Zoom::k_breathingRoom,
Zoom::k_forceXAxisThreshold,
@@ -37,6 +38,7 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
float resultX[2] = {FLT_MAX, - FLT_MAX};
float resultYMin = FLT_MAX, resultYMax = - FLT_MAX;
float asymptote[2] = {FLT_MAX, - FLT_MAX};
float explosion[2] = {FLT_MAX, - FLT_MAX};
int numberOfPoints;
float xFallback, yFallback[2] = {NAN, NAN};
float firstResult;
@@ -106,6 +108,7 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
}
case static_cast<uint8_t>(PointOfInterest::Root):
asymptote[i] = i == 0 ? FLT_MAX : - FLT_MAX;
explosion[i] = i == 0 ? FLT_MAX : - FLT_MAX;
resultX[0] = std::min(resultX[0], center + (i == 0 ? dXNext : dXPrev));
resultX[1] = std::max(resultX[1], center + (i == 1 ? dXNext : dXPrev));
if (std::isnan(firstResult)) {
@@ -117,11 +120,16 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
if ((std::fabs(slopeNext) < k_asymptoteThreshold) && (std::fabs(slopePrev) > k_asymptoteThreshold)) {
// Horizontal asymptote begins
asymptote[i] = (i == 0) ? std::min(asymptote[i], center + dXNext) : std::max(asymptote[i], center + dXNext);
} else if ((std::fabs(slopeNext) < k_asymptoteThreshold) && (std::fabs(slopePrev) > k_asymptoteThreshold)) {
} else if ((std::fabs(slopeNext) > k_asymptoteThreshold) && (std::fabs(slopePrev) < k_asymptoteThreshold)) {
// Horizontal asymptote invalidates : it might be an asymptote when
// going the other way.
asymptote[1 - i] = (i == 1) ? std::min(asymptote[1 - i], center + dXPrev) : std::max(asymptote[1 - i], center + dXPrev);
}
if (std::fabs(slopeNext) > k_explosionThreshold && std::fabs(slopePrev) < k_explosionThreshold) {
explosion[i] = (i == 0) ? std::min(explosion[i], center + dXNext) : std::max(explosion[i], center + dXNext);
} else if (std::fabs(slopeNext) < k_explosionThreshold && std::fabs(slopePrev) > k_explosionThreshold) {
explosion[1 - i] = (i == 1) ? std::min(explosion[1 - i], center + dXPrev) : std::max(explosion[1 - i], center + dXPrev);
}
}
}
if (std::fabs(resultX[i]) > std::fabs(firstResult) * k_maxRatioBetweenPointsOfInterest && !std::isnan(xFallback)) {
@@ -142,6 +150,8 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
resultX[1] = k_defaultHalfRange;
return false;
} else {
resultX[0] = std::min(resultX[0], explosion[0]);
resultX[1] = std::max(resultX[1], explosion[1]);
/* Add breathing room around points of interest. */
float xRange = resultX[1] - resultX[0];
resultX[0] -= k_breathingRoom * xRange;