From: mar77i Date: Wed, 25 Dec 2024 19:56:58 +0000 (+0100) Subject: auto-fit num_vertices for round lines X-Git-Url: https://git.mar77i.info/?a=commitdiff_plain;h=b6fccbaa7fd3f966cbe5b11be9bf07d1552289c5;p=zenbook_conf auto-fit num_vertices for round lines --- diff --git a/vector_assets.py b/vector_assets.py index fa4f1dd..3a887ba 100755 --- a/vector_assets.py +++ b/vector_assets.py @@ -40,10 +40,9 @@ laptop_vertical = Shapes( ] ) 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), ( @@ -51,10 +50,9 @@ touchscreen = Shapes( 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( ( @@ -63,53 +61,48 @@ touchscreen = Shapes( ), (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( diff --git a/vectors.py b/vectors.py index e71f22d..be4c4fb 100644 --- a/vectors.py +++ b/vectors.py @@ -1,5 +1,5 @@ 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 @@ -90,8 +90,9 @@ class StrokeRoundLine(Polygon): 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 = [] @@ -126,6 +127,10 @@ class StrokeRoundLine(Polygon): 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): @@ -136,60 +141,69 @@ class Shapes(Shape): 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))