From 7645409591aebdd79feeb9b860b244eb0271e297 Mon Sep 17 00:00:00 2001 From: Bill Westrup Date: Tue, 28 Apr 2026 18:07:15 -0500 Subject: [PATCH] feat(pcb_component): add relational_constraints for auto-placement engines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds an optional `relational_constraints` field to `pcb_component` to express soft proximity relationships between components. This is particularly useful for hierarchical auto-placement pipelines that need to encode constraints like "this decoupling cap must stay within Nmm of its IC" without hard-coding absolute coordinates. Fields: - `anchor_to`: name of the target component to stay near - `max_distance`: maximum allowed Euclidean distance (mm) between centers - `keep_near`: grouping hint for tile/cluster assignment All fields are optional. The constraints are advisory — they are intended to be consumed by placement engines rather than enforced by the schema validator. Motivated by real-world use in the Sentinel RTLS v6 PCB pipeline, where 100+ components are placed across 6 hierarchical tiles and proximity to anchor ICs (nRF9151, nPM1300, etc.) must be enforced without relying on fixed coordinate systems. --- src/pcb/pcb_component.ts | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/pcb/pcb_component.ts b/src/pcb/pcb_component.ts index cce66ea4..0c38cdc3 100644 --- a/src/pcb/pcb_component.ts +++ b/src/pcb/pcb_component.ts @@ -75,6 +75,31 @@ export const pcb_component = z .describe( "Does this component take up all the space within its bounds on a layer. This is generally true except for when separated pin headers are being represented by a single component (in which case, chips can be placed between the pin headers) or for tall modules where chips fit underneath", ), + relational_constraints: z + .object({ + anchor_to: z + .string() + .optional() + .describe( + "The name of another component that this component should be placed near (soft constraint for auto-placement engines)", + ), + max_distance: z + .number() + .optional() + .describe( + "Maximum allowable Euclidean distance in mm between this component's center and the anchor_to component's center", + ), + keep_near: z + .string() + .optional() + .describe( + "Hint for auto-placement engines to keep this component in the same tile/cluster as the named component", + ), + }) + .optional() + .describe( + "Soft placement relationships between this component and others, used by auto-placement engines", + ), }) .describe("Defines a component on the PCB") @@ -117,6 +142,23 @@ export interface PcbComponent { | "from_back" metadata?: PcbComponentMetadata obstructs_within_bounds: boolean + relational_constraints?: { + /** + * The name of another component that this component should be placed near. + * Soft constraint for auto-placement engines. + */ + anchor_to?: string + /** + * Maximum allowable Euclidean distance in mm between this component's + * center and the anchor_to component's center. + */ + max_distance?: number + /** + * Hint for auto-placement engines to keep this component in the same + * tile or cluster as the named component. + */ + keep_near?: string + } } /**