@esengine/pathfinding 12.1.2 → 13.1.0

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/BinaryHeap.ts","../src/core/AStarPathfinder.ts","../src/core/GridPathfinder.ts","../src/core/JPSPathfinder.ts","../src/core/HPAPathfinder.ts","../src/navmesh/NavMesh.ts"],"sourcesContent":["/**\n * @zh 二叉堆(优先队列)\n * @en Binary Heap (Priority Queue)\n *\n * @zh 用于 A* 算法的高效开放列表\n * @en Efficient open list for A* algorithm\n */\nexport class BinaryHeap<T> {\n private heap: T[] = [];\n private readonly compare: (a: T, b: T) => number;\n\n /**\n * @zh 创建二叉堆\n * @en Create binary heap\n *\n * @param compare - @zh 比较函数,返回负数表示 a < b @en Compare function, returns negative if a < b\n */\n constructor(compare: (a: T, b: T) => number) {\n this.compare = compare;\n }\n\n /**\n * @zh 堆大小\n * @en Heap size\n */\n get size(): number {\n return this.heap.length;\n }\n\n /**\n * @zh 是否为空\n * @en Is empty\n */\n get isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * @zh 插入元素\n * @en Push element\n */\n push(item: T): void {\n this.heap.push(item);\n this.bubbleUp(this.heap.length - 1);\n }\n\n /**\n * @zh 弹出最小元素\n * @en Pop minimum element\n */\n pop(): T | undefined {\n if (this.heap.length === 0) {\n return undefined;\n }\n\n const result = this.heap[0];\n const last = this.heap.pop()!;\n\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sinkDown(0);\n }\n\n return result;\n }\n\n /**\n * @zh 查看最小元素(不移除)\n * @en Peek minimum element (without removing)\n */\n peek(): T | undefined {\n return this.heap[0];\n }\n\n /**\n * @zh 更新元素(重新排序)\n * @en Update element (re-sort)\n */\n update(item: T): void {\n const index = this.heap.indexOf(item);\n if (index !== -1) {\n this.bubbleUp(index);\n this.sinkDown(index);\n }\n }\n\n /**\n * @zh 检查是否包含元素\n * @en Check if contains element\n */\n contains(item: T): boolean {\n return this.heap.indexOf(item) !== -1;\n }\n\n /**\n * @zh 清空堆\n * @en Clear heap\n */\n clear(): void {\n this.heap.length = 0;\n }\n\n /**\n * @zh 上浮操作\n * @en Bubble up operation\n */\n private bubbleUp(index: number): void {\n const item = this.heap[index];\n\n while (index > 0) {\n const parentIndex = Math.floor((index - 1) / 2);\n const parent = this.heap[parentIndex];\n\n if (this.compare(item, parent) >= 0) {\n break;\n }\n\n this.heap[index] = parent;\n index = parentIndex;\n }\n\n this.heap[index] = item;\n }\n\n /**\n * @zh 下沉操作\n * @en Sink down operation\n */\n private sinkDown(index: number): void {\n const length = this.heap.length;\n const item = this.heap[index];\n\n while (true) {\n const leftIndex = 2 * index + 1;\n const rightIndex = 2 * index + 2;\n let smallest = index;\n\n if (leftIndex < length && this.compare(this.heap[leftIndex], this.heap[smallest]) < 0) {\n smallest = leftIndex;\n }\n\n if (rightIndex < length && this.compare(this.heap[rightIndex], this.heap[smallest]) < 0) {\n smallest = rightIndex;\n }\n\n if (smallest === index) {\n break;\n }\n\n this.heap[index] = this.heap[smallest];\n this.heap[smallest] = item;\n index = smallest;\n }\n }\n}\n","/**\n * @zh A* 寻路算法实现\n * @en A* Pathfinding Algorithm Implementation\n */\n\nimport { IndexedBinaryHeap, type IHeapIndexable } from './IndexedBinaryHeap';\nimport type {\n IPathfindingMap,\n IPathfinder,\n IPathResult,\n IPathfindingOptions,\n IPathNode,\n IPoint\n} from './IPathfinding';\nimport { EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from './IPathfinding';\n\n// =============================================================================\n// 内部节点类型 | Internal Node Type\n// =============================================================================\n\ninterface AStarNode extends IHeapIndexable {\n node: IPathNode;\n g: number; // Cost from start\n h: number; // Heuristic to end\n f: number; // Total cost (g + h)\n parent: AStarNode | null;\n closed: boolean;\n opened: boolean;\n heapIndex: number; // For IndexedBinaryHeap O(log n) update\n}\n\n// =============================================================================\n// A* 寻路器 | A* Pathfinder\n// =============================================================================\n\n/**\n * @zh A* 寻路器\n * @en A* Pathfinder\n *\n * @zh 使用 A* 算法在地图上查找最短路径\n * @en Uses A* algorithm to find shortest path on a map\n *\n * @example\n * ```typescript\n * const map = new GridMap(width, height);\n * const pathfinder = new AStarPathfinder(map);\n * const result = pathfinder.findPath(0, 0, 10, 10);\n * if (result.found) {\n * console.log('Path:', result.path);\n * }\n * ```\n */\nexport class AStarPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private nodeCache: Map<string | number, AStarNode> = new Map();\n private openList: IndexedBinaryHeap<AStarNode>;\n\n constructor(map: IPathfindingMap) {\n this.map = map;\n this.openList = new IndexedBinaryHeap<AStarNode>((a, b) => a.f - b.f);\n }\n\n /**\n * @zh 查找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n // Clear previous state\n this.clear();\n\n // Get start and end nodes\n const startNode = this.map.getNodeAt(startX, startY);\n const endNode = this.map.getNodeAt(endX, endY);\n\n // Validate nodes\n if (!startNode || !endNode) {\n return EMPTY_PATH_RESULT;\n }\n\n if (!startNode.walkable || !endNode.walkable) {\n return EMPTY_PATH_RESULT;\n }\n\n // Same position\n if (startNode.id === endNode.id) {\n return {\n found: true,\n path: [startNode.position],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n // Initialize start node\n const start = this.getOrCreateAStarNode(startNode);\n start.g = 0;\n start.h = this.map.heuristic(startNode.position, endNode.position) * opts.heuristicWeight;\n start.f = start.h;\n start.opened = true;\n\n this.openList.push(start);\n\n let nodesSearched = 0;\n const endPosition = endNode.position;\n\n // A* main loop\n while (!this.openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = this.openList.pop()!;\n current.closed = true;\n nodesSearched++;\n\n // Found the goal\n if (current.node.id === endNode.id) {\n return this.buildPath(current, nodesSearched);\n }\n\n // Explore neighbors\n const neighbors = this.map.getNeighbors(current.node);\n\n for (const neighborNode of neighbors) {\n // Skip if not walkable or already closed\n if (!neighborNode.walkable) {\n continue;\n }\n\n const neighbor = this.getOrCreateAStarNode(neighborNode);\n\n if (neighbor.closed) {\n continue;\n }\n\n // Calculate tentative g score\n const movementCost = this.map.getMovementCost(current.node, neighborNode);\n const tentativeG = current.g + movementCost;\n\n // Check if this path is better\n if (!neighbor.opened) {\n // First time visiting this node\n neighbor.g = tentativeG;\n neighbor.h = this.map.heuristic(neighborNode.position, endPosition) * opts.heuristicWeight;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n neighbor.opened = true;\n this.openList.push(neighbor);\n } else if (tentativeG < neighbor.g) {\n // Found a better path\n neighbor.g = tentativeG;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n this.openList.update(neighbor);\n }\n }\n }\n\n // No path found\n return {\n found: false,\n path: [],\n cost: 0,\n nodesSearched\n };\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.nodeCache.clear();\n this.openList.clear();\n }\n\n /**\n * @zh 获取或创建 A* 节点\n * @en Get or create A* node\n */\n private getOrCreateAStarNode(node: IPathNode): AStarNode {\n let astarNode = this.nodeCache.get(node.id);\n\n if (!astarNode) {\n astarNode = {\n node,\n g: Infinity,\n h: 0,\n f: Infinity,\n parent: null,\n closed: false,\n opened: false,\n heapIndex: -1\n };\n this.nodeCache.set(node.id, astarNode);\n }\n\n return astarNode;\n }\n\n /**\n * @zh 构建路径结果\n * @en Build path result\n */\n private buildPath(endNode: AStarNode, nodesSearched: number): IPathResult {\n const path: IPoint[] = [];\n let current: AStarNode | null = endNode;\n\n while (current) {\n path.push(current.node.position);\n current = current.parent;\n }\n\n path.reverse();\n\n return {\n found: true,\n path,\n cost: endNode.g,\n nodesSearched\n };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 A* 寻路器\n * @en Create A* pathfinder\n */\nexport function createAStarPathfinder(map: IPathfindingMap): AStarPathfinder {\n return new AStarPathfinder(map);\n}\n","/**\n * @zh 网格寻路器(统一实现)\n * @en Grid Pathfinder (unified implementation)\n */\n\nimport type { IPathfinder, IPathResult, IPathfindingOptions, IPoint } from './IPathfinding';\nimport { EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from './IPathfinding';\nimport { GridMap } from '../grid/GridMap';\n\n// =============================================================================\n// 配置 | Configuration\n// =============================================================================\n\n/**\n * @zh 寻路模式\n * @en Pathfinding mode\n */\nexport type GridPathfinderMode = 'standard' | 'fast' | 'bidirectional';\n\n/**\n * @zh 网格寻路器配置\n * @en Grid pathfinder configuration\n */\nexport interface IGridPathfinderConfig {\n /**\n * @zh 寻路模式\n * @en Pathfinding mode\n *\n * - standard: 标准A*,适合小地图\n * - fast: TypedArray优化,适合中大地图\n * - bidirectional: 双向搜索,适合超大地图\n */\n mode?: GridPathfinderMode;\n}\n\n// =============================================================================\n// 常量 | Constants\n// =============================================================================\n\nconst CLOSED_FLAG = 1;\nconst OPENED_FLAG = 2;\nconst BACKWARD_CLOSED = 4;\nconst BACKWARD_OPENED = 8;\n\n// =============================================================================\n// 状态存储 | State Storage\n// =============================================================================\n\nclass GridState {\n private readonly size: number;\n readonly width: number;\n\n private g: Float32Array;\n private f: Float32Array;\n private flags: Uint8Array;\n private parent: Int32Array;\n private heapIndex: Int32Array;\n private version: Uint32Array;\n private currentVersion: number = 1;\n\n // 双向搜索额外状态\n private gBack: Float32Array | null = null;\n private fBack: Float32Array | null = null;\n private parentBack: Int32Array | null = null;\n private heapIndexBack: Int32Array | null = null;\n\n constructor(width: number, height: number, bidirectional: boolean = false) {\n this.width = width;\n this.size = width * height;\n\n this.g = new Float32Array(this.size);\n this.f = new Float32Array(this.size);\n this.flags = new Uint8Array(this.size);\n this.parent = new Int32Array(this.size);\n this.heapIndex = new Int32Array(this.size);\n this.version = new Uint32Array(this.size);\n\n if (bidirectional) {\n this.gBack = new Float32Array(this.size);\n this.fBack = new Float32Array(this.size);\n this.parentBack = new Int32Array(this.size);\n this.heapIndexBack = new Int32Array(this.size);\n }\n }\n\n reset(): void {\n this.currentVersion++;\n if (this.currentVersion > 0xFFFFFFFF) {\n this.version.fill(0);\n this.currentVersion = 1;\n }\n }\n\n private isInit(i: number): boolean {\n return this.version[i] === this.currentVersion;\n }\n\n private init(i: number): void {\n if (!this.isInit(i)) {\n this.g[i] = Infinity;\n this.f[i] = Infinity;\n this.flags[i] = 0;\n this.parent[i] = -1;\n this.heapIndex[i] = -1;\n if (this.gBack) {\n this.gBack[i] = Infinity;\n this.fBack![i] = Infinity;\n this.parentBack![i] = -1;\n this.heapIndexBack![i] = -1;\n }\n this.version[i] = this.currentVersion;\n }\n }\n\n // Forward\n getG(i: number): number { return this.isInit(i) ? this.g[i] : Infinity; }\n setG(i: number, v: number): void { this.init(i); this.g[i] = v; }\n getF(i: number): number { return this.isInit(i) ? this.f[i] : Infinity; }\n setF(i: number, v: number): void { this.init(i); this.f[i] = v; }\n getParent(i: number): number { return this.isInit(i) ? this.parent[i] : -1; }\n setParent(i: number, v: number): void { this.init(i); this.parent[i] = v; }\n getHeapIndex(i: number): number { return this.isInit(i) ? this.heapIndex[i] : -1; }\n setHeapIndex(i: number, v: number): void { this.init(i); this.heapIndex[i] = v; }\n isClosed(i: number): boolean { return this.isInit(i) && (this.flags[i] & CLOSED_FLAG) !== 0; }\n setClosed(i: number): void { this.init(i); this.flags[i] |= CLOSED_FLAG; }\n isOpened(i: number): boolean { return this.isInit(i) && (this.flags[i] & OPENED_FLAG) !== 0; }\n setOpened(i: number): void { this.init(i); this.flags[i] |= OPENED_FLAG; }\n\n // Backward\n getGBack(i: number): number { return this.isInit(i) ? this.gBack![i] : Infinity; }\n setGBack(i: number, v: number): void { this.init(i); this.gBack![i] = v; }\n getFBack(i: number): number { return this.isInit(i) ? this.fBack![i] : Infinity; }\n setFBack(i: number, v: number): void { this.init(i); this.fBack![i] = v; }\n getParentBack(i: number): number { return this.isInit(i) ? this.parentBack![i] : -1; }\n setParentBack(i: number, v: number): void { this.init(i); this.parentBack![i] = v; }\n getHeapIndexBack(i: number): number { return this.isInit(i) ? this.heapIndexBack![i] : -1; }\n setHeapIndexBack(i: number, v: number): void { this.init(i); this.heapIndexBack![i] = v; }\n isClosedBack(i: number): boolean { return this.isInit(i) && (this.flags[i] & BACKWARD_CLOSED) !== 0; }\n setClosedBack(i: number): void { this.init(i); this.flags[i] |= BACKWARD_CLOSED; }\n isOpenedBack(i: number): boolean { return this.isInit(i) && (this.flags[i] & BACKWARD_OPENED) !== 0; }\n setOpenedBack(i: number): void { this.init(i); this.flags[i] |= BACKWARD_OPENED; }\n}\n\n// =============================================================================\n// 堆 | Heap\n// =============================================================================\n\nclass GridHeap {\n private heap: number[] = [];\n private state: GridState;\n private isBack: boolean;\n\n constructor(state: GridState, isBack: boolean = false) {\n this.state = state;\n this.isBack = isBack;\n }\n\n get size(): number { return this.heap.length; }\n get isEmpty(): boolean { return this.heap.length === 0; }\n\n private getF(i: number): number {\n return this.isBack ? this.state.getFBack(i) : this.state.getF(i);\n }\n private getHeapIndex(i: number): number {\n return this.isBack ? this.state.getHeapIndexBack(i) : this.state.getHeapIndex(i);\n }\n private setHeapIndex(i: number, v: number): void {\n if (this.isBack) this.state.setHeapIndexBack(i, v);\n else this.state.setHeapIndex(i, v);\n }\n\n push(i: number): void {\n this.setHeapIndex(i, this.heap.length);\n this.heap.push(i);\n this.bubbleUp(this.heap.length - 1);\n }\n\n pop(): number {\n if (this.heap.length === 0) return -1;\n const result = this.heap[0];\n this.setHeapIndex(result, -1);\n const last = this.heap.pop()!;\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.setHeapIndex(last, 0);\n this.sinkDown(0);\n }\n return result;\n }\n\n update(i: number): void {\n const pos = this.getHeapIndex(i);\n if (pos >= 0 && pos < this.heap.length) {\n this.bubbleUp(pos);\n this.sinkDown(this.getHeapIndex(i));\n }\n }\n\n clear(): void { this.heap.length = 0; }\n\n private bubbleUp(pos: number): void {\n const idx = this.heap[pos];\n const f = this.getF(idx);\n while (pos > 0) {\n const pp = (pos - 1) >> 1;\n const pi = this.heap[pp];\n if (f >= this.getF(pi)) break;\n this.heap[pos] = pi;\n this.setHeapIndex(pi, pos);\n pos = pp;\n }\n this.heap[pos] = idx;\n this.setHeapIndex(idx, pos);\n }\n\n private sinkDown(pos: number): void {\n const len = this.heap.length;\n const idx = this.heap[pos];\n const f = this.getF(idx);\n const half = len >> 1;\n while (pos < half) {\n const left = (pos << 1) + 1;\n const right = left + 1;\n let smallest = pos, smallestF = f;\n const lf = this.getF(this.heap[left]);\n if (lf < smallestF) { smallest = left; smallestF = lf; }\n if (right < len) {\n const rf = this.getF(this.heap[right]);\n if (rf < smallestF) smallest = right;\n }\n if (smallest === pos) break;\n const si = this.heap[smallest];\n this.heap[pos] = si;\n this.setHeapIndex(si, pos);\n pos = smallest;\n }\n this.heap[pos] = idx;\n this.setHeapIndex(idx, pos);\n }\n}\n\n// =============================================================================\n// 网格寻路器 | Grid Pathfinder\n// =============================================================================\n\n/**\n * @zh 网格寻路器\n * @en Grid Pathfinder\n */\nexport class GridPathfinder implements IPathfinder {\n private readonly map: GridMap;\n private readonly mode: GridPathfinderMode;\n private readonly state: GridState;\n private readonly openList: GridHeap;\n private readonly openListBack: GridHeap | null;\n\n constructor(map: GridMap, config?: IGridPathfinderConfig) {\n this.map = map;\n this.mode = config?.mode ?? 'fast';\n const isBidir = this.mode === 'bidirectional';\n this.state = new GridState(map.width, map.height, isBidir);\n this.openList = new GridHeap(this.state, false);\n this.openListBack = isBidir ? new GridHeap(this.state, true) : null;\n }\n\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n if (this.mode === 'bidirectional') {\n return this.findPathBidirectional(startX, startY, endX, endY, options);\n }\n return this.findPathUnidirectional(startX, startY, endX, endY, options);\n }\n\n private findPathUnidirectional(\n startX: number, startY: number,\n endX: number, endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = options ? { ...DEFAULT_PATHFINDING_OPTIONS, ...options } : DEFAULT_PATHFINDING_OPTIONS;\n const { width, height } = this.map;\n\n this.state.reset();\n this.openList.clear();\n\n if (!this.validate(startX, startY, endX, endY)) return EMPTY_PATH_RESULT;\n\n const startIdx = startY * width + startX;\n const endIdx = endY * width + endX;\n\n if (startIdx === endIdx) {\n return { found: true, path: [{ x: startX, y: startY }], cost: 0, nodesSearched: 1 };\n }\n\n const hw = opts.heuristicWeight;\n const h0 = this.map.heuristic({ x: startX, y: startY }, { x: endX, y: endY }) * hw;\n this.state.setG(startIdx, 0);\n this.state.setF(startIdx, h0);\n this.state.setOpened(startIdx);\n this.openList.push(startIdx);\n\n let searched = 0;\n const maxNodes = opts.maxNodes;\n const { allowDiagonal, avoidCorners, diagonalCost } = this.map['options'];\n const nodes = this.map['nodes'];\n const dx = allowDiagonal ? [0, 1, 1, 1, 0, -1, -1, -1] : [0, 1, 0, -1];\n const dy = allowDiagonal ? [-1, -1, 0, 1, 1, 1, 0, -1] : [-1, 0, 1, 0];\n const dirCount = dx.length;\n\n while (!this.openList.isEmpty && searched < maxNodes) {\n const cur = this.openList.pop();\n this.state.setClosed(cur);\n searched++;\n\n if (cur === endIdx) {\n return this.buildPath(startIdx, endIdx, searched);\n }\n\n const cx = cur % width, cy = (cur / width) | 0;\n const curG = this.state.getG(cur);\n\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dx[d], ny = cy + dy[d];\n if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;\n\n const neighbor = nodes[ny][nx];\n if (!neighbor.walkable) continue;\n\n if (avoidCorners && dx[d] !== 0 && dy[d] !== 0) {\n if (!nodes[cy][cx + dx[d]].walkable || !nodes[cy + dy[d]][cx].walkable) continue;\n }\n\n const ni = ny * width + nx;\n if (this.state.isClosed(ni)) continue;\n\n const isDiag = dx[d] !== 0 && dy[d] !== 0;\n const cost = isDiag ? neighbor.cost * diagonalCost : neighbor.cost;\n const tentG = curG + cost;\n\n if (!this.state.isOpened(ni)) {\n const h = this.map.heuristic({ x: nx, y: ny }, { x: endX, y: endY }) * hw;\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.state.setOpened(ni);\n this.openList.push(ni);\n } else if (tentG < this.state.getG(ni)) {\n const h = this.state.getF(ni) - this.state.getG(ni);\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.openList.update(ni);\n }\n }\n }\n\n return { found: false, path: [], cost: 0, nodesSearched: searched };\n }\n\n private findPathBidirectional(\n startX: number, startY: number,\n endX: number, endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = options ? { ...DEFAULT_PATHFINDING_OPTIONS, ...options } : DEFAULT_PATHFINDING_OPTIONS;\n const { width, height } = this.map;\n\n this.state.reset();\n this.openList.clear();\n this.openListBack!.clear();\n\n if (!this.validate(startX, startY, endX, endY)) return EMPTY_PATH_RESULT;\n\n const startIdx = startY * width + startX;\n const endIdx = endY * width + endX;\n\n if (startIdx === endIdx) {\n return { found: true, path: [{ x: startX, y: startY }], cost: 0, nodesSearched: 1 };\n }\n\n const hw = opts.heuristicWeight;\n const startPos = { x: startX, y: startY };\n const endPos = { x: endX, y: endY };\n\n // Init forward\n const hf = this.map.heuristic(startPos, endPos) * hw;\n this.state.setG(startIdx, 0);\n this.state.setF(startIdx, hf);\n this.state.setOpened(startIdx);\n this.openList.push(startIdx);\n\n // Init backward\n const hb = this.map.heuristic(endPos, startPos) * hw;\n this.state.setGBack(endIdx, 0);\n this.state.setFBack(endIdx, hb);\n this.state.setOpenedBack(endIdx);\n this.openListBack!.push(endIdx);\n\n let searched = 0;\n const maxNodes = opts.maxNodes;\n let meetIdx = -1, bestCost = Infinity;\n\n const { allowDiagonal, avoidCorners, diagonalCost } = this.map['options'];\n const nodes = this.map['nodes'];\n const dx = allowDiagonal ? [0, 1, 1, 1, 0, -1, -1, -1] : [0, 1, 0, -1];\n const dy = allowDiagonal ? [-1, -1, 0, 1, 1, 1, 0, -1] : [-1, 0, 1, 0];\n const dirCount = dx.length;\n\n while ((!this.openList.isEmpty || !this.openListBack!.isEmpty) && searched < maxNodes) {\n // Forward\n if (!this.openList.isEmpty) {\n const cur = this.openList.pop();\n this.state.setClosed(cur);\n searched++;\n\n const curG = this.state.getG(cur);\n if (this.state.isClosedBack(cur)) {\n const total = curG + this.state.getGBack(cur);\n if (total < bestCost) { bestCost = total; meetIdx = cur; }\n }\n if (meetIdx !== -1 && curG >= bestCost) break;\n\n const cx = cur % width, cy = (cur / width) | 0;\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dx[d], ny = cy + dy[d];\n if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;\n const neighbor = nodes[ny][nx];\n if (!neighbor.walkable) continue;\n if (avoidCorners && dx[d] !== 0 && dy[d] !== 0) {\n if (!nodes[cy][cx + dx[d]].walkable || !nodes[cy + dy[d]][cx].walkable) continue;\n }\n const ni = ny * width + nx;\n if (this.state.isClosed(ni)) continue;\n const isDiag = dx[d] !== 0 && dy[d] !== 0;\n const cost = isDiag ? neighbor.cost * diagonalCost : neighbor.cost;\n const tentG = curG + cost;\n if (!this.state.isOpened(ni)) {\n const h = this.map.heuristic({ x: nx, y: ny }, endPos) * hw;\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.state.setOpened(ni);\n this.openList.push(ni);\n } else if (tentG < this.state.getG(ni)) {\n const h = this.state.getF(ni) - this.state.getG(ni);\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.openList.update(ni);\n }\n }\n }\n\n // Backward\n if (!this.openListBack!.isEmpty) {\n const cur = this.openListBack!.pop();\n this.state.setClosedBack(cur);\n searched++;\n\n const curG = this.state.getGBack(cur);\n if (this.state.isClosed(cur)) {\n const total = curG + this.state.getG(cur);\n if (total < bestCost) { bestCost = total; meetIdx = cur; }\n }\n if (meetIdx !== -1 && curG >= bestCost) break;\n\n const cx = cur % width, cy = (cur / width) | 0;\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dx[d], ny = cy + dy[d];\n if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;\n const neighbor = nodes[ny][nx];\n if (!neighbor.walkable) continue;\n if (avoidCorners && dx[d] !== 0 && dy[d] !== 0) {\n if (!nodes[cy][cx + dx[d]].walkable || !nodes[cy + dy[d]][cx].walkable) continue;\n }\n const ni = ny * width + nx;\n if (this.state.isClosedBack(ni)) continue;\n const isDiag = dx[d] !== 0 && dy[d] !== 0;\n const cost = isDiag ? neighbor.cost * diagonalCost : neighbor.cost;\n const tentG = curG + cost;\n if (!this.state.isOpenedBack(ni)) {\n const h = this.map.heuristic({ x: nx, y: ny }, startPos) * hw;\n this.state.setGBack(ni, tentG);\n this.state.setFBack(ni, tentG + h);\n this.state.setParentBack(ni, cur);\n this.state.setOpenedBack(ni);\n this.openListBack!.push(ni);\n } else if (tentG < this.state.getGBack(ni)) {\n const h = this.state.getFBack(ni) - this.state.getGBack(ni);\n this.state.setGBack(ni, tentG);\n this.state.setFBack(ni, tentG + h);\n this.state.setParentBack(ni, cur);\n this.openListBack!.update(ni);\n }\n }\n }\n }\n\n if (meetIdx === -1) {\n return { found: false, path: [], cost: 0, nodesSearched: searched };\n }\n\n return this.buildPathBidirectional(startIdx, endIdx, meetIdx, searched);\n }\n\n private validate(startX: number, startY: number, endX: number, endY: number): boolean {\n const { width, height } = this.map;\n if (startX < 0 || startX >= width || startY < 0 || startY >= height) return false;\n if (endX < 0 || endX >= width || endY < 0 || endY >= height) return false;\n return this.map.isWalkable(startX, startY) && this.map.isWalkable(endX, endY);\n }\n\n private buildPath(startIdx: number, endIdx: number, searched: number): IPathResult {\n const w = this.state.width;\n const path: IPoint[] = [];\n let cur = endIdx;\n while (cur !== -1) {\n path.push({ x: cur % w, y: (cur / w) | 0 });\n cur = cur === startIdx ? -1 : this.state.getParent(cur);\n }\n path.reverse();\n return { found: true, path, cost: this.state.getG(endIdx), nodesSearched: searched };\n }\n\n private buildPathBidirectional(startIdx: number, endIdx: number, meetIdx: number, searched: number): IPathResult {\n const w = this.state.width;\n const path: IPoint[] = [];\n\n // Forward path\n let cur = meetIdx;\n while (cur !== -1 && cur !== startIdx) {\n path.push({ x: cur % w, y: (cur / w) | 0 });\n cur = this.state.getParent(cur);\n }\n path.push({ x: startIdx % w, y: (startIdx / w) | 0 });\n path.reverse();\n\n // Backward path\n cur = this.state.getParentBack(meetIdx);\n while (cur !== -1 && cur !== endIdx) {\n path.push({ x: cur % w, y: (cur / w) | 0 });\n cur = this.state.getParentBack(cur);\n }\n if (meetIdx !== endIdx) {\n path.push({ x: endIdx % w, y: (endIdx / w) | 0 });\n }\n\n const cost = this.state.getG(meetIdx) + this.state.getGBack(meetIdx);\n return { found: true, path, cost, nodesSearched: searched };\n }\n\n clear(): void {\n this.state.reset();\n this.openList.clear();\n this.openListBack?.clear();\n }\n}\n\n/**\n * @zh 创建网格寻路器\n * @en Create grid pathfinder\n */\nexport function createGridPathfinder(map: GridMap, config?: IGridPathfinderConfig): GridPathfinder {\n return new GridPathfinder(map, config);\n}\n","/**\n * @zh JPS (Jump Point Search) 寻路算法实现\n * @en JPS (Jump Point Search) Pathfinding Algorithm Implementation\n *\n * @zh JPS 是 A* 的优化版本,通过跳跃点剪枝大幅提升开放地形的搜索效率\n * @en JPS is an optimized version of A* that significantly improves search efficiency on open terrain through jump point pruning\n */\n\nimport { BinaryHeap } from './BinaryHeap';\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n IPathResult,\n IPathfinder,\n IPathfindingOptions\n} from './IPathfinding';\nimport { DEFAULT_PATHFINDING_OPTIONS, EMPTY_PATH_RESULT } from './IPathfinding';\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\n/**\n * @zh JPS 节点\n * @en JPS Node\n */\ninterface JPSNode {\n x: number;\n y: number;\n g: number;\n h: number;\n f: number;\n parent: JPSNode | null;\n closed: boolean;\n}\n\n// =============================================================================\n// JPS 寻路器 | JPS Pathfinder\n// =============================================================================\n\n/**\n * @zh JPS 寻路器\n * @en JPS Pathfinder\n *\n * @zh 适用于均匀代价网格地图,在开放地形上比标准 A* 快 10-100 倍\n * @en Suitable for uniform cost grid maps, 10-100x faster than standard A* on open terrain\n *\n * @example\n * ```typescript\n * const map = createGridMap(100, 100);\n * const pathfinder = new JPSPathfinder(map);\n * const result = pathfinder.findPath(0, 0, 99, 99);\n * ```\n */\nexport class JPSPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private readonly width: number;\n private readonly height: number;\n\n private openList: BinaryHeap<JPSNode>;\n private nodeGrid: (JPSNode | null)[][];\n\n constructor(map: IPathfindingMap) {\n this.map = map;\n\n // 获取地图尺寸\n const bounds = this.getMapBounds();\n this.width = bounds.width;\n this.height = bounds.height;\n\n this.openList = new BinaryHeap<JPSNode>((a, b) => a.f - b.f);\n this.nodeGrid = [];\n }\n\n /**\n * @zh 寻找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: Partial<IPathfindingOptions>\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n // 验证起点和终点\n if (!this.map.isWalkable(startX, startY) || !this.map.isWalkable(endX, endY)) {\n return EMPTY_PATH_RESULT;\n }\n\n // 相同位置\n if (startX === endX && startY === endY) {\n return {\n found: true,\n path: [{ x: startX, y: startY }],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n // 初始化\n this.initGrid();\n this.openList.clear();\n\n const startNode = this.getOrCreateNode(startX, startY);\n startNode.g = 0;\n startNode.h = this.heuristic(startX, startY, endX, endY) * opts.heuristicWeight;\n startNode.f = startNode.h;\n this.openList.push(startNode);\n\n let nodesSearched = 0;\n\n while (!this.openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = this.openList.pop()!;\n current.closed = true;\n nodesSearched++;\n\n // 到达终点\n if (current.x === endX && current.y === endY) {\n return {\n found: true,\n path: this.buildPath(current),\n cost: current.g,\n nodesSearched\n };\n }\n\n // 查找跳跃点\n this.identifySuccessors(current, endX, endY, opts);\n }\n\n return {\n found: false,\n path: [],\n cost: 0,\n nodesSearched\n };\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.openList.clear();\n this.nodeGrid = [];\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n /**\n * @zh 获取地图边界\n * @en Get map bounds\n */\n private getMapBounds(): { width: number; height: number } {\n // 尝试从地图获取尺寸\n const mapAny = this.map as any;\n if (typeof mapAny.width === 'number' && typeof mapAny.height === 'number') {\n return { width: mapAny.width, height: mapAny.height };\n }\n // 默认尺寸\n return { width: 1000, height: 1000 };\n }\n\n /**\n * @zh 初始化节点网格\n * @en Initialize node grid\n */\n private initGrid(): void {\n this.nodeGrid = [];\n for (let i = 0; i < this.width; i++) {\n this.nodeGrid[i] = [];\n }\n }\n\n /**\n * @zh 获取或创建节点\n * @en Get or create node\n */\n private getOrCreateNode(x: number, y: number): JPSNode {\n // Bounds check to ensure valid array indices\n const xi = x | 0;\n const yi = y | 0;\n if (xi < 0 || xi >= this.width || yi < 0 || yi >= this.height) {\n throw new Error('[JPSPathfinder] Invalid grid coordinates');\n }\n if (!this.nodeGrid[xi]) {\n this.nodeGrid[xi] = [];\n }\n if (!this.nodeGrid[xi][yi]) {\n this.nodeGrid[xi][yi] = {\n x: xi,\n y: yi,\n g: Infinity,\n h: 0,\n f: Infinity,\n parent: null,\n closed: false\n };\n }\n return this.nodeGrid[xi][yi]!;\n }\n\n /**\n * @zh 启发式函数(八方向距离)\n * @en Heuristic function (octile distance)\n */\n private heuristic(x1: number, y1: number, x2: number, y2: number): number {\n const dx = Math.abs(x1 - x2);\n const dy = Math.abs(y1 - y2);\n return dx + dy + (Math.SQRT2 - 2) * Math.min(dx, dy);\n }\n\n /**\n * @zh 识别后继节点(跳跃点)\n * @en Identify successors (jump points)\n */\n private identifySuccessors(\n node: JPSNode,\n endX: number,\n endY: number,\n opts: Required<IPathfindingOptions>\n ): void {\n const neighbors = this.findNeighbors(node);\n\n for (const neighbor of neighbors) {\n const jumpPoint = this.jump(\n neighbor.x,\n neighbor.y,\n node.x,\n node.y,\n endX,\n endY\n );\n\n if (jumpPoint) {\n const jx = jumpPoint.x;\n const jy = jumpPoint.y;\n\n const jpNode = this.getOrCreateNode(jx, jy);\n if (jpNode.closed) continue;\n\n const dx = Math.abs(jx - node.x);\n const dy = Math.abs(jy - node.y);\n const distance = Math.sqrt(dx * dx + dy * dy);\n const tentativeG = node.g + distance;\n\n if (tentativeG < jpNode.g) {\n jpNode.g = tentativeG;\n jpNode.h = this.heuristic(jx, jy, endX, endY) * opts.heuristicWeight;\n jpNode.f = jpNode.g + jpNode.h;\n jpNode.parent = node;\n\n if (!this.openList.contains(jpNode)) {\n this.openList.push(jpNode);\n } else {\n this.openList.update(jpNode);\n }\n }\n }\n }\n }\n\n /**\n * @zh 查找邻居(根据父节点方向剪枝)\n * @en Find neighbors (pruned based on parent direction)\n */\n private findNeighbors(node: JPSNode): IPoint[] {\n const { x, y, parent } = node;\n const neighbors: IPoint[] = [];\n\n // 无父节点,返回所有可通行邻居\n if (!parent) {\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue;\n const nx = x + dx;\n const ny = y + dy;\n if (this.isWalkableAt(nx, ny)) {\n // 对角线移动检查\n if (dx !== 0 && dy !== 0) {\n if (this.isWalkableAt(x + dx, y) || this.isWalkableAt(x, y + dy)) {\n neighbors.push({ x: nx, y: ny });\n }\n } else {\n neighbors.push({ x: nx, y: ny });\n }\n }\n }\n }\n return neighbors;\n }\n\n // 有父节点,根据方向剪枝\n const dx = Math.sign(x - parent.x);\n const dy = Math.sign(y - parent.y);\n\n // 对角线移动\n if (dx !== 0 && dy !== 0) {\n // 自然邻居\n if (this.isWalkableAt(x, y + dy)) {\n neighbors.push({ x, y: y + dy });\n }\n if (this.isWalkableAt(x + dx, y)) {\n neighbors.push({ x: x + dx, y });\n }\n if (this.isWalkableAt(x, y + dy) || this.isWalkableAt(x + dx, y)) {\n if (this.isWalkableAt(x + dx, y + dy)) {\n neighbors.push({ x: x + dx, y: y + dy });\n }\n }\n\n // 强制邻居\n if (!this.isWalkableAt(x - dx, y) && this.isWalkableAt(x, y + dy)) {\n if (this.isWalkableAt(x - dx, y + dy)) {\n neighbors.push({ x: x - dx, y: y + dy });\n }\n }\n if (!this.isWalkableAt(x, y - dy) && this.isWalkableAt(x + dx, y)) {\n if (this.isWalkableAt(x + dx, y - dy)) {\n neighbors.push({ x: x + dx, y: y - dy });\n }\n }\n }\n // 水平移动\n else if (dx !== 0) {\n if (this.isWalkableAt(x + dx, y)) {\n neighbors.push({ x: x + dx, y });\n\n // 强制邻居\n if (!this.isWalkableAt(x, y + 1) && this.isWalkableAt(x + dx, y + 1)) {\n neighbors.push({ x: x + dx, y: y + 1 });\n }\n if (!this.isWalkableAt(x, y - 1) && this.isWalkableAt(x + dx, y - 1)) {\n neighbors.push({ x: x + dx, y: y - 1 });\n }\n }\n }\n // 垂直移动\n else if (dy !== 0) {\n if (this.isWalkableAt(x, y + dy)) {\n neighbors.push({ x, y: y + dy });\n\n // 强制邻居\n if (!this.isWalkableAt(x + 1, y) && this.isWalkableAt(x + 1, y + dy)) {\n neighbors.push({ x: x + 1, y: y + dy });\n }\n if (!this.isWalkableAt(x - 1, y) && this.isWalkableAt(x - 1, y + dy)) {\n neighbors.push({ x: x - 1, y: y + dy });\n }\n }\n }\n\n return neighbors;\n }\n\n /**\n * @zh 跳跃函数(迭代版本,避免递归开销)\n * @en Jump function (iterative version to avoid recursion overhead)\n */\n private jump(\n startX: number,\n startY: number,\n px: number,\n py: number,\n endX: number,\n endY: number\n ): IPoint | null {\n const dx = startX - px;\n const dy = startY - py;\n\n let x = startX;\n let y = startY;\n\n while (true) {\n if (!this.isWalkableAt(x, y)) {\n return null;\n }\n\n if (x === endX && y === endY) {\n return { x, y };\n }\n\n if (dx !== 0 && dy !== 0) {\n if ((this.isWalkableAt(x - dx, y + dy) && !this.isWalkableAt(x - dx, y)) ||\n (this.isWalkableAt(x + dx, y - dy) && !this.isWalkableAt(x, y - dy))) {\n return { x, y };\n }\n\n if (this.jumpStraight(x + dx, y, dx, 0, endX, endY) ||\n this.jumpStraight(x, y + dy, 0, dy, endX, endY)) {\n return { x, y };\n }\n\n if (!this.isWalkableAt(x + dx, y) && !this.isWalkableAt(x, y + dy)) {\n return null;\n }\n } else if (dx !== 0) {\n if ((this.isWalkableAt(x + dx, y + 1) && !this.isWalkableAt(x, y + 1)) ||\n (this.isWalkableAt(x + dx, y - 1) && !this.isWalkableAt(x, y - 1))) {\n return { x, y };\n }\n } else if (dy !== 0) {\n if ((this.isWalkableAt(x + 1, y + dy) && !this.isWalkableAt(x + 1, y)) ||\n (this.isWalkableAt(x - 1, y + dy) && !this.isWalkableAt(x - 1, y))) {\n return { x, y };\n }\n }\n\n x += dx;\n y += dy;\n }\n }\n\n /**\n * @zh 直线跳跃(水平或垂直方向)\n * @en Straight jump (horizontal or vertical direction)\n */\n private jumpStraight(\n startX: number,\n startY: number,\n dx: number,\n dy: number,\n endX: number,\n endY: number\n ): boolean {\n let x = startX;\n let y = startY;\n\n while (true) {\n if (!this.isWalkableAt(x, y)) {\n return false;\n }\n\n if (x === endX && y === endY) {\n return true;\n }\n\n if (dx !== 0) {\n if ((this.isWalkableAt(x + dx, y + 1) && !this.isWalkableAt(x, y + 1)) ||\n (this.isWalkableAt(x + dx, y - 1) && !this.isWalkableAt(x, y - 1))) {\n return true;\n }\n } else if (dy !== 0) {\n if ((this.isWalkableAt(x + 1, y + dy) && !this.isWalkableAt(x + 1, y)) ||\n (this.isWalkableAt(x - 1, y + dy) && !this.isWalkableAt(x - 1, y))) {\n return true;\n }\n }\n\n x += dx;\n y += dy;\n }\n }\n\n /**\n * @zh 检查位置是否可通行\n * @en Check if position is walkable\n */\n private isWalkableAt(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return this.map.isWalkable(x, y);\n }\n\n /**\n * @zh 构建路径\n * @en Build path\n */\n private buildPath(endNode: JPSNode): IPoint[] {\n const path: IPoint[] = [];\n let current: JPSNode | null = endNode;\n\n while (current) {\n path.unshift({ x: current.x, y: current.y });\n current = current.parent;\n }\n\n // 插值跳跃点之间的路径\n return this.interpolatePath(path);\n }\n\n /**\n * @zh 插值路径(在跳跃点之间填充中间点)\n * @en Interpolate path (fill intermediate points between jump points)\n */\n private interpolatePath(jumpPoints: IPoint[]): IPoint[] {\n if (jumpPoints.length < 2) {\n return jumpPoints;\n }\n\n const path: IPoint[] = [jumpPoints[0]];\n\n for (let i = 1; i < jumpPoints.length; i++) {\n const prev = jumpPoints[i - 1];\n const curr = jumpPoints[i];\n\n const dx = curr.x - prev.x;\n const dy = curr.y - prev.y;\n const steps = Math.max(Math.abs(dx), Math.abs(dy));\n\n const stepX = dx === 0 ? 0 : dx / Math.abs(dx);\n const stepY = dy === 0 ? 0 : dy / Math.abs(dy);\n\n let x = prev.x;\n let y = prev.y;\n\n for (let j = 0; j < steps; j++) {\n // 优先对角移动\n if (x !== curr.x && y !== curr.y) {\n x += stepX;\n y += stepY;\n } else if (x !== curr.x) {\n x += stepX;\n } else if (y !== curr.y) {\n y += stepY;\n }\n\n if (x !== prev.x || y !== prev.y) {\n path.push({ x, y });\n }\n }\n }\n\n return path;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 JPS 寻路器\n * @en Create JPS pathfinder\n *\n * @param map - @zh 寻路地图实例 @en Pathfinding map instance\n * @returns @zh JPS 寻路器实例 @en JPS pathfinder instance\n */\nexport function createJPSPathfinder(map: IPathfindingMap): JPSPathfinder {\n return new JPSPathfinder(map);\n}\n","/**\n * @zh HPA* (Hierarchical Pathfinding A*) 寻路算法实现\n * @en HPA* (Hierarchical Pathfinding A*) Pathfinding Algorithm Implementation\n *\n * @zh HPA* 是一种分层寻路算法,适用于超大地图 (1000x1000+)\n * @en HPA* is a hierarchical pathfinding algorithm suitable for very large maps (1000x1000+)\n *\n * @zh 工作原理:\n * 1. 将地图划分为集群 (clusters)\n * 2. 在集群边界检测入口点 (entrances)\n * 3. 构建抽象图 (abstract graph) 连接入口点\n * 4. 先在抽象图上寻路,再细化为详细路径\n *\n * @en How it works:\n * 1. Divide map into clusters\n * 2. Detect entrances at cluster boundaries\n * 3. Build abstract graph connecting entrances\n * 4. First find path on abstract graph, then refine to detailed path\n */\n\nimport { BinaryHeap } from './BinaryHeap';\nimport type {\n IPathfindingMap,\n IPoint,\n IPathResult,\n IPathfinder,\n IPathfindingOptions\n} from './IPathfinding';\nimport { DEFAULT_PATHFINDING_OPTIONS, EMPTY_PATH_RESULT } from './IPathfinding';\nimport { AStarPathfinder } from './AStarPathfinder';\n\n// =============================================================================\n// 配置 | Configuration\n// =============================================================================\n\n/**\n * @zh HPA* 配置\n * @en HPA* Configuration\n */\nexport interface IHPAConfig {\n /**\n * @zh 集群大小(边长)\n * @en Cluster size (side length)\n */\n clusterSize: number;\n\n /**\n * @zh 最大入口宽度(超过此宽度会拆分为多个入口)\n * @en Maximum entrance width (entrances wider than this will be split)\n */\n maxEntranceWidth: number;\n\n /**\n * @zh 是否启用内部路径缓存\n * @en Whether to enable internal path caching\n */\n cacheInternalPaths: boolean;\n}\n\n/**\n * @zh 默认 HPA* 配置\n * @en Default HPA* configuration\n */\nexport const DEFAULT_HPA_CONFIG: IHPAConfig = {\n clusterSize: 10,\n maxEntranceWidth: 6,\n cacheInternalPaths: true\n};\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\n/**\n * @zh 集群\n * @en Cluster\n */\ninterface Cluster {\n id: number;\n x: number;\n y: number;\n width: number;\n height: number;\n entrances: Entrance[];\n}\n\n/**\n * @zh 入口(集群之间的连接点)\n * @en Entrance (connection point between clusters)\n */\ninterface Entrance {\n id: number;\n cluster1Id: number;\n cluster2Id: number;\n point1: IPoint;\n point2: IPoint;\n center: IPoint;\n}\n\n/**\n * @zh 抽象节点\n * @en Abstract node\n */\ninterface AbstractNode {\n id: number;\n position: IPoint;\n clusterId: number;\n entranceId: number;\n edges: AbstractEdge[];\n}\n\n/**\n * @zh 抽象边\n * @en Abstract edge\n */\ninterface AbstractEdge {\n targetNodeId: number;\n cost: number;\n isInterEdge: boolean;\n}\n\n/**\n * @zh A* 搜索节点\n * @en A* search node\n */\ninterface SearchNode {\n abstractNode: AbstractNode;\n g: number;\n h: number;\n f: number;\n parent: SearchNode | null;\n}\n\n// =============================================================================\n// HPA* 寻路器 | HPA* Pathfinder\n// =============================================================================\n\n/**\n * @zh HPA* 寻路器\n * @en HPA* Pathfinder\n *\n * @zh 适用于超大地图的分层寻路算法\n * @en Hierarchical pathfinding algorithm for very large maps\n *\n * @example\n * ```typescript\n * const map = createGridMap(1000, 1000);\n * const pathfinder = new HPAPathfinder(map, { clusterSize: 20 });\n *\n * // Preprocess (do once after map changes)\n * pathfinder.preprocess();\n *\n * // Find path\n * const result = pathfinder.findPath(0, 0, 999, 999);\n * ```\n */\nexport class HPAPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private readonly config: IHPAConfig;\n private readonly width: number;\n private readonly height: number;\n\n private clusters: Cluster[] = [];\n private entrances: Entrance[] = [];\n private abstractNodes: Map<number, AbstractNode> = new Map();\n private clusterGrid: (Cluster | null)[][] = [];\n\n private nextEntranceId: number = 0;\n private nextNodeId: number = 0;\n\n private internalPathCache: Map<string, IPoint[]> = new Map();\n private localPathfinder: AStarPathfinder;\n\n private preprocessed: boolean = false;\n\n constructor(map: IPathfindingMap, config?: Partial<IHPAConfig>) {\n this.map = map;\n this.config = { ...DEFAULT_HPA_CONFIG, ...config };\n\n const bounds = this.getMapBounds();\n this.width = bounds.width;\n this.height = bounds.height;\n\n this.localPathfinder = new AStarPathfinder(map);\n }\n\n /**\n * @zh 预处理地图(构建抽象图)\n * @en Preprocess map (build abstract graph)\n *\n * @zh 在地图变化后需要重新调用\n * @en Need to call again after map changes\n */\n preprocess(): void {\n this.clusters = [];\n this.entrances = [];\n this.abstractNodes.clear();\n this.clusterGrid = [];\n this.internalPathCache.clear();\n this.nextEntranceId = 0;\n this.nextNodeId = 0;\n\n this.buildClusters();\n this.findEntrances();\n this.buildAbstractGraph();\n\n this.preprocessed = true;\n }\n\n /**\n * @zh 寻找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: Partial<IPathfindingOptions>\n ): IPathResult {\n if (!this.preprocessed) {\n this.preprocess();\n }\n\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n if (!this.map.isWalkable(startX, startY) || !this.map.isWalkable(endX, endY)) {\n return EMPTY_PATH_RESULT;\n }\n\n if (startX === endX && startY === endY) {\n return {\n found: true,\n path: [{ x: startX, y: startY }],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n const startCluster = this.getClusterAt(startX, startY);\n const endCluster = this.getClusterAt(endX, endY);\n\n if (!startCluster || !endCluster) {\n return EMPTY_PATH_RESULT;\n }\n\n if (startCluster.id === endCluster.id) {\n return this.findLocalPath(startX, startY, endX, endY, opts);\n }\n\n const startNodes = this.insertTemporaryNode(startX, startY, startCluster);\n const endNodes = this.insertTemporaryNode(endX, endY, endCluster);\n\n const abstractPath = this.searchAbstractGraph(startNodes, endNodes, opts);\n\n this.removeTemporaryNodes(startNodes);\n this.removeTemporaryNodes(endNodes);\n\n if (!abstractPath || abstractPath.length === 0) {\n return EMPTY_PATH_RESULT;\n }\n\n return this.refinePath(abstractPath, startX, startY, endX, endY, opts);\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.clusters = [];\n this.entrances = [];\n this.abstractNodes.clear();\n this.clusterGrid = [];\n this.internalPathCache.clear();\n this.preprocessed = false;\n }\n\n /**\n * @zh 通知地图区域变化\n * @en Notify map region change\n */\n notifyRegionChange(minX: number, minY: number, maxX: number, maxY: number): void {\n this.preprocessed = false;\n this.internalPathCache.clear();\n }\n\n /**\n * @zh 获取预处理统计信息\n * @en Get preprocessing statistics\n */\n getStats(): {\n clusters: number;\n entrances: number;\n abstractNodes: number;\n cacheSize: number;\n } {\n return {\n clusters: this.clusters.length,\n entrances: this.entrances.length,\n abstractNodes: this.abstractNodes.size,\n cacheSize: this.internalPathCache.size\n };\n }\n\n // =========================================================================\n // 预处理方法 | Preprocessing Methods\n // =========================================================================\n\n private getMapBounds(): { width: number; height: number } {\n const mapAny = this.map as any;\n if (typeof mapAny.width === 'number' && typeof mapAny.height === 'number') {\n return { width: mapAny.width, height: mapAny.height };\n }\n return { width: 1000, height: 1000 };\n }\n\n private buildClusters(): void {\n const clusterSize = this.config.clusterSize;\n const clustersX = Math.ceil(this.width / clusterSize);\n const clustersY = Math.ceil(this.height / clusterSize);\n\n this.clusterGrid = [];\n for (let x = 0; x < clustersX; x++) {\n this.clusterGrid[x] = [];\n }\n\n let clusterId = 0;\n for (let cy = 0; cy < clustersY; cy++) {\n for (let cx = 0; cx < clustersX; cx++) {\n const cluster: Cluster = {\n id: clusterId++,\n x: cx * clusterSize,\n y: cy * clusterSize,\n width: Math.min(clusterSize, this.width - cx * clusterSize),\n height: Math.min(clusterSize, this.height - cy * clusterSize),\n entrances: []\n };\n this.clusters.push(cluster);\n this.clusterGrid[cx][cy] = cluster;\n }\n }\n }\n\n private findEntrances(): void {\n const clusterSize = this.config.clusterSize;\n const clustersX = Math.ceil(this.width / clusterSize);\n const clustersY = Math.ceil(this.height / clusterSize);\n\n for (let cy = 0; cy < clustersY; cy++) {\n for (let cx = 0; cx < clustersX; cx++) {\n const cluster = this.clusterGrid[cx][cy];\n if (!cluster) continue;\n\n if (cx < clustersX - 1) {\n const rightCluster = this.clusterGrid[cx + 1]?.[cy];\n if (rightCluster) {\n this.findEntrancesBetween(cluster, rightCluster, 'horizontal');\n }\n }\n\n if (cy < clustersY - 1) {\n const bottomCluster = this.clusterGrid[cx]?.[cy + 1];\n if (bottomCluster) {\n this.findEntrancesBetween(cluster, bottomCluster, 'vertical');\n }\n }\n }\n }\n }\n\n private findEntrancesBetween(\n cluster1: Cluster,\n cluster2: Cluster,\n direction: 'horizontal' | 'vertical'\n ): void {\n const maxWidth = this.config.maxEntranceWidth;\n let entranceStart: number | null = null;\n let entranceLength = 0;\n\n if (direction === 'horizontal') {\n const x1 = cluster1.x + cluster1.width - 1;\n const x2 = cluster2.x;\n const startY = Math.max(cluster1.y, cluster2.y);\n const endY = Math.min(cluster1.y + cluster1.height, cluster2.y + cluster2.height);\n\n for (let y = startY; y < endY; y++) {\n const walkable1 = this.map.isWalkable(x1, y);\n const walkable2 = this.map.isWalkable(x2, y);\n\n if (walkable1 && walkable2) {\n if (entranceStart === null) {\n entranceStart = y;\n entranceLength = 1;\n } else {\n entranceLength++;\n }\n\n if (entranceLength >= maxWidth || y === endY - 1) {\n this.createEntrance(cluster1, cluster2, x1, x2, entranceStart, entranceStart + entranceLength - 1, 'horizontal');\n entranceStart = null;\n entranceLength = 0;\n }\n } else if (entranceStart !== null) {\n this.createEntrance(cluster1, cluster2, x1, x2, entranceStart, entranceStart + entranceLength - 1, 'horizontal');\n entranceStart = null;\n entranceLength = 0;\n }\n }\n } else {\n const y1 = cluster1.y + cluster1.height - 1;\n const y2 = cluster2.y;\n const startX = Math.max(cluster1.x, cluster2.x);\n const endX = Math.min(cluster1.x + cluster1.width, cluster2.x + cluster2.width);\n\n for (let x = startX; x < endX; x++) {\n const walkable1 = this.map.isWalkable(x, y1);\n const walkable2 = this.map.isWalkable(x, y2);\n\n if (walkable1 && walkable2) {\n if (entranceStart === null) {\n entranceStart = x;\n entranceLength = 1;\n } else {\n entranceLength++;\n }\n\n if (entranceLength >= maxWidth || x === endX - 1) {\n this.createEntrance(cluster1, cluster2, entranceStart, entranceStart + entranceLength - 1, y1, y2, 'vertical');\n entranceStart = null;\n entranceLength = 0;\n }\n } else if (entranceStart !== null) {\n this.createEntrance(cluster1, cluster2, entranceStart, entranceStart + entranceLength - 1, y1, y2, 'vertical');\n entranceStart = null;\n entranceLength = 0;\n }\n }\n }\n }\n\n private createEntrance(\n cluster1: Cluster,\n cluster2: Cluster,\n coord1Start: number,\n coord1End: number,\n coord2Start: number,\n coord2End: number,\n direction: 'horizontal' | 'vertical'\n ): void {\n let point1: IPoint;\n let point2: IPoint;\n let center: IPoint;\n\n if (direction === 'horizontal') {\n const midY = Math.floor((coord1Start + coord1End) / 2);\n point1 = { x: coord1Start, y: midY };\n point2 = { x: coord2Start, y: midY };\n center = { x: coord1Start, y: midY };\n } else {\n const midX = Math.floor((coord1Start + coord1End) / 2);\n point1 = { x: midX, y: coord2Start };\n point2 = { x: midX, y: coord2End };\n center = { x: midX, y: coord2Start };\n }\n\n const entrance: Entrance = {\n id: this.nextEntranceId++,\n cluster1Id: cluster1.id,\n cluster2Id: cluster2.id,\n point1,\n point2,\n center\n };\n\n this.entrances.push(entrance);\n cluster1.entrances.push(entrance);\n cluster2.entrances.push(entrance);\n }\n\n private buildAbstractGraph(): void {\n for (const entrance of this.entrances) {\n const node1 = this.createAbstractNode(entrance.point1, entrance.cluster1Id, entrance.id);\n const node2 = this.createAbstractNode(entrance.point2, entrance.cluster2Id, entrance.id);\n\n node1.edges.push({ targetNodeId: node2.id, cost: 1, isInterEdge: true });\n node2.edges.push({ targetNodeId: node1.id, cost: 1, isInterEdge: true });\n }\n\n for (const cluster of this.clusters) {\n this.connectIntraClusterNodes(cluster);\n }\n }\n\n private createAbstractNode(position: IPoint, clusterId: number, entranceId: number): AbstractNode {\n const node: AbstractNode = {\n id: this.nextNodeId++,\n position,\n clusterId,\n entranceId,\n edges: []\n };\n this.abstractNodes.set(node.id, node);\n return node;\n }\n\n private connectIntraClusterNodes(cluster: Cluster): void {\n const nodesInCluster: AbstractNode[] = [];\n\n for (const node of this.abstractNodes.values()) {\n if (node.clusterId === cluster.id) {\n nodesInCluster.push(node);\n }\n }\n\n for (let i = 0; i < nodesInCluster.length; i++) {\n for (let j = i + 1; j < nodesInCluster.length; j++) {\n const node1 = nodesInCluster[i];\n const node2 = nodesInCluster[j];\n\n const cost = this.heuristic(node1.position, node2.position);\n node1.edges.push({ targetNodeId: node2.id, cost, isInterEdge: false });\n node2.edges.push({ targetNodeId: node1.id, cost, isInterEdge: false });\n }\n }\n }\n\n // =========================================================================\n // 搜索方法 | Search Methods\n // =========================================================================\n\n private getClusterAt(x: number, y: number): Cluster | null {\n const clusterSize = this.config.clusterSize;\n const cx = Math.floor(x / clusterSize);\n const cy = Math.floor(y / clusterSize);\n return this.clusterGrid[cx]?.[cy] ?? null;\n }\n\n private insertTemporaryNode(\n x: number,\n y: number,\n cluster: Cluster\n ): AbstractNode[] {\n const tempNodes: AbstractNode[] = [];\n const tempNode = this.createAbstractNode({ x, y }, cluster.id, -1);\n tempNodes.push(tempNode);\n\n for (const node of this.abstractNodes.values()) {\n if (node.clusterId === cluster.id && node.id !== tempNode.id) {\n const cost = this.heuristic({ x, y }, node.position);\n tempNode.edges.push({ targetNodeId: node.id, cost, isInterEdge: false });\n node.edges.push({ targetNodeId: tempNode.id, cost, isInterEdge: false });\n }\n }\n\n return tempNodes;\n }\n\n private removeTemporaryNodes(nodes: AbstractNode[]): void {\n for (const node of nodes) {\n for (const edge of node.edges) {\n const targetNode = this.abstractNodes.get(edge.targetNodeId);\n if (targetNode) {\n targetNode.edges = targetNode.edges.filter(e => e.targetNodeId !== node.id);\n }\n }\n this.abstractNodes.delete(node.id);\n }\n }\n\n private searchAbstractGraph(\n startNodes: AbstractNode[],\n endNodes: AbstractNode[],\n opts: Required<IPathfindingOptions>\n ): AbstractNode[] | null {\n if (startNodes.length === 0 || endNodes.length === 0) {\n return null;\n }\n\n const endNodeIds = new Set(endNodes.map(n => n.id));\n const openList = new BinaryHeap<SearchNode>((a, b) => a.f - b.f);\n const closedSet = new Set<number>();\n\n for (const startNode of startNodes) {\n const h = this.heuristic(startNode.position, endNodes[0].position);\n openList.push({\n abstractNode: startNode,\n g: 0,\n h: h * opts.heuristicWeight,\n f: h * opts.heuristicWeight,\n parent: null\n });\n }\n\n let nodesSearched = 0;\n\n while (!openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = openList.pop()!;\n nodesSearched++;\n\n if (endNodeIds.has(current.abstractNode.id)) {\n return this.reconstructAbstractPath(current);\n }\n\n if (closedSet.has(current.abstractNode.id)) {\n continue;\n }\n closedSet.add(current.abstractNode.id);\n\n for (const edge of current.abstractNode.edges) {\n if (closedSet.has(edge.targetNodeId)) {\n continue;\n }\n\n const neighbor = this.abstractNodes.get(edge.targetNodeId);\n if (!neighbor) continue;\n\n const tentativeG = current.g + edge.cost;\n const h = this.heuristic(neighbor.position, endNodes[0].position) * opts.heuristicWeight;\n\n openList.push({\n abstractNode: neighbor,\n g: tentativeG,\n h,\n f: tentativeG + h,\n parent: current\n });\n }\n }\n\n return null;\n }\n\n private reconstructAbstractPath(endNode: SearchNode): AbstractNode[] {\n const path: AbstractNode[] = [];\n let current: SearchNode | null = endNode;\n\n while (current) {\n path.unshift(current.abstractNode);\n current = current.parent;\n }\n\n return path;\n }\n\n private refinePath(\n abstractPath: AbstractNode[],\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n opts: Required<IPathfindingOptions>\n ): IPathResult {\n const fullPath: IPoint[] = [];\n let totalCost = 0;\n let nodesSearched = abstractPath.length;\n\n let currentX = startX;\n let currentY = startY;\n\n for (let i = 0; i < abstractPath.length; i++) {\n const node = abstractPath[i];\n const targetX = i === abstractPath.length - 1 ? endX : node.position.x;\n const targetY = i === abstractPath.length - 1 ? endY : node.position.y;\n\n if (currentX !== targetX || currentY !== targetY) {\n const segment = this.localPathfinder.findPath(currentX, currentY, targetX, targetY, opts);\n\n if (!segment.found) {\n if (fullPath.length > 0) {\n return {\n found: true,\n path: fullPath,\n cost: totalCost,\n nodesSearched\n };\n }\n return EMPTY_PATH_RESULT;\n }\n\n for (let j = fullPath.length === 0 ? 0 : 1; j < segment.path.length; j++) {\n fullPath.push(segment.path[j]);\n }\n\n totalCost += segment.cost;\n nodesSearched += segment.nodesSearched;\n }\n\n currentX = targetX;\n currentY = targetY;\n }\n\n if (currentX !== endX || currentY !== endY) {\n const finalSegment = this.localPathfinder.findPath(currentX, currentY, endX, endY, opts);\n if (finalSegment.found) {\n for (let j = 1; j < finalSegment.path.length; j++) {\n fullPath.push(finalSegment.path[j]);\n }\n totalCost += finalSegment.cost;\n nodesSearched += finalSegment.nodesSearched;\n }\n }\n\n return {\n found: fullPath.length > 0,\n path: fullPath,\n cost: totalCost,\n nodesSearched\n };\n }\n\n // =========================================================================\n // 辅助方法 | Helper Methods\n // =========================================================================\n\n private findLocalPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n opts: Required<IPathfindingOptions>\n ): IPathResult {\n return this.localPathfinder.findPath(startX, startY, endX, endY, opts);\n }\n\n private findInternalPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n cluster: Cluster\n ): IPoint[] | null {\n const cacheKey = `${cluster.id}:${startX},${startY}->${endX},${endY}`;\n\n if (this.config.cacheInternalPaths) {\n const cached = this.internalPathCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n const result = this.localPathfinder.findPath(startX, startY, endX, endY);\n\n if (result.found && this.config.cacheInternalPaths) {\n this.internalPathCache.set(cacheKey, [...result.path]);\n }\n\n return result.found ? [...result.path] : null;\n }\n\n private calculatePathCost(path: IPoint[]): number {\n let cost = 0;\n for (let i = 1; i < path.length; i++) {\n const dx = Math.abs(path[i].x - path[i - 1].x);\n const dy = Math.abs(path[i].y - path[i - 1].y);\n cost += dx !== 0 && dy !== 0 ? Math.SQRT2 : 1;\n }\n return cost;\n }\n\n private heuristic(a: IPoint, b: IPoint): number {\n const dx = Math.abs(a.x - b.x);\n const dy = Math.abs(a.y - b.y);\n return dx + dy + (Math.SQRT2 - 2) * Math.min(dx, dy);\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 HPA* 寻路器\n * @en Create HPA* pathfinder\n *\n * @param map - @zh 寻路地图实例 @en Pathfinding map instance\n * @param config - @zh HPA* 配置 @en HPA* configuration\n * @returns @zh HPA* 寻路器实例 @en HPA* pathfinder instance\n */\nexport function createHPAPathfinder(\n map: IPathfindingMap,\n config?: Partial<IHPAConfig>\n): HPAPathfinder {\n return new HPAPathfinder(map, config);\n}\n","/**\n * @zh 导航网格实现\n * @en NavMesh Implementation\n */\n\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n IPathResult,\n IPathfindingOptions\n} from '../core/IPathfinding';\nimport { createPoint, euclideanDistance, EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from '../core/IPathfinding';\nimport { BinaryHeap } from '../core/BinaryHeap';\n\n// =============================================================================\n// 导航多边形 | Navigation Polygon\n// =============================================================================\n\n/**\n * @zh 导航多边形\n * @en Navigation polygon\n */\nexport interface INavPolygon {\n /** @zh 多边形ID @en Polygon ID */\n readonly id: number;\n /** @zh 顶点列表 @en Vertex list */\n readonly vertices: readonly IPoint[];\n /** @zh 中心点 @en Center point */\n readonly center: IPoint;\n /** @zh 邻居多边形ID @en Neighbor polygon IDs */\n readonly neighbors: readonly number[];\n /** @zh 到邻居的共享边 @en Shared edges to neighbors */\n readonly portals: ReadonlyMap<number, IPortal>;\n}\n\n/**\n * @zh 入口(两个多边形之间的共享边)\n * @en Portal (shared edge between two polygons)\n */\nexport interface IPortal {\n /** @zh 边的左端点 @en Left endpoint of edge */\n readonly left: IPoint;\n /** @zh 边的右端点 @en Right endpoint of edge */\n readonly right: IPoint;\n}\n\n// =============================================================================\n// 导航网格节点 | NavMesh Node\n// =============================================================================\n\n/**\n * @zh 导航网格节点(包装多边形)\n * @en NavMesh node (wraps polygon)\n */\nclass NavMeshNode implements IPathNode {\n readonly id: number;\n readonly position: IPoint;\n readonly cost: number;\n readonly walkable: boolean;\n readonly polygon: INavPolygon;\n\n constructor(polygon: INavPolygon) {\n this.id = polygon.id;\n this.position = polygon.center;\n this.cost = 1;\n this.walkable = true;\n this.polygon = polygon;\n }\n}\n\n// =============================================================================\n// 导航网格 | Navigation Mesh\n// =============================================================================\n\n/**\n * @zh 导航网格\n * @en Navigation Mesh\n *\n * @zh 使用凸多边形网格进行高效寻路,适合复杂地形\n * @en Uses convex polygon mesh for efficient pathfinding, suitable for complex terrain\n *\n * @example\n * ```typescript\n * const navmesh = new NavMesh();\n *\n * // Add polygons\n * navmesh.addPolygon([\n * { x: 0, y: 0 }, { x: 10, y: 0 },\n * { x: 10, y: 10 }, { x: 0, y: 10 }\n * ]);\n *\n * // Build connections\n * navmesh.build();\n *\n * // Find path\n * const result = navmesh.findPath(1, 1, 8, 8);\n * ```\n */\nexport class NavMesh implements IPathfindingMap {\n private polygons: Map<number, INavPolygon> = new Map();\n private nodes: Map<number, NavMeshNode> = new Map();\n private nextId = 0;\n\n /**\n * @zh 添加导航多边形\n * @en Add navigation polygon\n *\n * @returns @zh 多边形ID @en Polygon ID\n */\n addPolygon(vertices: IPoint[], neighbors: number[] = []): number {\n const id = this.nextId++;\n const center = this.calculateCenter(vertices);\n\n const polygon: INavPolygon = {\n id,\n vertices,\n center,\n neighbors,\n portals: new Map()\n };\n\n this.polygons.set(id, polygon);\n this.nodes.set(id, new NavMeshNode(polygon));\n\n return id;\n }\n\n /**\n * @zh 设置两个多边形之间的连接\n * @en Set connection between two polygons\n */\n setConnection(\n polyA: number,\n polyB: number,\n portal: IPortal\n ): void {\n const polygonA = this.polygons.get(polyA);\n const polygonB = this.polygons.get(polyB);\n\n if (!polygonA || !polygonB) {\n return;\n }\n\n // Update neighbors and portals\n const neighborsA = [...polygonA.neighbors];\n const portalsA = new Map(polygonA.portals);\n\n if (!neighborsA.includes(polyB)) {\n neighborsA.push(polyB);\n }\n portalsA.set(polyB, portal);\n\n this.polygons.set(polyA, {\n ...polygonA,\n neighbors: neighborsA,\n portals: portalsA\n });\n\n // Reverse portal for the other direction\n const reversePortal: IPortal = {\n left: portal.right,\n right: portal.left\n };\n\n const neighborsB = [...polygonB.neighbors];\n const portalsB = new Map(polygonB.portals);\n\n if (!neighborsB.includes(polyA)) {\n neighborsB.push(polyA);\n }\n portalsB.set(polyA, reversePortal);\n\n this.polygons.set(polyB, {\n ...polygonB,\n neighbors: neighborsB,\n portals: portalsB\n });\n }\n\n /**\n * @zh 自动检测并建立相邻多边形的连接\n * @en Auto-detect and build connections between adjacent polygons\n */\n build(): void {\n const polygonList = Array.from(this.polygons.values());\n\n for (let i = 0; i < polygonList.length; i++) {\n for (let j = i + 1; j < polygonList.length; j++) {\n const polyA = polygonList[i];\n const polyB = polygonList[j];\n\n const sharedEdge = this.findSharedEdge(polyA.vertices, polyB.vertices);\n\n if (sharedEdge) {\n this.setConnection(polyA.id, polyB.id, sharedEdge);\n }\n }\n }\n }\n\n /**\n * @zh 查找两个多边形的共享边\n * @en Find shared edge between two polygons\n */\n private findSharedEdge(\n verticesA: readonly IPoint[],\n verticesB: readonly IPoint[]\n ): IPortal | null {\n const epsilon = 0.0001;\n\n for (let i = 0; i < verticesA.length; i++) {\n const a1 = verticesA[i];\n const a2 = verticesA[(i + 1) % verticesA.length];\n\n for (let j = 0; j < verticesB.length; j++) {\n const b1 = verticesB[j];\n const b2 = verticesB[(j + 1) % verticesB.length];\n\n // Check if edges match (in either direction)\n const match1 =\n Math.abs(a1.x - b2.x) < epsilon &&\n Math.abs(a1.y - b2.y) < epsilon &&\n Math.abs(a2.x - b1.x) < epsilon &&\n Math.abs(a2.y - b1.y) < epsilon;\n\n const match2 =\n Math.abs(a1.x - b1.x) < epsilon &&\n Math.abs(a1.y - b1.y) < epsilon &&\n Math.abs(a2.x - b2.x) < epsilon &&\n Math.abs(a2.y - b2.y) < epsilon;\n\n if (match1 || match2) {\n return {\n left: a1,\n right: a2\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * @zh 计算多边形中心\n * @en Calculate polygon center\n */\n private calculateCenter(vertices: readonly IPoint[]): IPoint {\n let x = 0;\n let y = 0;\n\n for (const v of vertices) {\n x += v.x;\n y += v.y;\n }\n\n return createPoint(x / vertices.length, y / vertices.length);\n }\n\n /**\n * @zh 查找包含点的多边形\n * @en Find polygon containing point\n */\n findPolygonAt(x: number, y: number): INavPolygon | null {\n for (const polygon of this.polygons.values()) {\n if (this.isPointInPolygon(x, y, polygon.vertices)) {\n return polygon;\n }\n }\n return null;\n }\n\n /**\n * @zh 检查点是否在多边形内\n * @en Check if point is inside polygon\n */\n private isPointInPolygon(x: number, y: number, vertices: readonly IPoint[]): boolean {\n let inside = false;\n const n = vertices.length;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = vertices[i].x;\n const yi = vertices[i].y;\n const xj = vertices[j].x;\n const yj = vertices[j].y;\n\n if (\n yi > y !== yj > y &&\n x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n ) {\n inside = !inside;\n }\n }\n\n return inside;\n }\n\n // ==========================================================================\n // IPathfindingMap 接口实现 | IPathfindingMap Interface Implementation\n // ==========================================================================\n\n getNodeAt(x: number, y: number): IPathNode | null {\n const polygon = this.findPolygonAt(x, y);\n return polygon ? this.nodes.get(polygon.id) ?? null : null;\n }\n\n getNeighbors(node: IPathNode): IPathNode[] {\n const navNode = node as NavMeshNode;\n const neighbors: IPathNode[] = [];\n\n for (const neighborId of navNode.polygon.neighbors) {\n const neighbor = this.nodes.get(neighborId);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n\n return neighbors;\n }\n\n heuristic(a: IPoint, b: IPoint): number {\n return euclideanDistance(a, b);\n }\n\n getMovementCost(from: IPathNode, to: IPathNode): number {\n return euclideanDistance(from.position, to.position);\n }\n\n isWalkable(x: number, y: number): boolean {\n return this.findPolygonAt(x, y) !== null;\n }\n\n // ==========================================================================\n // 寻路 | Pathfinding\n // ==========================================================================\n\n /**\n * @zh 在导航网格上寻路\n * @en Find path on navigation mesh\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n const startPolygon = this.findPolygonAt(startX, startY);\n const endPolygon = this.findPolygonAt(endX, endY);\n\n if (!startPolygon || !endPolygon) {\n return EMPTY_PATH_RESULT;\n }\n\n // Same polygon\n if (startPolygon.id === endPolygon.id) {\n return {\n found: true,\n path: [createPoint(startX, startY), createPoint(endX, endY)],\n cost: euclideanDistance(\n createPoint(startX, startY),\n createPoint(endX, endY)\n ),\n nodesSearched: 1\n };\n }\n\n // A* on polygon graph\n const polygonPath = this.findPolygonPath(startPolygon, endPolygon, opts);\n\n if (!polygonPath.found) {\n return EMPTY_PATH_RESULT;\n }\n\n // Convert polygon path to point path using funnel algorithm\n const start = createPoint(startX, startY);\n const end = createPoint(endX, endY);\n const pointPath = this.funnelPath(start, end, polygonPath.polygons);\n\n return {\n found: true,\n path: pointPath,\n cost: this.calculatePathLength(pointPath),\n nodesSearched: polygonPath.nodesSearched\n };\n }\n\n /**\n * @zh 在多边形图上寻路\n * @en Find path on polygon graph\n */\n private findPolygonPath(\n start: INavPolygon,\n end: INavPolygon,\n opts: Required<IPathfindingOptions>\n ): { found: boolean; polygons: INavPolygon[]; nodesSearched: number } {\n interface AStarState {\n polygon: INavPolygon;\n g: number;\n f: number;\n parent: AStarState | null;\n }\n\n const openList = new BinaryHeap<AStarState>((a, b) => a.f - b.f);\n const closed = new Set<number>();\n const states = new Map<number, AStarState>();\n\n const startState: AStarState = {\n polygon: start,\n g: 0,\n f: euclideanDistance(start.center, end.center) * opts.heuristicWeight,\n parent: null\n };\n\n states.set(start.id, startState);\n openList.push(startState);\n\n let nodesSearched = 0;\n\n while (!openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = openList.pop()!;\n nodesSearched++;\n\n if (current.polygon.id === end.id) {\n // Reconstruct path\n const path: INavPolygon[] = [];\n let state: AStarState | null = current;\n\n while (state) {\n path.unshift(state.polygon);\n state = state.parent;\n }\n\n return { found: true, polygons: path, nodesSearched };\n }\n\n closed.add(current.polygon.id);\n\n for (const neighborId of current.polygon.neighbors) {\n if (closed.has(neighborId)) {\n continue;\n }\n\n const neighborPolygon = this.polygons.get(neighborId);\n if (!neighborPolygon) {\n continue;\n }\n\n const g = current.g + euclideanDistance(\n current.polygon.center,\n neighborPolygon.center\n );\n\n let neighborState = states.get(neighborId);\n\n if (!neighborState) {\n neighborState = {\n polygon: neighborPolygon,\n g,\n f: g + euclideanDistance(neighborPolygon.center, end.center) * opts.heuristicWeight,\n parent: current\n };\n states.set(neighborId, neighborState);\n openList.push(neighborState);\n } else if (g < neighborState.g) {\n neighborState.g = g;\n neighborState.f = g + euclideanDistance(neighborPolygon.center, end.center) * opts.heuristicWeight;\n neighborState.parent = current;\n openList.update(neighborState);\n }\n }\n }\n\n return { found: false, polygons: [], nodesSearched };\n }\n\n /**\n * @zh 使用漏斗算法优化路径\n * @en Optimize path using funnel algorithm\n */\n private funnelPath(\n start: IPoint,\n end: IPoint,\n polygons: INavPolygon[]\n ): IPoint[] {\n if (polygons.length <= 1) {\n return [start, end];\n }\n\n // Collect portals\n const portals: IPortal[] = [];\n\n for (let i = 0; i < polygons.length - 1; i++) {\n const portal = polygons[i].portals.get(polygons[i + 1].id);\n if (portal) {\n portals.push(portal);\n }\n }\n\n if (portals.length === 0) {\n return [start, end];\n }\n\n // Simple string pulling algorithm\n const path: IPoint[] = [start];\n\n let apex = start;\n let leftIndex = 0;\n let rightIndex = 0;\n let left = portals[0].left;\n let right = portals[0].right;\n\n for (let i = 1; i <= portals.length; i++) {\n const nextLeft = i < portals.length ? portals[i].left : end;\n const nextRight = i < portals.length ? portals[i].right : end;\n\n // Update right\n if (this.triArea2(apex, right, nextRight) <= 0) {\n if (apex === right || this.triArea2(apex, left, nextRight) > 0) {\n right = nextRight;\n rightIndex = i;\n } else {\n path.push(left);\n apex = left;\n leftIndex = rightIndex = leftIndex;\n left = right = apex;\n i = leftIndex;\n continue;\n }\n }\n\n // Update left\n if (this.triArea2(apex, left, nextLeft) >= 0) {\n if (apex === left || this.triArea2(apex, right, nextLeft) < 0) {\n left = nextLeft;\n leftIndex = i;\n } else {\n path.push(right);\n apex = right;\n leftIndex = rightIndex = rightIndex;\n left = right = apex;\n i = rightIndex;\n continue;\n }\n }\n }\n\n path.push(end);\n\n return path;\n }\n\n /**\n * @zh 计算三角形面积的两倍(用于判断点的相对位置)\n * @en Calculate twice the triangle area (for point relative position)\n */\n private triArea2(a: IPoint, b: IPoint, c: IPoint): number {\n return (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y);\n }\n\n /**\n * @zh 计算路径总长度\n * @en Calculate total path length\n */\n private calculatePathLength(path: readonly IPoint[]): number {\n let length = 0;\n\n for (let i = 1; i < path.length; i++) {\n length += euclideanDistance(path[i - 1], path[i]);\n }\n\n return length;\n }\n\n /**\n * @zh 清空导航网格\n * @en Clear navigation mesh\n */\n clear(): void {\n this.polygons.clear();\n this.nodes.clear();\n this.nextId = 0;\n }\n\n /**\n * @zh 获取所有多边形\n * @en Get all polygons\n */\n getPolygons(): INavPolygon[] {\n return Array.from(this.polygons.values());\n }\n\n /**\n * @zh 获取多边形数量\n * @en Get polygon count\n */\n get polygonCount(): number {\n return this.polygons.size;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建导航网格\n * @en Create navigation mesh\n */\nexport function createNavMesh(): NavMesh {\n return new NavMesh();\n}\n"],"mappings":"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","names":["BinaryHeap","compare","heap","size","length","isEmpty","push","item","bubbleUp","pop","undefined","result","last","sinkDown","peek","update","index","indexOf","contains","clear","parentIndex","Math","floor","parent","leftIndex","rightIndex","smallest","AStarPathfinder","map","nodeCache","Map","openList","IndexedBinaryHeap","a","b","f","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","clear","startNode","getNodeAt","endNode","EMPTY_PATH_RESULT","walkable","id","found","path","position","cost","nodesSearched","start","getOrCreateAStarNode","g","h","heuristic","heuristicWeight","opened","push","endPosition","isEmpty","maxNodes","current","pop","closed","node","buildPath","neighbors","getNeighbors","neighborNode","neighbor","movementCost","getMovementCost","tentativeG","parent","update","astarNode","get","Infinity","heapIndex","set","reverse","createAStarPathfinder","CLOSED_FLAG","OPENED_FLAG","BACKWARD_CLOSED","BACKWARD_OPENED","GridState","width","height","bidirectional","size","g","f","flags","parent","heapIndex","version","currentVersion","gBack","fBack","parentBack","heapIndexBack","Float32Array","Uint8Array","Int32Array","Uint32Array","reset","fill","isInit","i","init","Infinity","getG","setG","v","getF","setF","getParent","setParent","getHeapIndex","setHeapIndex","isClosed","setClosed","isOpened","setOpened","getGBack","setGBack","getFBack","setFBack","getParentBack","setParentBack","getHeapIndexBack","setHeapIndexBack","isClosedBack","setClosedBack","isOpenedBack","setOpenedBack","_a","GridHeap","state","isBack","heap","length","isEmpty","push","bubbleUp","pop","result","last","sinkDown","update","pos","clear","idx","pp","pi","len","half","left","right","smallest","smallestF","lf","rf","si","GridPathfinder","map","config","mode","openList","openListBack","isBidir","findPath","startX","startY","endX","endY","options","findPathBidirectional","findPathUnidirectional","opts","DEFAULT_PATHFINDING_OPTIONS","validate","EMPTY_PATH_RESULT","startIdx","endIdx","found","path","x","y","cost","nodesSearched","hw","heuristicWeight","h0","heuristic","searched","maxNodes","allowDiagonal","avoidCorners","diagonalCost","nodes","dx","dy","dirCount","cur","buildPath","cx","cy","curG","d","nx","ny","neighbor","walkable","ni","isDiag","tentG","h","startPos","endPos","hf","hb","meetIdx","bestCost","total","buildPathBidirectional","isWalkable","w","reverse","createGridPathfinder","JPSPathfinder","map","width","height","openList","nodeGrid","bounds","getMapBounds","BinaryHeap","a","b","f","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","isWalkable","EMPTY_PATH_RESULT","found","path","x","y","cost","nodesSearched","initGrid","clear","startNode","getOrCreateNode","g","h","heuristic","heuristicWeight","push","isEmpty","maxNodes","current","pop","closed","buildPath","identifySuccessors","mapAny","i","xi","yi","Error","Infinity","parent","x1","y1","x2","y2","dx","Math","abs","dy","SQRT2","min","node","neighbors","findNeighbors","neighbor","jumpPoint","jump","jx","jy","jpNode","distance","sqrt","tentativeG","contains","update","nx","ny","isWalkableAt","sign","px","py","jumpStraight","endNode","unshift","interpolatePath","jumpPoints","length","prev","curr","steps","max","stepX","stepY","j","createJPSPathfinder","DEFAULT_HPA_CONFIG","clusterSize","maxEntranceWidth","cacheInternalPaths","HPAPathfinder","map","config","width","height","clusters","entrances","abstractNodes","Map","clusterGrid","nextEntranceId","nextNodeId","internalPathCache","localPathfinder","preprocessed","bounds","getMapBounds","AStarPathfinder","preprocess","clear","buildClusters","findEntrances","buildAbstractGraph","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","isWalkable","EMPTY_PATH_RESULT","found","path","x","y","cost","nodesSearched","startCluster","getClusterAt","endCluster","id","findLocalPath","startNodes","insertTemporaryNode","endNodes","abstractPath","searchAbstractGraph","removeTemporaryNodes","length","refinePath","notifyRegionChange","minX","minY","maxX","maxY","getStats","size","cacheSize","mapAny","clustersX","Math","ceil","clustersY","clusterId","cy","cx","cluster","min","push","rightCluster","findEntrancesBetween","bottomCluster","cluster1","cluster2","direction","maxWidth","entranceStart","entranceLength","x1","x2","max","walkable1","walkable2","createEntrance","y1","y2","coord1Start","coord1End","coord2Start","coord2End","point1","point2","center","midY","floor","midX","entrance","cluster1Id","cluster2Id","node1","createAbstractNode","node2","edges","targetNodeId","isInterEdge","connectIntraClusterNodes","position","entranceId","node","set","nodesInCluster","values","i","j","heuristic","tempNodes","tempNode","nodes","edge","targetNode","get","filter","e","delete","endNodeIds","Set","n","openList","BinaryHeap","a","b","f","closedSet","startNode","h","abstractNode","g","heuristicWeight","parent","isEmpty","maxNodes","current","pop","has","reconstructAbstractPath","add","neighbor","tentativeG","endNode","unshift","fullPath","totalCost","currentX","currentY","targetX","targetY","segment","finalSegment","findInternalPath","cacheKey","cached","result","calculatePathCost","dx","abs","dy","SQRT2","createHPAPathfinder","_a","NavMeshNode","polygon","id","position","cost","walkable","center","NavMesh","polygons","Map","nodes","nextId","addPolygon","vertices","neighbors","calculateCenter","portals","set","setConnection","polyA","polyB","portal","polygonA","get","polygonB","neighborsA","portalsA","includes","push","reversePortal","left","right","neighborsB","portalsB","build","polygonList","Array","from","values","i","length","j","sharedEdge","findSharedEdge","verticesA","verticesB","epsilon","a1","a2","b1","b2","match1","Math","abs","x","y","match2","v","createPoint","findPolygonAt","isPointInPolygon","inside","n","xi","yi","xj","yj","getNodeAt","getNeighbors","node","navNode","neighborId","neighbor","heuristic","a","b","euclideanDistance","getMovementCost","to","isWalkable","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","startPolygon","endPolygon","EMPTY_PATH_RESULT","found","path","nodesSearched","polygonPath","findPolygonPath","start","end","pointPath","funnelPath","calculatePathLength","openList","BinaryHeap","f","closed","Set","states","startState","g","heuristicWeight","parent","isEmpty","maxNodes","current","pop","state","unshift","add","has","neighborPolygon","neighborState","update","apex","leftIndex","rightIndex","nextLeft","nextRight","triArea2","c","clear","getPolygons","polygonCount","size","createNavMesh"]}
1
+ {"version":3,"sources":["../src/core/BinaryHeap.ts","../src/core/AStarPathfinder.ts","../src/core/GridPathfinder.ts","../src/core/JPSPathfinder.ts","../src/core/HPAPathfinder.ts","../src/navmesh/NavMesh.ts"],"sourcesContent":["/**\n * @zh 二叉堆(优先队列)\n * @en Binary Heap (Priority Queue)\n *\n * @zh 用于 A* 算法的高效开放列表\n * @en Efficient open list for A* algorithm\n */\nexport class BinaryHeap<T> {\n private heap: T[] = [];\n private readonly compare: (a: T, b: T) => number;\n\n /**\n * @zh 创建二叉堆\n * @en Create binary heap\n *\n * @param compare - @zh 比较函数,返回负数表示 a < b @en Compare function, returns negative if a < b\n */\n constructor(compare: (a: T, b: T) => number) {\n this.compare = compare;\n }\n\n /**\n * @zh 堆大小\n * @en Heap size\n */\n get size(): number {\n return this.heap.length;\n }\n\n /**\n * @zh 是否为空\n * @en Is empty\n */\n get isEmpty(): boolean {\n return this.heap.length === 0;\n }\n\n /**\n * @zh 插入元素\n * @en Push element\n */\n push(item: T): void {\n this.heap.push(item);\n this.bubbleUp(this.heap.length - 1);\n }\n\n /**\n * @zh 弹出最小元素\n * @en Pop minimum element\n */\n pop(): T | undefined {\n if (this.heap.length === 0) {\n return undefined;\n }\n\n const result = this.heap[0];\n const last = this.heap.pop()!;\n\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.sinkDown(0);\n }\n\n return result;\n }\n\n /**\n * @zh 查看最小元素(不移除)\n * @en Peek minimum element (without removing)\n */\n peek(): T | undefined {\n return this.heap[0];\n }\n\n /**\n * @zh 更新元素(重新排序)\n * @en Update element (re-sort)\n */\n update(item: T): void {\n const index = this.heap.indexOf(item);\n if (index !== -1) {\n this.bubbleUp(index);\n this.sinkDown(index);\n }\n }\n\n /**\n * @zh 检查是否包含元素\n * @en Check if contains element\n */\n contains(item: T): boolean {\n return this.heap.indexOf(item) !== -1;\n }\n\n /**\n * @zh 清空堆\n * @en Clear heap\n */\n clear(): void {\n this.heap.length = 0;\n }\n\n /**\n * @zh 上浮操作\n * @en Bubble up operation\n */\n private bubbleUp(index: number): void {\n const item = this.heap[index];\n\n while (index > 0) {\n const parentIndex = Math.floor((index - 1) / 2);\n const parent = this.heap[parentIndex];\n\n if (this.compare(item, parent) >= 0) {\n break;\n }\n\n this.heap[index] = parent;\n index = parentIndex;\n }\n\n this.heap[index] = item;\n }\n\n /**\n * @zh 下沉操作\n * @en Sink down operation\n */\n private sinkDown(index: number): void {\n const length = this.heap.length;\n const item = this.heap[index];\n\n while (true) {\n const leftIndex = 2 * index + 1;\n const rightIndex = 2 * index + 2;\n let smallest = index;\n\n if (leftIndex < length && this.compare(this.heap[leftIndex], this.heap[smallest]) < 0) {\n smallest = leftIndex;\n }\n\n if (rightIndex < length && this.compare(this.heap[rightIndex], this.heap[smallest]) < 0) {\n smallest = rightIndex;\n }\n\n if (smallest === index) {\n break;\n }\n\n this.heap[index] = this.heap[smallest];\n this.heap[smallest] = item;\n index = smallest;\n }\n }\n}\n","/**\n * @zh A* 寻路算法实现\n * @en A* Pathfinding Algorithm Implementation\n */\n\nimport { IndexedBinaryHeap, type IHeapIndexable } from './IndexedBinaryHeap';\nimport type {\n IPathfindingMap,\n IPathfinder,\n IPathResult,\n IPathfindingOptions,\n IPathNode,\n IPoint\n} from './IPathfinding';\nimport { EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from './IPathfinding';\n\n// =============================================================================\n// 内部节点类型 | Internal Node Type\n// =============================================================================\n\ninterface AStarNode extends IHeapIndexable {\n node: IPathNode;\n g: number; // Cost from start\n h: number; // Heuristic to end\n f: number; // Total cost (g + h)\n parent: AStarNode | null;\n closed: boolean;\n opened: boolean;\n heapIndex: number; // For IndexedBinaryHeap O(log n) update\n}\n\n// =============================================================================\n// A* 寻路器 | A* Pathfinder\n// =============================================================================\n\n/**\n * @zh A* 寻路器\n * @en A* Pathfinder\n *\n * @zh 使用 A* 算法在地图上查找最短路径\n * @en Uses A* algorithm to find shortest path on a map\n *\n * @example\n * ```typescript\n * const map = new GridMap(width, height);\n * const pathfinder = new AStarPathfinder(map);\n * const result = pathfinder.findPath(0, 0, 10, 10);\n * if (result.found) {\n * console.log('Path:', result.path);\n * }\n * ```\n */\nexport class AStarPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private nodeCache: Map<string | number, AStarNode> = new Map();\n private openList: IndexedBinaryHeap<AStarNode>;\n\n constructor(map: IPathfindingMap) {\n this.map = map;\n this.openList = new IndexedBinaryHeap<AStarNode>((a, b) => a.f - b.f);\n }\n\n /**\n * @zh 查找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n // Clear previous state\n this.clear();\n\n // Get start and end nodes\n const startNode = this.map.getNodeAt(startX, startY);\n const endNode = this.map.getNodeAt(endX, endY);\n\n // Validate nodes\n if (!startNode || !endNode) {\n return EMPTY_PATH_RESULT;\n }\n\n if (!startNode.walkable || !endNode.walkable) {\n return EMPTY_PATH_RESULT;\n }\n\n // Same position\n if (startNode.id === endNode.id) {\n return {\n found: true,\n path: [startNode.position],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n // Initialize start node\n const start = this.getOrCreateAStarNode(startNode);\n start.g = 0;\n start.h = this.map.heuristic(startNode.position, endNode.position) * opts.heuristicWeight;\n start.f = start.h;\n start.opened = true;\n\n this.openList.push(start);\n\n let nodesSearched = 0;\n const endPosition = endNode.position;\n\n // A* main loop\n while (!this.openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = this.openList.pop()!;\n current.closed = true;\n nodesSearched++;\n\n // Found the goal\n if (current.node.id === endNode.id) {\n return this.buildPath(current, nodesSearched);\n }\n\n // Explore neighbors\n const neighbors = this.map.getNeighbors(current.node);\n\n for (const neighborNode of neighbors) {\n // Skip if not walkable or already closed\n if (!neighborNode.walkable) {\n continue;\n }\n\n const neighbor = this.getOrCreateAStarNode(neighborNode);\n\n if (neighbor.closed) {\n continue;\n }\n\n // Calculate tentative g score\n const movementCost = this.map.getMovementCost(current.node, neighborNode);\n const tentativeG = current.g + movementCost;\n\n // Check if this path is better\n if (!neighbor.opened) {\n // First time visiting this node\n neighbor.g = tentativeG;\n neighbor.h = this.map.heuristic(neighborNode.position, endPosition) * opts.heuristicWeight;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n neighbor.opened = true;\n this.openList.push(neighbor);\n } else if (tentativeG < neighbor.g) {\n // Found a better path\n neighbor.g = tentativeG;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n this.openList.update(neighbor);\n }\n }\n }\n\n // No path found\n return {\n found: false,\n path: [],\n cost: 0,\n nodesSearched\n };\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.nodeCache.clear();\n this.openList.clear();\n }\n\n /**\n * @zh 获取或创建 A* 节点\n * @en Get or create A* node\n */\n private getOrCreateAStarNode(node: IPathNode): AStarNode {\n let astarNode = this.nodeCache.get(node.id);\n\n if (!astarNode) {\n astarNode = {\n node,\n g: Infinity,\n h: 0,\n f: Infinity,\n parent: null,\n closed: false,\n opened: false,\n heapIndex: -1\n };\n this.nodeCache.set(node.id, astarNode);\n }\n\n return astarNode;\n }\n\n /**\n * @zh 构建路径结果\n * @en Build path result\n */\n private buildPath(endNode: AStarNode, nodesSearched: number): IPathResult {\n const path: IPoint[] = [];\n let current: AStarNode | null = endNode;\n\n while (current) {\n path.push(current.node.position);\n current = current.parent;\n }\n\n path.reverse();\n\n return {\n found: true,\n path,\n cost: endNode.g,\n nodesSearched\n };\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 A* 寻路器\n * @en Create A* pathfinder\n */\nexport function createAStarPathfinder(map: IPathfindingMap): AStarPathfinder {\n return new AStarPathfinder(map);\n}\n","/**\n * @zh 网格寻路器(统一实现)\n * @en Grid Pathfinder (unified implementation)\n */\n\nimport type { IPathfinder, IPathResult, IPathfindingOptions, IPoint } from './IPathfinding';\nimport { EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from './IPathfinding';\nimport { GridMap } from '../grid/GridMap';\n\n// =============================================================================\n// 配置 | Configuration\n// =============================================================================\n\n/**\n * @zh 寻路模式\n * @en Pathfinding mode\n */\nexport type GridPathfinderMode = 'standard' | 'fast' | 'bidirectional';\n\n/**\n * @zh 网格寻路器配置\n * @en Grid pathfinder configuration\n */\nexport interface IGridPathfinderConfig {\n /**\n * @zh 寻路模式\n * @en Pathfinding mode\n *\n * - standard: 标准A*,适合小地图\n * - fast: TypedArray优化,适合中大地图\n * - bidirectional: 双向搜索,适合超大地图\n */\n mode?: GridPathfinderMode;\n}\n\n// =============================================================================\n// 常量 | Constants\n// =============================================================================\n\nconst CLOSED_FLAG = 1;\nconst OPENED_FLAG = 2;\nconst BACKWARD_CLOSED = 4;\nconst BACKWARD_OPENED = 8;\n\n// =============================================================================\n// 状态存储 | State Storage\n// =============================================================================\n\nclass GridState {\n private readonly size: number;\n readonly width: number;\n\n private g: Float32Array;\n private f: Float32Array;\n private flags: Uint8Array;\n private parent: Int32Array;\n private heapIndex: Int32Array;\n private version: Uint32Array;\n private currentVersion: number = 1;\n\n // 双向搜索额外状态\n private gBack: Float32Array | null = null;\n private fBack: Float32Array | null = null;\n private parentBack: Int32Array | null = null;\n private heapIndexBack: Int32Array | null = null;\n\n constructor(width: number, height: number, bidirectional: boolean = false) {\n this.width = width;\n this.size = width * height;\n\n this.g = new Float32Array(this.size);\n this.f = new Float32Array(this.size);\n this.flags = new Uint8Array(this.size);\n this.parent = new Int32Array(this.size);\n this.heapIndex = new Int32Array(this.size);\n this.version = new Uint32Array(this.size);\n\n if (bidirectional) {\n this.gBack = new Float32Array(this.size);\n this.fBack = new Float32Array(this.size);\n this.parentBack = new Int32Array(this.size);\n this.heapIndexBack = new Int32Array(this.size);\n }\n }\n\n reset(): void {\n this.currentVersion++;\n if (this.currentVersion > 0xFFFFFFFF) {\n this.version.fill(0);\n this.currentVersion = 1;\n }\n }\n\n private isInit(i: number): boolean {\n return this.version[i] === this.currentVersion;\n }\n\n private init(i: number): void {\n if (!this.isInit(i)) {\n this.g[i] = Infinity;\n this.f[i] = Infinity;\n this.flags[i] = 0;\n this.parent[i] = -1;\n this.heapIndex[i] = -1;\n if (this.gBack) {\n this.gBack[i] = Infinity;\n this.fBack![i] = Infinity;\n this.parentBack![i] = -1;\n this.heapIndexBack![i] = -1;\n }\n this.version[i] = this.currentVersion;\n }\n }\n\n // Forward\n getG(i: number): number { return this.isInit(i) ? this.g[i] : Infinity; }\n setG(i: number, v: number): void { this.init(i); this.g[i] = v; }\n getF(i: number): number { return this.isInit(i) ? this.f[i] : Infinity; }\n setF(i: number, v: number): void { this.init(i); this.f[i] = v; }\n getParent(i: number): number { return this.isInit(i) ? this.parent[i] : -1; }\n setParent(i: number, v: number): void { this.init(i); this.parent[i] = v; }\n getHeapIndex(i: number): number { return this.isInit(i) ? this.heapIndex[i] : -1; }\n setHeapIndex(i: number, v: number): void { this.init(i); this.heapIndex[i] = v; }\n isClosed(i: number): boolean { return this.isInit(i) && (this.flags[i] & CLOSED_FLAG) !== 0; }\n setClosed(i: number): void { this.init(i); this.flags[i] |= CLOSED_FLAG; }\n isOpened(i: number): boolean { return this.isInit(i) && (this.flags[i] & OPENED_FLAG) !== 0; }\n setOpened(i: number): void { this.init(i); this.flags[i] |= OPENED_FLAG; }\n\n // Backward\n getGBack(i: number): number { return this.isInit(i) ? this.gBack![i] : Infinity; }\n setGBack(i: number, v: number): void { this.init(i); this.gBack![i] = v; }\n getFBack(i: number): number { return this.isInit(i) ? this.fBack![i] : Infinity; }\n setFBack(i: number, v: number): void { this.init(i); this.fBack![i] = v; }\n getParentBack(i: number): number { return this.isInit(i) ? this.parentBack![i] : -1; }\n setParentBack(i: number, v: number): void { this.init(i); this.parentBack![i] = v; }\n getHeapIndexBack(i: number): number { return this.isInit(i) ? this.heapIndexBack![i] : -1; }\n setHeapIndexBack(i: number, v: number): void { this.init(i); this.heapIndexBack![i] = v; }\n isClosedBack(i: number): boolean { return this.isInit(i) && (this.flags[i] & BACKWARD_CLOSED) !== 0; }\n setClosedBack(i: number): void { this.init(i); this.flags[i] |= BACKWARD_CLOSED; }\n isOpenedBack(i: number): boolean { return this.isInit(i) && (this.flags[i] & BACKWARD_OPENED) !== 0; }\n setOpenedBack(i: number): void { this.init(i); this.flags[i] |= BACKWARD_OPENED; }\n}\n\n// =============================================================================\n// 堆 | Heap\n// =============================================================================\n\nclass GridHeap {\n private heap: number[] = [];\n private state: GridState;\n private isBack: boolean;\n\n constructor(state: GridState, isBack: boolean = false) {\n this.state = state;\n this.isBack = isBack;\n }\n\n get size(): number { return this.heap.length; }\n get isEmpty(): boolean { return this.heap.length === 0; }\n\n private getF(i: number): number {\n return this.isBack ? this.state.getFBack(i) : this.state.getF(i);\n }\n private getHeapIndex(i: number): number {\n return this.isBack ? this.state.getHeapIndexBack(i) : this.state.getHeapIndex(i);\n }\n private setHeapIndex(i: number, v: number): void {\n if (this.isBack) this.state.setHeapIndexBack(i, v);\n else this.state.setHeapIndex(i, v);\n }\n\n push(i: number): void {\n this.setHeapIndex(i, this.heap.length);\n this.heap.push(i);\n this.bubbleUp(this.heap.length - 1);\n }\n\n pop(): number {\n if (this.heap.length === 0) return -1;\n const result = this.heap[0];\n this.setHeapIndex(result, -1);\n const last = this.heap.pop()!;\n if (this.heap.length > 0) {\n this.heap[0] = last;\n this.setHeapIndex(last, 0);\n this.sinkDown(0);\n }\n return result;\n }\n\n update(i: number): void {\n const pos = this.getHeapIndex(i);\n if (pos >= 0 && pos < this.heap.length) {\n this.bubbleUp(pos);\n this.sinkDown(this.getHeapIndex(i));\n }\n }\n\n clear(): void { this.heap.length = 0; }\n\n private bubbleUp(pos: number): void {\n const idx = this.heap[pos];\n const f = this.getF(idx);\n while (pos > 0) {\n const pp = (pos - 1) >> 1;\n const pi = this.heap[pp];\n if (f >= this.getF(pi)) break;\n this.heap[pos] = pi;\n this.setHeapIndex(pi, pos);\n pos = pp;\n }\n this.heap[pos] = idx;\n this.setHeapIndex(idx, pos);\n }\n\n private sinkDown(pos: number): void {\n const len = this.heap.length;\n const idx = this.heap[pos];\n const f = this.getF(idx);\n const half = len >> 1;\n while (pos < half) {\n const left = (pos << 1) + 1;\n const right = left + 1;\n let smallest = pos, smallestF = f;\n const lf = this.getF(this.heap[left]);\n if (lf < smallestF) { smallest = left; smallestF = lf; }\n if (right < len) {\n const rf = this.getF(this.heap[right]);\n if (rf < smallestF) smallest = right;\n }\n if (smallest === pos) break;\n const si = this.heap[smallest];\n this.heap[pos] = si;\n this.setHeapIndex(si, pos);\n pos = smallest;\n }\n this.heap[pos] = idx;\n this.setHeapIndex(idx, pos);\n }\n}\n\n// =============================================================================\n// 网格寻路器 | Grid Pathfinder\n// =============================================================================\n\n/**\n * @zh 网格寻路器\n * @en Grid Pathfinder\n */\nexport class GridPathfinder implements IPathfinder {\n private readonly map: GridMap;\n private readonly mode: GridPathfinderMode;\n private readonly state: GridState;\n private readonly openList: GridHeap;\n private readonly openListBack: GridHeap | null;\n\n constructor(map: GridMap, config?: IGridPathfinderConfig) {\n this.map = map;\n this.mode = config?.mode ?? 'fast';\n const isBidir = this.mode === 'bidirectional';\n this.state = new GridState(map.width, map.height, isBidir);\n this.openList = new GridHeap(this.state, false);\n this.openListBack = isBidir ? new GridHeap(this.state, true) : null;\n }\n\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n if (this.mode === 'bidirectional') {\n return this.findPathBidirectional(startX, startY, endX, endY, options);\n }\n return this.findPathUnidirectional(startX, startY, endX, endY, options);\n }\n\n private findPathUnidirectional(\n startX: number, startY: number,\n endX: number, endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = options ? { ...DEFAULT_PATHFINDING_OPTIONS, ...options } : DEFAULT_PATHFINDING_OPTIONS;\n const { width, height } = this.map;\n\n this.state.reset();\n this.openList.clear();\n\n if (!this.validate(startX, startY, endX, endY)) return EMPTY_PATH_RESULT;\n\n const startIdx = startY * width + startX;\n const endIdx = endY * width + endX;\n\n if (startIdx === endIdx) {\n return { found: true, path: [{ x: startX, y: startY }], cost: 0, nodesSearched: 1 };\n }\n\n const hw = opts.heuristicWeight;\n const h0 = this.map.heuristic({ x: startX, y: startY }, { x: endX, y: endY }) * hw;\n this.state.setG(startIdx, 0);\n this.state.setF(startIdx, h0);\n this.state.setOpened(startIdx);\n this.openList.push(startIdx);\n\n let searched = 0;\n const maxNodes = opts.maxNodes;\n const { allowDiagonal, avoidCorners, diagonalCost } = this.map['options'];\n const nodes = this.map['nodes'];\n const dx = allowDiagonal ? [0, 1, 1, 1, 0, -1, -1, -1] : [0, 1, 0, -1];\n const dy = allowDiagonal ? [-1, -1, 0, 1, 1, 1, 0, -1] : [-1, 0, 1, 0];\n const dirCount = dx.length;\n\n while (!this.openList.isEmpty && searched < maxNodes) {\n const cur = this.openList.pop();\n this.state.setClosed(cur);\n searched++;\n\n if (cur === endIdx) {\n return this.buildPath(startIdx, endIdx, searched);\n }\n\n const cx = cur % width, cy = (cur / width) | 0;\n const curG = this.state.getG(cur);\n\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dx[d], ny = cy + dy[d];\n if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;\n\n const neighbor = nodes[ny][nx];\n if (!neighbor.walkable) continue;\n\n if (avoidCorners && dx[d] !== 0 && dy[d] !== 0) {\n if (!nodes[cy][cx + dx[d]].walkable || !nodes[cy + dy[d]][cx].walkable) continue;\n }\n\n const ni = ny * width + nx;\n if (this.state.isClosed(ni)) continue;\n\n const isDiag = dx[d] !== 0 && dy[d] !== 0;\n const cost = isDiag ? neighbor.cost * diagonalCost : neighbor.cost;\n const tentG = curG + cost;\n\n if (!this.state.isOpened(ni)) {\n const h = this.map.heuristic({ x: nx, y: ny }, { x: endX, y: endY }) * hw;\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.state.setOpened(ni);\n this.openList.push(ni);\n } else if (tentG < this.state.getG(ni)) {\n const h = this.state.getF(ni) - this.state.getG(ni);\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.openList.update(ni);\n }\n }\n }\n\n return { found: false, path: [], cost: 0, nodesSearched: searched };\n }\n\n private findPathBidirectional(\n startX: number, startY: number,\n endX: number, endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = options ? { ...DEFAULT_PATHFINDING_OPTIONS, ...options } : DEFAULT_PATHFINDING_OPTIONS;\n const { width, height } = this.map;\n\n this.state.reset();\n this.openList.clear();\n this.openListBack!.clear();\n\n if (!this.validate(startX, startY, endX, endY)) return EMPTY_PATH_RESULT;\n\n const startIdx = startY * width + startX;\n const endIdx = endY * width + endX;\n\n if (startIdx === endIdx) {\n return { found: true, path: [{ x: startX, y: startY }], cost: 0, nodesSearched: 1 };\n }\n\n const hw = opts.heuristicWeight;\n const startPos = { x: startX, y: startY };\n const endPos = { x: endX, y: endY };\n\n // Init forward\n const hf = this.map.heuristic(startPos, endPos) * hw;\n this.state.setG(startIdx, 0);\n this.state.setF(startIdx, hf);\n this.state.setOpened(startIdx);\n this.openList.push(startIdx);\n\n // Init backward\n const hb = this.map.heuristic(endPos, startPos) * hw;\n this.state.setGBack(endIdx, 0);\n this.state.setFBack(endIdx, hb);\n this.state.setOpenedBack(endIdx);\n this.openListBack!.push(endIdx);\n\n let searched = 0;\n const maxNodes = opts.maxNodes;\n let meetIdx = -1, bestCost = Infinity;\n\n const { allowDiagonal, avoidCorners, diagonalCost } = this.map['options'];\n const nodes = this.map['nodes'];\n const dx = allowDiagonal ? [0, 1, 1, 1, 0, -1, -1, -1] : [0, 1, 0, -1];\n const dy = allowDiagonal ? [-1, -1, 0, 1, 1, 1, 0, -1] : [-1, 0, 1, 0];\n const dirCount = dx.length;\n\n while ((!this.openList.isEmpty || !this.openListBack!.isEmpty) && searched < maxNodes) {\n // Forward\n if (!this.openList.isEmpty) {\n const cur = this.openList.pop();\n this.state.setClosed(cur);\n searched++;\n\n const curG = this.state.getG(cur);\n if (this.state.isClosedBack(cur)) {\n const total = curG + this.state.getGBack(cur);\n if (total < bestCost) { bestCost = total; meetIdx = cur; }\n }\n if (meetIdx !== -1 && curG >= bestCost) break;\n\n const cx = cur % width, cy = (cur / width) | 0;\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dx[d], ny = cy + dy[d];\n if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;\n const neighbor = nodes[ny][nx];\n if (!neighbor.walkable) continue;\n if (avoidCorners && dx[d] !== 0 && dy[d] !== 0) {\n if (!nodes[cy][cx + dx[d]].walkable || !nodes[cy + dy[d]][cx].walkable) continue;\n }\n const ni = ny * width + nx;\n if (this.state.isClosed(ni)) continue;\n const isDiag = dx[d] !== 0 && dy[d] !== 0;\n const cost = isDiag ? neighbor.cost * diagonalCost : neighbor.cost;\n const tentG = curG + cost;\n if (!this.state.isOpened(ni)) {\n const h = this.map.heuristic({ x: nx, y: ny }, endPos) * hw;\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.state.setOpened(ni);\n this.openList.push(ni);\n } else if (tentG < this.state.getG(ni)) {\n const h = this.state.getF(ni) - this.state.getG(ni);\n this.state.setG(ni, tentG);\n this.state.setF(ni, tentG + h);\n this.state.setParent(ni, cur);\n this.openList.update(ni);\n }\n }\n }\n\n // Backward\n if (!this.openListBack!.isEmpty) {\n const cur = this.openListBack!.pop();\n this.state.setClosedBack(cur);\n searched++;\n\n const curG = this.state.getGBack(cur);\n if (this.state.isClosed(cur)) {\n const total = curG + this.state.getG(cur);\n if (total < bestCost) { bestCost = total; meetIdx = cur; }\n }\n if (meetIdx !== -1 && curG >= bestCost) break;\n\n const cx = cur % width, cy = (cur / width) | 0;\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dx[d], ny = cy + dy[d];\n if (nx < 0 || nx >= width || ny < 0 || ny >= height) continue;\n const neighbor = nodes[ny][nx];\n if (!neighbor.walkable) continue;\n if (avoidCorners && dx[d] !== 0 && dy[d] !== 0) {\n if (!nodes[cy][cx + dx[d]].walkable || !nodes[cy + dy[d]][cx].walkable) continue;\n }\n const ni = ny * width + nx;\n if (this.state.isClosedBack(ni)) continue;\n const isDiag = dx[d] !== 0 && dy[d] !== 0;\n const cost = isDiag ? neighbor.cost * diagonalCost : neighbor.cost;\n const tentG = curG + cost;\n if (!this.state.isOpenedBack(ni)) {\n const h = this.map.heuristic({ x: nx, y: ny }, startPos) * hw;\n this.state.setGBack(ni, tentG);\n this.state.setFBack(ni, tentG + h);\n this.state.setParentBack(ni, cur);\n this.state.setOpenedBack(ni);\n this.openListBack!.push(ni);\n } else if (tentG < this.state.getGBack(ni)) {\n const h = this.state.getFBack(ni) - this.state.getGBack(ni);\n this.state.setGBack(ni, tentG);\n this.state.setFBack(ni, tentG + h);\n this.state.setParentBack(ni, cur);\n this.openListBack!.update(ni);\n }\n }\n }\n }\n\n if (meetIdx === -1) {\n return { found: false, path: [], cost: 0, nodesSearched: searched };\n }\n\n return this.buildPathBidirectional(startIdx, endIdx, meetIdx, searched);\n }\n\n private validate(startX: number, startY: number, endX: number, endY: number): boolean {\n const { width, height } = this.map;\n if (startX < 0 || startX >= width || startY < 0 || startY >= height) return false;\n if (endX < 0 || endX >= width || endY < 0 || endY >= height) return false;\n return this.map.isWalkable(startX, startY) && this.map.isWalkable(endX, endY);\n }\n\n private buildPath(startIdx: number, endIdx: number, searched: number): IPathResult {\n const w = this.state.width;\n const path: IPoint[] = [];\n let cur = endIdx;\n while (cur !== -1) {\n path.push({ x: cur % w, y: (cur / w) | 0 });\n cur = cur === startIdx ? -1 : this.state.getParent(cur);\n }\n path.reverse();\n return { found: true, path, cost: this.state.getG(endIdx), nodesSearched: searched };\n }\n\n private buildPathBidirectional(startIdx: number, endIdx: number, meetIdx: number, searched: number): IPathResult {\n const w = this.state.width;\n const path: IPoint[] = [];\n\n // Forward path\n let cur = meetIdx;\n while (cur !== -1 && cur !== startIdx) {\n path.push({ x: cur % w, y: (cur / w) | 0 });\n cur = this.state.getParent(cur);\n }\n path.push({ x: startIdx % w, y: (startIdx / w) | 0 });\n path.reverse();\n\n // Backward path\n cur = this.state.getParentBack(meetIdx);\n while (cur !== -1 && cur !== endIdx) {\n path.push({ x: cur % w, y: (cur / w) | 0 });\n cur = this.state.getParentBack(cur);\n }\n if (meetIdx !== endIdx) {\n path.push({ x: endIdx % w, y: (endIdx / w) | 0 });\n }\n\n const cost = this.state.getG(meetIdx) + this.state.getGBack(meetIdx);\n return { found: true, path, cost, nodesSearched: searched };\n }\n\n clear(): void {\n this.state.reset();\n this.openList.clear();\n this.openListBack?.clear();\n }\n}\n\n/**\n * @zh 创建网格寻路器\n * @en Create grid pathfinder\n */\nexport function createGridPathfinder(map: GridMap, config?: IGridPathfinderConfig): GridPathfinder {\n return new GridPathfinder(map, config);\n}\n","/**\n * @zh JPS (Jump Point Search) 寻路算法实现\n * @en JPS (Jump Point Search) Pathfinding Algorithm Implementation\n *\n * @zh JPS 是 A* 的优化版本,通过跳跃点剪枝大幅提升开放地形的搜索效率\n * @en JPS is an optimized version of A* that significantly improves search efficiency on open terrain through jump point pruning\n */\n\nimport { BinaryHeap } from './BinaryHeap';\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n IPathResult,\n IPathfinder,\n IPathfindingOptions\n} from './IPathfinding';\nimport { DEFAULT_PATHFINDING_OPTIONS, EMPTY_PATH_RESULT } from './IPathfinding';\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\n/**\n * @zh JPS 节点\n * @en JPS Node\n */\ninterface JPSNode {\n x: number;\n y: number;\n g: number;\n h: number;\n f: number;\n parent: JPSNode | null;\n closed: boolean;\n}\n\n// =============================================================================\n// JPS 寻路器 | JPS Pathfinder\n// =============================================================================\n\n/**\n * @zh JPS 寻路器\n * @en JPS Pathfinder\n *\n * @zh 适用于均匀代价网格地图,在开放地形上比标准 A* 快 10-100 倍\n * @en Suitable for uniform cost grid maps, 10-100x faster than standard A* on open terrain\n *\n * @example\n * ```typescript\n * const map = createGridMap(100, 100);\n * const pathfinder = new JPSPathfinder(map);\n * const result = pathfinder.findPath(0, 0, 99, 99);\n * ```\n */\nexport class JPSPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private readonly width: number;\n private readonly height: number;\n\n private openList: BinaryHeap<JPSNode>;\n private nodeGrid: (JPSNode | null)[][];\n\n constructor(map: IPathfindingMap) {\n this.map = map;\n\n // 获取地图尺寸\n const bounds = this.getMapBounds();\n this.width = bounds.width;\n this.height = bounds.height;\n\n this.openList = new BinaryHeap<JPSNode>((a, b) => a.f - b.f);\n this.nodeGrid = [];\n }\n\n /**\n * @zh 寻找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: Partial<IPathfindingOptions>\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n // 验证起点和终点\n if (!this.map.isWalkable(startX, startY) || !this.map.isWalkable(endX, endY)) {\n return EMPTY_PATH_RESULT;\n }\n\n // 相同位置\n if (startX === endX && startY === endY) {\n return {\n found: true,\n path: [{ x: startX, y: startY }],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n // 初始化\n this.initGrid();\n this.openList.clear();\n\n const startNode = this.getOrCreateNode(startX, startY);\n startNode.g = 0;\n startNode.h = this.heuristic(startX, startY, endX, endY) * opts.heuristicWeight;\n startNode.f = startNode.h;\n this.openList.push(startNode);\n\n let nodesSearched = 0;\n\n while (!this.openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = this.openList.pop()!;\n current.closed = true;\n nodesSearched++;\n\n // 到达终点\n if (current.x === endX && current.y === endY) {\n return {\n found: true,\n path: this.buildPath(current),\n cost: current.g,\n nodesSearched\n };\n }\n\n // 查找跳跃点\n this.identifySuccessors(current, endX, endY, opts);\n }\n\n return {\n found: false,\n path: [],\n cost: 0,\n nodesSearched\n };\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.openList.clear();\n this.nodeGrid = [];\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n /**\n * @zh 获取地图边界\n * @en Get map bounds\n */\n private getMapBounds(): { width: number; height: number } {\n // 尝试从地图获取尺寸\n const mapAny = this.map as any;\n if (typeof mapAny.width === 'number' && typeof mapAny.height === 'number') {\n return { width: mapAny.width, height: mapAny.height };\n }\n // 默认尺寸\n return { width: 1000, height: 1000 };\n }\n\n /**\n * @zh 初始化节点网格\n * @en Initialize node grid\n */\n private initGrid(): void {\n this.nodeGrid = [];\n for (let i = 0; i < this.width; i++) {\n this.nodeGrid[i] = [];\n }\n }\n\n /**\n * @zh 获取或创建节点\n * @en Get or create node\n */\n private getOrCreateNode(x: number, y: number): JPSNode {\n // Bounds check to ensure valid array indices\n const xi = x | 0;\n const yi = y | 0;\n if (xi < 0 || xi >= this.width || yi < 0 || yi >= this.height) {\n throw new Error('[JPSPathfinder] Invalid grid coordinates');\n }\n if (!this.nodeGrid[xi]) {\n this.nodeGrid[xi] = [];\n }\n if (!this.nodeGrid[xi][yi]) {\n this.nodeGrid[xi][yi] = {\n x: xi,\n y: yi,\n g: Infinity,\n h: 0,\n f: Infinity,\n parent: null,\n closed: false\n };\n }\n return this.nodeGrid[xi][yi]!;\n }\n\n /**\n * @zh 启发式函数(八方向距离)\n * @en Heuristic function (octile distance)\n */\n private heuristic(x1: number, y1: number, x2: number, y2: number): number {\n const dx = Math.abs(x1 - x2);\n const dy = Math.abs(y1 - y2);\n return dx + dy + (Math.SQRT2 - 2) * Math.min(dx, dy);\n }\n\n /**\n * @zh 识别后继节点(跳跃点)\n * @en Identify successors (jump points)\n */\n private identifySuccessors(\n node: JPSNode,\n endX: number,\n endY: number,\n opts: Required<IPathfindingOptions>\n ): void {\n const neighbors = this.findNeighbors(node);\n\n for (const neighbor of neighbors) {\n const jumpPoint = this.jump(\n neighbor.x,\n neighbor.y,\n node.x,\n node.y,\n endX,\n endY\n );\n\n if (jumpPoint) {\n const jx = jumpPoint.x;\n const jy = jumpPoint.y;\n\n const jpNode = this.getOrCreateNode(jx, jy);\n if (jpNode.closed) continue;\n\n const dx = Math.abs(jx - node.x);\n const dy = Math.abs(jy - node.y);\n const distance = Math.sqrt(dx * dx + dy * dy);\n const tentativeG = node.g + distance;\n\n if (tentativeG < jpNode.g) {\n jpNode.g = tentativeG;\n jpNode.h = this.heuristic(jx, jy, endX, endY) * opts.heuristicWeight;\n jpNode.f = jpNode.g + jpNode.h;\n jpNode.parent = node;\n\n if (!this.openList.contains(jpNode)) {\n this.openList.push(jpNode);\n } else {\n this.openList.update(jpNode);\n }\n }\n }\n }\n }\n\n /**\n * @zh 查找邻居(根据父节点方向剪枝)\n * @en Find neighbors (pruned based on parent direction)\n */\n private findNeighbors(node: JPSNode): IPoint[] {\n const { x, y, parent } = node;\n const neighbors: IPoint[] = [];\n\n // 无父节点,返回所有可通行邻居\n if (!parent) {\n for (let dx = -1; dx <= 1; dx++) {\n for (let dy = -1; dy <= 1; dy++) {\n if (dx === 0 && dy === 0) continue;\n const nx = x + dx;\n const ny = y + dy;\n if (this.isWalkableAt(nx, ny)) {\n // 对角线移动检查\n if (dx !== 0 && dy !== 0) {\n if (this.isWalkableAt(x + dx, y) || this.isWalkableAt(x, y + dy)) {\n neighbors.push({ x: nx, y: ny });\n }\n } else {\n neighbors.push({ x: nx, y: ny });\n }\n }\n }\n }\n return neighbors;\n }\n\n // 有父节点,根据方向剪枝\n const dx = Math.sign(x - parent.x);\n const dy = Math.sign(y - parent.y);\n\n // 对角线移动\n if (dx !== 0 && dy !== 0) {\n // 自然邻居\n if (this.isWalkableAt(x, y + dy)) {\n neighbors.push({ x, y: y + dy });\n }\n if (this.isWalkableAt(x + dx, y)) {\n neighbors.push({ x: x + dx, y });\n }\n if (this.isWalkableAt(x, y + dy) || this.isWalkableAt(x + dx, y)) {\n if (this.isWalkableAt(x + dx, y + dy)) {\n neighbors.push({ x: x + dx, y: y + dy });\n }\n }\n\n // 强制邻居\n if (!this.isWalkableAt(x - dx, y) && this.isWalkableAt(x, y + dy)) {\n if (this.isWalkableAt(x - dx, y + dy)) {\n neighbors.push({ x: x - dx, y: y + dy });\n }\n }\n if (!this.isWalkableAt(x, y - dy) && this.isWalkableAt(x + dx, y)) {\n if (this.isWalkableAt(x + dx, y - dy)) {\n neighbors.push({ x: x + dx, y: y - dy });\n }\n }\n }\n // 水平移动\n else if (dx !== 0) {\n if (this.isWalkableAt(x + dx, y)) {\n neighbors.push({ x: x + dx, y });\n\n // 强制邻居\n if (!this.isWalkableAt(x, y + 1) && this.isWalkableAt(x + dx, y + 1)) {\n neighbors.push({ x: x + dx, y: y + 1 });\n }\n if (!this.isWalkableAt(x, y - 1) && this.isWalkableAt(x + dx, y - 1)) {\n neighbors.push({ x: x + dx, y: y - 1 });\n }\n }\n }\n // 垂直移动\n else if (dy !== 0) {\n if (this.isWalkableAt(x, y + dy)) {\n neighbors.push({ x, y: y + dy });\n\n // 强制邻居\n if (!this.isWalkableAt(x + 1, y) && this.isWalkableAt(x + 1, y + dy)) {\n neighbors.push({ x: x + 1, y: y + dy });\n }\n if (!this.isWalkableAt(x - 1, y) && this.isWalkableAt(x - 1, y + dy)) {\n neighbors.push({ x: x - 1, y: y + dy });\n }\n }\n }\n\n return neighbors;\n }\n\n /**\n * @zh 跳跃函数(迭代版本,避免递归开销)\n * @en Jump function (iterative version to avoid recursion overhead)\n */\n private jump(\n startX: number,\n startY: number,\n px: number,\n py: number,\n endX: number,\n endY: number\n ): IPoint | null {\n const dx = startX - px;\n const dy = startY - py;\n\n let x = startX;\n let y = startY;\n\n while (true) {\n if (!this.isWalkableAt(x, y)) {\n return null;\n }\n\n if (x === endX && y === endY) {\n return { x, y };\n }\n\n if (dx !== 0 && dy !== 0) {\n if ((this.isWalkableAt(x - dx, y + dy) && !this.isWalkableAt(x - dx, y)) ||\n (this.isWalkableAt(x + dx, y - dy) && !this.isWalkableAt(x, y - dy))) {\n return { x, y };\n }\n\n if (this.jumpStraight(x + dx, y, dx, 0, endX, endY) ||\n this.jumpStraight(x, y + dy, 0, dy, endX, endY)) {\n return { x, y };\n }\n\n if (!this.isWalkableAt(x + dx, y) && !this.isWalkableAt(x, y + dy)) {\n return null;\n }\n } else if (dx !== 0) {\n if ((this.isWalkableAt(x + dx, y + 1) && !this.isWalkableAt(x, y + 1)) ||\n (this.isWalkableAt(x + dx, y - 1) && !this.isWalkableAt(x, y - 1))) {\n return { x, y };\n }\n } else if (dy !== 0) {\n if ((this.isWalkableAt(x + 1, y + dy) && !this.isWalkableAt(x + 1, y)) ||\n (this.isWalkableAt(x - 1, y + dy) && !this.isWalkableAt(x - 1, y))) {\n return { x, y };\n }\n }\n\n x += dx;\n y += dy;\n }\n }\n\n /**\n * @zh 直线跳跃(水平或垂直方向)\n * @en Straight jump (horizontal or vertical direction)\n */\n private jumpStraight(\n startX: number,\n startY: number,\n dx: number,\n dy: number,\n endX: number,\n endY: number\n ): boolean {\n let x = startX;\n let y = startY;\n\n while (true) {\n if (!this.isWalkableAt(x, y)) {\n return false;\n }\n\n if (x === endX && y === endY) {\n return true;\n }\n\n if (dx !== 0) {\n if ((this.isWalkableAt(x + dx, y + 1) && !this.isWalkableAt(x, y + 1)) ||\n (this.isWalkableAt(x + dx, y - 1) && !this.isWalkableAt(x, y - 1))) {\n return true;\n }\n } else if (dy !== 0) {\n if ((this.isWalkableAt(x + 1, y + dy) && !this.isWalkableAt(x + 1, y)) ||\n (this.isWalkableAt(x - 1, y + dy) && !this.isWalkableAt(x - 1, y))) {\n return true;\n }\n }\n\n x += dx;\n y += dy;\n }\n }\n\n /**\n * @zh 检查位置是否可通行\n * @en Check if position is walkable\n */\n private isWalkableAt(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return this.map.isWalkable(x, y);\n }\n\n /**\n * @zh 构建路径\n * @en Build path\n */\n private buildPath(endNode: JPSNode): IPoint[] {\n const path: IPoint[] = [];\n let current: JPSNode | null = endNode;\n\n while (current) {\n path.unshift({ x: current.x, y: current.y });\n current = current.parent;\n }\n\n // 插值跳跃点之间的路径\n return this.interpolatePath(path);\n }\n\n /**\n * @zh 插值路径(在跳跃点之间填充中间点)\n * @en Interpolate path (fill intermediate points between jump points)\n */\n private interpolatePath(jumpPoints: IPoint[]): IPoint[] {\n if (jumpPoints.length < 2) {\n return jumpPoints;\n }\n\n const path: IPoint[] = [jumpPoints[0]];\n\n for (let i = 1; i < jumpPoints.length; i++) {\n const prev = jumpPoints[i - 1];\n const curr = jumpPoints[i];\n\n const dx = curr.x - prev.x;\n const dy = curr.y - prev.y;\n const steps = Math.max(Math.abs(dx), Math.abs(dy));\n\n const stepX = dx === 0 ? 0 : dx / Math.abs(dx);\n const stepY = dy === 0 ? 0 : dy / Math.abs(dy);\n\n let x = prev.x;\n let y = prev.y;\n\n for (let j = 0; j < steps; j++) {\n // 优先对角移动\n if (x !== curr.x && y !== curr.y) {\n x += stepX;\n y += stepY;\n } else if (x !== curr.x) {\n x += stepX;\n } else if (y !== curr.y) {\n y += stepY;\n }\n\n if (x !== prev.x || y !== prev.y) {\n path.push({ x, y });\n }\n }\n }\n\n return path;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 JPS 寻路器\n * @en Create JPS pathfinder\n *\n * @param map - @zh 寻路地图实例 @en Pathfinding map instance\n * @returns @zh JPS 寻路器实例 @en JPS pathfinder instance\n */\nexport function createJPSPathfinder(map: IPathfindingMap): JPSPathfinder {\n return new JPSPathfinder(map);\n}\n","/**\n * @zh HPA* (Hierarchical Pathfinding A*) 寻路算法实现\n * @en HPA* (Hierarchical Pathfinding A*) Pathfinding Algorithm Implementation\n *\n * @zh HPA* 是一种分层寻路算法,适用于超大地图 (1000x1000+)\n * @en HPA* is a hierarchical pathfinding algorithm suitable for very large maps (1000x1000+)\n *\n * @zh 工作原理:\n * 1. 将地图划分为集群 (clusters)\n * 2. 在集群边界检测入口点 (entrances)\n * 3. 构建抽象图 (abstract graph) 连接入口点\n * 4. 先在抽象图上寻路,再细化为详细路径\n *\n * @en How it works:\n * 1. Divide map into clusters\n * 2. Detect entrances at cluster boundaries\n * 3. Build abstract graph connecting entrances\n * 4. First find path on abstract graph, then refine to detailed path\n */\n\nimport { BinaryHeap } from './BinaryHeap';\nimport type {\n IPathfindingMap,\n IPoint,\n IPathResult,\n IPathfinder,\n IPathfindingOptions\n} from './IPathfinding';\nimport { DEFAULT_PATHFINDING_OPTIONS, EMPTY_PATH_RESULT } from './IPathfinding';\nimport { AStarPathfinder } from './AStarPathfinder';\n\n// =============================================================================\n// 配置 | Configuration\n// =============================================================================\n\n/**\n * @zh HPA* 配置\n * @en HPA* Configuration\n */\nexport interface IHPAConfig {\n /**\n * @zh 集群大小(边长)\n * @en Cluster size (side length)\n */\n clusterSize: number;\n\n /**\n * @zh 最大入口宽度(超过此宽度会拆分为多个入口)\n * @en Maximum entrance width (entrances wider than this will be split)\n */\n maxEntranceWidth: number;\n\n /**\n * @zh 是否启用内部路径缓存\n * @en Whether to enable internal path caching\n */\n cacheInternalPaths: boolean;\n}\n\n/**\n * @zh 默认 HPA* 配置\n * @en Default HPA* configuration\n */\nexport const DEFAULT_HPA_CONFIG: IHPAConfig = {\n clusterSize: 10,\n maxEntranceWidth: 6,\n cacheInternalPaths: true\n};\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\n/**\n * @zh 集群\n * @en Cluster\n */\ninterface Cluster {\n id: number;\n x: number;\n y: number;\n width: number;\n height: number;\n entrances: Entrance[];\n}\n\n/**\n * @zh 入口(集群之间的连接点)\n * @en Entrance (connection point between clusters)\n */\ninterface Entrance {\n id: number;\n cluster1Id: number;\n cluster2Id: number;\n point1: IPoint;\n point2: IPoint;\n center: IPoint;\n}\n\n/**\n * @zh 抽象节点\n * @en Abstract node\n */\ninterface AbstractNode {\n id: number;\n position: IPoint;\n clusterId: number;\n entranceId: number;\n edges: AbstractEdge[];\n}\n\n/**\n * @zh 抽象边\n * @en Abstract edge\n */\ninterface AbstractEdge {\n targetNodeId: number;\n cost: number;\n isInterEdge: boolean;\n}\n\n/**\n * @zh A* 搜索节点\n * @en A* search node\n */\ninterface SearchNode {\n abstractNode: AbstractNode;\n g: number;\n h: number;\n f: number;\n parent: SearchNode | null;\n}\n\n// =============================================================================\n// HPA* 寻路器 | HPA* Pathfinder\n// =============================================================================\n\n/**\n * @zh HPA* 寻路器\n * @en HPA* Pathfinder\n *\n * @zh 适用于超大地图的分层寻路算法\n * @en Hierarchical pathfinding algorithm for very large maps\n *\n * @example\n * ```typescript\n * const map = createGridMap(1000, 1000);\n * const pathfinder = new HPAPathfinder(map, { clusterSize: 20 });\n *\n * // Preprocess (do once after map changes)\n * pathfinder.preprocess();\n *\n * // Find path\n * const result = pathfinder.findPath(0, 0, 999, 999);\n * ```\n */\nexport class HPAPathfinder implements IPathfinder {\n private readonly map: IPathfindingMap;\n private readonly config: IHPAConfig;\n private readonly width: number;\n private readonly height: number;\n\n private clusters: Cluster[] = [];\n private entrances: Entrance[] = [];\n private abstractNodes: Map<number, AbstractNode> = new Map();\n private clusterGrid: (Cluster | null)[][] = [];\n\n private nextEntranceId: number = 0;\n private nextNodeId: number = 0;\n\n private internalPathCache: Map<string, IPoint[]> = new Map();\n private localPathfinder: AStarPathfinder;\n\n private preprocessed: boolean = false;\n\n constructor(map: IPathfindingMap, config?: Partial<IHPAConfig>) {\n this.map = map;\n this.config = { ...DEFAULT_HPA_CONFIG, ...config };\n\n const bounds = this.getMapBounds();\n this.width = bounds.width;\n this.height = bounds.height;\n\n this.localPathfinder = new AStarPathfinder(map);\n }\n\n /**\n * @zh 预处理地图(构建抽象图)\n * @en Preprocess map (build abstract graph)\n *\n * @zh 在地图变化后需要重新调用\n * @en Need to call again after map changes\n */\n preprocess(): void {\n this.clusters = [];\n this.entrances = [];\n this.abstractNodes.clear();\n this.clusterGrid = [];\n this.internalPathCache.clear();\n this.nextEntranceId = 0;\n this.nextNodeId = 0;\n\n this.buildClusters();\n this.findEntrances();\n this.buildAbstractGraph();\n\n this.preprocessed = true;\n }\n\n /**\n * @zh 寻找路径\n * @en Find path\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: Partial<IPathfindingOptions>\n ): IPathResult {\n if (!this.preprocessed) {\n this.preprocess();\n }\n\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n if (!this.map.isWalkable(startX, startY) || !this.map.isWalkable(endX, endY)) {\n return EMPTY_PATH_RESULT;\n }\n\n if (startX === endX && startY === endY) {\n return {\n found: true,\n path: [{ x: startX, y: startY }],\n cost: 0,\n nodesSearched: 1\n };\n }\n\n const startCluster = this.getClusterAt(startX, startY);\n const endCluster = this.getClusterAt(endX, endY);\n\n if (!startCluster || !endCluster) {\n return EMPTY_PATH_RESULT;\n }\n\n if (startCluster.id === endCluster.id) {\n return this.findLocalPath(startX, startY, endX, endY, opts);\n }\n\n const startNodes = this.insertTemporaryNode(startX, startY, startCluster);\n const endNodes = this.insertTemporaryNode(endX, endY, endCluster);\n\n const abstractPath = this.searchAbstractGraph(startNodes, endNodes, opts);\n\n this.removeTemporaryNodes(startNodes);\n this.removeTemporaryNodes(endNodes);\n\n if (!abstractPath || abstractPath.length === 0) {\n return EMPTY_PATH_RESULT;\n }\n\n return this.refinePath(abstractPath, startX, startY, endX, endY, opts);\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.clusters = [];\n this.entrances = [];\n this.abstractNodes.clear();\n this.clusterGrid = [];\n this.internalPathCache.clear();\n this.preprocessed = false;\n }\n\n /**\n * @zh 通知地图区域变化\n * @en Notify map region change\n */\n notifyRegionChange(minX: number, minY: number, maxX: number, maxY: number): void {\n this.preprocessed = false;\n this.internalPathCache.clear();\n }\n\n /**\n * @zh 获取预处理统计信息\n * @en Get preprocessing statistics\n */\n getStats(): {\n clusters: number;\n entrances: number;\n abstractNodes: number;\n cacheSize: number;\n } {\n return {\n clusters: this.clusters.length,\n entrances: this.entrances.length,\n abstractNodes: this.abstractNodes.size,\n cacheSize: this.internalPathCache.size\n };\n }\n\n // =========================================================================\n // 预处理方法 | Preprocessing Methods\n // =========================================================================\n\n private getMapBounds(): { width: number; height: number } {\n const mapAny = this.map as any;\n if (typeof mapAny.width === 'number' && typeof mapAny.height === 'number') {\n return { width: mapAny.width, height: mapAny.height };\n }\n return { width: 1000, height: 1000 };\n }\n\n private buildClusters(): void {\n const clusterSize = this.config.clusterSize;\n const clustersX = Math.ceil(this.width / clusterSize);\n const clustersY = Math.ceil(this.height / clusterSize);\n\n this.clusterGrid = [];\n for (let x = 0; x < clustersX; x++) {\n this.clusterGrid[x] = [];\n }\n\n let clusterId = 0;\n for (let cy = 0; cy < clustersY; cy++) {\n for (let cx = 0; cx < clustersX; cx++) {\n const cluster: Cluster = {\n id: clusterId++,\n x: cx * clusterSize,\n y: cy * clusterSize,\n width: Math.min(clusterSize, this.width - cx * clusterSize),\n height: Math.min(clusterSize, this.height - cy * clusterSize),\n entrances: []\n };\n this.clusters.push(cluster);\n this.clusterGrid[cx][cy] = cluster;\n }\n }\n }\n\n private findEntrances(): void {\n const clusterSize = this.config.clusterSize;\n const clustersX = Math.ceil(this.width / clusterSize);\n const clustersY = Math.ceil(this.height / clusterSize);\n\n for (let cy = 0; cy < clustersY; cy++) {\n for (let cx = 0; cx < clustersX; cx++) {\n const cluster = this.clusterGrid[cx][cy];\n if (!cluster) continue;\n\n if (cx < clustersX - 1) {\n const rightCluster = this.clusterGrid[cx + 1]?.[cy];\n if (rightCluster) {\n this.findEntrancesBetween(cluster, rightCluster, 'horizontal');\n }\n }\n\n if (cy < clustersY - 1) {\n const bottomCluster = this.clusterGrid[cx]?.[cy + 1];\n if (bottomCluster) {\n this.findEntrancesBetween(cluster, bottomCluster, 'vertical');\n }\n }\n }\n }\n }\n\n private findEntrancesBetween(\n cluster1: Cluster,\n cluster2: Cluster,\n direction: 'horizontal' | 'vertical'\n ): void {\n const maxWidth = this.config.maxEntranceWidth;\n let entranceStart: number | null = null;\n let entranceLength = 0;\n\n if (direction === 'horizontal') {\n const x1 = cluster1.x + cluster1.width - 1;\n const x2 = cluster2.x;\n const startY = Math.max(cluster1.y, cluster2.y);\n const endY = Math.min(cluster1.y + cluster1.height, cluster2.y + cluster2.height);\n\n for (let y = startY; y < endY; y++) {\n const walkable1 = this.map.isWalkable(x1, y);\n const walkable2 = this.map.isWalkable(x2, y);\n\n if (walkable1 && walkable2) {\n if (entranceStart === null) {\n entranceStart = y;\n entranceLength = 1;\n } else {\n entranceLength++;\n }\n\n if (entranceLength >= maxWidth || y === endY - 1) {\n this.createEntrance(cluster1, cluster2, x1, x2, entranceStart, entranceStart + entranceLength - 1, 'horizontal');\n entranceStart = null;\n entranceLength = 0;\n }\n } else if (entranceStart !== null) {\n this.createEntrance(cluster1, cluster2, x1, x2, entranceStart, entranceStart + entranceLength - 1, 'horizontal');\n entranceStart = null;\n entranceLength = 0;\n }\n }\n } else {\n const y1 = cluster1.y + cluster1.height - 1;\n const y2 = cluster2.y;\n const startX = Math.max(cluster1.x, cluster2.x);\n const endX = Math.min(cluster1.x + cluster1.width, cluster2.x + cluster2.width);\n\n for (let x = startX; x < endX; x++) {\n const walkable1 = this.map.isWalkable(x, y1);\n const walkable2 = this.map.isWalkable(x, y2);\n\n if (walkable1 && walkable2) {\n if (entranceStart === null) {\n entranceStart = x;\n entranceLength = 1;\n } else {\n entranceLength++;\n }\n\n if (entranceLength >= maxWidth || x === endX - 1) {\n this.createEntrance(cluster1, cluster2, entranceStart, entranceStart + entranceLength - 1, y1, y2, 'vertical');\n entranceStart = null;\n entranceLength = 0;\n }\n } else if (entranceStart !== null) {\n this.createEntrance(cluster1, cluster2, entranceStart, entranceStart + entranceLength - 1, y1, y2, 'vertical');\n entranceStart = null;\n entranceLength = 0;\n }\n }\n }\n }\n\n private createEntrance(\n cluster1: Cluster,\n cluster2: Cluster,\n coord1Start: number,\n coord1End: number,\n coord2Start: number,\n coord2End: number,\n direction: 'horizontal' | 'vertical'\n ): void {\n let point1: IPoint;\n let point2: IPoint;\n let center: IPoint;\n\n if (direction === 'horizontal') {\n const midY = Math.floor((coord1Start + coord1End) / 2);\n point1 = { x: coord1Start, y: midY };\n point2 = { x: coord2Start, y: midY };\n center = { x: coord1Start, y: midY };\n } else {\n const midX = Math.floor((coord1Start + coord1End) / 2);\n point1 = { x: midX, y: coord2Start };\n point2 = { x: midX, y: coord2End };\n center = { x: midX, y: coord2Start };\n }\n\n const entrance: Entrance = {\n id: this.nextEntranceId++,\n cluster1Id: cluster1.id,\n cluster2Id: cluster2.id,\n point1,\n point2,\n center\n };\n\n this.entrances.push(entrance);\n cluster1.entrances.push(entrance);\n cluster2.entrances.push(entrance);\n }\n\n private buildAbstractGraph(): void {\n for (const entrance of this.entrances) {\n const node1 = this.createAbstractNode(entrance.point1, entrance.cluster1Id, entrance.id);\n const node2 = this.createAbstractNode(entrance.point2, entrance.cluster2Id, entrance.id);\n\n node1.edges.push({ targetNodeId: node2.id, cost: 1, isInterEdge: true });\n node2.edges.push({ targetNodeId: node1.id, cost: 1, isInterEdge: true });\n }\n\n for (const cluster of this.clusters) {\n this.connectIntraClusterNodes(cluster);\n }\n }\n\n private createAbstractNode(position: IPoint, clusterId: number, entranceId: number): AbstractNode {\n const node: AbstractNode = {\n id: this.nextNodeId++,\n position,\n clusterId,\n entranceId,\n edges: []\n };\n this.abstractNodes.set(node.id, node);\n return node;\n }\n\n private connectIntraClusterNodes(cluster: Cluster): void {\n const nodesInCluster: AbstractNode[] = [];\n\n for (const node of this.abstractNodes.values()) {\n if (node.clusterId === cluster.id) {\n nodesInCluster.push(node);\n }\n }\n\n for (let i = 0; i < nodesInCluster.length; i++) {\n for (let j = i + 1; j < nodesInCluster.length; j++) {\n const node1 = nodesInCluster[i];\n const node2 = nodesInCluster[j];\n\n const cost = this.heuristic(node1.position, node2.position);\n node1.edges.push({ targetNodeId: node2.id, cost, isInterEdge: false });\n node2.edges.push({ targetNodeId: node1.id, cost, isInterEdge: false });\n }\n }\n }\n\n // =========================================================================\n // 搜索方法 | Search Methods\n // =========================================================================\n\n private getClusterAt(x: number, y: number): Cluster | null {\n const clusterSize = this.config.clusterSize;\n const cx = Math.floor(x / clusterSize);\n const cy = Math.floor(y / clusterSize);\n return this.clusterGrid[cx]?.[cy] ?? null;\n }\n\n private insertTemporaryNode(\n x: number,\n y: number,\n cluster: Cluster\n ): AbstractNode[] {\n const tempNodes: AbstractNode[] = [];\n const tempNode = this.createAbstractNode({ x, y }, cluster.id, -1);\n tempNodes.push(tempNode);\n\n for (const node of this.abstractNodes.values()) {\n if (node.clusterId === cluster.id && node.id !== tempNode.id) {\n const cost = this.heuristic({ x, y }, node.position);\n tempNode.edges.push({ targetNodeId: node.id, cost, isInterEdge: false });\n node.edges.push({ targetNodeId: tempNode.id, cost, isInterEdge: false });\n }\n }\n\n return tempNodes;\n }\n\n private removeTemporaryNodes(nodes: AbstractNode[]): void {\n for (const node of nodes) {\n for (const edge of node.edges) {\n const targetNode = this.abstractNodes.get(edge.targetNodeId);\n if (targetNode) {\n targetNode.edges = targetNode.edges.filter(e => e.targetNodeId !== node.id);\n }\n }\n this.abstractNodes.delete(node.id);\n }\n }\n\n private searchAbstractGraph(\n startNodes: AbstractNode[],\n endNodes: AbstractNode[],\n opts: Required<IPathfindingOptions>\n ): AbstractNode[] | null {\n if (startNodes.length === 0 || endNodes.length === 0) {\n return null;\n }\n\n const endNodeIds = new Set(endNodes.map(n => n.id));\n const openList = new BinaryHeap<SearchNode>((a, b) => a.f - b.f);\n const closedSet = new Set<number>();\n\n for (const startNode of startNodes) {\n const h = this.heuristic(startNode.position, endNodes[0].position);\n openList.push({\n abstractNode: startNode,\n g: 0,\n h: h * opts.heuristicWeight,\n f: h * opts.heuristicWeight,\n parent: null\n });\n }\n\n let nodesSearched = 0;\n\n while (!openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = openList.pop()!;\n nodesSearched++;\n\n if (endNodeIds.has(current.abstractNode.id)) {\n return this.reconstructAbstractPath(current);\n }\n\n if (closedSet.has(current.abstractNode.id)) {\n continue;\n }\n closedSet.add(current.abstractNode.id);\n\n for (const edge of current.abstractNode.edges) {\n if (closedSet.has(edge.targetNodeId)) {\n continue;\n }\n\n const neighbor = this.abstractNodes.get(edge.targetNodeId);\n if (!neighbor) continue;\n\n const tentativeG = current.g + edge.cost;\n const h = this.heuristic(neighbor.position, endNodes[0].position) * opts.heuristicWeight;\n\n openList.push({\n abstractNode: neighbor,\n g: tentativeG,\n h,\n f: tentativeG + h,\n parent: current\n });\n }\n }\n\n return null;\n }\n\n private reconstructAbstractPath(endNode: SearchNode): AbstractNode[] {\n const path: AbstractNode[] = [];\n let current: SearchNode | null = endNode;\n\n while (current) {\n path.unshift(current.abstractNode);\n current = current.parent;\n }\n\n return path;\n }\n\n private refinePath(\n abstractPath: AbstractNode[],\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n opts: Required<IPathfindingOptions>\n ): IPathResult {\n const fullPath: IPoint[] = [];\n let totalCost = 0;\n let nodesSearched = abstractPath.length;\n\n let currentX = startX;\n let currentY = startY;\n\n for (let i = 0; i < abstractPath.length; i++) {\n const node = abstractPath[i];\n const targetX = i === abstractPath.length - 1 ? endX : node.position.x;\n const targetY = i === abstractPath.length - 1 ? endY : node.position.y;\n\n if (currentX !== targetX || currentY !== targetY) {\n const segment = this.localPathfinder.findPath(currentX, currentY, targetX, targetY, opts);\n\n if (!segment.found) {\n if (fullPath.length > 0) {\n return {\n found: true,\n path: fullPath,\n cost: totalCost,\n nodesSearched\n };\n }\n return EMPTY_PATH_RESULT;\n }\n\n for (let j = fullPath.length === 0 ? 0 : 1; j < segment.path.length; j++) {\n fullPath.push(segment.path[j]);\n }\n\n totalCost += segment.cost;\n nodesSearched += segment.nodesSearched;\n }\n\n currentX = targetX;\n currentY = targetY;\n }\n\n if (currentX !== endX || currentY !== endY) {\n const finalSegment = this.localPathfinder.findPath(currentX, currentY, endX, endY, opts);\n if (finalSegment.found) {\n for (let j = 1; j < finalSegment.path.length; j++) {\n fullPath.push(finalSegment.path[j]);\n }\n totalCost += finalSegment.cost;\n nodesSearched += finalSegment.nodesSearched;\n }\n }\n\n return {\n found: fullPath.length > 0,\n path: fullPath,\n cost: totalCost,\n nodesSearched\n };\n }\n\n // =========================================================================\n // 辅助方法 | Helper Methods\n // =========================================================================\n\n private findLocalPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n opts: Required<IPathfindingOptions>\n ): IPathResult {\n return this.localPathfinder.findPath(startX, startY, endX, endY, opts);\n }\n\n private findInternalPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n cluster: Cluster\n ): IPoint[] | null {\n const cacheKey = `${cluster.id}:${startX},${startY}->${endX},${endY}`;\n\n if (this.config.cacheInternalPaths) {\n const cached = this.internalPathCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n }\n\n const result = this.localPathfinder.findPath(startX, startY, endX, endY);\n\n if (result.found && this.config.cacheInternalPaths) {\n this.internalPathCache.set(cacheKey, [...result.path]);\n }\n\n return result.found ? [...result.path] : null;\n }\n\n private calculatePathCost(path: IPoint[]): number {\n let cost = 0;\n for (let i = 1; i < path.length; i++) {\n const dx = Math.abs(path[i].x - path[i - 1].x);\n const dy = Math.abs(path[i].y - path[i - 1].y);\n cost += dx !== 0 && dy !== 0 ? Math.SQRT2 : 1;\n }\n return cost;\n }\n\n private heuristic(a: IPoint, b: IPoint): number {\n const dx = Math.abs(a.x - b.x);\n const dy = Math.abs(a.y - b.y);\n return dx + dy + (Math.SQRT2 - 2) * Math.min(dx, dy);\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建 HPA* 寻路器\n * @en Create HPA* pathfinder\n *\n * @param map - @zh 寻路地图实例 @en Pathfinding map instance\n * @param config - @zh HPA* 配置 @en HPA* configuration\n * @returns @zh HPA* 寻路器实例 @en HPA* pathfinder instance\n */\nexport function createHPAPathfinder(\n map: IPathfindingMap,\n config?: Partial<IHPAConfig>\n): HPAPathfinder {\n return new HPAPathfinder(map, config);\n}\n","/**\n * @zh 导航网格实现\n * @en NavMesh Implementation\n */\n\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n IPathResult,\n IPathfindingOptions\n} from '../core/IPathfinding';\nimport { createPoint, euclideanDistance, EMPTY_PATH_RESULT, DEFAULT_PATHFINDING_OPTIONS } from '../core/IPathfinding';\nimport { BinaryHeap } from '../core/BinaryHeap';\n\n// =============================================================================\n// 导航多边形 | Navigation Polygon\n// =============================================================================\n\n/**\n * @zh 导航多边形\n * @en Navigation polygon\n */\nexport interface INavPolygon {\n /** @zh 多边形ID @en Polygon ID */\n readonly id: number;\n /** @zh 顶点列表 @en Vertex list */\n readonly vertices: readonly IPoint[];\n /** @zh 中心点 @en Center point */\n readonly center: IPoint;\n /** @zh 邻居多边形ID @en Neighbor polygon IDs */\n readonly neighbors: readonly number[];\n /** @zh 到邻居的共享边 @en Shared edges to neighbors */\n readonly portals: ReadonlyMap<number, IPortal>;\n}\n\n/**\n * @zh 入口(两个多边形之间的共享边)\n * @en Portal (shared edge between two polygons)\n */\nexport interface IPortal {\n /** @zh 边的左端点 @en Left endpoint of edge */\n readonly left: IPoint;\n /** @zh 边的右端点 @en Right endpoint of edge */\n readonly right: IPoint;\n}\n\n// =============================================================================\n// 导航网格节点 | NavMesh Node\n// =============================================================================\n\n/**\n * @zh 导航网格节点(包装多边形)\n * @en NavMesh node (wraps polygon)\n */\nclass NavMeshNode implements IPathNode {\n readonly id: number;\n readonly position: IPoint;\n readonly cost: number;\n readonly walkable: boolean;\n readonly polygon: INavPolygon;\n\n constructor(polygon: INavPolygon) {\n this.id = polygon.id;\n this.position = polygon.center;\n this.cost = 1;\n this.walkable = true;\n this.polygon = polygon;\n }\n}\n\n// =============================================================================\n// 导航网格 | Navigation Mesh\n// =============================================================================\n\n/**\n * @zh 导航网格\n * @en Navigation Mesh\n *\n * @zh 使用凸多边形网格进行高效寻路,适合复杂地形\n * @en Uses convex polygon mesh for efficient pathfinding, suitable for complex terrain\n *\n * @example\n * ```typescript\n * const navmesh = new NavMesh();\n *\n * // Add polygons\n * navmesh.addPolygon([\n * { x: 0, y: 0 }, { x: 10, y: 0 },\n * { x: 10, y: 10 }, { x: 0, y: 10 }\n * ]);\n *\n * // Build connections\n * navmesh.build();\n *\n * // Find path\n * const result = navmesh.findPath(1, 1, 8, 8);\n * ```\n */\nexport class NavMesh implements IPathfindingMap {\n private polygons: Map<number, INavPolygon> = new Map();\n private nodes: Map<number, NavMeshNode> = new Map();\n private nextId = 0;\n\n /**\n * @zh 添加导航多边形\n * @en Add navigation polygon\n *\n * @returns @zh 多边形ID @en Polygon ID\n */\n addPolygon(vertices: IPoint[], neighbors: number[] = []): number {\n const id = this.nextId++;\n const center = this.calculateCenter(vertices);\n\n const polygon: INavPolygon = {\n id,\n vertices,\n center,\n neighbors,\n portals: new Map()\n };\n\n this.polygons.set(id, polygon);\n this.nodes.set(id, new NavMeshNode(polygon));\n\n return id;\n }\n\n /**\n * @zh 设置两个多边形之间的连接\n * @en Set connection between two polygons\n */\n setConnection(\n polyA: number,\n polyB: number,\n portal: IPortal\n ): void {\n const polygonA = this.polygons.get(polyA);\n const polygonB = this.polygons.get(polyB);\n\n if (!polygonA || !polygonB) {\n return;\n }\n\n // Update neighbors and portals\n const neighborsA = [...polygonA.neighbors];\n const portalsA = new Map(polygonA.portals);\n\n if (!neighborsA.includes(polyB)) {\n neighborsA.push(polyB);\n }\n portalsA.set(polyB, portal);\n\n this.polygons.set(polyA, {\n ...polygonA,\n neighbors: neighborsA,\n portals: portalsA\n });\n\n // Reverse portal for the other direction\n const reversePortal: IPortal = {\n left: portal.right,\n right: portal.left\n };\n\n const neighborsB = [...polygonB.neighbors];\n const portalsB = new Map(polygonB.portals);\n\n if (!neighborsB.includes(polyA)) {\n neighborsB.push(polyA);\n }\n portalsB.set(polyA, reversePortal);\n\n this.polygons.set(polyB, {\n ...polygonB,\n neighbors: neighborsB,\n portals: portalsB\n });\n }\n\n /**\n * @zh 自动检测并建立相邻多边形的连接\n * @en Auto-detect and build connections between adjacent polygons\n */\n build(): void {\n const polygonList = Array.from(this.polygons.values());\n\n for (let i = 0; i < polygonList.length; i++) {\n for (let j = i + 1; j < polygonList.length; j++) {\n const polyA = polygonList[i];\n const polyB = polygonList[j];\n\n const sharedEdge = this.findSharedEdge(polyA.vertices, polyB.vertices);\n\n if (sharedEdge) {\n this.setConnection(polyA.id, polyB.id, sharedEdge);\n }\n }\n }\n }\n\n /**\n * @zh 查找两个多边形的共享边\n * @en Find shared edge between two polygons\n */\n private findSharedEdge(\n verticesA: readonly IPoint[],\n verticesB: readonly IPoint[]\n ): IPortal | null {\n const epsilon = 0.0001;\n\n for (let i = 0; i < verticesA.length; i++) {\n const a1 = verticesA[i];\n const a2 = verticesA[(i + 1) % verticesA.length];\n\n for (let j = 0; j < verticesB.length; j++) {\n const b1 = verticesB[j];\n const b2 = verticesB[(j + 1) % verticesB.length];\n\n // Check if edges match (in either direction)\n const match1 =\n Math.abs(a1.x - b2.x) < epsilon &&\n Math.abs(a1.y - b2.y) < epsilon &&\n Math.abs(a2.x - b1.x) < epsilon &&\n Math.abs(a2.y - b1.y) < epsilon;\n\n const match2 =\n Math.abs(a1.x - b1.x) < epsilon &&\n Math.abs(a1.y - b1.y) < epsilon &&\n Math.abs(a2.x - b2.x) < epsilon &&\n Math.abs(a2.y - b2.y) < epsilon;\n\n if (match1 || match2) {\n return {\n left: a1,\n right: a2\n };\n }\n }\n }\n\n return null;\n }\n\n /**\n * @zh 计算多边形中心\n * @en Calculate polygon center\n */\n private calculateCenter(vertices: readonly IPoint[]): IPoint {\n let x = 0;\n let y = 0;\n\n for (const v of vertices) {\n x += v.x;\n y += v.y;\n }\n\n return createPoint(x / vertices.length, y / vertices.length);\n }\n\n /**\n * @zh 查找包含点的多边形\n * @en Find polygon containing point\n */\n findPolygonAt(x: number, y: number): INavPolygon | null {\n for (const polygon of this.polygons.values()) {\n if (this.isPointInPolygon(x, y, polygon.vertices)) {\n return polygon;\n }\n }\n return null;\n }\n\n /**\n * @zh 检查点是否在多边形内\n * @en Check if point is inside polygon\n */\n private isPointInPolygon(x: number, y: number, vertices: readonly IPoint[]): boolean {\n let inside = false;\n const n = vertices.length;\n\n for (let i = 0, j = n - 1; i < n; j = i++) {\n const xi = vertices[i].x;\n const yi = vertices[i].y;\n const xj = vertices[j].x;\n const yj = vertices[j].y;\n\n if (\n yi > y !== yj > y &&\n x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n ) {\n inside = !inside;\n }\n }\n\n return inside;\n }\n\n // ==========================================================================\n // IPathfindingMap 接口实现 | IPathfindingMap Interface Implementation\n // ==========================================================================\n\n getNodeAt(x: number, y: number): IPathNode | null {\n const polygon = this.findPolygonAt(x, y);\n return polygon ? this.nodes.get(polygon.id) ?? null : null;\n }\n\n getNeighbors(node: IPathNode): IPathNode[] {\n const navNode = node as NavMeshNode;\n const neighbors: IPathNode[] = [];\n\n for (const neighborId of navNode.polygon.neighbors) {\n const neighbor = this.nodes.get(neighborId);\n if (neighbor) {\n neighbors.push(neighbor);\n }\n }\n\n return neighbors;\n }\n\n heuristic(a: IPoint, b: IPoint): number {\n return euclideanDistance(a, b);\n }\n\n getMovementCost(from: IPathNode, to: IPathNode): number {\n return euclideanDistance(from.position, to.position);\n }\n\n isWalkable(x: number, y: number): boolean {\n return this.findPolygonAt(x, y) !== null;\n }\n\n // ==========================================================================\n // 寻路 | Pathfinding\n // ==========================================================================\n\n /**\n * @zh 在导航网格上寻路\n * @en Find path on navigation mesh\n */\n findPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IPathfindingOptions\n ): IPathResult {\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n const startPolygon = this.findPolygonAt(startX, startY);\n const endPolygon = this.findPolygonAt(endX, endY);\n\n if (!startPolygon || !endPolygon) {\n return EMPTY_PATH_RESULT;\n }\n\n // Same polygon\n if (startPolygon.id === endPolygon.id) {\n return {\n found: true,\n path: [createPoint(startX, startY), createPoint(endX, endY)],\n cost: euclideanDistance(\n createPoint(startX, startY),\n createPoint(endX, endY)\n ),\n nodesSearched: 1\n };\n }\n\n // A* on polygon graph\n const polygonPath = this.findPolygonPath(startPolygon, endPolygon, opts);\n\n if (!polygonPath.found) {\n return EMPTY_PATH_RESULT;\n }\n\n // Convert polygon path to point path using funnel algorithm\n const start = createPoint(startX, startY);\n const end = createPoint(endX, endY);\n const pointPath = this.funnelPath(start, end, polygonPath.polygons);\n\n return {\n found: true,\n path: pointPath,\n cost: this.calculatePathLength(pointPath),\n nodesSearched: polygonPath.nodesSearched\n };\n }\n\n /**\n * @zh 在多边形图上寻路\n * @en Find path on polygon graph\n */\n private findPolygonPath(\n start: INavPolygon,\n end: INavPolygon,\n opts: Required<IPathfindingOptions>\n ): { found: boolean; polygons: INavPolygon[]; nodesSearched: number } {\n interface AStarState {\n polygon: INavPolygon;\n g: number;\n f: number;\n parent: AStarState | null;\n }\n\n const openList = new BinaryHeap<AStarState>((a, b) => a.f - b.f);\n const closed = new Set<number>();\n const states = new Map<number, AStarState>();\n\n const startState: AStarState = {\n polygon: start,\n g: 0,\n f: euclideanDistance(start.center, end.center) * opts.heuristicWeight,\n parent: null\n };\n\n states.set(start.id, startState);\n openList.push(startState);\n\n let nodesSearched = 0;\n\n while (!openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = openList.pop()!;\n nodesSearched++;\n\n if (current.polygon.id === end.id) {\n // Reconstruct path\n const path: INavPolygon[] = [];\n let state: AStarState | null = current;\n\n while (state) {\n path.unshift(state.polygon);\n state = state.parent;\n }\n\n return { found: true, polygons: path, nodesSearched };\n }\n\n closed.add(current.polygon.id);\n\n for (const neighborId of current.polygon.neighbors) {\n if (closed.has(neighborId)) {\n continue;\n }\n\n const neighborPolygon = this.polygons.get(neighborId);\n if (!neighborPolygon) {\n continue;\n }\n\n const g = current.g + euclideanDistance(\n current.polygon.center,\n neighborPolygon.center\n );\n\n let neighborState = states.get(neighborId);\n\n if (!neighborState) {\n neighborState = {\n polygon: neighborPolygon,\n g,\n f: g + euclideanDistance(neighborPolygon.center, end.center) * opts.heuristicWeight,\n parent: current\n };\n states.set(neighborId, neighborState);\n openList.push(neighborState);\n } else if (g < neighborState.g) {\n neighborState.g = g;\n neighborState.f = g + euclideanDistance(neighborPolygon.center, end.center) * opts.heuristicWeight;\n neighborState.parent = current;\n openList.update(neighborState);\n }\n }\n }\n\n return { found: false, polygons: [], nodesSearched };\n }\n\n /**\n * @zh 使用漏斗算法优化路径\n * @en Optimize path using funnel algorithm\n */\n private funnelPath(\n start: IPoint,\n end: IPoint,\n polygons: INavPolygon[]\n ): IPoint[] {\n if (polygons.length <= 1) {\n return [start, end];\n }\n\n // Collect portals\n const portals: IPortal[] = [];\n\n for (let i = 0; i < polygons.length - 1; i++) {\n const portal = polygons[i].portals.get(polygons[i + 1].id);\n if (portal) {\n portals.push(portal);\n }\n }\n\n if (portals.length === 0) {\n return [start, end];\n }\n\n // Simple string pulling algorithm\n const path: IPoint[] = [start];\n\n let apex = start;\n let leftIndex = 0;\n let rightIndex = 0;\n let left = portals[0].left;\n let right = portals[0].right;\n\n for (let i = 1; i <= portals.length; i++) {\n const nextLeft = i < portals.length ? portals[i].left : end;\n const nextRight = i < portals.length ? portals[i].right : end;\n\n // Update right\n if (this.triArea2(apex, right, nextRight) <= 0) {\n if (apex === right || this.triArea2(apex, left, nextRight) > 0) {\n right = nextRight;\n rightIndex = i;\n } else {\n path.push(left);\n apex = left;\n leftIndex = rightIndex = leftIndex;\n left = right = apex;\n i = leftIndex;\n continue;\n }\n }\n\n // Update left\n if (this.triArea2(apex, left, nextLeft) >= 0) {\n if (apex === left || this.triArea2(apex, right, nextLeft) < 0) {\n left = nextLeft;\n leftIndex = i;\n } else {\n path.push(right);\n apex = right;\n leftIndex = rightIndex = rightIndex;\n left = right = apex;\n i = rightIndex;\n continue;\n }\n }\n }\n\n path.push(end);\n\n return path;\n }\n\n /**\n * @zh 计算三角形面积的两倍(用于判断点的相对位置)\n * @en Calculate twice the triangle area (for point relative position)\n */\n private triArea2(a: IPoint, b: IPoint, c: IPoint): number {\n return (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y);\n }\n\n /**\n * @zh 计算路径总长度\n * @en Calculate total path length\n */\n private calculatePathLength(path: readonly IPoint[]): number {\n let length = 0;\n\n for (let i = 1; i < path.length; i++) {\n length += euclideanDistance(path[i - 1], path[i]);\n }\n\n return length;\n }\n\n /**\n * @zh 清空导航网格\n * @en Clear navigation mesh\n */\n clear(): void {\n this.polygons.clear();\n this.nodes.clear();\n this.nextId = 0;\n }\n\n /**\n * @zh 获取所有多边形\n * @en Get all polygons\n */\n getPolygons(): INavPolygon[] {\n return Array.from(this.polygons.values());\n }\n\n /**\n * @zh 获取多边形数量\n * @en Get polygon count\n */\n get polygonCount(): number {\n return this.polygons.size;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建导航网格\n * @en Create navigation mesh\n */\nexport function createNavMesh(): NavMesh {\n return new NavMesh();\n}\n"],"mappings":"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","names":["BinaryHeap","compare","heap","size","length","isEmpty","push","item","bubbleUp","pop","undefined","result","last","sinkDown","peek","update","index","indexOf","contains","clear","parentIndex","Math","floor","parent","leftIndex","rightIndex","smallest","AStarPathfinder","map","nodeCache","Map","openList","IndexedBinaryHeap","a","b","f","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","clear","startNode","getNodeAt","endNode","EMPTY_PATH_RESULT","walkable","id","found","path","position","cost","nodesSearched","start","getOrCreateAStarNode","g","h","heuristic","heuristicWeight","opened","push","endPosition","isEmpty","maxNodes","current","pop","closed","node","buildPath","neighbors","getNeighbors","neighborNode","neighbor","movementCost","getMovementCost","tentativeG","parent","update","astarNode","get","Infinity","heapIndex","set","reverse","createAStarPathfinder","CLOSED_FLAG","OPENED_FLAG","BACKWARD_CLOSED","BACKWARD_OPENED","GridState","width","height","bidirectional","size","g","f","flags","parent","heapIndex","version","currentVersion","gBack","fBack","parentBack","heapIndexBack","Float32Array","Uint8Array","Int32Array","Uint32Array","reset","fill","isInit","i","init","Infinity","getG","setG","v","getF","setF","getParent","setParent","getHeapIndex","setHeapIndex","isClosed","setClosed","isOpened","setOpened","getGBack","setGBack","getFBack","setFBack","getParentBack","setParentBack","getHeapIndexBack","setHeapIndexBack","isClosedBack","setClosedBack","isOpenedBack","setOpenedBack","_a","GridHeap","state","isBack","heap","length","isEmpty","push","bubbleUp","pop","result","last","sinkDown","update","pos","clear","idx","pp","pi","len","half","left","right","smallest","smallestF","lf","rf","si","GridPathfinder","map","config","mode","openList","openListBack","isBidir","findPath","startX","startY","endX","endY","options","findPathBidirectional","findPathUnidirectional","opts","DEFAULT_PATHFINDING_OPTIONS","validate","EMPTY_PATH_RESULT","startIdx","endIdx","found","path","x","y","cost","nodesSearched","hw","heuristicWeight","h0","heuristic","searched","maxNodes","allowDiagonal","avoidCorners","diagonalCost","nodes","dx","dy","dirCount","cur","buildPath","cx","cy","curG","d","nx","ny","neighbor","walkable","ni","isDiag","tentG","h","startPos","endPos","hf","hb","meetIdx","bestCost","total","buildPathBidirectional","isWalkable","w","reverse","createGridPathfinder","JPSPathfinder","map","width","height","openList","nodeGrid","bounds","getMapBounds","BinaryHeap","a","b","f","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","isWalkable","EMPTY_PATH_RESULT","found","path","x","y","cost","nodesSearched","initGrid","clear","startNode","getOrCreateNode","g","h","heuristic","heuristicWeight","push","isEmpty","maxNodes","current","pop","closed","buildPath","identifySuccessors","mapAny","i","xi","yi","Error","Infinity","parent","x1","y1","x2","y2","dx","Math","abs","dy","SQRT2","min","node","neighbors","findNeighbors","neighbor","jumpPoint","jump","jx","jy","jpNode","distance","sqrt","tentativeG","contains","update","nx","ny","isWalkableAt","sign","px","py","jumpStraight","endNode","unshift","interpolatePath","jumpPoints","length","prev","curr","steps","max","stepX","stepY","j","createJPSPathfinder","DEFAULT_HPA_CONFIG","clusterSize","maxEntranceWidth","cacheInternalPaths","HPAPathfinder","map","config","width","height","clusters","entrances","abstractNodes","Map","clusterGrid","nextEntranceId","nextNodeId","internalPathCache","localPathfinder","preprocessed","bounds","getMapBounds","AStarPathfinder","preprocess","clear","buildClusters","findEntrances","buildAbstractGraph","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","isWalkable","EMPTY_PATH_RESULT","found","path","x","y","cost","nodesSearched","startCluster","getClusterAt","endCluster","id","findLocalPath","startNodes","insertTemporaryNode","endNodes","abstractPath","searchAbstractGraph","removeTemporaryNodes","length","refinePath","notifyRegionChange","minX","minY","maxX","maxY","getStats","size","cacheSize","mapAny","clustersX","Math","ceil","clustersY","clusterId","cy","cx","cluster","min","push","rightCluster","findEntrancesBetween","bottomCluster","cluster1","cluster2","direction","maxWidth","entranceStart","entranceLength","x1","x2","max","walkable1","walkable2","createEntrance","y1","y2","coord1Start","coord1End","coord2Start","coord2End","point1","point2","center","midY","floor","midX","entrance","cluster1Id","cluster2Id","node1","createAbstractNode","node2","edges","targetNodeId","isInterEdge","connectIntraClusterNodes","position","entranceId","node","set","nodesInCluster","values","i","j","heuristic","tempNodes","tempNode","nodes","edge","targetNode","get","filter","e","delete","endNodeIds","Set","n","openList","BinaryHeap","a","b","f","closedSet","startNode","h","abstractNode","g","heuristicWeight","parent","isEmpty","maxNodes","current","pop","has","reconstructAbstractPath","add","neighbor","tentativeG","endNode","unshift","fullPath","totalCost","currentX","currentY","targetX","targetY","segment","finalSegment","findInternalPath","cacheKey","cached","result","calculatePathCost","dx","abs","dy","SQRT2","createHPAPathfinder","_a","NavMeshNode","polygon","id","position","cost","walkable","center","NavMesh","polygons","Map","nodes","nextId","addPolygon","vertices","neighbors","calculateCenter","portals","set","setConnection","polyA","polyB","portal","polygonA","get","polygonB","neighborsA","portalsA","includes","push","reversePortal","left","right","neighborsB","portalsB","build","polygonList","Array","from","values","i","length","j","sharedEdge","findSharedEdge","verticesA","verticesB","epsilon","a1","a2","b1","b2","match1","Math","abs","x","y","match2","v","createPoint","findPolygonAt","isPointInPolygon","inside","n","xi","yi","xj","yj","getNodeAt","getNeighbors","node","navNode","neighborId","neighbor","heuristic","a","b","euclideanDistance","getMovementCost","to","isWalkable","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","startPolygon","endPolygon","EMPTY_PATH_RESULT","found","path","nodesSearched","polygonPath","findPolygonPath","start","end","pointPath","funnelPath","calculatePathLength","openList","BinaryHeap","f","closed","Set","states","startState","g","heuristicWeight","parent","isEmpty","maxNodes","current","pop","state","unshift","add","has","neighborPolygon","neighborState","update","apex","leftIndex","rightIndex","nextLeft","nextRight","triArea2","c","clear","getPolygons","polygonCount","size","createNavMesh"]}