]> git.mar77i.info Git - zenbook_conf/commitdiff
improve vector drawing. split out vector_assets
authormar77i <mar77i@protonmail.ch>
Wed, 25 Dec 2024 10:52:45 +0000 (11:52 +0100)
committermar77i <mar77i@protonmail.ch>
Wed, 25 Dec 2024 10:52:45 +0000 (11:52 +0100)
vector_assets.py [new file with mode: 0755]
vectors.py [changed mode: 0755->0644]
zenbook_conf.py

diff --git a/vector_assets.py b/vector_assets.py
new file mode 100755 (executable)
index 0000000..fa4f1dd
--- /dev/null
@@ -0,0 +1,180 @@
+from math import cos, pi, sin
+
+import pygame
+
+from vectors import (
+    Polygon, Rect, Shapes, StrokeCircleSegment, StrokeRoundLine, StrokeSquareLine
+)
+
+tau = 2 * pi
+
+
+laptop_single = Shapes(
+    [
+        Rect((2, 3), (16.4, 1)),
+        Rect((2, 4), (1, 8.1)),
+        Rect((17.4, 4), (1, 8.1)),
+        Rect((2, 12.1), (16.4, 1)),
+        Polygon([(2, 13.1), (18.4, 13.1), (22.4, 18.1), (6, 18.1)]),
+    ]
+)
+laptop_double = Shapes(
+    [
+        Rect((2, 3), (16.4, 1)),
+        Rect((2, 4), (1, 8.1)),
+        Rect((17.4, 4), (1, 8.1)),
+        Rect((2, 12.1), (16.4, 1)),
+        Polygon([(2, 13.1), (3, 13.1), (6.2, 17.1), (5.2, 17.1)]),
+        Polygon([(17.4, 13.1), (18.4, 13.1), (21.6, 17.1), (20.4, 17.1)]),
+        Polygon([(5.2, 17.1), (21.6, 17.1), (22.4, 18.1), (6, 18.1)]),
+    ]
+)
+laptop_vertical = Shapes(
+    [
+        Rect((0.5, 1), (17.75, 1)),
+        Rect((0.5, 2), (1, 14.4)),
+        Rect((9, 2), (1, 14.4)),
+        Rect((17.25, 2), (1, 14.4)),
+        Rect((0.5, 16.4), (17.75, 1)),
+        Polygon([(2, 17.4), (6, 22.4), (20.75, 22.4), (16.75, 17.4)]),
+    ]
+)
+FINGER_RADIUS = 1.25
+NUM_VERTICES = 32
+touchscreen = Shapes(
+    [
+        StrokeCircleSegment((12, 16), 5, 0, tau * 3 / 8, 1, NUM_VERTICES),
+        StrokeRoundLine(
+            (12 + cos(tau * 3 / 8) * 5, 16 + sin(tau * 3 / 8) * 5),
+            (
+                4 + cos(tau * 3 / 8) * FINGER_RADIUS,
+                13 + sin(tau * 3 / 8) * FINGER_RADIUS,
+            ),
+            1,
+            NUM_VERTICES,
+        ),
+        StrokeCircleSegment(
+            (4, 13), FINGER_RADIUS, tau * 3 / 8, tau * 7 / 8, 1, NUM_VERTICES
+        ),
+        StrokeRoundLine(
+            (
+                4 + cos(tau * 7 / 8) * FINGER_RADIUS,
+                13 + sin(tau * 7 / 8) * FINGER_RADIUS,
+            ),
+            (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),
+        StrokeCircleSegment(
+            (11, 11.5), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1, NUM_VERTICES
+        ),
+        StrokeCircleSegment(
+            (13.25, 12), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1, NUM_VERTICES
+        ),
+        StrokeCircleSegment(
+            (15.5, 12.5), FINGER_RADIUS, tau * 5 / 8, tau, 1, NUM_VERTICES
+        ),
+        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),
+    ]
+)
+stylus = Shapes(
+    [
+        StrokeCircleSegment((3, 3), 1.5, tau * 3 / 8, tau * 7 / 8, 1, NUM_VERTICES),
+        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),
+    ]
+)
+bluetooth = Shapes(
+    [
+        StrokeSquareLine((10, 2), (15, 6), 1.5),
+        StrokeSquareLine((15, 6), (5, 14), 1.5),
+        StrokeSquareLine((10, 2.75), (10, 18.25), 1.5),
+        StrokeSquareLine((10, 19), (15, 15), 1.5),
+        StrokeSquareLine((15, 15), (5, 7), 1.5),
+    ]
+)
+
+
+def main():
+    shapes = [
+        {
+            "shape": laptop_single,
+            "pos": (100, 100),
+        },
+        {
+            "shape": laptop_double,
+            "pos": (600, 100),
+        },
+        {
+            "shape": laptop_vertical,
+            "pos": (1100, 100),
+        },
+        {
+            "shape": touchscreen,
+            "pos": (100, 600),
+        },
+        {
+            "shape": stylus,
+            "pos": (600, 600),
+        },
+        {
+            "shape": bluetooth,
+            "pos": (1100, 600),
+        },
+    ]
+    surf = pygame.display.set_mode((2000, 1600))
+    running = True
+    dirty = False
+    clock = pygame.time.Clock()
+    while True:
+        for ev in pygame.event.get():
+            if ev.type == pygame.QUIT:
+                running = False
+                break
+            elif ev.type == pygame.WINDOWEXPOSED:
+                dirty = True
+            elif ev.type == pygame.KEYDOWN:
+                if ev.key == pygame.K_ESCAPE:
+                    running = False
+                    break
+        if not running:
+            break
+        elif dirty:
+            surf.fill("black")
+            for item in shapes:
+                item["shape"].draw(surf, item["pos"], (16, 16), "green")
+            pygame.display.update()
+            dirty = False
+        clock.tick(60)
+
+
+if __name__ == "__main__":
+    main()
old mode 100755 (executable)
new mode 100644 (file)
index 9b10c52..e71f22d
@@ -1,5 +1,3 @@
-#!/usr/bin/env python3
-
 from itertools import chain
 from math import atan2, ceil, cos, floor, pi, sin, sqrt
 
