Files
Upsilon/app/plot.cpp
Romain Goyet ac4660bf3b ION: SCREEN_WIDTH becomes ION_SCREEN_WIDTH
Change-Id: Ifc7d06b773f8660cff30e727f510eea448b23852
2016-06-10 17:32:31 +02:00

86 lines
2.4 KiB
C++

extern "C" {
#include <assert.h>
#include <kandinsky.h>
#include <stdlib.h>
#include <ion.h>
}
#include <poincare.h>
#include "utils.h"
#include "plot.h"
constexpr KDCoordinate kScreenWidth = ION_SCREEN_WIDTH;
const KDCoordinate kScreenHeight = ION_SCREEN_HEIGHT;
static float plotValues[kScreenWidth];
static float yMin, yMax;
// 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);
}
}
static void fill_values(Expression * e, float xMin, float xMax) {
assert(e);
Context plotContext;
// Initialize min and max.
Float xExp = Float(xMin);
plotContext.setExpressionForSymbolName(&xExp, "x");
plotValues[0] = e->approximate(plotContext);
yMin = plotValues[0];
yMax = plotValues[0];
for (KDCoordinate i = 1; i < kScreenWidth; i++) {
float x = xMin + (xMax-xMin)/kScreenWidth*i;
Float xExp = Float(x);
plotContext.setExpressionForSymbolName(&xExp, "x");
plotValues[i] = e->approximate(plotContext);
if (plotValues[i] > yMax) {
yMax = plotValues[i];
}
if (plotValues[i] < yMin) {
yMin = plotValues[i];
}
}
}
// TODO: Add a cursor.
// TODO: print the expression.
void plot(Expression * e, float xMin, float xMax) {
assert(e);
fill_values(e, xMin, xMax);
// Plot the original axes.
plot_axes(xMin, xMax, yMin, yMax);
// We need to initialize the first point.
KDCoordinate j = ((plotValues[0]-yMin) / (yMax-yMin) * (kScreenHeight - 1));
KDPoint previousPoint = KDPointMake(0, kScreenHeight - 1 - j);
for (KDCoordinate i = 1; i < kScreenWidth; i++) {
// TODO: check for yMin == yMax
KDCoordinate j = ((plotValues[i]-yMin) / (yMax-yMin) * (kScreenHeight - 1));
KDPoint currentPoint = KDPointMake(i, kScreenHeight - 1 - j);
KDDrawLine(previousPoint, currentPoint, 0xFF);
previousPoint = currentPoint;
}
ion_get_event(); // We wait for a text input.
}