@ngx-km/path-finding 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -0
- package/fesm2022/ngx-km-path-finding.mjs +1002 -0
- package/fesm2022/ngx-km-path-finding.mjs.map +1 -0
- package/index.d.ts +465 -0
- package/package.json +23 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngx-km-path-finding.mjs","sources":["../../../../libs/ngx-km-path-finding/src/lib/models/path-finding.models.ts","../../../../libs/ngx-km-path-finding/src/lib/utils/path.utils.ts","../../../../libs/ngx-km-path-finding/src/lib/utils/anchor.utils.ts","../../../../libs/ngx-km-path-finding/src/lib/utils/geometry.utils.ts","../../../../libs/ngx-km-path-finding/src/lib/strategies/orthogonal.strategy.ts","../../../../libs/ngx-km-path-finding/src/lib/strategies/bezier.strategy.ts","../../../../libs/ngx-km-path-finding/src/lib/strategies/straight.strategy.ts","../../../../libs/ngx-km-path-finding/src/lib/services/path-finding.service.ts","../../../../libs/ngx-km-path-finding/src/index.ts","../../../../libs/ngx-km-path-finding/src/ngx-km-path-finding.ts"],"sourcesContent":["/**\n * Path Finding Models\n *\n * Types and interfaces for obstacle-aware path routing between nodes.\n */\n\n/**\n * Type of path to generate\n * - orthogonal: Right-angle turns only (Manhattan-style)\n * - bezier: Smooth curved paths\n * - straight: Direct line (may overlap obstacles)\n */\nexport type PathType = 'orthogonal' | 'bezier' | 'straight';\n\n/**\n * Side of a node where a connection point is located\n */\nexport type ConnectionSide = 'top' | 'right' | 'bottom' | 'left';\n\n/**\n * A point in 2D space\n */\nexport interface Point {\n x: number;\n y: number;\n}\n\n/**\n * A rectangle representing a node's bounds\n */\nexport interface Rectangle {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/**\n * A node with position and dimensions for path finding\n * Used as an obstacle when routing paths\n */\nexport interface PathNode {\n /** Unique identifier */\n id: string;\n /** X coordinate (top-left corner) */\n x: number;\n /** Y coordinate (top-left corner) */\n y: number;\n /** Width of the node */\n width: number;\n /** Height of the node */\n height: number;\n}\n\n/**\n * A relationship/edge between two nodes that needs a path\n */\nexport interface PathRelationship {\n /** Unique identifier for this relationship */\n id: string;\n /** ID of the source node */\n sourceId: string;\n /** ID of the target node */\n targetId: string;\n /** Optional: force connection from specific side of source */\n sourceAnchor?: ConnectionSide;\n /** Optional: force connection to specific side of target */\n targetAnchor?: ConnectionSide;\n}\n\n/**\n * A connection point on a node's edge\n */\nexport interface ConnectionPoint {\n /** The side of the node */\n side: ConnectionSide;\n /** X coordinate of the connection point */\n x: number;\n /** Y coordinate of the connection point */\n y: number;\n}\n\n/**\n * A waypoint along a path\n */\nexport interface Waypoint extends Point {\n /** Optional: indicates if this is a control point for bezier curves */\n isControlPoint?: boolean;\n}\n\n/**\n * A calculated path between two nodes\n */\nexport interface CalculatedPath {\n /** The relationship ID this path corresponds to */\n relationshipId: string;\n /** Source node ID */\n sourceId: string;\n /** Target node ID */\n targetId: string;\n /** Connection point on source node */\n sourcePoint: ConnectionPoint;\n /** Connection point on target node */\n targetPoint: ConnectionPoint;\n /** Ordered list of waypoints forming the path */\n waypoints: Waypoint[];\n /** The midpoint of the path (useful for labels/pills) */\n midpoint: Point;\n /** Total length of the path */\n length: number;\n /** Type of path */\n pathType: PathType;\n}\n\n/**\n * Options for path finding\n */\nexport interface PathFindingOptions {\n /** Type of path to generate */\n pathType?: PathType;\n /** Padding around obstacles when routing */\n obstaclePadding?: number;\n /** Minimum distance from node corners for connection points */\n cornerPadding?: number;\n /** Minimum spacing between connection points on same side */\n connectionSpacing?: number;\n /** Whether to allow paths to pass through other nodes */\n allowOverlap?: boolean;\n /** Whether to spread anchor points when multiple edges connect to the same side */\n spreadAnchors?: boolean;\n /** Spacing between spread anchor points (when spreadAnchors is enabled) */\n anchorSpacing?: number;\n}\n\n/**\n * Default path finding options\n */\nexport const DEFAULT_PATH_FINDING_OPTIONS: Required<PathFindingOptions> = {\n pathType: 'orthogonal',\n obstaclePadding: 20,\n cornerPadding: 10,\n connectionSpacing: 15,\n allowOverlap: false,\n spreadAnchors: true,\n anchorSpacing: 15,\n};\n\n/**\n * Input for path finding calculation\n */\nexport interface PathFindingInput {\n /** All nodes (used as obstacles) */\n nodes: PathNode[];\n /** Relationships to calculate paths for */\n relationships: PathRelationship[];\n /** Path finding options */\n options?: PathFindingOptions;\n}\n\n/**\n * Result of path finding calculation\n */\nexport interface PathFindingResult {\n /** Calculated paths for each relationship */\n paths: CalculatedPath[];\n}\n","/**\n * Path Utilities\n *\n * Functions for path manipulation, simplification, and measurement.\n */\n\nimport { Point, Waypoint } from '../models/path-finding.models';\n\n/**\n * Calculate the length of a route using Manhattan distance (orthogonal segments)\n * Used for comparing route candidates\n */\nexport function calculateRouteLength(points: Point[]): number {\n let length = 0;\n for (let i = 0; i < points.length - 1; i++) {\n length += Math.abs(points[i + 1].x - points[i].x) + Math.abs(points[i + 1].y - points[i].y);\n }\n return length;\n}\n\n/**\n * Calculate total path length using Euclidean distance\n * Excludes control points for bezier curves\n */\nexport function calculatePathLength(waypoints: Waypoint[]): number {\n let length = 0;\n const points = waypoints.filter((w) => !w.isControlPoint);\n\n for (let i = 0; i < points.length - 1; i++) {\n length += Math.hypot(points[i + 1].x - points[i].x, points[i + 1].y - points[i].y);\n }\n\n return length;\n}\n\n/**\n * Calculate the midpoint of a path\n * Returns the point at half the total path length\n */\nexport function calculateMidpoint(waypoints: Waypoint[]): Point {\n if (waypoints.length === 0) return { x: 0, y: 0 };\n if (waypoints.length === 1) return { x: waypoints[0].x, y: waypoints[0].y };\n\n const nonControlPoints = waypoints.filter((w) => !w.isControlPoint);\n\n if (nonControlPoints.length >= 2) {\n const totalLength = calculatePathLength(nonControlPoints);\n const targetLength = totalLength / 2;\n let accumulatedLength = 0;\n\n for (let i = 0; i < nonControlPoints.length - 1; i++) {\n const segmentLength = Math.hypot(\n nonControlPoints[i + 1].x - nonControlPoints[i].x,\n nonControlPoints[i + 1].y - nonControlPoints[i].y\n );\n\n if (accumulatedLength + segmentLength >= targetLength) {\n const remainingLength = targetLength - accumulatedLength;\n const ratio = segmentLength > 0 ? remainingLength / segmentLength : 0;\n\n return {\n x: nonControlPoints[i].x + (nonControlPoints[i + 1].x - nonControlPoints[i].x) * ratio,\n y: nonControlPoints[i].y + (nonControlPoints[i + 1].y - nonControlPoints[i].y) * ratio,\n };\n }\n\n accumulatedLength += segmentLength;\n }\n }\n\n const midIndex = Math.floor(nonControlPoints.length / 2);\n return { x: nonControlPoints[midIndex].x, y: nonControlPoints[midIndex].y };\n}\n\n/**\n * Simplify path by removing collinear points\n * This reduces redundant waypoints while preserving path shape\n */\nexport function simplifyPath(waypoints: Waypoint[]): Waypoint[] {\n if (waypoints.length <= 2) return waypoints;\n\n const simplified: Waypoint[] = [waypoints[0]];\n\n for (let i = 1; i < waypoints.length - 1; i++) {\n const prev = simplified[simplified.length - 1];\n const curr = waypoints[i];\n const next = waypoints[i + 1];\n\n const isCollinear =\n (Math.abs(prev.x - curr.x) < 0.001 && Math.abs(curr.x - next.x) < 0.001) ||\n (Math.abs(prev.y - curr.y) < 0.001 && Math.abs(curr.y - next.y) < 0.001);\n\n if (!isCollinear) {\n simplified.push(curr);\n }\n }\n\n simplified.push(waypoints[waypoints.length - 1]);\n return simplified;\n}\n","/**\n * Anchor Utilities\n *\n * Functions for calculating connection points and anchor slot assignments.\n */\n\nimport { Point, PathNode, ConnectionSide, ConnectionPoint, CalculatedPath } from '../models/path-finding.models';\nimport { clamp } from './geometry.utils';\n\n/**\n * Anchor slot assignment for spreading multiple connections on the same side\n */\nexport interface AnchorSlot {\n nodeId: string;\n side: ConnectionSide;\n relationshipId: string;\n isSource: boolean;\n slotIndex: number;\n totalSlots: number;\n}\n\n/**\n * Padded connection point - sits at padding distance from node edge\n */\nexport interface PaddedPoint {\n x: number;\n y: number;\n side: ConnectionSide;\n nodeEdgeX: number;\n nodeEdgeY: number;\n}\n\n/**\n * Get preferred connection side based on relative position of nodes\n */\nexport function getPreferredSide(from: PathNode, to: PathNode): ConnectionSide {\n const fromCenterX = from.x + from.width / 2;\n const fromCenterY = from.y + from.height / 2;\n const toCenterX = to.x + to.width / 2;\n const toCenterY = to.y + to.height / 2;\n\n const dx = toCenterX - fromCenterX;\n const dy = toCenterY - fromCenterY;\n\n if (Math.abs(dx) > Math.abs(dy)) {\n return dx > 0 ? 'right' : 'left';\n } else {\n return dy > 0 ? 'bottom' : 'top';\n }\n}\n\n/**\n * Get connection point on a node\n */\nexport function getConnectionPoint(\n node: PathNode,\n targetNode: PathNode,\n forcedAnchor: ConnectionSide | undefined,\n cornerPadding: number,\n slot?: AnchorSlot,\n anchorSpacing?: number\n): ConnectionPoint {\n const side = forcedAnchor || getPreferredSide(node, targetNode);\n const point = getPointOnSide(node, side, cornerPadding, slot, anchorSpacing);\n return { side, x: point.x, y: point.y };\n}\n\n/**\n * Get point on a specific side of a node\n * Uses even distribution when multiple slots are on the same side\n */\nexport function getPointOnSide(\n node: PathNode,\n side: ConnectionSide,\n cornerPadding: number,\n slot?: AnchorSlot,\n _anchorSpacing?: number // kept for API compatibility but not used\n): Point {\n // Calculate position on edge using even distribution\n const isVerticalSide = side === 'left' || side === 'right';\n const edgeLength = isVerticalSide ? node.height : node.width;\n const usableLength = edgeLength - 2 * cornerPadding;\n\n let edgePosition: number;\n if (slot && slot.totalSlots > 1) {\n // Distribute evenly: for N slots, divide into N+1 segments\n const t = (slot.slotIndex + 1) / (slot.totalSlots + 1);\n edgePosition = cornerPadding + t * usableLength;\n } else {\n // Single slot or no slot - use center\n edgePosition = edgeLength / 2;\n }\n\n switch (side) {\n case 'top':\n return {\n x: node.x + edgePosition,\n y: node.y,\n };\n case 'bottom':\n return {\n x: node.x + edgePosition,\n y: node.y + node.height,\n };\n case 'left':\n return {\n x: node.x,\n y: node.y + edgePosition,\n };\n case 'right':\n return {\n x: node.x + node.width,\n y: node.y + edgePosition,\n };\n }\n}\n\n/**\n * Get a padded point - sits at padding distance from node edge\n * Uses even distribution when multiple slots are on the same side\n */\nexport function getPaddedPoint(\n node: PathNode,\n side: ConnectionSide,\n padding: number,\n cornerPadding: number,\n slot?: AnchorSlot\n): PaddedPoint {\n // Calculate position on edge using even distribution\n const isVerticalSide = side === 'left' || side === 'right';\n const edgeLength = isVerticalSide ? node.height : node.width;\n const usableLength = edgeLength - 2 * cornerPadding;\n\n let edgePosition: number;\n if (slot && slot.totalSlots > 1) {\n // Distribute evenly: for N slots, divide into N+1 segments\n const t = (slot.slotIndex + 1) / (slot.totalSlots + 1);\n edgePosition = cornerPadding + t * usableLength;\n } else {\n // Single slot or no slot - use center\n edgePosition = edgeLength / 2;\n }\n\n switch (side) {\n case 'top': {\n const edgeX = node.x + edgePosition;\n return {\n x: edgeX,\n y: node.y - padding,\n side,\n nodeEdgeX: edgeX,\n nodeEdgeY: node.y,\n };\n }\n case 'bottom': {\n const edgeX = node.x + edgePosition;\n return {\n x: edgeX,\n y: node.y + node.height + padding,\n side,\n nodeEdgeX: edgeX,\n nodeEdgeY: node.y + node.height,\n };\n }\n case 'left': {\n const edgeY = node.y + edgePosition;\n return {\n x: node.x - padding,\n y: edgeY,\n side,\n nodeEdgeX: node.x,\n nodeEdgeY: edgeY,\n };\n }\n case 'right': {\n const edgeY = node.y + edgePosition;\n return {\n x: node.x + node.width + padding,\n y: edgeY,\n side,\n nodeEdgeX: node.x + node.width,\n nodeEdgeY: edgeY,\n };\n }\n }\n}\n\n/**\n * Calculate actual slot positions on a node edge\n * Uses even distribution across the available edge space\n */\nexport function calculateSlotPositions(\n node: PathNode,\n side: ConnectionSide,\n totalSlots: number,\n cornerPadding = 5\n): Array<{ x: number; y: number }> {\n const positions: Array<{ x: number; y: number }> = [];\n\n // Calculate the available range on this edge\n const isVerticalSide = side === 'left' || side === 'right';\n const edgeLength = isVerticalSide ? node.height : node.width;\n const usableLength = edgeLength - 2 * cornerPadding;\n\n for (let i = 0; i < totalSlots; i++) {\n // Distribute evenly: for N slots, divide into N+1 segments\n // and place slots at positions 1, 2, ..., N\n const t = (i + 1) / (totalSlots + 1);\n const offset = cornerPadding + t * usableLength;\n\n switch (side) {\n case 'top':\n positions.push({ x: node.x + offset, y: node.y });\n break;\n case 'bottom':\n positions.push({ x: node.x + offset, y: node.y + node.height });\n break;\n case 'left':\n positions.push({ x: node.x, y: node.y + offset });\n break;\n case 'right':\n positions.push({ x: node.x + node.width, y: node.y + offset });\n break;\n }\n }\n\n return positions;\n}\n\n/**\n * Find optimal slot assignment to minimize crossings\n * Returns an array where assignment[connIndex] = slotIndex\n */\nexport function findOptimalSlotAssignment(\n connections: Array<{ otherNodeX: number; otherNodeY: number; relationshipId: string; isSource: boolean }>,\n slotPositions: Array<{ x: number; y: number }>\n): number[] {\n const n = connections.length;\n\n // For small numbers, try all permutations to find the best one\n if (n <= 6) {\n return findBestPermutation(connections, slotPositions);\n }\n\n // For larger numbers, use greedy assignment based on distance\n return greedySlotAssignment(connections, slotPositions);\n}\n\n/**\n * Try all permutations to find the one with minimum total distance\n */\nfunction findBestPermutation(\n connections: Array<{ otherNodeX: number; otherNodeY: number }>,\n slotPositions: Array<{ x: number; y: number }>\n): number[] {\n const n = connections.length;\n const indices = Array.from({ length: n }, (_, i) => i);\n let bestAssignment = indices.slice();\n let bestScore = Infinity;\n\n // Generate all permutations\n const permute = (arr: number[], start: number) => {\n if (start === arr.length - 1) {\n // Calculate score for this permutation\n let totalDist = 0;\n for (let i = 0; i < n; i++) {\n const slot = slotPositions[arr[i]];\n const conn = connections[i];\n totalDist += Math.hypot(conn.otherNodeX - slot.x, conn.otherNodeY - slot.y);\n }\n\n if (totalDist < bestScore) {\n bestScore = totalDist;\n bestAssignment = arr.slice();\n }\n return;\n }\n\n for (let i = start; i < arr.length; i++) {\n [arr[start], arr[i]] = [arr[i], arr[start]];\n permute(arr, start + 1);\n [arr[start], arr[i]] = [arr[i], arr[start]];\n }\n };\n\n permute(indices, 0);\n return bestAssignment;\n}\n\n/**\n * Greedy slot assignment for larger numbers of connections\n */\nfunction greedySlotAssignment(\n connections: Array<{ otherNodeX: number; otherNodeY: number }>,\n slotPositions: Array<{ x: number; y: number }>\n): number[] {\n const n = connections.length;\n const assignment: number[] = new Array(n).fill(-1);\n const usedSlots = new Set<number>();\n\n // Create distance matrix\n const distances: Array<{ connIdx: number; slotIdx: number; dist: number }> = [];\n for (let c = 0; c < n; c++) {\n for (let s = 0; s < n; s++) {\n const dist = Math.hypot(\n connections[c].otherNodeX - slotPositions[s].x,\n connections[c].otherNodeY - slotPositions[s].y\n );\n distances.push({ connIdx: c, slotIdx: s, dist });\n }\n }\n\n // Sort by distance and greedily assign\n distances.sort((a, b) => a.dist - b.dist);\n\n for (const { connIdx, slotIdx } of distances) {\n if (assignment[connIdx] === -1 && !usedSlots.has(slotIdx)) {\n assignment[connIdx] = slotIdx;\n usedSlots.add(slotIdx);\n }\n }\n\n return assignment;\n}\n\n/**\n * Calculate anchor slot assignments based on actual path results\n * This uses the sides that were actually chosen by the routing algorithm\n */\nexport function calculateAnchorSlotsFromPaths(\n paths: CalculatedPath[],\n nodeMap: Map<string, PathNode>\n): Map<string, AnchorSlot> {\n const slots = new Map<string, AnchorSlot>();\n\n // Group connections by node and side\n const connectionsByNodeSide = new Map<\n string,\n Array<{\n relationshipId: string;\n isSource: boolean;\n otherNodeX: number;\n otherNodeY: number;\n }>\n >();\n\n for (const path of paths) {\n const sourceNode = nodeMap.get(path.sourceId);\n const targetNode = nodeMap.get(path.targetId);\n\n if (!sourceNode || !targetNode) continue;\n\n // Use the actual sides from the calculated path\n const sourceSide = path.sourcePoint.side;\n const targetSide = path.targetPoint.side;\n\n // Source connection\n const sourceKey = `${path.sourceId}:${sourceSide}`;\n if (!connectionsByNodeSide.has(sourceKey)) {\n connectionsByNodeSide.set(sourceKey, []);\n }\n connectionsByNodeSide.get(sourceKey)!.push({\n relationshipId: path.relationshipId,\n isSource: true,\n otherNodeX: targetNode.x + targetNode.width / 2,\n otherNodeY: targetNode.y + targetNode.height / 2,\n });\n\n // Target connection\n const targetKey = `${path.targetId}:${targetSide}`;\n if (!connectionsByNodeSide.has(targetKey)) {\n connectionsByNodeSide.set(targetKey, []);\n }\n connectionsByNodeSide.get(targetKey)!.push({\n relationshipId: path.relationshipId,\n isSource: false,\n otherNodeX: sourceNode.x + sourceNode.width / 2,\n otherNodeY: sourceNode.y + sourceNode.height / 2,\n });\n }\n\n // Assign slots for each node-side combination\n for (const [key, connections] of connectionsByNodeSide) {\n const [nodeId, side] = key.split(':') as [string, ConnectionSide];\n const node = nodeMap.get(nodeId);\n if (!node) continue;\n\n const totalSlots = connections.length;\n\n if (totalSlots === 1) {\n // Single connection - just assign slot 0\n const conn = connections[0];\n const slotKey = `${conn.relationshipId}-${conn.isSource ? 'source' : 'target'}`;\n slots.set(slotKey, {\n nodeId,\n side,\n relationshipId: conn.relationshipId,\n isSource: conn.isSource,\n slotIndex: 0,\n totalSlots: 1,\n });\n continue;\n }\n\n // Calculate the actual slot positions on the node edge\n const slotPositions = calculateSlotPositions(node, side, totalSlots);\n\n // Find optimal assignment: pair each connection with a slot position\n // to minimize total distance and avoid crossings\n const assignment = findOptimalSlotAssignment(connections, slotPositions);\n\n // Assign slots based on the optimal pairing\n assignment.forEach((slotIndex, connIndex) => {\n const conn = connections[connIndex];\n const slotKey = `${conn.relationshipId}-${conn.isSource ? 'source' : 'target'}`;\n slots.set(slotKey, {\n nodeId,\n side,\n relationshipId: conn.relationshipId,\n isSource: conn.isSource,\n slotIndex,\n totalSlots,\n });\n });\n }\n\n return slots;\n}\n","/**\n * Geometry Utilities\n *\n * Core geometric types and functions for path finding calculations.\n */\n\nimport { Point, PathNode } from '../models/path-finding.models';\n\n/**\n * Rectangle with computed bounds for efficient collision detection\n */\nexport interface Rect {\n x: number;\n y: number;\n width: number;\n height: number;\n right: number;\n bottom: number;\n centerX: number;\n centerY: number;\n}\n\n/**\n * Clamp a value between min and max\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value));\n}\n\n/**\n * Create a Rect from a PathNode\n */\nexport function createRect(node: PathNode): Rect {\n return {\n x: node.x,\n y: node.y,\n width: node.width,\n height: node.height,\n right: node.x + node.width,\n bottom: node.y + node.height,\n centerX: node.x + node.width / 2,\n centerY: node.y + node.height / 2,\n };\n}\n\n/**\n * Create a padded Rect from a PathNode\n */\nexport function createPaddedRect(node: PathNode, padding: number): Rect {\n return {\n x: node.x - padding,\n y: node.y - padding,\n width: node.width + padding * 2,\n height: node.height + padding * 2,\n right: node.x + node.width + padding,\n bottom: node.y + node.height + padding,\n centerX: node.x + node.width / 2,\n centerY: node.y + node.height / 2,\n };\n}\n\n/**\n * Expand a Rect by padding amount on all sides\n */\nexport function expandRect(rect: Rect, padding: number): Rect {\n return {\n x: rect.x - padding,\n y: rect.y - padding,\n width: rect.width + padding * 2,\n height: rect.height + padding * 2,\n right: rect.right + padding,\n bottom: rect.bottom + padding,\n centerX: rect.centerX,\n centerY: rect.centerY,\n };\n}\n\n/**\n * Check if a line segment passes through rectangle interior (not just touches edge)\n * Used for obstacle collision detection in orthogonal routing\n */\nexport function linePassesThroughRect(p1: Point, p2: Point, rect: Rect): boolean {\n // Check bounding box overlap first\n const lineMinX = Math.min(p1.x, p2.x);\n const lineMaxX = Math.max(p1.x, p2.x);\n const lineMinY = Math.min(p1.y, p2.y);\n const lineMaxY = Math.max(p1.y, p2.y);\n\n // No overlap at all\n if (lineMaxX <= rect.x || lineMinX >= rect.right) return false;\n if (lineMaxY <= rect.y || lineMinY >= rect.bottom) return false;\n\n // For orthogonal lines, check if line passes through interior\n const isVertical = Math.abs(p1.x - p2.x) < 0.001;\n const isHorizontal = Math.abs(p1.y - p2.y) < 0.001;\n\n if (isVertical) {\n // Vertical line: passes through if x is strictly inside rect\n return p1.x > rect.x && p1.x < rect.right;\n }\n\n if (isHorizontal) {\n // Horizontal line: passes through if y is strictly inside rect\n return p1.y > rect.y && p1.y < rect.bottom;\n }\n\n // Diagonal line (shouldn't happen for orthogonal routing)\n return true;\n}\n","/**\n * Orthogonal Path Strategy\n *\n * Generates paths with right-angle turns only (Manhattan-style routing).\n * Supports obstacle avoidance with multiple routing strategies.\n */\n\nimport { Waypoint, ConnectionSide, PathNode } from '../models/path-finding.models';\nimport { PathStrategy, PathStrategyContext, PathStrategyResult, RouteCandidate } from './path-strategy.interface';\nimport { Rect, createRect, createPaddedRect, expandRect, linePassesThroughRect } from '../utils/geometry.utils';\nimport { simplifyPath, calculateRouteLength } from '../utils/path.utils';\nimport { getPreferredSide, getPaddedPoint, PaddedPoint, AnchorSlot } from '../utils/anchor.utils';\n\n/**\n * Orthogonal path strategy - routes paths with right-angle turns\n */\nexport class OrthogonalStrategy implements PathStrategy {\n calculatePath(context: PathStrategyContext): PathStrategyResult {\n const { source, target, relationship, allNodes, options, sourceSlot, targetSlot } = context;\n const padding = options.obstaclePadding;\n\n // Create rectangles for collision detection\n const sourceRect = createRect(source);\n const targetRect = createRect(target);\n\n // Get obstacles (all nodes except source and target, with padding)\n const obstacles = options.allowOverlap\n ? []\n : allNodes\n .filter((n) => n.id !== source.id && n.id !== target.id)\n .map((n) => createPaddedRect(n, padding));\n\n // If we have slots from a previous pass, force those sides to maintain consistency\n const forcedSourceSide = sourceSlot?.side ?? relationship.sourceAnchor;\n const forcedTargetSide = targetSlot?.side ?? relationship.targetAnchor;\n\n const bestRoute = this.findBestOrthogonalRoute(\n source,\n target,\n sourceRect,\n targetRect,\n obstacles,\n padding,\n forcedSourceSide,\n forcedTargetSide,\n options.cornerPadding,\n sourceSlot,\n targetSlot\n );\n\n return {\n sourcePoint: {\n side: bestRoute.sourceSide,\n x: bestRoute.waypoints[0].x,\n y: bestRoute.waypoints[0].y,\n },\n targetPoint: {\n side: bestRoute.targetSide,\n x: bestRoute.waypoints[bestRoute.waypoints.length - 1].x,\n y: bestRoute.waypoints[bestRoute.waypoints.length - 1].y,\n },\n waypoints: bestRoute.waypoints,\n };\n }\n\n /**\n * Find the best orthogonal route using padded-edge approach\n */\n private findBestOrthogonalRoute(\n sourceNode: PathNode,\n targetNode: PathNode,\n sourceRect: Rect,\n targetRect: Rect,\n obstacles: Rect[],\n padding: number,\n forcedSourceSide: ConnectionSide | undefined,\n forcedTargetSide: ConnectionSide | undefined,\n cornerPadding: number,\n sourceSlot?: AnchorSlot,\n targetSlot?: AnchorSlot\n ): RouteCandidate {\n const candidates: RouteCandidate[] = [];\n\n // Determine which sides to try\n const sourceSides: ConnectionSide[] = forcedSourceSide\n ? [forcedSourceSide]\n : ['top', 'right', 'bottom', 'left'];\n\n const targetSides: ConnectionSide[] = forcedTargetSide\n ? [forcedTargetSide]\n : ['top', 'right', 'bottom', 'left'];\n\n // Try all side combinations\n for (const sourceSide of sourceSides) {\n for (const targetSide of targetSides) {\n // Get padded points (at padding distance from node edge)\n const sourcePadded = getPaddedPoint(sourceNode, sourceSide, padding, cornerPadding, sourceSlot);\n const targetPadded = getPaddedPoint(targetNode, targetSide, padding, cornerPadding, targetSlot);\n\n // Find route between padded points\n const paddedRoute = this.findPaddedRoute(sourcePadded, targetPadded, sourceRect, targetRect, obstacles, padding);\n\n if (paddedRoute) {\n // Extend route to actual node edges\n const fullRoute = this.extendRouteToEdges(paddedRoute, sourcePadded, targetPadded);\n const length = calculateRouteLength(fullRoute);\n\n candidates.push({\n waypoints: fullRoute,\n length,\n sourceSide,\n targetSide,\n });\n }\n }\n }\n\n // Return the shortest valid route\n if (candidates.length > 0) {\n candidates.sort((a, b) => a.length - b.length);\n return candidates[0];\n }\n\n // Fallback: simple direct route\n const preferredSourceSide = forcedSourceSide || getPreferredSide(sourceNode, targetNode);\n const preferredTargetSide = forcedTargetSide || getPreferredSide(targetNode, sourceNode);\n\n const sourcePadded = getPaddedPoint(sourceNode, preferredSourceSide, padding, cornerPadding, sourceSlot);\n const targetPadded = getPaddedPoint(targetNode, preferredTargetSide, padding, cornerPadding, targetSlot);\n\n const fallbackRoute = this.createFallbackRoute(sourcePadded, targetPadded);\n const fullRoute = this.extendRouteToEdges(fallbackRoute, sourcePadded, targetPadded);\n\n return {\n waypoints: fullRoute,\n length: Infinity,\n sourceSide: preferredSourceSide,\n targetSide: preferredTargetSide,\n };\n }\n\n /**\n * Find route between padded points avoiding obstacles\n */\n private findPaddedRoute(\n source: PaddedPoint,\n target: PaddedPoint,\n sourceRect: Rect,\n targetRect: Rect,\n obstacles: Rect[],\n padding: number\n ): Waypoint[] | null {\n // Create padded obstacle rects for collision detection\n // Include source and target nodes as obstacles (paths shouldn't go through them)\n const paddedSourceRect = expandRect(sourceRect, padding);\n const paddedTargetRect = expandRect(targetRect, padding);\n const allObstacles = [...obstacles, paddedSourceRect, paddedTargetRect];\n\n // Try strategies in order of simplicity\n const strategies = [\n () => this.tryDirect(source, target, allObstacles),\n () => this.tryLShape(source, target, allObstacles),\n () => this.tryZShape(source, target, allObstacles),\n () => this.tryUShape(source, target, sourceRect, targetRect, allObstacles, padding),\n ];\n\n for (const strategy of strategies) {\n const route = strategy();\n if (route) {\n return simplifyPath(route);\n }\n }\n\n return null;\n }\n\n /**\n * Try direct route (straight line between padded points)\n */\n private tryDirect(source: PaddedPoint, target: PaddedPoint, obstacles: Rect[]): Waypoint[] | null {\n // Only works if horizontally or vertically aligned\n const isHorizontal = Math.abs(source.y - target.y) < 1;\n const isVertical = Math.abs(source.x - target.x) < 1;\n\n if (!isHorizontal && !isVertical) return null;\n\n const route: Waypoint[] = [\n { x: source.x, y: source.y },\n { x: target.x, y: target.y },\n ];\n\n if (this.isRouteValid(route, obstacles)) {\n return route;\n }\n\n return null;\n }\n\n /**\n * Try L-shaped route (one bend)\n */\n private tryLShape(source: PaddedPoint, target: PaddedPoint, obstacles: Rect[]): Waypoint[] | null {\n const isHorizontalSource = source.side === 'left' || source.side === 'right';\n const isHorizontalTarget = target.side === 'left' || target.side === 'right';\n\n // L-route only works when source and target are on different axis\n if (isHorizontalSource === isHorizontalTarget) return null;\n\n const routes: Waypoint[][] = [];\n\n if (isHorizontalSource) {\n // Source horizontal, target vertical: go horizontal first, then vertical\n routes.push([\n { x: source.x, y: source.y },\n { x: target.x, y: source.y },\n { x: target.x, y: target.y },\n ]);\n } else {\n // Source vertical, target horizontal: go vertical first, then horizontal\n routes.push([\n { x: source.x, y: source.y },\n { x: source.x, y: target.y },\n { x: target.x, y: target.y },\n ]);\n }\n\n for (const route of routes) {\n if (this.isRouteValid(route, obstacles)) {\n return route;\n }\n }\n\n return null;\n }\n\n /**\n * Try Z-shaped route (two bends)\n */\n private tryZShape(source: PaddedPoint, target: PaddedPoint, obstacles: Rect[]): Waypoint[] | null {\n const isHorizontalSource = source.side === 'left' || source.side === 'right';\n const isHorizontalTarget = target.side === 'left' || target.side === 'right';\n\n const routes: Waypoint[][] = [];\n\n if (isHorizontalSource && isHorizontalTarget) {\n // Both horizontal: route with vertical middle segment\n const midX = (source.x + target.x) / 2;\n routes.push([\n { x: source.x, y: source.y },\n { x: midX, y: source.y },\n { x: midX, y: target.y },\n { x: target.x, y: target.y },\n ]);\n } else if (!isHorizontalSource && !isHorizontalTarget) {\n // Both vertical: route with horizontal middle segment\n const midY = (source.y + target.y) / 2;\n routes.push([\n { x: source.x, y: source.y },\n { x: source.x, y: midY },\n { x: target.x, y: midY },\n { x: target.x, y: target.y },\n ]);\n }\n\n // Sort by length and return first valid\n routes.sort((a, b) => calculateRouteLength(a) - calculateRouteLength(b));\n\n for (const route of routes) {\n if (this.isRouteValid(route, obstacles)) {\n return route;\n }\n }\n\n return null;\n }\n\n /**\n * Try U-shaped route (goes around nodes)\n */\n private tryUShape(\n source: PaddedPoint,\n target: PaddedPoint,\n sourceRect: Rect,\n targetRect: Rect,\n obstacles: Rect[],\n padding: number\n ): Waypoint[] | null {\n const routes: Waypoint[][] = [];\n\n // Calculate bounds for going around\n const minX = Math.min(sourceRect.x, targetRect.x) - padding * 2;\n const maxX = Math.max(sourceRect.right, targetRect.right) + padding * 2;\n const minY = Math.min(sourceRect.y, targetRect.y) - padding * 2;\n const maxY = Math.max(sourceRect.bottom, targetRect.bottom) + padding * 2;\n\n // Route around top\n routes.push([\n { x: source.x, y: source.y },\n { x: source.x, y: minY },\n { x: target.x, y: minY },\n { x: target.x, y: target.y },\n ]);\n\n // Route around bottom\n routes.push([\n { x: source.x, y: source.y },\n { x: source.x, y: maxY },\n { x: target.x, y: maxY },\n { x: target.x, y: target.y },\n ]);\n\n // Route around left\n routes.push([\n { x: source.x, y: source.y },\n { x: minX, y: source.y },\n { x: minX, y: target.y },\n { x: target.x, y: target.y },\n ]);\n\n // Route around right\n routes.push([\n { x: source.x, y: source.y },\n { x: maxX, y: source.y },\n { x: maxX, y: target.y },\n { x: target.x, y: target.y },\n ]);\n\n // Sort by length and return first valid\n routes.sort((a, b) => calculateRouteLength(a) - calculateRouteLength(b));\n\n for (const route of routes) {\n if (this.isRouteValid(route, obstacles)) {\n return route;\n }\n }\n\n return null;\n }\n\n /**\n * Create fallback route when no valid route is found\n */\n private createFallbackRoute(source: PaddedPoint, target: PaddedPoint): Waypoint[] {\n const isHorizontalSource = source.side === 'left' || source.side === 'right';\n\n if (isHorizontalSource) {\n return [\n { x: source.x, y: source.y },\n { x: target.x, y: source.y },\n { x: target.x, y: target.y },\n ];\n } else {\n return [\n { x: source.x, y: source.y },\n { x: source.x, y: target.y },\n { x: target.x, y: target.y },\n ];\n }\n }\n\n /**\n * Extend route from padded points to actual node edges\n */\n private extendRouteToEdges(paddedRoute: Waypoint[], source: PaddedPoint, target: PaddedPoint): Waypoint[] {\n const result: Waypoint[] = [];\n\n // Add start point at node edge\n result.push({ x: source.nodeEdgeX, y: source.nodeEdgeY });\n\n // Add all waypoints from padded route\n for (const wp of paddedRoute) {\n result.push({ x: wp.x, y: wp.y });\n }\n\n // Add end point at node edge\n result.push({ x: target.nodeEdgeX, y: target.nodeEdgeY });\n\n return simplifyPath(result);\n }\n\n /**\n * Check if route is valid (doesn't pass through obstacles)\n */\n private isRouteValid(route: Waypoint[], obstacles: Rect[]): boolean {\n for (let i = 0; i < route.length - 1; i++) {\n const p1 = route[i];\n const p2 = route[i + 1];\n\n for (const obs of obstacles) {\n if (linePassesThroughRect(p1, p2, obs)) {\n return false;\n }\n }\n }\n return true;\n }\n}\n","/**\n * Bezier Path Strategy\n *\n * Generates smooth curved paths using cubic bezier curves.\n * Control points are positioned based on connection sides.\n */\n\nimport { Point, Waypoint, ConnectionPoint } from '../models/path-finding.models';\nimport { PathStrategy, PathStrategyContext, PathStrategyResult } from './path-strategy.interface';\nimport { getConnectionPoint } from '../utils/anchor.utils';\n\n/**\n * Bezier path strategy - creates smooth curved paths\n */\nexport class BezierStrategy implements PathStrategy {\n calculatePath(context: PathStrategyContext): PathStrategyResult {\n const { source, target, relationship, options, sourceSlot, targetSlot } = context;\n\n const sourcePoint = getConnectionPoint(\n source,\n target,\n relationship.sourceAnchor,\n options.cornerPadding,\n sourceSlot,\n options.anchorSpacing\n );\n\n const targetPoint = getConnectionPoint(\n target,\n source,\n relationship.targetAnchor,\n options.cornerPadding,\n targetSlot,\n options.anchorSpacing\n );\n\n const waypoints = this.calculateBezierPath(sourcePoint, targetPoint);\n\n return {\n sourcePoint,\n targetPoint,\n waypoints,\n };\n }\n\n /**\n * Calculate bezier path with control points\n */\n private calculateBezierPath(source: ConnectionPoint, target: ConnectionPoint): Waypoint[] {\n const controlDistance = Math.max(50, Math.hypot(target.x - source.x, target.y - source.y) * 0.3);\n\n const sourceControl = this.getControlPointForBezier(source, controlDistance);\n const targetControl = this.getControlPointForBezier(target, controlDistance);\n\n return [\n { x: source.x, y: source.y },\n { x: sourceControl.x, y: sourceControl.y, isControlPoint: true },\n { x: targetControl.x, y: targetControl.y, isControlPoint: true },\n { x: target.x, y: target.y },\n ];\n }\n\n /**\n * Get control point position based on connection side\n */\n private getControlPointForBezier(connection: ConnectionPoint, distance: number): Point {\n switch (connection.side) {\n case 'top':\n return { x: connection.x, y: connection.y - distance };\n case 'bottom':\n return { x: connection.x, y: connection.y + distance };\n case 'left':\n return { x: connection.x - distance, y: connection.y };\n case 'right':\n return { x: connection.x + distance, y: connection.y };\n }\n }\n}\n","/**\n * Straight Path Strategy\n *\n * Generates direct line paths between nodes.\n * Simple and fast, but may overlap obstacles.\n */\n\nimport { Waypoint } from '../models/path-finding.models';\nimport { PathStrategy, PathStrategyContext, PathStrategyResult } from './path-strategy.interface';\nimport { getConnectionPoint } from '../utils/anchor.utils';\n\n/**\n * Straight path strategy - creates direct line paths\n */\nexport class StraightStrategy implements PathStrategy {\n calculatePath(context: PathStrategyContext): PathStrategyResult {\n const { source, target, relationship, options, sourceSlot, targetSlot } = context;\n\n const sourcePoint = getConnectionPoint(\n source,\n target,\n relationship.sourceAnchor,\n options.cornerPadding,\n sourceSlot,\n options.anchorSpacing\n );\n\n const targetPoint = getConnectionPoint(\n target,\n source,\n relationship.targetAnchor,\n options.cornerPadding,\n targetSlot,\n options.anchorSpacing\n );\n\n const waypoints: Waypoint[] = [\n { x: sourcePoint.x, y: sourcePoint.y },\n { x: targetPoint.x, y: targetPoint.y },\n ];\n\n return {\n sourcePoint,\n targetPoint,\n waypoints,\n };\n }\n}\n","import { Injectable } from '@angular/core';\r\nimport {\r\n PathNode,\r\n PathRelationship,\r\n PathFindingOptions,\r\n PathFindingInput,\r\n PathFindingResult,\r\n CalculatedPath,\r\n DEFAULT_PATH_FINDING_OPTIONS,\r\n} from '../models/path-finding.models';\r\nimport { calculateMidpoint, calculatePathLength } from '../utils/path.utils';\r\nimport { AnchorSlot, calculateAnchorSlotsFromPaths } from '../utils/anchor.utils';\r\nimport { PathStrategy, PathStrategyContext } from '../strategies/path-strategy.interface';\r\nimport { OrthogonalStrategy } from '../strategies/orthogonal.strategy';\r\nimport { BezierStrategy } from '../strategies/bezier.strategy';\r\nimport { StraightStrategy } from '../strategies/straight.strategy';\r\n\r\n/**\r\n * Path Finding Service\r\n *\r\n * Calculates obstacle-aware paths between nodes using smart routing.\r\n * Automatically selects optimal connection sides to find shortest valid paths.\r\n *\r\n * Uses strategy pattern for different path types:\r\n * - Orthogonal: Right-angle turns with obstacle avoidance\r\n * - Bezier: Smooth curved paths\r\n * - Straight: Direct line paths\r\n */\r\n@Injectable()\r\nexport class PathFindingService {\r\n private readonly strategies: Record<string, PathStrategy> = {\r\n orthogonal: new OrthogonalStrategy(),\r\n bezier: new BezierStrategy(),\r\n straight: new StraightStrategy(),\r\n };\r\n\r\n /**\r\n * Calculate paths for all relationships\r\n */\r\n calculatePaths(input: PathFindingInput): PathFindingResult {\r\n const options = { ...DEFAULT_PATH_FINDING_OPTIONS, ...input.options };\r\n const nodeMap = new Map<string, PathNode>();\r\n\r\n for (const node of input.nodes) {\r\n nodeMap.set(node.id, node);\r\n }\r\n\r\n // First pass: calculate paths without anchor spreading to determine actual sides\r\n const initialPaths: CalculatedPath[] = [];\r\n\r\n for (const relationship of input.relationships) {\r\n const sourceNode = nodeMap.get(relationship.sourceId);\r\n const targetNode = nodeMap.get(relationship.targetId);\r\n\r\n if (!sourceNode || !targetNode) {\r\n console.warn(\r\n `PathFindingService: Relationship \"${relationship.id}\" references unknown node`\r\n );\r\n continue;\r\n }\r\n\r\n const path = this.calculatePath(\r\n sourceNode,\r\n targetNode,\r\n relationship,\r\n input.nodes,\r\n options,\r\n undefined,\r\n undefined\r\n );\r\n\r\n initialPaths.push(path);\r\n }\r\n\r\n // If anchor spreading is disabled, return initial paths\r\n if (!options.spreadAnchors) {\r\n return { paths: initialPaths };\r\n }\r\n\r\n // Second pass: calculate anchor slots based on actual sides used, then recalculate paths\r\n const anchorSlots = calculateAnchorSlotsFromPaths(initialPaths, nodeMap);\r\n\r\n const paths: CalculatedPath[] = [];\r\n\r\n for (const relationship of input.relationships) {\r\n const sourceNode = nodeMap.get(relationship.sourceId);\r\n const targetNode = nodeMap.get(relationship.targetId);\r\n\r\n if (!sourceNode || !targetNode) {\r\n continue;\r\n }\r\n\r\n const sourceSlot = anchorSlots.get(`${relationship.id}-source`);\r\n const targetSlot = anchorSlots.get(`${relationship.id}-target`);\r\n\r\n const path = this.calculatePath(\r\n sourceNode,\r\n targetNode,\r\n relationship,\r\n input.nodes,\r\n options,\r\n sourceSlot,\r\n targetSlot\r\n );\r\n\r\n paths.push(path);\r\n }\r\n\r\n return { paths };\r\n }\r\n\r\n /**\r\n * Calculate a single path between two nodes\r\n */\r\n private calculatePath(\r\n source: PathNode,\r\n target: PathNode,\r\n relationship: PathRelationship,\r\n allNodes: PathNode[],\r\n options: Required<PathFindingOptions>,\r\n sourceSlot?: AnchorSlot,\r\n targetSlot?: AnchorSlot\r\n ): CalculatedPath {\r\n const strategy = this.strategies[options.pathType];\r\n\r\n const context: PathStrategyContext = {\r\n source,\r\n target,\r\n relationship,\r\n allNodes,\r\n options,\r\n sourceSlot,\r\n targetSlot,\r\n };\r\n\r\n const result = strategy.calculatePath(context);\r\n const midpoint = calculateMidpoint(result.waypoints);\r\n const length = calculatePathLength(result.waypoints);\r\n\r\n return {\r\n relationshipId: relationship.id,\r\n sourceId: relationship.sourceId,\r\n targetId: relationship.targetId,\r\n sourcePoint: result.sourcePoint,\r\n targetPoint: result.targetPoint,\r\n waypoints: result.waypoints,\r\n midpoint,\r\n length,\r\n pathType: options.pathType,\r\n };\r\n }\r\n\r\n /**\r\n * Recalculate paths (convenience method)\r\n */\r\n recalculatePaths(input: PathFindingInput): PathFindingResult {\r\n return this.calculatePaths(input);\r\n }\r\n\r\n /**\r\n * Calculate a single path (convenience method)\r\n */\r\n calculateSinglePath(\r\n source: PathNode,\r\n target: PathNode,\r\n relationship: PathRelationship,\r\n obstacles: PathNode[],\r\n options?: PathFindingOptions\r\n ): CalculatedPath {\r\n const fullOptions = { ...DEFAULT_PATH_FINDING_OPTIONS, ...options };\r\n return this.calculatePath(\r\n source,\r\n target,\r\n relationship,\r\n obstacles,\r\n fullOptions,\r\n undefined,\r\n undefined\r\n );\r\n }\r\n}\r\n","// Models - Types\nexport type {\n PathType,\n ConnectionSide,\n Point,\n Rectangle,\n PathNode,\n PathRelationship,\n ConnectionPoint,\n Waypoint,\n CalculatedPath,\n PathFindingOptions,\n PathFindingInput,\n PathFindingResult,\n} from './lib/models/path-finding.models';\n\n// Models - Values\nexport { DEFAULT_PATH_FINDING_OPTIONS } from './lib/models/path-finding.models';\n\n// Service\nexport { PathFindingService } from './lib/services/path-finding.service';\n\n// Utilities - Geometry\nexport type { Rect } from './lib/utils/geometry.utils';\nexport {\n clamp,\n createRect,\n createPaddedRect,\n expandRect,\n linePassesThroughRect,\n} from './lib/utils/geometry.utils';\n\n// Utilities - Path\nexport {\n calculateRouteLength,\n calculatePathLength,\n calculateMidpoint,\n simplifyPath,\n} from './lib/utils/path.utils';\n\n// Utilities - Anchor\nexport type { AnchorSlot, PaddedPoint } from './lib/utils/anchor.utils';\nexport {\n getPreferredSide,\n getConnectionPoint,\n getPointOnSide,\n getPaddedPoint,\n calculateSlotPositions,\n findOptimalSlotAssignment,\n calculateAnchorSlotsFromPaths,\n} from './lib/utils/anchor.utils';\n\n// Strategies - Interface\nexport type {\n PathStrategyResult,\n PathStrategyContext,\n RouteCandidate,\n PathStrategy,\n} from './lib/strategies/path-strategy.interface';\n\n// Strategies - Implementations\nexport { OrthogonalStrategy } from './lib/strategies/orthogonal.strategy';\nexport { BezierStrategy } from './lib/strategies/bezier.strategy';\nexport { StraightStrategy } from './lib/strategies/straight.strategy';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Path Finding Models
|
|
5
|
+
*
|
|
6
|
+
* Types and interfaces for obstacle-aware path routing between nodes.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Type of path to generate
|
|
10
|
+
* - orthogonal: Right-angle turns only (Manhattan-style)
|
|
11
|
+
* - bezier: Smooth curved paths
|
|
12
|
+
* - straight: Direct line (may overlap obstacles)
|
|
13
|
+
*/
|
|
14
|
+
type PathType = 'orthogonal' | 'bezier' | 'straight';
|
|
15
|
+
/**
|
|
16
|
+
* Side of a node where a connection point is located
|
|
17
|
+
*/
|
|
18
|
+
type ConnectionSide = 'top' | 'right' | 'bottom' | 'left';
|
|
19
|
+
/**
|
|
20
|
+
* A point in 2D space
|
|
21
|
+
*/
|
|
22
|
+
interface Point {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A rectangle representing a node's bounds
|
|
28
|
+
*/
|
|
29
|
+
interface Rectangle {
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
width: number;
|
|
33
|
+
height: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* A node with position and dimensions for path finding
|
|
37
|
+
* Used as an obstacle when routing paths
|
|
38
|
+
*/
|
|
39
|
+
interface PathNode {
|
|
40
|
+
/** Unique identifier */
|
|
41
|
+
id: string;
|
|
42
|
+
/** X coordinate (top-left corner) */
|
|
43
|
+
x: number;
|
|
44
|
+
/** Y coordinate (top-left corner) */
|
|
45
|
+
y: number;
|
|
46
|
+
/** Width of the node */
|
|
47
|
+
width: number;
|
|
48
|
+
/** Height of the node */
|
|
49
|
+
height: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A relationship/edge between two nodes that needs a path
|
|
53
|
+
*/
|
|
54
|
+
interface PathRelationship {
|
|
55
|
+
/** Unique identifier for this relationship */
|
|
56
|
+
id: string;
|
|
57
|
+
/** ID of the source node */
|
|
58
|
+
sourceId: string;
|
|
59
|
+
/** ID of the target node */
|
|
60
|
+
targetId: string;
|
|
61
|
+
/** Optional: force connection from specific side of source */
|
|
62
|
+
sourceAnchor?: ConnectionSide;
|
|
63
|
+
/** Optional: force connection to specific side of target */
|
|
64
|
+
targetAnchor?: ConnectionSide;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* A connection point on a node's edge
|
|
68
|
+
*/
|
|
69
|
+
interface ConnectionPoint {
|
|
70
|
+
/** The side of the node */
|
|
71
|
+
side: ConnectionSide;
|
|
72
|
+
/** X coordinate of the connection point */
|
|
73
|
+
x: number;
|
|
74
|
+
/** Y coordinate of the connection point */
|
|
75
|
+
y: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A waypoint along a path
|
|
79
|
+
*/
|
|
80
|
+
interface Waypoint extends Point {
|
|
81
|
+
/** Optional: indicates if this is a control point for bezier curves */
|
|
82
|
+
isControlPoint?: boolean;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A calculated path between two nodes
|
|
86
|
+
*/
|
|
87
|
+
interface CalculatedPath {
|
|
88
|
+
/** The relationship ID this path corresponds to */
|
|
89
|
+
relationshipId: string;
|
|
90
|
+
/** Source node ID */
|
|
91
|
+
sourceId: string;
|
|
92
|
+
/** Target node ID */
|
|
93
|
+
targetId: string;
|
|
94
|
+
/** Connection point on source node */
|
|
95
|
+
sourcePoint: ConnectionPoint;
|
|
96
|
+
/** Connection point on target node */
|
|
97
|
+
targetPoint: ConnectionPoint;
|
|
98
|
+
/** Ordered list of waypoints forming the path */
|
|
99
|
+
waypoints: Waypoint[];
|
|
100
|
+
/** The midpoint of the path (useful for labels/pills) */
|
|
101
|
+
midpoint: Point;
|
|
102
|
+
/** Total length of the path */
|
|
103
|
+
length: number;
|
|
104
|
+
/** Type of path */
|
|
105
|
+
pathType: PathType;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Options for path finding
|
|
109
|
+
*/
|
|
110
|
+
interface PathFindingOptions {
|
|
111
|
+
/** Type of path to generate */
|
|
112
|
+
pathType?: PathType;
|
|
113
|
+
/** Padding around obstacles when routing */
|
|
114
|
+
obstaclePadding?: number;
|
|
115
|
+
/** Minimum distance from node corners for connection points */
|
|
116
|
+
cornerPadding?: number;
|
|
117
|
+
/** Minimum spacing between connection points on same side */
|
|
118
|
+
connectionSpacing?: number;
|
|
119
|
+
/** Whether to allow paths to pass through other nodes */
|
|
120
|
+
allowOverlap?: boolean;
|
|
121
|
+
/** Whether to spread anchor points when multiple edges connect to the same side */
|
|
122
|
+
spreadAnchors?: boolean;
|
|
123
|
+
/** Spacing between spread anchor points (when spreadAnchors is enabled) */
|
|
124
|
+
anchorSpacing?: number;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Default path finding options
|
|
128
|
+
*/
|
|
129
|
+
declare const DEFAULT_PATH_FINDING_OPTIONS: Required<PathFindingOptions>;
|
|
130
|
+
/**
|
|
131
|
+
* Input for path finding calculation
|
|
132
|
+
*/
|
|
133
|
+
interface PathFindingInput {
|
|
134
|
+
/** All nodes (used as obstacles) */
|
|
135
|
+
nodes: PathNode[];
|
|
136
|
+
/** Relationships to calculate paths for */
|
|
137
|
+
relationships: PathRelationship[];
|
|
138
|
+
/** Path finding options */
|
|
139
|
+
options?: PathFindingOptions;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Result of path finding calculation
|
|
143
|
+
*/
|
|
144
|
+
interface PathFindingResult {
|
|
145
|
+
/** Calculated paths for each relationship */
|
|
146
|
+
paths: CalculatedPath[];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Path Finding Service
|
|
151
|
+
*
|
|
152
|
+
* Calculates obstacle-aware paths between nodes using smart routing.
|
|
153
|
+
* Automatically selects optimal connection sides to find shortest valid paths.
|
|
154
|
+
*
|
|
155
|
+
* Uses strategy pattern for different path types:
|
|
156
|
+
* - Orthogonal: Right-angle turns with obstacle avoidance
|
|
157
|
+
* - Bezier: Smooth curved paths
|
|
158
|
+
* - Straight: Direct line paths
|
|
159
|
+
*/
|
|
160
|
+
declare class PathFindingService {
|
|
161
|
+
private readonly strategies;
|
|
162
|
+
/**
|
|
163
|
+
* Calculate paths for all relationships
|
|
164
|
+
*/
|
|
165
|
+
calculatePaths(input: PathFindingInput): PathFindingResult;
|
|
166
|
+
/**
|
|
167
|
+
* Calculate a single path between two nodes
|
|
168
|
+
*/
|
|
169
|
+
private calculatePath;
|
|
170
|
+
/**
|
|
171
|
+
* Recalculate paths (convenience method)
|
|
172
|
+
*/
|
|
173
|
+
recalculatePaths(input: PathFindingInput): PathFindingResult;
|
|
174
|
+
/**
|
|
175
|
+
* Calculate a single path (convenience method)
|
|
176
|
+
*/
|
|
177
|
+
calculateSinglePath(source: PathNode, target: PathNode, relationship: PathRelationship, obstacles: PathNode[], options?: PathFindingOptions): CalculatedPath;
|
|
178
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<PathFindingService, never>;
|
|
179
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<PathFindingService>;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Geometry Utilities
|
|
184
|
+
*
|
|
185
|
+
* Core geometric types and functions for path finding calculations.
|
|
186
|
+
*/
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Rectangle with computed bounds for efficient collision detection
|
|
190
|
+
*/
|
|
191
|
+
interface Rect {
|
|
192
|
+
x: number;
|
|
193
|
+
y: number;
|
|
194
|
+
width: number;
|
|
195
|
+
height: number;
|
|
196
|
+
right: number;
|
|
197
|
+
bottom: number;
|
|
198
|
+
centerX: number;
|
|
199
|
+
centerY: number;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Clamp a value between min and max
|
|
203
|
+
*/
|
|
204
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
205
|
+
/**
|
|
206
|
+
* Create a Rect from a PathNode
|
|
207
|
+
*/
|
|
208
|
+
declare function createRect(node: PathNode): Rect;
|
|
209
|
+
/**
|
|
210
|
+
* Create a padded Rect from a PathNode
|
|
211
|
+
*/
|
|
212
|
+
declare function createPaddedRect(node: PathNode, padding: number): Rect;
|
|
213
|
+
/**
|
|
214
|
+
* Expand a Rect by padding amount on all sides
|
|
215
|
+
*/
|
|
216
|
+
declare function expandRect(rect: Rect, padding: number): Rect;
|
|
217
|
+
/**
|
|
218
|
+
* Check if a line segment passes through rectangle interior (not just touches edge)
|
|
219
|
+
* Used for obstacle collision detection in orthogonal routing
|
|
220
|
+
*/
|
|
221
|
+
declare function linePassesThroughRect(p1: Point, p2: Point, rect: Rect): boolean;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Path Utilities
|
|
225
|
+
*
|
|
226
|
+
* Functions for path manipulation, simplification, and measurement.
|
|
227
|
+
*/
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Calculate the length of a route using Manhattan distance (orthogonal segments)
|
|
231
|
+
* Used for comparing route candidates
|
|
232
|
+
*/
|
|
233
|
+
declare function calculateRouteLength(points: Point[]): number;
|
|
234
|
+
/**
|
|
235
|
+
* Calculate total path length using Euclidean distance
|
|
236
|
+
* Excludes control points for bezier curves
|
|
237
|
+
*/
|
|
238
|
+
declare function calculatePathLength(waypoints: Waypoint[]): number;
|
|
239
|
+
/**
|
|
240
|
+
* Calculate the midpoint of a path
|
|
241
|
+
* Returns the point at half the total path length
|
|
242
|
+
*/
|
|
243
|
+
declare function calculateMidpoint(waypoints: Waypoint[]): Point;
|
|
244
|
+
/**
|
|
245
|
+
* Simplify path by removing collinear points
|
|
246
|
+
* This reduces redundant waypoints while preserving path shape
|
|
247
|
+
*/
|
|
248
|
+
declare function simplifyPath(waypoints: Waypoint[]): Waypoint[];
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Anchor Utilities
|
|
252
|
+
*
|
|
253
|
+
* Functions for calculating connection points and anchor slot assignments.
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Anchor slot assignment for spreading multiple connections on the same side
|
|
258
|
+
*/
|
|
259
|
+
interface AnchorSlot {
|
|
260
|
+
nodeId: string;
|
|
261
|
+
side: ConnectionSide;
|
|
262
|
+
relationshipId: string;
|
|
263
|
+
isSource: boolean;
|
|
264
|
+
slotIndex: number;
|
|
265
|
+
totalSlots: number;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Padded connection point - sits at padding distance from node edge
|
|
269
|
+
*/
|
|
270
|
+
interface PaddedPoint {
|
|
271
|
+
x: number;
|
|
272
|
+
y: number;
|
|
273
|
+
side: ConnectionSide;
|
|
274
|
+
nodeEdgeX: number;
|
|
275
|
+
nodeEdgeY: number;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Get preferred connection side based on relative position of nodes
|
|
279
|
+
*/
|
|
280
|
+
declare function getPreferredSide(from: PathNode, to: PathNode): ConnectionSide;
|
|
281
|
+
/**
|
|
282
|
+
* Get connection point on a node
|
|
283
|
+
*/
|
|
284
|
+
declare function getConnectionPoint(node: PathNode, targetNode: PathNode, forcedAnchor: ConnectionSide | undefined, cornerPadding: number, slot?: AnchorSlot, anchorSpacing?: number): ConnectionPoint;
|
|
285
|
+
/**
|
|
286
|
+
* Get point on a specific side of a node
|
|
287
|
+
* Uses even distribution when multiple slots are on the same side
|
|
288
|
+
*/
|
|
289
|
+
declare function getPointOnSide(node: PathNode, side: ConnectionSide, cornerPadding: number, slot?: AnchorSlot, _anchorSpacing?: number): Point;
|
|
290
|
+
/**
|
|
291
|
+
* Get a padded point - sits at padding distance from node edge
|
|
292
|
+
* Uses even distribution when multiple slots are on the same side
|
|
293
|
+
*/
|
|
294
|
+
declare function getPaddedPoint(node: PathNode, side: ConnectionSide, padding: number, cornerPadding: number, slot?: AnchorSlot): PaddedPoint;
|
|
295
|
+
/**
|
|
296
|
+
* Calculate actual slot positions on a node edge
|
|
297
|
+
* Uses even distribution across the available edge space
|
|
298
|
+
*/
|
|
299
|
+
declare function calculateSlotPositions(node: PathNode, side: ConnectionSide, totalSlots: number, cornerPadding?: number): Array<{
|
|
300
|
+
x: number;
|
|
301
|
+
y: number;
|
|
302
|
+
}>;
|
|
303
|
+
/**
|
|
304
|
+
* Find optimal slot assignment to minimize crossings
|
|
305
|
+
* Returns an array where assignment[connIndex] = slotIndex
|
|
306
|
+
*/
|
|
307
|
+
declare function findOptimalSlotAssignment(connections: Array<{
|
|
308
|
+
otherNodeX: number;
|
|
309
|
+
otherNodeY: number;
|
|
310
|
+
relationshipId: string;
|
|
311
|
+
isSource: boolean;
|
|
312
|
+
}>, slotPositions: Array<{
|
|
313
|
+
x: number;
|
|
314
|
+
y: number;
|
|
315
|
+
}>): number[];
|
|
316
|
+
/**
|
|
317
|
+
* Calculate anchor slot assignments based on actual path results
|
|
318
|
+
* This uses the sides that were actually chosen by the routing algorithm
|
|
319
|
+
*/
|
|
320
|
+
declare function calculateAnchorSlotsFromPaths(paths: CalculatedPath[], nodeMap: Map<string, PathNode>): Map<string, AnchorSlot>;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Path Strategy Interface
|
|
324
|
+
*
|
|
325
|
+
* Base interface for path generation strategies.
|
|
326
|
+
* Each strategy implements a different path type (orthogonal, bezier, straight).
|
|
327
|
+
*/
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Result from a path strategy calculation
|
|
331
|
+
*/
|
|
332
|
+
interface PathStrategyResult {
|
|
333
|
+
/** Connection point on source node */
|
|
334
|
+
sourcePoint: ConnectionPoint;
|
|
335
|
+
/** Connection point on target node */
|
|
336
|
+
targetPoint: ConnectionPoint;
|
|
337
|
+
/** Ordered list of waypoints forming the path */
|
|
338
|
+
waypoints: Waypoint[];
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Context passed to path strategies
|
|
342
|
+
*/
|
|
343
|
+
interface PathStrategyContext {
|
|
344
|
+
/** Source node */
|
|
345
|
+
source: PathNode;
|
|
346
|
+
/** Target node */
|
|
347
|
+
target: PathNode;
|
|
348
|
+
/** Relationship being routed */
|
|
349
|
+
relationship: PathRelationship;
|
|
350
|
+
/** All nodes (for obstacle detection) */
|
|
351
|
+
allNodes: PathNode[];
|
|
352
|
+
/** Path finding options */
|
|
353
|
+
options: Required<PathFindingOptions>;
|
|
354
|
+
/** Optional source anchor slot for spreading */
|
|
355
|
+
sourceSlot?: AnchorSlot;
|
|
356
|
+
/** Optional target anchor slot for spreading */
|
|
357
|
+
targetSlot?: AnchorSlot;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* A candidate route with metadata for comparison
|
|
361
|
+
*/
|
|
362
|
+
interface RouteCandidate {
|
|
363
|
+
waypoints: Waypoint[];
|
|
364
|
+
length: number;
|
|
365
|
+
sourceSide: ConnectionSide;
|
|
366
|
+
targetSide: ConnectionSide;
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Interface for path generation strategies
|
|
370
|
+
*/
|
|
371
|
+
interface PathStrategy {
|
|
372
|
+
/**
|
|
373
|
+
* Calculate a path between source and target nodes
|
|
374
|
+
*/
|
|
375
|
+
calculatePath(context: PathStrategyContext): PathStrategyResult;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Orthogonal Path Strategy
|
|
380
|
+
*
|
|
381
|
+
* Generates paths with right-angle turns only (Manhattan-style routing).
|
|
382
|
+
* Supports obstacle avoidance with multiple routing strategies.
|
|
383
|
+
*/
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Orthogonal path strategy - routes paths with right-angle turns
|
|
387
|
+
*/
|
|
388
|
+
declare class OrthogonalStrategy implements PathStrategy {
|
|
389
|
+
calculatePath(context: PathStrategyContext): PathStrategyResult;
|
|
390
|
+
/**
|
|
391
|
+
* Find the best orthogonal route using padded-edge approach
|
|
392
|
+
*/
|
|
393
|
+
private findBestOrthogonalRoute;
|
|
394
|
+
/**
|
|
395
|
+
* Find route between padded points avoiding obstacles
|
|
396
|
+
*/
|
|
397
|
+
private findPaddedRoute;
|
|
398
|
+
/**
|
|
399
|
+
* Try direct route (straight line between padded points)
|
|
400
|
+
*/
|
|
401
|
+
private tryDirect;
|
|
402
|
+
/**
|
|
403
|
+
* Try L-shaped route (one bend)
|
|
404
|
+
*/
|
|
405
|
+
private tryLShape;
|
|
406
|
+
/**
|
|
407
|
+
* Try Z-shaped route (two bends)
|
|
408
|
+
*/
|
|
409
|
+
private tryZShape;
|
|
410
|
+
/**
|
|
411
|
+
* Try U-shaped route (goes around nodes)
|
|
412
|
+
*/
|
|
413
|
+
private tryUShape;
|
|
414
|
+
/**
|
|
415
|
+
* Create fallback route when no valid route is found
|
|
416
|
+
*/
|
|
417
|
+
private createFallbackRoute;
|
|
418
|
+
/**
|
|
419
|
+
* Extend route from padded points to actual node edges
|
|
420
|
+
*/
|
|
421
|
+
private extendRouteToEdges;
|
|
422
|
+
/**
|
|
423
|
+
* Check if route is valid (doesn't pass through obstacles)
|
|
424
|
+
*/
|
|
425
|
+
private isRouteValid;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Bezier Path Strategy
|
|
430
|
+
*
|
|
431
|
+
* Generates smooth curved paths using cubic bezier curves.
|
|
432
|
+
* Control points are positioned based on connection sides.
|
|
433
|
+
*/
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* Bezier path strategy - creates smooth curved paths
|
|
437
|
+
*/
|
|
438
|
+
declare class BezierStrategy implements PathStrategy {
|
|
439
|
+
calculatePath(context: PathStrategyContext): PathStrategyResult;
|
|
440
|
+
/**
|
|
441
|
+
* Calculate bezier path with control points
|
|
442
|
+
*/
|
|
443
|
+
private calculateBezierPath;
|
|
444
|
+
/**
|
|
445
|
+
* Get control point position based on connection side
|
|
446
|
+
*/
|
|
447
|
+
private getControlPointForBezier;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Straight Path Strategy
|
|
452
|
+
*
|
|
453
|
+
* Generates direct line paths between nodes.
|
|
454
|
+
* Simple and fast, but may overlap obstacles.
|
|
455
|
+
*/
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Straight path strategy - creates direct line paths
|
|
459
|
+
*/
|
|
460
|
+
declare class StraightStrategy implements PathStrategy {
|
|
461
|
+
calculatePath(context: PathStrategyContext): PathStrategyResult;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export { BezierStrategy, DEFAULT_PATH_FINDING_OPTIONS, OrthogonalStrategy, PathFindingService, StraightStrategy, calculateAnchorSlotsFromPaths, calculateMidpoint, calculatePathLength, calculateRouteLength, calculateSlotPositions, clamp, createPaddedRect, createRect, expandRect, findOptimalSlotAssignment, getConnectionPoint, getPaddedPoint, getPointOnSide, getPreferredSide, linePassesThroughRect, simplifyPath };
|
|
465
|
+
export type { AnchorSlot, CalculatedPath, ConnectionPoint, ConnectionSide, PaddedPoint, PathFindingInput, PathFindingOptions, PathFindingResult, PathNode, PathRelationship, PathStrategy, PathStrategyContext, PathStrategyResult, PathType, Point, Rect, Rectangle, RouteCandidate, Waypoint };
|