96 lines
3.1 KiB
Python
96 lines
3.1 KiB
Python
import pcbnew
|
||
from shapely.geometry import MultiPolygon, Polygon
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# KiKit postprocess hook – cleanup.py
|
||
#
|
||
# 1. Copy all Edge.Cuts content (substrate rings) to Eco1_User as segments,
|
||
# EXCEPT the outermost panel rectangle.
|
||
# ---------------------------------------------------------------------------
|
||
|
||
TOLERANCE_NM = 1_000 # 1 µm
|
||
|
||
|
||
def _mm(nm_val):
|
||
return f"{pcbnew.ToMM(int(nm_val)):.4f} mm"
|
||
|
||
|
||
def _collect_rings(geom):
|
||
"""Return all rings as list of (shapely_ring, coord_list)."""
|
||
rings = []
|
||
if isinstance(geom, Polygon):
|
||
rings.append((geom.exterior, list(geom.exterior.coords)))
|
||
for interior in geom.interiors:
|
||
rings.append((interior, list(interior.coords)))
|
||
elif isinstance(geom, MultiPolygon):
|
||
for poly in geom.geoms:
|
||
rings.extend(_collect_rings(poly))
|
||
return rings
|
||
|
||
|
||
def _is_outer_frame(ring_geom, x0, y0, x1, y1, tol=TOLERANCE_NM):
|
||
"""True if the ring's bounding box equals the panel bounding box."""
|
||
b = ring_geom.bounds
|
||
return (abs(b[0] - x0) <= tol and abs(b[1] - y0) <= tol and
|
||
abs(b[2] - x1) <= tol and abs(b[3] - y1) <= tol)
|
||
|
||
|
||
def _shapely_to_segments(board, coords, layer, width_mm=0.05):
|
||
pts = list(coords)
|
||
if not pts:
|
||
return 0
|
||
if pts[0] != pts[-1]:
|
||
pts.append(pts[0])
|
||
count = 0
|
||
for i in range(len(pts) - 1):
|
||
seg = pcbnew.PCB_SHAPE(board)
|
||
seg.SetShape(pcbnew.SHAPE_T_SEGMENT)
|
||
seg.SetLayer(layer)
|
||
seg.SetWidth(pcbnew.FromMM(width_mm))
|
||
seg.SetStart(pcbnew.VECTOR2I(int(pts[i][0]), int(pts[i][1])))
|
||
seg.SetEnd (pcbnew.VECTOR2I(int(pts[i+1][0]), int(pts[i+1][1])))
|
||
board.Add(seg)
|
||
count += 1
|
||
return count
|
||
|
||
|
||
def kikitPostprocess(panel, arg):
|
||
print("=" * 60)
|
||
print("[cleanup] START")
|
||
|
||
board = panel.board
|
||
substrate = panel.boardSubstrate
|
||
|
||
# outer panel bbox
|
||
b = substrate.bounds()
|
||
x0, y0, x1, y1 = int(b[0]), int(b[1]), int(b[2]), int(b[3])
|
||
print(f"[cleanup] Panel bbox: ({_mm(x0)},{_mm(y0)})–({_mm(x1)},{_mm(y1)})")
|
||
|
||
# get substrate geometry
|
||
geom = None
|
||
for attr in ("substrates", "substrate", "_substrate", "geometry"):
|
||
if hasattr(substrate, attr):
|
||
geom = getattr(substrate, attr)
|
||
break
|
||
if geom is None:
|
||
print("[cleanup] ERROR: cannot access substrate geometry")
|
||
return
|
||
|
||
rings = _collect_rings(geom)
|
||
print(f"[cleanup] Total rings in substrate: {len(rings)}")
|
||
|
||
total = 0
|
||
for i, (ring_geom, coords) in enumerate(rings):
|
||
rb = ring_geom.bounds
|
||
if _is_outer_frame(ring_geom, x0, y0, x1, y1):
|
||
print(f"[cleanup] ring[{i}] pts={len(coords)-1} → OUTER FRAME, skipped")
|
||
continue
|
||
n = _shapely_to_segments(board, coords, pcbnew.Eco1_User)
|
||
total += n
|
||
print(f"[cleanup] ring[{i}] pts={len(coords)-1}"
|
||
f" bbox=({_mm(rb[0])},{_mm(rb[1])})–({_mm(rb[2])},{_mm(rb[3])})"
|
||
f" → {n} segments on Eco1_User")
|
||
|
||
print(f"[cleanup] Total Eco1_User segments added: {total}")
|
||
print("[cleanup] END")
|
||
print("=" * 60) |