ShiboSoftwareDev/linux-gameboy-advance
Restores PCB assembly metadata by assigning part numbers and 3D CAD models, removing test-point bodies, and validating top-side SMT solder-paste features without altering copper or pads.
- Version
- 1.0.17
- License
- unset
- Stars
- 0
scripts/search-via-position.mjs
import fs from "node:fs"
import {
checkViaTraceClearance,
checkViaPadClearance,
checkViasInPads,
checkDifferentNetViaSpacing,
checkSameNetViaSpacing,
checkEachPcbTraceNonOverlapping,
} from "@tscircuit/checks"
import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map"
const circuit = JSON.parse(fs.readFileSync("dist/index/circuit.json", "utf8"))
const traces = JSON.parse(fs.readFileSync("work/optimized-carrier-traces.json", "utf8"))
const cache = JSON.parse(fs.readFileSync("carrier-route-cache.json", "utf8"))
const carrierIds = new Set(cache.traces.map((trace) => trace.pcb_trace_id))
const routeById = new Map(traces.map((trace) => [trace.pcb_trace_id, trace.route]))
for (const trace of circuit.filter((e) => e.type === "pcb_trace" && routeById.has(e.pcb_trace_id)))
trace.route = routeById.get(trace.pcb_trace_id)
const keyByTrace = new Map(circuit.filter((e)=>e.type==="pcb_via").map((v)=>[v.pcb_trace_id,v.subcircuit_connectivity_map_key]))
for(let i=circuit.length-1;i>=0;i--) if(circuit[i].type==="pcb_via"&&carrierIds.has(circuit[i].pcb_trace_id)) circuit.splice(i,1)
let nextVia=0
for(const trace of circuit.filter((e)=>e.type==="pcb_trace"&&carrierIds.has(e.pcb_trace_id))){
let occurrence=0
for(const point of trace.route.filter((p)=>p.route_type==="via")) circuit.push({
type:"pcb_via",pcb_via_id:`search_via_${nextVia++}`,pcb_trace_id:trace.pcb_trace_id,
x:point.x,y:point.y,hole_diameter:point.via_hole_diameter,outer_diameter:point.via_diameter,
layers:["top","inner1","inner2","bottom"],from_layer:point.from_layer,to_layer:point.to_layer,
subcircuit_id:trace.subcircuit_id,subcircuit_connectivity_map_key:keyByTrace.get(trace.pcb_trace_id),occurrence:occurrence++,
})
}
const connMap=getFullConnectivityMapFromCircuitJson(circuit)
const cases=[
{traceId:"source_trace_127_0",routeIndex:31,occurrence:3},
{traceId:"source_trace_124_0",routeIndex:31,occurrence:2},
]
const hasCandidateError=(via)=>[
...checkViaTraceClearance(circuit,{connMap,minClearance:0.1}),
...checkViaPadClearance(circuit,{connMap,minClearance:0.1}),
...checkViasInPads(circuit),
...checkDifferentNetViaSpacing(circuit,{connMap,minClearance:0.2}),
...checkSameNetViaSpacing(circuit,{connMap,minClearance:0.2}),
...checkEachPcbTraceNonOverlapping(circuit,{connMap,minClearance:0.1}),
].some((e)=>
e.pcb_via_id===via.pcb_via_id||
e.pcb_pad_ids?.includes(via.pcb_via_id)||
e.pcb_trace_error_id?.includes(via.pcb_via_id)||
e.pcb_trace_error_id?.includes(via.pcb_trace_id)||
e.message?.includes(via.pcb_via_id))
for(const item of cases){
const trace=circuit.find((e)=>e.type==="pcb_trace"&&e.pcb_trace_id===item.traceId)
const via=circuit.find((e)=>e.type==="pcb_via"&&e.pcb_trace_id===item.traceId&&e.occurrence===item.occurrence)
const point=trace.route[item.routeIndex], origin={x:point.x,y:point.y}
let found=null, tested=0
outer: for(let radius=0;radius<=4;radius+=0.05){
const steps=Math.ceil(radius/0.05)
for(let ix=-steps;ix<=steps;ix++)for(let iy=-steps;iy<=steps;iy++){
const dx=ix*0.05,dy=iy*0.05,d=Math.hypot(dx,dy)
if(d>radius+1e-6||d<radius-0.07)continue
const x=origin.x+dx,y=origin.y+dy
for(const index of [item.routeIndex-1,item.routeIndex,item.routeIndex+1]){
trace.route[index].x=x;trace.route[index].y=y
}
via.x=x;via.y=y;tested++
if(!hasCandidateError(via)){found={x,y,d};break outer}
}
}
console.log(item.traceId,{origin,found,tested})
if(found){
for(const index of [item.routeIndex-1,item.routeIndex,item.routeIndex+1]){
routeById.get(item.traceId)[index].x=found.x;routeById.get(item.traceId)[index].y=found.y
}
}
}
fs.writeFileSync("work/searched-carrier-traces.json",JSON.stringify(traces,null,2)+"\n")