diff --git a/apps/graph/graph/graph_controller_helper.cpp b/apps/graph/graph/graph_controller_helper.cpp index 59364ce9e..466643dca 100644 --- a/apps/graph/graph/graph_controller_helper.cpp +++ b/apps/graph/graph/graph_controller_helper.cpp @@ -24,7 +24,7 @@ bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCurso t += dir; //TODO LEA delt } - Coordinate2D xy = function->xyEvaluationAtParameter(t, App::app()->localContext()); + Coordinate2D xy = function->evaluateXYAtParameter(t, App::app()->localContext()); cursor->moveTo(t, xy.x(), xy.y()); return true; } diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index e674ce092..e09f22ee1 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -30,40 +30,39 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { ExpiringPointer f = m_functionStore->modelForRecord(record);; switch (f->plotType()) { + case Shared::CartesianFunction::PlotType::Cartesian: drawCartesianCurve(ctx, rect, [](float t, void * model, void * context) { CartesianFunction * f = (CartesianFunction *)model; Poincare::Context * c = (Poincare::Context *)context; - return f->evaluateAtParameter(t, c).y(); + return f->evaluateXYAtParameter(t, c); }, f.operator->(), context(), f->color(), record == m_selectedRecord, m_highlightedStart, m_highlightedEnd); /* Draw tangent */ if (m_tangent && record == m_selectedRecord) { float tangentParameter[2]; tangentParameter[0] = f->approximateDerivative(m_curveViewCursor->x(), context()); - tangentParameter[1] = -tangentParameter[0]*m_curveViewCursor->x()+f->evaluateAtParameter(m_curveViewCursor->x(), context()).y(); + tangentParameter[1] = -tangentParameter[0]*m_curveViewCursor->x()+f->evaluateXYAtParameter(m_curveViewCursor->x(), context()).x2(); drawCartesianCurve(ctx, rect, [](float t, void * model, void * context) { float * tangent = (float *)model; - return tangent[0]*t+tangent[1]; + return Poincare::Coordinate2D(t, tangent[0]*t+tangent[1]); }, tangentParameter, nullptr, Palette::GreyVeryDark); } break; + case Shared::CartesianFunction::PlotType::Polar: drawCurve(ctx, rect, 0.0f, 396.0f, 36.0f, [](float t, void * model, void * context) { //TODO LEA RUBEN use the models's tMin, tMax CartesianFunction * f = (CartesianFunction *)model; Poincare::Context * c = (Poincare::Context *)context; - return f->evaluateAtParameter(t, c).y() * std::cos(t); - }, [](float t, void * model, void * context) { - CartesianFunction * f = (CartesianFunction *)model; - Poincare::Context * c = (Poincare::Context *)context; - return f->evaluateAtParameter(t, c).y() * std::sin(t); + return f->evaluateXYAtParameter(t, c); }, f.operator->(), context(), false, f->color()); break; + case Shared::CartesianFunction::PlotType::Parametric: drawCurve(ctx, rect, 0.0f, 396.0f, 36.0f, [](float t, void * model, void * context) { //TODO LEA RUBEN use the models's tMin, tMax CartesianFunction * f = (CartesianFunction *)model; Poincare::Context * c = (Poincare::Context *)context; if (f->isCircularlyDefined(c)) { - return NAN; + return Poincare::Coordinate2D(NAN, NAN); } constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1; char unknownX[bufferSize]; @@ -71,36 +70,15 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { Poincare::VariableContext variableContext(unknownX, c); variableContext.setApproximationForVariable(t); Poincare::Expression e = f->expressionReduced(c); - assert( - e.type() == Poincare::ExpressionNode::Type::Matrix && - static_cast(e).numberOfRows() == 2 && - static_cast(e).numberOfColumns() == 1 - ); + assert(e.type() == Poincare::ExpressionNode::Type::Matrix + && static_cast(e).numberOfRows() == 2 + && static_cast(e).numberOfColumns() == 1); Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, c); - return e.childAtIndex(0).approximateToScalar(&variableContext, complexFormat, preferences->angleUnit()); - }, [](float t, void * model, void * context) { - CartesianFunction * f = (CartesianFunction *)model; - Poincare::Context * c = (Poincare::Context *)context; - if (f->isCircularlyDefined(c)) { - return NAN; - } - constexpr int bufferSize = CodePoint::MaxCodePointCharLength + 1; - char unknownX[bufferSize]; - Poincare::SerializationHelper::CodePoint(unknownX, bufferSize, UCodePointUnknownX); - Poincare::VariableContext variableContext(unknownX, c); - variableContext.setApproximationForVariable(t); - Poincare::Expression e = f->expressionReduced(c); - assert( - e.type() == Poincare::ExpressionNode::Type::Matrix && - static_cast(e).numberOfRows() == 2 && - static_cast(e).numberOfColumns() == 1 - ); - Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences(); - Poincare::Preferences::ComplexFormat complexFormat = Poincare::Expression::UpdatedComplexFormatWithExpressionInput(preferences->complexFormat(), e, c); - return e.childAtIndex(1).approximateToScalar(&variableContext, complexFormat, preferences->angleUnit()); + return Poincare::Coordinate2D(e.childAtIndex(0).approximateToScalar(&variableContext, complexFormat, preferences->angleUnit()), e.childAtIndex(1).approximateToScalar(&variableContext, complexFormat, preferences->angleUnit())); }, f.operator->(), context(), false, f->color()); break; + default: assert(false); } diff --git a/apps/graph/graph/tangent_graph_controller.cpp b/apps/graph/graph/tangent_graph_controller.cpp index f3f5fa8b2..c349cc6bf 100644 --- a/apps/graph/graph/tangent_graph_controller.cpp +++ b/apps/graph/graph/tangent_graph_controller.cpp @@ -47,7 +47,7 @@ bool TangentGraphController::textFieldDidFinishEditing(TextField * textField, co } ExpiringPointer function = App::app()->functionStore()->modelForRecord(m_record); assert(function->plotType() == Shared::CartesianFunction::PlotType::Cartesian); - double y = function->evaluateAtParameter(floatBody, myApp->localContext()).y(); + double y = function->evaluate2DAtParameter(floatBody, myApp->localContext()).x2(); m_cursor->moveTo(floatBody, floatBody, y); interactiveCurveViewRange()->panToMakePointVisible(m_cursor->x(), m_cursor->y(), cursorTopMarginRatio(), k_cursorRightMarginRatio, cursorBottomMarginRatio(), k_cursorLeftMarginRatio); reloadBannerView(); @@ -82,7 +82,7 @@ void TangentGraphController::reloadBannerView() { legendLength = strlcpy(buffer, legend, bufferSize); Shared::TextFieldDelegateApp * myApp = textFieldDelegateApp(); assert(function->plotType() == Shared::CartesianFunction::PlotType::Cartesian); - y = -y*m_cursor->x()+function->evaluateAtParameter(m_cursor->x(), myApp->localContext()).y(); + y = -y*m_cursor->x()+function->evaluate2DAtParameter(m_cursor->x(), myApp->localContext()).x2(); PoincareHelpers::ConvertFloatToText(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(precision), precision); m_bannerView->bView()->setText(buffer); m_bannerView->reload(); diff --git a/apps/graph/values/values_controller.cpp b/apps/graph/values/values_controller.cpp index c9dc19dc0..5df51b57c 100644 --- a/apps/graph/values/values_controller.cpp +++ b/apps/graph/values/values_controller.cpp @@ -152,7 +152,7 @@ double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int colum return function->approximateDerivative(abscissa, context); } //TODO LEA RUBEN - return function->evaluateAtParameter(abscissa, context).x(); + return function->evaluate2DAtParameter(abscissa, context).x1(); } void ValuesController::updateNumberOfColumns() { diff --git a/apps/probability/distribution/distribution.cpp b/apps/probability/distribution/distribution.cpp index 51a2f0c60..8379a94a5 100644 --- a/apps/probability/distribution/distribution.cpp +++ b/apps/probability/distribution/distribution.cpp @@ -126,8 +126,8 @@ double Distribution::cumulativeDistributiveInverseForProbabilityUsingIncreasingF this, probability, nullptr); - assert(std::isnan(result.y()) || std::fabs(result.y()) < FLT_EPSILON); - return result.x(); + assert(std::isnan(result.x2()) || std::fabs(result.x2()) < FLT_EPSILON); + return result.x1(); } float Distribution::yMin() const { diff --git a/apps/probability/distribution_curve_view.cpp b/apps/probability/distribution_curve_view.cpp index c1184fefb..640fca7d3 100644 --- a/apps/probability/distribution_curve_view.cpp +++ b/apps/probability/distribution_curve_view.cpp @@ -25,7 +25,7 @@ void DistributionCurveView::drawRect(KDContext * ctx, KDRect rect) const { return; } if (m_distribution->isContinuous()) { - drawCartesianCurve(ctx, rect, EvaluateAtAbscissa, m_distribution, nullptr, Palette::YellowDark, true, lowerBound, upperBound); + drawCartesianCurve(ctx, rect, EvaluateXYAtAbscissa, m_distribution, nullptr, Palette::YellowDark, true, lowerBound, upperBound); } else { drawHistogram(ctx, rect, EvaluateAtAbscissa, m_distribution, nullptr, 0, 1, false, Palette::GreyMiddle, Palette::YellowDark, lowerBound, upperBound+0.5f); } @@ -43,6 +43,10 @@ float DistributionCurveView::EvaluateAtAbscissa(float abscissa, void * model, vo return distribution->evaluateAtAbscissa(abscissa); } +Poincare::Coordinate2D DistributionCurveView::EvaluateXYAtAbscissa(float abscissa, void * model, void * context) { + return Poincare::Coordinate2D(abscissa, EvaluateAtAbscissa(abscissa, model, context)); +} + void DistributionCurveView::drawStandardNormal(KDContext * ctx, KDRect rect, float colorLowerBound, float colorUpperBound) const { // Save the previous curve view range DistributionCurveView * constCastedThis = const_cast(this); @@ -51,7 +55,7 @@ void DistributionCurveView::drawStandardNormal(KDContext * ctx, KDRect rect, flo // Draw a centered reduced normal curve NormalDistribution n; constCastedThis->setCurveViewRange(&n); - drawCartesianCurve(ctx, rect, EvaluateAtAbscissa, &n, nullptr, Palette::YellowDark, true, colorLowerBound, colorUpperBound); + drawCartesianCurve(ctx, rect, EvaluateXYAtAbscissa, &n, nullptr, Palette::YellowDark, true, colorLowerBound, colorUpperBound); // Put back the previous curve view range constCastedThis->setCurveViewRange(previousRange); diff --git a/apps/probability/distribution_curve_view.h b/apps/probability/distribution_curve_view.h index 313bcf847..68af5e3c3 100644 --- a/apps/probability/distribution_curve_view.h +++ b/apps/probability/distribution_curve_view.h @@ -7,6 +7,7 @@ #include "calculation/calculation.h" #include #include +#include namespace Probability { @@ -28,6 +29,7 @@ protected: char * label(Axis axis, int index) const override; private: static float EvaluateAtAbscissa(float abscissa, void * model, void * context); + static Poincare::Coordinate2D EvaluateXYAtAbscissa(float abscissa, void * model, void * context); static constexpr KDColor k_backgroundColor = Palette::WallScreen; void drawStandardNormal(KDContext * ctx, KDRect rect, float colorLowerBound, float colorUpperBound) const; char m_labels[k_maxNumberOfXLabels][k_labelBufferMaxSize]; diff --git a/apps/regression/graph_view.cpp b/apps/regression/graph_view.cpp index 3fc7c71d2..ea03cc5f6 100644 --- a/apps/regression/graph_view.cpp +++ b/apps/regression/graph_view.cpp @@ -29,7 +29,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { drawCartesianCurve(ctx, rect, [](float abscissa, void * model, void * context) { Model * regressionModel = static_cast(model); double * regressionCoefficients = static_cast(context); - return (float)regressionModel->evaluate(regressionCoefficients, abscissa); + return Poincare::Coordinate2D(abscissa, (float)regressionModel->evaluate(regressionCoefficients, abscissa)); }, seriesModel, m_store->coefficientsForSeries(series, globContext), color); for (int index = 0; index < m_store->numberOfPairsOfSeries(series); index++) { diff --git a/apps/regression/model/model.cpp b/apps/regression/model/model.cpp index d22a9d111..ca91effd3 100644 --- a/apps/regression/model/model.cpp +++ b/apps/regression/model/model.cpp @@ -27,7 +27,7 @@ double Model::levelSet(double * modelCoefficients, double xMin, double step, dou Expression yExpression = Number::DecimalNumber(y); PoincareHelpers::Simplify(&yExpression, context); Expression modelExpression = simplifiedExpression(modelCoefficients, context); - double result = PoincareHelpers::NextIntersection(modelExpression, "x", xMin, step, xMax, context, yExpression).x(); + double result = PoincareHelpers::NextIntersection(modelExpression, "x", xMin, step, xMax, context, yExpression).x1(); return result; } diff --git a/apps/sequence/graph/graph_controller.cpp b/apps/sequence/graph/graph_controller.cpp index 6f0a52d59..3714388eb 100644 --- a/apps/sequence/graph/graph_controller.cpp +++ b/apps/sequence/graph/graph_controller.cpp @@ -67,7 +67,7 @@ bool GraphController::textFieldDidFinishEditing(TextField * textField, const cha return false; } floatBody = std::fmax(0, std::round(floatBody)); - double y = xyValues(selectedCurveIndex(), floatBody, myApp->localContext()).y(); + double y = xyValues(selectedCurveIndex(), floatBody, myApp->localContext()).x2(); m_cursor->moveTo(floatBody, floatBody, y); interactiveCurveViewRange()->panToMakePointVisible(m_cursor->x(), m_cursor->y(), cursorTopMarginRatio(), k_cursorRightMarginRatio, cursorBottomMarginRatio(), k_cursorLeftMarginRatio); reloadBannerView(); @@ -94,7 +94,7 @@ bool GraphController::moveCursorHorizontally(int direction) { return false; } Sequence * s = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(indexFunctionSelectedByCursor())); - double y = s->evaluateAtParameter(x, textFieldDelegateApp()->localContext()).y(); + double y = s->evaluateXYAtParameter(x, textFieldDelegateApp()->localContext()).x2(); m_cursor->moveTo(x, x, y); return true; } diff --git a/apps/sequence/graph/graph_view.cpp b/apps/sequence/graph/graph_view.cpp index 2668ee843..7d522d956 100644 --- a/apps/sequence/graph/graph_view.cpp +++ b/apps/sequence/graph/graph_view.cpp @@ -24,7 +24,7 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const { rectXMin = rectXMin < 0 ? 0 : rectXMin; float rectXMax = pixelToFloat(Axis::Horizontal, rect.right() + k_externRectMargin); for (int x = rectXMin; x < rectXMax; x += step) { - float y = s->evaluateAtParameter((float)x, context()).y(); + float y = s->evaluateXYAtParameter((float)x, context()).x2(); if (std::isnan(y)) { continue; } diff --git a/apps/sequence/sequence.h b/apps/sequence/sequence.h index 2b9f3be8f..99cd41d6e 100644 --- a/apps/sequence/sequence.h +++ b/apps/sequence/sequence.h @@ -57,10 +57,10 @@ public: bool isDefined() override; bool isEmpty() override; // Approximation - Poincare::Coordinate2D evaluateAtParameter(float x, Poincare::Context * context) const override { + Poincare::Coordinate2D evaluateXYAtParameter(float x, Poincare::Context * context) const override { return Poincare::Coordinate2D(x, templatedApproximateAtAbscissa(x, static_cast(context))); } - Poincare::Coordinate2D evaluateAtParameter(double x, Poincare::Context * context) const override { + Poincare::Coordinate2D evaluateXYAtParameter(double x, Poincare::Context * context) const override { return Poincare::Coordinate2D(x,templatedApproximateAtAbscissa(x, static_cast(context))); } template T approximateToNextRank(int n, SequenceContext * sqctx) const; diff --git a/apps/shared/cartesian_function.cpp b/apps/shared/cartesian_function.cpp index c4383b29b..41d89554b 100644 --- a/apps/shared/cartesian_function.cpp +++ b/apps/shared/cartesian_function.cpp @@ -112,8 +112,8 @@ void CartesianFunction::setPlotType(PlotType plotType) { return recordData()->setPlotType(plotType); } -Coordinate2D CartesianFunction::xyEvaluationAtParameter(double t, Poincare::Context * context) const { - Coordinate2D x1x2 = evaluateAtParameter(t, context); +Coordinate2D CartesianFunction::evaluateXYAtParameter(double t, Poincare::Context * context) const { + Coordinate2D x1x2 = evaluate2DAtParameter(t, context); PlotType type = plotType(); if (type == PlotType::Cartesian || type == PlotType::Parametric) { return x1x2; diff --git a/apps/shared/cartesian_function.h b/apps/shared/cartesian_function.h index d8e0428ff..ea5a33ec4 100644 --- a/apps/shared/cartesian_function.h +++ b/apps/shared/cartesian_function.h @@ -26,11 +26,11 @@ public: void setPlotType(PlotType plotType); // Evaluation - Poincare::Coordinate2D xyEvaluationAtParameter(double t, Poincare::Context * context) const; - Poincare::Coordinate2D evaluateAtParameter(float t, Poincare::Context * context) const override { + Poincare::Coordinate2D evaluateXYAtParameter(double t, Poincare::Context * context) const; + Poincare::Coordinate2D evaluate2DAtParameter(float t, Poincare::Context * context) const override { return templatedApproximateAtParameter(t, context); } - Poincare::Coordinate2D evaluateAtParameter(double t, Poincare::Context * context) const override { + Poincare::Coordinate2D evaluate2DAtParameter(double t, Poincare::Context * context) const override { return templatedApproximateAtParameter(t, context); } // Derivative diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index 9ada00d5e..791abacad 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -502,7 +502,7 @@ const uint8_t stampMask[stampSize+1][stampSize+1] = { constexpr static int k_maxNumberOfIterations = 10; -void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateModelWithParameter xEvaluation, EvaluateModelWithParameter yEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool colorUnderCurve, float colorLowerBound, float colorUpperBound) const { +void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateXYForParameter xyEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool colorUnderCurve, float colorLowerBound, float colorUpperBound) const { float previousX = NAN; float x = NAN; float previousY = NAN; @@ -514,29 +514,28 @@ void CurveView::drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd return; } previousX = x; - x = xEvaluation(t, model, context); previousY = y; - y = yEvaluation(t, model, context); + Coordinate2D xy = xyEvaluation(t, model, context); + x = xy.x1(); + y = xy.x2(); if (std::isnan(x) || std::isinf(x) || std::isnan(y) || std::isinf(y)) { continue; } if (colorUnderCurve && colorLowerBound < x && x < colorUpperBound) { drawSegment(ctx, rect, Axis::Vertical, x, minFloat(0.0f, y), maxFloat(0.0f, y), color, 1); } - jointDots(ctx, rect, xEvaluation, yEvaluation, model, context, drawStraightLinesEarly, t - tStep, previousX, previousY, t, x, y, color, k_maxNumberOfIterations); + jointDots(ctx, rect, xyEvaluation, model, context, drawStraightLinesEarly, t - tStep, previousX, previousY, t, x, y, color, k_maxNumberOfIterations); } } -void CurveView::drawCartesianCurve(KDContext * ctx, KDRect rect, EvaluateModelWithParameter yEvaluation, void * model, void * context, KDColor color, bool colorUnderCurve, float colorLowerBound, float colorUpperBound) const { +void CurveView::drawCartesianCurve(KDContext * ctx, KDRect rect, EvaluateXYForParameter xyEvaluation, void * model, void * context, KDColor color, bool colorUnderCurve, float colorLowerBound, float colorUpperBound) const { float tStart = pixelToFloat(Axis::Horizontal, rect.left() - k_externRectMargin); float tEnd = pixelToFloat(Axis::Horizontal, rect.right() + k_externRectMargin); float tStep = pixelWidth(); - drawCurve(ctx, rect, tStart, tEnd, tStep, [](float t, void * model, void * context) { - return t; - }, yEvaluation, model, context, true, color, colorUnderCurve, colorLowerBound, colorUpperBound); + drawCurve(ctx, rect, tStart, tEnd, tStep, xyEvaluation, model, context, true, color, colorUnderCurve, colorLowerBound, colorUpperBound); } -void CurveView::drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, float firstBarAbscissa, float barWidth, +void CurveView::drawHistogram(KDContext * ctx, KDRect rect, EvaluateYForX yEvaluation, void * model, void * context, float firstBarAbscissa, float barWidth, bool fillBar, KDColor defaultColor, KDColor highlightColor, float highlightLowerBound, float highlightUpperBound) const { float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); float rectMinBinNumber = std::floor((rectMin - firstBarAbscissa)/barWidth); @@ -554,7 +553,7 @@ void CurveView::drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithPar return; } float centerX = fillBar ? x+barWidth/2.0f : x; - float y = evaluation(centerX, model, context); + float y = yEvaluation(centerX, model, context); if (std::isnan(y)) { continue; } @@ -574,7 +573,7 @@ void CurveView::drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithPar } } -void CurveView::jointDots(KDContext * ctx, KDRect rect, EvaluateModelWithParameter xEvaluation, EvaluateModelWithParameter yEvaluation, void * model, void * context, bool drawStraightLinesEarly, float t, float x, float y, float s, float u, float v, KDColor color, int maxNumberOfRecursion) const { +void CurveView::jointDots(KDContext * ctx, KDRect rect, EvaluateXYForParameter xyEvaluation , void * model, void * context, bool drawStraightLinesEarly, float t, float x, float y, float s, float u, float v, KDColor color, int maxNumberOfRecursion) const { float pxf = floatToPixel(Axis::Horizontal, x); float pyf = floatToPixel(Axis::Vertical, y); float puf = floatToPixel(Axis::Horizontal, u); @@ -588,8 +587,9 @@ void CurveView::jointDots(KDContext * ctx, KDRect rect, EvaluateModelWithParamet } // Middle point float ct = (t + s)/2.0f; - float cx = xEvaluation(ct, model, context); - float cy = yEvaluation(ct, model, context); + Coordinate2D cxy = xyEvaluation(ct, model, context); + float cx = cxy.x1(); + float cy = cxy.x2(); if ((drawStraightLinesEarly || maxNumberOfRecursion == 0) && ((x <= cx && cx <= u) || (u <= cx && cx <= x)) && ((y <= cy && cy <= v) || (v <= cy && cy <= y))) { /* As the middle dot is between the two dots, we assume that we * can draw a 'straight' line between the two */ @@ -597,8 +597,8 @@ void CurveView::jointDots(KDContext * ctx, KDRect rect, EvaluateModelWithParamet return; } if (maxNumberOfRecursion > 0) { - jointDots(ctx, rect, xEvaluation, yEvaluation, model, context, drawStraightLinesEarly, t, x, y, ct, cx, cy, color, maxNumberOfRecursion-1); - jointDots(ctx, rect, xEvaluation, yEvaluation, model, context, drawStraightLinesEarly, ct, cx, cy, s, u, v, color, maxNumberOfRecursion-1); + jointDots(ctx, rect, xyEvaluation, model, context, drawStraightLinesEarly, t, x, y, ct, cx, cy, color, maxNumberOfRecursion-1); + jointDots(ctx, rect, xyEvaluation, model, context, drawStraightLinesEarly, ct, cx, cy, s, u, v, color, maxNumberOfRecursion-1); } } diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 9fc1a08b9..d4b18dbec 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -5,6 +5,7 @@ #include "curve_view_range.h" #include "curve_view_cursor.h" #include +#include #include namespace Shared { @@ -14,8 +15,8 @@ public: /* We want a 3 characters margin before the first label tick, so that most * labels appear completely. This gives 3*charWidth/320 = 3*7/320= 0.066 */ static constexpr float k_labelsHorizontalMarginRatio = 0.066f; - //TODO LEA RUBEN EvaluateModelWithParameter that returns Coordinate2D - typedef float (*EvaluateModelWithParameter)(float t, void * model, void * context); + typedef Poincare::Coordinate2D (*EvaluateXYForParameter)(float t, void * model, void * context); + typedef float (*EvaluateYForX)(float x, void * model, void * context); enum class Axis { Horizontal = 0, Vertical = 1 @@ -63,9 +64,9 @@ protected: void drawGrid(KDContext * ctx, KDRect rect) const; void drawAxes(KDContext * ctx, KDRect rect) const; void drawAxis(KDContext * ctx, KDRect rect, Axis axis) const; - void drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateModelWithParameter xEvaluation, EvaluateModelWithParameter yEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f) const; - void drawCartesianCurve(KDContext * ctx, KDRect rect, EvaluateModelWithParameter yEvaluation, void * model, void * context, KDColor color, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f) const; - void drawHistogram(KDContext * ctx, KDRect rect, EvaluateModelWithParameter evaluation, void * model, void * context, float firstBarAbscissa, float barWidth, + void drawCurve(KDContext * ctx, KDRect rect, float tStart, float tEnd, float tStep, EvaluateXYForParameter xyEvaluation, void * model, void * context, bool drawStraightLinesEarly, KDColor color, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f) const; + void drawCartesianCurve(KDContext * ctx, KDRect rect, EvaluateXYForParameter xyEvaluation, void * model, void * context, KDColor color, bool colorUnderCurve = false, float colorLowerBound = 0.0f, float colorUpperBound = 0.0f) const; + void drawHistogram(KDContext * ctx, KDRect rect, EvaluateYForX yEvaluation, void * model, void * context, float firstBarAbscissa, float barWidth, bool fillBar, KDColor defaultColor, KDColor highlightColor, float highlightLowerBound = INFINITY, float highlightUpperBound = -INFINITY) const; void computeLabels(Axis axis); void simpleDrawBothAxesLabels(KDContext * ctx, KDRect rect) const; @@ -84,7 +85,7 @@ private: int numberOfLabels(Axis axis) const; /* Recursively join two dots (dichotomy). The method stops when the * maxNumberOfRecursion in reached. */ - void jointDots(KDContext * ctx, KDRect rect, EvaluateModelWithParameter xEvaluation, EvaluateModelWithParameter yEvaluation, void * model, void * context, bool drawStraightLinesEarly, float t, float x, float y, float s, float u, float v, KDColor color, int maxNumberOfRecursion) const; + void jointDots(KDContext * ctx, KDRect rect, EvaluateXYForParameter xyEvaluation, void * model, void * context, bool drawStraightLinesEarly, float t, float x, float y, float s, float u, float v, KDColor color, int maxNumberOfRecursion) const; /* Join two dots with a straight line. */ void straightJoinDots(KDContext * ctx, KDRect rect, float pxf, float pyf, float puf, float pvf, KDColor color) const; /* Stamp centered around (pxf, pyf). If pxf and pyf are not round number, the diff --git a/apps/shared/function.h b/apps/shared/function.h index 6f5cd7d79..0f5f2e325 100644 --- a/apps/shared/function.h +++ b/apps/shared/function.h @@ -41,8 +41,8 @@ public: int nameWithArgument(char * buffer, size_t bufferSize); // Evaluation - virtual Poincare::Coordinate2D evaluateAtParameter(float t, Poincare::Context * context) const = 0; - virtual Poincare::Coordinate2D evaluateAtParameter(double t, Poincare::Context * context) const = 0; + virtual Poincare::Coordinate2D evaluate2DAtParameter(float t, Poincare::Context * context) const = 0; + virtual Poincare::Coordinate2D evaluate2DAtParameter(double t, Poincare::Context * context) const = 0; protected: /* FunctionRecordDataBuffer is the layout of the data buffer of Record * representing a Function. We want to avoid padding which would: diff --git a/apps/shared/function_go_to_parameter_controller.cpp b/apps/shared/function_go_to_parameter_controller.cpp index 5abea7151..c3f05559b 100644 --- a/apps/shared/function_go_to_parameter_controller.cpp +++ b/apps/shared/function_go_to_parameter_controller.cpp @@ -24,7 +24,7 @@ bool FunctionGoToParameterController::setParameterAtIndex(int parameterIndex, do assert(parameterIndex == 0); FunctionApp * myApp = FunctionApp::app(); ExpiringPointer function = myApp->functionStore()->modelForRecord(m_record); - Poincare::Coordinate2D xy = function->evaluateAtParameter(f, myApp->localContext()); + Poincare::Coordinate2D xy = function->evaluate2DAtParameter(f, myApp->localContext()); m_cursor->moveTo(f, xy.x(), xy.y()); m_graphRange->centerAxisAround(CurveViewRange::Axis::X, m_cursor->x()); m_graphRange->centerAxisAround(CurveViewRange::Axis::Y, m_cursor->y()); diff --git a/apps/shared/function_graph_controller.cpp b/apps/shared/function_graph_controller.cpp index eb4f9043c..133547a95 100644 --- a/apps/shared/function_graph_controller.cpp +++ b/apps/shared/function_graph_controller.cpp @@ -107,7 +107,7 @@ InteractiveCurveViewRangeDelegate::Range FunctionGraphController::computeYRange( const int balancedBound = std::floor((tMax-tMin)/2/step); for (int j = -balancedBound; j <= balancedBound ; j++) { float t = (tMin+tMax)/2 + step * j; - Coordinate2D xy = f->evaluateAtParameter(t, context); + Coordinate2D xy = f->evaluate2DAtParameter(t, context); float x = xy.x(); if (!std::isnan(x) && !std::isinf(x) && x >= xMin && x <= xMax) { float y = xy.y(); @@ -139,7 +139,7 @@ void FunctionGraphController::initCursorParameters() { Coordinate2D xy; do { ExpiringPointer firstFunction = functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(functionIndex++)); - xy = firstFunction->evaluateAtParameter(t, context); + xy = firstFunction->evaluate2DAtParameter(t, context); } while ((std::isnan(xy.y()) || std::isinf(xy.y())) && functionIndex < functionStore()->numberOfActiveFunctions()); m_cursor->moveTo(t, xy.x(), xy.y()); functionIndex = (std::isnan(xy.y()) || std::isinf(xy.y())) ? 0 : functionIndex - 1; @@ -181,7 +181,7 @@ bool FunctionGraphController::closestCurveIndexIsSuitable(int newIndex, int curr } Coordinate2D FunctionGraphController::xyValues(int curveIndex, double t, Poincare::Context * context) const { - return functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(curveIndex))->evaluateAtParameter(t, context); + return functionStore()->modelForRecord(functionStore()->activeRecordAtIndex(curveIndex))->evaluate2DAtParameter(t, context); } int FunctionGraphController::numberOfCurves() const { diff --git a/apps/shared/sum_graph_controller.cpp b/apps/shared/sum_graph_controller.cpp index bdffbf805..e4e3551bb 100644 --- a/apps/shared/sum_graph_controller.cpp +++ b/apps/shared/sum_graph_controller.cpp @@ -66,7 +66,7 @@ bool SumGraphController::moveCursorHorizontallyToPosition(double x) { assert(!m_record.isNull()); ExpiringPointer function = myApp->functionStore()->modelForRecord(m_record); - Coordinate2D xy = function->evaluateAtParameter(x, myApp->localContext()); //TODO LEA assertion that x = t? + Coordinate2D xy = function->evaluate2DAtParameter(x, myApp->localContext()); //TODO LEA assertion that x = t? double y = xy.y(); m_cursor->moveTo(x, x, y); if (m_step == Step::SecondParameter) { diff --git a/apps/shared/values_controller.cpp b/apps/shared/values_controller.cpp index b7b1882d4..304e3ba47 100644 --- a/apps/shared/values_controller.cpp +++ b/apps/shared/values_controller.cpp @@ -329,7 +329,7 @@ double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int colum ExpiringPointer function = functionStore()->modelForRecord(recordAtColumn(columnIndex)); //TODO LEA RUBEN Careful with merge //TODO LEA RUBEN change with evaluationOfParameterAtColumn? - Poincare::Coordinate2D xy = function->evaluateAtParameter(abscissa, textFieldDelegateApp()->localContext()); + Poincare::Coordinate2D xy = function->evaluate2DAtParameter(abscissa, textFieldDelegateApp()->localContext()); return xy.y(); } diff --git a/poincare/src/expression.cpp b/poincare/src/expression.cpp index c4b62db2b..44997fa26 100644 --- a/poincare/src/expression.cpp +++ b/poincare/src/expression.cpp @@ -889,7 +889,7 @@ Coordinate2D Expression::nextMaximum(const char * symbol, double start, const char * symbol = reinterpret_cast(context2); return -expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit); - return Coordinate2D(minimumOfOpposite.x(), -minimumOfOpposite.y()); + return Coordinate2D(minimumOfOpposite.x1(), -minimumOfOpposite.x2()); } double Expression::nextRoot(const char * symbol, double start, double step, double max, Context * context, Preferences::ComplexFormat complexFormat, Preferences::AngleUnit angleUnit) const { @@ -910,8 +910,8 @@ Coordinate2D Expression::nextIntersection(const char * symbol, double st return expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)-expression1->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit, expression); Coordinate2D result(resultAbscissa, approximateWithValueForSymbol(symbol, resultAbscissa, context, complexFormat, angleUnit)); - if (std::fabs(result.y()) < step*k_solverPrecision) { - result.setY(0.0); + if (std::fabs(result.x2()) < step*k_solverPrecision) { + result.setX2(0.0); } return result; } @@ -929,26 +929,26 @@ Coordinate2D Expression::nextMinimumOfExpression(const char * symbol, do result = brentMinimum(symbol, bracket[0], bracket[2], evaluate, context, complexFormat, angleUnit, expression); x = bracket[1]; // Because of float approximation, exact zero is never reached - if (std::fabs(result.x()) < std::fabs(step)*k_solverPrecision) { - result.setX(0); - result.setY(evaluate(0, context, complexFormat, angleUnit, this, symbol, &expression)); + if (std::fabs(result.x1()) < std::fabs(step)*k_solverPrecision) { + result.setX1(0); + result.setX2(evaluate(0, context, complexFormat, angleUnit, this, symbol, &expression)); } /* Ignore extremum whose value is undefined or too big because they are * really unlikely to be local extremum. */ - if (std::isnan(result.y()) || std::fabs(result.y()) > k_maxFloat) { - result.setX(NAN); + if (std::isnan(result.x2()) || std::fabs(result.x2()) > k_maxFloat) { + result.setX1(NAN); } // Idem, exact 0 never reached - if (std::fabs(result.y()) < std::fabs(step)*k_solverPrecision) { - result.setY(0); + if (std::fabs(result.x2()) < std::fabs(step)*k_solverPrecision) { + result.setX2(0); } - endCondition = std::isnan(result.x()) && (step > 0.0 ? x <= max : x >= max); + endCondition = std::isnan(result.x1()) && (step > 0.0 ? x <= max : x >= max); if (lookForRootMinimum) { - endCondition |= std::fabs(result.y()) > 0 && (step > 0.0 ? x <= max : x >= max); + endCondition |= std::fabs(result.x2()) > 0 && (step > 0.0 ? x <= max : x >= max); } } while (endCondition); - if (lookForRootMinimum && std::fabs(result.y()) > 0) { - result.setX(NAN); + if (lookForRootMinimum && std::fabs(result.x2()) > 0) { + result.setX1(NAN); } return result; } @@ -961,18 +961,18 @@ void Expression::bracketMinimum(const char * symbol, double start, double step, }; double x = start+2.0*step; while (step > 0.0 ? x <= max : x >= max) { - p[2].setX(x); - p[2].setY(evaluate(x, context, complexFormat, angleUnit, this, symbol, &expression)); - if ((p[0].y() > p[1].y() || std::isnan(p[0].y())) - && (p[2].y() > p[1].y() || std::isnan(p[2].y())) - && (!std::isnan(p[0].y()) || !std::isnan(p[2].y()))) + p[2].setX1(x); + p[2].setX2(evaluate(x, context, complexFormat, angleUnit, this, symbol, &expression)); + if ((p[0].x2() > p[1].x2() || std::isnan(p[0].x2())) + && (p[2].x2() > p[1].x2() || std::isnan(p[2].x2())) + && (!std::isnan(p[0].x2()) || !std::isnan(p[2].x2()))) { - result[0] = p[0].x(); - result[1] = p[1].x(); - result[2] = p[2].x(); + result[0] = p[0].x1(); + result[1] = p[1].x1(); + result[2] = p[2].x1(); return; } - if (p[0].y() > p[1].y() && p[1].y() == p[2].y()) { + if (p[0].x2() > p[1].x2() && p[1].x2() == p[2].x2()) { } else { p[0] = p[1]; p[1] = p[2]; @@ -1028,8 +1028,8 @@ double Expression::nextIntersectionWithExpression(const char * symbol, double st return (expression1->isUninitialized() ? 0.0 : expression1->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit)) - expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit); }, context, complexFormat, angleUnit, expression, true)}; for (int i = 0; i < 2; i++) { - if (!std::isnan(resultExtremum[i].x()) && (std::isnan(result) || std::fabs(result - start) > std::fabs(resultExtremum[i].x() - start))) { - result = resultExtremum[i].x(); + if (!std::isnan(resultExtremum[i].x1()) && (std::isnan(result) || std::fabs(result - start) > std::fabs(resultExtremum[i].x1() - start))) { + result = resultExtremum[i].x1(); } } if (std::fabs(result) < std::fabs(step)*k_solverPrecision) {