export type Point = { x: number; y: number; }; export type Rect = { x: number; y: number; width: number; height: number; }; export type RouteResult = { points: Point[]; }; export type ConnectionSide = 'top' | 'bottom' | 'left' | 'right'; /** * Determine which side of a rectangle a connection should attach to, * based on the relative position of the other node's center. */ export declare function determineSide(nodeRect: Rect, otherCenter: Point): ConnectionSide; /** * Get the default port point for a given side of a rectangle (center of the side). */ export declare function sideCenter(rect: Rect, side: ConnectionSide): Point; /** * Distribute multiple connection points evenly along a border side of a node. * Returns the computed port points ordered by the angular position of their targets. */ export declare function distributeConnectionPoints(nodeRect: Rect, connectedEdges: Array<{ targetCenter: Point; side: ConnectionSide; }>): Point[]; /** * True when the axis-aligned segment a→b passes through the INTERIOR of `rect` * (not merely grazes its border). `inset` shrinks the rect so a connector that * legitimately touches a node's edge (its own anchor) is not counted. Used at * paint time to detect a connector that would render behind an unrelated node. */ export declare function segmentEntersRectInterior(a: Point, b: Point, rect: Rect, inset?: number): boolean; /** * True when any segment of the polyline `points` enters the interior of `rect`. */ export declare function polylineEntersRect(points: Point[], rect: Rect, inset?: number): boolean; /** * The lane separation used by channel routing — and the unit the ER layout sizes its * vertical channels (nodesep) by, so they MUST agree: if the channel is narrower than the * lanes need, the lanes bundle. Exported as the single source of that number (GH-565). */ export declare const CHANNEL_LANE_GAP = 16; /** * Channel routing (GH-564): give every connector its own lane so no two lines overlap * collinearly and no line runs through a table interior. Operates on the INTERIOR * vertical segments of each route (the long "down the channel" runs): when two share an * x (within `gap`) and overlap in y, or when a segment crosses an obstacle interior, it * shifts the segment sideways to the nearest clear lane and re-links its neighbours so * the route stays orthogonal. Mutates the routes in place. Reusable across diagram types. */ export declare function assignChannelLanes(routes: Point[][], obstacles: Rect[], gap?: number): void; /** * Remove tiny "jog" steps that add two elbows for a negligible offset (GH-565). A Z-route * whose middle segment is only a few px long reads as two needless kinks; if the route can * be straightened by snapping the short segment's neighbours into line WITHOUT entering a * table interior, do it. Walks each route, and for an interior segment shorter than * `maxJog` collapses it by aligning the points on either side, then verifies the resulting * straightened segment clears every obstacle (else leaves the jog). Mutates in place. */ export declare function simplifyShortJogs(routes: Point[][], obstacles: Rect[], maxJog?: number): void; /** * Route an edge between two rectangles using orthogonal (Manhattan) routing. * Produces L-shaped (2 segments) or Z-shaped (3 segments) paths. * Avoids obstacles by adding detour segments when needed. */ export declare function routeEdge(sourceRect: Rect, targetRect: Rect, sourcePort: Point, targetPort: Point, obstacles: Rect[], sourceSideHint?: ConnectionSide, targetSideHint?: ConnectionSide): RouteResult;