hrithik18k/metal-touch-panel

A PCB autorouting wrapper that corrects footprint-trace obstacle dimensions, solves routes with a preloaded trace-graph solver, and reports completed traces or routing errors.

Version
1.0.0
License
unset
Stars
0

scripts/audit-coil-clearance.mjs

import fs from 'node:fs';
const filename=process.argv[2]??'dist/index/circuit.json';
const a=JSON.parse(fs.readFileSync(filename,'utf8'));
const coils=a.filter(e=>e.type==='pcb_trace'&&e.pcb_component_id&&e.route.length>40);
function pd(p,a,b){const dx=b.x-a.x,dy=b.y-a.y;const t=Math.max(0,Math.min(1,((p.x-a.x)*dx+(p.y-a.y)*dy)/(dx*dx+dy*dy||1)));return Math.hypot(p.x-a.x-t*dx,p.y-a.y-t*dy)}
function sd(a,b,c,d){const cross=(u,v,w)=>(v.x-u.x)*(w.y-u.y)-(v.y-u.y)*(w.x-u.x); if(cross(a,b,c)*cross(a,b,d)<0&&cross(c,d,a)*cross(c,d,b)<0)return 0;return Math.min(pd(a,c,d),pd(b,c,d),pd(c,a,b),pd(d,a,b));}
const collisions=[];
for(const c of coils){
 const ends=[c.route[0],c.route.at(-1)];
 for(const t of a.filter(e=>e.type==='pcb_trace'&&!coils.includes(e))){
  for(let i=1;i<c.route.length;i++)for(let j=1;j<t.route.length;j++){
   const u=c.route[i-1],v=c.route[i],p=t.route[j-1],q=t.route[j];
   if(p.route_type!=='wire'||q.route_type!=='wire'||p.layer!=='top'||q.layer!=='top')continue;
   // Only endpoint copper may touch the winding. Exempt only tiny terminal segments.
   if(ends.some(e=>Math.hypot(p.x-e.x,p.y-e.y)<0.55&&Math.hypot(q.x-e.x,q.y-e.y)<0.55))continue;
   const gap=sd(u,v,p,q)-(u.width+p.width)/2;
   if(gap<0.10-1e-6){
    const touchesTerminal=(i===1||i===c.route.length-1)&&ends.some(e=>pd(e,p,q)<0.001);
    if(!touchesTerminal)collisions.push({coil:c.pcb_trace_id,trace:t.pcb_trace_id,coilSegment:i,traceSegment:j,gapMm:+gap.toFixed(5)});
   }
  }
 }
}
const summary={file:filename,coils:coils.length,collisions,errors:a.filter(e=>e.type.endsWith('_error')).map(e=>({type:e.type,message:e.message})),traces:a.filter(e=>e.type==='pcb_trace').length};
console.log(JSON.stringify(summary,null,2));
process.exitCode=(coils.length!==4 || collisions.length || summary.errors.length)?1:0;