@esengine/pathfinding 13.1.0 → 13.2.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.d.ts +125 -25
- package/dist/index.js +871 -313
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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 * 5. 先在抽象图上寻路,再利用缓存细化为详细路径\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. Precompute actual path costs between entrances within clusters\n * 5. First find path on abstract graph, then refine using cached paths\n */\n\nimport { IndexedBinaryHeap, IHeapIndexable } from './IndexedBinaryHeap';\nimport type {\n IPathfindingMap,\n IPoint,\n IPathResult,\n IPathfinder,\n IPathfindingOptions,\n IPathNode\n} from './IPathfinding';\nimport { DEFAULT_PATHFINDING_OPTIONS, EMPTY_PATH_RESULT } from './IPathfinding';\nimport { AStarPathfinder } from './AStarPathfinder';\nimport { PathCache } from './PathCache';\n\n// =============================================================================\n// 类型定义 | Type Definitions\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 or use endpoint strategy)\n */\n maxEntranceWidth: number;\n\n /**\n * @zh 是否启用内部路径缓存\n * @en Whether to enable internal path caching\n */\n cacheInternalPaths: boolean;\n\n /**\n * @zh 入口策略:'middle' 在中间放节点,'end' 在宽入口两端各放节点\n * @en Entrance strategy: 'middle' places node at center, 'end' places nodes at both ends for wide entrances\n */\n entranceStrategy?: 'middle' | 'end';\n\n /**\n * @zh 是否延迟计算 intra-edges(大幅加速预处理,首次查询时计算真实路径)\n * @en Whether to lazily compute intra-edges (greatly speeds up preprocessing, computes actual paths on first query)\n */\n lazyIntraEdges?: boolean;\n}\n\n/**\n * @zh 默认 HPA* 配置\n * @en Default HPA* configuration\n */\nexport const DEFAULT_HPA_CONFIG: IHPAConfig = {\n clusterSize: 64,\n maxEntranceWidth: 16,\n cacheInternalPaths: true,\n entranceStrategy: 'end',\n lazyIntraEdges: true\n};\n\n/**\n * @zh 抽象边信息\n * @en Abstract edge information\n */\ninterface AbstractEdge {\n /** @zh 目标节点 ID @en Target node ID */\n targetNodeId: number;\n /** @zh 边代价(真实路径代价)@en Edge cost (actual path cost) */\n cost: number;\n /** @zh 是否为跨集群边 @en Is inter-cluster edge */\n isInterEdge: boolean;\n /** @zh 缓存的具体路径(ConcreteNodeId 列表)@en Cached concrete path (ConcreteNodeId list) */\n innerPath: number[] | null;\n}\n\n/**\n * @zh 抽象节点\n * @en Abstract node\n */\ninterface AbstractNode {\n /** @zh 节点 ID @en Node ID */\n id: number;\n /** @zh 位置(地图坐标)@en Position (map coordinates) */\n position: IPoint;\n /** @zh 所属集群 ID @en Cluster ID */\n clusterId: number;\n /** @zh 对应的具体地图节点 ID (y * width + x) @en Corresponding concrete node ID */\n concreteNodeId: number;\n /** @zh 出边列表 @en Outgoing edges */\n edges: AbstractEdge[];\n}\n\n/**\n * @zh A* 搜索节点\n * @en A* search node\n */\ninterface SearchNode extends IHeapIndexable {\n node: AbstractNode;\n g: number;\n h: number;\n f: number;\n parent: SearchNode | null;\n closed: boolean;\n opened: boolean;\n heapIndex: number;\n}\n\n/**\n * @zh 入口区间(边界上连续可通行的区域)\n * @en Entrance span (continuous walkable region on boundary)\n */\ninterface EntranceSpan {\n start: number;\n end: number;\n}\n\n// =============================================================================\n// SubMap 子地图类 (Slice) | SubMap Class (Slice)\n// =============================================================================\n\n/**\n * @zh 子地图 - 为集群提供隔离的地图视图\n * @en SubMap - Provides isolated map view for cluster\n *\n * @zh 不复制数据,只做坐标转换并委托给父地图\n * @en Doesn't copy data, just transforms coordinates and delegates to parent map\n */\nclass SubMap implements IPathfindingMap {\n readonly width: number;\n readonly height: number;\n\n constructor(\n private readonly parentMap: IPathfindingMap,\n private readonly originX: number,\n private readonly originY: number,\n width: number,\n height: number\n ) {\n this.width = width;\n this.height = height;\n }\n\n /**\n * @zh 局部坐标转全局坐标\n * @en Convert local to global coordinates\n */\n localToGlobal(localX: number, localY: number): IPoint {\n return {\n x: this.originX + localX,\n y: this.originY + localY\n };\n }\n\n /**\n * @zh 全局坐标转局部坐标\n * @en Convert global to local coordinates\n */\n globalToLocal(globalX: number, globalY: number): IPoint {\n return {\n x: globalX - this.originX,\n y: globalY - this.originY\n };\n }\n\n isWalkable(x: number, y: number): boolean {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return false;\n }\n return this.parentMap.isWalkable(this.originX + x, this.originY + y);\n }\n\n getNodeAt(x: number, y: number): IPathNode | null {\n if (x < 0 || x >= this.width || y < 0 || y >= this.height) {\n return null;\n }\n const globalNode = this.parentMap.getNodeAt(this.originX + x, this.originY + y);\n if (!globalNode) return null;\n\n // 创建局部节点(调整坐标)\n return {\n id: y * this.width + x,\n position: { x, y },\n cost: globalNode.cost,\n walkable: globalNode.walkable\n };\n }\n\n getNeighbors(node: IPathNode): IPathNode[] {\n const neighbors: IPathNode[] = [];\n const { x, y } = node.position;\n\n // 8方向邻居\n const directions = [\n { dx: 0, dy: -1 }, // N\n { dx: 1, dy: -1 }, // NE\n { dx: 1, dy: 0 }, // E\n { dx: 1, dy: 1 }, // SE\n { dx: 0, dy: 1 }, // S\n { dx: -1, dy: 1 }, // SW\n { dx: -1, dy: 0 }, // W\n { dx: -1, dy: -1 } // NW\n ];\n\n for (const dir of directions) {\n const nx = x + dir.dx;\n const ny = y + dir.dy;\n\n if (nx < 0 || nx >= this.width || ny < 0 || ny >= this.height) {\n continue;\n }\n\n if (!this.isWalkable(nx, ny)) {\n continue;\n }\n\n // 对角线移动:检查是否被角落阻挡\n if (dir.dx !== 0 && dir.dy !== 0) {\n if (!this.isWalkable(x + dir.dx, y) || !this.isWalkable(x, y + dir.dy)) {\n continue;\n }\n }\n\n const neighborNode = this.getNodeAt(nx, ny);\n if (neighborNode) {\n neighbors.push(neighborNode);\n }\n }\n\n return neighbors;\n }\n\n heuristic(a: IPoint, b: IPoint): number {\n // Octile 距离\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 getMovementCost(from: IPathNode, to: IPathNode): number {\n const dx = Math.abs(to.position.x - from.position.x);\n const dy = Math.abs(to.position.y - from.position.y);\n const baseCost = (dx !== 0 && dy !== 0) ? Math.SQRT2 : 1;\n return baseCost * to.cost;\n }\n}\n\n// =============================================================================\n// Cluster 集群类 | Cluster Class\n// =============================================================================\n\n/**\n * @zh 集群 - 管理地图的一个区域\n * @en Cluster - Manages a region of the map\n */\nclass Cluster {\n readonly id: number;\n readonly originX: number;\n readonly originY: number;\n readonly width: number;\n readonly height: number;\n readonly subMap: SubMap;\n\n /** @zh 集群内的抽象节点 ID 列表 @en Abstract node IDs in this cluster */\n nodeIds: number[] = [];\n\n /** @zh 预计算的距离缓存 @en Precomputed distance cache */\n private readonly distanceCache: Map<string, number> = new Map();\n\n /** @zh 预计算的路径缓存 @en Precomputed path cache */\n private readonly pathCache: Map<string, number[]> = new Map();\n\n constructor(\n id: number,\n originX: number,\n originY: number,\n width: number,\n height: number,\n parentMap: IPathfindingMap\n ) {\n this.id = id;\n this.originX = originX;\n this.originY = originY;\n this.width = width;\n this.height = height;\n this.subMap = new SubMap(parentMap, originX, originY, width, height);\n }\n\n /**\n * @zh 检查点是否在集群内\n * @en Check if point is in cluster\n */\n containsPoint(x: number, y: number): boolean {\n return x >= this.originX && x < this.originX + this.width &&\n y >= this.originY && y < this.originY + this.height;\n }\n\n /**\n * @zh 添加节点 ID\n * @en Add node ID\n */\n addNodeId(nodeId: number): void {\n if (!this.nodeIds.includes(nodeId)) {\n this.nodeIds.push(nodeId);\n }\n }\n\n /**\n * @zh 移除节点 ID\n * @en Remove node ID\n */\n removeNodeId(nodeId: number): void {\n const idx = this.nodeIds.indexOf(nodeId);\n if (idx !== -1) {\n this.nodeIds.splice(idx, 1);\n }\n }\n\n /**\n * @zh 生成缓存键\n * @en Generate cache key\n */\n private getCacheKey(fromId: number, toId: number): string {\n return `${fromId}->${toId}`;\n }\n\n /**\n * @zh 设置缓存\n * @en Set cache\n */\n setCache(fromId: number, toId: number, cost: number, path: number[]): void {\n const key = this.getCacheKey(fromId, toId);\n this.distanceCache.set(key, cost);\n this.pathCache.set(key, path);\n }\n\n /**\n * @zh 获取缓存的距离\n * @en Get cached distance\n */\n getCachedDistance(fromId: number, toId: number): number | undefined {\n return this.distanceCache.get(this.getCacheKey(fromId, toId));\n }\n\n /**\n * @zh 获取缓存的路径\n * @en Get cached path\n */\n getCachedPath(fromId: number, toId: number): number[] | undefined {\n return this.pathCache.get(this.getCacheKey(fromId, toId));\n }\n\n /**\n * @zh 清除缓存\n * @en Clear cache\n */\n clearCache(): void {\n this.distanceCache.clear();\n this.pathCache.clear();\n }\n\n /**\n * @zh 获取缓存大小\n * @en Get cache size\n */\n getCacheSize(): number {\n return this.distanceCache.size;\n }\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: Required<IHPAConfig>;\n private readonly mapWidth: number;\n private readonly mapHeight: number;\n\n // 集群管理\n private clusters: Cluster[] = [];\n private clusterGrid: (number | null)[][] = []; // [cx][cy] -> clusterId\n private clustersX: number = 0;\n private clustersY: number = 0;\n\n // 抽象图\n private abstractNodes: Map<number, AbstractNode> = new Map();\n private nodesByCluster: Map<number, number[]> = new Map();\n private nextNodeId: number = 0;\n\n // 入口统计\n private entranceCount: number = 0;\n\n // 内部寻路器\n private readonly localPathfinder: AStarPathfinder;\n\n // 完整路径缓存\n private readonly pathCache: PathCache;\n private mapVersion: number = 0;\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 } as Required<IHPAConfig>;\n\n const bounds = this.getMapBounds();\n this.mapWidth = bounds.width;\n this.mapHeight = bounds.height;\n\n this.localPathfinder = new AStarPathfinder(map);\n this.pathCache = new PathCache({ maxEntries: 1000, ttlMs: 0 });\n }\n\n // =========================================================================\n // 公共 API | Public API\n // =========================================================================\n\n /**\n * @zh 预处理地图(构建抽象图)\n * @en Preprocess map (build abstract graph)\n */\n preprocess(): void {\n this.clear();\n\n // 1. 构建集群\n this.buildClusters();\n\n // 2. 检测入口并创建抽象节点\n this.buildEntrances();\n\n // 3. 创建集群内边(计算真实代价)\n this.buildIntraEdges();\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 // 验证起点终点\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 const cached = this.pathCache.get(startX, startY, endX, endY, this.mapVersion);\n if (cached) {\n return cached;\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 let result: IPathResult;\n\n // 同一集群:直接局部搜索\n if (startCluster.id === endCluster.id) {\n result = this.findLocalPath(startX, startY, endX, endY, opts);\n } else {\n // 跨集群:HPA* 搜索\n const startTemp = this.insertTempNode(startX, startY, startCluster);\n const endTemp = this.insertTempNode(endX, endY, endCluster);\n\n const abstractPath = this.abstractSearch(startTemp, endTemp, opts);\n\n this.removeTempNode(startTemp, startCluster);\n this.removeTempNode(endTemp, endCluster);\n\n if (!abstractPath || abstractPath.length === 0) {\n return EMPTY_PATH_RESULT;\n }\n\n result = this.refinePath(abstractPath, startX, startY, endX, endY, opts);\n }\n\n // 缓存结果\n if (result.found) {\n this.pathCache.set(startX, startY, endX, endY, result, this.mapVersion);\n }\n\n return result;\n }\n\n /**\n * @zh 清理状态\n * @en Clear state\n */\n clear(): void {\n this.clusters = [];\n this.clusterGrid = [];\n this.abstractNodes.clear();\n this.nodesByCluster.clear();\n this.nextNodeId = 0;\n this.entranceCount = 0;\n this.pathCache.invalidateAll();\n this.mapVersion++;\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 // 找出受影响的集群并重建其 intra-edges\n const affectedClusters = this.getAffectedClusters(minX, minY, maxX, maxY);\n\n for (const cluster of affectedClusters) {\n // 清除该集群的缓存\n cluster.clearCache();\n\n // 移除该集群内所有节点的 intra-edges\n for (const nodeId of cluster.nodeIds) {\n const node = this.abstractNodes.get(nodeId);\n if (node) {\n node.edges = node.edges.filter(e => e.isInterEdge);\n }\n }\n\n // 重建 intra-edges\n this.buildClusterIntraEdges(cluster);\n }\n\n this.pathCache.invalidateRegion(minX, minY, maxX, maxY);\n this.mapVersion++;\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 let cacheSize = 0;\n for (const cluster of this.clusters) {\n cacheSize += cluster.getCacheSize();\n }\n\n return {\n clusters: this.clusters.length,\n entrances: this.entranceCount,\n abstractNodes: this.abstractNodes.size,\n cacheSize\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 /**\n * @zh 构建集群\n * @en Build clusters\n */\n private buildClusters(): void {\n const clusterSize = this.config.clusterSize;\n this.clustersX = Math.ceil(this.mapWidth / clusterSize);\n this.clustersY = Math.ceil(this.mapHeight / clusterSize);\n\n // 初始化集群网格\n this.clusterGrid = [];\n for (let cx = 0; cx < this.clustersX; cx++) {\n this.clusterGrid[cx] = [];\n for (let cy = 0; cy < this.clustersY; cy++) {\n this.clusterGrid[cx][cy] = null;\n }\n }\n\n // 创建集群\n let clusterId = 0;\n for (let cy = 0; cy < this.clustersY; cy++) {\n for (let cx = 0; cx < this.clustersX; cx++) {\n const originX = cx * clusterSize;\n const originY = cy * clusterSize;\n const width = Math.min(clusterSize, this.mapWidth - originX);\n const height = Math.min(clusterSize, this.mapHeight - originY);\n\n const cluster = new Cluster(\n clusterId,\n originX,\n originY,\n width,\n height,\n this.map\n );\n\n this.clusters.push(cluster);\n this.clusterGrid[cx][cy] = clusterId;\n this.nodesByCluster.set(clusterId, []);\n clusterId++;\n }\n }\n }\n\n /**\n * @zh 检测入口并创建抽象节点\n * @en Detect entrances and create abstract nodes\n */\n private buildEntrances(): void {\n const clusterSize = this.config.clusterSize;\n\n for (let cy = 0; cy < this.clustersY; cy++) {\n for (let cx = 0; cx < this.clustersX; cx++) {\n const clusterId = this.clusterGrid[cx][cy];\n if (clusterId === null) continue;\n\n const cluster1 = this.clusters[clusterId];\n\n // 右边相邻集群\n if (cx < this.clustersX - 1) {\n const cluster2Id = this.clusterGrid[cx + 1][cy];\n if (cluster2Id !== null) {\n const cluster2 = this.clusters[cluster2Id];\n this.detectAndCreateEntrances(cluster1, cluster2, 'vertical');\n }\n }\n\n // 下边相邻集群\n if (cy < this.clustersY - 1) {\n const cluster2Id = this.clusterGrid[cx][cy + 1];\n if (cluster2Id !== null) {\n const cluster2 = this.clusters[cluster2Id];\n this.detectAndCreateEntrances(cluster1, cluster2, 'horizontal');\n }\n }\n }\n }\n }\n\n /**\n * @zh 检测并创建两个相邻集群之间的入口\n * @en Detect and create entrances between two adjacent clusters\n */\n private detectAndCreateEntrances(\n cluster1: Cluster,\n cluster2: Cluster,\n boundaryDirection: 'horizontal' | 'vertical'\n ): void {\n const spans = this.detectEntranceSpans(cluster1, cluster2, boundaryDirection);\n\n for (const span of spans) {\n this.createEntranceNodes(cluster1, cluster2, span, boundaryDirection);\n }\n }\n\n /**\n * @zh 检测边界上的连续可通行区间\n * @en Detect continuous walkable spans on boundary\n */\n private detectEntranceSpans(\n cluster1: Cluster,\n cluster2: Cluster,\n boundaryDirection: 'horizontal' | 'vertical'\n ): EntranceSpan[] {\n const spans: EntranceSpan[] = [];\n\n if (boundaryDirection === 'vertical') {\n // cluster1 在左,cluster2 在右\n const x1 = cluster1.originX + cluster1.width - 1;\n const x2 = cluster2.originX;\n const startY = Math.max(cluster1.originY, cluster2.originY);\n const endY = Math.min(\n cluster1.originY + cluster1.height,\n cluster2.originY + cluster2.height\n );\n\n let spanStart: number | null = null;\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 (spanStart === null) {\n spanStart = y;\n }\n } else {\n if (spanStart !== null) {\n spans.push({ start: spanStart, end: y - 1 });\n spanStart = null;\n }\n }\n }\n\n if (spanStart !== null) {\n spans.push({ start: spanStart, end: endY - 1 });\n }\n } else {\n // cluster1 在上,cluster2 在下\n const y1 = cluster1.originY + cluster1.height - 1;\n const y2 = cluster2.originY;\n const startX = Math.max(cluster1.originX, cluster2.originX);\n const endX = Math.min(\n cluster1.originX + cluster1.width,\n cluster2.originX + cluster2.width\n );\n\n let spanStart: number | null = null;\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 (spanStart === null) {\n spanStart = x;\n }\n } else {\n if (spanStart !== null) {\n spans.push({ start: spanStart, end: x - 1 });\n spanStart = null;\n }\n }\n }\n\n if (spanStart !== null) {\n spans.push({ start: spanStart, end: endX - 1 });\n }\n }\n\n return spans;\n }\n\n /**\n * @zh 为入口区间创建抽象节点\n * @en Create abstract nodes for entrance span\n */\n private createEntranceNodes(\n cluster1: Cluster,\n cluster2: Cluster,\n span: EntranceSpan,\n boundaryDirection: 'horizontal' | 'vertical'\n ): void {\n const spanLength = span.end - span.start + 1;\n const maxWidth = this.config.maxEntranceWidth;\n const strategy = this.config.entranceStrategy;\n\n // 确定要放置节点的位置\n const positions: number[] = [];\n\n if (spanLength <= maxWidth) {\n // 窄入口:放在中间\n positions.push(Math.floor((span.start + span.end) / 2));\n } else {\n // 宽入口:均匀分布多个节点\n // Wide entrance: distribute multiple nodes evenly\n const numNodes = Math.ceil(spanLength / maxWidth);\n const spacing = spanLength / numNodes;\n\n for (let i = 0; i < numNodes; i++) {\n // 在每个子区间的中心放置节点\n const pos = Math.floor(span.start + spacing * (i + 0.5));\n positions.push(Math.min(pos, span.end));\n }\n\n // 如果使用 'end' 策略,确保两端也有节点\n if (strategy === 'end') {\n if (!positions.includes(span.start)) {\n positions.unshift(span.start);\n }\n if (!positions.includes(span.end)) {\n positions.push(span.end);\n }\n }\n }\n\n // 为每个位置创建节点对\n for (const pos of positions) {\n let p1: IPoint, p2: IPoint;\n\n if (boundaryDirection === 'vertical') {\n // cluster1 在左,cluster2 在右\n p1 = { x: cluster1.originX + cluster1.width - 1, y: pos };\n p2 = { x: cluster2.originX, y: pos };\n } else {\n // cluster1 在上,cluster2 在下\n p1 = { x: pos, y: cluster1.originY + cluster1.height - 1 };\n p2 = { x: pos, y: cluster2.originY };\n }\n\n // 创建节点对\n const node1 = this.createAbstractNode(p1, cluster1);\n const node2 = this.createAbstractNode(p2, cluster2);\n\n // 创建 inter-edge(代价为 1,相邻格子)\n const interCost = 1;\n\n node1.edges.push({\n targetNodeId: node2.id,\n cost: interCost,\n isInterEdge: true,\n innerPath: null\n });\n\n node2.edges.push({\n targetNodeId: node1.id,\n cost: interCost,\n isInterEdge: true,\n innerPath: null\n });\n\n this.entranceCount++;\n }\n }\n\n /**\n * @zh 创建抽象节点\n * @en Create abstract node\n */\n private createAbstractNode(position: IPoint, cluster: Cluster): AbstractNode {\n // 检查是否已存在相同位置的节点\n const concreteId = position.y * this.mapWidth + position.x;\n\n for (const nodeId of cluster.nodeIds) {\n const existing = this.abstractNodes.get(nodeId);\n if (existing && existing.concreteNodeId === concreteId) {\n return existing;\n }\n }\n\n // 创建新节点\n const node: AbstractNode = {\n id: this.nextNodeId++,\n position: { x: position.x, y: position.y },\n clusterId: cluster.id,\n concreteNodeId: concreteId,\n edges: []\n };\n\n this.abstractNodes.set(node.id, node);\n cluster.addNodeId(node.id);\n\n const clusterNodes = this.nodesByCluster.get(cluster.id);\n if (clusterNodes) {\n clusterNodes.push(node.id);\n }\n\n return node;\n }\n\n /**\n * @zh 构建所有集群的 intra-edges\n * @en Build intra-edges for all clusters\n */\n private buildIntraEdges(): void {\n for (const cluster of this.clusters) {\n this.buildClusterIntraEdges(cluster);\n }\n }\n\n /**\n * @zh 构建单个集群的 intra-edges\n * @en Build intra-edges for single cluster\n */\n private buildClusterIntraEdges(cluster: Cluster): void {\n const nodeIds = cluster.nodeIds;\n\n if (nodeIds.length < 2) return;\n\n if (this.config.lazyIntraEdges) {\n // 延迟计算模式:只用启发式距离创建边,真实路径在首次使用时计算\n this.buildLazyIntraEdges(cluster);\n } else {\n // 立即计算模式:预处理时计算所有真实路径\n this.buildEagerIntraEdges(cluster);\n }\n }\n\n /**\n * @zh 延迟构建 intra-edges(只用启发式距离)\n * @en Build lazy intra-edges (using heuristic distance only)\n */\n private buildLazyIntraEdges(cluster: Cluster): void {\n const nodeIds = cluster.nodeIds;\n\n for (let i = 0; i < nodeIds.length; i++) {\n for (let j = i + 1; j < nodeIds.length; j++) {\n const node1 = this.abstractNodes.get(nodeIds[i])!;\n const node2 = this.abstractNodes.get(nodeIds[j])!;\n\n // 使用启发式距离作为估计代价\n const heuristicCost = this.heuristic(node1.position, node2.position);\n\n // 创建双向 intra-edge(innerPath = null 表示未计算)\n node1.edges.push({\n targetNodeId: node2.id,\n cost: heuristicCost,\n isInterEdge: false,\n innerPath: null // 标记为未计算\n });\n\n node2.edges.push({\n targetNodeId: node1.id,\n cost: heuristicCost,\n isInterEdge: false,\n innerPath: null\n });\n }\n }\n }\n\n /**\n * @zh 立即构建 intra-edges(计算真实路径)\n * @en Build eager intra-edges (compute actual paths)\n */\n private buildEagerIntraEdges(cluster: Cluster): void {\n const nodeIds = cluster.nodeIds;\n\n // 为子地图创建 A* 寻路器\n const subPathfinder = new AStarPathfinder(cluster.subMap);\n\n // 计算所有节点对之间的真实路径\n for (let i = 0; i < nodeIds.length; i++) {\n for (let j = i + 1; j < nodeIds.length; j++) {\n const node1 = this.abstractNodes.get(nodeIds[i])!;\n const node2 = this.abstractNodes.get(nodeIds[j])!;\n\n // 转换为局部坐标\n const local1 = cluster.subMap.globalToLocal(node1.position.x, node1.position.y);\n const local2 = cluster.subMap.globalToLocal(node2.position.x, node2.position.y);\n\n // A* 计算真实路径\n const result = subPathfinder.findPath(\n local1.x, local1.y,\n local2.x, local2.y\n );\n\n if (result.found && result.path.length > 0) {\n // 转换路径为全局 ConcreteNodeId\n const globalPath: number[] = result.path.map(p => {\n const global = cluster.subMap.localToGlobal(p.x, p.y);\n return global.y * this.mapWidth + global.x;\n });\n\n // 缓存到集群\n if (this.config.cacheInternalPaths) {\n cluster.setCache(node1.id, node2.id, result.cost, globalPath);\n cluster.setCache(node2.id, node1.id, result.cost, [...globalPath].reverse());\n }\n\n // 创建双向 intra-edge\n node1.edges.push({\n targetNodeId: node2.id,\n cost: result.cost,\n isInterEdge: false,\n innerPath: this.config.cacheInternalPaths ? globalPath : null\n });\n\n node2.edges.push({\n targetNodeId: node1.id,\n cost: result.cost,\n isInterEdge: false,\n innerPath: this.config.cacheInternalPaths ? [...globalPath].reverse() : null\n });\n }\n // 如果路径不存在,不创建边(集群内不连通)\n }\n }\n }\n\n /**\n * @zh 按需计算 intra-edge 的真实路径\n * @en Compute actual path for intra-edge on demand\n */\n private computeIntraEdgePath(\n fromNode: AbstractNode,\n toNode: AbstractNode,\n edge: AbstractEdge\n ): { cost: number; path: number[] } | null {\n const cluster = this.clusters[fromNode.clusterId];\n if (!cluster) return null;\n\n // 检查集群缓存\n const cachedPath = cluster.getCachedPath(fromNode.id, toNode.id);\n const cachedCost = cluster.getCachedDistance(fromNode.id, toNode.id);\n if (cachedPath && cachedCost !== undefined) {\n // 更新边的代价和路径\n edge.cost = cachedCost;\n (edge as any).innerPath = cachedPath;\n return { cost: cachedCost, path: cachedPath };\n }\n\n // 计算真实路径\n const subPathfinder = new AStarPathfinder(cluster.subMap);\n const local1 = cluster.subMap.globalToLocal(fromNode.position.x, fromNode.position.y);\n const local2 = cluster.subMap.globalToLocal(toNode.position.x, toNode.position.y);\n\n const result = subPathfinder.findPath(local1.x, local1.y, local2.x, local2.y);\n\n if (result.found && result.path.length > 0) {\n // 转换路径为全局 ConcreteNodeId\n const globalPath: number[] = result.path.map(p => {\n const global = cluster.subMap.localToGlobal(p.x, p.y);\n return global.y * this.mapWidth + global.x;\n });\n\n // 缓存结果\n if (this.config.cacheInternalPaths) {\n cluster.setCache(fromNode.id, toNode.id, result.cost, globalPath);\n // 也缓存反向路径\n cluster.setCache(toNode.id, fromNode.id, result.cost, [...globalPath].reverse());\n }\n\n // 更新边\n edge.cost = result.cost;\n (edge as any).innerPath = globalPath;\n\n // 更新反向边\n const reverseEdge = toNode.edges.find(e => e.targetNodeId === fromNode.id);\n if (reverseEdge) {\n reverseEdge.cost = result.cost;\n (reverseEdge as any).innerPath = [...globalPath].reverse();\n }\n\n return { cost: result.cost, path: globalPath };\n }\n\n return null;\n }\n\n // =========================================================================\n // 搜索方法 | Search Methods\n // =========================================================================\n\n /**\n * @zh 获取指定位置的集群\n * @en Get cluster at position\n */\n private getClusterAt(x: number, y: number): Cluster | null {\n const cx = Math.floor(x / this.config.clusterSize);\n const cy = Math.floor(y / this.config.clusterSize);\n\n if (cx < 0 || cx >= this.clustersX || cy < 0 || cy >= this.clustersY) {\n return null;\n }\n\n const clusterId = this.clusterGrid[cx]?.[cy];\n if (clusterId === null || clusterId === undefined) {\n return null;\n }\n\n return this.clusters[clusterId] || null;\n }\n\n /**\n * @zh 获取受影响的集群\n * @en Get affected clusters\n */\n private getAffectedClusters(minX: number, minY: number, maxX: number, maxY: number): Cluster[] {\n const affected: Cluster[] = [];\n const clusterSize = this.config.clusterSize;\n\n const minCX = Math.floor(minX / clusterSize);\n const maxCX = Math.floor(maxX / clusterSize);\n const minCY = Math.floor(minY / clusterSize);\n const maxCY = Math.floor(maxY / clusterSize);\n\n for (let cy = minCY; cy <= maxCY; cy++) {\n for (let cx = minCX; cx <= maxCX; cx++) {\n if (cx >= 0 && cx < this.clustersX && cy >= 0 && cy < this.clustersY) {\n const clusterId = this.clusterGrid[cx]?.[cy];\n if (clusterId !== null && clusterId !== undefined) {\n affected.push(this.clusters[clusterId]);\n }\n }\n }\n }\n\n return affected;\n }\n\n /**\n * @zh 插入临时节点\n * @en Insert temporary node\n */\n private insertTempNode(x: number, y: number, cluster: Cluster): AbstractNode {\n const concreteId = y * this.mapWidth + x;\n\n // 检查是否已存在该位置的节点\n for (const nodeId of cluster.nodeIds) {\n const existing = this.abstractNodes.get(nodeId);\n if (existing && existing.concreteNodeId === concreteId) {\n return existing;\n }\n }\n\n // 创建临时节点\n const tempNode: AbstractNode = {\n id: this.nextNodeId++,\n position: { x, y },\n clusterId: cluster.id,\n concreteNodeId: concreteId,\n edges: []\n };\n\n this.abstractNodes.set(tempNode.id, tempNode);\n cluster.addNodeId(tempNode.id);\n\n // 计算到集群内所有其他节点的真实路径\n const subPathfinder = new AStarPathfinder(cluster.subMap);\n const localPos = cluster.subMap.globalToLocal(x, y);\n\n for (const existingNodeId of cluster.nodeIds) {\n if (existingNodeId === tempNode.id) continue;\n\n const existingNode = this.abstractNodes.get(existingNodeId);\n if (!existingNode) continue;\n\n const targetLocalPos = cluster.subMap.globalToLocal(\n existingNode.position.x,\n existingNode.position.y\n );\n\n const result = subPathfinder.findPath(\n localPos.x, localPos.y,\n targetLocalPos.x, targetLocalPos.y\n );\n\n if (result.found && result.path.length > 0) {\n // 转换路径\n const globalPath: number[] = result.path.map(p => {\n const global = cluster.subMap.localToGlobal(p.x, p.y);\n return global.y * this.mapWidth + global.x;\n });\n\n // 添加双向边\n tempNode.edges.push({\n targetNodeId: existingNode.id,\n cost: result.cost,\n isInterEdge: false,\n innerPath: globalPath\n });\n\n existingNode.edges.push({\n targetNodeId: tempNode.id,\n cost: result.cost,\n isInterEdge: false,\n innerPath: [...globalPath].reverse()\n });\n }\n }\n\n return tempNode;\n }\n\n /**\n * @zh 移除临时节点\n * @en Remove temporary node\n */\n private removeTempNode(node: AbstractNode, cluster: Cluster): void {\n // 移除其他节点指向此节点的边\n for (const existingNodeId of cluster.nodeIds) {\n if (existingNodeId === node.id) continue;\n\n const existingNode = this.abstractNodes.get(existingNodeId);\n if (existingNode) {\n existingNode.edges = existingNode.edges.filter(\n e => e.targetNodeId !== node.id\n );\n }\n }\n\n // 从集群和图中移除\n cluster.removeNodeId(node.id);\n this.abstractNodes.delete(node.id);\n }\n\n /**\n * @zh 在抽象图上进行 A* 搜索\n * @en Perform A* search on abstract graph\n */\n private abstractSearch(\n startNode: AbstractNode,\n endNode: AbstractNode,\n opts: Required<IPathfindingOptions>\n ): AbstractNode[] | null {\n const openList = new IndexedBinaryHeap<SearchNode>((a, b) => a.f - b.f);\n const nodeMap = new Map<number, SearchNode>();\n\n const endPosition = endNode.position;\n\n // 初始化起点\n const h = this.heuristic(startNode.position, endPosition) * opts.heuristicWeight;\n const startSearchNode: SearchNode = {\n node: startNode,\n g: 0,\n h,\n f: h,\n parent: null,\n closed: false,\n opened: true,\n heapIndex: -1\n };\n\n openList.push(startSearchNode);\n nodeMap.set(startNode.id, startSearchNode);\n\n let nodesSearched = 0;\n\n while (!openList.isEmpty && nodesSearched < opts.maxNodes) {\n const current = openList.pop()!;\n current.closed = true;\n nodesSearched++;\n\n // 找到目标\n if (current.node.id === endNode.id) {\n return this.reconstructPath(current);\n }\n\n // 扩展邻居\n for (const edge of current.node.edges) {\n let neighbor = nodeMap.get(edge.targetNodeId);\n\n if (!neighbor) {\n const neighborNode = this.abstractNodes.get(edge.targetNodeId);\n if (!neighborNode) continue;\n\n const nh = this.heuristic(neighborNode.position, endPosition) * opts.heuristicWeight;\n neighbor = {\n node: neighborNode,\n g: Infinity,\n h: nh,\n f: Infinity,\n parent: null,\n closed: false,\n opened: false,\n heapIndex: -1\n };\n nodeMap.set(edge.targetNodeId, neighbor);\n }\n\n if (neighbor.closed) continue;\n\n const tentativeG = current.g + edge.cost;\n\n if (!neighbor.opened) {\n neighbor.g = tentativeG;\n neighbor.f = tentativeG + neighbor.h;\n neighbor.parent = current;\n neighbor.opened = true;\n openList.push(neighbor);\n } else if (tentativeG < neighbor.g) {\n neighbor.g = tentativeG;\n neighbor.f = tentativeG + neighbor.h;\n neighbor.parent = current;\n openList.update(neighbor);\n }\n }\n }\n\n return null;\n }\n\n /**\n * @zh 重建抽象路径\n * @en Reconstruct abstract path\n */\n private reconstructPath(endNode: SearchNode): AbstractNode[] {\n const path: AbstractNode[] = [];\n let current: SearchNode | null = endNode;\n\n while (current) {\n path.unshift(current.node);\n current = current.parent;\n }\n\n return path;\n }\n\n /**\n * @zh 细化抽象路径为具体路径\n * @en Refine abstract path to concrete path\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 if (abstractPath.length === 0) {\n return EMPTY_PATH_RESULT;\n }\n\n const fullPath: IPoint[] = [];\n let totalCost = 0;\n let nodesSearched = abstractPath.length;\n\n // 处理抽象路径中的每一段\n for (let i = 0; i < abstractPath.length - 1; i++) {\n const fromNode = abstractPath[i];\n const toNode = abstractPath[i + 1];\n\n // 查找连接边\n const edge = fromNode.edges.find(e => e.targetNodeId === toNode.id);\n\n if (!edge) {\n // 边不存在,需要实时计算\n const segResult = this.findLocalPath(\n fromNode.position.x, fromNode.position.y,\n toNode.position.x, toNode.position.y,\n opts\n );\n\n if (segResult.found) {\n this.appendPath(fullPath, segResult.path);\n totalCost += segResult.cost;\n nodesSearched += segResult.nodesSearched;\n }\n } else if (edge.isInterEdge) {\n // Inter-edge:直接连接\n if (fullPath.length === 0 ||\n fullPath[fullPath.length - 1].x !== fromNode.position.x ||\n fullPath[fullPath.length - 1].y !== fromNode.position.y) {\n fullPath.push({ x: fromNode.position.x, y: fromNode.position.y });\n }\n fullPath.push({ x: toNode.position.x, y: toNode.position.y });\n totalCost += edge.cost;\n } else if (edge.innerPath && edge.innerPath.length > 0) {\n // Intra-edge:使用缓存路径\n const concretePath = edge.innerPath.map(id => ({\n x: id % this.mapWidth,\n y: Math.floor(id / this.mapWidth)\n }));\n this.appendPath(fullPath, concretePath);\n totalCost += edge.cost;\n } else {\n // Lazy intra-edge 或没有缓存路径:按需计算真实路径\n // Lazy intra-edge or no cached path: compute actual path on demand\n const computed = this.computeIntraEdgePath(fromNode, toNode, edge);\n\n if (computed && computed.path.length > 0) {\n // 使用计算出的路径\n const concretePath = computed.path.map(id => ({\n x: id % this.mapWidth,\n y: Math.floor(id / this.mapWidth)\n }));\n this.appendPath(fullPath, concretePath);\n totalCost += computed.cost;\n } else {\n // 路径计算失败,回退到实时搜索\n // Path computation failed, fall back to real-time search\n const segResult = this.findLocalPath(\n fromNode.position.x, fromNode.position.y,\n toNode.position.x, toNode.position.y,\n opts\n );\n\n if (segResult.found) {\n this.appendPath(fullPath, segResult.path);\n totalCost += segResult.cost;\n nodesSearched += segResult.nodesSearched;\n }\n }\n }\n }\n\n // 确保起点正确\n if (fullPath.length > 0 && (fullPath[0].x !== startX || fullPath[0].y !== startY)) {\n // 连接起点到路径开头\n const firstPoint = fullPath[0];\n if (Math.abs(firstPoint.x - startX) <= 1 && Math.abs(firstPoint.y - startY) <= 1) {\n fullPath.unshift({ x: startX, y: startY });\n } else {\n const segResult = this.findLocalPath(startX, startY, firstPoint.x, firstPoint.y, opts);\n if (segResult.found) {\n fullPath.splice(0, 0, ...segResult.path.slice(0, -1));\n totalCost += segResult.cost;\n }\n }\n }\n\n // 确保终点正确\n if (fullPath.length > 0) {\n const lastPoint = fullPath[fullPath.length - 1];\n if (lastPoint.x !== endX || lastPoint.y !== endY) {\n if (Math.abs(lastPoint.x - endX) <= 1 && Math.abs(lastPoint.y - endY) <= 1) {\n fullPath.push({ x: endX, y: endY });\n } else {\n const segResult = this.findLocalPath(lastPoint.x, lastPoint.y, endX, endY, opts);\n if (segResult.found) {\n fullPath.push(...segResult.path.slice(1));\n totalCost += segResult.cost;\n }\n }\n }\n }\n\n return {\n found: fullPath.length > 0,\n path: fullPath,\n cost: totalCost,\n nodesSearched\n };\n }\n\n /**\n * @zh 追加路径(避免重复点)\n * @en Append path (avoid duplicate points)\n */\n private appendPath(fullPath: IPoint[], segment: readonly IPoint[]): void {\n if (segment.length === 0) return;\n\n let startIdx = 0;\n\n // 避免重复第一个点\n if (fullPath.length > 0) {\n const last = fullPath[fullPath.length - 1];\n if (last.x === segment[0].x && last.y === segment[0].y) {\n startIdx = 1;\n }\n }\n\n for (let i = startIdx; i < segment.length; i++) {\n fullPath.push({ x: segment[i].x, y: segment[i].y });\n }\n }\n\n /**\n * @zh 局部寻路\n * @en Local pathfinding\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 /**\n * @zh 启发式函数(Octile 距离)\n * @en Heuristic function (Octile distance)\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","entranceStrategy","lazyIntraEdges","_a","SubMap","parentMap","originX","originY","width","height","localToGlobal","localX","localY","x","y","globalToLocal","globalX","globalY","isWalkable","getNodeAt","globalNode","id","position","cost","walkable","getNeighbors","node","neighbors","directions","dx","dy","dir","nx","ny","neighborNode","push","heuristic","a","b","Math","abs","SQRT2","min","getMovementCost","from","to","baseCost","Cluster","subMap","nodeIds","distanceCache","Map","pathCache","containsPoint","addNodeId","nodeId","includes","removeNodeId","idx","indexOf","splice","getCacheKey","fromId","toId","setCache","path","key","set","getCachedDistance","get","getCachedPath","clearCache","clear","getCacheSize","size","HPAPathfinder","map","config","mapWidth","mapHeight","clusters","clusterGrid","clustersX","clustersY","abstractNodes","nodesByCluster","nextNodeId","entranceCount","localPathfinder","mapVersion","preprocessed","bounds","getMapBounds","AStarPathfinder","PathCache","maxEntries","ttlMs","preprocess","buildClusters","buildEntrances","buildIntraEdges","findPath","startX","startY","endX","endY","options","opts","DEFAULT_PATHFINDING_OPTIONS","EMPTY_PATH_RESULT","found","nodesSearched","cached","startCluster","getClusterAt","endCluster","result","findLocalPath","startTemp","insertTempNode","endTemp","abstractPath","abstractSearch","removeTempNode","length","refinePath","invalidateAll","notifyRegionChange","minX","minY","maxX","maxY","affectedClusters","getAffectedClusters","cluster","edges","filter","e","isInterEdge","buildClusterIntraEdges","invalidateRegion","getStats","cacheSize","entrances","mapAny","ceil","cx","cy","clusterId","cluster1","cluster2Id","cluster2","detectAndCreateEntrances","boundaryDirection","spans","detectEntranceSpans","span","createEntranceNodes","x1","x2","max","spanStart","walkable1","walkable2","start","end","y1","y2","spanLength","maxWidth","strategy","positions","floor","numNodes","spacing","i","pos","unshift","p1","p2","node1","createAbstractNode","node2","interCost","targetNodeId","innerPath","concreteId","existing","concreteNodeId","clusterNodes","buildLazyIntraEdges","buildEagerIntraEdges","j","heuristicCost","subPathfinder","local1","local2","globalPath","p","global","reverse","computeIntraEdgePath","fromNode","toNode","edge","cachedPath","cachedCost","undefined","reverseEdge","find","affected","minCX","maxCX","minCY","maxCY","tempNode","localPos","existingNodeId","existingNode","targetLocalPos","delete","startNode","endNode","openList","IndexedBinaryHeap","f","nodeMap","endPosition","h","heuristicWeight","startSearchNode","g","parent","closed","opened","heapIndex","isEmpty","maxNodes","current","pop","reconstructPath","neighbor","nh","Infinity","tentativeG","update","fullPath","totalCost","segResult","appendPath","concretePath","computed","firstPoint","slice","lastPoint","segment","startIdx","last","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"]}
|