Skip to content

Commit 7fb9141

Browse files
authored
Merge pull request #67 from bablokb/arc
add support for arcs
2 parents 86f0f24 + f0fddbc commit 7fb9141

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed

README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ Usage Example
6363
import displayio
6464
from adafruit_display_shapes.rect import Rect
6565
from adafruit_display_shapes.circle import Circle
66+
from adafruit_display_shapes.arc import Arc
6667
from adafruit_display_shapes.roundrect import RoundRect
6768
6869
splash = displayio.Group()
@@ -84,6 +85,9 @@ Usage Example
8485
circle = Circle(100, 100, 20, fill=0x00FF00, outline=0xFF00FF)
8586
splash.append(circle)
8687
88+
arc = Arc(x=100, y=100, radius=25, angle=45, direction=90, segments=10, outline=0x00FF00)
89+
splash.append(arc)
90+
8791
rect2 = Rect(50, 100, 61, 81, outline=0x0, stroke=3)
8892
splash.append(rect2)
8993

adafruit_display_shapes/arc.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# SPDX-FileCopyrightText: 2023 Bernhard Bablok
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
`arc`
7+
================================================================================
8+
9+
Various common shapes for use with displayio - Arc shape!
10+
11+
12+
* Author(s): Bernhard Bablok
13+
14+
Implementation Notes
15+
--------------------
16+
17+
**Software and Dependencies:**
18+
19+
* Adafruit CircuitPython firmware for the supported boards:
20+
https://github.com/adafruit/circuitpython/releases
21+
22+
"""
23+
24+
try:
25+
from typing import Optional
26+
except ImportError:
27+
pass
28+
29+
import math
30+
import displayio
31+
from adafruit_display_shapes.polygon import Polygon
32+
33+
try:
34+
import vectorio
35+
36+
HAVE_VECTORIO = True
37+
except ImportError:
38+
HAVE_VECTORIO = False
39+
40+
__version__ = "0.0.0+auto.0"
41+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Shapes.git"
42+
43+
44+
class Arc(displayio.Group):
45+
# pylint: disable=too-few-public-methods, invalid-name
46+
"""An arc. Technically, an arc is a Group with one or two polygons.
47+
48+
An arc is defined by a radius, an angle (in degrees) and a direction (also in
49+
degrees). The latter is the direction of the midpoint of the arc.
50+
51+
The direction-parameter uses the layout of polar-coordinates, i.e. zero points
52+
to the right, 90 to the top, 180 to the left and 270 to the bottom.
53+
54+
The Arc-class creates the arc as a polygon. The number of segments define
55+
how round the arc is. There is a memory-tradeoff if the segment-number is
56+
large.
57+
58+
:param float radius: The (outer) radius of the arc.
59+
:param float angle: The angle of the arc in degrees.
60+
:param float direction: The direction of the middle-point of the arc in degrees (0)
61+
:param int segments: The number of segments of the arc.
62+
:param arc_width int: (Optional) The width of the arc. This creates an inner arc as well.
63+
:param int|None outline: The outline of the arc. Can be a hex value for a color or
64+
``None`` for no outline.
65+
:param int|None fill: The fill-color of the arc. Can be a hex value for a color or
66+
``None`` for no filling. Ignored if port does not support vectorio.
67+
"""
68+
69+
def __init__(
70+
# pylint: disable=too-many-arguments, too-many-locals
71+
self,
72+
radius: float,
73+
angle: float,
74+
direction: float,
75+
segments: int,
76+
*args,
77+
arc_width: Optional[int] = 1,
78+
outline: Optional[int] = None,
79+
fill: Optional[int] = None,
80+
**kwargs,
81+
) -> None:
82+
super().__init__(*args, **kwargs)
83+
# shift direction by angle/2
84+
direction = direction - angle / 2
85+
# create outer points
86+
points = []
87+
for i in range(segments + 1):
88+
alpha = (i * angle / segments + direction) / 180 * math.pi
89+
x0 = int(radius * math.cos(alpha))
90+
y0 = -int(radius * math.sin(alpha))
91+
points.append((x0, y0))
92+
93+
# create inner points
94+
if arc_width > 1:
95+
for i in range(segments, -1, -1):
96+
alpha = (i * angle / segments + direction) / 180 * math.pi
97+
x0 = int((radius - arc_width) * math.cos(alpha))
98+
y0 = -int((radius - arc_width) * math.sin(alpha))
99+
points.append((x0, y0))
100+
101+
# create polygon(s) and add to ourselves
102+
if arc_width > 1 and HAVE_VECTORIO and fill is not None:
103+
palette = displayio.Palette(1)
104+
palette[0] = fill
105+
self.append(vectorio.Polygon(pixel_shader=palette, points=points, x=0, y=0))
106+
if outline is not None:
107+
self.append(Polygon(points, outline=outline, colors=1, close=arc_width > 1))

docs/api.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@
2424

2525
.. automodule:: adafruit_display_shapes.sparkline
2626
:members:
27+
28+
.. automodule:: adafruit_display_shapes.arc
29+
:members:

docs/examples.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,12 @@ Example showing the features of the new Circle setter
5151
.. literalinclude:: ../examples/display_shapes_circle_animation.py
5252
:caption: examples/display_shapes_circle_animation.py
5353
:linenos:
54+
55+
Arc Simple Test
56+
---------------
57+
58+
Example demonstrating various arcs.
59+
60+
.. literalinclude:: ../examples/display_shapes_arc.py
61+
:caption: examples/display_shapes_arc.py
62+
:linenos:

examples/display_shapes_arc.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# SPDX-FileCopyrightText: 2023 Bernhard Bablok
2+
# SPDX-License-Identifier: MIT
3+
4+
import time
5+
import board
6+
7+
import displayio
8+
from adafruit_display_shapes.arc import Arc
9+
from adafruit_display_shapes.circle import Circle
10+
11+
# use built in display (PyPortal, PyGamer, PyBadge, CLUE, etc.)
12+
# see guide for setting up external displays (TFT / OLED breakouts, RGB matrices, etc.)
13+
# https://learn.adafruit.com/circuitpython-display-support-using-displayio/display-and-display-bus
14+
display = board.DISPLAY
15+
16+
w2 = int(display.width / 2)
17+
h2 = int(display.height / 2)
18+
19+
WHITE = 0xFFFFFF
20+
RED = 0xFF0000
21+
GREEN = 0x00FF00
22+
BLUE = 0x0000FF
23+
24+
# Make the display context
25+
group = displayio.Group()
26+
display.root_group = group
27+
28+
# little circle in the center of all arcs
29+
circle = Circle(w2, h2, 5, fill=0xFF0000, outline=0xFF0000)
30+
group.append(circle)
31+
32+
# red arc with white outline, 10 pixels wide
33+
arc1 = Arc(
34+
x=w2,
35+
y=h2,
36+
radius=min(display.width, display.height) / 4,
37+
angle=90,
38+
direction=90,
39+
segments=10,
40+
arc_width=10,
41+
outline=WHITE,
42+
fill=RED,
43+
)
44+
group.append(arc1)
45+
46+
# green arc (single line)
47+
arc2 = Arc(
48+
x=w2,
49+
y=h2,
50+
radius=min(display.width, display.height) / 4 + 5,
51+
angle=180,
52+
direction=90,
53+
segments=20,
54+
arc_width=1,
55+
outline=GREEN,
56+
)
57+
group.append(arc2)
58+
59+
# blue arc (or pie)
60+
arc3 = Arc(
61+
x=w2,
62+
y=h2,
63+
radius=min(display.width, display.height) / 4,
64+
angle=90,
65+
direction=-90,
66+
segments=10,
67+
arc_width=min(display.width, display.height) / 4 - 5,
68+
outline=BLUE,
69+
)
70+
group.append(arc3)
71+
72+
while True:
73+
time.sleep(0.1)

0 commit comments

Comments
 (0)