Created
August 9, 2021 18:17
-
-
Save FoamyGuy/03dcfe6abce6f240f77d3f86f30eb902 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Gauge | |
Turning the arc function into a guage that starts at angle 315 degrees | |
and sweeps 270 degrees | |
""" | |
import math | |
import displayio | |
import bitmaptools | |
import time | |
class Gauge(displayio.TileGrid): | |
def __init__(self, xcenter, ycenter, radius, width, progress, lineColor, progressColor, backgroundColor): | |
self.xcenter = xcenter | |
self.ycenter = ycenter | |
self.radius = radius | |
self.width = width | |
self._progress = progress | |
tileGridWidth = 2 * self.radius + 1 | |
tileGridHeight = math.ceil(0.71 * self.radius) + self.radius + 1 | |
self._bitmap = displayio.Bitmap(tileGridWidth, tileGridHeight, 3) | |
self._palette = displayio.Palette(3) | |
self._palette[0] = backgroundColor | |
self._palette[1] = lineColor | |
self._palette[2] = progressColor | |
x_offset = self.xcenter - self.radius + 1 | |
y_offset = self.ycenter - self.radius + 1 | |
super().__init__( | |
self._bitmap, pixel_shader=self._palette, x=x_offset, y=y_offset | |
) | |
self._draw_progress() | |
def _boundaryFill4(self, px, py, fc, | |
bc): # px & py = x, y coord to start fill, fc = fill color, bc = background color | |
fillArea = [[px, py]] | |
while len(fillArea) > 0: | |
x, y = fillArea.pop() | |
if self._bitmap[x, y] != bc: | |
continue | |
self._bitmap[x, y] = fc | |
fillArea.append((x + 1, y)) | |
fillArea.append((x - 1, y)) | |
fillArea.append((x, y + 1)) | |
fillArea.append((x, y - 1)) | |
def _bLine(self, x0, y0, x1, y1, color): # function to draw a line | |
if x0 == x1: | |
if y0 > y1: | |
y0, y1 = y1, y0 | |
for h in range(y0, y1 + 1): | |
self._bitmap[x0, h] = color | |
elif y0 == y1: | |
if x0 > x1: | |
x0, x1 = x1, x0 | |
for w in range(x0, x1 + 1): | |
self._bitmap[w, y0] = color | |
else: | |
steep = abs(y1 - y0) > abs(x1 - x0) | |
if steep: | |
x0, y0 = y0, x0 | |
x1, y1 = y1, x1 | |
if x0 > x1: | |
x0, x1 = x1, x0 | |
y0, y1 = y1, y0 | |
dx = x1 - x0 | |
dy = abs(y1 - y0) | |
err = dx / 2 | |
if y0 < y1: | |
ystep = 1 | |
else: | |
ystep = -1 | |
for x in range(x0, x1 + 1): | |
if steep: | |
self._bitmap[y0, x] = color | |
else: | |
self._bitmap[x, y0] = color | |
err -= dy | |
if err < 0: | |
y0 += ystep | |
err += dx | |
def _draw_progress(self): | |
# empty the bitmap | |
#self._bitmap.fill(0) | |
x = 0 | |
y = self.radius | |
d = 3 - 2 * self.radius | |
# Bresenham's circle algorithm | |
# Outer arc | |
while x <= y: | |
self._bitmap[-x + self.radius, -y + self.radius] = 1 | |
self._bitmap[x + self.radius, -y + self.radius] = 1 | |
self._bitmap[y + self.radius, x + self.radius] = 1 | |
self._bitmap[-y + self.radius, x + self.radius] = 1 | |
self._bitmap[-y + self.radius, -x + self.radius] = 1 | |
self._bitmap[y + self.radius, -x + self.radius] = 1 | |
if d <= 0: | |
d = d + (4 * x) + 6 | |
else: | |
d = d + 4 * (x - y) + 10 | |
y = y - 1 | |
x = x + 1 | |
self.yend = self.xend = x - 1 | |
# Inner Arc | |
x = 0 | |
y = self.radius - self.width + 1 | |
d = 3 - 2 * (y) | |
while x <= y: | |
self._bitmap[-x + self.radius, -y + self.radius] = 1 | |
self._bitmap[x + self.radius, -y + self.radius] = 1 | |
self._bitmap[y + self.radius, x + self.radius] = 1 | |
self._bitmap[-y + self.radius, x + self.radius] = 1 | |
self._bitmap[-y + self.radius, -x + self.radius] = 1 | |
self._bitmap[y + self.radius, -x + self.radius] = 1 | |
if d <= 0: | |
d = d + (4 * x) + 6 | |
else: | |
d = d + 4 * (x - y) + 10 | |
y = y - 1 | |
x = x + 1 | |
self.yend2 = self.xend2 = x - 1 | |
# Connect inner and outer arc at endpoints | |
x = self.xend | |
for y in range(self.yend, self.yend2 - 1, -1): | |
self._bitmap[self.radius - x, self.radius + y] = 1 | |
self._bitmap[self.radius + x, self.radius + y] = 1 | |
x -= 1 | |
# Color in progress | |
#print("drawing progress: {}".format(self.progress)) | |
# Find progress point | |
prog = 315 - (self.progress * 270 / 100) # what percent of gauge in degrees to fill in | |
xs = self.radius + int(round(math.sin(math.radians(prog)) * (self.radius - 1), 0)) | |
ys = self.radius + int(round(math.cos(math.radians(prog)) * (self.radius - 1), 0)) | |
xe = self.radius + int(round(math.sin(math.radians(prog)) * (self.radius - self.width + 2), 0)) | |
ye = self.radius + int(round(math.cos(math.radians(prog)) * (self.radius - self.width + 2), 0)) | |
#print("{}, {}, {}, {}".format(xs, ys, xe, ye)) | |
if self.progress == 0: # Just draw the gauge | |
return | |
# Find a point just above the 0% progress line as a start point for the boundary fill | |
x = self.radius - ((int((self.xend - self.xend2) / 2) + 1) + self.xend2) | |
y = self.radius + ((int((self.yend - self.yend2) / 2) - 1) + self.yend2) | |
bitmaptools.paint_fill(self._bitmap, x, y, 0, 2) | |
#time.sleep(1) | |
#self._boundaryFill4(x, y, 0, 2) | |
# Draw end line for progress value | |
if self.progress != 100: # @ 100%, no need to draw end line | |
self._bLine(xs, ys, xe, ye, 2) | |
#print("{}, {}".format(x, y)) | |
#self._boundaryFill4(x, y, 2, 0) | |
before = time.monotonic() | |
bitmaptools.paint_fill(self._bitmap, x, y, 2, 0) | |
#print("took {} to fill".format(time.monotonic()- before)) | |
@property | |
def progress(self): | |
return self._progress | |
@progress.setter | |
def progress(self, new_progress): | |
#print("updating progress") | |
self._progress = new_progress | |
self._draw_progress() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment