Add packed layout Python prototype
This commit is contained in:
Executable
+159
@@ -0,0 +1,159 @@
|
||||
import tkinter as tk
|
||||
from positions import *
|
||||
|
||||
TEXT_SIZE = 14
|
||||
PADDING = 40
|
||||
OVERLAP_OUTLINE_WIDTH = 4
|
||||
SCREEN_WIDTH=1200
|
||||
SCREEN_HEIGHT=160
|
||||
VSCALE=2
|
||||
|
||||
def rgb_to_hex(rgb):
|
||||
r, g, b = rgb
|
||||
return f"#{r:02x}{g:02x}{b:02x}"
|
||||
|
||||
|
||||
def rect_bounds(box):
|
||||
return box.get_left(), box.get_top(), box.get_right(), box.get_bottom()
|
||||
|
||||
|
||||
def intersection(a, b):
|
||||
ax1, ay1, ax2, ay2 = rect_bounds(a)
|
||||
bx1, by1, bx2, by2 = rect_bounds(b)
|
||||
|
||||
x1 = max(ax1, bx1)
|
||||
y1 = max(ay1, by1)
|
||||
x2 = min(ax2, bx2)
|
||||
y2 = min(ay2, by2)
|
||||
|
||||
if x1 < x2 and y1 < y2:
|
||||
return x1, y1, x2, y2
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def visualize_packing(items):
|
||||
root = tk.Tk()
|
||||
root.title("Rectangle Packing Visualizer")
|
||||
|
||||
canvas_width = SCREEN_WIDTH + PADDING * 2
|
||||
canvas_height = SCREEN_HEIGHT*VSCALE + PADDING * 2
|
||||
|
||||
canvas = tk.Canvas(
|
||||
root,
|
||||
width=canvas_width,
|
||||
height=canvas_height,
|
||||
bg="black",
|
||||
highlightthickness=0
|
||||
)
|
||||
canvas.pack()
|
||||
|
||||
ox = PADDING
|
||||
oy = PADDING
|
||||
|
||||
# Outer perimeter
|
||||
canvas.create_rectangle(
|
||||
ox,
|
||||
oy,
|
||||
ox + SCREEN_WIDTH,
|
||||
oy + SCREEN_HEIGHT*VSCALE,
|
||||
fill="white",
|
||||
outline="white"
|
||||
)
|
||||
|
||||
boxes = [box for item in items for box in item.boxes]
|
||||
|
||||
# Draw boxes
|
||||
for box in boxes:
|
||||
x1 = ox + box.get_left()
|
||||
y1 = oy + box.get_top() * VSCALE
|
||||
x2 = ox + box.get_right()
|
||||
y2 = oy + box.get_bottom() * VSCALE
|
||||
|
||||
canvas.create_rectangle(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
fill=rgb_to_hex(box.item.color),
|
||||
outline="black"
|
||||
)
|
||||
|
||||
# Icon containers draw only vertical separators for simulated icon/dot slots.
|
||||
if box.item.is_icon_item and box is box.item.boxes[0]:
|
||||
cursor = box.get_left()
|
||||
for kind, width in box.item.render_segments()[:-1]:
|
||||
cursor += width
|
||||
x = ox + cursor
|
||||
canvas.create_line(
|
||||
x,
|
||||
y1,
|
||||
x,
|
||||
y2,
|
||||
fill="black",
|
||||
width=2,
|
||||
)
|
||||
|
||||
# Draw overlap regions
|
||||
for i in range(len(boxes)):
|
||||
for j in range(i + 1, len(boxes)):
|
||||
if boxes[i].item is boxes[j].item:
|
||||
continue
|
||||
overlap = intersection(boxes[i], boxes[j])
|
||||
|
||||
if overlap:
|
||||
x1, y1, x2, y2 = overlap
|
||||
y1 *= VSCALE
|
||||
y2 *= VSCALE
|
||||
|
||||
x1 += ox
|
||||
y1 += oy
|
||||
x2 += ox
|
||||
y2 += oy
|
||||
|
||||
# Red overlap area
|
||||
canvas.create_rectangle(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
fill="red",
|
||||
outline="red"
|
||||
)
|
||||
|
||||
# Thick red circle around overlap
|
||||
cx = (x1 + x2) / 2
|
||||
cy = (y1 + y2) / 2
|
||||
radius = max(x2 - x1, y2 - y1) / 2 + 12
|
||||
|
||||
canvas.create_oval(
|
||||
cx - radius,
|
||||
cy - radius,
|
||||
cx + radius,
|
||||
cy + radius,
|
||||
outline="red",
|
||||
width=OVERLAP_OUTLINE_WIDTH
|
||||
)
|
||||
|
||||
# Draw item texts
|
||||
for item in items:
|
||||
x1 = ox + item.get_left()
|
||||
y1 = oy + item.get_top() * VSCALE
|
||||
x2 = ox + item.get_right()
|
||||
y2 = oy + item.get_bottom() * VSCALE
|
||||
|
||||
canvas.create_text(
|
||||
(x1 + x2) / 2,
|
||||
(y1 + y2) / 2,
|
||||
text=item.rendername(),
|
||||
font=("Arial", TEXT_SIZE),
|
||||
fill="black"
|
||||
)
|
||||
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
containers = position_containers()
|
||||
|
||||
visualize_packing(containers)
|
||||
Reference in New Issue
Block a user