#!/usr/bin/env python3
"""Extract precise outline of Window 20x60mm at each Z level."""
import struct, numpy as np

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]
    verts = []
    for i in range(n):
        f.read(12)
        tri = []
        for j in range(3):
            x, y, z = struct.unpack('<fff', f.read(12))
            tri.append([x, y, z])
        f.read(2)
        verts.append(tri)

verts = np.array(verts)
all_pts = verts.reshape(-1, 3)

# Center at origin
x_cent = all_pts[:,0].mean()
y_cent = all_pts[:,1].mean()
all_pts[:,0] -= x_cent
all_pts[:,1] -= y_cent

print("Centered at: X=0, Y=0")
print("X range: %.2f to %.2f (%.2f)" % (all_pts[:,0].min(), all_pts[:,0].max(), all_pts[:,0].max()-all_pts[:,0].min()))
print("Y range: %.2f to %.2f (%.2f)" % (all_pts[:,1].min(), all_pts[:,1].max(), all_pts[:,1].max()-all_pts[:,1].min()))
print("Z range: %.2f to %.2f (%.2f)" % (all_pts[:,2].min(), all_pts[:,2].max(), all_pts[:,2].max()-all_pts[:,2].min()))

# Extract perimeter at key Z bands (±0.05 tolerance)
z_bands = [(0.0, 0.1), (1.55, 1.65), (1.9, 2.1), (3.15, 3.25), (4.75, 4.85)]
z_labels = ["Z=0 (base)", "Z=1.6 (tier1 top)", "Z=2.0 (transition)", "Z=3.2 (tier2 top)", "Z=4.8 (tier3 top)"]

for (z_lo, z_hi), label in zip(z_bands, z_labels):
    mask = (all_pts[:,2] >= z_lo) & (all_pts[:,2] <= z_hi)
    pts = all_pts[mask]
    if len(pts) == 0:
        continue
    
    print("\n--- %s (%d pts) ---" % (label, len(pts)))
    print("  X: %.2f .. %.2f (%.2f)" % (pts[:,0].min(), pts[:,0].max(), pts[:,0].max()-pts[:,0].min()))
    print("  Y: %.2f .. %.2f (%.2f)" % (pts[:,1].min(), pts[:,1].max(), pts[:,1].max()-pts[:,1].min()))
    
    # Get X values at top and bottom Y edges
    y_top = pts[:,1].max()
    y_bot = pts[:,1].min()
    
    # At top edge (Y near y_top)
    top_mask = pts[:,1] > y_top - 0.5
    top_pts = pts[top_mask]
    print("  Top edge (Y~%.1f): X=%+.2f .. %+.2f" % (y_top, top_pts[:,0].min(), top_pts[:,0].max()))
    
    # At bottom edge
    bot_mask = pts[:,1] < y_bot + 0.5
    bot_pts = pts[bot_mask]
    print("  Bot edge (Y~%.1f): X=%+.2f .. %+.2f" % (y_bot, bot_pts[:,0].min(), bot_pts[:,0].max()))
    
    # At center Y
    y_mid_mask = (pts[:,1] > -0.5) & (pts[:,1] < 0.5)
    mid_pts = pts[y_mid_mask]
    if len(mid_pts) > 0:
        xs = np.unique(np.round(mid_pts[:,0], 1))
        # Find gaps
        if len(xs) > 1:
            gaps = []
            for i in range(len(xs)-1):
                if xs[i+1] - xs[i] > 2.0:
                    gaps.append((xs[i], xs[i+1]))
            if gaps:
                print("  Mid Y gaps:", gaps)
            else:
                print("  Mid Y: X=%+.1f .. %+.1f" % (xs.min(), xs.max()))
