]> Repositories - hackapet/Adafruit_Blinka_Displayio.git/blob - vectorio/_circle.py
Merge pull request #159 from philrittenhouse/main
[hackapet/Adafruit_Blinka_Displayio.git] / vectorio / _circle.py
1 # SPDX-FileCopyrightText: 2020 Melissa LeBlanc-Williams for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4
5 """
6 `vectorio.circle`
7 ================================================================================
8
9 vectorio Circle for Blinka
10
11 **Software and Dependencies:**
12
13 * Adafruit Blinka:
14   https://github.com/adafruit/Adafruit_Blinka/releases
15
16 * Author(s): Melissa LeBlanc-Williams
17
18 """
19
20 from typing import Union
21 from displayio._colorconverter import ColorConverter
22 from displayio._palette import Palette
23 from displayio._area import Area
24 from ._vectorshape import _VectorShape
25
26 __version__ = "0.0.0+auto.0"
27 __repo__ = "https://github.com/adafruit/Adafruit_Blinka_displayio.git"
28
29
30 class Circle(_VectorShape):
31     """Vectorio Circle"""
32
33     def __init__(
34         self,
35         *,
36         pixel_shader: Union[ColorConverter, Palette],
37         radius: int,
38         x: int,
39         y: int,
40     ):
41         """Circle is positioned on screen by its center point.
42
43         :param Union[~displayio.ColorConverter,~displayio.Palette] pixel_shader:
44             The pixel shader that produces colors from values
45         :param int radius: The radius of the circle in pixels
46         :param int x: Initial x position of the axis.
47         :param int y: Initial y position of the axis.
48         :param int color_index: Initial color_index to use when selecting color from the palette.
49         """
50         self._radius = 1
51         self._color_index = 1
52         super().__init__(pixel_shader, x, y)
53         self.radius = radius
54
55     @property
56     def radius(self) -> int:
57         """The radius of the circle in pixels"""
58         return self._radius
59
60     @radius.setter
61     def radius(self, value: int) -> None:
62         if value < 1:
63             raise ValueError("radius must be >= 1")
64         self._radius = int(value)  # other code assumes radius is an integer
65         self._shape_set_dirty()
66
67     @property
68     def color_index(self) -> int:
69         """The color_index of the circle as 0 based index of the palette."""
70         return self._color_index - 1
71
72     @color_index.setter
73     def color_index(self, value: int) -> None:
74         self._color_index = abs(value + 1)
75         self._shape_set_dirty()
76
77     def _get_pixel(self, x: int, y: int) -> int:
78         x = abs(x)
79         y = abs(y)
80         if x + y <= self._radius:
81             return self._color_index
82         if x > self._radius or y > self._radius:
83             return 0
84         pythagoras_smaller_than_radius = x * x + y * y <= self._radius * self._radius
85         return self._color_index if pythagoras_smaller_than_radius else 0
86
87     def _get_area(self, out_area: Area) -> None:
88         out_area.x1 = -1 * self._radius - 1
89         out_area.y1 = -1 * self._radius - 1
90         out_area.x2 = self._radius + 1
91         out_area.y2 = self._radius + 1