@@ -65,85 +63,68 @@ class StrokeSquareLine(Polygon):
     """
     Rotate a rectangle along the direction in which we're drawing.
     """
-    def __init__(self, start, end, width):
-        super().__init__(list(self.make_line_shape(start, end, width / 2)))
-
-    def make_line_shape(self, p1, p2, shape_r):
+    def __init__(self, p1, p2, width):
         p_rel = (p1[0] - p2[0], p1[1] - p2[1])
-        distance = sqrt(p_rel[0] * p_rel[0] + p_rel[1] * p_rel[1])
-        if distance:
-            back = (p_rel[0] * shape_r / distance, p_rel[1] * shape_r / distance)
+        twice_distance = 2 * sqrt(p_rel[0] * p_rel[0] + p_rel[1] * p_rel[1])
+        if twice_distance:
+            back = (
+                p_rel[0] * width / twice_distance, p_rel[1] * width / twice_distance
+            )
             back_sum, back_diff = back[0] + back[1], back[0] - back[1]
         else:
-            back_sum, back_diff = -shape_r, shape_r
+            back_sum, back_diff = -width / 2, width / 2
         # left is aka: (back[1], -back[0])
         # right is aka: (-back[1], back[0])
-        yield from (
-            (p1[0] + back_sum, p1[1] - back_diff),
-            (p1[0] + back_diff, p1[1] + back_sum),
-            (p2[0] - back_sum, p2[1] + back_diff),
-            (p2[0] - back_diff, p2[1] - back_sum),
+        super().__init__(
+            [
+                (p1[0] + back_sum, p1[1] - back_diff),
+                (p1[0] + back_diff, p1[1] + back_sum),
+                (p2[0] - back_sum, p2[1] + back_diff),
+                (p2[0] - back_diff, p2[1] - back_sum),
+            ]
         )
 
 
-class StrokeRoundLine(StrokeSquareLine):
+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, start, end, width, num_vertices):
-        self.num_vertices = num_vertices
-        super().__init__(start, end, width)
-
-    def make_line_shape(self, p1, p2, shape_r):
-        p_rel = (p1[0] - p2[0], p1[1] - p2[1])
-        distance = sqrt(p_rel[0] * p_rel[0] + p_rel[1] * p_rel[1])
+    def __init__(self, p1, p2, width, num_vertices):
+        radius = width / 2
+        delta = (p1[0] - p2[0], p1[1] - p2[1])
+        distance = sqrt(delta[0] * delta[0] + delta[1] * delta[1])
+        points = []
         if distance == 0:
