mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-20 01:08:15 +01:00
[Git] Fix conflicts
This commit is contained in:
@@ -134,6 +134,13 @@ port_src += $(addprefix python/port/,\
|
||||
mod/ion/modion_table.cpp \
|
||||
mod/kandinsky/modkandinsky.cpp \
|
||||
mod/kandinsky/modkandinsky_table.c \
|
||||
mod/matplotlib/modmatplotlib.cpp \
|
||||
mod/matplotlib/modmatplotlib_table.c \
|
||||
mod/matplotlib/pyplot/modpyplot.cpp \
|
||||
mod/matplotlib/pyplot/modpyplot_table.c \
|
||||
mod/matplotlib/pyplot/plot_controller.cpp \
|
||||
mod/matplotlib/pyplot/plot_store.cpp \
|
||||
mod/matplotlib/pyplot/plot_view.cpp \
|
||||
mod/time/modtime.c \
|
||||
mod/time/modtime_table.c \
|
||||
mod/turtle/modturtle.cpp \
|
||||
|
||||
@@ -130,6 +130,21 @@ Q(EE)
|
||||
Q(Ans)
|
||||
Q(EXE)
|
||||
|
||||
// Matplotlib QSTRs
|
||||
Q(arrow)
|
||||
Q(axis)
|
||||
Q(bar)
|
||||
Q(grid)
|
||||
Q(grid)
|
||||
Q(hist)
|
||||
Q(plot)
|
||||
Q(matplotlib)
|
||||
Q(matplotlib.pyplot)
|
||||
Q(pyplot)
|
||||
Q(scatter)
|
||||
Q(show)
|
||||
Q(text)
|
||||
|
||||
// Turtle QSTRs
|
||||
Q(turtle)
|
||||
Q(forward)
|
||||
|
||||
13
python/port/mod/matplotlib/modmatplotlib.cpp
Normal file
13
python/port/mod/matplotlib/modmatplotlib.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
extern "C" {
|
||||
#include "modmatplotlib.h"
|
||||
#include "pyplot/modpyplot.h"
|
||||
}
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// Internal functions
|
||||
|
||||
mp_obj_t modmatplotlib___init__() {
|
||||
modpyplot___init__();
|
||||
return mp_const_none;
|
||||
}
|
||||
3
python/port/mod/matplotlib/modmatplotlib.h
Normal file
3
python/port/mod/matplotlib/modmatplotlib.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#include <py/obj.h>
|
||||
|
||||
mp_obj_t modmatplotlib___init__();
|
||||
18
python/port/mod/matplotlib/modmatplotlib_table.c
Normal file
18
python/port/mod/matplotlib/modmatplotlib_table.c
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "modmatplotlib.h"
|
||||
|
||||
extern const mp_obj_module_t modpyplot_module;
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(modmatplotlib___init___obj, modmatplotlib___init__);
|
||||
|
||||
STATIC const mp_rom_map_elem_t modmatplotlib_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_matplotlib) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&modmatplotlib___init___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pyplot), MP_ROM_PTR(&modpyplot_module) }
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(modmatplotlib_module_globals, modmatplotlib_module_globals_table);
|
||||
|
||||
const mp_obj_module_t modmatplotlib_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&modmatplotlib_module_globals,
|
||||
};
|
||||
33
python/port/mod/matplotlib/modpyplot_table.c
Normal file
33
python/port/mod/matplotlib/modpyplot_table.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "modpyplot.h"
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(modpyplot___init___obj, modpyplot___init__);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_arrow_obj, 4, 4, modpyplot_arrow);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_axis_obj, 0, 1, modpyplot_axis);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_bar_obj, 2, 4, modpyplot_bar);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_grid_obj, 0, 1, modpyplot_grid);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_hist_obj, 1, 2, modpyplot_hist);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_plot_obj, 1, 2, modpyplot_plot);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(modpyplot_scatter_obj, modpyplot_scatter);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(modpyplot_show_obj, modpyplot_show);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(modpyplot_text_obj, modpyplot_text);
|
||||
|
||||
STATIC const mp_rom_map_elem_t modpyplot_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_matplotlib_dot_pyplot) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&modpyplot___init___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_arrow), MP_ROM_PTR(&modpyplot_arrow_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_axis), MP_ROM_PTR(&modpyplot_axis_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&modpyplot_bar_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_grid), MP_ROM_PTR(&modpyplot_grid_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_hist), MP_ROM_PTR(&modpyplot_hist_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_plot), MP_ROM_PTR(&modpyplot_plot_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scatter), MP_ROM_PTR(&modpyplot_scatter_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&modpyplot_show_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&modpyplot_text_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(modpyplot_module_globals, modpyplot_module_globals_table);
|
||||
|
||||
const mp_obj_module_t modpyplot_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&modpyplot_module_globals,
|
||||
};
|
||||
362
python/port/mod/matplotlib/pyplot/modpyplot.cpp
Normal file
362
python/port/mod/matplotlib/pyplot/modpyplot.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
extern "C" {
|
||||
#include "modpyplot.h"
|
||||
}
|
||||
#include <assert.h>
|
||||
#include <escher/palette.h>
|
||||
#include "port.h"
|
||||
#include "plot_controller.h"
|
||||
|
||||
Matplotlib::PlotStore * sPlotStore = nullptr;
|
||||
Matplotlib::PlotController * sPlotController = nullptr;
|
||||
static int paletteIndex = 0;
|
||||
|
||||
// Private helper
|
||||
|
||||
// Method to populate items with a scalar or an array argument
|
||||
|
||||
static size_t extractArgument(mp_obj_t arg, mp_obj_t ** items) {
|
||||
size_t itemLength;
|
||||
if (mp_obj_is_type(arg, &mp_type_tuple) || mp_obj_is_type(arg, &mp_type_list)) {
|
||||
mp_obj_get_array(arg, &itemLength, items);
|
||||
} else {
|
||||
itemLength = 1;
|
||||
*items = m_new(mp_obj_t, 1);
|
||||
(*items)[0] = arg;
|
||||
}
|
||||
return itemLength;
|
||||
}
|
||||
|
||||
// Extract two scalar or array arguments and check for their strickly equal dimension
|
||||
|
||||
static size_t extractArgumentsAndCheckEqualSize(mp_obj_t x, mp_obj_t y, mp_obj_t ** xItems, mp_obj_t ** yItems) {
|
||||
size_t xLength = extractArgument(x, xItems);
|
||||
size_t yLength = extractArgument(y, yItems);
|
||||
if (xLength != yLength) {
|
||||
mp_raise_ValueError("x and y must be the same size");
|
||||
}
|
||||
return xLength;
|
||||
}
|
||||
|
||||
/* Extract one scalar or array arguments and check that it is either:
|
||||
* - of size 1
|
||||
* - of the required size
|
||||
*/
|
||||
|
||||
size_t extractArgumentAndValidateSize(mp_obj_t arg, size_t requiredlength, mp_obj_t ** items) {
|
||||
size_t itemLength = extractArgument(arg, items);
|
||||
if (itemLength > 1 && requiredlength > 1 && itemLength != requiredlength) {
|
||||
mp_raise_ValueError("shape mismatch");
|
||||
}
|
||||
return itemLength;
|
||||
}
|
||||
|
||||
// Internal functions
|
||||
|
||||
mp_obj_t modpyplot___init__() {
|
||||
static Matplotlib::PlotStore plotStore;
|
||||
static Matplotlib::PlotController plotController(&plotStore);
|
||||
sPlotStore = &plotStore;
|
||||
sPlotController = &plotController;
|
||||
sPlotStore->flush();
|
||||
paletteIndex = 0;
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
void modpyplot_gc_collect() {
|
||||
if (sPlotStore == nullptr) {
|
||||
return;
|
||||
}
|
||||
MicroPython::collectRootsAtAddress(
|
||||
reinterpret_cast<char *>(sPlotStore),
|
||||
sizeof(Matplotlib::PlotStore)
|
||||
);
|
||||
}
|
||||
|
||||
void modpyplot_flush_used_heap() {
|
||||
if (sPlotStore) {
|
||||
// Clean the store object
|
||||
sPlotStore->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/* arrow(x,y,dx,dy)
|
||||
* x, y, dx, dy scalars
|
||||
* */
|
||||
|
||||
mp_obj_t modpyplot_arrow(size_t n_args, const mp_obj_t *args) {
|
||||
assert(n_args == 4);
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
KDColor color = Palette::nextDataColor(&paletteIndex);
|
||||
sPlotStore->addSegment(args[0], args[1], mp_obj_new_float(mp_obj_get_float(args[0])+mp_obj_get_float(args[2])), mp_obj_new_float(mp_obj_get_float(args[1])+mp_obj_get_float(args[3])), color, true); // TODO: use float_binary_op
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/* axis(arg)
|
||||
* - arg = "on", "off", "auto"
|
||||
* - arg = True, False
|
||||
* - arg = [xmin, xmax, ymin, ymax], (xmin, xmax, ymin, ymax)
|
||||
* Returns : (xmin, xmax, ymin, ymax) : float */
|
||||
|
||||
mp_obj_t modpyplot_axis(size_t n_args, const mp_obj_t *args) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
if (n_args == 1) {
|
||||
mp_obj_t arg = args[0];
|
||||
if (mp_obj_is_str(arg)) {
|
||||
if (mp_obj_str_equal(arg, mp_obj_new_str("on", 2))) {
|
||||
sPlotStore->setAxesRequested(true);
|
||||
} else if (mp_obj_str_equal(arg, mp_obj_new_str("off", 3))) {
|
||||
sPlotStore->setAxesRequested(false);
|
||||
} else if (mp_obj_str_equal(arg, mp_obj_new_str("auto", 4))) {
|
||||
sPlotStore->setAxesRequested(true);
|
||||
sPlotStore->setAxesAuto(true);
|
||||
} else {
|
||||
mp_raise_ValueError("Unrecognized string given to axis; try 'on', 'off' or 'auto'");
|
||||
}
|
||||
#warning Use mp_obj_is_bool when upgrading uPy
|
||||
} else if (mp_obj_is_type(arg, &mp_type_bool)) {
|
||||
sPlotStore->setAxesRequested(mp_obj_is_true(arg));
|
||||
} else if (mp_obj_is_type(arg, &mp_type_tuple) || mp_obj_is_type(arg, &mp_type_list)) {
|
||||
mp_obj_t * items;
|
||||
mp_obj_get_array_fixed_n(arg, 4, &items);
|
||||
sPlotStore->setXMin(mp_obj_get_float(items[0]));
|
||||
sPlotStore->setXMax(mp_obj_get_float(items[1]));
|
||||
sPlotStore->setYMin(mp_obj_get_float(items[2]));
|
||||
sPlotStore->setYMax(mp_obj_get_float(items[3]));
|
||||
sPlotStore->setAxesAuto(false);
|
||||
} else {
|
||||
mp_raise_TypeError("the first argument to axis() must be an iterable of the form [xmin, xmax, ymin, ymax]");
|
||||
}
|
||||
}
|
||||
|
||||
// Build the return value
|
||||
mp_obj_t coords[4];
|
||||
coords[0] = mp_obj_new_float(sPlotStore->xMin());
|
||||
coords[1] = mp_obj_new_float(sPlotStore->xMax());
|
||||
coords[2] = mp_obj_new_float(sPlotStore->yMin());
|
||||
coords[3] = mp_obj_new_float(sPlotStore->yMax());
|
||||
return mp_obj_new_tuple(4, coords);
|
||||
}
|
||||
|
||||
/* bar(x, height, width, bottom)
|
||||
* 'x', 'height', 'width' and 'bottom' can either be a scalar or an array/tuple of
|
||||
* scalar.
|
||||
* 'width' default value is 0.8
|
||||
* 'bottom' default value is None
|
||||
* */
|
||||
|
||||
// TODO: accept keyword args?
|
||||
|
||||
mp_obj_t modpyplot_bar(size_t n_args, const mp_obj_t *args) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
mp_obj_t * xItems;
|
||||
mp_obj_t * hItems;
|
||||
mp_obj_t * wItems;
|
||||
mp_obj_t * bItems;
|
||||
|
||||
// x arg
|
||||
size_t xLength = extractArgument(args[0], &xItems);
|
||||
|
||||
// height arg
|
||||
size_t hLength = extractArgumentAndValidateSize(args[1], xLength, &hItems);
|
||||
|
||||
// width arg
|
||||
size_t wLength = 1;
|
||||
if (n_args >= 3) {
|
||||
wLength = extractArgumentAndValidateSize(args[2], xLength, &wItems);
|
||||
} else {
|
||||
wItems = m_new(mp_obj_t, 1);
|
||||
wItems[0] = mp_obj_new_float(0.8f);
|
||||
}
|
||||
|
||||
// bottom arg
|
||||
size_t bLength = 1;
|
||||
if (n_args >= 4) {
|
||||
bLength = extractArgumentAndValidateSize(args[3], xLength, &bItems);
|
||||
} else {
|
||||
bItems = m_new(mp_obj_t, 1);
|
||||
bItems[0] = mp_obj_new_float(0.0f);
|
||||
}
|
||||
|
||||
KDColor color = Palette::nextDataColor(&paletteIndex);
|
||||
for (size_t i=0; i<xLength; i++) {
|
||||
mp_float_t iH = mp_obj_get_float(hItems[hLength > 1 ? i : 0]);
|
||||
mp_float_t iW = mp_obj_get_float(wItems[wLength > 1 ? i : 0]);
|
||||
mp_float_t iB = mp_obj_get_float(bItems[bLength > 1 ? i : 0]);
|
||||
mp_float_t iX = mp_obj_get_float(xItems[i])-iW/2.0;
|
||||
mp_float_t iYStart = iH < 0.0 ? iB : iB + iH;
|
||||
mp_float_t iYEnd = iH < 0.0 ? iB + iH : iB;
|
||||
sPlotStore->addRect(mp_obj_new_float(iX), mp_obj_new_float(iX+iW), mp_obj_new_float(iYStart), mp_obj_new_float(iYEnd), color); // TODO: use float_binary_op?
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t modpyplot_grid(size_t n_args, const mp_obj_t *args) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
if (n_args == 0) {
|
||||
// Toggle the grid visibility
|
||||
sPlotStore->setGridRequested(!sPlotStore->gridRequested());
|
||||
} else {
|
||||
sPlotStore->setGridRequested(mp_obj_is_true(args[0]));
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/* hist(x, bins)
|
||||
* 'x' array
|
||||
* 'bins': (default value 10)
|
||||
* - int (number of bins)
|
||||
* - sequence of bins
|
||||
* */
|
||||
|
||||
mp_obj_t modpyplot_hist(size_t n_args, const mp_obj_t *args) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
// Sort data to easily get the minimal and maximal value and count bin sizes
|
||||
mp_obj_t * xItems;
|
||||
size_t xLength = extractArgument(args[0], &xItems);
|
||||
if (xLength == 0) {
|
||||
return mp_const_none;
|
||||
}
|
||||
mp_obj_t xList = mp_obj_new_list(xLength, xItems);
|
||||
mp_obj_list_sort(1, &xList, (mp_map_t*)&mp_const_empty_map);
|
||||
mp_obj_list_get(xList, &xLength, &xItems);
|
||||
assert(xLength > 0);
|
||||
mp_float_t min = mp_obj_get_float(xItems[0]);
|
||||
mp_float_t max = mp_obj_get_float(xItems[xLength - 1]);
|
||||
|
||||
mp_obj_t * edgeItems;
|
||||
size_t nBins;
|
||||
// bin arg
|
||||
if (n_args >= 2 && (mp_obj_is_type(args[1], &mp_type_tuple) || mp_obj_is_type(args[1], &mp_type_list))) {
|
||||
size_t nEdges;
|
||||
mp_obj_get_array(args[1], &nEdges, &edgeItems);
|
||||
nBins = nEdges -1;
|
||||
} else {
|
||||
nBins = 10;
|
||||
if (n_args >= 2) {
|
||||
nBins = mp_obj_get_int(args[1]);
|
||||
}
|
||||
|
||||
mp_float_t binWidth = (max-min)/nBins;
|
||||
// Create a array of bins
|
||||
edgeItems = m_new(mp_obj_t, nBins + 1);
|
||||
// Handle empty range case
|
||||
if (max - min <= FLT_EPSILON) {
|
||||
binWidth = 1.0;
|
||||
nBins = 1;
|
||||
}
|
||||
|
||||
// Fill the bin edges list
|
||||
for (int i = 0; i < nBins+1; i++) {
|
||||
edgeItems[i] = mp_obj_new_float(min+i*binWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize bins list
|
||||
mp_obj_t * binItems = m_new(mp_obj_t, nBins);
|
||||
for (size_t i=0; i<nBins; i++) {
|
||||
binItems[i] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
}
|
||||
|
||||
// Fill bins list by linearly scanning the x and incrementing the bin count
|
||||
// Linearity is enabled thanks to sorting
|
||||
size_t binIndex = 0;
|
||||
size_t xIndex = 0;
|
||||
while (binIndex < nBins) {
|
||||
mp_float_t lowerBound = mp_obj_get_float(edgeItems[binIndex]);
|
||||
// Skip xItem if below the lower bound
|
||||
while (xIndex < xLength && mp_obj_get_float(xItems[xIndex]) < lowerBound) {
|
||||
xIndex++;
|
||||
}
|
||||
mp_float_t upperBound = mp_obj_get_float(edgeItems[binIndex+1]);
|
||||
while (xIndex < xLength && (mp_obj_get_float(xItems[xIndex]) < upperBound || (binIndex == nBins - 1 && mp_obj_get_float(xItems[xIndex]) == upperBound))) {
|
||||
assert(mp_obj_get_float(xItems[xIndex]) >= lowerBound);
|
||||
// Increment the bin count
|
||||
binItems[binIndex] = MP_OBJ_NEW_SMALL_INT(MP_OBJ_SMALL_INT_VALUE(binItems[binIndex]) + 1);
|
||||
xIndex++;
|
||||
}
|
||||
binIndex++;
|
||||
}
|
||||
|
||||
KDColor color = Palette::nextDataColor(&paletteIndex);
|
||||
for (size_t i=0; i<nBins; i++) {
|
||||
sPlotStore->addRect(edgeItems[i], edgeItems[i+1], binItems[i], mp_obj_new_float(0.0), color);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/* scatter(x, y)
|
||||
* - x, y: list
|
||||
* - x, y: scalar
|
||||
* */
|
||||
|
||||
mp_obj_t modpyplot_scatter(mp_obj_t x, mp_obj_t y) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
mp_obj_t * xItems, * yItems;
|
||||
size_t length = extractArgumentsAndCheckEqualSize(x, y, &xItems, &yItems);
|
||||
|
||||
KDColor color = Palette::nextDataColor(&paletteIndex);
|
||||
for (size_t i=0; i<length; i++) {
|
||||
sPlotStore->addDot(xItems[i], yItems[i], color);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/* plot(x, y) plots the curve (x, y)
|
||||
* plot(y) plots the curve x as index array ([0,1,2...],y)
|
||||
* */
|
||||
|
||||
mp_obj_t modpyplot_plot(size_t n_args, const mp_obj_t *args) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
mp_obj_t * xItems, * yItems;
|
||||
size_t length;
|
||||
if (n_args == 1) {
|
||||
length = extractArgument(args[0], &yItems);
|
||||
|
||||
// Create the default xItems: [0, 1, 2,...]
|
||||
xItems = m_new(mp_obj_t, length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
xItems[i] = mp_obj_new_float((float)i);
|
||||
}
|
||||
} else {
|
||||
assert(n_args == 2);
|
||||
length = extractArgumentsAndCheckEqualSize(args[0], args[1], &xItems, &yItems);
|
||||
}
|
||||
|
||||
KDColor color = Palette::nextDataColor(&paletteIndex);
|
||||
for (int i=0; i<(int)length-1; i++) {
|
||||
sPlotStore->addSegment(xItems[i], yItems[i], xItems[i+1], yItems[i+1], color, false);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t modpyplot_text(mp_obj_t x, mp_obj_t y, mp_obj_t s) {
|
||||
assert(sPlotStore != nullptr);
|
||||
|
||||
// Input parameter validation
|
||||
mp_obj_get_float(x);
|
||||
mp_obj_get_float(y);
|
||||
mp_obj_str_get_str(s);
|
||||
|
||||
sPlotStore->addLabel(x, y, s);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t modpyplot_show() {
|
||||
if (sPlotStore->isEmpty()) {
|
||||
return mp_const_none;
|
||||
}
|
||||
MicroPython::ExecutionEnvironment * env = MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
|
||||
env->displayViewController(sPlotController);
|
||||
return mp_const_none;
|
||||
}
|
||||
15
python/port/mod/matplotlib/pyplot/modpyplot.h
Normal file
15
python/port/mod/matplotlib/pyplot/modpyplot.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <py/obj.h>
|
||||
|
||||
mp_obj_t modpyplot___init__();
|
||||
void modpyplot_gc_collect();
|
||||
void modpyplot_flush_used_heap();
|
||||
|
||||
mp_obj_t modpyplot_arrow(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t modpyplot_axis(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t modpyplot_bar(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t modpyplot_grid(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t modpyplot_hist(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t modpyplot_plot(size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t modpyplot_scatter(mp_obj_t x, mp_obj_t y);
|
||||
mp_obj_t modpyplot_text(mp_obj_t x, mp_obj_t y, mp_obj_t s);
|
||||
mp_obj_t modpyplot_show();
|
||||
33
python/port/mod/matplotlib/pyplot/modpyplot_table.c
Normal file
33
python/port/mod/matplotlib/pyplot/modpyplot_table.c
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "modpyplot.h"
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(modpyplot___init___obj, modpyplot___init__);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_arrow_obj, 4, 4, modpyplot_arrow);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_axis_obj, 0, 1, modpyplot_axis);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_bar_obj, 2, 4, modpyplot_bar);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_grid_obj, 0, 1, modpyplot_grid);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_hist_obj, 1, 2, modpyplot_hist);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(modpyplot_plot_obj, 1, 2, modpyplot_plot);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(modpyplot_scatter_obj, modpyplot_scatter);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(modpyplot_show_obj, modpyplot_show);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(modpyplot_text_obj, modpyplot_text);
|
||||
|
||||
STATIC const mp_rom_map_elem_t modpyplot_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyplot) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&modpyplot___init___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_arrow), MP_ROM_PTR(&modpyplot_arrow_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_axis), MP_ROM_PTR(&modpyplot_axis_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&modpyplot_bar_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_grid), MP_ROM_PTR(&modpyplot_grid_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_hist), MP_ROM_PTR(&modpyplot_hist_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_plot), MP_ROM_PTR(&modpyplot_plot_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scatter), MP_ROM_PTR(&modpyplot_scatter_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&modpyplot_show_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&modpyplot_text_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(modpyplot_module_globals, modpyplot_module_globals_table);
|
||||
|
||||
const mp_obj_module_t modpyplot_module = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&modpyplot_module_globals,
|
||||
};
|
||||
14
python/port/mod/matplotlib/pyplot/plot_controller.cpp
Normal file
14
python/port/mod/matplotlib/pyplot/plot_controller.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "plot_controller.h"
|
||||
|
||||
namespace Matplotlib {
|
||||
|
||||
void PlotController::viewWillAppear() {
|
||||
m_store->initRange();
|
||||
curveView()->reload();
|
||||
}
|
||||
|
||||
void PlotController::viewDidDisappear() {
|
||||
m_store->flush();
|
||||
}
|
||||
|
||||
}
|
||||
27
python/port/mod/matplotlib/pyplot/plot_controller.h
Normal file
27
python/port/mod/matplotlib/pyplot/plot_controller.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef PYTHON_MATPLOTLIB_PLOT_CONTROLLER_H
|
||||
#define PYTHON_MATPLOTLIB_PLOT_CONTROLLER_H
|
||||
|
||||
#include <apps/shared/zoom_and_pan_curve_view_controller.h>
|
||||
#include "plot_view.h"
|
||||
#include "plot_store.h"
|
||||
|
||||
namespace Matplotlib {
|
||||
|
||||
class PlotController : public Shared::ZoomAndPanCurveViewController {
|
||||
public:
|
||||
PlotController(PlotStore * store) : Shared::ZoomAndPanCurveViewController(nullptr), m_store(store), m_view(m_store) {}
|
||||
|
||||
void viewWillAppear() override;
|
||||
void viewDidDisappear() override;
|
||||
|
||||
protected:
|
||||
Shared::CurveView * curveView() override { return &m_view; }
|
||||
Shared::InteractiveCurveViewRange * interactiveCurveViewRange() override { return m_store; }
|
||||
private:
|
||||
PlotStore * m_store;
|
||||
PlotView m_view;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
219
python/port/mod/matplotlib/pyplot/plot_store.cpp
Normal file
219
python/port/mod/matplotlib/pyplot/plot_store.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
#include "plot_store.h"
|
||||
|
||||
namespace Matplotlib {
|
||||
|
||||
PlotStore::PlotStore() : Shared::InteractiveCurveViewRange(),
|
||||
m_axesRequested(true),
|
||||
m_axesAuto(true),
|
||||
m_gridRequested(false)
|
||||
{
|
||||
flush();
|
||||
}
|
||||
|
||||
void PlotStore::flush() {
|
||||
m_dots = mp_obj_new_list(0, nullptr);
|
||||
m_segments = mp_obj_new_list(0, nullptr);
|
||||
m_rects = mp_obj_new_list(0, nullptr);
|
||||
m_labels = mp_obj_new_list(0, nullptr);
|
||||
m_axesRequested = true;
|
||||
m_axesAuto = true;
|
||||
m_gridRequested = false;
|
||||
}
|
||||
|
||||
bool PlotStore::isEmpty() {
|
||||
return MP_OBJ_SMALL_INT_VALUE(mp_obj_len(m_dots)) == 0 && MP_OBJ_SMALL_INT_VALUE(mp_obj_len(m_segments)) == 0 && MP_OBJ_SMALL_INT_VALUE(mp_obj_len(m_rects)) == 0 && MP_OBJ_SMALL_INT_VALUE(mp_obj_len(m_labels)) == 0;
|
||||
}
|
||||
|
||||
// Iterators
|
||||
|
||||
template <class T>
|
||||
PlotStore::ListIterator<T> PlotStore::ListIterator<T>::Begin(mp_obj_t list) {
|
||||
ListIterator<T> it;
|
||||
mp_obj_list_get(list, &(it.m_numberOfTuples), &(it.m_tuples));
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PlotStore::ListIterator<T> PlotStore::ListIterator<T>::End(mp_obj_t list) {
|
||||
ListIterator<T> it;
|
||||
mp_obj_list_get(list, &(it.m_numberOfTuples), &(it.m_tuples));
|
||||
if (it.m_numberOfTuples > 0) {
|
||||
it.m_tupleIndex = it.m_numberOfTuples;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PlotStore::ListIterator<T> & PlotStore::ListIterator<T>::operator++() {
|
||||
if (m_tupleIndex < m_numberOfTuples) {
|
||||
m_tupleIndex++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool PlotStore::ListIterator<T>::operator!=(const PlotStore::ListIterator<T> & it) const {
|
||||
return m_tupleIndex != it.m_tupleIndex;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
T PlotStore::ListIterator<T>::operator*() {
|
||||
return T(m_tuples[m_tupleIndex]);
|
||||
};
|
||||
|
||||
void checkFloatType(mp_obj_t * elements, size_t nbOfElements) {
|
||||
for (int i = 0; i < nbOfElements; i++) {
|
||||
// TODO: we don't take advantage of the fact that we extracted the value at the sametime... Maybe change the way things are done, build the c objects in addItem instead of allocating them on the python heap? Or use float array in python?
|
||||
mp_float_t value;
|
||||
if (!mp_obj_get_float_maybe(elements[i], &value)) {
|
||||
mp_raise_TypeError("argument should be a number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dot
|
||||
|
||||
template class PlotStore::ListIterator<PlotStore::Dot>;
|
||||
|
||||
PlotStore::Dot::Dot(mp_obj_t tuple) {
|
||||
mp_obj_t * elements;
|
||||
mp_obj_get_array_fixed_n(tuple, 3, &elements);
|
||||
m_x = mp_obj_get_float(elements[0]);
|
||||
m_y = mp_obj_get_float(elements[1]);
|
||||
m_color = KDColor::RGB16(mp_obj_get_int(elements[2]));
|
||||
}
|
||||
|
||||
void PlotStore::addDot(mp_obj_t x, mp_obj_t y, KDColor c) {
|
||||
mp_obj_t color = mp_obj_new_int(c);
|
||||
mp_obj_t items[3] = {x, y, color};
|
||||
checkFloatType(items, 2);
|
||||
mp_obj_t tuple = mp_obj_new_tuple(3, items);
|
||||
mp_obj_list_append(m_dots, tuple);
|
||||
}
|
||||
|
||||
// Segment
|
||||
|
||||
template class PlotStore::ListIterator<PlotStore::Segment>;
|
||||
|
||||
PlotStore::Segment::Segment(mp_obj_t tuple) {
|
||||
mp_obj_t * elements;
|
||||
mp_obj_get_array_fixed_n(tuple, 6 , &elements);
|
||||
m_xStart = mp_obj_get_float(elements[0]);
|
||||
m_yStart = mp_obj_get_float(elements[1]);
|
||||
m_xEnd = mp_obj_get_float(elements[2]);
|
||||
m_yEnd = mp_obj_get_float(elements[3]);
|
||||
m_color = KDColor::RGB16(mp_obj_get_int(elements[4]));
|
||||
m_arrow = elements[5] == mp_const_true;
|
||||
}
|
||||
|
||||
void PlotStore::addSegment(mp_obj_t xStart, mp_obj_t yStart, mp_obj_t xEnd, mp_obj_t yEnd, KDColor c, bool arrowEdge) {
|
||||
mp_obj_t color = mp_obj_new_int(c);
|
||||
mp_obj_t items[6] = {xStart, yStart, xEnd, yEnd, color, arrowEdge ? mp_const_true : mp_const_false};
|
||||
checkFloatType(items, 4);
|
||||
mp_obj_t tuple = mp_obj_new_tuple(6, items);
|
||||
mp_obj_list_append(m_segments, tuple);
|
||||
}
|
||||
|
||||
// Rect
|
||||
|
||||
template class PlotStore::ListIterator<PlotStore::Rect>;
|
||||
|
||||
PlotStore::Rect::Rect(mp_obj_t tuple) {
|
||||
mp_obj_t * elements;
|
||||
mp_obj_get_array_fixed_n(tuple, 5, &elements);
|
||||
m_left = mp_obj_get_float(elements[0]);
|
||||
m_right = mp_obj_get_float(elements[1]);
|
||||
m_top = mp_obj_get_float(elements[2]);
|
||||
m_bottom = mp_obj_get_float(elements[3]);
|
||||
m_color = KDColor::RGB16(mp_obj_get_int(elements[4]));
|
||||
}
|
||||
|
||||
void PlotStore::addRect(mp_obj_t left, mp_obj_t right, mp_obj_t top, mp_obj_t bottom, KDColor c) {
|
||||
mp_obj_t color = mp_obj_new_int(c);
|
||||
mp_obj_t items[5] = {left, right, top, bottom, color};
|
||||
checkFloatType(items, 4);
|
||||
mp_obj_t tuple = mp_obj_new_tuple(5, items);
|
||||
mp_obj_list_append(m_rects, tuple);
|
||||
}
|
||||
|
||||
// Label
|
||||
|
||||
template class PlotStore::ListIterator<PlotStore::Label>;
|
||||
|
||||
PlotStore::Label::Label(mp_obj_t tuple) {
|
||||
mp_obj_t * elements;
|
||||
mp_obj_get_array_fixed_n(tuple, 3, &elements);
|
||||
m_x = mp_obj_get_float(elements[0]);
|
||||
m_y = mp_obj_get_float(elements[1]);
|
||||
m_string = mp_obj_str_get_str(elements[2]);
|
||||
}
|
||||
|
||||
void PlotStore::addLabel(mp_obj_t x, mp_obj_t y, mp_obj_t string) {
|
||||
mp_obj_t items[3] = {x, y, string};
|
||||
checkFloatType(items, 2);
|
||||
if (!mp_obj_is_str(string)) {
|
||||
mp_raise_TypeError("argument should be a string");
|
||||
}
|
||||
mp_obj_t tuple = mp_obj_new_tuple(3, items);
|
||||
mp_obj_list_append(m_labels, tuple);
|
||||
}
|
||||
|
||||
// Axes
|
||||
|
||||
static inline float minFloat(float x, float y) { return x < y ? x : y; }
|
||||
static inline float maxFloat(float x, float y) { return x > y ? x : y; }
|
||||
|
||||
void updateRange(float * xMin, float * xMax, float * yMin, float * yMax, float x, float y) {
|
||||
if (!std::isnan(x) && !std::isinf(x) && !std::isnan(y) && !std::isinf(y)) {
|
||||
*xMin = minFloat(*xMin, x);
|
||||
*xMax = maxFloat(*xMax, x);
|
||||
*yMin = minFloat(*yMin, y);
|
||||
*yMax = maxFloat(*yMax, y);
|
||||
}
|
||||
}
|
||||
|
||||
void checkPositiveRangeAndAddMargin(float * min, float * max) {
|
||||
if (*min > *max) {
|
||||
*min = - Shared::Range1D::k_default;
|
||||
*max = Shared::Range1D::k_default;
|
||||
return;
|
||||
}
|
||||
// Add margins
|
||||
float margin = (*max - *min)/10.0f;
|
||||
if (margin < FLT_EPSILON) {
|
||||
margin = 1.0f;
|
||||
}
|
||||
*min -= margin;
|
||||
*max += margin;
|
||||
}
|
||||
|
||||
void PlotStore::initRange() {
|
||||
if (m_axesAuto) {
|
||||
float xMin = FLT_MAX;
|
||||
float xMax = -FLT_MAX;
|
||||
float yMin = FLT_MAX;
|
||||
float yMax = -FLT_MAX;
|
||||
for (PlotStore::Dot dot : dots()) {
|
||||
updateRange(&xMin, &xMax, &yMin, &yMax, dot.x(), dot.y());
|
||||
}
|
||||
for (PlotStore::Label label : labels()) {
|
||||
updateRange(&xMin, &xMax, &yMin, &yMax, label.x(), label.y());
|
||||
}
|
||||
for (PlotStore::Segment segment : segments()) {
|
||||
updateRange(&xMin, &xMax, &yMin, &yMax, segment.xStart(), segment.yStart());
|
||||
updateRange(&xMin, &xMax, &yMin, &yMax, segment.xEnd(), segment.yEnd());
|
||||
}
|
||||
for (PlotStore::Rect rectangle : rects()) {
|
||||
updateRange(&xMin, &xMax, &yMin, &yMax, rectangle.left(), rectangle.top());
|
||||
updateRange(&xMin, &xMax, &yMin, &yMax, rectangle.right(), rectangle.bottom());
|
||||
}
|
||||
checkPositiveRangeAndAddMargin(&xMin, &xMax);
|
||||
checkPositiveRangeAndAddMargin(&yMin, &yMax);
|
||||
setXMin(xMin);
|
||||
setXMax(xMax);
|
||||
setYMin(yMin);
|
||||
setYMax(yMax);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
142
python/port/mod/matplotlib/pyplot/plot_store.h
Normal file
142
python/port/mod/matplotlib/pyplot/plot_store.h
Normal file
@@ -0,0 +1,142 @@
|
||||
#ifndef PYTHON_MATPLOTLIB_PLOT_STORE_H
|
||||
#define PYTHON_MATPLOTLIB_PLOT_STORE_H
|
||||
|
||||
//#include <apps/shared/curve_view_range.h>
|
||||
#include <apps/shared/interactive_curve_view_range.h>
|
||||
extern "C" {
|
||||
#include <py/runtime.h>
|
||||
}
|
||||
|
||||
namespace Matplotlib {
|
||||
|
||||
class PlotStore : public Shared::InteractiveCurveViewRange {
|
||||
public:
|
||||
PlotStore();
|
||||
void flush();
|
||||
bool isEmpty();
|
||||
|
||||
// Iterators
|
||||
|
||||
template <class T>
|
||||
class ListIterator {
|
||||
public:
|
||||
static ListIterator Begin(mp_obj_t list);
|
||||
static ListIterator End(mp_obj_t list);
|
||||
T operator*();
|
||||
ListIterator & operator++();
|
||||
bool operator!=(const ListIterator & it) const;
|
||||
private:
|
||||
ListIterator() : m_tupleIndex(0) {}
|
||||
mp_obj_t * m_tuples;
|
||||
size_t m_numberOfTuples;
|
||||
size_t m_tupleIndex;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Iterable {
|
||||
public:
|
||||
Iterable(mp_obj_t list) : m_list(list) {}
|
||||
T begin() const { return T::Begin(m_list); }
|
||||
T end() const { return T::End(m_list); }
|
||||
private:
|
||||
mp_obj_t m_list;
|
||||
};
|
||||
|
||||
// Dot
|
||||
|
||||
class Dot {
|
||||
public:
|
||||
Dot(mp_obj_t tuple);
|
||||
float x() const { return m_x; }
|
||||
float y() const { return m_y; }
|
||||
KDColor color() const { return m_color; }
|
||||
private:
|
||||
float m_x;
|
||||
float m_y;
|
||||
KDColor m_color;
|
||||
};
|
||||
|
||||
void addDot(mp_obj_t x, mp_obj_t y, KDColor c);
|
||||
Iterable<ListIterator<Dot>> dots() { return Iterable<ListIterator<Dot>>(m_dots); }
|
||||
|
||||
// Segment
|
||||
|
||||
class Segment {
|
||||
public:
|
||||
Segment(mp_obj_t tuple);
|
||||
float xStart() const { return m_xStart; }
|
||||
float yStart() const { return m_yStart; }
|
||||
float xEnd() const { return m_xEnd; }
|
||||
float yEnd() const { return m_yEnd; }
|
||||
bool isArrow() const { return m_arrow; }
|
||||
KDColor color() const { return m_color; }
|
||||
private:
|
||||
float m_xStart;
|
||||
float m_yStart;
|
||||
float m_xEnd;
|
||||
float m_yEnd;
|
||||
bool m_arrow;
|
||||
KDColor m_color;
|
||||
};
|
||||
|
||||
void addSegment(mp_obj_t xStart, mp_obj_t yStart, mp_obj_t xEnd, mp_obj_t yEnd, KDColor c, bool arrowEdge);
|
||||
Iterable<ListIterator<Segment>> segments() { return Iterable<ListIterator<Segment>>(m_segments); }
|
||||
|
||||
// Rect
|
||||
|
||||
class Rect {
|
||||
public:
|
||||
Rect(mp_obj_t tuple);
|
||||
float left() const { return m_left; }
|
||||
float right() const { return m_right; }
|
||||
float top() const { return m_top; }
|
||||
float bottom() const { return m_bottom; }
|
||||
KDColor color() const { return m_color; }
|
||||
private:
|
||||
float m_left;
|
||||
float m_right;
|
||||
float m_top;
|
||||
float m_bottom;
|
||||
KDColor m_color;
|
||||
};
|
||||
|
||||
void addRect(mp_obj_t x, mp_obj_t y, mp_obj_t width, mp_obj_t height, KDColor c);
|
||||
Iterable<ListIterator<Rect>> rects() { return Iterable<ListIterator<Rect>>(m_rects); }
|
||||
|
||||
// Label
|
||||
|
||||
class Label {
|
||||
public:
|
||||
Label(mp_obj_t tuple);
|
||||
float x() const { return m_x; }
|
||||
float y() const { return m_y; }
|
||||
const char * string() const { return m_string; }
|
||||
private:
|
||||
float m_x;
|
||||
float m_y;
|
||||
const char * m_string;
|
||||
};
|
||||
|
||||
void addLabel(mp_obj_t x, mp_obj_t y, mp_obj_t string);
|
||||
Iterable<ListIterator<Label>> labels() { return Iterable<ListIterator<Label>>(m_labels); }
|
||||
|
||||
void setAxesRequested(bool b) { m_axesRequested = b; }
|
||||
bool axesRequested() const { return m_axesRequested; }
|
||||
void setAxesAuto(bool b) { m_axesAuto = b; }
|
||||
void initRange();
|
||||
|
||||
void setGridRequested(bool b) { m_gridRequested = b; }
|
||||
bool gridRequested() const { return m_gridRequested; }
|
||||
private:
|
||||
mp_obj_t m_dots; // List of (x, y, color)
|
||||
mp_obj_t m_labels; // List of (x, y, string)
|
||||
mp_obj_t m_segments; // List of (x, y, dx, dy, style, color)
|
||||
mp_obj_t m_rects; // List of (x, y, w, h, color)
|
||||
bool m_axesRequested;
|
||||
bool m_axesAuto;
|
||||
bool m_gridRequested;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
80
python/port/mod/matplotlib/pyplot/plot_view.cpp
Normal file
80
python/port/mod/matplotlib/pyplot/plot_view.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "plot_view.h"
|
||||
|
||||
namespace Matplotlib {
|
||||
|
||||
void PlotView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(rect, KDColorWhite);
|
||||
|
||||
if (m_store->gridRequested()) {
|
||||
drawGrid(ctx, rect);
|
||||
}
|
||||
|
||||
// Draw labels below all figures because they're drawn on a white rectangle.
|
||||
// TODO: we could blend them in the background by adding a parameter to drawLabelsAndGraduations.
|
||||
if (m_store->axesRequested()) {
|
||||
drawAxes(ctx, rect);
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Vertical, true);
|
||||
drawLabelsAndGraduations(ctx, rect, Axis::Horizontal, true);
|
||||
}
|
||||
|
||||
for (PlotStore::Dot dot : m_store->dots()) {
|
||||
traceDot(ctx, rect, dot);
|
||||
}
|
||||
|
||||
for (PlotStore::Label label : m_store->labels()) {
|
||||
traceLabel(ctx, rect, label);
|
||||
}
|
||||
|
||||
for (PlotStore::Segment segment : m_store->segments()) {
|
||||
traceSegment(ctx, rect, segment);
|
||||
}
|
||||
|
||||
for (PlotStore::Rect rectangle : m_store->rects()) {
|
||||
traceRect(ctx, rect, rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
void PlotView::traceDot(KDContext * ctx, KDRect r, PlotStore::Dot dot) const {
|
||||
drawDot(ctx, r, dot.x(), dot.y(), dot.color());
|
||||
}
|
||||
|
||||
void PlotView::traceSegment(KDContext * ctx, KDRect r, PlotStore::Segment segment) const {
|
||||
drawSegment(
|
||||
ctx, r,
|
||||
segment.xStart(), segment.yStart(),
|
||||
segment.xEnd(), segment.yEnd(),
|
||||
segment.color()
|
||||
);
|
||||
if (segment.isArrow()) {
|
||||
float dx = segment.xEnd() - segment.xStart();
|
||||
float dy = segment.yEnd() - segment.yStart();
|
||||
drawArrow(ctx, r, segment.xEnd(), segment.yEnd(), dx, dy, segment.color());
|
||||
}
|
||||
}
|
||||
|
||||
static inline KDCoordinate maxKDCoordinate(KDCoordinate x, KDCoordinate y) { return x > y ? x : y; }
|
||||
void PlotView::traceRect(KDContext * ctx, KDRect r, PlotStore::Rect rect) const {
|
||||
KDCoordinate left = std::round(floatToPixel(Axis::Horizontal, rect.left()));
|
||||
KDCoordinate right = std::round(floatToPixel(Axis::Horizontal, rect.right()));
|
||||
KDCoordinate top = std::round(floatToPixel(Axis::Vertical, rect.top()));
|
||||
KDCoordinate bottom = std::round(floatToPixel(Axis::Vertical, rect.bottom()));
|
||||
KDRect pixelRect(
|
||||
left,
|
||||
top,
|
||||
maxKDCoordinate(right - left, 1), // Rectangle should at least be visible
|
||||
bottom - top
|
||||
);
|
||||
ctx->fillRect(pixelRect, rect.color());
|
||||
}
|
||||
|
||||
void PlotView::traceLabel(KDContext * ctx, KDRect r, PlotStore::Label label) const {
|
||||
drawLabel(ctx, r,
|
||||
label.x(), label.y(), label.string(),
|
||||
KDColorBlack,
|
||||
RelativePosition::After,
|
||||
RelativePosition::After
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
24
python/port/mod/matplotlib/pyplot/plot_view.h
Normal file
24
python/port/mod/matplotlib/pyplot/plot_view.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef PYTHON_MATPLOTLIB_PLOT_VIEW_H
|
||||
#define PYTHON_MATPLOTLIB_PLOT_VIEW_H
|
||||
|
||||
#include <apps/shared/labeled_curve_view.h>
|
||||
#include "plot_store.h"
|
||||
|
||||
namespace Matplotlib {
|
||||
|
||||
class PlotView : public Shared::LabeledCurveView {
|
||||
public:
|
||||
PlotView(PlotStore * s) : Shared::LabeledCurveView(s), m_store(s) {}
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
void traceDot(KDContext * ctx, KDRect r, PlotStore::Dot dot) const;
|
||||
void traceSegment(KDContext * ctx, KDRect r, PlotStore::Segment segment) const;
|
||||
void traceRect(KDContext * ctx, KDRect r, PlotStore::Rect rect) const;
|
||||
void traceLabel(KDContext * ctx, KDRect r, PlotStore::Label label) const;
|
||||
PlotStore * m_store;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -130,12 +130,16 @@ typedef long mp_off_t;
|
||||
|
||||
extern const struct _mp_obj_module_t modion_module;
|
||||
extern const struct _mp_obj_module_t modkandinsky_module;
|
||||
extern const struct _mp_obj_module_t modmatplotlib_module;
|
||||
extern const struct _mp_obj_module_t modpyplot_module;
|
||||
extern const struct _mp_obj_module_t modtime_module;
|
||||
extern const struct _mp_obj_module_t modturtle_module;
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_ROM_QSTR(MP_QSTR_ion), MP_ROM_PTR(&modion_module) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_kandinsky), MP_ROM_PTR(&modkandinsky_module) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_matplotlib), MP_ROM_PTR(&modmatplotlib_module) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_matplotlib_dot_pyplot), MP_ROM_PTR(&modpyplot_module) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&modtime_module) }, \
|
||||
{ MP_ROM_QSTR(MP_QSTR_turtle), MP_ROM_PTR(&modturtle_module) }, \
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ extern "C" {
|
||||
#include "py/stackctrl.h"
|
||||
#include "mphalport.h"
|
||||
#include "mod/turtle/modturtle.h"
|
||||
#include "mod/matplotlib/pyplot/modpyplot.h"
|
||||
}
|
||||
|
||||
static MicroPython::ScriptProvider * sScriptProvider = nullptr;
|
||||
@@ -81,6 +82,10 @@ void MicroPython::ExecutionEnvironment::runCode(const char * str) {
|
||||
mp_obj_print_helper(&mp_plat_print, (mp_obj_t)nlr.ret_val, PRINT_EXC);
|
||||
mp_print_str(&mp_plat_print, "\n");
|
||||
/* End of mp_obj_print_exception. */
|
||||
|
||||
// Flush the store if an error is encountered to avoid being stuck with a full memory
|
||||
modpyplot_flush_used_heap();
|
||||
// TODO: do the same for other modules?
|
||||
}
|
||||
|
||||
// Disable the user interruption
|
||||
@@ -94,13 +99,6 @@ void MicroPython::ExecutionEnvironment::interrupt() {
|
||||
mp_keyboard_interrupt();
|
||||
}
|
||||
|
||||
void MicroPython::ExecutionEnvironment::setSandboxIsDisplayed(bool display) {
|
||||
if (m_sandboxIsDisplayed && !display) {
|
||||
modturtle_view_did_disappear();
|
||||
}
|
||||
m_sandboxIsDisplayed = display;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
extern const void * _stack_start;
|
||||
extern const void * _stack_end;
|
||||
@@ -176,6 +174,7 @@ void gc_collect(void) {
|
||||
gc_collect_start();
|
||||
|
||||
modturtle_gc_collect();
|
||||
modpyplot_gc_collect();
|
||||
|
||||
/* get the registers.
|
||||
* regs is the also the last object on the stack so the stack is bound by
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
extern "C" {
|
||||
#include <stddef.h>
|
||||
}
|
||||
#include <escher/view_controller.h>
|
||||
|
||||
namespace MicroPython {
|
||||
|
||||
@@ -14,21 +15,23 @@ public:
|
||||
|
||||
class ExecutionEnvironment {
|
||||
public:
|
||||
ExecutionEnvironment() : m_sandboxIsDisplayed(false) {}
|
||||
ExecutionEnvironment() {}
|
||||
static ExecutionEnvironment * currentExecutionEnvironment();
|
||||
void runCode(const char * );
|
||||
virtual const char * inputText(const char * prompt) { return nullptr; }
|
||||
virtual void displaySandbox() {}
|
||||
virtual void hideSandbox() {}
|
||||
|
||||
// Sandbox
|
||||
void displaySandbox() { displayViewController(sandbox()); }
|
||||
virtual ViewController * sandbox() { return nullptr; }
|
||||
virtual void resetSandbox() {}
|
||||
|
||||
// Generic View Controller
|
||||
virtual void displayViewController(ViewController * controller) {}
|
||||
virtual void hideAnyDisplayedViewController() {}
|
||||
|
||||
virtual void printText(const char * text, size_t length) {}
|
||||
virtual void refreshPrintOutput() {}
|
||||
void interrupt();
|
||||
void setSandboxIsDisplayed(bool display);
|
||||
protected:
|
||||
bool sandboxIsDisplayed() const { return m_sandboxIsDisplayed; }
|
||||
private:
|
||||
bool m_sandboxIsDisplayed;
|
||||
};
|
||||
|
||||
void init(void * heapStart, void * heapEnd);
|
||||
@@ -36,6 +39,6 @@ void deinit();
|
||||
void registerScriptProvider(ScriptProvider * s);
|
||||
void collectRootsAtAddress(char * address, int len);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user