]
)
FINGER_RADIUS = 1.25
-NUM_VERTICES = 32
touchscreen = Shapes(
[
- StrokeCircleSegment((12, 16), 5, 0, tau * 3 / 8, 1, NUM_VERTICES),
+ StrokeCircleSegment((12, 16), 5, 0, tau * 3 / 8, 1),
StrokeRoundLine(
(12 + cos(tau * 3 / 8) * 5, 16 + sin(tau * 3 / 8) * 5),
(
13 + sin(tau * 3 / 8) * FINGER_RADIUS,
),
1,
- NUM_VERTICES,
),
StrokeCircleSegment(
- (4, 13), FINGER_RADIUS, tau * 3 / 8, tau * 7 / 8, 1, NUM_VERTICES
+ (4, 13), FINGER_RADIUS, tau * 3 / 8, tau * 7 / 8, 1,
),
StrokeRoundLine(
(
),
(7, 13.5),
1,
- NUM_VERTICES,
),
- StrokeRoundLine((7, 13.5), (7, 6), 1, NUM_VERTICES),
- StrokeCircleSegment((8.25, 6), FINGER_RADIUS, pi, tau, 1, NUM_VERTICES),
- StrokeRoundLine((9.5, 6), (9.5, 11), 1, NUM_VERTICES),
+ StrokeRoundLine((7, 13.5), (7, 6), 1),
+ StrokeCircleSegment((8.25, 6), FINGER_RADIUS, pi, tau, 1),
+ StrokeRoundLine((9.5, 6), (9.5, 11), 1),
StrokeCircleSegment(
- (11, 11.5), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1, NUM_VERTICES
+ (11, 11.5), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1,
),
StrokeCircleSegment(
- (13.25, 12), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1, NUM_VERTICES
+ (13.25, 12), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1,
),
StrokeCircleSegment(
- (15.5, 12.5), FINGER_RADIUS, tau * 5 / 8, tau, 1, NUM_VERTICES
+ (15.5, 12.5), FINGER_RADIUS, tau * 5 / 8, tau, 1,
),
- StrokeRoundLine((16.75, 12.5), (17, 16), 1, NUM_VERTICES),
- StrokeCircleSegment((8.25, 6), 3, pi, tau, 1, NUM_VERTICES),
- StrokeCircleSegment((8.25, 6), 5, pi, tau, 1, NUM_VERTICES),
+ StrokeRoundLine((16.75, 12.5), (17, 16), 1),
+ StrokeCircleSegment((8.25, 6), 3, pi, tau, 1),
+ StrokeCircleSegment((8.25, 6), 5, pi, tau, 1),
]
)
stylus = Shapes(
[
- StrokeCircleSegment((3, 3), 1.5, tau * 3 / 8, tau * 7 / 8, 1, NUM_VERTICES),
+ StrokeCircleSegment((3, 3), 1.5, tau * 3 / 8, tau * 7 / 8, 1),
StrokeRoundLine(
(3 + cos(tau * 3 / 8) * 1.5, 3 + sin(tau * 3 / 8) * 1.5),
(16 + cos(tau * 3 / 8) * 1.5, 16 + sin(tau * 3 / 8) * 1.5),
1,
- NUM_VERTICES,
),
StrokeRoundLine(
(3 + cos(tau * 7 / 8) * 1.5, 3 + sin(tau * 7 / 8) * 1.5),
(16 + cos(tau * 7 / 8) * 1.5, 16 + sin(tau * 7 / 8) * 1.5),
1,
- NUM_VERTICES,
),
StrokeRoundLine(
(16 + cos(tau * 3 / 8) * 1.5, 16 + sin(tau * 3 / 8) * 1.5),
(18, 18),
1,
- NUM_VERTICES,
),
StrokeRoundLine(
(16 + cos(tau * 7 / 8) * 1.5, 16 + sin(tau * 7 / 8) * 1.5),
(18, 18),
1,
- NUM_VERTICES,
),
- StrokeRoundLine((11, 11), (12, 12), 1, NUM_VERTICES),
+ StrokeRoundLine((11, 11), (12, 12), 1),
]
)
bluetooth = Shapes(
from itertools import chain
-from math import atan2, ceil, cos, floor, pi, sin, sqrt
+from math import acos, atan2, ceil, cos, floor, pi, sin, sqrt
import pygame
Enclose a rectangle fitted between two points with a regular, non-rotated n-gon
that should be visually indistinguishable with a half circle
"""
- def __init__(self, p1, p2, width, num_vertices):
+ def __init__(self, p1, p2, width):
radius = width / 2
+ num_vertices = self.corners_needed_to_appear_round(radius)
delta = (p1[0] - p2[0], p1[1] - p2[1])
distance = sqrt(delta[0] * delta[0] + delta[1] * delta[1])
points = []
p = p2
super().__init__(points)
+ @staticmethod
+ def corners_needed_to_appear_round(radius, threshold=.5):
+ return ceil(pi / acos(1 - threshold / radius))
+
class Shapes(Shape):
def __init__(self, shapes):
shape.draw(surf, pos, unit, color)
-class StrokePath(Shapes):
- def __init__(self, points, closed, width, num_vertices):
- self._points = list(points)
+class StrokePath:
+ def __init__(self, points, closed, width):
+ self.points = list(*points)
self.closed = bool(closed)
self.width = width
- self.num_vertices = num_vertices
- super().__init__([])
@property
def shapes(self):
- if not self._points:
+ if not self.points:
return
if self.closed:
yield StrokeRoundLine(
- self._points[-1],
- self._points[0],
+ self.points[-1],
+ self.points[0],
self.width,
- self.num_vertices,
)
- iter_points = iter(self._points)
+ iter_points = iter(self.points)
old = next(iter_points)
for new in iter_points:
- yield StrokeRoundLine(old, new, self.width, self.num_vertices)
+ yield StrokeRoundLine(old, new, self.width)
old = new
- @shapes.setter
- def shapes(self, value):
- pass
+ draw = Shapes.draw
class StrokeCircle(StrokePath):
- def __init__(self, center, radius, width, num_vertices):
- super().__init__(
- [
- (center[0] + cos(a) * radius, center[1] + sin(a) * radius)
- for a in (tau * i / num_vertices for i in range(num_vertices))
- ],
- True,
- width,
- num_vertices,
- )
+ def __init__(self, center, radius, width):
+ self.center = center
+ self.radius = radius
+ super().__init__([], True, width)
+
+ def get_points(self, unit):
+ num_vertices = StrokeRoundLine.corners_needed_to_appear_round(self.radius * max(unit))
+ return [
+ (
+ self.center[0] + cos(a) * self.radius,
+ self.center[1] + sin(a) * self.radius,
+ )
+ for a in (tau * i / num_vertices for i in range(num_vertices))
+ ]
+ def draw(self, surf, pos, unit, color):
+ if not self.points:
+ self.points.extend(self.get_points(unit))
+ super().draw(surf, pos, unit, color)
-class StrokeCircleSegment(StrokePath):
- def __init__(self, center, radius, start_angle, end_angle, width, num_vertices):
- super().__init__(
- [
- (center[0] + cos(a) * radius, center[1] + sin(a) * radius)
- for a in self.get_angle_segments(start_angle, end_angle, num_vertices)
- ],
- False,
- width,
- num_vertices,
- )
+
+class StrokeCircleSegment(StrokeCircle):
+ def __init__(self, center, radius, start_angle, end_angle, width):
+ self.start_angle = start_angle
+ self.end_angle = end_angle
+ super().__init__(center, radius, width)
+ self.closed = False
+
+ def get_points(self, unit):
+ return [
+ (self.center[0] + cos(a) * self.radius, self.center[1] + sin(a) * self.radius)
+ for a in self.get_angle_segments(
+ self.start_angle,
+ self.end_angle,
+ StrokeRoundLine.corners_needed_to_appear_round(self.radius * max(unit)),
+ )
+ ]
def get_angle_segments(self, start_angle, end_angle, num_vertices):
start_angle, end_angle = sorted((start_angle, end_angle))