diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index d99098cad..114687371 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -154,27 +154,8 @@ int FunctionGraphController::numberOfCurves() const { } void FunctionGraphController::interestingRanges(InteractiveCurveViewRange * range) { - Poincare::Context * context = textFieldDelegateApp()->localContext(); - constexpr int maxLength = 10; - float xMins[maxLength], xMaxs[maxLength], yMins[maxLength], yMaxs[maxLength]; - int length = functionStore()->numberOfActiveFunctions(); - float ratio = InteractiveCurveViewRange::NormalYXRatio() / (1 + cursorTopMarginRatio() + cursorBottomMarginRatio()); - - for (int i = 0; i < length; i++) { - ExpiringPointer f = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(i)); - f->rangeForDisplay(xMins + i, xMaxs + i, yMins + i, yMaxs + i, ratio, context); - } - - float xMin, xMax, yMin, yMax; - Poincare::Zoom::CombineRanges(length, xMins, xMaxs, &xMin, &xMax); - Poincare::Zoom::CombineRanges(length, yMins, yMaxs, &yMin, &yMax); - Poincare::Zoom::SanitizeRange(&xMin, &xMax, &yMin, &yMax, range->NormalYXRatio()); - - range->setXMin(xMin); - range->setXMax(xMax); - range->setYMin(yMin); - range->setYMax(yMax); + InterestingRangesHelper(range, textFieldDelegateApp()->localContext(), functionStore(), ratio); } } diff --git a/apps/shared/interactive_curve_view_controller.cpp b/apps/shared/interactive_curve_view_controller.cpp index 49b2850ef..4373fed66 100644 --- a/apps/shared/interactive_curve_view_controller.cpp +++ b/apps/shared/interactive_curve_view_controller.cpp @@ -41,32 +41,7 @@ InteractiveCurveViewController::InteractiveCurveViewController(Responder * paren } float InteractiveCurveViewController::addMargin(float y, float range, bool isVertical, bool isMin) { - /* The provided min or max range limit y is altered by adding a margin. - * In pixels, the view's height occupied by the vertical range is equal to - * viewHeight - topMargin - bottomMargin. - * Hence one pixel must correspond to - * range / (viewHeight - topMargin - bottomMargin). - * Finally, adding topMargin pixels of margin, say at the top, comes down - * to adding - * range * topMargin / (viewHeight - topMargin - bottomMargin) - * which is equal to - * range * topMarginRatio / ( 1 - topMarginRatio - bottomMarginRatio) - * where - * topMarginRation = topMargin / viewHeight - * bottomMarginRatio = bottomMargin / viewHeight. - * The same goes horizontally. - */ - float topMarginRatio = isVertical ? cursorTopMarginRatio() : cursorRightMarginRatio(); - float bottomMarginRatio = isVertical ? cursorBottomMarginRatio() : cursorLeftMarginRatio(); - assert(topMarginRatio + bottomMarginRatio < 1); // Assertion so that the formula is correct - float ratioDenominator = 1 - bottomMarginRatio - topMarginRatio; - float ratio = isMin ? -bottomMarginRatio : topMarginRatio; - /* We want to add slightly more than the required margin, so that - * InteractiveCurveViewRange::panToMakePointVisible does not think a point is - * invisible due to precision problems when checking if it is outside the - * required margin. This is why we add a 1.05f factor. */ - ratio = 1.05f * ratio / ratioDenominator; - return y + ratio * range; + return AddMarginHelper(y, range, isVertical, isMin, cursorTopMarginRatio(), cursorBottomMarginRatio(), cursorLeftMarginRatio(), cursorRightMarginRatio()); } void InteractiveCurveViewController::updateZoomButtons() { diff --git a/apps/shared/interactive_curve_view_range_delegate.cpp b/apps/shared/interactive_curve_view_range_delegate.cpp new file mode 100644 index 000000000..b82eb80bf --- /dev/null +++ b/apps/shared/interactive_curve_view_range_delegate.cpp @@ -0,0 +1,58 @@ +#include "interactive_curve_view_range_delegate.h" +#include "interactive_curve_view_range.h" +#include "function_store.h" +#include + +namespace Shared { + +void InteractiveCurveViewRangeDelegate::InterestingRangesHelper(InteractiveCurveViewRange * range, Poincare::Context * context, FunctionStore * functionStore, float targetRatio) { + constexpr int maxLength = 10; + float xMins[maxLength], xMaxs[maxLength], yMins[maxLength], yMaxs[maxLength]; + int length = functionStore->numberOfActiveFunctions(); + + for (int i = 0; i < length; i++) { + ExpiringPointer f = functionStore->modelForRecord(functionStore->activeRecordAtIndex(i)); + f->rangeForDisplay(xMins + i, xMaxs + i, yMins + i, yMaxs + i, targetRatio, context); + } + + float xMin, xMax, yMin, yMax; + Poincare::Zoom::CombineRanges(length, xMins, xMaxs, &xMin, &xMax); + Poincare::Zoom::CombineRanges(length, yMins, yMaxs, &yMin, &yMax); + Poincare::Zoom::SanitizeRange(&xMin, &xMax, &yMin, &yMax, range->NormalYXRatio()); + + range->setXMin(xMin); + range->setXMax(xMax); + range->setYMin(yMin); + range->setYMax(yMax); +} + +float InteractiveCurveViewRangeDelegate::AddMarginHelper(float x, float range, bool isVertical, bool isMin, float top, float bottom, float left, float right) { + /* The provided min or max range limit y is altered by adding a margin. + * In pixels, the view's height occupied by the vertical range is equal to + * viewHeight - topMargin - bottomMargin. + * Hence one pixel must correspond to + * range / (viewHeight - topMargin - bottomMargin). + * Finally, adding topMargin pixels of margin, say at the top, comes down + * to adding + * range * topMargin / (viewHeight - topMargin - bottomMargin) + * which is equal to + * range * topMarginRatio / ( 1 - topMarginRatio - bottomMarginRatio) + * where + * topMarginRation = topMargin / viewHeight + * bottomMarginRatio = bottomMargin / viewHeight. + * The same goes horizontally. + */ + float topMarginRatio = isVertical ? top : right; + float bottomMarginRatio = isVertical ? bottom : left; + assert(topMarginRatio + bottomMarginRatio < 1); // Assertion so that the formula is correct + float ratioDenominator = 1 - bottomMarginRatio - topMarginRatio; + float ratio = isMin ? -bottomMarginRatio : topMarginRatio; + /* We want to add slightly more than the required margin, so that + * InteractiveCurveViewRange::panToMakePointVisible does not think a point is + * invisible due to precision problems when checking if it is outside the + * required margin. This is why we add a 1.05f factor. */ + ratio = 1.05f * ratio / ratioDenominator; + return x + ratio * range; +} + +} diff --git a/apps/shared/interactive_curve_view_range_delegate.h b/apps/shared/interactive_curve_view_range_delegate.h index d09961b33..8a163feaa 100644 --- a/apps/shared/interactive_curve_view_range_delegate.h +++ b/apps/shared/interactive_curve_view_range_delegate.h @@ -1,15 +1,21 @@ #ifndef SHARED_INTERACTIVE_CURVE_VIEW_DELEGATE_H #define SHARED_INTERACTIVE_CURVE_VIEW_DELEGATE_H +#include #include namespace Shared { class InteractiveCurveViewRange; +class FunctionStore; class InteractiveCurveViewRangeDelegate { public: static constexpr float k_defaultXHalfRange = 10.0f; + + static void InterestingRangesHelper(InteractiveCurveViewRange * range, Poincare::Context * context, FunctionStore * functionStore, float targetRatio); + static float AddMarginHelper(float x, float range, bool isVertical, bool isMin, float top, float bottom, float left, float right); + virtual float interestingXMin() const { return -k_defaultXHalfRange; } virtual bool defaultRangeIsNormalized() const { return false; } virtual void interestingRanges(InteractiveCurveViewRange * range) { assert(false); }