From 2bcb2155caba059ae184ff7725e2a26d7c012067 Mon Sep 17 00:00:00 2001 From: Corentin Barman Date: Sun, 27 Nov 2016 19:06:53 +0100 Subject: [PATCH 1/2] Added a function to draw thick arcs --- src/gdisp/gdisp.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ src/gdisp/gdisp.h | 25 ++++++++++++ 2 files changed, 122 insertions(+) diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index e03971a4..e3056ee6 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -1911,6 +1911,103 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c } #endif +#if GDISP_NEED_ARC + #if (!GMISC_NEED_FIXEDTRIG && !GMISC_NEED_FASTTRIG) || !GFX_USE_GMISC + #include + #endif + + void gdispGDrawThickArc(GDisplay *g, coord_t xc, coord_t yc, coord_t radiusStart, coord_t radiusEnd, coord_t start, coord_t end, color_t color) { + coord_t x, y, d, r; + coord_t startTan, endTan, curangle; + coord_t precision = 512; + + // Normalize the angles + if (start < 0) + start -= (start/360-1)*360; + else if (start >= 360) + start %= 360; + if (end < 0) + end -= (end/360-1)*360; + else if (end >= 360) + end %= 360; + + #if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG + startTan = ffsin(start % 45) * precision / ffcos(start % 45) + start / 45 * precision; + endTan = ffsin(end % 45) * precision / ffcos(end % 45) + end / 45 * precision; + #elif GFX_USE_GMISC && GMISC_NEED_FASTTRIG + startTan = fsin(start % 45) * precision / fcos(start % 45) + start / 45 * precision; + endTan = fsin(end % 45) * precision / fcos(end % 45) + end / 45 * precision; + #else + startTan = (tan((start % 45)*GFX_PI/180) + start / 45)* precision; + endTan = (tan((end % 45) *GFX_PI/180) + end / 45) * precision; + #endif + + MUTEX_ENTER(g); + g->p.color = color; + + //Draw concentric circles using Andres algorithm + for(r = radiusStart; r <= radiusEnd; r++) + { + x = 0; + y = r; + d = r - 1; + + while (y >= x){ + + //approximate tan + curangle = x*precision/y; + + if(end > start){ + //Draw points by symmetry + if(curangle > startTan && curangle < endTan){g->p.y = xc - x; g->p.x = yc + y; drawpixel_clip(g);} + if(curangle + 2*precision > startTan && curangle + 2*precision < endTan){g->p.y = xc - y; g->p.x = yc - x; drawpixel_clip(g);} + if(curangle + 4*precision > startTan && curangle + 4*precision < endTan){g->p.y = xc + x; g->p.x = yc - y; drawpixel_clip(g);} + if(curangle + 6*precision > startTan && curangle + 6*precision < endTan){g->p.y = xc + y; g->p.x = yc + x; drawpixel_clip(g);} + + curangle = precision - curangle; + + if(curangle + precision > startTan && curangle + precision < endTan){g->p.y = xc - y; g->p.x = yc + x; drawpixel_clip(g);} + if(curangle + 3*precision > startTan && curangle + 3*precision < endTan){g->p.y = xc - x; g->p.x = yc - y; drawpixel_clip(g);} + if(curangle + 5*precision > startTan && curangle + 5*precision < endTan){g->p.y = xc + y; g->p.x = yc - x; drawpixel_clip(g);} + if(curangle + 7*precision > startTan && curangle + 7*precision < endTan){g->p.y = xc + x; g->p.x = yc + y; drawpixel_clip(g);} + } + else{ + //Draw points by symmetry + if(curangle > startTan || curangle < endTan){g->p.y = xc - x; g->p.x = yc + y; drawpixel_clip(g);} + if(curangle + 2*precision > startTan || curangle + 2*precision < endTan){g->p.y = xc - y; g->p.x = yc - x; drawpixel_clip(g);} + if(curangle + 4*precision > startTan || curangle + 4*precision < endTan){g->p.y = xc + x; g->p.x = yc - y; drawpixel_clip(g);} + if(curangle + 6*precision > startTan || curangle + 6*precision < endTan){g->p.y = xc + y; g->p.x = yc + x; drawpixel_clip(g);} + + curangle = precision - curangle; + + if(curangle + precision > startTan || curangle + precision < endTan){g->p.y = xc - y; g->p.x = yc + x; drawpixel_clip(g);} + if(curangle + 3*precision > startTan || curangle + 3*precision < endTan){g->p.y = xc - x; g->p.x = yc - y; drawpixel_clip(g);} + if(curangle + 5*precision > startTan || curangle + 5*precision < endTan){g->p.y = xc + y; g->p.x = yc - x; drawpixel_clip(g);} + if(curangle + 7*precision > startTan || curangle + 7*precision < endTan){g->p.y = xc + x; g->p.x = yc + y; drawpixel_clip(g);} + } + + //Compute next point + if (d >= 2 * x){ + d -= 2 * x + 1; + x++; + } + else if (d < 2 * (r - y)){ + d += 2 * y - 1; + y--; + } + else{ + d += 2 * (y - x - 1); + y--; + x++; + } + } + } + + autoflush(g); + MUTEX_EXIT(g); + } +#endif + #if GDISP_NEED_ARC void gdispGFillArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { coord_t a, b, P; diff --git a/src/gdisp/gdisp.h b/src/gdisp/gdisp.h index 7878233e..3185f82f 100644 --- a/src/gdisp/gdisp.h +++ b/src/gdisp/gdisp.h @@ -711,6 +711,31 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co void gdispGDrawArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color); #define gdispDrawArc(x,y,r,s,e,c) gdispGDrawArc(GDISP,x,y,r,s,e,c) + /* + * @brief Draw a thick arc. + * @pre GDISP_NEED_ARC must be TRUE in your gfxconf.h + * + * @param[in] g The display to use + * @param[in] xc,yc The center point + * @param[in] startradius The inner radius of the thick arc + * @param[in] endradius The outer radius of the thick arc + * @param[in] startangle The start angle (0 to 360) + * @param[in] endangle The end angle (0 to 360) + * @param[in] color The color of the arc + * + * @note This routine requires trig support. It can either come from your C runtime library + * cos() and sin() which requires floating point support (and is slow), or you can define GFX_USE_GMISC + * and either GMISC_NEED_FIXEDTRIG or GMISC_NEED_FASTTRIG. + * GMISC_NEED_FASTTRIG uses table based floating point trig operations. + * GMISC_NEED_FIXEDTRIG uses fixed point integer trig operations. + * Note accuracy on both the table based options are more than adequate for the one degree + * resolution provided by these arc routines. Both are much faster than your C runtime library. + * + * @api + */ + void gdispGDrawThickArc(GDisplay *g, coord_t xc, coord_t yc, coord_t startradius, coord_t endradius, coord_t startangle, coord_t endangle, color_t color); + #define gdispDrawThickArc(x,y,rs,re,s,e,c) gdispGDrawThickArc(GDISP,x,y,rs,re,s,e,c) + /* * @brief Draw a filled arc. * @pre GDISP_NEED_ARC must be TRUE in your gfxconf.h From 0b4b99163b018a7ffb96bd8c93b465f776a27e05 Mon Sep 17 00:00:00 2001 From: Corentin Barman Date: Sun, 11 Dec 2016 15:46:55 +0100 Subject: [PATCH 2/2] Fixed drawThickArc function --- src/gdisp/gdisp.c | 68 +++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index e3056ee6..11d5c6c9 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -1932,14 +1932,35 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c end %= 360; #if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG - startTan = ffsin(start % 45) * precision / ffcos(start % 45) + start / 45 * precision; - endTan = ffsin(end % 45) * precision / ffcos(end % 45) + end / 45 * precision; + if((start / 45) % 2 == 0){ + startTan = ffsin(start % 45) * precision / ffcos(start % 45) + start / 45 * precision;} + else{ + startTan = ffsin(start % 45 - 45) * precision / ffcos(start % 45 - 45) + start / 45 * precision + precision;} + + if((end / 45) % 2 == 0){ + endTan = ffsin(end % 45) * precision / ffcos(end % 45) + end / 45 * precision;} + else{ + endTan = ffsin(end % 45 - 45) * precision / ffcos(end % 45 - 45) + end / 45 * precision + precision;} #elif GFX_USE_GMISC && GMISC_NEED_FASTTRIG - startTan = fsin(start % 45) * precision / fcos(start % 45) + start / 45 * precision; - endTan = fsin(end % 45) * precision / fcos(end % 45) + end / 45 * precision; + if((start / 45) % 2 == 0){ + startTan = fsin(start % 45) * precision / fcos(start % 45) + start / 45 * precision;} + else{ + startTan = fsin(start % 45 - 45) * precision / fcos(start % 45 - 45) + start / 45 * precision + precision;} + + if((end / 45) % 2 == 0){ + endTan = fsin(end % 45) * precision / fcos(end % 45) + end / 45 * precision;} + else{ + endTan = fsin(end % 45 - 45) * precision / fcos(end % 45 - 45) + end / 45 * precision + precision;} #else - startTan = (tan((start % 45)*GFX_PI/180) + start / 45)* precision; - endTan = (tan((end % 45) *GFX_PI/180) + end / 45) * precision; + if((start / 45) % 2 == 0){ + startTan = (tan((start % 45)*GFX_PI/180) + start / 45)* precision;} + else{ + startTan = (1+tan((start % 45 - 45)*GFX_PI/180) + start / 45)* precision;} + + if((end / 45) % 2 == 0){ + endTan = (tan((end % 45) *GFX_PI/180) + end / 45) * precision;} + else{ + endTan = (1+tan((end % 45 - 45) *GFX_PI/180) + end / 45) * precision;} #endif MUTEX_ENTER(g); @@ -1953,37 +1974,38 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c d = r - 1; while (y >= x){ - //approximate tan curangle = x*precision/y; if(end > start){ + g->p.color = color; //Draw points by symmetry - if(curangle > startTan && curangle < endTan){g->p.y = xc - x; g->p.x = yc + y; drawpixel_clip(g);} - if(curangle + 2*precision > startTan && curangle + 2*precision < endTan){g->p.y = xc - y; g->p.x = yc - x; drawpixel_clip(g);} - if(curangle + 4*precision > startTan && curangle + 4*precision < endTan){g->p.y = xc + x; g->p.x = yc - y; drawpixel_clip(g);} - if(curangle + 6*precision > startTan && curangle + 6*precision < endTan){g->p.y = xc + y; g->p.x = yc + x; drawpixel_clip(g);} + if(curangle > startTan && curangle < endTan){g->p.y = yc - x; g->p.x = xc + y; drawpixel_clip(g);} + if(curangle + 2*precision > startTan && curangle + 2*precision < endTan){g->p.y = yc - y; g->p.x = xc - x; drawpixel_clip(g);} + if(curangle + 4*precision > startTan && curangle + 4*precision < endTan){g->p.y = yc + x; g->p.x = xc - y; drawpixel_clip(g);} + if(curangle + 6*precision > startTan && curangle + 6*precision < endTan){g->p.y = yc + y; g->p.x = xc + x; drawpixel_clip(g);} curangle = precision - curangle; - if(curangle + precision > startTan && curangle + precision < endTan){g->p.y = xc - y; g->p.x = yc + x; drawpixel_clip(g);} - if(curangle + 3*precision > startTan && curangle + 3*precision < endTan){g->p.y = xc - x; g->p.x = yc - y; drawpixel_clip(g);} - if(curangle + 5*precision > startTan && curangle + 5*precision < endTan){g->p.y = xc + y; g->p.x = yc - x; drawpixel_clip(g);} - if(curangle + 7*precision > startTan && curangle + 7*precision < endTan){g->p.y = xc + x; g->p.x = yc + y; drawpixel_clip(g);} + if(curangle + precision > startTan && curangle + precision < endTan){g->p.y = yc - y; g->p.x = xc + x; drawpixel_clip(g);} + if(curangle + 3*precision > startTan && curangle + 3*precision < endTan){g->p.y = yc - x; g->p.x = xc - y; drawpixel_clip(g);} + if(curangle + 5*precision > startTan && curangle + 5*precision < endTan){g->p.y = yc + y; g->p.x = xc - x; drawpixel_clip(g);} + if(curangle + 7*precision > startTan && curangle + 7*precision < endTan){g->p.y = yc + x; g->p.x = xc + y; drawpixel_clip(g);} + } else{ //Draw points by symmetry - if(curangle > startTan || curangle < endTan){g->p.y = xc - x; g->p.x = yc + y; drawpixel_clip(g);} - if(curangle + 2*precision > startTan || curangle + 2*precision < endTan){g->p.y = xc - y; g->p.x = yc - x; drawpixel_clip(g);} - if(curangle + 4*precision > startTan || curangle + 4*precision < endTan){g->p.y = xc + x; g->p.x = yc - y; drawpixel_clip(g);} - if(curangle + 6*precision > startTan || curangle + 6*precision < endTan){g->p.y = xc + y; g->p.x = yc + x; drawpixel_clip(g);} + if(curangle > startTan || curangle < endTan){g->p.y = yc - x; g->p.x = xc + y; drawpixel_clip(g);} + if(curangle + 2*precision > startTan || curangle + 2*precision < endTan){g->p.y = yc - y; g->p.x = xc - x; drawpixel_clip(g);} + if(curangle + 4*precision > startTan || curangle + 4*precision < endTan){g->p.y = yc + x; g->p.x = xc - y; drawpixel_clip(g);} + if(curangle + 6*precision > startTan || curangle + 6*precision < endTan){g->p.y = yc + y; g->p.x = xc + x; drawpixel_clip(g);} curangle = precision - curangle; - if(curangle + precision > startTan || curangle + precision < endTan){g->p.y = xc - y; g->p.x = yc + x; drawpixel_clip(g);} - if(curangle + 3*precision > startTan || curangle + 3*precision < endTan){g->p.y = xc - x; g->p.x = yc - y; drawpixel_clip(g);} - if(curangle + 5*precision > startTan || curangle + 5*precision < endTan){g->p.y = xc + y; g->p.x = yc - x; drawpixel_clip(g);} - if(curangle + 7*precision > startTan || curangle + 7*precision < endTan){g->p.y = xc + x; g->p.x = yc + y; drawpixel_clip(g);} + if(curangle + precision > startTan || curangle + precision < endTan){g->p.y = yc - y; g->p.x = xc + x; drawpixel_clip(g);} + if(curangle + 3*precision > startTan || curangle + 3*precision < endTan){g->p.y = yc - x; g->p.x = xc - y; drawpixel_clip(g);} + if(curangle + 5*precision > startTan || curangle + 5*precision < endTan){g->p.y = yc + y; g->p.x = xc - x; drawpixel_clip(g);} + if(curangle + 7*precision > startTan || curangle + 7*precision < endTan){g->p.y = yc + x; g->p.x = xc + y; drawpixel_clip(g);} } //Compute next point