import trimesh
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import os

OUTPUT_DIR = "/DATA/AppData/hermes/Projekte/3d"
os.makedirs(OUTPUT_DIR, exist_ok=True)
NAME = "box_30x180x50_rounded"

# ─── PARAMETERS ─────────────────────
OUTER_W = 30    # mm (3 cm)
OUTER_L = 180   # mm (18 cm)
OUTER_H = 50    # mm (5 cm)
WALL   = 1.5    # mm Wandstärke
R      = 5.0    # mm Eckradius aussen
ARC    = 32     # Zylinder-Segmente
# ─────────────────────────────────────

INNER_W = OUTER_W - 2*WALL
INNER_L = OUTER_L - 2*WALL
INNER_R = max(0.5, R - WALL)

def make_box(w, d, h, center=(0,0,0)):
    m = trimesh.creation.box(extents=[w, d, h])
    m.apply_translation(center)
    return m

def round_vertical_edges(mesh, w, d, h, r, arc=32):
    """Subtrahiert Zylinder an allen 4 vertikalen Ecken."""
    hw, hl = w/2 - r, d/2 - r
    for sx in [-1, 1]:
        for sy in [-1, 1]:
            cyl = trimesh.creation.cylinder(radius=r, height=h + 2, sections=arc)
            cyl.apply_translation([sx * hw, sy * hl, h/2])
            mesh = mesh.difference(cyl)
    return mesh

# --- Outer (solid, rounded) ---
outer = make_box(OUTER_W, OUTER_L, OUTER_H, center=(0, 0, OUTER_H/2))
outer = round_vertical_edges(outer, OUTER_W, OUTER_L, OUTER_H, R, ARC)

# --- Inner cavity (solid, rounded) ---
# Starts at z=WALL, goes to z=OUTER_H
inner_h = OUTER_H - WALL
inner = make_box(INNER_W, INNER_L, inner_h, center=(0, 0, OUTER_H - inner_h/2))
inner = round_vertical_edges(inner, INNER_W, INNER_L, inner_h, INNER_R, ARC)

# --- Boolean ---
result = outer.difference(inner)

# ─── OUTPUT ────────────────────────
bb = result.extents
warnings = []
if max(bb) > 180:
    warnings.append(f"Exceeds A1 Mini: {bb[0]:.1f}x{bb[1]:.1f} mm")
if not result.is_watertight:
    warnings.append("Mesh not watertight")

stl = f"{OUTPUT_DIR}/{NAME}.stl"
png = f"{OUTPUT_DIR}/{NAME}.png"
result.export(stl)

fig = plt.figure(figsize=(15, 5))
ax = fig.add_subplot(111, projection='3d')
ax.add_collection3d(Poly3DCollection(
    result.vertices[result.faces], alpha=0.85, edgecolor='k',
    linewidth=0.1, facecolor='#7aa6d8'))
v = result.vertices
ax.set_xlim(v[:,0].min(), v[:,0].max())
ax.set_ylim(v[:,1].min(), v[:,1].max())
ax.set_zlim(v[:,2].min(), v[:,2].max())
ax.set_box_aspect([float(np.ptp(v[:,i])) for i in range(3)])
ax.set_xlabel('X (mm)'); ax.set_ylabel('Y (mm)'); ax.set_zlabel('Z (mm)')
ax.set_title(f"{NAME} — {bb[0]:.1f}×{bb[1]:.1f}×{bb[2]:.1f} mm | R={R}mm")
plt.tight_layout()
plt.savefig(png, dpi=110, bbox_inches='tight'); plt.close()

print(f"OK {NAME}")
print(f"   Aussenmasse:  {bb[0]:.1f} × {bb[1]:.1f} × {bb[2]:.1f} mm")
print(f"   Wandstärke:   {WALL} mm")
print(f"   Eckradius:    {R} mm (aussen), {INNER_R:.1f} mm (innen)")
print(f"   Volumen:      {result.volume/1000:.1f} cm³")
print(f"   Watertight:   {result.is_watertight}")
print(f"   STL:          {stl}")
for w in warnings:
    print(f"   WARN: {w}")
