From 7b8973f0205d729ab3ad13f609fae76bb64af714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 9 Sep 2019 10:22:44 +0200 Subject: [PATCH] [apps/graph] Move nextIntersectionFrom method from controller to model and take into account the function domain in the intersection computation --- .../graph/intersection_graph_controller.cpp | 7 ++----- apps/shared/cartesian_function.cpp | 21 +++++++++++++++++++ apps/shared/cartesian_function.h | 3 +++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/apps/graph/graph/intersection_graph_controller.cpp b/apps/graph/graph/intersection_graph_controller.cpp index abf46f87e..6257d9fe4 100644 --- a/apps/graph/graph/intersection_graph_controller.cpp +++ b/apps/graph/graph/intersection_graph_controller.cpp @@ -42,15 +42,12 @@ void IntersectionGraphController::reloadBannerView() { Poincare::Coordinate2D IntersectionGraphController::computeNewPointOfInterest(double start, double step, double max, Poincare::Context * context) { // TODO The following three lines should be factored. - constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1; - char unknownX[bufferSize]; - Poincare::SerializationHelper::CodePoint(unknownX, bufferSize, UCodePointUnknownX); Poincare::Coordinate2D result = Poincare::Coordinate2D(NAN, NAN); for (int i = 0; i < functionStore()->numberOfActiveFunctions(); i++) { Ion::Storage::Record record = functionStore()->activeRecordAtIndex(i); if (record != m_record) { - Poincare::Expression e = functionStore()->modelForRecord(record)->expressionReduced(context); - Poincare::Coordinate2D intersection = Shared::PoincareHelpers::NextIntersection(functionStore()->modelForRecord(m_record)->expressionReduced(context), unknownX, start, step, max, context, e); + CartesianFunction f = *(functionStore()->modelForRecord(record)); + Poincare::Coordinate2D intersection = functionStore()->modelForRecord(m_record)->nextIntersectionFrom(start, step, max, context, &f); if ((std::isnan(result.x1()) || std::fabs(intersection.x1()-start) < std::fabs(result.x1()-start)) && !std::isnan(intersection.x1())) { m_intersectedRecord = record; result = (std::isnan(result.x1()) || std::fabs(intersection.x1()-start) < std::fabs(result.x1()-start)) ? intersection : result; diff --git a/apps/shared/cartesian_function.cpp b/apps/shared/cartesian_function.cpp index 70ec010d5..463820a1c 100644 --- a/apps/shared/cartesian_function.cpp +++ b/apps/shared/cartesian_function.cpp @@ -16,6 +16,9 @@ using namespace Poincare; namespace Shared { +static inline double maxDouble(double x, double y) { return x > y ? x : y; } +static inline double minDouble(double x, double y) { return x < y ? x : y; } + void CartesianFunction::DefaultName(char buffer[], size_t bufferSize) { constexpr int k_maxNumberOfDefaultLetterNames = 4; static constexpr const char k_defaultLetterNames[k_maxNumberOfDefaultLetterNames] = { @@ -271,6 +274,24 @@ Coordinate2D CartesianFunction::templatedApproximateAtParameter(T t, Poincare PoincareHelpers::ApproximateWithValueForSymbol(e.childAtIndex(1), unknown, t, context)); } +Coordinate2D CartesianFunction::nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, CartesianFunction * f) const { + assert(plotType() == PlotType::Cartesian); + constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1; + char unknownX[bufferSize]; + SerializationHelper::CodePoint(unknownX, bufferSize, UCodePointUnknownX); + double domainMin = maxDouble(tMin(), f->tMin()); + double domainMax = minDouble(tMax(), f->tMax()); + if (step > 0.0f) { + start = maxDouble(start, domainMin); + max = minDouble(max, domainMax); + } else { + start = minDouble(start, domainMax); + max = maxDouble(max, domainMin); + } + return PoincareHelpers::NextIntersection(expressionReduced(context), unknownX, start, step, max, context, f->expressionReduced(context)); +} + + template Coordinate2D CartesianFunction::templatedApproximateAtParameter(float, Poincare::Context *) const; template Coordinate2D CartesianFunction::templatedApproximateAtParameter(double, Poincare::Context *) const; diff --git a/apps/shared/cartesian_function.h b/apps/shared/cartesian_function.h index d0b9e5b8a..6f8b90a6e 100644 --- a/apps/shared/cartesian_function.h +++ b/apps/shared/cartesian_function.h @@ -5,6 +5,7 @@ #include "function.h" #include "range_1D.h" #include +#include namespace Shared { @@ -56,6 +57,8 @@ public: void setTMax(float tMax); float rangeStep() const override { return plotType() == PlotType::Cartesian ? NAN : (tMax() - tMin())/k_polarParamRangeSearchNumberOfPoints; } + // Cartesian calculation + Poincare::Coordinate2D nextIntersectionFrom(double start, double step, double max, Poincare::Context * context, CartesianFunction * f) const; private: constexpr static float k_polarParamRangeSearchNumberOfPoints = 100.0f; // This is ad hoc, no special justification template Poincare::Coordinate2D privateEvaluateXYAtParameter(T t, Poincare::Context * context) const;