aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Bodenmann <info@b-electronics.ch>2016-12-11 17:40:38 +0100
committerGogs <gogs@fake.local>2016-12-11 17:40:38 +0100
commit81fc34801dc619981addef9dae1aa5b34fe8a4b3 (patch)
treecefc47086fcb6feff44390b28ecf71c6314b64b2
parente927bff0890b6b2a1f5a223f804aa1de71f091a6 (diff)
parent0b4b99163b018a7ffb96bd8c93b465f776a27e05 (diff)
downloaduGFX-81fc34801dc619981addef9dae1aa5b34fe8a4b3.tar.gz
uGFX-81fc34801dc619981addef9dae1aa5b34fe8a4b3.tar.bz2
uGFX-81fc34801dc619981addef9dae1aa5b34fe8a4b3.zip
Merge branch 'master' of CorentinB/uGFX into master
-rw-r--r--src/gdisp/gdisp.c119
-rw-r--r--src/gdisp/gdisp.h25
2 files changed, 144 insertions, 0 deletions
diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c
index e03971a4..11d5c6c9 100644
--- a/src/gdisp/gdisp.c
+++ b/src/gdisp/gdisp.c
@@ -1912,6 +1912,125 @@ 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 <math.h>
+ #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
+ 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
+ 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
+ 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);
+ 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){
+ g->p.color = color;
+ //Draw points by symmetry
+ 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 = 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 = 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 = 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
+ 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;
coord_t sy, ey;
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
@@ -712,6 +712,31 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#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
*