kopia lustrzana https://github.com/pimoroni/pimoroni-pico
PicoVector: Matrix transforms and polygon type.
rodzic
61c9d7e9b6
commit
7c5ebfce8c
|
@ -2,14 +2,14 @@
|
|||
#include <vector>
|
||||
|
||||
namespace pimoroni {
|
||||
void PicoVector::polygon(std::vector<pretty_poly::contour_t<int>> contours, Point origin, int scale) {
|
||||
pretty_poly::draw_polygon<int>(
|
||||
void PicoVector::polygon(std::vector<pretty_poly::contour_t<picovector_point_type>> contours, Point origin, int scale) {
|
||||
pretty_poly::draw_polygon<picovector_point_type>(
|
||||
contours,
|
||||
pretty_poly::point_t<int>(origin.x, origin.y),
|
||||
scale);
|
||||
}
|
||||
|
||||
void PicoVector::rotate(std::vector<pretty_poly::contour_t<int>> &contours, Point origin, float angle) {
|
||||
void PicoVector::rotate(std::vector<pretty_poly::contour_t<picovector_point_type>> &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);
|
||||
|
@ -23,7 +23,7 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void PicoVector::translate(std::vector<pretty_poly::contour_t<int>> &contours, Point translation) {
|
||||
void PicoVector::translate(std::vector<pretty_poly::contour_t<picovector_point_type>> &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++) {
|
||||
|
@ -32,6 +32,25 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void PicoVector::rotate(pretty_poly::contour_t<picovector_point_type> &contour, 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 i = 0u; i < contour.count; i++) {
|
||||
contour.points[i] *= t1;
|
||||
contour.points[i] *= r;
|
||||
contour.points[i] *= t2;
|
||||
}
|
||||
}
|
||||
|
||||
void PicoVector::translate(pretty_poly::contour_t<picovector_point_type> &contour, Point translation) {
|
||||
pretty_poly::mat3_t t = pretty_poly::mat3_t::translation(translation.x, translation.y);
|
||||
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<int> caret = pretty_poly::point_t<int>(origin.x, origin.y);
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
#include "pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
// Integer point types cause compound error in transformations
|
||||
typedef float picovector_point_type;
|
||||
|
||||
class PicoVector {
|
||||
private:
|
||||
PicoGraphics *graphics;
|
||||
|
@ -59,12 +63,15 @@ namespace pimoroni {
|
|||
return result;
|
||||
}
|
||||
|
||||
void rotate(std::vector<pretty_poly::contour_t<int>> &contours, Point origin, float angle);
|
||||
void translate(std::vector<pretty_poly::contour_t<int>> &contours, Point translation);
|
||||
void rotate(std::vector<pretty_poly::contour_t<picovector_point_type>> &contours, Point origin, float angle);
|
||||
void translate(std::vector<pretty_poly::contour_t<picovector_point_type>> &contours, Point translation);
|
||||
|
||||
void rotate(pretty_poly::contour_t<picovector_point_type> &contour, Point origin, float angle);
|
||||
void translate(pretty_poly::contour_t<picovector_point_type> &contour, Point translation);
|
||||
|
||||
Point text(std::string_view text, Point origin);
|
||||
|
||||
void polygon(std::vector<pretty_poly::contour_t<int>> contours, Point origin = Point(0, 0), int scale=65536);
|
||||
void polygon(std::vector<pretty_poly::contour_t<picovector_point_type>> contours, Point origin = Point(0, 0), int scale=65536);
|
||||
|
||||
static constexpr size_t pretty_poly_buffer_size() {
|
||||
return pretty_poly::buffer_size();
|
||||
|
|
|
@ -122,14 +122,14 @@ namespace pretty_poly {
|
|||
|
||||
// start with the last point to close the loop
|
||||
point_t<int> last(
|
||||
(((contour.points[contour.count - 1].x * scale) << settings::antialias) / 65536) + ox,
|
||||
(((contour.points[contour.count - 1].y * scale) << settings::antialias) / 65536) + oy
|
||||
(((int(contour.points[contour.count - 1].x) * scale) << settings::antialias) / 65536) + ox,
|
||||
(((int(contour.points[contour.count - 1].y) * scale) << settings::antialias) / 65536) + oy
|
||||
);
|
||||
|
||||
for(auto i = 0u; i < contour.count; i++) {
|
||||
point_t<int> point(
|
||||
(((contour.points[i].x * scale) << settings::antialias) / 65536) + ox,
|
||||
(((contour.points[i].y * scale) << settings::antialias) / 65536) + oy
|
||||
(((int(contour.points[i].x) * scale) << settings::antialias) / 65536) + ox,
|
||||
(((int(contour.points[i].y) * scale) << settings::antialias) / 65536) + oy
|
||||
);
|
||||
|
||||
add_line_segment_to_nodes(last, point);
|
||||
|
@ -234,5 +234,6 @@ namespace pretty_poly {
|
|||
}
|
||||
|
||||
template void pretty_poly::draw_polygon<int>(std::vector<contour_t<int>> contours, point_t<int> origin, int scale);
|
||||
template void pretty_poly::draw_polygon<float>(std::vector<contour_t<float>> contours, point_t<int> origin, int scale);
|
||||
template void pretty_poly::draw_polygon<uint8_t>(std::vector<contour_t<uint8_t>> contours, point_t<int> origin, int scale);
|
||||
template void pretty_poly::draw_polygon<int8_t>(std::vector<contour_t<int8_t>> contours, point_t<int> origin, int scale);
|
|
@ -36,7 +36,7 @@ namespace pretty_poly {
|
|||
static mat3_t identity() {mat3_t m; m.v00 = m.v11 = m.v22 = 1.0f; return m;}
|
||||
static mat3_t rotation(float a) {
|
||||
float c = cosf(a), s = sinf(a); mat3_t r = mat3_t::identity();
|
||||
r.v00 = c; r.v01 = s; r.v10 = -s; r.v11 = c; return r;}
|
||||
r.v00 = c; r.v01 = -s; r.v10 = s; r.v11 = c; return r;}
|
||||
static mat3_t translation(float x, float y) {
|
||||
mat3_t r = mat3_t::identity(); r.v02 = x; r.v12 = y; return r;}
|
||||
static mat3_t scale(float x, float y) {
|
||||
|
@ -56,8 +56,9 @@ namespace pretty_poly {
|
|||
inline point_t& operator/= (const float a) {x /= a; y /= a; return *this;}
|
||||
inline point_t& operator/= (const point_t &a) {x /= a.x; y /= a.y; return *this;}
|
||||
void transform(const mat3_t &m) {
|
||||
this->x = (m.v00 * float(this->x) + m.v01 * float(this->y) + m.v02);
|
||||
this->y = (m.v10 * float(this->x) + m.v11 * float(this->y) + m.v12);
|
||||
float tx = x, ty = y;
|
||||
this->x = (m.v00 * tx + m.v01 * ty + m.v02);
|
||||
this->y = (m.v10 * tx + m.v11 * ty + m.v12);
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,21 +1,81 @@
|
|||
#include "picovector.h"
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(VECTOR_polygon_obj, 2, VECTOR_polygon);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(VECTOR_regular_polygon_obj, 6, VECTOR_regular_polygon);
|
||||
/* Polygon */
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(POLYGON__del__obj, POLYGON__del__);
|
||||
|
||||
|
||||
STATIC const mp_rom_map_elem_t POLYGON_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&POLYGON__del__obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(POLYGON_locals_dict, POLYGON_locals_dict_table);
|
||||
|
||||
#ifdef MP_DEFINE_CONST_OBJ_TYPE
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
POLYGON_type,
|
||||
MP_QSTR_polygon,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, POLYGON_make_new,
|
||||
print, POLYGON_print,
|
||||
locals_dict, (mp_obj_dict_t*)&POLYGON_locals_dict
|
||||
);
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
REGULAR_POLYGON_type,
|
||||
MP_QSTR_regular_polygon,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, REGULAR_POLYGON_make_new,
|
||||
locals_dict, (mp_obj_dict_t*)&POLYGON_locals_dict
|
||||
);
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
RECTANGLE_type,
|
||||
MP_QSTR_rectangle,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, RECTANGLE_make_new,
|
||||
locals_dict, (mp_obj_dict_t*)&POLYGON_locals_dict
|
||||
);
|
||||
#else
|
||||
const mp_obj_type_t POLYGON_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_polygon,
|
||||
.make_new = POLYGON_make_new,
|
||||
.print = POLYGON_print,
|
||||
.locals_dict = (mp_obj_dict_t*)&POLYGON_locals_dict,
|
||||
};
|
||||
const mp_obj_type_t REGULAR_POLYGON_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_regular_polygon,
|
||||
.make_new = REGULAR_POLYGON_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&POLYGON_locals_dict,
|
||||
};
|
||||
const mp_obj_type_t RECTANGLE_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_rectangle,
|
||||
.make_new = RECTANGLE_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&POLYGON_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* PicoVector */
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(VECTOR_text_obj, 4, VECTOR_text);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(VECTOR_set_font_obj, VECTOR_set_font);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(VECTOR_set_font_size_obj, VECTOR_set_font_size);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(VECTOR_set_antialiasing_obj, VECTOR_set_antialiasing);
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(VECTOR_draw_obj, 2, VECTOR_draw);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(VECTOR_rotate_obj, 3, VECTOR_rotate);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(VECTOR_translate_obj, 4, VECTOR_translate);
|
||||
|
||||
// class
|
||||
STATIC const mp_rom_map_elem_t VECTOR_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_polygon), MP_ROM_PTR(&VECTOR_polygon_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_regular_polygon), MP_ROM_PTR(&VECTOR_regular_polygon_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_font), MP_ROM_PTR(&VECTOR_set_font_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_font_size), MP_ROM_PTR(&VECTOR_set_font_size_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_antialiasing), MP_ROM_PTR(&VECTOR_set_antialiasing_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&VECTOR_text_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_draw), MP_ROM_PTR(&VECTOR_draw_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rotate), MP_ROM_PTR(&VECTOR_rotate_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_translate), MP_ROM_PTR(&VECTOR_translate_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(VECTOR_locals_dict, VECTOR_locals_dict_table);
|
||||
|
@ -37,10 +97,14 @@ const mp_obj_type_t VECTOR_type = {
|
|||
};
|
||||
#endif
|
||||
|
||||
// module
|
||||
/* Module */
|
||||
|
||||
STATIC const mp_map_elem_t VECTOR_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_picovector) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PicoVector), (mp_obj_t)&VECTOR_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Polygon), (mp_obj_t)&POLYGON_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RegularPolygon), (mp_obj_t)®ULAR_POLYGON_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Rectangle), (mp_obj_t)&RECTANGLE_type },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ANTIALIAS_NONE), MP_ROM_INT(0) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ANTIALIAS_X4), MP_ROM_INT(1) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ANTIALIAS_X16), MP_ROM_INT(2) },
|
||||
|
|
|
@ -23,6 +23,10 @@ typedef struct _VECTOR_obj_t {
|
|||
PicoVector *vector;
|
||||
} _VECTOR_obj_t;
|
||||
|
||||
typedef struct _POLYGON_obj_t {
|
||||
mp_obj_base_t base;
|
||||
pretty_poly::contour_t<picovector_point_type> contour;
|
||||
} _POLYGON_obj_t;
|
||||
|
||||
pretty_poly::file_io::file_io(std::string_view filename) {
|
||||
mp_obj_t fn = mp_obj_new_str(filename.data(), (mp_uint_t)filename.size());
|
||||
|
@ -103,6 +107,139 @@ static const std::string_view mp_obj_to_string_r(const mp_obj_t &obj) {
|
|||
mp_raise_TypeError("can't convert object to str implicitly");
|
||||
}
|
||||
|
||||
/* POLYGON */
|
||||
|
||||
mp_obj_t RECTANGLE_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
enum { ARG_x, ARG_y, ARG_w, ARG_h };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_w, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_h, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
_POLYGON_obj_t *self = m_new_obj_with_finaliser(_POLYGON_obj_t);
|
||||
self->base.type = &POLYGON_type;
|
||||
|
||||
int x = args[ARG_x].u_int;
|
||||
int y = args[ARG_y].u_int;
|
||||
int w = args[ARG_w].u_int;
|
||||
int h = args[ARG_h].u_int;
|
||||
|
||||
self->contour.points = m_new(pretty_poly::point_t<picovector_point_type>, 4);
|
||||
self->contour.count = 4;
|
||||
|
||||
self->contour.points[0] = {float(x), float(y)};
|
||||
self->contour.points[1] = {float(x + w), float(y)};
|
||||
self->contour.points[2] = {float(x + w), float(y + h)};
|
||||
self->contour.points[3] = {float(x), float(y + h)};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
mp_obj_t REGULAR_POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
enum { ARG_x, ARG_y, ARG_sides, ARG_radius, ARG_rotation };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_sides, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_rotation, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
_POLYGON_obj_t *self = m_new_obj_with_finaliser(_POLYGON_obj_t);
|
||||
self->base.type = &POLYGON_type;
|
||||
|
||||
Point origin(args[ARG_x].u_int, args[ARG_y].u_int);
|
||||
unsigned int sides = args[ARG_sides].u_int;
|
||||
float radius = mp_obj_get_float(args[ARG_radius].u_obj);
|
||||
float rotation = 0.0f;
|
||||
if (args[ARG_rotation].u_obj != mp_const_none) {
|
||||
rotation = mp_obj_get_float(args[ARG_rotation].u_obj);
|
||||
rotation *= (M_PI / 180.0f);
|
||||
}
|
||||
int o_x = args[ARG_x].u_int;
|
||||
int o_y = args[ARG_y].u_int;
|
||||
|
||||
float angle = (360.0f / sides) * (M_PI / 180.0f);
|
||||
|
||||
self->contour.points = m_new(pretty_poly::point_t<picovector_point_type>, sides);
|
||||
self->contour.count = sides;
|
||||
|
||||
for(auto s = 0u; s < sides; s++) {
|
||||
float current_angle = angle * s + rotation;
|
||||
self->contour.points[s] = {
|
||||
(picovector_point_type)(cos(current_angle) * radius) + o_x,
|
||||
(picovector_point_type)(sin(current_angle) * radius) + o_y
|
||||
};
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
mp_obj_t POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_POLYGON_obj_t *self = m_new_obj_with_finaliser(_POLYGON_obj_t);
|
||||
self->base.type = &POLYGON_type;
|
||||
|
||||
size_t num_points = n_args;
|
||||
const mp_obj_t *points = all_args;
|
||||
|
||||
if(num_points < 3) mp_raise_ValueError("Polygon: At least 3 points required.");
|
||||
|
||||
self->contour.points = m_new(pretty_poly::point_t<picovector_point_type>, num_points);
|
||||
self->contour.count = num_points;
|
||||
|
||||
for(auto i = 0u; i < num_points; i++) {
|
||||
mp_obj_t c_obj = points[i];
|
||||
|
||||
if(!mp_obj_is_exact_type(c_obj, &mp_type_tuple)) mp_raise_ValueError("Not a tuple");
|
||||
|
||||
mp_obj_tuple_t *t_point = MP_OBJ_TO_PTR2(c_obj, mp_obj_tuple_t);
|
||||
|
||||
if(t_point->len != 2) mp_raise_ValueError("Tuple must have X, Y");
|
||||
|
||||
self->contour.points[i] = {
|
||||
(picovector_point_type)mp_obj_get_int(t_point->items[0]),
|
||||
(picovector_point_type)mp_obj_get_int(t_point->items[1]),
|
||||
};
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void POLYGON_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
_POLYGON_obj_t *self = MP_OBJ_TO_PTR2(self_in, _POLYGON_obj_t);
|
||||
|
||||
mp_print_str(print, "Polygon(");
|
||||
mp_print_str(print, ", points = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->contour.count), PRINT_REPR);
|
||||
mp_print_str(print, ", bounds = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->contour.bounds().x), PRINT_REPR);
|
||||
mp_print_str(print, ", ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->contour.bounds().y), PRINT_REPR);
|
||||
mp_print_str(print, ", ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->contour.bounds().w), PRINT_REPR);
|
||||
mp_print_str(print, ", ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(self->contour.bounds().h), PRINT_REPR);
|
||||
mp_print_str(print, ")");
|
||||
}
|
||||
|
||||
mp_obj_t POLYGON__del__(mp_obj_t self_in) {
|
||||
_POLYGON_obj_t *self = MP_OBJ_TO_PTR2(self_in, _POLYGON_obj_t);
|
||||
(void)self;
|
||||
// TODO: Do we actually need to free anything here, if it's on GC heap it should get collected
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
/* VECTOR */
|
||||
|
||||
mp_obj_t VECTOR_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
enum {
|
||||
ARG_picographics
|
||||
|
@ -186,15 +323,14 @@ mp_obj_t VECTOR_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args)
|
|||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VECTOR_regular_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_x, ARG_y, ARG_sides, ARG_radius, ARG_rotation };
|
||||
mp_obj_t VECTOR_rotate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_polygon, ARG_angle, ARG_origin_x, ARG_origin_y };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_sides, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_rotation, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_polygon, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_angle, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_origin_x, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_origin_y, MP_ARG_INT, {.u_int = 0} }
|
||||
};
|
||||
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
|
@ -202,107 +338,63 @@ mp_obj_t VECTOR_regular_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_
|
|||
|
||||
_VECTOR_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _VECTOR_obj_t);
|
||||
|
||||
Point origin(args[ARG_x].u_int, args[ARG_y].u_int);
|
||||
unsigned int sides = args[ARG_sides].u_int;
|
||||
float radius = mp_obj_get_float(args[ARG_radius].u_obj);
|
||||
float rotation = mp_obj_get_float(args[ARG_rotation].u_obj);
|
||||
int o_x = args[ARG_x].u_int;
|
||||
int o_y = args[ARG_y].u_int;
|
||||
if(!MP_OBJ_IS_TYPE(args[ARG_polygon].u_obj, &POLYGON_type)) mp_raise_TypeError("rotate: polygon required");
|
||||
|
||||
float angle = (360.0f / sides) * (M_PI / 180.0f);
|
||||
_POLYGON_obj_t *poly = MP_OBJ_TO_PTR2(args[ARG_polygon].u_obj, _POLYGON_obj_t);
|
||||
|
||||
pretty_poly::point_t<int> *points = new pretty_poly::point_t<int>[sides];
|
||||
Point origin = Point(args[ARG_origin_x].u_int, args[ARG_origin_y].u_int);
|
||||
|
||||
for(auto s = 0u; s < sides; s++) {
|
||||
float current_angle = angle * s + rotation;
|
||||
points[s] = {
|
||||
int(cos(current_angle) * radius),
|
||||
int(sin(current_angle) * radius)
|
||||
};
|
||||
}
|
||||
float angle = mp_obj_get_float(args[ARG_angle].u_obj);
|
||||
|
||||
std::vector<pretty_poly::contour_t<int>> contours;
|
||||
contours.push_back({points, sides});
|
||||
self->vector->polygon(contours, Point(o_x, o_y));
|
||||
|
||||
delete points;
|
||||
self->vector->rotate(poly->contour, origin, angle);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VECTOR_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
mp_obj_t VECTOR_translate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_self, ARG_polygon, ARG_x, ARG_y };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_polygon, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_x, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_y, MP_ARG_INT, {.u_int = 0} }
|
||||
};
|
||||
|
||||
size_t num_tuples = n_args - 1;
|
||||
const mp_obj_t *lists = pos_args + 1;
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
_VECTOR_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _VECTOR_obj_t);
|
||||
|
||||
if(!MP_OBJ_IS_TYPE(args[ARG_polygon].u_obj, &POLYGON_type)) mp_raise_TypeError("rotate: polygon required");
|
||||
|
||||
_POLYGON_obj_t *poly = MP_OBJ_TO_PTR2(args[ARG_polygon].u_obj, _POLYGON_obj_t);
|
||||
|
||||
Point translate = Point(args[ARG_x].u_int, args[ARG_y].u_int);
|
||||
|
||||
self->vector->translate(poly->contour, translate);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t VECTOR_draw(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
|
||||
size_t num_polygons = n_args - 1;
|
||||
const mp_obj_t *polygons = pos_args + 1;
|
||||
|
||||
_VECTOR_obj_t *self = MP_OBJ_TO_PTR2(pos_args[0], _VECTOR_obj_t);
|
||||
|
||||
int offset_x = 0;
|
||||
int offset_y = 0;
|
||||
float angle = 0.0f;
|
||||
std::vector<pretty_poly::contour_t<picovector_point_type>> contours;
|
||||
|
||||
// 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++;
|
||||
num_tuples--;
|
||||
for(auto i = 0u; i < num_polygons; i++) {
|
||||
mp_obj_t poly_obj = polygons[i];
|
||||
|
||||
if(!MP_OBJ_IS_TYPE(poly_obj, &POLYGON_type)) mp_raise_TypeError("draw: Polygon required.");
|
||||
|
||||
_POLYGON_obj_t *poly = MP_OBJ_TO_PTR2(poly_obj, _POLYGON_obj_t);
|
||||
contours.push_back(poly->contour);
|
||||
}
|
||||
|
||||
if (mp_obj_is_int(pos_args[2])) {
|
||||
offset_y = mp_obj_get_int(pos_args[2]);
|
||||
lists++;
|
||||
num_tuples--;
|
||||
}
|
||||
|
||||
if (mp_obj_is_float(pos_args[3])) {
|
||||
angle = mp_obj_get_float(pos_args[3]);
|
||||
lists++;
|
||||
num_tuples--;
|
||||
}
|
||||
|
||||
std::vector<pretty_poly::contour_t<int>> contours;
|
||||
|
||||
for(auto i = 0u; i < num_tuples; i++) {
|
||||
mp_obj_t c_obj = lists[i];
|
||||
|
||||
if(!mp_obj_is_exact_type(c_obj, &mp_type_list)) mp_raise_ValueError("Not a list");
|
||||
|
||||
mp_obj_list_t *t_contour = MP_OBJ_TO_PTR2(c_obj, mp_obj_list_t);
|
||||
|
||||
pretty_poly::point_t<int> *points = new pretty_poly::point_t<int>[t_contour->len];
|
||||
|
||||
for(auto p = 0u; p < t_contour->len; p++) {
|
||||
mp_obj_t p_obj = t_contour->items[p];
|
||||
|
||||
if(!mp_obj_is_exact_type(p_obj, &mp_type_tuple)) mp_raise_ValueError("Not a tuple");
|
||||
|
||||
mp_obj_tuple_t *t_point = MP_OBJ_TO_PTR2(p_obj, mp_obj_tuple_t);
|
||||
points[p] = {
|
||||
mp_obj_get_int(t_point->items[0]),
|
||||
mp_obj_get_int(t_point->items[1]),
|
||||
};
|
||||
}
|
||||
|
||||
contours.push_back({points, t_contour->len});
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
self->vector->polygon(contours);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,24 @@
|
|||
#include "py/objstr.h"
|
||||
|
||||
extern const mp_obj_type_t VECTOR_type;
|
||||
extern const mp_obj_type_t POLYGON_type;
|
||||
extern const mp_obj_type_t REGULAR_POLYGON_type;
|
||||
extern const mp_obj_type_t RECTANGLE_type;
|
||||
|
||||
extern mp_obj_t POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t REGULAR_POLYGON_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t RECTANGLE_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern void POLYGON_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
|
||||
extern mp_obj_t POLYGON__del__(mp_obj_t self_in);
|
||||
|
||||
extern mp_obj_t VECTOR_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
|
||||
extern mp_obj_t VECTOR_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t VECTOR_regular_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t VECTOR_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t VECTOR_set_font(mp_obj_t self_in, mp_obj_t font, mp_obj_t size);
|
||||
extern mp_obj_t VECTOR_set_font_size(mp_obj_t self_in, mp_obj_t size);
|
||||
extern mp_obj_t VECTOR_set_antialiasing(mp_obj_t self_in, mp_obj_t aa);
|
||||
extern mp_obj_t VECTOR_set_antialiasing(mp_obj_t self_in, mp_obj_t aa);
|
||||
|
||||
extern mp_obj_t VECTOR_draw(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t VECTOR_rotate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t VECTOR_translate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
Ładowanie…
Reference in New Issue