diff --git a/libraries/pico_vector/pico_vector.cpp b/libraries/pico_vector/pico_vector.cpp index a060aa38..3c0314e6 100644 --- a/libraries/pico_vector/pico_vector.cpp +++ b/libraries/pico_vector/pico_vector.cpp @@ -9,6 +9,29 @@ namespace pimoroni { scale); } + void PicoVector::rotate(std::vector> &contours, Point origin, float angle) { + pretty_poly::mat3_t t2 = pretty_poly::mat3_t::translation(origin.x, origin.y); + pretty_poly::mat3_t t1 = pretty_poly::mat3_t::translation(-origin.x, -origin.y); + angle = 2 * M_PI * (angle / 360.0f); + pretty_poly::mat3_t r = pretty_poly::mat3_t::rotation(angle); + for(auto &contour : contours) { + for(auto i = 0u; i < contour.count; i++) { + contour.points[i] *= t1; + contour.points[i] *= r; + contour.points[i] *= t2; + } + } + } + + void PicoVector::translate(std::vector> &contours, Point translation) { + pretty_poly::mat3_t t = pretty_poly::mat3_t::translation(translation.x, translation.y); + for(auto &contour : contours) { + for(auto i = 0u; i < contour.count; i++) { + contour.points[i] *= t; + } + } + } + Point PicoVector::text(std::string_view text, Point origin) { // TODO: Normalize types somehow, so we're not converting? pretty_poly::point_t caret = pretty_poly::point_t(origin.x, origin.y); diff --git a/libraries/pico_vector/pico_vector.hpp b/libraries/pico_vector/pico_vector.hpp index 80a6d27f..75c6cbdb 100644 --- a/libraries/pico_vector/pico_vector.hpp +++ b/libraries/pico_vector/pico_vector.hpp @@ -59,6 +59,9 @@ namespace pimoroni { return result; } + void rotate(std::vector> &contours, Point origin, float angle); + void translate(std::vector> &contours, Point translation); + Point text(std::string_view text, Point origin); void polygon(std::vector> contours, Point origin = Point(0, 0), int scale=65536); diff --git a/libraries/pico_vector/pretty_poly_types.hpp b/libraries/pico_vector/pretty_poly_types.hpp index 643dba58..896acc52 100644 --- a/libraries/pico_vector/pretty_poly_types.hpp +++ b/libraries/pico_vector/pretty_poly_types.hpp @@ -111,6 +111,10 @@ namespace pretty_poly { contour_t(std::vector> v) : points(v.data()), count(v.size()) {}; contour_t(point_t *points, unsigned count) : points(points), count(count) {}; + // TODO: Make this work, it's so much nicer to use auto point : contour + //point_t *begin() const { return points; }; + //point_t *end() const { return points + count * sizeof(point_t); }; + rect_t bounds() { T minx = this->points[0].x, maxx = minx; T miny = this->points[0].y, maxy = miny; diff --git a/micropython/modules/picovector/picovector.cpp b/micropython/modules/picovector/picovector.cpp index 60af3f9d..848d239c 100644 --- a/micropython/modules/picovector/picovector.cpp +++ b/micropython/modules/picovector/picovector.cpp @@ -239,7 +239,11 @@ mp_obj_t VECTOR_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar int offset_x = 0; int offset_y = 0; + float angle = 0.0f; + // TODO: We should probably convert this to a full-fat argument parser + // with optional kwargs for translation and rotation + // this is very, very hacky if(mp_obj_is_int(pos_args[1])) { offset_x = mp_obj_get_int(pos_args[1]); lists++; @@ -252,6 +256,12 @@ mp_obj_t VECTOR_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar num_tuples--; } + if (mp_obj_is_float(pos_args[3])) { + angle = mp_obj_get_float(pos_args[3]); + lists++; + num_tuples--; + } + std::vector> contours; for(auto i = 0u; i < num_tuples; i++) { @@ -278,7 +288,17 @@ mp_obj_t VECTOR_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ar contours.push_back({points, t_contour->len}); } - self->vector->polygon(contours, Point(offset_x, offset_y)); + // TODO: This is pretty awful + // Translating contours could be another operation + // But it's costly to convert to/from a list of lists of tuples + // Perhaps polygons should be a purely internal C++ concept + // And we could have make_polygon(list(tuple, tuple)) ? + if(angle != 0.0f) { + self->vector->rotate(contours, Point(offset_x, offset_y), angle); + self->vector->polygon(contours, Point(0, 0)); + } else { + self->vector->polygon(contours, Point(offset_x, offset_y)); + } for(auto contour : contours) { delete contour.points;