tscircuit/autorouting-dataset-01
This code manages the hardware and electronic components for circuit design and PCB layout, defining components like resistors, capacitors, transistors, connectors, and footprints, and providing tools for component placement, PCB topology, and electrical connections.
- Version
- 1.0.102
- License
- unset
- Stars
- 4
scripts/random-circuits/findDeterministicPlacement.ts
import { type Bounds, boundsAreaOverlap, boundsDistance } from "lib/maths/box"
import { getBoardBoundsWithPadding } from "scripts/random-circuits/getBoardBoundsWithPadding"
import type { GenerationContext } from "types/GenerationContext"
/**
* Finds a valid deterministic placement for a component footprint.
*/
export const findDeterministicPlacement = (
options: {
footprintSize: { width: number; height: number }
existingBounds: Bounds[]
boardSize: { width: number; height: number }
gap: number
},
ctx: GenerationContext,
): { pcbX: number; pcbY: number; width: number; height: number } | null => {
const { footprintSize, existingBounds, boardSize, gap } = options
const padding = Math.max(2, ctx.configuration.maxGapBetweenParts)
const inner = getBoardBoundsWithPadding(boardSize, padding)
const step = Math.max(0.5, gap / 2)
const maxSpanX = Math.max(0, inner.maxX - inner.minX - footprintSize.width)
const maxSpanY = Math.max(0, inner.maxY - inner.minY - footprintSize.height)
const maxRing = Math.ceil(Math.max(maxSpanX, maxSpanY) / step)
for (let ring = 0; ring <= maxRing; ring++) {
for (let dx = -ring; dx <= ring; dx++) {
for (let dy = -ring; dy <= ring; dy++) {
if (Math.abs(dx) !== ring && Math.abs(dy) !== ring) continue
const pcbX = dx * step
const pcbY = dy * step
const candidate: Bounds = {
minX: pcbX - footprintSize.width / 2,
maxX: pcbX + footprintSize.width / 2,
minY: pcbY - footprintSize.height / 2,
maxY: pcbY + footprintSize.height / 2,
}
if (!boundsAreaOverlap(candidate, inner)) continue
let collision = false
for (const existing of existingBounds) {
if (boundsDistance(candidate, existing) < gap) {
collision = true
break
}
}
if (collision) continue
return {
pcbX,
pcbY,
width: footprintSize.width,
height: footprintSize.height,
}
}
}
}
return null
}