mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-28 01:59:59 +01:00
[apps/regression] Draw the right regression curve
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user