[apps/graph] Evaluation methods renaming

This commit is contained in:
Léa Saviot
2019-08-28 16:56:49 +02:00
parent 28a721e96e
commit c71ef7ff79
22 changed files with 94 additions and 109 deletions

View File

@@ -24,7 +24,7 @@ bool GraphControllerHelper::privateMoveCursorHorizontally(Shared::CurveViewCurso
t += dir; //TODO LEA delt
}
Coordinate2D<double> xy = function->xyEvaluationAtParameter(t, App::app()->localContext());
Coordinate2D<double> xy = function->evaluateXYAtParameter(t, App::app()->localContext());
cursor->moveTo(t, xy.x(), xy.y());
return true;
}

View File

@@ -30,40 +30,39 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
ExpiringPointer<CartesianFunction> 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<float>(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<float>(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<Poincare::Matrix&>(e).numberOfRows() == 2 &&
static_cast<Poincare::Matrix&>(e).numberOfColumns() == 1
);
assert(e.type() == Poincare::ExpressionNode::Type::Matrix
&& static_cast<Poincare::Matrix&>(e).numberOfRows() == 2
&& static_cast<Poincare::Matrix&>(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<float>(&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<Poincare::Matrix&>(e).numberOfRows() == 2 &&
static_cast<Poincare::Matrix&>(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<float>(&variableContext, complexFormat, preferences->angleUnit());
return Poincare::Coordinate2D<float>(e.childAtIndex(0).approximateToScalar<float>(&variableContext, complexFormat, preferences->angleUnit()), e.childAtIndex(1).approximateToScalar<float>(&variableContext, complexFormat, preferences->angleUnit()));
}, f.operator->(), context(), false, f->color());
break;
default:
assert(false);
}

View File

@@ -47,7 +47,7 @@ bool TangentGraphController::textFieldDidFinishEditing(TextField * textField, co
}
ExpiringPointer<CartesianFunction> 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<double>(y, buffer + legendLength, PrintFloat::bufferSizeForFloatsWithPrecision(precision), precision);
m_bannerView->bView()->setText(buffer);
m_bannerView->reload();

View File

@@ -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() {

View File

@@ -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 {

View File

@@ -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<float> DistributionCurveView::EvaluateXYAtAbscissa(float abscissa, void * model, void * context) {
return Poincare::Coordinate2D<float>(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<DistributionCurveView *>(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);

View File

@@ -7,6 +7,7 @@
#include "calculation/calculation.h"
#include <escher.h>
#include <poincare/print_float.h>
#include <poincare/coordinate_2D.h>
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<float> 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];

View File

@@ -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 *>(model);
double * regressionCoefficients = static_cast<double *>(context);
return (float)regressionModel->evaluate(regressionCoefficients, abscissa);
return Poincare::Coordinate2D<float>(abscissa, (float)regressionModel->evaluate(regressionCoefficients, abscissa));
},
seriesModel, m_store->coefficientsForSeries(series, globContext), color);
for (int index = 0; index < m_store->numberOfPairsOfSeries(series); index++) {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -57,10 +57,10 @@ public:
bool isDefined() override;
bool isEmpty() override;
// Approximation
Poincare::Coordinate2D<float> evaluateAtParameter(float x, Poincare::Context * context) const override {
Poincare::Coordinate2D<float> evaluateXYAtParameter(float x, Poincare::Context * context) const override {
return Poincare::Coordinate2D<float>(x, templatedApproximateAtAbscissa(x, static_cast<SequenceContext *>(context)));
}
Poincare::Coordinate2D<double> evaluateAtParameter(double x, Poincare::Context * context) const override {
Poincare::Coordinate2D<double> evaluateXYAtParameter(double x, Poincare::Context * context) const override {
return Poincare::Coordinate2D<double>(x,templatedApproximateAtAbscissa(x, static_cast<SequenceContext *>(context)));
}
template<typename T> T approximateToNextRank(int n, SequenceContext * sqctx) const;

View File

@@ -112,8 +112,8 @@ void CartesianFunction::setPlotType(PlotType plotType) {
return recordData()->setPlotType(plotType);
}
Coordinate2D<double> CartesianFunction::xyEvaluationAtParameter(double t, Poincare::Context * context) const {
Coordinate2D<double> x1x2 = evaluateAtParameter(t, context);
Coordinate2D<double> CartesianFunction::evaluateXYAtParameter(double t, Poincare::Context * context) const {
Coordinate2D<double> x1x2 = evaluate2DAtParameter(t, context);
PlotType type = plotType();
if (type == PlotType::Cartesian || type == PlotType::Parametric) {
return x1x2;

View File

@@ -26,11 +26,11 @@ public:
void setPlotType(PlotType plotType);
// Evaluation
Poincare::Coordinate2D<double> xyEvaluationAtParameter(double t, Poincare::Context * context) const;
Poincare::Coordinate2D<float> evaluateAtParameter(float t, Poincare::Context * context) const override {
Poincare::Coordinate2D<double> evaluateXYAtParameter(double t, Poincare::Context * context) const;
Poincare::Coordinate2D<float> evaluate2DAtParameter(float t, Poincare::Context * context) const override {
return templatedApproximateAtParameter(t, context);
}
Poincare::Coordinate2D<double> evaluateAtParameter(double t, Poincare::Context * context) const override {
Poincare::Coordinate2D<double> evaluate2DAtParameter(double t, Poincare::Context * context) const override {
return templatedApproximateAtParameter(t, context);
}
// Derivative

View File

@@ -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<float> 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<float> 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);
}
}

View File

@@ -5,6 +5,7 @@
#include "curve_view_range.h"
#include "curve_view_cursor.h"
#include <poincare/preferences.h>
#include <poincare/coordinate_2D.h>
#include <cmath>
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<float>
typedef float (*EvaluateModelWithParameter)(float t, void * model, void * context);
typedef Poincare::Coordinate2D<float> (*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

View File

@@ -41,8 +41,8 @@ public:
int nameWithArgument(char * buffer, size_t bufferSize);
// Evaluation
virtual Poincare::Coordinate2D<float> evaluateAtParameter(float t, Poincare::Context * context) const = 0;
virtual Poincare::Coordinate2D<double> evaluateAtParameter(double t, Poincare::Context * context) const = 0;
virtual Poincare::Coordinate2D<float> evaluate2DAtParameter(float t, Poincare::Context * context) const = 0;
virtual Poincare::Coordinate2D<double> 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:

View File

@@ -24,7 +24,7 @@ bool FunctionGoToParameterController::setParameterAtIndex(int parameterIndex, do
assert(parameterIndex == 0);
FunctionApp * myApp = FunctionApp::app();
ExpiringPointer<Function> function = myApp->functionStore()->modelForRecord(m_record);
Poincare::Coordinate2D<double> xy = function->evaluateAtParameter(f, myApp->localContext());
Poincare::Coordinate2D<double> 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());

View File

@@ -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<float> xy = f->evaluateAtParameter(t, context);
Coordinate2D<float> 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<double> xy;
do {
ExpiringPointer<Function> 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<double> 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 {

View File

@@ -66,7 +66,7 @@ bool SumGraphController::moveCursorHorizontallyToPosition(double x) {
assert(!m_record.isNull());
ExpiringPointer<Function> function = myApp->functionStore()->modelForRecord(m_record);
Coordinate2D<double> xy = function->evaluateAtParameter(x, myApp->localContext()); //TODO LEA assertion that x = t?
Coordinate2D<double> 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) {

View File

@@ -329,7 +329,7 @@ double ValuesController::evaluationOfAbscissaAtColumn(double abscissa, int colum
ExpiringPointer<Function> function = functionStore()->modelForRecord(recordAtColumn(columnIndex));
//TODO LEA RUBEN Careful with merge
//TODO LEA RUBEN change with evaluationOfParameterAtColumn?
Poincare::Coordinate2D<double> xy = function->evaluateAtParameter(abscissa, textFieldDelegateApp()->localContext());
Poincare::Coordinate2D<double> xy = function->evaluate2DAtParameter(abscissa, textFieldDelegateApp()->localContext());
return xy.y();
}

View File

@@ -889,7 +889,7 @@ Coordinate2D<double> Expression::nextMaximum(const char * symbol, double start,
const char * symbol = reinterpret_cast<const char *>(context2);
return -expression0->approximateWithValueForSymbol(symbol, x, context, complexFormat, angleUnit);
}, context, complexFormat, angleUnit);
return Coordinate2D<double>(minimumOfOpposite.x(), -minimumOfOpposite.y());
return Coordinate2D<double>(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<double> 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<double> 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<double> 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) {