Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from tkinter import *
- import math
- import dataclasses
- size = 500
- margin = 10
- point_size = 8
- @dataclasses.dataclass
- class Point:
- x: float
- y: float
- def tuple(self): return (self.x, self.y)
- def __add__(self, p): return Point(self.x+p.x, self.y+p.y)
- def __truediv__(self, s): return self * (1/s)
- def __mul__(self, s): return Point(self.x*s, self.y*s)
- def __sub__(self, p): return self + (p*-1)
- def midpoint(a,b):
- return (a+b) / 2
- def lerp(a,b,t):
- """linear interpolation, AKA a linear bezier curve."""
- return (b-a)*t + a
- def bezier(a,b,c):
- """yields coordinates for points on a quadratic bezier curve."""
- num_segments = 16
- for i in range(num_segments+1):
- t = i / num_segments
- yield lerp(lerp(a,b,t), lerp(b,c,t), t)
- def create_smooth_poly(canvas, points, **kwargs):
- """
- emulates the behavior of tkinter's smooth-styled polygon.
- draws a series of quadratic bezier curves,
- using the polygon's vertices as control points,
- and the polygon's edge's midpoints as endpoints.
- """
- assert len(points) >= 3
- spline_points = []
- for i, p3 in enumerate(points):
- p2,p1 = points[i-1],points[i-2]
- spline_points.extend(list(bezier(midpoint(p1,p2), p2, midpoint(p2,p3))))
- return canvas.create_polygon([p.tuple() for p in spline_points], **kwargs)
- def create_point(canvas, p, size, **kwargs):
- """Draw a point on the canvas. Why isn't this a native tkinter method?"""
- w = Point(size/2, size/2)
- canvas.create_arc((p-w).tuple() + (p+w).tuple(), start=0, extent=359, style=CHORD, **kwargs)
- # is anyone else annoyed that you can't make a chord of extent 360?
- def example_square():
- return [Point(margin, margin), Point(margin,size-margin), Point(size-margin,size-margin), Point(size-margin, margin)]
- def example_triangle():
- p0 = Point(margin, margin)
- p1 = Point(size-margin, margin)
- side_length = size - margin/2
- p2 = p0 + Point(side_length*math.cos(math.radians(60)), side_length*math.sin(math.radians(60)))
- return [p0, p1, p2]
- points = example_square()
- rawpoly = [s for p in points for s in p.tuple()]
- root = Tk()
- canvas = Canvas(root, width=size, height=size)
- canvas.pack()
- #poly
- canvas.create_polygon(rawpoly, fill="gray", smooth=False)
- #native tkinter smooth poly
- canvas.create_polygon(rawpoly, outline="red", fill="", smooth=True)
- #custom smooth poly
- create_smooth_poly(canvas, points, outline="blue", fill="")
- #corners
- for p in points:
- create_point(canvas, p, 8, fill="black")
- #midpoints
- w = Point(point_size/2, point_size/2)
- for i, p1 in enumerate(points):
- p0 = points[i-1]
- create_point(canvas, midpoint(p0, p1), 8, fill="green", outline="green")
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement