#include "shared-module/vectorio/__init__.h"#include "shared-bindings/vectorio/Polygon.h"#include "shared-module/displayio/area.h"#include "py/runtime.h"#include "py/gc.h"#include "stdlib.h"#include <stdio.h>#define VECTORIO_POLYGON_DEBUG(...) (void)0// #define VECTORIO_POLYGON_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__)// Converts a list of points tuples to a flat list of ints for speedier internal use.// Also validates the points.static void _clobber_points_list(vectorio_polygon_t *self, mp_obj_t points_tuple_list) {size_t len = 0;mp_obj_t *items;mp_obj_list_get(points_tuple_list, &len, &items);VECTORIO_POLYGON_DEBUG("polygon_points_list len: %d\n", len);if ( len < 3 ) {mp_raise_TypeError_varg(translate("Polygon needs at least 3 points"));}if ( self->len < 2*len ) {if ( self->points_list != NULL ) {gc_free( self->points_list );}self->points_list = gc_alloc( 2 * len * sizeof(int), false, false );}self->len = 2*len;for ( size_t i = 0; i < len; ++i) {size_t tuple_len = 0;mp_obj_t *tuple_items;mp_obj_tuple_get(items[i], &tuple_len, &tuple_items);if (tuple_len != 2) {mp_raise_ValueError_varg(translate("%q must be a tuple of length 2"), MP_QSTR_point);}if ( !mp_obj_get_int_maybe(tuple_items[ 0 ], &self->points_list[2*i ])|| !mp_obj_get_int_maybe(tuple_items[ 1 ], &self->points_list[2*i + 1])) {self->len = 0;gc_free( self->points_list );self->points_list = NULL;mp_raise_ValueError_varg(translate("unsupported %q type"), MP_QSTR_point);}}}void common_hal_vectorio_polygon_construct(vectorio_polygon_t *self, mp_obj_t points_list) {VECTORIO_POLYGON_DEBUG("%p polygon_construct\n", self);self->points_list = NULL;self->len = 0;self->on_dirty.obj = NULL;_clobber_points_list( self, points_list );}mp_obj_t common_hal_vectorio_polygon_get_points(vectorio_polygon_t *self) {return self->points_list;}void common_hal_vectorio_polygon_set_points(vectorio_polygon_t *self, mp_obj_t points_list) {_clobber_points_list( self, points_list );if (self->on_dirty.obj != NULL) {self->on_dirty.event(self->on_dirty.obj);}}void common_hal_vectorio_polygon_set_on_dirty(vectorio_polygon_t *self, vectorio_event_t notification) {if ( self->on_dirty.obj != NULL ) {mp_raise_TypeError(translate("polygon can only be registered in one parent"));}self->on_dirty = notification;}void common_hal_vectorio_polygon_get_area(void *polygon, displayio_area_t *area) {vectorio_polygon_t *self = polygon;area->x1 = SHRT_MAX;area->y1 = SHRT_MAX;area->x2 = SHRT_MIN;area->y2 = SHRT_MIN;for (size_t i=0; i < self->len; ++i) {int x = self->points_list[i];++i;int y = self->points_list[i];if (x <= area->x1) area->x1 = x-1;if (y <= area->y1) area->y1 = y-1;if (x >= area->x2) area->x2 = x+1;if (y >= area->y2) area->y2 = y+1;}}// <0 if the point is to the left of the line vector// 0 if the point is on the line// >0 if the point is to the right of the line vector__attribute__((always_inline)) static inline int line_side( mp_int_t x1, mp_int_t y1, mp_int_t x2, mp_int_t y2, int16_t px, int16_t py ) {return (px - x1) * (y2 - y1)- (py - y1) * (x2 - x1);}uint32_t common_hal_vectorio_polygon_get_pixel(void *obj, int16_t x, int16_t y) {VECTORIO_POLYGON_DEBUG("%p polygon get_pixel %d, %d\n", obj, x, y);vectorio_polygon_t *self = obj;if (self->len == 0) {return 0;}int winding_number = 0;int x1 = self->points_list[0];int y1 = self->points_list[1];for (size_t i=2; i <= self->len + 1; ++i) {VECTORIO_POLYGON_DEBUG(" {(%3d, %3d),", x1, y1);int x2 = self->points_list[i % self->len];++i;int y2 = self->points_list[i % self->len];VECTORIO_POLYGON_DEBUG(" (%3d, %3d)}\n", x2, y2);if ( y1 <= y ) {if ( y2 > y && line_side(x1, y1, x2, y2, x, y) > 0 ) {// Wind up, point is to the right of the edge vector++winding_number;VECTORIO_POLYGON_DEBUG(" wind:%2d winding_number:%2d\n", 1, winding_number);}} else if ( y2 <= y && line_side(x1, y1, x2, y2, x, y) < 0 ) {// Wind down, point is to the left of the edge vector--winding_number;VECTORIO_POLYGON_DEBUG(" wind:%2d winding_number:%2d\n", -1, winding_number);}x1 = x2;y1 = y2;}return winding_number == 0 ? 0 : 1;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。