astra/nema17-stepper-motor-controller-spring-clamp-rp2040
A 4-layer RP2040 controller board that negotiates USB‑C PD motor power and drives a NEMA17 stepper via a DRV8825, with current sensing, thermal shutdown, RGB status LED, buzzer alarm, optional AS5600 encoder, protection/filtering, and test points.
- Version
- 1.4.0
- License
- unset
- Stars
- 0
routing/ground-pour-selection.ts
import selection from './ground-pour-selection.json';
/** Frozen pour selection for the validated fixed route plan.
* The pinned pour generator leaves floating fragments. The independent copper
* audit identifies those fragments; this finalization step removes their actual
* copper before normal DRC, preview and export. No error record is filtered.
* A geometry change fails closed and requires regenerating the selection/audit.
*/
export function canonicalPour(pour: any): string {
return JSON.stringify({layer:pour.layer,source_net_id:pour.source_net_id,shape:pour.brep_shape}, (_key,value)=>
typeof value==='number'?Math.round(value*1e7)/1e7:value);
}
export function selectConnectedGroundPours(json: any[], regions: Array<{geometry:any;keep:boolean}>) {
const pours=json.filter(e=>e.type==='pcb_copper_pour');
const expected=new Map(regions.map(r=>[canonicalPour(r.geometry),r.keep]));
if (pours.length!==regions.length || pours.some(p=>!expected.has(canonicalPour(p)))) {
throw new Error('Ground pour geometry changed. Regenerate and audit routing/ground-pour-selection.json.');
}
return pours.filter(p=>!expected.get(canonicalPour(p))).map(p=>p.pcb_copper_pour_id);
}
export function installGroundPourFinalization(board: any) {
if(!board || board.__groundPourSelectionInstalled)return;
board.__groundPourSelectionInstalled=true;
const original=board.doInitialPcbDesignRuleChecks.bind(board);
board.doInitialPcbDesignRuleChecks=()=>{
const db=board.root?.db;
// Placement-only CLI renders intentionally have no routed copper.
if(db && !board.root.pcbDisabled && !board.root.pcbRoutingDisabled) {
const remove=selectConnectedGroundPours(db.toArray(),selection.regions);
for(const id of remove)db.pcb_copper_pour.delete(id);
// Remove annotations that referred to removed geometry, not checks.
const deleted=new Set(remove);
for(const trace of db.pcb_trace.list()) {
if(trace.route.some((p:any)=>deleted.has(p.copper_pour_id))) {
db.pcb_trace.update(trace.pcb_trace_id,{route:trace.route.map((p:any)=>{
if(!deleted.has(p.copper_pour_id))return p;
const {copper_pour_id,is_inside_copper_pour,...point}=p;return point;
})});
}
}
}
return original();
};
}