From 1cce542cd566d859ecec3386bf8e19be1626f1d7 Mon Sep 17 00:00:00 2001 From: Gabor Date: Fri, 17 Feb 2017 11:29:17 +0100 Subject: [PATCH] lv_draw: triangle draw added for experimental usage --- lv_draw/lv_draw.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++ lv_draw/lv_draw.h | 13 +++++ 2 files changed, 149 insertions(+) diff --git a/lv_draw/lv_draw.c b/lv_draw/lv_draw.c index 8734b4638..c82d131df 100644 --- a/lv_draw/lv_draw.c +++ b/lv_draw/lv_draw.c @@ -48,6 +48,11 @@ static void lv_draw_rect_border_corner(const area_t * cords_p, const area_t * ma static uint16_t lv_draw_rect_radius_corr(uint16_t r, cord_t w, cord_t h); #endif /*USE_LV_RECT != 0*/ + +#if USE_LV_TRIANGLE != 0 +static void point_swap(point_t * p1, point_t * p2); +#endif + /********************** * STATIC VARIABLES **********************/ @@ -115,6 +120,115 @@ void lv_draw_rect(const area_t * cords_p, const area_t * mask_p, } #endif /*USE_LV_RECT != 0*/ +#if USE_LV_TRIANGLE != 0 +/** + * + * @param points pointer to an array with 3 points + * @param mask_p the triangle will be drawn only in this mask + * @param color color of the triangle + */ +void lv_draw_triangle(const point_t * points, const area_t * mask_p, color_t color) +{ + point_t tri[3]; + + memcpy(tri, points, sizeof(tri)); + + /*Sort the vertices according to their y coordinate (0: y max, 1: y mid, 2:y min)*/ + if(tri[1].y < tri[0].y) point_swap(&tri[1], &tri[0]); + if(tri[2].y < tri[1].y) point_swap(&tri[2], &tri[1]); + if(tri[1].y < tri[0].y) point_swap(&tri[1], &tri[0]); + + /*Return is the triangle is degenerated*/ + if(tri[0].x == tri[1].x && tri[0].y == tri[1].y) return; + if(tri[1].x == tri[2].x && tri[1].y == tri[2].y) return; + if(tri[0].x == tri[2].x && tri[0].y == tri[2].y) return; + + if(tri[0].x == tri[1].x && tri[1].x == tri[2].x) return; + if(tri[0].y == tri[1].y && tri[1].y == tri[2].y) return; + + /*Draw the triangle*/ + point_t edge1; + cord_t dx1 = MATH_ABS(tri[0].x - tri[1].x); + cord_t sx1 = tri[0].x < tri[1].x ? 1 : -1; + cord_t dy1 = MATH_ABS(tri[0].y - tri[1].y); + cord_t sy1 = tri[0].y < tri[1].y ? 1 : -1; + cord_t err1 = (dx1 > dy1 ? dx1 : -dy1) / 2; + cord_t err_tmp1; + + point_t edge2; + cord_t dx2 = MATH_ABS(tri[0].x - tri[2].x); + cord_t sx2 = tri[0].x < tri[2].x ? 1 : -1; + cord_t dy2 = MATH_ABS(tri[0].y - tri[2].y); + cord_t sy2 = tri[0].y < tri[2].y ? 1 : -1; + cord_t err2 = (dx1 > dy2 ? dx2 : -dy2) / 2; + cord_t err_tmp2; + + cord_t y1_tmp; + cord_t y2_tmp; + + edge1.x = tri[0].x; + edge1.y = tri[0].y; + edge2.x = tri[0].x; + edge2.y = tri[0].y; + area_t act_area; + area_t draw_area; + + while(1) { + act_area.x1 = edge1.x; + act_area.x2 = edge2.x ; + act_area.y1 = edge1.y; + act_area.y2 = edge2.y ; + + + draw_area.x1 = MATH_MIN(act_area.x1, act_area.x2); + draw_area.x2 = MATH_MAX(act_area.x1, act_area.x2); + draw_area.y1 = MATH_MIN(act_area.y1, act_area.y2); + draw_area.y2 = MATH_MAX(act_area.y1, act_area.y2); + draw_area.x2--; /*Do not draw most right pixel because it will be drawn by the adjacent triangle*/ + fill_fp(&draw_area, mask_p, color, OPA_50); + + /*Calc. the next point of edge1*/ + y1_tmp = edge1.y; + do { + if (edge1.x == tri[1].x && edge1.y == tri[1].y) { + + dx1 = MATH_ABS(tri[1].x - tri[2].x); + sx1 = tri[1].x < tri[2].x ? 1 : -1; + dy1 = MATH_ABS(tri[1].y - tri[2].y); + sy1 = tri[1].y < tri[2].y ? 1 : -1; + err1 = (dx1 > dy1 ? dx1 : -dy1) / 2; + } + else if (edge1.x == tri[2].x && edge1.y == tri[2].y) return; + err_tmp1 = err1; + if (err_tmp1 >-dx1) { + err1 -= dy1; + edge1.x += sx1; + } + if (err_tmp1 < dy1) { + err1 += dx1; + edge1.y += sy1; + } + } while(edge1.y == y1_tmp); + + /*Calc. the next point of edge2*/ + y2_tmp = edge2.y; + do { + if (edge2.x == tri[2].x && edge2.y == tri[2].y) return; + err_tmp2 = err2; + if (err_tmp2 > -dx2) { + err2 -= dy2; + edge2.x += sx2; + } + if (err_tmp2 < dy2) { + err2 += dx2; + edge2.y += sy2; + } + } while(edge2.y == y2_tmp); + } +} + +#endif + #if USE_LV_LABEL != 0 /** * Write a text @@ -935,3 +1049,25 @@ static uint16_t lv_draw_rect_radius_corr(uint16_t r, cord_t w, cord_t h) #endif /*USE_LV_RECT != 0*/ + +#if USE_LV_TRIANGLE != 0 +/** + * Swap two points + * p1 pointer to the first point + * p2 pointer to the second point + */ +static void point_swap(point_t * p1, point_t * p2) +{ + point_t tmp; + tmp.x = p1->x; + tmp.y = p1->y; + + p1->x = p2->x; + p1->y = p2->y; + + p2->x = tmp.x; + p2->y = tmp.y; + +} + +#endif diff --git a/lv_draw/lv_draw.h b/lv_draw/lv_draw.h index 088099755..728e9213a 100644 --- a/lv_draw/lv_draw.h +++ b/lv_draw/lv_draw.h @@ -42,6 +42,19 @@ void lv_draw_rect(const area_t * cords_p, const area_t * mask_p, const lv_rects_t * rects_p, opa_t opa); #endif + +/*Experimental use for 3D modeling*/ +#define USE_LV_TRIANGLE 0 +#if USE_LV_TRIANGLE != 0 +/** + * + * @param points pointer to an array with 3 points + * @param mask_p the triangle will be drawn only in this mask + * @param color color of the triangle + */ +void lv_draw_triangle(const point_t * points, const area_t * mask_p, color_t color); +#endif + /** * Write a text * @param cords_p coordinates of the label