imrishabh18/corne-keyboard
The code defines and renders two surface-mount chip components with SMT pads, silkscreen outlines, and 3D CAD models (OBJ and STEP) for PCB assembly.
- Version
- 2.0.21
- License
- unset
- Stars
- 1
scripts/refine-left-local.ts
import fs from 'node:fs'
import * as C from '@tscircuit/checks'
let circuit=JSON.parse(fs.readFileSync('../left-refined.circuit.json','utf8'))
const checkNames=['checkEachPcbTraceNonOverlapping','checkPadTraceClearance','checkViaTraceClearance','checkViaPadClearance','checkSameNetViaSpacing','checkDifferentNetViaSpacing','checkCopperToBoardEdgeClearance','checkPcbCopperOverKeepout']
const errors=(c:any[])=>C.dedupePcbDrcErrors(checkNames.flatMap(k=>(C as any)[k](c)))
const score=(e:any[])=>e.reduce((s,e)=>s+100+Math.max(0,0.1-(e.actual_clearance??Number(e.message.match(/gap: ([\d.-]+)/)?.[1]??0))),0)
const move=(c:any[],from:any,to:any)=>{for(const x of c){if(x.type==='pcb_via'&&Math.hypot(x.x-from.x,x.y-from.y)<1e-6){x.x=to.x;x.y=to.y}if(x.type==='pcb_trace')for(const p of x.route)if(Math.hypot(p.x-from.x,p.y-from.y)<1e-6&&!p.start_pcb_port_id&&!p.end_pcb_port_id){p.x=to.x;p.y=to.y}}}
let current=errors(circuit)
function tryCandidates(label:string,candidates:any[][]){let value=score(current);for(const c of candidates){const e=errors(c);if(score(e)<value-1e-8){circuit=c;current=e;value=score(e);console.log(label,current.length,current.map((x:any)=>x.message));fs.writeFileSync('../left-local.circuit.json',JSON.stringify(circuit))}}}
for(const id of ['pcb_via_95','pcb_via_27','pcb_via_29']){const v=circuit.find((x:any)=>x.pcb_via_id===id);const cs=[];for(const r of id==='pcb_via_95'?[.01,.015,.02,.025]:[.04,.08,.12])for(let k=0;k<8;k++){const c=structuredClone(circuit);move(c,v,{x:v.x+r*Math.cos(k*Math.PI/4),y:v.y+r*Math.sin(k*Math.PI/4)});cs.push(c)}tryCandidates(id,cs)}
for(const [traceId,point] of [['source_trace_110_mst4_0',circuit.find((x:any)=>x.pcb_via_id==='pcb_via_204')],['source_trace_106_mst0_0',{x:48.378311815468294,y:36.835393010126225}] ] as any[]){
const base=circuit,trace=base.find((x:any)=>x.pcb_trace_id===traceId&&x.type==='pcb_trace');const candidates=[]
for(let i=1;i<trace.route.length;i++){const a=trace.route[i-1],b=trace.route[i];if(a.route_type!=='wire'||b.route_type!=='wire'||a.layer!==b.layer)continue;const dx=b.x-a.x,dy=b.y-a.y,len=Math.hypot(dx,dy);if(len<.001)continue;const t=Math.max(0,Math.min(1,((point.x-a.x)*dx+(point.y-a.y)*dy)/(len*len)));const closest={x:a.x+t*dx,y:a.y+t*dy};if(Math.hypot(closest.x-point.x,closest.y-point.y)>.6)continue;
for(const span of [.25,.5,1])for(const offset of [-.15,-.08,-.03,.03,.08,.15]){const u=Math.max(0,t-span/len),v=Math.min(1,t+span/len);const p={x:a.x+u*dx,y:a.y+u*dy},q={x:a.x+v*dx,y:a.y+v*dy};const nx=-dy/len*offset,ny=dx/len*offset;const c=structuredClone(base);const tr=c.find((x:any)=>x.type==='pcb_trace'&&x.pcb_trace_id===traceId);const wire=(p:any)=>({route_type:'wire',layer:a.layer,width:a.width,x:p.x,y:p.y});tr.route.splice(i,0,wire(p),wire({x:p.x+nx,y:p.y+ny}),wire({x:q.x+nx,y:q.y+ny}),wire(q));candidates.push(c)}
}tryCandidates(traceId,candidates)
}
const final=C.dedupePcbDrcErrors([...(await C.runAllRoutingChecks(circuit)),...C.checkCopperToBoardEdgeClearance(circuit),...C.checkPcbCopperOverKeepout(circuit)])
fs.writeFileSync('../left-local.circuit.json',JSON.stringify(circuit,null,2));fs.writeFileSync('../left-local.errors.json',JSON.stringify(final,null,2));console.log('FINAL',final.length,final.map((e:any)=>e.message))