Guest User

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
  59. p2 = p0 + Point(side_length*math.cos(math.radians(60)), side_length*math.sin(math.radians(60)))
  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