/** * Calculate the minimum distance from a point to a line segment. * This provides accurate distance measurements for angled segments. * * @param px - Point X coordinate * @param py - Point Y coordinate * @param x1 - Segment start X coordinate * @param y1 - Segment start Y coordinate * @param x2 - Segment end X coordinate * @param y2 - Segment end Y coordinate * @returns Minimum distance from point to segment */ export declare function pointToSegmentDistance(px: number, py: number, x1: number, y1: number, x2: number, y2: number): number; /** * Represents a single cell in the routing grid. */ export interface IGridCell { /** Grid column index */ x: number; /** Grid row index */ y: number; /** Layer this cell is on */ layer: string; /** Whether this cell is blocked by an obstacle */ occupied: boolean; /** If occupied, which net owns this cell (null if not net-specific) */ net?: string; /** If true, this cell is from a manual route and blocks routing even on the same net */ isManualRoute?: boolean; /** If true, this cell blocks routing for all nets (e.g., keepouts, board outline) */ absoluteBlock?: boolean; /** If true, this cell belongs to a pad area (for via placement rules) */ pad?: boolean; /** Cost multiplier for routing through this cell (1.0 = normal, higher = discouraged) */ cost: number; /** Maximum obstacle-required clearance (mm) affecting this cell */ clearance?: number; /** * For track obstacles, the half width (mm) of the occupying geometry. * Used to enforce edge-to-edge clearance by requiring the new centerline * to stay at least (obstacleHalfWidth + centerlineClearance) away. */ obstacleHalfWidthMm?: number; /** IDs of obstacles occupying this cell for precise geometry lookups */ obstacleIds?: string[]; } /** * Represents an obstacle in the routing space. */ export interface IRoutingObstacle { /** Type of obstacle for debugging/visualization */ type: 'component' | 'pad' | 'track' | 'zone' | 'keepout' | 'outline'; /** Bounding box in world coordinates (mm) */ bounds: { minX: number; maxX: number; minY: number; maxY: number; }; /** Layers this obstacle exists on */ layers: string[]; /** Net assignment - obstacles on same net don't block each other */ net?: string; /** Required clearance around this obstacle in mm */ clearance: number; /** Priority - higher priority obstacles block lower priority ones */ priority?: number; /** If true, this obstacle blocks routing even on the same net (for manual routes) */ isManualRoute?: boolean; /** Optional geometric description for precise rasterization (used for tracks) */ segment?: { x1: number; y1: number; x2: number; y2: number; width: number; }; /** Optional pad geometry for precise rasterization */ padShape?: { shape: 'circle' | 'rect' | 'oval' | 'roundrect'; center: { x: number; y: number; }; width: number; height: number; rotation: number; }; /** Optional polygon geometry (zones, keepouts) for precise rasterization */ polygon?: { points: { x: number; y: number; }[]; }; } /** * Grid-based spatial representation for PCB routing. * Discretizes continuous PCB space into a uniform grid for pathfinding algorithms. */ export declare class RoutingGrid { private debug; private static orientation; private static onSegment; private static segmentsIntersect; private static pointInPolygon; private bounds; gridResolution: number; private layers; private cells; private gridWidth; private gridHeight; private cellsTotalSize; private maxObstacleClearance; maxObstacleHalfWidthMm: number; private obstacles; private _version; private layerIndex; /** * Creates a new routing grid. * * @param bounds - World-space bounds of the routing area in mm * @param gridResolution - Size of each grid cell in mm (e.g., 0.1 = 10 cells per mm) * @param layers - List of copper layers to route on (e.g., ['F.Cu', 'B.Cu']) * * @example * ```ts * const grid = new RoutingGrid( * { minX: 0, maxX: 100, minY: 0, maxY: 80 }, * 0.1, // 0.1mm per cell * ['F.Cu', 'B.Cu'] * ); * ``` */ constructor(bounds: { minX: number; maxX: number; minY: number; maxY: number; }, gridResolution: number, layers: string[], debug?: boolean); /** * Add an obstacle to the grid. * Marks all cells within the obstacle bounds as occupied. * Note: Clearance is NOT applied here - it's checked during routing in isOccupied(). * * @param obstacle - The obstacle to add */ private static _obstacleIdCounter; addObstacle(obstacle: IRoutingObstacle): void; /** * Check if a specific grid cell belongs to a pad area on a given layer. */ isPadCell(x: number, y: number, layer: string): boolean; /** * Check if any pad lies within the specified clearance of a grid coordinate. * Ignores net assignments so that callers can enforce absolute pad spacing. */ hasPadWithinClearance(x: number, y: number, layer: string, clearanceMm: number): boolean; /** * Check if a grid cell is occupied. * * @param x - Grid X coordinate * @param y - Grid Y coordinate * @param layer - Layer to check * @param clearance - Additional clearance to check (in mm, not grid cells) * @param net - Net we're routing - obstacles on same net don't block * @returns True if occupied, false if available for routing */ isOccupied(x: number, y: number, layer: string, clearance?: number, net?: string, considerObstacleClearance?: boolean, sumObstacleClearance?: boolean): boolean; /** * Fast-path occupancy check for via placement: returns true only if the cell * at (x, y, layer) is occupied by an obstacle whose ID is in `obstacleIds`. * Avoids the expensive clearance-radius scan of isOccupied(). * * @param x Grid X coordinate * @param y Grid Y coordinate * @param layer Layer name * @param obstacleIds Set (or array) of obstacle IDs already belonging to the * current net — these are ignored so the via can share pads. */ isOccupiedById(x: number, y: number, layer: string, obstacleIds: Set | string[]): boolean; /** * Check if a position conflicts with track obstacles using precise point-to-segment distance. * This method provides more accurate clearance checking for angled tracks. * * @param worldX - World X coordinate in mm * @param worldY - World Y coordinate in mm * @param layer - Layer to check * @param clearance - Required clearance in mm * @param net - Net we're routing (for same-net exemptions) * @returns True if position conflicts with track obstacles */ checkTrackObstaclePrecise(worldX: number, worldY: number, layer: string, clearance: number, net?: string): boolean; /** * Get obstacle data for a cell (internal helper). * @private */ private getCellObstacle; /** * Convert grid X coordinate to world X coordinate in mm. * @param gridX - Grid X coordinate * @returns World X coordinate in mm */ gridToWorldX(gridX: number): number; /** * Convert grid Y coordinate to world Y coordinate in mm. * @param gridY - Grid Y coordinate * @returns World Y coordinate in mm */ gridToWorldY(gridY: number): number; /** * Convert grid X coordinate to world X coordinate using cell boundary (no center offset). * This provides more accurate positioning for track creation. * @param gridX - Grid X coordinate * @returns World X coordinate in mm */ getWorldXFromGrid(gridX: number): number; /** * Convert grid Y coordinate to world Y coordinate using cell boundary (no center offset). * This provides more accurate positioning for track creation. * @param gridY - Grid Y coordinate * @returns World Y coordinate in mm */ getWorldYFromGrid(gridY: number): number; /** * Check if a single cell is occupied (internal helper). * @private */ private isCellOccupied; /** * Get the routing cost for a grid cell. * * @param x - Grid X coordinate * @param y - Grid Y coordinate * @param layer - Layer to check * @returns Cost multiplier (1.0 = normal, higher = more expensive) */ getCellCost(x: number, y: number, layer: string): number; /** * Set the routing cost for a grid cell. * Useful for biasing routes toward or away from certain areas. * * @param x - Grid X coordinate * @param y - Grid Y coordinate * @param layer - Layer * @param cost - Cost multiplier */ setCellCost(x: number, y: number, layer: string, cost: number): void; markTerminal(gx: number, gy: number, layer: string, radiusCells: number, net?: string): void; /** * Convert world coordinates (mm) to grid coordinates. * * @param worldX - X coordinate in mm * @param worldY - Y coordinate in mm * @returns Grid coordinates */ worldToGrid(worldX: number, worldY: number): { x: number; y: number; }; /** * Convert grid coordinates to world coordinates (mm). * Returns the center of the grid cell. * * @param gridX - Grid X coordinate * @param gridY - Grid Y coordinate * @returns World coordinates in mm */ gridToWorld(gridX: number, gridY: number): { x: number; y: number; }; /** * Check if grid coordinates are within bounds. * * @param x - Grid X coordinate * @param y - Grid Y coordinate * @returns True if in bounds */ isInBounds(x: number, y: number): boolean; /** * Get the cell key for the internal map. * @private */ private getCellIndex; /** * Get a cell by coordinates, if present. */ getCell(x: number, y: number, layer: string): IGridCell | undefined; /** * Convert world bounds to grid bounds. * @private */ private worldBoundsToGridBounds; /** * Get grid dimensions. */ getDimensions(): { width: number; height: number; layers: number; }; /** * Get grid resolution in mm. */ getResolution(): number; /** * Get the list of layers in the grid. */ getLayers(): string[]; /** * Get grid bounds in world coordinates. */ getBounds(): { minX: number; maxX: number; minY: number; maxY: number; }; getCellsArray(): readonly (IGridCell | undefined)[]; getVersion(): number; /** * Clear all obstacles from the grid. * Useful for rebuilding the grid with different obstacles. */ clear(): void; /** * Get statistics about the grid. */ getStats(): { totalCells: number; occupiedCells: number; freeCells: number; occupancyPercent: number; }; } //# sourceMappingURL=routing_grid.d.ts.map