#!/usr/bin/env python3
"""Generate silhouette images of the STL from each axis using numpy/PIL."""
import struct, numpy as np
from PIL import Image

path = "/app/projects/esp32-box/original/Window 20x60mm.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)
# Center XY
cx, cy = pts[:,0].mean(), pts[:,1].mean()
pts[:,0] -= cx
pts[:,1] -= cy

def project_2d(pts, u_axis, v_axis, size=500, margin=3):
    """Project 3D points onto 2D plane defined by u/v axes."""
    u = pts[:,u_axis]
    v = pts[:,v_axis]
    u_min, u_max = u.min(), u.max()
    v_min, v_max = v.min(), v.max()
    u_range = u_max - u_min + margin*2
    v_range = v_max - v_min + margin*2
    scale = min(size / u_range, size / v_range)
    u_pix = ((u - u_min + margin) * scale).astype(int)
    v_pix = ((v - v_min + margin) * scale).astype(int)
    # Clamp
    u_pix = np.clip(u_pix, 0, size-1)
    v_pix = np.clip(v_pix, 0, size-1)
    return u_pix, v_pix, u_range, v_range, scale

def render_silhouette(pts, zdim, u_axis, v_axis, z_axis, size=500, margin=3):
    """Render silhouette projection using full vertex cloud."""
    u, v, u_range, v_range, scale = project_2d(pts, u_axis, v_axis, size, margin)
    img = Image.new("RGB", (size, size), "white")
    pix = img.load()
    for ui, vi in zip(u, v):
        pix[ui, vi] = (100, 100, 200)
    # Highlight edges: check range
    print(f"  Range: %s=[%.1f..%.1f] %s=[%.1f..%.1f]" % (
         "XYZ"[u_axis], pts[:,u_axis].min(), pts[:,u_axis].max(),
         "XYZ"[v_axis], pts[:,v_axis].min(), pts[:,v_axis].max()))
    return img

OUT = "/app/projects/esp32-box/exports"

# Front view: looking at XY plane (Z is depth)
print("=== FRONT VIEW (XY plane) ===")
img = render_silhouette(pts, 2, 0, 1, 2)
img.save(f"{OUT}/window_front.png")
print(f"Saved window_front.png")

# Side view: looking at XZ plane (Y is depth)
print("=== SIDE VIEW (XZ plane) ===")
img2 = render_silhouette(pts, 1, 0, 2, 1)
img2.save(f"{OUT}/window_side.png")
print(f"Saved window_side.png")

# Top view: looking at YZ plane (X is depth)
print("=== TOP VIEW (YZ plane) ===")
img3 = render_silhouette(pts, 0, 1, 2, 0)
img3.save(f"{OUT}/window_top.png")
print(f"Saved window_top.png")

# Also save a silhouette with all points
img4 = Image.new("RGB", (500, 500), "black")
pix4 = img4.load()
u, v, _, _, _ = project_2d(pts, 0, 1)
for ui, vi in zip(u, v):
    pix4[ui, vi] = (200, 200, 255)
img4.save(f"{OUT}/window_front_dense.png")
print(f"Saved window_front_dense.png")

print("\nDONE")
