From 9eb65a374bee23a2cf1631dae7155dabe594e6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 10:04:42 +0100 Subject: [PATCH 01/14] [escher] Correct syntax error Change-Id: Ic04ba9bdad1f0b5949c85b7c41fbf4c58688b74c --- escher/include/escher/editable_text_cell.h | 2 +- escher/src/editable_text_cell.cpp | 2 +- escher/src/even_odd_editable_text_cell.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/escher/include/escher/editable_text_cell.h b/escher/include/escher/editable_text_cell.h index f4005ad9f..6550f3944 100644 --- a/escher/include/escher/editable_text_cell.h +++ b/escher/include/escher/editable_text_cell.h @@ -10,7 +10,7 @@ class EditableTextCell : public TableViewCell, public Responder { public: EditableTextCell(Responder * parentResponder, TextFieldDelegate * delegate, char * draftTextBuffer, float horizontalAlignment = 0.0f, float verticalAlignment = 0.5f, KDColor textColor = KDColorBlack, KDColor = KDColorWhite); - TextField * textfield(); + TextField * textField(); void reloadCell() override; const char * text() const; void setText(const char * textContent); diff --git a/escher/src/editable_text_cell.cpp b/escher/src/editable_text_cell.cpp index 5e4bf5fd0..b9bcdd3f7 100644 --- a/escher/src/editable_text_cell.cpp +++ b/escher/src/editable_text_cell.cpp @@ -11,7 +11,7 @@ EditableTextCell::EditableTextCell(Responder * parentResponder, TextFieldDelegat { } -TextField * EditableTextCell::textfield() { +TextField * EditableTextCell::textField() { return &m_textField; } diff --git a/escher/src/even_odd_editable_text_cell.cpp b/escher/src/even_odd_editable_text_cell.cpp index 4a75b3e27..855e551d3 100644 --- a/escher/src/even_odd_editable_text_cell.cpp +++ b/escher/src/even_odd_editable_text_cell.cpp @@ -11,7 +11,7 @@ EvenOddEditableTextCell::EvenOddEditableTextCell(Responder * parentResponder, Te void EvenOddEditableTextCell::reloadCell() { EvenOddCell::reloadCell(); - m_editableCell.textfield()->setBackgroundColor(backgroundColor()); + m_editableCell.textField()->setBackgroundColor(backgroundColor()); } const char * EvenOddEditableTextCell::text() const { From e688b91fce576d81d358c7dee51315f497ced146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 10:06:00 +0100 Subject: [PATCH 02/14] [apps/probability] Add method in data model (to delete pairs) Change-Id: Idff6b1a01c655552d75252551b882f72ba7d6f0d --- apps/statistics/data.cpp | 12 +++++++++++- apps/statistics/data.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/statistics/data.cpp b/apps/statistics/data.cpp index 38820b5c6..e362f2014 100644 --- a/apps/statistics/data.cpp +++ b/apps/statistics/data.cpp @@ -22,7 +22,7 @@ int Data::sizeAtIndex(int index) { void Data::setValueAtIndex(float value, int index) { m_values[index] = value; if (index >= m_numberOfPairs) { - m_sizes[index] = 0; + m_sizes[index] = 1; m_numberOfPairs++; } } @@ -35,4 +35,14 @@ void Data::setSizeAtIndex(int size, int index) { } } +void Data::deletePairAtIndex(int index) { + m_numberOfPairs--; + for (int k = index; k < m_numberOfPairs; k++) { + m_values[k] = m_values[k+1]; + m_sizes[k] = m_sizes[k+1]; + } + m_values[m_numberOfPairs] = 0.0f; + m_sizes[m_numberOfPairs] = 1; +} + } diff --git a/apps/statistics/data.h b/apps/statistics/data.h index 668729ab7..1876e1e2b 100644 --- a/apps/statistics/data.h +++ b/apps/statistics/data.h @@ -13,6 +13,7 @@ public: int sizeAtIndex(int index); void setValueAtIndex(float value, int index); void setSizeAtIndex(int size, int index); + void deletePairAtIndex(int index); // TODO: decide the max number of elements after optimization constexpr static int k_maxNumberOfPairs = 500; private: From b85ea03b8e2d213bf6fe0889e829237b848bb9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 10:06:40 +0100 Subject: [PATCH 03/14] [escher] Add a method in even odd editable text cell to access editable text cell Change-Id: Ic1c7749dfacb890f6def5f7261ba4cb0659fc1f3 --- escher/include/escher/even_odd_editable_text_cell.h | 1 + escher/src/even_odd_editable_text_cell.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/escher/include/escher/even_odd_editable_text_cell.h b/escher/include/escher/even_odd_editable_text_cell.h index 421256de0..e63331567 100644 --- a/escher/include/escher/even_odd_editable_text_cell.h +++ b/escher/include/escher/even_odd_editable_text_cell.h @@ -8,6 +8,7 @@ class EvenOddEditableTextCell : public EvenOddCell, public Responder { public: EvenOddEditableTextCell(Responder * parentResponder, TextFieldDelegate * delegate, char * draftTextBuffer); + EditableTextCell * editableTextCell(); void reloadCell() override; const char * text() const; void setText(const char * textContent); diff --git a/escher/src/even_odd_editable_text_cell.cpp b/escher/src/even_odd_editable_text_cell.cpp index 855e551d3..bb7c28637 100644 --- a/escher/src/even_odd_editable_text_cell.cpp +++ b/escher/src/even_odd_editable_text_cell.cpp @@ -9,6 +9,10 @@ EvenOddEditableTextCell::EvenOddEditableTextCell(Responder * parentResponder, Te { } +EditableTextCell * EvenOddEditableTextCell::editableTextCell() { + return &m_editableCell; +} + void EvenOddEditableTextCell::reloadCell() { EvenOddCell::reloadCell(); m_editableCell.textField()->setBackgroundColor(backgroundColor()); From ef9b47555b53313110e05fbaeda7edb5293d2540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 10:08:03 +0100 Subject: [PATCH 04/14] [apps/probability] Improve data controller to delete pairs of data Change-Id: Ifc64250e277c61976c82a91c21a68dd775d7cac0 --- apps/statistics/data_controller.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/statistics/data_controller.cpp b/apps/statistics/data_controller.cpp index 98f888d1b..f14ff2da6 100644 --- a/apps/statistics/data_controller.cpp +++ b/apps/statistics/data_controller.cpp @@ -79,6 +79,18 @@ bool DataController::handleEvent(Ion::Events::Event event) { app()->setFirstResponder(tabController()); return true; } + if (event == Ion::Events::Clear) { + if (m_selectableTableView.selectedColumn() == 0) { + m_data->deletePairAtIndex(m_selectableTableView.selectedRow()-1); + m_selectableTableView.reloadData(); + } else { + m_data->setSizeAtIndex(1, m_selectableTableView.selectedRow()-1); + EvenOddEditableTextCell * myCell = (EvenOddEditableTextCell *)m_selectableTableView.cellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + willDisplayCellAtLocation(myCell, m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow()); + myCell->editableTextCell()->textField()->handleEvent(Ion::Events::OK); + } + return true; + } return false; } From bd8ecf73dbf8f23e84bce2ca1a88c14befc3bdf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 10:14:51 +0100 Subject: [PATCH 05/14] [apps/probability] Add a pointer to the data model in the histogram controller Change-Id: I1297e10f1e30133d93e96becfb4bc49eb7a8a28d --- apps/statistics/app.cpp | 2 +- apps/statistics/histogram_controller.cpp | 10 +++++++--- apps/statistics/histogram_controller.h | 4 +++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/statistics/app.cpp b/apps/statistics/app.cpp index 75b547900..f96d28ec8 100644 --- a/apps/statistics/app.cpp +++ b/apps/statistics/app.cpp @@ -12,7 +12,7 @@ App::App(Container * container) : m_boxController(BoxController(&m_boxAlternateEmptyViewController)), m_boxAlternateEmptyViewController(AlternateEmptyViewController(nullptr, &m_boxController, &m_boxController)), m_boxStackViewController(StackViewController(&m_tabViewController, &m_boxAlternateEmptyViewController)), - m_histogramController(HistogramController(&m_histogramHeader, &m_histogramHeader)), + m_histogramController(HistogramController(&m_histogramHeader, &m_histogramHeader, &m_data)), m_histogramHeader(HeaderViewController(&m_histogramAlternateEmptyViewController, &m_histogramController, &m_histogramController)), m_histogramAlternateEmptyViewController(AlternateEmptyViewController(nullptr, &m_histogramHeader, &m_histogramController)), m_histogramStackViewController(StackViewController(&m_tabViewController, &m_histogramAlternateEmptyViewController)), diff --git a/apps/statistics/histogram_controller.cpp b/apps/statistics/histogram_controller.cpp index 0e9dcf5e3..9f0f1ace4 100644 --- a/apps/statistics/histogram_controller.cpp +++ b/apps/statistics/histogram_controller.cpp @@ -2,12 +2,13 @@ namespace Statistics { -HistogramController::HistogramController(Responder * parentResponder, HeaderViewController * headerViewController) : +HistogramController::HistogramController(Responder * parentResponder, HeaderViewController * headerViewController, Data * data) : ViewController(parentResponder), HeaderViewDelegate(headerViewController), m_view(SolidColorView(KDColorGreen)), m_settingButton(Button(this, "Reglages de l'histogramme",Invocation([](void * context, void * sender) {}, this))), - m_selectedBin(0) + m_selectedBin(0), + m_data(data) { } @@ -49,11 +50,14 @@ Button * HistogramController::buttonAtIndex(int index) { } bool HistogramController::isEmpty() { + if (m_data->numberOfPairs() == 0) { + return true; + } return false; } const char * HistogramController::emptyMessage() { - return "Aucune donnée à tracer"; + return "Aucune donnee à tracer"; } Responder * HistogramController::defaultController() { diff --git a/apps/statistics/histogram_controller.h b/apps/statistics/histogram_controller.h index c0fed2498..0f7726ad8 100644 --- a/apps/statistics/histogram_controller.h +++ b/apps/statistics/histogram_controller.h @@ -2,13 +2,14 @@ #define STATISTICS_HISTOGRAM_CONTROLLER_H #include +#include "data.h" namespace Statistics { class HistogramController : public ViewController, public HeaderViewDelegate, public AlternateEmptyViewDelegate { public: - HistogramController(Responder * parentResponder, HeaderViewController * headerViewController); + HistogramController(Responder * parentResponder, HeaderViewController * headerViewController, Data * m_data); const char * title() const override; View * view() override; bool handleEvent(Ion::Events::Event event) override; @@ -24,6 +25,7 @@ private: SolidColorView m_view; Button m_settingButton; int m_selectedBin; + Data * m_data; }; } From 30fb8307bc16bbf44610d75062c9f36b6a179903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 11:30:53 +0100 Subject: [PATCH 06/14] [apps/graph/graph] Create a class banner view Change-Id: I76e4f1a4300f631bbd93855bc992beb81bc5fecf --- apps/graph/Makefile | 1 + apps/graph/graph/banner_view.cpp | 82 ++++++++++++++++++++++++++++++++ apps/graph/graph/banner_view.h | 33 +++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 apps/graph/graph/banner_view.cpp create mode 100644 apps/graph/graph/banner_view.h diff --git a/apps/graph/Makefile b/apps/graph/Makefile index 01bb69cda..afd4276c9 100644 --- a/apps/graph/Makefile +++ b/apps/graph/Makefile @@ -3,6 +3,7 @@ app_objs += $(addprefix apps/graph/,\ function.o\ function_store.o\ function_title_cell.o\ + graph/banner_view.o\ graph/graph_window.o\ graph/window_parameter_controller.o\ graph/cursor_view.o\ diff --git a/apps/graph/graph/banner_view.cpp b/apps/graph/graph/banner_view.cpp new file mode 100644 index 000000000..306b9a2a3 --- /dev/null +++ b/apps/graph/graph/banner_view.cpp @@ -0,0 +1,82 @@ +#include "banner_view.h" +#include +#include "../../constant.h" + +namespace Graph { + +BannerView::BannerView() : + m_abscissa(0.0f), + m_function(nullptr), + m_abscissaView(0.0f, 0.5f), + m_functionView(0.5f, 0.5f), + m_derivativeView(1.0f, 0.5f), + m_displayDerivative(false), + m_context(nullptr) +{ +} + +void BannerView::drawRect(KDContext * ctx, KDRect rect) const { + ctx->fillRect(bounds(), KDColorWhite); +} + +void BannerView::setContext(Context * context) { + m_context = context; +} + +void BannerView::setAbscissa(float x) { + markRectAsDirty(bounds()); + m_abscissa = x; + char buffer[4+Constant::FloatBufferSizeInScientificMode] = {'x', ' ', '=', ' ',0}; + Float(x).convertFloatToText(buffer+4, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_abscissaView.setText(buffer); +} + +void BannerView::setFunction(Function * f) { + markRectAsDirty(bounds()); + m_function = f; + float y = f->evaluateAtAbscissa(m_abscissa, m_context); + char buffer[8+Constant::FloatBufferSizeInScientificMode] = {0, 0, '(', 'x', ')', ' ', '=', ' ',0}; + buffer[1] = f->name()[0]; + Float(y).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaInScientificMode); + m_functionView.setText(buffer+1); + + y = f->approximateDerivative(m_abscissa, m_context); + buffer[0] = f->name()[0]; + buffer[1] = '\''; + Float(y).convertFloatToText(buffer+8, Constant::FloatBufferSizeInScientificMode, Constant::NumberOfDigitsInMantissaForDerivativeNumberInScientificMode); + m_derivativeView.setText(buffer); +} + +void BannerView::setDisplayDerivative(bool displayDerivative) { + m_displayDerivative = displayDerivative; +} + +bool BannerView::displayDerivative() { + return m_displayDerivative; +} + +int BannerView::numberOfSubviews() const { + if (m_displayDerivative) { + return 3; + } + return 2; +} + +View * BannerView::subviewAtIndex(int index) { + assert(index >= 0); + if (index == 0) { + return &m_abscissaView; + } + if (index == 1) { + return &m_functionView; + } + return &m_derivativeView; +} + +void BannerView::layoutSubviews() { + m_abscissaView.setFrame(bounds()); + m_functionView.setFrame(bounds()); + m_derivativeView.setFrame(bounds()); +} + +} diff --git a/apps/graph/graph/banner_view.h b/apps/graph/graph/banner_view.h new file mode 100644 index 000000000..e3770319b --- /dev/null +++ b/apps/graph/graph/banner_view.h @@ -0,0 +1,33 @@ +#ifndef GRAPH_BANNER_VIEW_H +#define GRAPH_BANNER_VIEW_H + +#include +#include "../function.h" + +namespace Graph { + +class BannerView : public View { +public: + BannerView(); + void drawRect(KDContext * ctx, KDRect rect) const override; + void setContext(Context * context); + void setAbscissa(float x); + void setFunction(Function * f); + void setDisplayDerivative(bool displayDerivative); + bool displayDerivative(); +private: + int numberOfSubviews() const override; + View * subviewAtIndex(int index) override; + void layoutSubviews() override; + float m_abscissa; + Function * m_function; + BufferTextView m_abscissaView; + BufferTextView m_functionView; + BufferTextView m_derivativeView; + bool m_displayDerivative; + Context * m_context; +}; + +} + +#endif From ba67ef4a2e49e08d3b9be35d1eef75618f3f9d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 11:31:53 +0100 Subject: [PATCH 07/14] [apps/graph/graph] Add a banner view in the graph view Change-Id: Iafa0dcfc730911264d5b045c14bde54f432f53a2 --- .../graph/curve_parameter_controller.cpp | 9 ++----- apps/graph/graph/curve_parameter_controller.h | 2 -- apps/graph/graph/graph_view.cpp | 26 ++++++++++++++++--- apps/graph/graph/graph_view.h | 6 +++++ 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/apps/graph/graph/curve_parameter_controller.cpp b/apps/graph/graph/curve_parameter_controller.cpp index 54fb977b8..49bd845e0 100644 --- a/apps/graph/graph/curve_parameter_controller.cpp +++ b/apps/graph/graph/curve_parameter_controller.cpp @@ -6,7 +6,6 @@ namespace Graph { CurveParameterController::CurveParameterController(GraphView * graphView) : ViewController(nullptr), m_graphView(graphView), - m_displayDerivative(false), m_function(nullptr), m_calculationCell(ChevronMenuListCell((char*)"Calculer")), m_goToCell(ChevronMenuListCell((char*)"Aller a")), @@ -33,7 +32,7 @@ void CurveParameterController::didBecomeFirstResponder() { void CurveParameterController::willDisplayCellForIndex(TableViewCell * cell, int index) { if (cell == &m_derivativeCell) { SwitchView * switchView = (SwitchView *)m_derivativeCell.accessoryView(); - switchView->setState(m_displayDerivative); + switchView->setState(m_graphView->bannerView()->displayDerivative()); } } @@ -50,7 +49,7 @@ bool CurveParameterController::handleEvent(Ion::Events::Event event) { return true; } case 2: - m_displayDerivative = !m_displayDerivative; + m_graphView->bannerView()->setDisplayDerivative(!m_graphView->bannerView()->displayDerivative()); m_selectableTableView.reloadData(); return true; default: @@ -79,10 +78,6 @@ KDCoordinate CurveParameterController::cellHeight() { return 35; } -bool CurveParameterController::displayDerivative() const { - return m_displayDerivative; -} - void CurveParameterController::setFunction(Function * function) { m_function = function; } diff --git a/apps/graph/graph/curve_parameter_controller.h b/apps/graph/graph/curve_parameter_controller.h index fd2e49f11..e89608968 100644 --- a/apps/graph/graph/curve_parameter_controller.h +++ b/apps/graph/graph/curve_parameter_controller.h @@ -20,11 +20,9 @@ public: TableViewCell * reusableCell(int index) override; int reusableCellCount() override; void willDisplayCellForIndex(TableViewCell * cell, int index) override; - bool displayDerivative() const; void setFunction(Function * function); private: GraphView * m_graphView; - bool m_displayDerivative; Function * m_function; constexpr static int k_totalNumberOfCells = 3; ChevronMenuListCell m_calculationCell; diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index 409927a45..c04d9ccd5 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -19,17 +19,25 @@ GraphView::GraphView(FunctionStore * functionStore, GraphWindow * graphWindow) : { } +BannerView * GraphView::bannerView() { + return &m_bannerView; +} + int GraphView::numberOfSubviews() const { - return 1; + return 2; }; View * GraphView::subviewAtIndex(int index) { - assert(index == 0); - return &m_cursorView; + assert(index >= 0 && index < 2); + if (index == 0) { + return &m_cursorView; + } + return &m_bannerView; } void GraphView::setContext(Context * context) { m_context = context; + m_bannerView.setContext(context); } Context * GraphView::context() const { @@ -74,6 +82,7 @@ void GraphView::goToAbscissaOnFunction(float abscissa, Function * function) { float ordinate = function->evaluateAtAbscissa(abscissa, m_context); m_graphWindow->centerAxisAround(GraphWindow::Axis::Y, ordinate); m_yCursorPosition = floatToPixel(Axis::Vertical, ordinate); + updateBannerView(function); reload(); } @@ -89,6 +98,7 @@ void GraphView::initCursorPosition() { float fCenter = firstFunction->evaluateAtAbscissa(center, m_context); m_xCursorPosition = (bounds().width()-1.0f)/2.0f; m_yCursorPosition = floatToPixel(Axis::Vertical, fCenter); + updateBannerView(firstFunction); } void GraphView::moveCursorHorizontally(KDCoordinate xOffset) { @@ -102,6 +112,7 @@ void GraphView::moveCursorHorizontally(KDCoordinate xOffset) { bool windowHasMoved = m_graphWindow->panToMakePointVisible(x, y, xMargin, yMargin); m_xCursorPosition = floatToPixel(Axis::Horizontal, x); m_yCursorPosition = floatToPixel(Axis::Vertical, y); + updateBannerView(f); if (windowHasMoved) { reload(); } else { @@ -134,6 +145,7 @@ Function * GraphView::moveCursorVertically(int direction) { markRectAsDirty(KDRect(KDPoint(roundf(m_xCursorPosition) - k_cursorSize/2, roundf(m_yCursorPosition)- k_cursorSize/2), k_cursorSize, k_cursorSize)); m_xCursorPosition = floatToPixel(Axis::Horizontal, x); m_yCursorPosition = floatToPixel(Axis::Vertical, nextY); + updateBannerView(nextFunction); if (windowHasMoved) { reload(); } else { @@ -144,10 +156,13 @@ Function * GraphView::moveCursorVertically(int direction) { void GraphView::layoutSubviews() { KDRect cursorFrame(roundf(m_xCursorPosition) - k_cursorSize/2, roundf(m_yCursorPosition) - k_cursorSize/2, k_cursorSize, k_cursorSize); + KDRect bannerFrame(KDRect(0, bounds().height()- k_bannerHeight, bounds().width(), k_bannerHeight)); if (!m_visibleCursor) { cursorFrame = KDRectZero; + bannerFrame = KDRectZero; } m_cursorView.setFrame(cursorFrame); + m_bannerView.setFrame(bannerFrame); } void GraphView::drawRect(KDContext * ctx, KDRect rect) const { @@ -199,4 +214,9 @@ float GraphView::evaluateCurveAtAbscissa(void * curve, float abscissa) const { return f->evaluateAtAbscissa(abscissa, m_context); } +void GraphView::updateBannerView(Function * function) { + m_bannerView.setAbscissa(xCursorPosition()); + m_bannerView.setFunction(function); +} + } diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h index 7bcfb4b29..11acba314 100644 --- a/apps/graph/graph/graph_view.h +++ b/apps/graph/graph/graph_view.h @@ -2,6 +2,7 @@ #define GRAPH_GRAPH_VIEW_H #include +#include "banner_view.h" #include "cursor_view.h" #include "graph_window.h" #include "../../curve_view.h" @@ -14,6 +15,7 @@ namespace Graph { class GraphView : public CurveView { public: GraphView(FunctionStore * functionStore, GraphWindow * graphWindow); + BannerView * bannerView(); void drawRect(KDContext * ctx, KDRect rect) const override; float xPixelCursorPosition(); @@ -32,6 +34,7 @@ private: constexpr static KDColor k_gridColor = KDColor::RGB24(0xEEEEEE); constexpr static KDCoordinate k_cursorSize = 9; constexpr static float k_cursorMarginToBorder = 6.0f; + constexpr static KDCoordinate k_bannerHeight = 30; int numberOfSubviews() const override; View * subviewAtIndex(int index) override; @@ -44,6 +47,9 @@ private: float evaluateCurveAtAbscissa(void * expression, float abscissa) const override; void drawGrid(KDContext * ctx, KDRect rect) const; void drawGridLines(KDContext * ctx, KDRect rect, Axis axis, float step, KDColor color) const; + void updateBannerView(Function * function); + + BannerView m_bannerView; CursorView m_cursorView; float m_xCursorPosition; From 4e1bd2b4774290ed2d27c036d94018a8d0016e1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 13:58:26 +0100 Subject: [PATCH 08/14] [apps/graph/graph] When redrawing the curve, slightly exceed the rect to ensure the continuity of the curve Change-Id: I7dcdc53dc14819b7bf1327a7ba98d459b3bc9c63 --- apps/curve_view.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/curve_view.cpp b/apps/curve_view.cpp index 76ada169e..4f4ca29a2 100644 --- a/apps/curve_view.cpp +++ b/apps/curve_view.cpp @@ -131,13 +131,14 @@ const uint8_t stampMask[stampSize+1][stampSize+1] = { constexpr static int k_maxNumberOfIterations = 10; constexpr static int k_resolution = 320.0f; +constexpr static int k_externRectMargin = 1; void CurveView::drawCurve(void * curve, KDColor color, KDContext * ctx, KDRect rect, bool colorUnderCurve, float colorLowerBound, float colorUpperBound, bool continuously) const { float xMin = min(Axis::Horizontal); float xMax = max(Axis::Horizontal); float xStep = (xMax-xMin)/k_resolution; - float rectMin = pixelToFloat(Axis::Horizontal, rect.left()); - float rectMax = pixelToFloat(Axis::Horizontal, rect.right()); + float rectMin = pixelToFloat(Axis::Horizontal, rect.left() - k_externRectMargin); + float rectMax = pixelToFloat(Axis::Horizontal, rect.right() + k_externRectMargin); for (float x = rectMin; x < rectMax; x += xStep) { float y = evaluateCurveAtAbscissa(curve, x); float pxf = floatToPixel(Axis::Horizontal, x); From 9ce66a254b176eb0f4f5f371dbca186281d35a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 14:05:55 +0100 Subject: [PATCH 09/14] [apps] Create an abstract model curve view window Change-Id: Iec94d0d75d03bb7a2a3e7085f38a0732639baff7 --- apps/Makefile | 1 + apps/curve_view_window.cpp | 29 +++++++++++++++++++++++++++++ apps/curve_view_window.h | 27 +++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 apps/curve_view_window.cpp create mode 100644 apps/curve_view_window.h diff --git a/apps/Makefile b/apps/Makefile index 61d173693..3aae45d86 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -9,6 +9,7 @@ app_objs += $(addprefix apps/,\ apps_container.o\ constant.o\ curve_view.o\ + curve_view_window.o\ editable_cell_table_view_controller.o\ expression_text_field_delegate.o\ float_parameter_controller.o\ diff --git a/apps/curve_view_window.cpp b/apps/curve_view_window.cpp new file mode 100644 index 000000000..682b8918e --- /dev/null +++ b/apps/curve_view_window.cpp @@ -0,0 +1,29 @@ +#include "curve_view_window.h" +#include +#include + +float CurveViewWindow::yGridUnit() { + return 0.0f; +} + +float CurveViewWindow::computeGridUnit(Axis axis) { + int a = 0; + int b = 0; + float d = xMax() - xMin(); + float maxNumberOfUnits = k_maxNumberOfXGridUnits; + float minNumberOfUnits = k_minNumberOfXGridUnits; + if (axis == Axis::Y) { + d = yMax() - yMin(); + maxNumberOfUnits = k_maxNumberOfYGridUnits; + minNumberOfUnits = k_minNumberOfYGridUnits; + } + float units[3] = {k_oneUnit, k_twoUnit, k_fiveUnit}; + for (int k = 0; k < 3; k++) { + float unit = units[k]; + if (floorf(log10f(d/(unit*maxNumberOfUnits))) != floorf(log10f(d/(unit*minNumberOfUnits)))) { + b = floorf(log10f(d/(unit*minNumberOfUnits))); + a = unit; + } + } + return a*powf(10,b); +} diff --git a/apps/curve_view_window.h b/apps/curve_view_window.h new file mode 100644 index 000000000..48412cf71 --- /dev/null +++ b/apps/curve_view_window.h @@ -0,0 +1,27 @@ +#ifndef APPS_CURVE_VIEW_WINDOW_H +#define APPS_CURVE_VIEW_WINDOW_H + +class CurveViewWindow { +public: + enum class Axis { + X, + Y + }; + virtual float xMin() = 0; + virtual float xMax() = 0; + virtual float yMin() = 0; + virtual float yMax() = 0; + virtual float xGridUnit() = 0; + virtual float yGridUnit(); +protected: + constexpr static float k_minNumberOfXGridUnits = 7.0f; + constexpr static float k_maxNumberOfXGridUnits = 18.0f; + constexpr static float k_minNumberOfYGridUnits = 5.0f; + constexpr static float k_maxNumberOfYGridUnits = 13.0f; + constexpr static float k_oneUnit = 1.0f; + constexpr static float k_twoUnit = 2.0f; + constexpr static float k_fiveUnit = 5.0f; + float computeGridUnit(Axis axis); +}; + +#endif From 2f3bfaf209927b5b3d102cb2856fef52f5b5fc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 14:10:30 +0100 Subject: [PATCH 10/14] [apps/graph/graph] Make the model graph window inherit from curve view window Change-Id: I21a08f181725800937ec5ee043cc40a0ac301a6a --- apps/graph/graph/graph_window.cpp | 72 ++++++++++--------------------- apps/graph/graph/graph_window.h | 27 ++++-------- 2 files changed, 31 insertions(+), 68 deletions(-) diff --git a/apps/graph/graph/graph_window.cpp b/apps/graph/graph/graph_window.cpp index 72d74d185..555f6db7c 100644 --- a/apps/graph/graph/graph_window.cpp +++ b/apps/graph/graph/graph_window.cpp @@ -51,23 +51,23 @@ float GraphWindow::yGridUnit() { void GraphWindow::setXMin(float xMin) { m_xMin = xMin; computeYaxes(); - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); } void GraphWindow::setXMax(float xMax) { m_xMax = xMax; computeYaxes(); - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); } void GraphWindow::setYMin(float yMin) { m_yMin = yMin; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } void GraphWindow::setYMax(float yMax) { m_yMax = yMax; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } void GraphWindow::setYAuto(bool yAuto) { @@ -104,7 +104,7 @@ bool GraphWindow::computeYaxes() { m_yMax = max + 1; } } - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); return true; } @@ -123,11 +123,11 @@ void GraphWindow::zoom(float ratio) { float yMax = m_yMax; m_xMin = (xMax+xMin)/2.0f - ratio*fabsf(xMax-xMin); m_xMax = (xMax+xMin)/2.0f + ratio*fabsf(xMax-xMin); - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); m_yAuto = false; m_yMin = (yMax+yMin)/2.0f - ratio*fabsf(yMax-yMin); m_yMax = (yMax+yMin)/2.0f + ratio*fabsf(yMax-yMin); - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } void GraphWindow::centerAxisAround(Axis axis, float position) { @@ -136,13 +136,13 @@ void GraphWindow::centerAxisAround(Axis axis, float position) { m_xMin = position - range/2.0f; m_xMax = position + range/2.0f; computeYaxes(); - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); } else { m_yAuto = false; float range = m_yMax - m_yMin; m_yMin = position - range/2.0f; m_yMax = position + range/2.0f; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } } @@ -151,23 +151,23 @@ void GraphWindow::translateWindow(Direction direction) { if (direction == Direction::Up) { m_yMin = m_yMin + m_yGridUnit; m_yMax = m_yMax + m_yGridUnit; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } if (direction == Direction::Down) { m_yMin = m_yMin - m_yGridUnit; m_yMax = m_yMax - m_yGridUnit; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } if (direction == Direction::Left) { m_xMin = m_xMin - m_xGridUnit; m_xMax = m_xMax - m_xGridUnit; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); computeYaxes(); } if (direction == Direction::Right) { m_xMin = m_xMin + m_xGridUnit; m_xMax = m_xMax + m_xGridUnit; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); computeYaxes(); } } @@ -175,11 +175,11 @@ void GraphWindow::translateWindow(Direction direction) { void GraphWindow::setTrigonometric() { m_xMin = -10.5f; m_xMax = 10.5f; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); m_yAuto = false; m_yMin = -1.6f; m_yMax = 1.6f; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } void GraphWindow::roundAbscissa() { @@ -187,7 +187,7 @@ void GraphWindow::roundAbscissa() { float xMax = m_xMax; m_xMin = roundf((xMin+xMax)/2) - 160.0f; m_xMax = roundf((xMin+xMax)/2) + 159.0f; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); computeYaxes(); } @@ -198,17 +198,17 @@ void GraphWindow::normalize() { float yMax = m_yMax; m_xMin = (xMin+xMax)/2 - 5.3f; m_xMax = (xMin+xMax)/2 + 5.3f; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); m_yAuto = false; m_yMin = (yMin+yMax)/2 - 3.1f; m_yMax = (yMin+yMax)/2 + 3.1f; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); } void GraphWindow::setDefault() { m_xMin = -10.0f; m_xMax = 10.0f; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); setYAuto(true); } @@ -219,56 +219,30 @@ bool GraphWindow::panToMakePointVisible(float x, float y, float xMargin, float y if (x < m_xMin + xMargin) { m_xMin = x - xMargin; m_xMax = m_xMin + xRange; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); computeYaxes(); windowMoved = true; } if (x > m_xMax - xMargin) { m_xMax = x + xMargin; m_xMin = m_xMax - xRange; - computeGridUnit(Axis::X); + m_xGridUnit = computeGridUnit(Axis::X); computeYaxes(); windowMoved = true; } if (y < m_yMin + yMargin) { m_yMin = y - yMargin; m_yMax = m_yMin + yRange; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); windowMoved = true; } if (y > m_yMax - yMargin) { m_yMax = y + yMargin; m_yMin = m_yMax - yRange; - computeGridUnit(Axis::Y); + m_yGridUnit = computeGridUnit(Axis::Y); windowMoved = true; } return windowMoved; } -void GraphWindow::computeGridUnit(Axis axis) { - int a = 0; - int b = 0; - float d = m_xMax - m_xMin; - float maxNumberOfUnits = k_maxNumberOfXGridUnits; - float minNumberOfUnits = k_minNumberOfXGridUnits; - if (axis == Axis::Y) { - d = m_yMax - m_yMin; - maxNumberOfUnits = k_maxNumberOfYGridUnits; - minNumberOfUnits = k_minNumberOfYGridUnits; - } - float units[3] = {k_oneUnit, k_twoUnit, k_fiveUnit}; - for (int k = 0; k < 3; k++) { - float unit = units[k]; - if (floorf(log10f(d/(unit*maxNumberOfUnits))) != floorf(log10f(d/(unit*minNumberOfUnits)))) { - b = floorf(log10f(d/(unit*minNumberOfUnits))); - a = unit; - } - } - if (axis == Axis::X) { - m_xGridUnit = a*powf(10,b); - } else { - m_yGridUnit = a*powf(10,b); - } -} - } diff --git a/apps/graph/graph/graph_window.h b/apps/graph/graph/graph_window.h index eb1b94835..5a94877f5 100644 --- a/apps/graph/graph/graph_window.h +++ b/apps/graph/graph/graph_window.h @@ -2,15 +2,12 @@ #define GRAPH_GRAPH_AXIS_INTERVAL_H #include "../function_store.h" +#include "../../curve_view_window.h" namespace Graph { -class GraphWindow { +class GraphWindow : public CurveViewWindow { public: - enum class Axis { - X, - Y - }; enum class Direction { Up, Left, @@ -18,13 +15,13 @@ public: Right }; GraphWindow(FunctionStore * functionStore); - float xMin(); - float xMax(); - float yMin(); - float yMax(); + float xMin() override; + float xMax() override; + float yMin() override; + float yMax() override; bool yAuto(); - float xGridUnit(); - float yGridUnit(); + float xGridUnit() override; + float yGridUnit() override; void setXMin(float f); void setXMax(float f); void setYMin(float f); @@ -44,14 +41,6 @@ public: void setDefault(); bool panToMakePointVisible(float x, float y, float xMargin, float yMargin); private: - constexpr static float k_minNumberOfXGridUnits = 7.0f; - constexpr static float k_maxNumberOfXGridUnits = 18.0f; - constexpr static float k_minNumberOfYGridUnits = 5.0f; - constexpr static float k_maxNumberOfYGridUnits = 13.0f; - constexpr static float k_oneUnit = 1.0f; - constexpr static float k_twoUnit = 2.0f; - constexpr static float k_fiveUnit = 5.0f; - void computeGridUnit(Axis axis); float m_xMin; float m_xMax; float m_yMin; From 0be1c43f721739187435188c40154b934e2a3ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 14:11:54 +0100 Subject: [PATCH 11/14] [apps/probability] Make the model law inherit from curve view window Change-Id: I2e2cf0c7a14cb1cb36c5b22c49b604d659d49bc6 --- apps/probability/law/law.cpp | 15 ++------------- apps/probability/law/law.h | 14 +++----------- apps/probability/law_curve_view.cpp | 2 +- 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/apps/probability/law/law.cpp b/apps/probability/law/law.cpp index 243057ffe..b05cdb0db 100644 --- a/apps/probability/law/law.cpp +++ b/apps/probability/law/law.cpp @@ -4,19 +4,8 @@ namespace Probability { -float Law::gridUnit() { - int a = 0; - int b = 0; - float d = xMax() - xMin(); - float units[3] = {k_oneUnit, k_twoUnit, k_fiveUnit}; - for (int k = 0; k < 3; k++) { - float unit = units[k]; - if (floorf(log10f(d/(unit*k_maxNumberOfXGridUnits))) != floorf(log10f(d/(unit*k_minNumberOfXGridUnits)))) { - b = floorf(log10f(d/(unit*k_minNumberOfXGridUnits))); - a = unit; - } - } - return a*powf(10,b); +float Law::xGridUnit() { + return computeGridUnit(Axis::X); } float Law::cumulativeDistributiveFunctionAtAbscissa(float x) const { diff --git a/apps/probability/law/law.h b/apps/probability/law/law.h index c7ef88b4e..9d718967b 100644 --- a/apps/probability/law/law.h +++ b/apps/probability/law/law.h @@ -2,10 +2,11 @@ #define PROBABILITE_LAW_H #include +#include "../../curve_view_window.h" namespace Probability { -class Law { +class Law : public CurveViewWindow { public: enum class Type : uint8_t{ Binomial, @@ -18,11 +19,7 @@ public: virtual const char * title() = 0; virtual Type type() const = 0; virtual bool isContinuous() const = 0; - virtual float xMin() = 0; - virtual float yMin() = 0; - virtual float xMax() = 0; - virtual float yMax() = 0; - float gridUnit(); + float xGridUnit() override; virtual int numberOfParameter() = 0; virtual float parameterValueAtIndex(int index) = 0; virtual const char * parameterNameAtIndex(int index) = 0; @@ -36,11 +33,6 @@ public: virtual float cumulativeDistributiveInverseForProbability(float * probability); virtual float rightIntegralInverseForProbability(float * probability); protected: - constexpr static float k_minNumberOfXGridUnits = 7.0f; - constexpr static float k_maxNumberOfXGridUnits = 18.0f; - constexpr static float k_oneUnit = 1.0f; - constexpr static float k_twoUnit = 2.0f; - constexpr static float k_fiveUnit = 5.0f; constexpr static float k_minMarginFactor = -0.2f; constexpr static float k_maxMarginFactor = 1.2f; constexpr static int k_maxNumberOfOperations = 1000000; diff --git a/apps/probability/law_curve_view.cpp b/apps/probability/law_curve_view.cpp index a86cd134b..5d1186161 100644 --- a/apps/probability/law_curve_view.cpp +++ b/apps/probability/law_curve_view.cpp @@ -57,7 +57,7 @@ float LawCurveView::max(Axis axis) const { float LawCurveView::gridUnit(Axis axis) const { assert(axis == Axis::Horizontal); - return m_law->gridUnit(); + return m_law->xGridUnit(); } char * LawCurveView::label(Axis axis, int index) const { From cda9582a7cc8e4bbff2a44e8a87dd0f22d092161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 14:20:57 +0100 Subject: [PATCH 12/14] [apps/statistics] Make data model inherit from curve view window Change-Id: Iabf36299d20b17d9ac6fb4ae3a6166513f9a50c7 --- apps/statistics/data.cpp | 53 ++++++++++++++++++++++++++++++++++++++++ apps/statistics/data.h | 12 ++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/apps/statistics/data.cpp b/apps/statistics/data.cpp index e362f2014..db1c5667b 100644 --- a/apps/statistics/data.cpp +++ b/apps/statistics/data.cpp @@ -1,4 +1,5 @@ #include "data.h" +#include namespace Statistics { @@ -45,4 +46,56 @@ void Data::deletePairAtIndex(int index) { m_sizes[m_numberOfPairs] = 1; } +int Data::sizeOfValuesBetweenBounds(float lowerBound, float upperBound) const { + int result = 0; + for (int k = 0; k < m_numberOfPairs; k++) { + if (m_values[k] < upperBound && lowerBound <= m_values[k]) { + result += m_sizes[k]; + } + } + return result; +} + +float Data::xMin() { + float valueMin = FLT_MAX; + for (int k = 0; k < m_numberOfPairs; k++) { + if (m_values[k] < valueMin) { + valueMin = m_values[k]; + } + } + return valueMin; +} + +float Data::xMax() { + float valueMax = -FLT_MAX; + for (int k = 0; k < m_numberOfPairs; k++) { + if (m_values[k] > valueMax) { + valueMax = m_values[k]; + } + } + float valueMin = xMin(); + if (valueMax - valueMin > k_maxRangeValue) { + valueMax = valueMin + 10.0f; + } + return valueMax; +} + +float Data::yMin() { + return 0.0f; +} + +float Data::yMax() { + float sizeMax = -FLT_MAX; + for (int k = 0; k < m_numberOfPairs; k++) { + if (m_sizes[k] > sizeMax) { + sizeMax = m_sizes[k]; + } + } + return sizeMax; +} + +float Data::xGridUnit() { + return computeGridUnit(Axis::X); +} + } diff --git a/apps/statistics/data.h b/apps/statistics/data.h index 1876e1e2b..61b6bdc40 100644 --- a/apps/statistics/data.h +++ b/apps/statistics/data.h @@ -1,9 +1,11 @@ #ifndef STATISTICS_DATA_H #define STATISTICS_DATA_H +#include "../curve_view_window.h" + namespace Statistics { -class Data { +class Data : public CurveViewWindow { public: Data(); // Delete the implicit copy constructor: the object is heavy @@ -14,9 +16,17 @@ public: void setValueAtIndex(float value, int index); void setSizeAtIndex(int size, int index); void deletePairAtIndex(int index); + int sizeOfValuesBetweenBounds(float lowerBound, float upperBound) const; + float xMin() override; + // if the range of value is to wide, value max returns valueMin + 10 + float xMax() override; + float yMin() override; + float yMax() override; + float xGridUnit() override; // TODO: decide the max number of elements after optimization constexpr static int k_maxNumberOfPairs = 500; private: + constexpr static int k_maxRangeValue = 320; int m_sizes[k_maxNumberOfPairs]; float m_values[k_maxNumberOfPairs]; int m_numberOfPairs; From 4d62c6c9bdb8bb3000c0d3f36aebe5dc7cfad2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 14:39:39 +0100 Subject: [PATCH 13/14] [apps] Use curve view window in the abstract class curve view Change-Id: I2c54cb111944f294e00d45244f23cdda9984bf02 --- apps/curve_view.cpp | 23 +++++++++++++++++++++-- apps/curve_view.h | 11 +++++++---- apps/graph/graph/graph_view.cpp | 16 +--------------- apps/graph/graph/graph_view.h | 3 --- apps/probability/law_curve_view.cpp | 16 +--------------- apps/probability/law_curve_view.h | 3 --- 6 files changed, 30 insertions(+), 42 deletions(-) diff --git a/apps/curve_view.cpp b/apps/curve_view.cpp index 4f4ca29a2..0ed9c571f 100644 --- a/apps/curve_view.cpp +++ b/apps/curve_view.cpp @@ -7,15 +7,34 @@ constexpr KDColor CurveView::k_axisColor; -CurveView::CurveView() : - View() +CurveView::CurveView(CurveViewWindow * curveViewWindow) : + View(), + m_curveViewWindow(curveViewWindow) { } +void CurveView::setCurveViewWindow(CurveViewWindow * curveViewWindow) { + m_curveViewWindow = curveViewWindow; +} + void CurveView::reload() { markRectAsDirty(bounds()); } +float CurveView::min(Axis axis) const { + assert(axis == Axis::Horizontal || axis == Axis::Vertical); + return (axis == Axis::Horizontal ? m_curveViewWindow->xMin() : m_curveViewWindow->yMin()); +} + +float CurveView::max(Axis axis) const { + assert(axis == Axis::Horizontal || axis == Axis::Vertical); + return (axis == Axis::Horizontal ? m_curveViewWindow->xMax() : m_curveViewWindow->yMax()); +} + +float CurveView::gridUnit(Axis axis) const { + return (axis == Axis::Horizontal ? m_curveViewWindow->xGridUnit() : m_curveViewWindow->yGridUnit()); +} + KDCoordinate CurveView::pixelLength(Axis axis) const { assert(axis == Axis::Horizontal || axis == Axis::Vertical); return (axis == Axis::Horizontal ? m_frame.width() : m_frame.height()); diff --git a/apps/curve_view.h b/apps/curve_view.h index 3aae1b06a..571c5dfc0 100644 --- a/apps/curve_view.h +++ b/apps/curve_view.h @@ -3,6 +3,7 @@ #include #include +#include "curve_view_window.h" class CurveView : public View { public: @@ -10,16 +11,17 @@ public: Horizontal = 0, Vertical = 1 }; - CurveView(); + CurveView(CurveViewWindow * curveViewWindow = nullptr); void reload(); protected: constexpr static KDColor k_axisColor = KDColor::RGB24(0x000000); constexpr static KDCoordinate k_labelMargin = 4; constexpr static int k_maxNumberOfXLabels = 18; constexpr static int k_maxNumberOfYLabels = 13; - virtual float min(Axis axis) const = 0; - virtual float max(Axis axis) const = 0; - virtual float gridUnit(Axis axis) const = 0; + void setCurveViewWindow(CurveViewWindow * curveViewWindow); + float min(Axis axis) const; + float max(Axis axis) const; + float gridUnit(Axis axis) const; virtual char * label(Axis axis, int index) const = 0; KDCoordinate pixelLength(Axis axis) const; float pixelToFloat(Axis axis, KDCoordinate p) const; @@ -43,6 +45,7 @@ private: * function shifts the stamp (by blending adjacent pixel colors) to draw with * anti alising. */ void stampAtLocation(float pxf, float pyf, KDColor color, KDContext * ctx, KDRect rect) const; + CurveViewWindow * m_curveViewWindow; }; #endif diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index c04d9ccd5..92de61c06 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -8,7 +8,7 @@ namespace Graph { constexpr KDColor GraphView::k_gridColor; GraphView::GraphView(FunctionStore * functionStore, GraphWindow * graphWindow) : - CurveView(), + CurveView(graphWindow), m_cursorView(CursorView()), m_xCursorPosition(-1.0f), m_yCursorPosition(-1.0f), @@ -60,10 +60,6 @@ void GraphView::reloadCursor() { layoutSubviews(); } -float GraphView::gridUnit(Axis axis) const { - return (axis == Axis::Horizontal ? m_graphWindow->xGridUnit() : m_graphWindow->yGridUnit()); -} - char * GraphView::label(Axis axis, int index) const { return (axis == Axis::Horizontal ? (char *)m_xLabels[index] : (char *)m_yLabels[index]); } @@ -199,16 +195,6 @@ void GraphView::drawGrid(KDContext * ctx, KDRect rect) const { drawGridLines(ctx, rect, Axis::Vertical, m_graphWindow->yGridUnit(), k_gridColor); } -float GraphView::min(Axis axis) const { - assert(axis == Axis::Horizontal || axis == Axis::Vertical); - return (axis == Axis::Horizontal ? m_graphWindow->xMin() : m_graphWindow->yMin()); -} - -float GraphView::max(Axis axis) const { - assert(axis == Axis::Horizontal || axis == Axis::Vertical); - return (axis == Axis::Horizontal ? m_graphWindow->xMax() : m_graphWindow->yMax()); -} - float GraphView::evaluateCurveAtAbscissa(void * curve, float abscissa) const { Function * f = (Function *)curve; return f->evaluateAtAbscissa(abscissa, m_context); diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h index 11acba314..0723a7607 100644 --- a/apps/graph/graph/graph_view.h +++ b/apps/graph/graph/graph_view.h @@ -40,9 +40,6 @@ private: View * subviewAtIndex(int index) override; void layoutSubviews() override; - float min(Axis axis) const override; - float max(Axis axis) const override; - float gridUnit(Axis axis) const override; char * label(Axis axis, int index) const override; float evaluateCurveAtAbscissa(void * expression, float abscissa) const override; void drawGrid(KDContext * ctx, KDRect rect) const; diff --git a/apps/probability/law_curve_view.cpp b/apps/probability/law_curve_view.cpp index 5d1186161..7e8752d3a 100644 --- a/apps/probability/law_curve_view.cpp +++ b/apps/probability/law_curve_view.cpp @@ -12,6 +12,7 @@ LawCurveView::LawCurveView() : } void LawCurveView::setLaw(Law * law) { + setCurveViewWindow(law); m_law = law; } @@ -45,21 +46,6 @@ void LawCurveView::drawRect(KDContext * ctx, KDRect rect) const { } } -float LawCurveView::min(Axis axis) const { - assert(axis == Axis::Horizontal || axis == Axis::Vertical); - return (axis == Axis::Horizontal ? m_law->xMin() : m_law->yMin()); -} - -float LawCurveView::max(Axis axis) const { - assert(axis == Axis::Horizontal || axis == Axis::Vertical); - return (axis == Axis::Horizontal ? m_law->xMax() : m_law->yMax()); -} - -float LawCurveView::gridUnit(Axis axis) const { - assert(axis == Axis::Horizontal); - return m_law->xGridUnit(); -} - char * LawCurveView::label(Axis axis, int index) const { assert(axis == Axis::Horizontal); return (char *)m_labels[index]; diff --git a/apps/probability/law_curve_view.h b/apps/probability/law_curve_view.h index 23ba954f8..9def316dd 100644 --- a/apps/probability/law_curve_view.h +++ b/apps/probability/law_curve_view.h @@ -18,9 +18,6 @@ public: void reload(); void drawRect(KDContext * ctx, KDRect rect) const override; protected: - float min(Axis axis) const override; - float max(Axis axis) const override; - float gridUnit(Axis axis) const override; char * label(Axis axis, int index) const override; private: char m_labels[k_maxNumberOfXLabels][Constant::FloatBufferSizeInScientificMode]; From f00492fb59d4555af23bccf36d9ac5676f3c5cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Tue, 20 Dec 2016 16:07:06 +0100 Subject: [PATCH 14/14] [apps] Add a margin around the window when drawing curves Change-Id: Iaf806c1f9e710dabc89f78b60d1c2985c9659012 --- apps/curve_view.cpp | 8 ++++++-- apps/curve_view.h | 3 +++ apps/probability/law/binomial_law.cpp | 9 ++------- apps/probability/law/exponential_law.cpp | 4 ++-- apps/probability/law/law.h | 2 -- apps/probability/law/normal_law.cpp | 9 ++------- apps/probability/law/poisson_law.cpp | 7 +++---- apps/probability/law/uniform_law.cpp | 4 ++-- 8 files changed, 20 insertions(+), 26 deletions(-) diff --git a/apps/curve_view.cpp b/apps/curve_view.cpp index 0ed9c571f..42dd57378 100644 --- a/apps/curve_view.cpp +++ b/apps/curve_view.cpp @@ -23,12 +23,16 @@ void CurveView::reload() { float CurveView::min(Axis axis) const { assert(axis == Axis::Horizontal || axis == Axis::Vertical); - return (axis == Axis::Horizontal ? m_curveViewWindow->xMin() : m_curveViewWindow->yMin()); + float range = axis == Axis::Horizontal ? m_curveViewWindow->xMax() - m_curveViewWindow->xMin() : m_curveViewWindow->yMax() - m_curveViewWindow->yMin(); + float absoluteMin = (axis == Axis::Horizontal ? m_curveViewWindow->xMin(): m_curveViewWindow->yMin()); + return absoluteMin - k_marginFactor*range; } float CurveView::max(Axis axis) const { assert(axis == Axis::Horizontal || axis == Axis::Vertical); - return (axis == Axis::Horizontal ? m_curveViewWindow->xMax() : m_curveViewWindow->yMax()); + float range = axis == Axis::Horizontal ? m_curveViewWindow->xMax() - m_curveViewWindow->xMin() : m_curveViewWindow->yMax() - m_curveViewWindow->yMin(); + float absoluteMax = (axis == Axis::Horizontal ? m_curveViewWindow->xMax() : m_curveViewWindow->yMax()); + return absoluteMax + k_marginFactor*range; } float CurveView::gridUnit(Axis axis) const { diff --git a/apps/curve_view.h b/apps/curve_view.h index 571c5dfc0..ee37fe522 100644 --- a/apps/curve_view.h +++ b/apps/curve_view.h @@ -19,6 +19,8 @@ protected: constexpr static int k_maxNumberOfXLabels = 18; constexpr static int k_maxNumberOfYLabels = 13; void setCurveViewWindow(CurveViewWindow * curveViewWindow); + /* The window bounds are deduced from the model bounds but also take into + account a margin (computed with k_marginFactor) */ float min(Axis axis) const; float max(Axis axis) const; float gridUnit(Axis axis) const; @@ -34,6 +36,7 @@ protected: void computeLabels(Axis axis); void drawLabels(Axis axis, bool shiftOrigin, KDContext * ctx, KDRect rect) const; private: + constexpr static float k_marginFactor = 0.2f; int numberOfLabels(Axis axis) const; virtual float evaluateCurveAtAbscissa(void * curve, float t) const = 0; /* Recursively join two dots (dichotomy). The method stops when the diff --git a/apps/probability/law/binomial_law.cpp b/apps/probability/law/binomial_law.cpp index 4bfc8f0be..e5c494a6e 100644 --- a/apps/probability/law/binomial_law.cpp +++ b/apps/probability/law/binomial_law.cpp @@ -48,17 +48,12 @@ float BinomialLaw::xMax() { } float BinomialLaw::yMin() { - int maxAbscissa = m_parameter2 < 1.0f ? (m_parameter1+1)*m_parameter2 : m_parameter1; - float result = k_minMarginFactor*evaluateAtAbscissa(maxAbscissa); - if (result >= 0.0f || isnan(result)) { - result = k_minMarginFactor; - } - return result; + return 0.0f; } float BinomialLaw::yMax() { int maxAbscissa = m_parameter2 < 1.0f ? (m_parameter1+1)*m_parameter2 : m_parameter1; - float result = k_maxMarginFactor*evaluateAtAbscissa(maxAbscissa); + float result = evaluateAtAbscissa(maxAbscissa); if (result <= 0.0f || result == yMin() || isnan(result)) { result = yMin() + 1.0f; } diff --git a/apps/probability/law/exponential_law.cpp b/apps/probability/law/exponential_law.cpp index dd197ff23..c34eba7bf 100644 --- a/apps/probability/law/exponential_law.cpp +++ b/apps/probability/law/exponential_law.cpp @@ -42,11 +42,11 @@ float ExponentialLaw::xMax() { } float ExponentialLaw::yMin() { - return k_minMarginFactor*m_parameter1; + return 0.0f; } float ExponentialLaw::yMax() { - return k_maxMarginFactor*m_parameter1; + return m_parameter1; } float ExponentialLaw::evaluateAtAbscissa(float x) const { diff --git a/apps/probability/law/law.h b/apps/probability/law/law.h index 9d718967b..662ee83d5 100644 --- a/apps/probability/law/law.h +++ b/apps/probability/law/law.h @@ -33,8 +33,6 @@ public: virtual float cumulativeDistributiveInverseForProbability(float * probability); virtual float rightIntegralInverseForProbability(float * probability); protected: - constexpr static float k_minMarginFactor = -0.2f; - constexpr static float k_maxMarginFactor = 1.2f; constexpr static int k_maxNumberOfOperations = 1000000; }; diff --git a/apps/probability/law/normal_law.cpp b/apps/probability/law/normal_law.cpp index 20eba841e..6103ba48d 100644 --- a/apps/probability/law/normal_law.cpp +++ b/apps/probability/law/normal_law.cpp @@ -55,17 +55,12 @@ float NormalLaw::xMax() { } float NormalLaw::yMin() { - float maxAbscissa = m_parameter1; - float result = k_minMarginFactor*evaluateAtAbscissa(maxAbscissa); - if (result >= 0.0f) { - result = k_minMarginFactor; - } - return result; + return 0.0f; } float NormalLaw::yMax() { float maxAbscissa = m_parameter1; - float result = k_maxMarginFactor*evaluateAtAbscissa(maxAbscissa); + float result = evaluateAtAbscissa(maxAbscissa); if (result <= 0.0f || result == yMin()) { result = yMin() + 1.0f; } diff --git a/apps/probability/law/poisson_law.cpp b/apps/probability/law/poisson_law.cpp index 19be3dc9d..17483d2b9 100644 --- a/apps/probability/law/poisson_law.cpp +++ b/apps/probability/law/poisson_law.cpp @@ -32,7 +32,7 @@ const char * PoissonLaw::parameterDefinitionAtIndex(int index) { } float PoissonLaw::xMin() { - return -1.0f; + return 0.0f; } float PoissonLaw::xMax() { @@ -41,13 +41,12 @@ float PoissonLaw::xMax() { } float PoissonLaw::yMin() { - int maxAbscissa = (int)m_parameter1; - return k_minMarginFactor*evaluateAtAbscissa(maxAbscissa); + return 0.0f; } float PoissonLaw::yMax() { int maxAbscissa = (int)m_parameter1; - return k_maxMarginFactor*evaluateAtAbscissa(maxAbscissa); + return evaluateAtAbscissa(maxAbscissa); } float PoissonLaw::evaluateAtAbscissa(float x) const { diff --git a/apps/probability/law/uniform_law.cpp b/apps/probability/law/uniform_law.cpp index d6069eff2..a80df4c81 100644 --- a/apps/probability/law/uniform_law.cpp +++ b/apps/probability/law/uniform_law.cpp @@ -48,11 +48,11 @@ float UniformLaw::xMax() { } float UniformLaw::yMin() { - return k_minMarginFactor*(1.0f/(m_parameter2-m_parameter1)); + return 0.0f; } float UniformLaw::yMax() { - return k_maxMarginFactor*(1.0f/(m_parameter2-m_parameter1)); + return (1.0f/(m_parameter2-m_parameter1)); } float UniformLaw::evaluateAtAbscissa(float t) const {