seveibar/pd-dual-stepper-controller
Bottom-side PCB silkscreen artwork consisting of embedded mirrored TS Circuit SVG logos, with via-clearance-aware lower-board placement.
- Version
- 0.1.0
- License
- unset
- Stars
- 0
scripts/resume-freerouting.py
"""Add the routed session to the authoritative DSN as editable copper for another routing pass."""
from freerouting_geometry import *
text=Path(sys.argv[1] if len(sys.argv)>1 else 'work/freerouting/routed.ses').read_text().replace('(string_quote ")','(string_quote DQUOTE)')
tokens=re.findall(r'"(?:[^"\\]|\\.)*"|[()]|[^\s()]+',text);stack=[];tree=None
for token in tokens:
if token=='(':
obj=[]
if stack:stack[-1].append(obj)
stack.append(obj)
elif token==')':tree=stack.pop()
else:stack[-1].append(token.strip('"'))
def entries(a,k):return [x for x in a if isinstance(x,list) and x and x[0]==k]
def one(a,k):return next(iter(entries(a,k)),None)
routes=one(tree,'routes');res=one(routes,'resolution');scale={'um':.001,'mm':1}[res[1]]/float(res[2]);copper=[]
fixed=[e for e in j if e['type']=='pcb_via']
for net in entries(one(routes,'network_out'),'net'):
for wire in entries(net,'wire'):
path=one(wire,'path');copper.append('(wire (path '+path[1]+' '+' '.join(u(float(v)*scale) for v in path[2:])+f') (net {net[1]}) (type normal))')
for via in entries(net,'via'):
x,y=float(via[2])*scale,float(via[3])*scale
if any(math.hypot(x-e['x'],y-e['y'])<.0002 for e in fixed):continue
copper.append(f'(via VIA {xy(x,y)} (net {net[1]}) (type normal))')
fresh=Path(sys.argv[2] if len(sys.argv)>2 else 'work/freerouting/board.dsn').read_text();assert fresh.endswith(')\n)\n')
Path(sys.argv[3] if len(sys.argv)>3 else 'work/freerouting/resume-clean.dsn').write_text(fresh[:-4]+'\n'+'\n'.join(copper)+'\n)\n)\n')
print('Preserved',len(copper),'editable wire/via objects')