Skip to content

Commit 56201e7

Browse files
RivasMarioclaude
andcommitted
KLE: drop RAlt (2 keys left of arrows) + add notch-grow/screw post-process
skyway96_kle.json: bottom row now Space | gap | RCtrl | Fn | arrows, with a 1u gap so RCtrl/Fn/arrows/numpad stay aligned to the PCB (original at .bak). scripts/postprocess_plate.py: grow edge notches + set screw-hole diameter, re-emit clean layered DXF (SendCutSend-ready). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent cfce35c commit 56201e7

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

scripts/postprocess_plate.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#!/usr/bin/env python3
2+
"""Post-process a generated plate DXF: grow edge notches for install clearance
3+
and normalize screw-hole diameter. Re-emits a clean layered DXF.
4+
5+
Usage:
6+
python scripts/postprocess_plate.py IN.dxf OUT.dxf [--notch-grow 1.0] [--screw-dia 2.6]
7+
"""
8+
import argparse, ezdxf
9+
from shapely.geometry import Polygon, box, MultiPolygon
10+
from shapely.ops import unary_union
11+
12+
13+
def loops(msp, layer):
14+
out = []
15+
for e in msp.query(f'LWPOLYLINE[layer=="{layer}"]'):
16+
pts = [(p[0], p[1]) for p in e.get_points()]
17+
if len(pts) >= 3:
18+
out.append(pts)
19+
return out
20+
21+
22+
def main():
23+
ap = argparse.ArgumentParser()
24+
ap.add_argument('inp'); ap.add_argument('out')
25+
ap.add_argument('--notch-grow', type=float, default=1.0)
26+
ap.add_argument('--screw-dia', type=float, default=2.6)
27+
a = ap.parse_args()
28+
r = a.screw_dia / 2.0
29+
30+
doc = ezdxf.readfile(a.inp); msp = doc.modelspace()
31+
switch = [Polygon(p) for p in loops(msp, 'SWITCH_CUTOUTS') if len(p) >= 3]
32+
stab = [Polygon(p) for p in loops(msp, 'STAB_CUTOUTS') if len(p) >= 3]
33+
screws = [(c.dxf.center.x, c.dxf.center.y) for c in msp.query('CIRCLE[layer=="PCB_SCREW_HOLES"]')]
34+
polys = [Polygon(p) for p in loops(msp, 'PLATE_OUTLINE') if len(p) >= 3]
35+
polys = sorted([p for p in polys if p.is_valid and p.area > 5], key=lambda p: p.area, reverse=True)
36+
main_poly, internal = polys[0], polys[1:]
37+
38+
# grow notches: the "bites" the perimeter takes out of its bounding box
39+
bites = box(*main_poly.bounds).difference(main_poly)
40+
geoms = [bites] if isinstance(bites, Polygon) else list(bites.geoms)
41+
real = [g for g in geoms if g.area > 2.0] # ignore corner slivers
42+
if real:
43+
grown = unary_union([g.buffer(a.notch_grow, join_style=2) for g in real])
44+
main_poly = main_poly.difference(grown)
45+
if isinstance(main_poly, MultiPolygon):
46+
main_poly = max(main_poly.geoms, key=lambda p: p.area)
47+
print(f"notches grown: {len(real)} (+{a.notch_grow}mm)")
48+
49+
out = ezdxf.new('R2010', setup=True); m = out.modelspace()
50+
for n, c in {'PLATE_OUTLINE': 7, 'SWITCH_CUTOUTS': 3, 'STAB_CUTOUTS': 5, 'PCB_SCREW_HOLES': 1}.items():
51+
out.layers.add(n, color=c)
52+
53+
def addp(poly, layer):
54+
ext = list(poly.exterior.coords)
55+
m.add_lwpolyline(ext[:-1] if ext[0] == ext[-1] else ext, close=True, dxfattribs={'layer': layer})
56+
for ring in poly.interiors:
57+
ri = list(ring.coords)
58+
m.add_lwpolyline(ri[:-1] if ri[0] == ri[-1] else ri, close=True, dxfattribs={'layer': layer})
59+
60+
addp(main_poly, 'PLATE_OUTLINE')
61+
for p in internal: addp(p, 'PLATE_OUTLINE')
62+
for p in switch: addp(p, 'SWITCH_CUTOUTS')
63+
for p in stab: addp(p, 'STAB_CUTOUTS')
64+
for x, y in screws: m.add_circle((x, y), r, dxfattribs={'layer': 'PCB_SCREW_HOLES'})
65+
out.saveas(a.out)
66+
print(f"wrote {a.out} switches={len(switch)} stabs={len(stab)} screws={len(screws)}{a.screw_dia})")
67+
68+
69+
if __name__ == '__main__':
70+
main()

skyway96_kle.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
[{"w":1.5},"Tab","Q","W","E","R","T","Y","U","I","O","P","{\n[","}\n]",{"w":1.5},"|\n\\","7\nHome","8\n","9\nPgUp",{"a":6,"h":2},"+"],
55
[{"a":4,"w":1.75},"Caps Lock","A","S","D","F","G","H","J","K","L",":\n;","\"\n'",{"w":2.25},"Enter","4\n","5","6\n"],
66
[{"w":2.25},"Shift","Z","X","C","V","B","N","M","<\n,",">\n.","?\n/",{"w":1.75},"Shift",{"a":7},"",{"a":4},"1\nEnd","2\n","3\nPgDn",{"h":2},"Enter"],
7-
[{"w":1.25},"Ctrl",{"w":1.25},"Win",{"w":1.25},"Alt",{"a":7,"w":6.25},"",{"a":4},"Alt","Ctrl","FN",{"a":7},"","","",{"a":4},"0\nIns",".\nDel"]
7+
[{"w":1.25},"Ctrl",{"w":1.25},"Win",{"w":1.25},"Alt",{"a":7,"w":6.25},"",{"a":4,"x":1},"Ctrl","FN",{"a":7},"","","",{"a":4},"0\nIns",".\nDel"]
88
]

0 commit comments

Comments
 (0)