From b085954ce5262b4f76e662f94606e56ec9e6c116 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Fri, 22 Mar 2019 22:09:57 -0700 Subject: [PATCH 1/3] Fixed Position Parameter --- adafruit_display_shapes/rect.py | 5 ++++- adafruit_display_shapes/roundrect.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) mode change 100644 => 100755 adafruit_display_shapes/rect.py mode change 100644 => 100755 adafruit_display_shapes/roundrect.py diff --git a/adafruit_display_shapes/rect.py b/adafruit_display_shapes/rect.py old mode 100644 new mode 100755 index 951552a..f68debc --- a/adafruit_display_shapes/rect.py +++ b/adafruit_display_shapes/rect.py @@ -78,7 +78,10 @@ def __init__(self, x, y, width, height, *, fill=None, outline=None, stroke=1): self._palette[0] = fill else: self._palette.make_transparent(0) - super().__init__(self._bitmap, pixel_shader=self._palette, position=(x, y)) + try: + super().__init__(self._bitmap, pixel_shader=self._palette, position=(x, y)) + except TypeError: + super().__init__(self._bitmap, pixel_shader=self._palette, x=x, y=y) @property def fill(self): diff --git a/adafruit_display_shapes/roundrect.py b/adafruit_display_shapes/roundrect.py old mode 100644 new mode 100755 index 9c3c4d6..0d51be0 --- a/adafruit_display_shapes/roundrect.py +++ b/adafruit_display_shapes/roundrect.py @@ -90,7 +90,10 @@ def __init__(self, x, y, width, height, r, *, fill=None, outline=None, stroke=1) # draw round corners self._helper(r, r, r, color=1, stroke=stroke, x_offset=width-2*r-1, y_offset=height-2*r-1) - super().__init__(self._bitmap, pixel_shader=self._palette, position=(x, y)) + try: + super().__init__(self._bitmap, pixel_shader=self._palette, position=(x, y)) + except TypeError: + super().__init__(self._bitmap, pixel_shader=self._palette, x=x, y=y) # pylint: disable=invalid-name, too-many-locals, too-many-branches def _helper(self, x0, y0, r, *, color, x_offset=0, y_offset=0, From 0e9fd8558edf3df50e4926d74c2a6b780d3463fe Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Thu, 1 Aug 2019 16:20:40 -0700 Subject: [PATCH 2/3] Added Triangle Shape --- adafruit_display_shapes/triangle.py | 218 ++++++++++++++++++++++++++ examples/display_shapes_simpletest.py | 4 + 2 files changed, 222 insertions(+) create mode 100755 adafruit_display_shapes/triangle.py diff --git a/adafruit_display_shapes/triangle.py b/adafruit_display_shapes/triangle.py new file mode 100755 index 0000000..1d4e10a --- /dev/null +++ b/adafruit_display_shapes/triangle.py @@ -0,0 +1,218 @@ +# The MIT License (MIT) +# +# Copyright (c) 2019 Limor Fried for Adafruit Industries +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +""" +`triangle` +================================================================================ + +Various common shapes for use with displayio - Triangle shape! + + +* Author(s): Melissa LeBlanc-Williams + +Implementation Notes +-------------------- + +**Software and Dependencies:** + +* Adafruit CircuitPython firmware for the supported boards: + https://github.com/adafruit/circuitpython/releases + +""" + +import displayio + +__version__ = "0.0.0-auto.0" +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Shapes.git" + + +class Triangle(displayio.TileGrid): + # pylint: disable=too-many-arguments,invalid-name + """A triangle. + + :param x0: The x-position of the first vertex. + :param y0: The y-position of the first vertex. + :param x1: The x-position of the second vertex. + :param y1: The y-position of the second vertex. + :param x2: The x-position of the third vertex. + :param y2: The y-position of the third vertex. + :param fill: The color to fill the triangle. Can be a hex value for a color or + ``None`` for transparent. + :param outline: The outline of the triangle. Can be a hex value for a color or + ``None`` for no outline. + """ + def __init__(self, x0, y0, x1, y1, x2, y2, *, fill=None, outline=None): + # Sort coordinates by Y order (y2 >= y1 >= y0) + if y0 > y1: + y0, y1 = y1, y0 + x0, x1 = x1, x0 + + if y1 > y2: + y1, y2 = y2, y1 + x1, x2 = x2, x1 + + if y0 > y1: + y0, y1 = y1, y0 + x0, x1 = x1, x0 + + smallest_x = x0 + largest_x = x0 + + # Find the largest and smallest X values to figure out width for bitmap + if x1 > largest_x: + largest_x = x1 + + if x1 < smallest_x: + smallest_x = x1 + + if x2 > largest_x: + largest_x = x2 + + if x2 < smallest_x: + smallest_x = x2 + + height = y2 - y0 + 1 + width = largest_x - smallest_x + 1 + + self._palette = displayio.Palette(3) + self._palette.make_transparent(0) + self._bitmap = displayio.Bitmap(width, height, 3) + + if fill is not None: + self._helper(x0 - smallest_x, 0, x1 - smallest_x, y1 - y0, x2 - smallest_x, y2 - y0) + self._palette[2] = fill + else: + self._palette.make_transparent(2) + + if outline is not None: + print("outline") + self._palette[1] = outline + self._line(x0 - smallest_x, 0, x1 - smallest_x, y1 - y0, 1) + self._line(x1 - smallest_x, y1 - y0, x2 - smallest_x, y2 - y0, 1) + self._line(x2 - smallest_x, y2 - y0, x0 - smallest_x, 0, 1) + + super().__init__(self._bitmap, pixel_shader=self._palette, x=smallest_x, y=y0) + + # pylint: disable=invalid-name, too-many-locals, too-many-branches + def _helper(self, x0, y0, x1, y1, x2, y2): + if y0 == y2: # Handle awkward all-on-same-line case as its own thing + a = x0 + b = x0 + if x1 < a: + a = x1 + elif x1 > b: + b = x1 + + if x2 < a: + a = x2 + elif x2 > b: + b = x2 + self._line(a, y0, b, y0, 2) + return + + if y1 == y2: + last = y1 # Include y1 scanline + else: + last = y1 - 1 # Skip it + + # Upper Triangle + for y in range(y0, last + 1): + a = round(x0 + (x1 - x0) * (y - y0) / (y1 - y0)) + b = round(x0 + (x2 - x0) * (y - y0) / (y2 - y0)) + if a > b: + a, b = b, a + self._line(a, y, b, y, 2) + # Lower Triangle + for y in range(last + 1, y2 + 1): + a = round(x1 + (x2 - x1) * (y - y1) / (y2 - y1)) + b = round(x0 + (x2 - x0) * (y - y0) / (y2 - y0)) + + if a > b: + a, b = b, a + self._line(a, y, b, y, 2) + + def _line(self, x0, y0, x1, y1, color): + if x0 == x1: + if y0 > y1: + y0, y1 = y1, y0 + for _h in range(y0, y1): + self._bitmap[x0, _h] = color + elif y0 == y1: + if x0 > x1: + x0, x1 = x1, x0 + for _w in range(x0, x1): + 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): + if steep: + self._bitmap[y0, x] = color + else: + self._bitmap[x, y0] = color + err -= dy + if err < 0: + y0 += ystep + err += dx + # pylint: enable=invalid-name, too-many-locals, too-many-branches + + @property + def fill(self): + """The fill of the triangle. Can be a hex value for a color or + ``None`` for transparent.""" + return self._palette[2] + + @fill.setter + def fill(self, color): + if color is None: + self._palette.make_transparent(2) + else: + self._palette[2] = color + + @property + def outline(self): + """The outline of the triangle. Can be a hex value for a color or + ``None`` for no outline.""" + return self._palette[1] + + @outline.setter + def outline(self, color): + if color is None: + self._palette.make_transparent(1) + else: + self._palette[1] = color diff --git a/examples/display_shapes_simpletest.py b/examples/display_shapes_simpletest.py index e8021eb..064ea76 100644 --- a/examples/display_shapes_simpletest.py +++ b/examples/display_shapes_simpletest.py @@ -3,6 +3,7 @@ from adafruit_display_shapes.rect import Rect from adafruit_display_shapes.circle import Circle from adafruit_display_shapes.roundrect import RoundRect +from adafruit_display_shapes.triangle import Triangle # Make the display context splash = displayio.Group(max_size=10) @@ -17,6 +18,9 @@ splash.append(bg_sprite) ########################################################################## +triangle = Triangle(170, 50, 120, 140, 210, 160, fill=0x00FF00, outline=0xFF00FF) +splash.append(triangle) + rect = Rect(80, 20, 41, 41, fill=0x0) splash.append(rect) From 9d30e16c6561f66b802e5769b7a106c588f53404 Mon Sep 17 00:00:00 2001 From: Melissa LeBlanc-Williams Date: Fri, 2 Aug 2019 11:26:05 -0700 Subject: [PATCH 3/3] Added Requested changes --- adafruit_display_shapes/triangle.py | 30 ++++++++--------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/adafruit_display_shapes/triangle.py b/adafruit_display_shapes/triangle.py index 1d4e10a..bde221c 100755 --- a/adafruit_display_shapes/triangle.py +++ b/adafruit_display_shapes/triangle.py @@ -73,31 +73,17 @@ def __init__(self, x0, y0, x1, y1, x2, y2, *, fill=None, outline=None): y0, y1 = y1, y0 x0, x1 = x1, x0 - smallest_x = x0 - largest_x = x0 - # Find the largest and smallest X values to figure out width for bitmap - if x1 > largest_x: - largest_x = x1 - - if x1 < smallest_x: - smallest_x = x1 - - if x2 > largest_x: - largest_x = x2 - - if x2 < smallest_x: - smallest_x = x2 - + xs = [x0, x1, x2] + width = max(xs) - min(xs) + 1 height = y2 - y0 + 1 - width = largest_x - smallest_x + 1 self._palette = displayio.Palette(3) self._palette.make_transparent(0) self._bitmap = displayio.Bitmap(width, height, 3) if fill is not None: - self._helper(x0 - smallest_x, 0, x1 - smallest_x, y1 - y0, x2 - smallest_x, y2 - y0) + self._draw_filled(x0 - min(xs), 0, x1 - min(xs), y1 - y0, x2 - min(xs), y2 - y0) self._palette[2] = fill else: self._palette.make_transparent(2) @@ -105,14 +91,14 @@ def __init__(self, x0, y0, x1, y1, x2, y2, *, fill=None, outline=None): if outline is not None: print("outline") self._palette[1] = outline - self._line(x0 - smallest_x, 0, x1 - smallest_x, y1 - y0, 1) - self._line(x1 - smallest_x, y1 - y0, x2 - smallest_x, y2 - y0, 1) - self._line(x2 - smallest_x, y2 - y0, x0 - smallest_x, 0, 1) + self._line(x0 - min(xs), 0, x1 - min(xs), y1 - y0, 1) + self._line(x1 - min(xs), y1 - y0, x2 - min(xs), y2 - y0, 1) + self._line(x2 - min(xs), y2 - y0, x0 - min(xs), 0, 1) - super().__init__(self._bitmap, pixel_shader=self._palette, x=smallest_x, y=y0) + super().__init__(self._bitmap, pixel_shader=self._palette, x=min(xs), y=y0) # pylint: disable=invalid-name, too-many-locals, too-many-branches - def _helper(self, x0, y0, x1, y1, x2, y2): + def _draw_filled(self, x0, y0, x1, y1, x2, y2): if y0 == y2: # Handle awkward all-on-same-line case as its own thing a = x0 b = x0