#!/usr/bin/env python3
"""Render smooth window STL as orthogonal silhouettes and slice images."""
import struct, numpy as np
from PIL import Image

path = "/app/projects/esp32-box/original/Window_20x60mm_-_liso.stl"

with open(path, "rb") as f:
    f.read(80)
    n = struct.unpack("<I", f.read(4))[0]
    pts = []
    for i in range(n):
        f.read(12)
        for j in range(3):
            x,y,z = struct.unpack("<fff", f.read(12))
            pts.append([x,y,z])
        f.read(2)
pts = np.array(pts)
cx, cy = pts[:,0].mean(), pts[:,1].mean()
pts[:,0] -= cx; pts[:,1] -= cy

OUT = "/app/projects/esp32-box/exports/slices_smooth"
import os; os.makedirs(OUT, exist_ok=True)

def render_pts(pts2d, size=300, margin=2, title=""):
    xmin, xmax = pts2d[:,0].min(), pts2d[:,0].max()
    ymin, ymax = pts2d[:,1].min(), pts2d[:,1].max()
    xr = xmax - xmin + margin*2
    yr = ymax - ymin + margin*2
    scale = min(size/xr, size/yr)
    img = Image.new("RGB", (size, size), "white")
    pix = img.load()
    for x, y in pts2d:
        px = int((x - xmin + margin) * scale)
        py = int((y - ymin + margin) * scale)
        px = max(0, min(size-1, px))
        py = max(0, min(size-1, py))
        pix[px, py] = (50, 100, 200)
    return img

# 1. Front view (XY)
mask = pts[:,2] > 0
img_f = render_pts(pts[mask][:,[0,1]], 400)
img_f.save(f"{OUT}/front_XY.png")
print("Saved front_XY.png")

# 2. Side view (XZ)
mask = np.abs(pts[:,1]) < 0.5
img_s = render_pts(pts[mask][:,[0,2]], 400)
img_s.save(f"{OUT}/side_XZ.png")
print("Saved side_XZ.png")

# 3. Isometric-ish (YZ scatter)
# Just use all points but vary alpha by density
# Skip separate YZ view - not needed
print("Skipping YZ view (no points near X=0 centerline)")

# 4. Also XY at specific Z ranges
for z_name, z_lo, z_hi in [("bottom_0", -0.1, 0.5), ("mid_1_2", 1.0, 1.5), ("top_3", 1.5, 3.3)]:
    mask = (pts[:,2] >= z_lo) & (pts[:,2] <= z_hi)
    if mask.any():
        img = render_pts(pts[mask][:,[0,1]], 400)
        img.save(f"{OUT}/xy_{z_name}.png")
        print(f"Saved xy_{z_name}.png")

# 5. Slice composite
key_z = [0, 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2]
n_cols = 3
n_rows = (len(key_z) + n_cols - 1)//n_cols
comp = Image.new("RGB", (n_cols*250, n_rows*250), "white")
from PIL import ImageDraw
for idx, z in enumerate(key_z):
    mask = np.abs(pts[:,2] - z) < 0.1
    if not mask.any(): continue
    col = idx % n_cols; row = idx // n_cols
    img = render_pts(pts[mask][:,[0,1]], 250)
    comp.paste(img, (col*250, row*250))
    d = ImageDraw.Draw(comp)
    d.text((col*250+5, row*250+5), f"Z={z:.1f}", fill="red")
comp.save(f"{OUT}/composite.png")
print("Saved composite.png")
