[poincare/zoom] Handle undefined functions

Rework the logic so that :
  - an undefined function will be displayed with a clealry defined
    null range.
  - display both an undefined function and a correct function at the
    same time will not affect the correct range.

Change-Id: Ife9dc0d2ace667cab5a6b8826347078fca33e4d5
This commit is contained in:
Gabriel Ozouf
2020-10-15 11:34:28 +02:00
committed by Émilie Feral
parent 20cbefad41
commit 958b172d08
5 changed files with 62 additions and 15 deletions

View File

@@ -285,10 +285,39 @@ void ContinuousFunction::rangeForDisplay(float * xMin, float * xMax, float * yMi
};
if (fullyComputed) {
/* The function has points of interest. */
Zoom::RefinedYRangeForDisplay(evaluation, *xMin, *xMax, yMin, yMax, context, this);
} else {
Zoom::RangeWithRatioForDisplay(evaluation, InteractiveCurveViewRange::NormalYXRatio(), xMin, xMax, yMin, yMax, context, this);
return;
}
/* Try to display an orthonormal range. */
Zoom::RangeWithRatioForDisplay(evaluation, InteractiveCurveViewRange::NormalYXRatio(), xMin, xMax, yMin, yMax, context, this);
if (std::isfinite(*xMin) && std::isfinite(*xMax) && std::isfinite(*yMin) && std::isfinite(*yMax)) {
return;
}
/* The function's profile is not great for an orthonormal range.
* Try a basic range. */
*xMin = - Zoom::k_defaultHalfRange;
*xMax = Zoom::k_defaultHalfRange;
Zoom::RefinedYRangeForDisplay(evaluation, *xMin, *xMax, yMin, yMax, context, this);
if (std::isfinite(*xMin) && std::isfinite(*xMax) && std::isfinite(*yMin) && std::isfinite(*yMax)) {
return;
}
/* The function's order of magnitude cannot be computed. Try to just display
* the full function. */
float step = (*xMax - *xMin) / k_polarParamRangeSearchNumberOfPoints;
Zoom::FullRange(evaluation, *xMin, *xMax, step, yMin, yMax, context, this);
if (std::isfinite(*xMin) && std::isfinite(*xMax) && std::isfinite(*yMin) && std::isfinite(*yMax)) {
return;
}
/* The function is probably undefined. */
*xMin = NAN;
*xMax = NAN;
*yMin = NAN;
*yMax = NAN;
}
void * ContinuousFunction::Model::expressionAddress(const Ion::Storage::Record * record) const {

View File

@@ -160,12 +160,15 @@ void FunctionGraphController::interestingRanges(InteractiveCurveViewRange * rang
float xMin, xMax, yMin, yMax;
Poincare::Zoom::CombineRanges(length, xMins, xMaxs, &xMin, &xMax);
Poincare::Zoom::CombineRanges(length, yMins, yMaxs, &yMin, &yMax);
range->setXMin(xMin);
range->setXMax(xMax);
range->setYMin(yMin);
range->setYMax(yMax);
yRangeForCursorFirstMove(range);
if (std::isfinite(xMin) && std::isfinite(xMax) && std::isfinite(yMin) && std::isfinite(yMax) && xMax > xMin && yMax > yMin) {
range->setXMin(xMin);
range->setXMax(xMax);
range->setYMin(yMin);
range->setYMax(yMax);
yRangeForCursorFirstMove(range);
} else {
range->setNullRange();
}
}
void FunctionGraphController::yRangeForCursorFirstMove(InteractiveCurveViewRange * range) const {

View File

@@ -134,6 +134,14 @@ void InteractiveCurveViewRange::setDefault() {
normalize();
}
void InteractiveCurveViewRange::setNullRange() {
m_xRange.setMin(- Range1D::k_default);
setXMax(Range1D::k_default);
m_yRange.setMin(0);
m_yRange.setMax(0);
normalize();
}
void InteractiveCurveViewRange::centerAxisAround(Axis axis, float position) {
if (std::isnan(position)) {
return;

View File

@@ -44,6 +44,7 @@ public:
void panWithVector(float x, float y);
virtual void normalize();
virtual void setDefault();
void setNullRange();
void centerAxisAround(Axis axis, float position);
void panToMakePointVisible(float x, float y, float topMarginRatio, float rightMarginRatio, float bottomMarginRation, float leftMarginRation, float pixelWidth);
void checkForNormalizedRange();

View File

@@ -146,8 +146,8 @@ bool Zoom::InterestingRangesForDisplay(ValueAtAbscissa evaluation, float * xMin,
resultX[1] = std::max(resultX[1], asymptote[1]);
if (resultX[0] >= resultX[1]) {
/* Fallback to default range. */
resultX[0] = - k_defaultHalfRange;
resultX[1] = k_defaultHalfRange;
resultX[0] = NAN;
resultX[1] = NAN;
return false;
} else {
resultX[0] = std::min(resultX[0], explosion[0]);
@@ -195,8 +195,9 @@ void Zoom::RefinedYRangeForDisplay(ValueAtAbscissa evaluation, float xMin, float
* order of magnitude and is used to cut the Y range. */
if (pop == 0) {
*yMin = 0;
*yMax = 0;
*yMin = NAN;
*yMax = NAN;
return;
} else {
float bound = std::exp(sum / pop + 1.f);
sampleYMin = std::max(sampleYMin, - bound);
@@ -286,9 +287,10 @@ void Zoom::RangeWithRatioForDisplay(ValueAtAbscissa evaluation, float yxRatio, f
xMagnitude *= 10.f;
}
if (bestGrade == FLT_MAX) {
*xMin = -k_defaultHalfRange;
*xMax = k_defaultHalfRange;
RefinedYRangeForDisplay(evaluation, *xMin, *xMax, yMin, yMax, context, auxiliary);
*xMin = NAN;
*xMax = NAN;
*yMin = NAN;
*yMax = NAN;
return;
}
@@ -309,6 +311,10 @@ void Zoom::FullRange(ValueAtAbscissa evaluation, float tMin, float tMax, float t
}
t += tStep;
}
if (*fMin > *fMax) {
*fMin = NAN;
*fMax = NAN;
}
}
void Zoom::RangeFromSingleValue(float value, float * boundMin, float * boundMax) {