/** * Pin-coordinate collision detection for schematic component placement. * * EasyEDA merges any two primitives that land on the exact same (x,y) canvas point, * regardless of net name, the moment either one is wired — so a newly-placed component * whose pin coincides with an unrelated component's pin is a silent-short risk even * before any wire is drawn. The bridge's own `NET_COLLISION` guard only catches this for * pins that are already part of a net (see `easyeda-bridge-extension/src/dispatcher.ts`'s * `collectPinCoordinateNets`) — a virgin, never-wired pin is invisible to it. This module * closes that gap by reading every placed component's real pin coordinates directly * (`SCH_PrimitiveComponent.getAllPinsByPrimitiveId` via `fetchComponentPins`), independent * of net membership. * * @module */ import { type ToolContext } from '../tools/types.js'; export interface CollisionPinRef { primitiveId: string; pinNumber: string; pinName: string; } export interface PinCollision { x: number; y: number; pins: CollisionPinRef[]; } export interface CollisionScanFailure { primitiveId: string; error: string; } export interface CollisionScanDiagnostics { stage: 'complete' | 'component_enumeration' | 'pin_lookup'; componentCount: number; componentsScanned: number; failedComponents: CollisionScanFailure[]; durationMs: number; componentEnumerationMs: number; pinLookupMs: number; concurrency: number; perCallTimeoutMs: number; overallTimeoutMs: number; stageError?: string; } export interface CollisionScanResult { collisions: PinCollision[]; diagnostics: CollisionScanDiagnostics; } export declare const COLLISION_SCAN_CONCURRENCY = 4; export declare const COLLISION_PIN_LOOKUP_TIMEOUT_MS = 5000; export declare const COLLISION_SCAN_TIMEOUT_MS = 20000; export declare function collisionScanErrorMessage(diagnostics: CollisionScanDiagnostics): string; /** * Full-sheet pin-coordinate collision scan with timing and failure diagnostics. * Successful pin lookups are still analyzed when another component stalls. */ export declare function scanSheetForPinCollisionsDetailed(ctx: ToolContext, projectId: string): Promise; /** * Strict compatibility wrapper used by safety-sensitive workflows. Standalone tooling uses * the detailed variant so it can expose partial results, while placement reconciliation must * fail closed when any component was not inspected. */ export declare function scanSheetForPinCollisions(ctx: ToolContext, projectId: string): Promise; export interface ReconcilePlacementResult { /** Collisions that could not be resolved by nudging — caller should block/report these. */ unresolvedCollisions: PinCollision[]; /** primitiveId -> final {x, y} for every candidate that was moved during reconcile. */ movedComponents: Map; } /** * Post-placement reconcile: check the newly-placed `candidatePrimitiveIds` for pin-coordinate * collisions against every other component on the sheet, and nudge (re-`modifyPrimitive`) any * offender by a fixed offset up to `NUDGE_ATTEMPTS` times. Safe to call only *before* any wires * are connected to the candidates — moving a component after it's wired does not move its wires * (see the dispatcher's `modifyPrimitive` limitation) and would itself create the exact hazard * this function exists to prevent. */ export declare function reconcilePlacementCollisions(ctx: ToolContext, projectId: string, candidatePrimitiveIds: string[], candidatePositions: Map): Promise;