diff --git a/apps/shared/continuous_function.cpp b/apps/shared/continuous_function.cpp index 616866239..800698037 100644 --- a/apps/shared/continuous_function.cpp +++ b/apps/shared/continuous_function.cpp @@ -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 { diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index adeba5bd4..73ed5b298 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -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 { diff --git a/apps/shared/interactive_curve_view_range.cpp b/apps/shared/interactive_curve_view_range.cpp index 90b35fa0e..20eb45544 100644 --- a/apps/shared/interactive_curve_view_range.cpp +++ b/apps/shared/interactive_curve_view_range.cpp @@ -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; diff --git a/apps/shared/interactive_curve_view_range.h b/apps/shared/interactive_curve_view_range.h index f9c933e85..4ea7b9c58 100644 --- a/apps/shared/interactive_curve_view_range.h +++ b/apps/shared/interactive_curve_view_range.h @@ -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(); diff --git a/poincare/src/zoom.cpp b/poincare/src/zoom.cpp index e989340af..d03cb5ff0 100644 --- a/poincare/src/zoom.cpp +++ b/poincare/src/zoom.cpp @@ -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) {