From f334977c6ac4ec14c63c970d11fe48607d02e565 Mon Sep 17 00:00:00 2001 From: Felix Raimundo Date: Thu, 7 Apr 2016 12:38:08 +0200 Subject: [PATCH] Nicer plot Change-Id: I6f080a4c26ad8ce574661228a4d4b53632d2f870 --- app/Makefile | 5 +- app/app.cpp | 49 +++++++---------- app/plot.cpp | 73 ++++++++++++++++++++++++++ app/plot.h | 7 +++ app/utils.cpp | 6 +++ ion/include/ion/events.h | 1 + ion/src/shared/events.c | 2 +- ion/src/simulator/keyboard/fltkkbd.cpp | 2 +- 8 files changed, 111 insertions(+), 34 deletions(-) create mode 100644 app/plot.cpp create mode 100644 app/plot.h diff --git a/app/Makefile b/app/Makefile index d662c1a4d..af3cc5a0c 100644 --- a/app/Makefile +++ b/app/Makefile @@ -1,6 +1,7 @@ app_objs += $(addprefix app/,\ - app.o\ - utils.o) + app.o\ + plot.o\ + utils.o) products += $(app_objs) app.elf app.hex app.bin app.elf: $(app_objs) diff --git a/app/app.cpp b/app/app.cpp index 6a71e3007..0af824ecb 100644 --- a/app/app.cpp +++ b/app/app.cpp @@ -8,32 +8,14 @@ extern "C" { #include #include "../poincare/src/layout/string_layout.h" +#include "plot.h" #include "utils.h" -const char* kParsingErrorMessage = "PARSING ERROR"; - -void plot(Expression * e, float xMin, float xMax, float yMin, float yMax) { - Context plotContext; - KDCoordinate screenWidth = SCREEN_WIDTH; - KDCoordinate screenHeight = SCREEN_HEIGHT; - KDPoint previousPoint; - for (KDCoordinate i=0;iapproximate(plotContext); - KDCoordinate j = ((y-yMin)/(yMax-yMin)*screenHeight); - KDPoint currentPoint = KDPointMake(i,screenHeight-j); - if (i>0) { - KDDrawLine(previousPoint, currentPoint, 0xFF); - } - previousPoint = currentPoint; - } -} +static const char* kParsingErrorMessage = "PARSING ERROR"; ////////////////////////////////////////////////////// -#define INPUT_MEMORY 15 +static constexpr uint8_t kInputMemory = 15; typedef struct user_expression_t { char* text_input; @@ -47,24 +29,24 @@ class UserExpressions { public: UserExpressions() { m_numberOfExpressions = 0; - m_position = INPUT_MEMORY; - for (int i=0; i +#include +#include +#include +} + +#include + +#include "utils.h" +#include "plot.h" + +constexpr KDCoordinate kScreenWidth = SCREEN_WIDTH; +const KDCoordinate kScreenHeight = SCREEN_HEIGHT; + +// For now we only plot the axes at the origin. +// TODO: print axes not at the origin with some values too. +// TODO: label the axes. +// TODO: put the values on the axes. +static void plot_axes(float xMin, float xMax, float yMin, float yMax) { + if (xMin < 0 && xMax > 0) { + float total = xMax - xMin; + float ratio = xMax / total; + KDCoordinate width = ratio * kScreenWidth; + KDDrawLine(KDPointMake(width, 0), KDPointMake(width, kScreenHeight-1), 0xff); + } + if (yMin < 0 && yMax > 0) { + float total = yMax - yMin; + float ratio = yMax / total; + KDCoordinate height = ratio * kScreenHeight; + KDDrawLine(KDPointMake(0, height), KDPointMake(kScreenWidth-1, height), 0xff); + } +} + +// TODO: Add a cursor. +// TODO: print the expression. +void plot(Expression * e, float xMin, float xMax, float yMin, float yMax) { + assert(e); + + Context plotContext; + + // Plot the original axes. + plot_axes(xMin, xMax, yMin, yMax); + + // We need to initialize the first point. + Float xExp = Float(xMin); + plotContext.setExpressionForSymbolName(&xExp, "x"); + float y = e->approximate(plotContext); + KDCoordinate j = ((y-yMin) / (yMax-yMin) * kScreenHeight); + if (j < 0) { + j = 0; + } else if (j >= kScreenHeight) { + j = kScreenHeight - 1; + } + KDPoint previousPoint = KDPointMake(0, kScreenHeight-j); + + for (KDCoordinate i = 1; i < kScreenWidth; i++) { + float x = xMin + (xMax-xMin)/kScreenWidth*i; + Float xExp = Float(x); + plotContext.setExpressionForSymbolName(&xExp, "x"); + float y = e->approximate(plotContext); + KDCoordinate j = ((y-yMin) / (yMax-yMin) * kScreenHeight); + KDPoint currentPoint = KDPointMake(i, kScreenHeight-j); + if (currentPoint.y < 0) { + currentPoint.y = 0; + } else if (currentPoint.y >= kScreenHeight) { + currentPoint.y = kScreenHeight - 1; + } + KDDrawLine(previousPoint, currentPoint, 0xFF); + previousPoint = currentPoint; + } + ion_get_event(); // We wait for a text input. +} diff --git a/app/plot.h b/app/plot.h new file mode 100644 index 000000000..f7a4570bb --- /dev/null +++ b/app/plot.h @@ -0,0 +1,7 @@ +#ifndef APP_PLOT_H +#define APP_PLOT_H + +// Note that currently the only variable is 'x' +void plot(Expression * e, float xMin, float xMax, float yMin, float yMax); + +#endif diff --git a/app/utils.cpp b/app/utils.cpp index 1604e4b6c..d3b7be9bc 100644 --- a/app/utils.cpp +++ b/app/utils.cpp @@ -174,6 +174,12 @@ text_event_t get_text(char* txt) { } else if (event == DOWN_ARROW) { text_event.event = DOWN_ARROW; break; + } else if (event == PLOT) { + text_event.event = PLOT; + input[max] = '\0'; + text_event.text = (char*) malloc(sizeof(char) * (index + 1)); + memcpy(text_event.text, input, (size_t) (index + 1)); + break; } else { assert(false); // unreachable. } diff --git a/ion/include/ion/events.h b/ion/include/ion/events.h index babf18ad8..18ac3c759 100644 --- a/ion/include/ion/events.h +++ b/ion/include/ion/events.h @@ -79,6 +79,7 @@ typedef enum { DOWN_ARROW, TRIG_MENU, DELETE, + PLOT, ERROR = 0xffffffff, } ion_event_t; diff --git a/ion/src/shared/events.c b/ion/src/shared/events.c index e49b0a031..d57e3a457 100644 --- a/ion/src/shared/events.c +++ b/ion/src/shared/events.c @@ -50,7 +50,7 @@ static ion_key_event_t ion_get_key_event() { static const ion_event_t kEventForKeyDown[ION_NUMBER_OF_KEYS] = { UPPER_CASE_A, UPPER_CASE_B, UPPER_CASE_C, UPPER_CASE_D, UPPER_CASE_E, UPPER_CASE_F, UPPER_CASE_G, DELETE, UP_ARROW, DOWN_ARROW, - UPPER_CASE_K, UPPER_CASE_L, TRIG_MENU, LEFT_ARROW, RIGHT_ARROW, + UPPER_CASE_K, PLOT, TRIG_MENU, LEFT_ARROW, RIGHT_ARROW, SEVEN, EIGHT, NINE, LEFT_PARENTHESIS, RIGHT_PARENTHESIS, FOUR, FIVE, SIX, PRODUCT, DIVISION, ONE, TWO, THREE, PLUS, MINUS, diff --git a/ion/src/simulator/keyboard/fltkkbd.cpp b/ion/src/simulator/keyboard/fltkkbd.cpp index 0df48c990..e08b341ea 100644 --- a/ion/src/simulator/keyboard/fltkkbd.cpp +++ b/ion/src/simulator/keyboard/fltkkbd.cpp @@ -7,7 +7,7 @@ static const char* kCharForKey[KEYBOARD_ROWS * KEYBOARD_COLUMNS] = { "A", "B", "C", "D", "E", "F", "G", "DEL", "UP", "DOWN", - "K", "L", "TRIG", "LEFT", "RIGHT", + "K", "PLOT", "TRIG", "LEFT", "RIGHT", "7", "8", "9", "(", ")", "4", "5", "6", "*", "/", "1", "2", "3", "+", "-",