-            yield from (
-                (p1[0] + cos(a) * shape_r, p1[1] + sin(a) * shape_r)
-                for a in (
-                    (i) * tau / self.num_vertices
-                    for i in range(self.num_vertices)
-                )
+            initial_corner = opposing_corner = num_vertices
+            back = (0, 0)
+        else:
+            initial_corner = ceil(
+                atan2(-delta[0], delta[1]) * num_vertices / tau
             )
-            return
-        angle = atan2(p_rel[1], p_rel[0])
-        if angle < 0:
-            angle += tau
-        # 0 <= angle < tau
-        initial_corner = ceil(
-            atan2(-p_rel[0], p_rel[1]) * self.num_vertices / tau
-        ) % self.num_vertices
-        opposing_corner = (
-            floor(atan2(p_rel[0], -p_rel[1]) * self.num_vertices / tau) - initial_corner
-        ) % self.num_vertices
-        shape = [
-            (cos(a) * shape_r, sin(a) * shape_r)
-            for a in (
-                (i + initial_corner) * tau / self.num_vertices
-                for i in range(self.num_vertices)
+            opposing_corner = (
+                floor(atan2(delta[0], -delta[1]) * num_vertices / tau) - initial_corner
+            ) % num_vertices
+            back = (delta[0] * radius / distance, delta[1] * radius / distance)
+            points.extend(
+                (
+                    (p2[0] + back[1], p2[1] - back[0]),
+                    (p1[0] + back[1], p1[1] - back[0]),
+                )
             )
-        ]
-        if distance == 0:
-            for vertex in shape:
-                yield (p1[0] + vertex[0], p1[1] + vertex[1])
-            return
-        # left: (cos(angle + tau * 3 / 4) * shape_r, sin(angle + tau * 3 / 4) * shape_r)
-        # right: (cos(angle + tau / 4) * shape_r, sin(angle + tau / 4) * shape_r)
-        # back = (cos(angle) * shape_r, sin(angle) * shape_r)
-        # no need for trig here, though, because we only go ±90°:
-        back = (p_rel[0] * shape_r / distance, p_rel[1] * shape_r / distance)
-        # left is aka: (back[1], -back[0])
-        # right is aka: (-back[1], back[0])
-        yield (p2[0] + back[1], p2[1] - back[0])
-        yield (p1[0] + back[1], p1[1] - back[0])
         p = p1
-        for i, vertex in enumerate(shape):
-            yield (p[0] + vertex[0], p[1] + vertex[1])
-            if i == opposing_corner and p == p1:
-                yield (p[0] - back[1], p[1] + back[0])
+        for i in range(num_vertices):
+            angle = (i + initial_corner) * tau / num_vertices
+            points.append((p[0] + cos(angle) * radius, p[1] + sin(angle) * radius))
+            if i == opposing_corner:
+                points.extend(
+                    (
+                        (p1[0] - back[1], p1[1] + back[0]),
+                        (p2[0] - back[1], p2[1] + back[0]),
+                    )
+                )
                 p = p2
-                yield (p[0] - back[1], p[1] + back[0])
+        super().__init__(points)
 
 
 class Shapes(Shape):
@@ -219,172 +200,3 @@ class StrokeCircleSegment(StrokePath):
                 yield end_angle
                 break
             yield start_angle + a
-
-
-laptop_single = Shapes(
-    [
-        Rect((2, 3), (16.4, 1)),
-        Rect((2, 4), (1, 8.1)),
-        Rect((17.4, 4), (1, 8.1)),
-        Rect((2, 12.1), (16.4, 1)),
-        Polygon([(2, 13.1), (18.4, 13.1), (22.4, 18.1), (6, 18.1)]),
-    ]
-)
-laptop_double = Shapes(
-    [
-        Rect((2, 3), (16.4, 1)),
-        Rect((2, 4), (1, 8.1)),
-        Rect((17.4, 4), (1, 8.1)),
-        Rect((2, 12.1), (16.4, 1)),
-        Polygon([(2, 13.1), (3, 13.1), (6.2, 17.1), (5.2, 17.1)]),
-        Polygon([(17.4, 13.1), (18.4, 13.1), (21.6, 17.1), (20.4, 17.1)]),
-        Polygon([(5.2, 17.1), (21.6, 17.1), (22.4, 18.1), (6, 18.1)]),
-    ]
-)
-laptop_vertical = Shapes(
-    [
-        Rect((0.5, 1), (17.75, 1)),
-        Rect((0.5, 2), (1, 14.4)),
-        Rect((9, 2), (1, 14.4)),
-        Rect((17.25, 2), (1, 14.4)),
-        Rect((0.5, 16.4), (17.75, 1)),
-        Polygon([(2, 17.4), (6, 22.4), (20.75, 22.4), (16.75, 17.4)]),
-    ]
-)
-FINGER_RADIUS = 1.25
-NUM_VERTICES = 32
-touchscreen = Shapes(
-    [
-        StrokeCircleSegment((12, 16), 5, 0, tau * 3 / 8, 1, NUM_VERTICES),
-        StrokeRoundLine(
-            (12 + cos(tau * 3 / 8) * 5, 16 + sin(tau * 3 / 8) * 5),
-            (
-                4 + cos(tau * 3 / 8) * FINGER_RADIUS,
-                13 + sin(tau * 3 / 8) * FINGER_RADIUS,
-            ),
-            1,
-            NUM_VERTICES,
-        ),
-        StrokeCircleSegment((4, 13), FINGER_RADIUS, tau * 3 / 8, tau * 7 / 8, 1, NUM_VERTICES),
-        StrokeRoundLine(
-            (
-                4 + cos(tau * 7 / 8) * FINGER_RADIUS,
-                13 + sin(tau * 7 / 8) * FINGER_RADIUS,
-            ),
-            (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),
-        StrokeCircleSegment(
-            (11, 11.5), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1, NUM_VERTICES
-        ),
-        StrokeCircleSegment(
-            (13.25, 12), FINGER_RADIUS, tau * 5 / 8, tau * 7 / 8, 1, NUM_VERTICES
-        ),
-        StrokeCircleSegment(
-            (15.5, 12.5), FINGER_RADIUS, tau * 5 / 8, tau, 1, NUM_VERTICES
-        ),
-        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),
-    ]
-)
-stylus = Shapes(
-    [
-        StrokeCircleSegment((3, 3), 1.5, tau * 3 / 8, tau * 7 / 8, 1, NUM_VERTICES),
-        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),
-    ]
-)
-bluetooth = Shapes(
-    [
-        StrokeSquareLine((10, 2), (15, 6), 1.5),
-        StrokeSquareLine((15, 6), (5, 14), 1.5),
-        StrokeSquareLine((10, 2.75), (10, 18.25), 1.5),
-        StrokeSquareLine((10, 19), (15, 15), 1.5),
-        StrokeSquareLine((15, 15), (5, 7), 1.5),
-    ]
-)
-
-
-def main():
-    shapes = [
-        {
-            "shape": laptop_single,
-            "pos": (100, 100),
-        },
-        {
-            "shape": laptop_double,
-            "pos": (600, 100),
-        },
-        {
-            "shape": laptop_vertical,
-            "pos": (1100, 100),
-        },
-        {
-            "shape": touchscreen,
-            "pos": (100, 600),
-        },
-        {
-            "shape": stylus,
-            "pos": (600, 600),
-        },
-        {
-            "shape": bluetooth,
-            "pos": (1100, 600),
-        },
-    ]
-    surf = pygame.display.set_mode((2000, 1600))
-    running = True
-    dirty = False
-    clock = pygame.time.Clock()
-    while True:
-        for ev in pygame.event.get():
-            if ev.type == pygame.QUIT:
-                running = False
-                break
-            elif ev.type == pygame.WINDOWEXPOSED:
-                dirty = True
-            elif ev.type == pygame.KEYDOWN:
-                if ev.key == pygame.K_ESCAPE:
-                    running = False
-                    break
-        if not running:
-            break
-        elif dirty:
-            surf.fill("black")
-            for item in shapes:
-                item["shape"].draw(surf, item["pos"], (16, 16), "green")
-            pygame.display.update()
-            dirty = False
-        clock.tick(60)
-
-
-if __name__ == "__main__":
-    main()
index 19aece51ea148ece63460100bd69f6ab211d3698..d69fab5b2b3429816f5f586f95970d8d7da24f22 100755 (executable)
@@ -6,7 +6,7 @@ import pygame
 
 from bluetooth import BluetoothConf
 from ui import Button, Icon, IconButton, Switch, UIParent
-from vectors import (
+from vector_assets import (
     bluetooth,
     laptop_double,
     laptop_single,