Skip to content

Commit 2687554

Browse files
authored
Merge pull request #4 from makermelissa/master
Added Triangle Shape
2 parents 3a746be + 9d30e16 commit 2687554

File tree

4 files changed

+208
-0
lines changed

4 files changed

+208
-0
lines changed

adafruit_display_shapes/rect.py

100644100755
File mode changed.

adafruit_display_shapes/roundrect.py

100644100755
File mode changed.

adafruit_display_shapes/triangle.py

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2019 Limor Fried for Adafruit Industries
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
"""
23+
`triangle`
24+
================================================================================
25+
26+
Various common shapes for use with displayio - Triangle shape!
27+
28+
29+
* Author(s): Melissa LeBlanc-Williams
30+
31+
Implementation Notes
32+
--------------------
33+
34+
**Software and Dependencies:**
35+
36+
* Adafruit CircuitPython firmware for the supported boards:
37+
https://github.com/adafruit/circuitpython/releases
38+
39+
"""
40+
41+
import displayio
42+
43+
__version__ = "0.0.0-auto.0"
44+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Shapes.git"
45+
46+
47+
class Triangle(displayio.TileGrid):
48+
# pylint: disable=too-many-arguments,invalid-name
49+
"""A triangle.
50+
51+
:param x0: The x-position of the first vertex.
52+
:param y0: The y-position of the first vertex.
53+
:param x1: The x-position of the second vertex.
54+
:param y1: The y-position of the second vertex.
55+
:param x2: The x-position of the third vertex.
56+
:param y2: The y-position of the third vertex.
57+
:param fill: The color to fill the triangle. Can be a hex value for a color or
58+
``None`` for transparent.
59+
:param outline: The outline of the triangle. Can be a hex value for a color or
60+
``None`` for no outline.
61+
"""
62+
def __init__(self, x0, y0, x1, y1, x2, y2, *, fill=None, outline=None):
63+
# Sort coordinates by Y order (y2 >= y1 >= y0)
64+
if y0 > y1:
65+
y0, y1 = y1, y0
66+
x0, x1 = x1, x0
67+
68+
if y1 > y2:
69+
y1, y2 = y2, y1
70+
x1, x2 = x2, x1
71+
72+
if y0 > y1:
73+
y0, y1 = y1, y0
74+
x0, x1 = x1, x0
75+
76+
# Find the largest and smallest X values to figure out width for bitmap
77+
xs = [x0, x1, x2]
78+
width = max(xs) - min(xs) + 1
79+
height = y2 - y0 + 1
80+
81+
self._palette = displayio.Palette(3)
82+
self._palette.make_transparent(0)
83+
self._bitmap = displayio.Bitmap(width, height, 3)
84+
85+
if fill is not None:
86+
self._draw_filled(x0 - min(xs), 0, x1 - min(xs), y1 - y0, x2 - min(xs), y2 - y0)
87+
self._palette[2] = fill
88+
else:
89+
self._palette.make_transparent(2)
90+
91+
if outline is not None:
92+
print("outline")
93+
self._palette[1] = outline
94+
self._line(x0 - min(xs), 0, x1 - min(xs), y1 - y0, 1)
95+
self._line(x1 - min(xs), y1 - y0, x2 - min(xs), y2 - y0, 1)
96+
self._line(x2 - min(xs), y2 - y0, x0 - min(xs), 0, 1)
97+
98+
super().__init__(self._bitmap, pixel_shader=self._palette, x=min(xs), y=y0)
99+
100+
# pylint: disable=invalid-name, too-many-locals, too-many-branches
101+
def _draw_filled(self, x0, y0, x1, y1, x2, y2):
102+
if y0 == y2: # Handle awkward all-on-same-line case as its own thing
103+
a = x0
104+
b = x0
105+
if x1 < a:
106+
a = x1
107+
elif x1 > b:
108+
b = x1
109+
110+
if x2 < a:
111+
a = x2
112+
elif x2 > b:
113+
b = x2
114+
self._line(a, y0, b, y0, 2)
115+
return
116+
117+
if y1 == y2:
118+
last = y1 # Include y1 scanline
119+
else:
120+
last = y1 - 1 # Skip it
121+
122+
# Upper Triangle
123+
for y in range(y0, last + 1):
124+
a = round(x0 + (x1 - x0) * (y - y0) / (y1 - y0))
125+
b = round(x0 + (x2 - x0) * (y - y0) / (y2 - y0))
126+
if a > b:
127+
a, b = b, a
128+
self._line(a, y, b, y, 2)
129+
# Lower Triangle
130+
for y in range(last + 1, y2 + 1):
131+
a = round(x1 + (x2 - x1) * (y - y1) / (y2 - y1))
132+
b = round(x0 + (x2 - x0) * (y - y0) / (y2 - y0))
133+
134+
if a > b:
135+
a, b = b, a
136+
self._line(a, y, b, y, 2)
137+
138+
def _line(self, x0, y0, x1, y1, color):
139+
if x0 == x1:
140+
if y0 > y1:
141+
y0, y1 = y1, y0
142+
for _h in range(y0, y1):
143+
self._bitmap[x0, _h] = color
144+
elif y0 == y1:
145+
if x0 > x1:
146+
x0, x1 = x1, x0
147+
for _w in range(x0, x1):
148+
self._bitmap[_w, y0] = color
149+
else:
150+
steep = abs(y1 - y0) > abs(x1 - x0)
151+
if steep:
152+
x0, y0 = y0, x0
153+
x1, y1 = y1, x1
154+
155+
if x0 > x1:
156+
x0, x1 = x1, x0
157+
y0, y1 = y1, y0
158+
159+
dx = x1 - x0
160+
dy = abs(y1 - y0)
161+
162+
err = dx / 2
163+
164+
if y0 < y1:
165+
ystep = 1
166+
else:
167+
ystep = -1
168+
169+
for x in range(x0, x1):
170+
if steep:
171+
self._bitmap[y0, x] = color
172+
else:
173+
self._bitmap[x, y0] = color
174+
err -= dy
175+
if err < 0:
176+
y0 += ystep
177+
err += dx
178+
# pylint: enable=invalid-name, too-many-locals, too-many-branches
179+
180+
@property
181+
def fill(self):
182+
"""The fill of the triangle. Can be a hex value for a color or
183+
``None`` for transparent."""
184+
return self._palette[2]
185+
186+
@fill.setter
187+
def fill(self, color):
188+
if color is None:
189+
self._palette.make_transparent(2)
190+
else:
191+
self._palette[2] = color
192+
193+
@property
194+
def outline(self):
195+
"""The outline of the triangle. Can be a hex value for a color or
196+
``None`` for no outline."""
197+
return self._palette[1]
198+
199+
@outline.setter
200+
def outline(self, color):
201+
if color is None:
202+
self._palette.make_transparent(1)
203+
else:
204+
self._palette[1] = color

examples/display_shapes_simpletest.py

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from adafruit_display_shapes.rect import Rect
44
from adafruit_display_shapes.circle import Circle
55
from adafruit_display_shapes.roundrect import RoundRect
6+
from adafruit_display_shapes.triangle import Triangle
67

78
# Make the display context
89
splash = displayio.Group(max_size=10)
@@ -17,6 +18,9 @@
1718
splash.append(bg_sprite)
1819
##########################################################################
1920

21+
triangle = Triangle(170, 50, 120, 140, 210, 160, fill=0x00FF00, outline=0xFF00FF)
22+
splash.append(triangle)
23+
2024
rect = Rect(80, 20, 41, 41, fill=0x0)
2125
splash.append(rect)
2226

0 commit comments

Comments
 (0)