Advertisement
here2share

# tk_spiraled_square.py

Feb 9th, 2025
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.39 KB | None | 0 0
  1. # tk_spiraled_square.py
  2.  
  3. import tkinter as tk
  4. import math
  5. from collections import defaultdict
  6.  
  7. WW = HH = 600
  8. N = 15
  9. cell_size = HH // N
  10. flipped = False
  11.  
  12. root = tk.Tk()
  13. root.geometry("+10+10")
  14. root.title("# tk_spiraled_square.py")
  15.  
  16. canvas = tk.Canvas(root, width=WW, height=HH, bg='white')
  17. canvas.pack()
  18.  
  19. def rotate_str(matrix):
  20.     rotated = []
  21.     for col in range(N-1, -1, -1):
  22.         new_row = []
  23.         for row in range(N):
  24.             new_row.append(matrix[row][col])
  25.         rotated.append(''.join(new_row))
  26.     return rotated
  27.  
  28. def replace_zeros(s):
  29.     index = s.find("100")
  30.     if index == -1:
  31.         return s
  32.     before_10 = s[:index + 2]
  33.     after_10 = s[index + 2:]
  34.     index = after_10.find("X")
  35.     old = after_10[:index + 1]
  36.     after_10 = after_10.replace(old, 'X' + '1' * index)
  37.     return before_10 + after_10
  38.  
  39. def generate_fixed_matrix(N):
  40.     matrix = ['0' * N for _ in range(N)]
  41.     matrix[0] = '1' * N
  42.     matrix[-1] = '0X' + '1' * (N - 2)
  43.     matrix = rotate_str(matrix)
  44.     matrix[0] = '1' * N
  45.  
  46.     while True:
  47.         for i in range(N):
  48.             if 'X' in matrix[i]:
  49.                 prev = matrix[i]
  50.                 matrix[i] = replace_zeros(matrix[i])
  51.                 break
  52.         if matrix[i] == prev:
  53.             matrix[i] = prev.replace('X', '1')
  54.             return matrix
  55.         matrix = rotate_str(matrix)
  56.  
  57. spirals = generate_fixed_matrix(N)
  58.  
  59. def get_boundary_segments(matrix, target):
  60.     segments = []
  61.     rows = len(matrix)
  62.     cols = len(matrix[0])
  63.     for i in range(rows):
  64.         for j in range(cols):
  65.             if matrix[i][j] == target:
  66.                 x = j * cell_size
  67.                 y = i * cell_size
  68.                 if i == 0 or matrix[i-1][j] != target:
  69.                     segments.append(((x, y), (x+cell_size, y)))
  70.                 if i == rows-1 or matrix[i+1][j] != target:
  71.                     segments.append(((x+cell_size, y+cell_size), (x, y+cell_size)))
  72.                 if j == 0 or matrix[i][j-1] != target:
  73.                     segments.append(((x, y+cell_size), (x, y)))
  74.                 if j == cols-1 or matrix[i][j+1] != target:
  75.                     segments.append(((x+cell_size, y), (x+cell_size, y+cell_size)))
  76.     return segments
  77.  
  78. def join_segments(segments):
  79.     neighbors = defaultdict(list)
  80.     for a, b in segments:
  81.         neighbors[a].append(b)
  82.         neighbors[b].append(a)
  83.    
  84.     start = next(iter(neighbors))
  85.     polygon = [start]
  86.     prev = None
  87.     current = start
  88.     while True:
  89.         nbs = neighbors[current]
  90.         if prev is None:
  91.             next_v = nbs[0]
  92.         else:
  93.             next_v = nbs[0] if nbs[0] != prev else nbs[1]
  94.         if next_v == start:
  95.             polygon.append(start)
  96.             break
  97.         polygon.append(next_v)
  98.         prev, current = current, next_v
  99.     return polygon
  100.  
  101. def get_polygon_for_color(matrix, target):
  102.     segments = get_boundary_segments(matrix, target)
  103.     poly = join_segments(segments)
  104.     return poly
  105.  
  106. def rotate_polygon(polygon, angle):
  107.     cx, cy = WW // 2, HH // 2
  108.     radians = math.radians(angle)
  109.     cos_a = math.cos(radians)
  110.     sin_a = math.sin(radians)
  111.  
  112.     rotated_poly = []
  113.     for x, y in polygon:
  114.         x -= cx
  115.         y -= cy
  116.         x_new = x * cos_a - y * sin_a + cx
  117.         y_new = x * sin_a + y * cos_a + cy
  118.         rotated_poly.append((x_new, y_new))
  119.    
  120.     return rotated_poly
  121.  
  122. def flip_polygon_vertically(polygon):
  123.     return [(x, HH - y) for x, y in polygon]
  124.  
  125. angle = 0
  126. def update_rotation():
  127.     global angle
  128.     angle += 90
  129.     draw_pattern()
  130.     root.after(1000, update_rotation)
  131.  
  132. def flip_polygons(event):
  133.     global flipped
  134.     flipped = not flipped
  135.     draw_pattern()
  136.  
  137. def draw_pattern():
  138.     global angle, flipped
  139.     canvas.delete("all")
  140.  
  141.     blue_poly = get_polygon_for_color(spirals, '1')
  142.     orange_poly = get_polygon_for_color(spirals, '0')
  143.  
  144.     blue_poly = rotate_polygon(blue_poly, angle)
  145.     orange_poly = rotate_polygon(orange_poly, angle)
  146.  
  147.     if flipped:
  148.         blue_poly = flip_polygon_vertically(blue_poly)
  149.         orange_poly = flip_polygon_vertically(orange_poly)
  150.  
  151.     canvas.create_polygon(blue_poly, fill='blue', outline='black')
  152.     canvas.create_polygon(orange_poly, fill='orange', outline='black')
  153.  
  154.     canvas.create_text(WW // 2, 60, text="Press Spacebar To Flip", font=("Arial", 18), fill="black")
  155.  
  156. root.bind("<space>", flip_polygons)
  157. draw_pattern()
  158. update_rotation()
  159. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement