 # Untitled

a guest
May 11th, 2021
20
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. from tkinter import *
2. import math
3. import dataclasses
4. size = 500
5. margin = 10
6. point_size = 8
7.
8. @dataclasses.dataclass
9. class Point:
10. x: float
11. y: float
12. def tuple(self): return (self.x, self.y)
13. def __add__(self, p): return Point(self.x+p.x, self.y+p.y)
14. def __truediv__(self, s): return self * (1/s)
15. def __mul__(self, s): return Point(self.x*s, self.y*s)
16. def __sub__(self, p): return self + (p*-1)
17.
18. def midpoint(a,b):
19. return (a+b) / 2
20.
21. def lerp(a,b,t):
22. """linear interpolation, AKA a linear bezier curve."""
23. return (b-a)*t + a
24.
25. def bezier(a,b,c):
26. """yields coordinates for points on a quadratic bezier curve."""
27. num_segments = 16
28. for i in range(num_segments+1):
29. t = i / num_segments
30. yield lerp(lerp(a,b,t), lerp(b,c,t), t)
31.
32. def create_smooth_poly(canvas, points, **kwargs):
33. """
34. emulates the behavior of tkinter's smooth-styled polygon.
35. draws a series of quadratic bezier curves,
36. using the polygon's vertices as control points,
37. and the polygon's edge's midpoints as endpoints.
38. """
39. assert len(points) >= 3
40. spline_points = []
41. for i, p3 in enumerate(points):
42. p2,p1 = points[i-1],points[i-2]
43. spline_points.extend(list(bezier(midpoint(p1,p2), p2, midpoint(p2,p3))))
44. return canvas.create_polygon([p.tuple() for p in spline_points], **kwargs)
45.
46. def create_point(canvas, p, size, **kwargs):
47. """Draw a point on the canvas. Why isn't this a native tkinter method?"""
48. w = Point(size/2, size/2)
49. canvas.create_arc((p-w).tuple() + (p+w).tuple(), start=0, extent=359, style=CHORD, **kwargs)
50. # is anyone else annoyed that you can't make a chord of extent 360?
51.
52. def example_square():
53. return [Point(margin, margin), Point(margin,size-margin), Point(size-margin,size-margin), Point(size-margin, margin)]
54.
55. def example_triangle():
56. p0 = Point(margin, margin)
57. p1 = Point(size-margin, margin)
58. side_length = size - margin/2
60. return [p0, p1, p2]
61.
62. points = example_square()
63. rawpoly = [s for p in points for s in p.tuple()]
64.
65. root = Tk()
66. canvas = Canvas(root, width=size, height=size)
67. canvas.pack()
68.
69. #poly
70. canvas.create_polygon(rawpoly, fill="gray", smooth=False)
71. #native tkinter smooth poly
72. canvas.create_polygon(rawpoly, outline="red", fill="", smooth=True)
73. #custom smooth poly
74. create_smooth_poly(canvas, points, outline="blue", fill="")
75.
76. #corners
77. for p in points:
78. create_point(canvas, p, 8, fill="black")
79.
80. #midpoints
81. w = Point(point_size/2, point_size/2)
82. for i, p1 in enumerate(points):
83. p0 = points[i-1]
84. create_point(canvas, midpoint(p0, p1), 8, fill="green", outline="green")
85.
86. root.mainloop()
RAW Paste Data