[apps/regression] Draw the right regression curve

This commit is contained in:
Léa Saviot
2018-06-06 17:36:19 +02:00
committed by Émilie Feral
parent 1c8ff9bd83
commit e777a191c6
6 changed files with 55 additions and 9 deletions

View File

@@ -12,7 +12,7 @@ GraphController::GraphController(Responder * parentResponder, ButtonRowControlle
m_crossCursorView(),
m_roundCursorView(),
m_bannerView(),
m_view(store, m_cursor, &m_bannerView, &m_crossCursorView),
m_view(store, m_cursor, &m_bannerView, &m_crossCursorView, this),
m_store(store),
m_initialisationParameterController(this, m_store),
m_predictionParameterController(this, m_store, m_cursor, this),

View File

@@ -1,15 +1,19 @@
#include "graph_view.h"
#include "model/model.h"
#include <apps/apps_container.h>
#include <poincare/context.h>
#include <assert.h>
using namespace Shared;
namespace Regression {
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) :
GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, View * cursorView, Responder * controller) :
CurveView(store, cursor, bannerView, cursorView),
m_store(store),
m_xLabels{},
m_yLabels{}
m_yLabels{},
m_controller(controller)
{
}
@@ -23,12 +27,16 @@ void GraphView::drawRect(KDContext * ctx, KDRect rect) const {
for (int series = 0; series < Store::k_numberOfSeries; series++) {
if (!m_store->seriesIsEmpty(series)) {
KDColor color = Palette::DataColor[series];
float regressionParameters[2] = {(float)m_store->slope(series), (float)m_store->yIntercept(series)};
Model * seriesModel = m_store->modelForSeries(series);
double coefficients[Model::k_maxNumberOfCoefficients];
Poincare::Context * globContext = const_cast<AppsContainer *>(static_cast<const AppsContainer *>(m_controller->app()->container()))->globalContext();
seriesModel->fit(m_store, series, coefficients, globContext);
drawCurve(ctx, rect, [](float abscissa, void * model, void * context) {
float * params = (float *)model;
return params[0]*abscissa+params[1];
Model * regressionModel = static_cast<Model *>(model);
double * regressionCoefficients = static_cast<double *>(context);
return (float)regressionModel->evaluate(regressionCoefficients, abscissa);
},
regressionParameters, nullptr, color);
seriesModel, coefficients, color);
for (int index = 0; index < m_store->numberOfPairsOfSeries(series); index++) {
drawDot(ctx, rect, m_store->get(series, 0, index), m_store->get(series, 1, index), color);
}

View File

@@ -10,16 +10,16 @@ namespace Regression {
class GraphView : public Shared::CurveView {
public:
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView);
GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView, Responder * controller);
void drawRect(KDContext * ctx, KDRect rect) const override;
private:
char * label(Axis axis, int index) const override;
Store * m_store;
char m_xLabels[k_maxNumberOfXLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)];
char m_yLabels[k_maxNumberOfYLabels][Poincare::PrintFloat::bufferSizeForFloatsWithPrecision(Constant::ShortNumberOfSignificantDigits)];
Responder * m_controller;
};
}
#endif

View File

@@ -24,6 +24,7 @@ public:
};
static constexpr int k_numberOfModels = 9;
static constexpr int k_maxNumberOfCoefficients = 5;
virtual ~Model() = default;
virtual double evaluate(double * modelCoefficients, double x) const = 0;
virtual void fit(Store * store, int series, double * modelCoefficients, Poincare::Context * context);
private:

View File

@@ -1,4 +1,13 @@
#include "store.h"
#include "model/cubic_model.h"
#include "model/exponential_model.h"
#include "model/linear_model.h"
#include "model/logarithmic_model.h"
#include "model/logistic_model.h"
#include "model/power_model.h"
#include "model/quadratic_model.h"
#include "model/quartic_model.h"
#include "model/trigonometric_model.h"
#include <assert.h>
#include <float.h>
#include <cmath>
@@ -11,6 +20,8 @@ namespace Regression {
static inline float max(float x, float y) { return (x>y ? x : y); }
static inline float min(float x, float y) { return (x<y ? x : y); }
static_assert(Model::k_numberOfModels == 9, "Number of models changed, Regression::Store() needs to adapt");
Store::Store() :
InteractiveCurveViewRange(nullptr, this),
DoublePairStore()
@@ -18,6 +29,21 @@ Store::Store() :
for (int i = 0; i < k_numberOfSeries; i++) {
m_regressionTypes[i] = Model::Type::Linear;
}
m_regressionModels[0] = new LinearModel();
m_regressionModels[1] = new QuadraticModel();
m_regressionModels[2] = new CubicModel();
m_regressionModels[3] = new QuarticModel();
m_regressionModels[4] = new LogarithmicModel();
m_regressionModels[5] = new ExponentialModel();
m_regressionModels[6] = new PowerModel();
m_regressionModels[7] = new TrigonometricModel();
m_regressionModels[8] = new LogisticModel();
}
Store::~Store() {
for (int i = 0; i < Model::k_numberOfModels; i++) {
delete m_regressionModels[i];
}
}
/* Regressions */

View File

@@ -13,12 +13,22 @@ namespace Regression {
class Store : public Shared::InteractiveCurveViewRange, public Shared::DoublePairStore, public Shared::InteractiveCurveViewRangeDelegate {
public:
Store();
~Store();
Store(const Store & other) = delete;
Store(Store && other) = delete;
Store& operator=(const Store & other) = delete;
Store& operator=(Store && other) = delete;
// Regression
void setSeriesRegressionType(int series, Model::Type type) {
assert(series >= 0 && series < k_numberOfSeries);
m_regressionTypes[series] = type;
}
Model * modelForSeries(int series) {
assert(series >= 0 && series < k_numberOfSeries);
assert((int)m_regressionTypes[series] >= 0 && (int)m_regressionTypes[series] < Model::k_numberOfModels);
return m_regressionModels[(int)m_regressionTypes[series]];
}
/* Return the series index of the closest regression at abscissa x, above
* ordinate y if direction > 0, below otherwise */
int closestVerticalRegression(int direction, float x, float y, int currentRegressionSeries);
@@ -60,6 +70,7 @@ private:
float maxValueOfColumn(int series, int i) const;
float minValueOfColumn(int series, int i) const;
Model::Type m_regressionTypes[k_numberOfSeries];
Model * m_regressionModels[Model::k_numberOfModels];
};
typedef double (Store::*ArgCalculPointer)(int, int) const;