from . layout import Layout
from . geometry.circle import (
make_circle_coord_map, calc_ring_steps, calc_ring_pixel_count,
make_circle_coord_map_positions)
from .. util import deprecated
[docs]class Circle(Layout):
CLONE_ATTRS = Layout.CLONE_ATTRS + (
'rings', 'pixels_per', 'maxAngleDiff', 'rotation', 'reverse_angle')
def __init__(self, drivers, rings=[], pixels_per=None,
maxAngleDiff=0, rotation=0, reverse_angle=False,
threadedUpdate=False, brightness=255, **kwargs):
super().__init__(drivers, threadedUpdate, brightness, **kwargs)
self.rings = rings
self.maxAngleDiff = maxAngleDiff
full_coords = False
for r in self.rings:
full_coords |= (len(r) > 2)
if not full_coords:
self.rings, self.ringSteps = make_circle_coord_map(
rings=self.rings, pixels_per=pixels_per)
else:
self.ringSteps = calc_ring_steps(self.rings)
self.ringCount = len(self.rings)
self.set_pixel_positions(make_circle_coord_map_positions(self.rings))
num = calc_ring_pixel_count(self.rings)
self.rotation = rotation
self.reverse_angle = reverse_angle
if self.numLEDs != num:
raise ValueError(
"Total ring LED count does not equal driver LED count!")
@property
def lastRing(self):
deprecated.deprecated('Circle.lastRing')
return self.ringCount - 1
@property
def shape(self):
"""Returns ``ringCount, ringSteps``."""
return self.ringCount, self.ringSteps
def __genOffsetFromAngle(self, angle, ring):
if ring >= self.ringCount:
return -1
angle = (angle + self.rotation) % 360
if self.reverse_angle:
angle = 360 - angle
offset = int(round(angle / self.ringSteps[ring]))
# wraps it back around
length = len(self.rings[ring]) - 1
if offset > length:
offset = 0
if self.maxAngleDiff > 0:
calcAngle = (offset * self.ringSteps[ring]) % 360
diff = abs(angle - calcAngle)
if diff > self.maxAngleDiff:
return -1
return offset
[docs] def angleToPixel(self, angle, ring):
offset = self.__genOffsetFromAngle(angle, ring)
if offset < 0:
return offset
return self.rings[ring][offset]
# Set single pixel to Color value
[docs] def set(self, ring, angle, color):
"""Set pixel to RGB color tuple"""
pixel = self.angleToPixel(angle, ring)
self._set_base(pixel, color)
[docs] def get(self, ring, angle):
"""Get RGB color tuple of color at index pixel"""
pixel = self.angleToPixel(angle, ring)
return self._get_base(pixel)
[docs] def drawRadius(self, angle, color, startRing=0, endRing=-1):
if startRing < 0:
startRing = 0
if endRing < 0 or endRing > self.ringCount - 1:
endRing = self.ringCount - 1
for ring in range(startRing, endRing + 1):
self.set(ring, angle, color)
[docs] def fillRing(self, ring, color, startAngle=0, endAngle=None):
if endAngle is None:
endAngle = 359
if ring >= self.ringCount:
raise ValueError("Invalid ring!")
def pixelRange(ring, start=0, stop=-1):
r = self.rings[ring]
if stop == -1:
stop = len(r) - 1
return [r[i] for i in range(start, stop + 1)]
start = self.__genOffsetFromAngle(startAngle, ring)
end = self.__genOffsetFromAngle(endAngle, ring)
if self.reverse_angle:
start, end = end, start
pixels = []
if start >= end:
pixels = pixelRange(ring, start)
pixels.extend(pixelRange(ring, 0, end))
elif start == end and startAngle > endAngle:
pixels = pixelRange(ring)
else:
pixels = pixelRange(ring, start, end)
for i in pixels:
self._set_base(i, color)
if deprecated.allowed(): # pragma: no cover
LEDCircle = Circle