From 68f0c20fd54f299bff1e09aa2de9d518a5f38304 Mon Sep 17 00:00:00 2001 From: ben-zen Date: Tue, 23 Sep 2014 21:14:20 -0700 Subject: [PATCH 1/2] Replaced body of previous circleFill() method in the MicroView class, in preparation for a pull request. --- MicroView.cpp | 92 +++++++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 39 deletions(-) diff --git a/MicroView.cpp b/MicroView.cpp index cc3db1c..79e8ba0 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -606,46 +606,60 @@ void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius) { Draw filled circle with radius using color and mode at x,y of the screen buffer. */ -void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) { - // Don't bother trying to draw something totally offscreen - if (x0 - radius >= LCDWIDTH || y0 - radius >= LCDHEIGHT) { - return; - } - - // High-level algorithm overview: - // Scan horizontally from left to right, then top to bottom, checking if each pixel - // is within the circle. We use uint16_t's because even the small screen squares beyond 8 bits. - uint16_t radiusSq = radius * radius; - - // Optimization: define the start and end onscreen - uint16_t xStart = max(0, x0-radius); - uint16_t xEnd = min(LCDWIDTH-1, x0+radius); - uint16_t yStart = max(0, y0-radius); - uint16_t yEnd = min(LCDHEIGHT-1, y0+radius); - - // scan horizontally... - for (uint16_t x = xStart; x <= xEnd; ++x) { - // Optimization: Record where if we have intersected the circle on this vertical - // scan. Once we have intersected, then don't intersect anymore, don't bother - // drawing; we've exited the circle. - bool intersected = false; - - // Optimization: relative x squared only changes with the outer loop/the horizontal scan. - int16_t rx2 = (x-x0) * (x-x0); - - // Scan vertically... - for (uint16_t y = yStart; y <= yEnd; ++y) { - int16_t ry2 = (y-y0) * (y-y0); - if (rx2 + ry2 <= radiusSq) { - pixel(x, y, color, mode); - intersected = true; - } - else if (intersected) { - // We've left the circle. Move on to the next horizontal scan line. - break; - } - } +void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t +color, uint8_t mode) { + int8_t x = radius; + int8_t y = 0; + int8_t radiusError = 1 - x; + int8_t y_last = y0 + x; + int8_t y_low; + int8_t x_alt; + int8_t x_alt_max; + while (x >= y) { + pixel(x + x0, y + y0, color, mode); + x_alt = (x0 - x); + x_alt_max = x0 + x; + while (x_alt < x_alt_max) { // Fill the line between these two points + pixel(x_alt, y + y0, color, mode); + x_alt++; + } + if (y != x) { + pixel(y + x0, x + y0, color, mode); + pixel(y + x0, y0 - x, color, mode); + } + if (y != 0) { + pixel(x + x0, y0 - y, color, mode); + x_alt = (x0 - x); + x_alt_max = x0 + x; + while (x_alt < x_alt_max) { + pixel(x_alt, y0 - y, color, mode); + x_alt++; + } + if (y != x) { + pixel(x0 - y, x + y0, color, mode); + pixel(x0 - y, y0 - x, color, mode); + if (y_last > y0 + x) { + x_alt = x0 - y + 1; + x_alt_max = x0 + y; + y_last = y0 + x; + y_low = y0 - x; + while (x_alt < x_alt_max) { + pixel(x_alt, y_last, color, mode); + pixel(x_alt, y_low, color, mode); + x_alt++; + } } + } + } + y++; + if (radiusError<0) { + radiusError += 2 * y + 1; + } + else { + x--; + radiusError += 2 * (y - x + 1); + } + } } /** \brief Get LCD height. From 8ae691c4c29c0adf397e4eddfba41769bbf8eb00 Mon Sep 17 00:00:00 2001 From: ben-zen Date: Tue, 23 Sep 2014 21:39:06 -0700 Subject: [PATCH 2/2] Fixed whitespace before pull request. --- MicroView.cpp | 105 +++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 52 deletions(-) diff --git a/MicroView.cpp b/MicroView.cpp index 394ef00..7b6e53c 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -604,62 +604,63 @@ void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius) { /** \brief Draw filled circle with color and mode. - Draw filled circle with radius using color and mode at x,y of the screen buffer. + Draw filled circle with radius using color and mode at x,y of the screen + buffer. Uses the Bresenham circle algorithm with a few modifications to + paint the circle without overlapping draw operations. */ void MicroView::circleFill(uint8_t x0, uint8_t y0, uint8_t radius, uint8_t color, uint8_t mode) { - int8_t x = radius; - int8_t y = 0; - int8_t radiusError = 1 - x; - int8_t y_last = y0 + x; - int8_t y_low; - int8_t x_alt; - int8_t x_alt_max; - while (x >= y) { - pixel(x + x0, y + y0, color, mode); - x_alt = (x0 - x); - x_alt_max = x0 + x; - while (x_alt < x_alt_max) { // Fill the line between these two points - pixel(x_alt, y + y0, color, mode); - x_alt++; - } - if (y != x) { - pixel(y + x0, x + y0, color, mode); - pixel(y + x0, y0 - x, color, mode); - } - if (y != 0) { - pixel(x + x0, y0 - y, color, mode); - x_alt = (x0 - x); - x_alt_max = x0 + x; - while (x_alt < x_alt_max) { - pixel(x_alt, y0 - y, color, mode); - x_alt++; - } - if (y != x) { - pixel(x0 - y, x + y0, color, mode); - pixel(x0 - y, y0 - x, color, mode); - if (y_last > y0 + x) { - x_alt = x0 - y + 1; - x_alt_max = x0 + y; - y_last = y0 + x; - y_low = y0 - x; - while (x_alt < x_alt_max) { - pixel(x_alt, y_last, color, mode); - pixel(x_alt, y_low, color, mode); - x_alt++; - } + int8_t x = radius; + int8_t y = 0; + int8_t radiusError = 1 - x; + int8_t y_last = y0 + x; + int8_t y_low; + int8_t x_alt; + int8_t x_alt_max; + while (x >= y) { + pixel(x + x0, y + y0, color, mode); + x_alt = (x0 - x); + x_alt_max = x0 + x; + while (x_alt < x_alt_max) { + pixel(x_alt, y + y0, color, mode); + x_alt++; + } + if (y != x) { + pixel(y + x0, x + y0, color, mode); + pixel(y + x0, y0 - x, color, mode); + } + if (y != 0) { + pixel(x + x0, y0 - y, color, mode); + x_alt = (x0 - x); + x_alt_max = x0 + x; + while (x_alt < x_alt_max) { + pixel(x_alt, y0 - y, color, mode); + x_alt++; + } + if (y != x) { + pixel(x0 - y, x + y0, color, mode); + pixel(x0 - y, y0 - x, color, mode); + if (y_last > y0 + x) { + x_alt = x0 - y + 1; + x_alt_max = x0 + y; + y_last = y0 + x; + y_low = y0 - x; + while (x_alt < x_alt_max) { + pixel(x_alt, y_last, color, mode); + pixel(x_alt, y_low, color, mode); + x_alt++; + } + } + } + } + y++; + if (radiusError<0) { + radiusError += 2 * y + 1; + } else { + x--; + radiusError += 2 * (y - x + 1); + } } - } - } - y++; - if (radiusError<0) { - radiusError += 2 * y + 1; - } - else { - x--; - radiusError += 2 * (y - x + 1); - } - } } /** \brief Get LCD height.