]> git.mar77i.info Git - zenbook_conf/commitdiff
auto-fit num_vertices for round lines
authormar77i <mar77i@protonmail.ch>
Wed, 25 Dec 2024 19:56:58 +0000 (20:56 +0100)
committermar77i <mar77i@protonmail.ch>
Wed, 25 Dec 2024 19:56:58 +0000 (20:56 +0100)
vector_assets.py
vectors.py

index fa4f1ddfbbdb2eab21605cb23436c252bc65b4de..3a887bad3a9fc208e65779ff4c153f6415407b4e 100755 (executable)
@@ -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(
index e71f22dbfdcbb85fc0927fec2abbef29d1415234..be4c4fb10c03b3e877a6896ec00a83271cd2e9e7 100644 (file)
@@ -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))