@esengine/pathfinding 12.0.0 → 12.1.2
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/IIncrementalPathfinding-3qs7e_pO.d.ts +450 -0
- package/dist/chunk-GTFFYRZM.js +36 -0
- package/dist/chunk-GTFFYRZM.js.map +1 -0
- package/dist/chunk-TPT7Q3E3.js +1648 -0
- package/dist/chunk-TPT7Q3E3.js.map +1 -0
- package/dist/ecs.d.ts +503 -0
- package/dist/ecs.js +1033 -0
- package/dist/ecs.js.map +1 -0
- package/dist/index.d.ts +886 -192
- package/dist/index.js +1650 -1066
- package/dist/index.js.map +1 -1
- package/dist/nodes.d.ts +143 -0
- package/dist/nodes.js +1174 -0
- package/dist/nodes.js.map +1 -0
- package/package.json +21 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/IPathfinding.ts","../src/core/IndexedBinaryHeap.ts","../src/core/PathCache.ts","../src/core/IncrementalAStarPathfinder.ts","../src/core/PathValidator.ts","../src/grid/GridMap.ts","../src/smoothing/PathSmoother.ts"],"sourcesContent":["/**\n * @zh 寻路系统核心接口\n * @en Pathfinding System Core Interfaces\n */\n\n// =============================================================================\n// 基础类型 | Basic Types\n// =============================================================================\n\n/**\n * @zh 2D 坐标点\n * @en 2D coordinate point\n */\nexport interface IPoint {\n readonly x: number;\n readonly y: number;\n}\n\n/**\n * @zh 创建点\n * @en Create a point\n */\nexport function createPoint(x: number, y: number): IPoint {\n return { x, y };\n}\n\n/**\n * @zh 路径节点\n * @en Path node\n */\nexport interface IPathNode {\n /** @zh 节点唯一标识 @en Unique node identifier */\n readonly id: string | number;\n /** @zh 节点位置 @en Node position */\n readonly position: IPoint;\n /** @zh 移动代价 @en Movement cost */\n readonly cost: number;\n /** @zh 是否可通行 @en Is walkable */\n readonly walkable: boolean;\n}\n\n/**\n * @zh 路径结果\n * @en Path result\n */\nexport interface IPathResult {\n /** @zh 是否找到路径 @en Whether path was found */\n readonly found: boolean;\n /** @zh 路径点列表 @en List of path points */\n readonly path: readonly IPoint[];\n /** @zh 路径总代价 @en Total path cost */\n readonly cost: number;\n /** @zh 搜索的节点数 @en Number of nodes searched */\n readonly nodesSearched: number;\n}\n\n/**\n * @zh 空路径结果\n * @en Empty path result\n */\nexport const EMPTY_PATH_RESULT: IPathResult = {\n found: false,\n path: [],\n cost: 0,\n nodesSearched: 0\n};\n\n// =============================================================================\n// 地图接口 | Map Interface\n// =============================================================================\n\n/**\n * @zh 寻路地图接口\n * @en Pathfinding map interface\n */\nexport interface IPathfindingMap {\n /**\n * @zh 获取节点的邻居\n * @en Get neighbors of a node\n */\n getNeighbors(node: IPathNode): IPathNode[];\n\n /**\n * @zh 获取指定位置的节点\n * @en Get node at position\n */\n getNodeAt(x: number, y: number): IPathNode | null;\n\n /**\n * @zh 计算两点间的启发式距离\n * @en Calculate heuristic distance between two points\n */\n heuristic(a: IPoint, b: IPoint): number;\n\n /**\n * @zh 计算两个邻居节点间的移动代价\n * @en Calculate movement cost between two neighbor nodes\n */\n getMovementCost(from: IPathNode, to: IPathNode): number;\n\n /**\n * @zh 检查位置是否可通行\n * @en Check if position is walkable\n */\n isWalkable(x: number, y: number): boolean;\n}\n\n// =============================================================================\n// 启发式函数 | Heuristic Functions\n// =============================================================================\n\n/**\n * @zh 启发式函数类型\n * @en Heuristic function type\n */\nexport type HeuristicFunction = (a: IPoint, b: IPoint) => number;\n\n/**\n * @zh 曼哈顿距离(4方向移动)\n * @en Manhattan distance (4-directional movement)\n */\nexport function manhattanDistance(a: IPoint, b: IPoint): number {\n return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n}\n\n/**\n * @zh 欧几里得距离(任意方向移动)\n * @en Euclidean distance (any direction movement)\n */\nexport function euclideanDistance(a: IPoint, b: IPoint): number {\n const dx = a.x - b.x;\n const dy = a.y - b.y;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n/**\n * @zh 切比雪夫距离(8方向移动)\n * @en Chebyshev distance (8-directional movement)\n */\nexport function chebyshevDistance(a: IPoint, b: IPoint): number {\n return Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y));\n}\n\n/**\n * @zh 八角距离(8方向移动,对角线代价为 √2)\n * @en Octile distance (8-directional, diagonal cost √2)\n */\nexport function octileDistance(a: IPoint, b: IPoint): number {\n const dx = Math.abs(a.x - b.x);\n const dy = Math.abs(a.y - b.y);\n const D = 1;\n const D2 = Math.SQRT2;\n return D * (dx + dy) + (D2 - 2 * D) * Math.min(dx, dy);\n}\n\n// =============================================================================\n// 寻路器接口 | Pathfinder Interface\n// =============================================================================\n\n/**\n * @zh 寻路配置\n * @en Pathfinding options\n */\nexport interface IPathfindingOptions {\n /** @zh 最大搜索节点数 @en Maximum nodes to search */\n maxNodes?: number;\n /** @zh 启发式权重 (>1 更快但可能非最优) @en Heuristic weight (>1 faster but may be suboptimal) */\n heuristicWeight?: number;\n /** @zh 是否允许对角移动 @en Allow diagonal movement */\n allowDiagonal?: boolean;\n /** @zh 是否避免穿角 @en Avoid corner cutting */\n avoidCorners?: boolean;\n}\n\n/**\n * @zh 默认寻路配置\n * @en Default pathfinding options\n */\nexport const DEFAULT_PATHFINDING_OPTIONS: Required<IPathfindingOptions> = {\n maxNodes: 10000,\n heuristicWeight: 1.0,\n allowDiagonal: true,\n avoidCorners: true\n};\n\n/**\n * @zh 寻路器接口\n * @en Pathfinder interface\n */\nexport interface IPathfinder {\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\n /**\n * @zh 清理状态(用于重用)\n * @en Clear state (for reuse)\n */\n clear(): void;\n}\n\n// =============================================================================\n// 路径平滑接口 | Path Smoothing Interface\n// =============================================================================\n\n/**\n * @zh 路径平滑器接口\n * @en Path smoother interface\n */\nexport interface IPathSmoother {\n /**\n * @zh 平滑路径\n * @en Smooth path\n */\n smooth(path: readonly IPoint[], map: IPathfindingMap): IPoint[];\n}\n\n/**\n * @zh 视线检测函数类型\n * @en Line of sight check function type\n */\nexport type LineOfSightCheck = (\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap\n) => boolean;\n","/**\n * @zh 带索引追踪的二叉堆(优先队列)\n * @en Indexed Binary Heap (Priority Queue) with index tracking\n */\n\n/**\n * @zh 可索引的堆元素接口\n * @en Interface for indexable heap elements\n */\nexport interface IHeapIndexable {\n /** @zh 堆中的索引位置 @en Index position in heap */\n heapIndex: number;\n}\n\n/**\n * @zh 带索引追踪的二叉堆\n * @en Binary Heap with index tracking\n */\nexport class IndexedBinaryHeap<T extends IHeapIndexable> {\n private heap: T[] = [];\n private readonly compare: (a: T, b: T) => number;\n\n /**\n * @zh 创建带索引追踪的二叉堆\n * @en Create indexed 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 item.heapIndex = this.heap.length;\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 result.heapIndex = -1;\n\n const last = this.heap.pop()!;\n\n if (this.heap.length > 0) {\n last.heapIndex = 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\n */\n update(item: T): void {\n const index = item.heapIndex;\n if (index >= 0 && index < this.heap.length && this.heap[index] === item) {\n this.bubbleUp(index);\n this.sinkDown(item.heapIndex);\n }\n }\n\n /**\n * @zh 检查是否包含元素\n * @en Check if contains element\n */\n contains(item: T): boolean {\n const index = item.heapIndex;\n return index >= 0 && index < this.heap.length && this.heap[index] === item;\n }\n\n /**\n * @zh 从堆中移除指定元素\n * @en Remove specific element from heap\n */\n remove(item: T): boolean {\n const index = item.heapIndex;\n if (index < 0 || index >= this.heap.length || this.heap[index] !== item) {\n return false;\n }\n\n item.heapIndex = -1;\n\n if (index === this.heap.length - 1) {\n this.heap.pop();\n return true;\n }\n\n const last = this.heap.pop()!;\n last.heapIndex = index;\n this.heap[index] = last;\n this.bubbleUp(index);\n this.sinkDown(last.heapIndex);\n\n return true;\n }\n\n /**\n * @zh 清空堆\n * @en Clear heap\n */\n clear(): void {\n for (const item of this.heap) {\n item.heapIndex = -1;\n }\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 = (index - 1) >> 1;\n const parent = this.heap[parentIndex];\n\n if (this.compare(item, parent) >= 0) {\n break;\n }\n\n parent.heapIndex = index;\n this.heap[index] = parent;\n index = parentIndex;\n }\n\n item.heapIndex = index;\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 const halfLength = length >> 1;\n\n while (index < halfLength) {\n const leftIndex = (index << 1) + 1;\n const rightIndex = leftIndex + 1;\n let smallest = index;\n let smallestItem = item;\n\n const left = this.heap[leftIndex];\n if (this.compare(left, smallestItem) < 0) {\n smallest = leftIndex;\n smallestItem = left;\n }\n\n if (rightIndex < length) {\n const right = this.heap[rightIndex];\n if (this.compare(right, smallestItem) < 0) {\n smallest = rightIndex;\n smallestItem = right;\n }\n }\n\n if (smallest === index) {\n break;\n }\n\n smallestItem.heapIndex = index;\n this.heap[index] = smallestItem;\n index = smallest;\n }\n\n item.heapIndex = index;\n this.heap[index] = item;\n }\n}\n","/**\n * @zh 路径缓存模块\n * @en Path Cache Module\n *\n * @zh 缓存已计算的路径,避免重复计算相同起点终点的路径\n * @en Cache computed paths to avoid recalculating paths with the same start and end points\n */\n\nimport type { IPoint, IPathResult } from './IPathfinding';\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\n/**\n * @zh 缓存条目\n * @en Cache entry\n */\ninterface ICacheEntry {\n result: IPathResult;\n timestamp: number;\n mapVersion: number;\n}\n\n/**\n * @zh 缓存配置\n * @en Cache configuration\n */\nexport interface IPathCacheConfig {\n /**\n * @zh 最大缓存条目数\n * @en Maximum number of cache entries\n */\n maxEntries: number;\n\n /**\n * @zh 缓存过期时间(毫秒),0 表示不过期\n * @en Cache expiration time in milliseconds, 0 means no expiration\n */\n ttlMs: number;\n\n /**\n * @zh 是否启用近似匹配(在一定范围内的起点/终点视为相同)\n * @en Whether to enable approximate matching (start/end within range considered same)\n */\n enableApproximateMatch: boolean;\n\n /**\n * @zh 近似匹配范围\n * @en Approximate matching range\n */\n approximateRange: number;\n}\n\n/**\n * @zh 默认缓存配置\n * @en Default cache configuration\n */\nexport const DEFAULT_PATH_CACHE_CONFIG: IPathCacheConfig = {\n maxEntries: 1000,\n ttlMs: 5000,\n enableApproximateMatch: false,\n approximateRange: 2\n};\n\n// =============================================================================\n// 路径缓存 | Path Cache\n// =============================================================================\n\n/**\n * @zh 路径缓存\n * @en Path Cache\n *\n * @zh 缓存已计算的路径,支持 LRU 淘汰策略和 TTL 过期\n * @en Cache computed paths with LRU eviction and TTL expiration\n *\n * @example\n * ```typescript\n * const cache = new PathCache({ maxEntries: 500 });\n * const cached = cache.get(0, 0, 10, 10, mapVersion);\n * if (!cached) {\n * const result = pathfinder.findPath(0, 0, 10, 10);\n * cache.set(0, 0, 10, 10, result, mapVersion);\n * }\n * ```\n */\nexport class PathCache {\n private readonly config: IPathCacheConfig;\n private readonly cache: Map<string, ICacheEntry>;\n private readonly accessOrder: string[];\n\n constructor(config: Partial<IPathCacheConfig> = {}) {\n this.config = { ...DEFAULT_PATH_CACHE_CONFIG, ...config };\n this.cache = new Map();\n this.accessOrder = [];\n }\n\n /**\n * @zh 获取缓存的路径\n * @en Get cached path\n *\n * @param startX - @zh 起点 X 坐标 @en Start X coordinate\n * @param startY - @zh 起点 Y 坐标 @en Start Y coordinate\n * @param endX - @zh 终点 X 坐标 @en End X coordinate\n * @param endY - @zh 终点 Y 坐标 @en End Y coordinate\n * @param mapVersion - @zh 地图版本号 @en Map version number\n * @returns @zh 缓存的路径结果或 null @en Cached path result or null\n */\n get(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n mapVersion: number\n ): IPathResult | null {\n const key = this.generateKey(startX, startY, endX, endY);\n const entry = this.cache.get(key);\n\n if (!entry) {\n if (this.config.enableApproximateMatch) {\n return this.getApproximate(startX, startY, endX, endY, mapVersion);\n }\n return null;\n }\n\n if (!this.isValid(entry, mapVersion)) {\n this.cache.delete(key);\n this.removeFromAccessOrder(key);\n return null;\n }\n\n this.updateAccessOrder(key);\n return entry.result;\n }\n\n /**\n * @zh 设置缓存路径\n * @en Set cached path\n *\n * @param startX - @zh 起点 X 坐标 @en Start X coordinate\n * @param startY - @zh 起点 Y 坐标 @en Start Y coordinate\n * @param endX - @zh 终点 X 坐标 @en End X coordinate\n * @param endY - @zh 终点 Y 坐标 @en End Y coordinate\n * @param result - @zh 路径结果 @en Path result\n * @param mapVersion - @zh 地图版本号 @en Map version number\n */\n set(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n result: IPathResult,\n mapVersion: number\n ): void {\n if (this.cache.size >= this.config.maxEntries) {\n this.evictLRU();\n }\n\n const key = this.generateKey(startX, startY, endX, endY);\n const entry: ICacheEntry = {\n result,\n timestamp: Date.now(),\n mapVersion\n };\n\n this.cache.set(key, entry);\n this.updateAccessOrder(key);\n }\n\n /**\n * @zh 使所有缓存失效\n * @en Invalidate all cache\n */\n invalidateAll(): void {\n this.cache.clear();\n this.accessOrder.length = 0;\n }\n\n /**\n * @zh 使指定区域的缓存失效\n * @en Invalidate cache for specified region\n *\n * @param minX - @zh 最小 X 坐标 @en Minimum X coordinate\n * @param minY - @zh 最小 Y 坐标 @en Minimum Y coordinate\n * @param maxX - @zh 最大 X 坐标 @en Maximum X coordinate\n * @param maxY - @zh 最大 Y 坐标 @en Maximum Y coordinate\n */\n invalidateRegion(minX: number, minY: number, maxX: number, maxY: number): void {\n const keysToDelete: string[] = [];\n\n for (const [key, entry] of this.cache) {\n const path = entry.result.path;\n if (path.length === 0) continue;\n\n for (const point of path) {\n if (point.x >= minX && point.x <= maxX &&\n point.y >= minY && point.y <= maxY) {\n keysToDelete.push(key);\n break;\n }\n }\n }\n\n for (const key of keysToDelete) {\n this.cache.delete(key);\n this.removeFromAccessOrder(key);\n }\n }\n\n /**\n * @zh 获取缓存统计信息\n * @en Get cache statistics\n */\n getStats(): { size: number; maxSize: number; hitRate?: number } {\n return {\n size: this.cache.size,\n maxSize: this.config.maxEntries\n };\n }\n\n /**\n * @zh 清理过期条目\n * @en Clean up expired entries\n */\n cleanup(): void {\n if (this.config.ttlMs === 0) return;\n\n const now = Date.now();\n const keysToDelete: string[] = [];\n\n for (const [key, entry] of this.cache) {\n if (now - entry.timestamp > this.config.ttlMs) {\n keysToDelete.push(key);\n }\n }\n\n for (const key of keysToDelete) {\n this.cache.delete(key);\n this.removeFromAccessOrder(key);\n }\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n private generateKey(startX: number, startY: number, endX: number, endY: number): string {\n return `${startX},${startY}->${endX},${endY}`;\n }\n\n private isValid(entry: ICacheEntry, mapVersion: number): boolean {\n if (entry.mapVersion !== mapVersion) {\n return false;\n }\n\n if (this.config.ttlMs > 0) {\n const age = Date.now() - entry.timestamp;\n if (age > this.config.ttlMs) {\n return false;\n }\n }\n\n return true;\n }\n\n private getApproximate(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n mapVersion: number\n ): IPathResult | null {\n const range = this.config.approximateRange;\n\n for (let sx = startX - range; sx <= startX + range; sx++) {\n for (let sy = startY - range; sy <= startY + range; sy++) {\n for (let ex = endX - range; ex <= endX + range; ex++) {\n for (let ey = endY - range; ey <= endY + range; ey++) {\n const key = this.generateKey(sx, sy, ex, ey);\n const entry = this.cache.get(key);\n if (entry && this.isValid(entry, mapVersion)) {\n this.updateAccessOrder(key);\n return this.adjustPathForApproximate(\n entry.result,\n startX, startY, endX, endY\n );\n }\n }\n }\n }\n }\n\n return null;\n }\n\n private adjustPathForApproximate(\n result: IPathResult,\n newStartX: number,\n newStartY: number,\n newEndX: number,\n newEndY: number\n ): IPathResult {\n if (result.path.length === 0) {\n return result;\n }\n\n const newPath: IPoint[] = [];\n const oldStart = result.path[0];\n const oldEnd = result.path[result.path.length - 1];\n\n if (newStartX !== oldStart.x || newStartY !== oldStart.y) {\n newPath.push({ x: newStartX, y: newStartY });\n }\n\n newPath.push(...result.path);\n\n if (newEndX !== oldEnd.x || newEndY !== oldEnd.y) {\n newPath.push({ x: newEndX, y: newEndY });\n }\n\n return {\n ...result,\n path: newPath\n };\n }\n\n private updateAccessOrder(key: string): void {\n this.removeFromAccessOrder(key);\n this.accessOrder.push(key);\n }\n\n private removeFromAccessOrder(key: string): void {\n const index = this.accessOrder.indexOf(key);\n if (index !== -1) {\n this.accessOrder.splice(index, 1);\n }\n }\n\n private evictLRU(): void {\n const lruKey = this.accessOrder.shift();\n if (lruKey) {\n this.cache.delete(lruKey);\n }\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建路径缓存\n * @en Create path cache\n *\n * @param config - @zh 缓存配置 @en Cache configuration\n * @returns @zh 路径缓存实例 @en Path cache instance\n */\nexport function createPathCache(config?: Partial<IPathCacheConfig>): PathCache {\n return new PathCache(config);\n}\n","/**\n * @zh 增量 A* 寻路算法实现\n * @en Incremental A* Pathfinding Algorithm Implementation\n */\n\nimport { IndexedBinaryHeap, type IHeapIndexable } from './IndexedBinaryHeap';\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n IPathfindingOptions\n} from './IPathfinding';\nimport { DEFAULT_PATHFINDING_OPTIONS } from './IPathfinding';\nimport type {\n IIncrementalPathfinder,\n IPathRequest,\n IPathProgress,\n IIncrementalPathResult,\n IIncrementalPathfindingOptions\n} from './IIncrementalPathfinding';\nimport { PathfindingState, EMPTY_PROGRESS } from './IIncrementalPathfinding';\nimport { PathCache, type IPathCacheConfig } from './PathCache';\n\n// =============================================================================\n// 内部类型 | Internal Types\n// =============================================================================\n\n/**\n * @zh A* 节点(内部使用)\n * @en A* Node (internal use)\n */\ninterface AStarNode extends IHeapIndexable {\n node: IPathNode;\n g: number;\n h: number;\n f: number;\n parent: AStarNode | null;\n closed: boolean;\n opened: boolean;\n heapIndex: number;\n}\n\n/**\n * @zh 寻路会话(保存跨帧状态)\n * @en Pathfinding session (preserves state across frames)\n */\ninterface PathfindingSession {\n request: IPathRequest;\n state: PathfindingState;\n options: Required<IPathfindingOptions>;\n\n openList: IndexedBinaryHeap<AStarNode>;\n nodeCache: Map<string | number, AStarNode>;\n\n startNode: IPathNode;\n endNode: IPathNode;\n endPosition: IPoint;\n\n nodesSearched: number;\n framesUsed: number;\n initialDistance: number;\n\n result: IIncrementalPathResult | null;\n\n affectedByChange: boolean;\n}\n\n/**\n * @zh 障碍物变化区域\n * @en Obstacle change region\n */\ninterface ChangeRegion {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n timestamp: number;\n}\n\n/**\n * @zh 增量寻路器配置\n * @en Incremental pathfinder configuration\n */\nexport interface IIncrementalPathfinderConfig {\n /**\n * @zh 是否启用路径缓存\n * @en Whether to enable path caching\n */\n enableCache?: boolean;\n\n /**\n * @zh 缓存配置\n * @en Cache configuration\n */\n cacheConfig?: Partial<IPathCacheConfig>;\n}\n\n// =============================================================================\n// 增量 A* 寻路器 | Incremental A* Pathfinder\n// =============================================================================\n\n/**\n * @zh 增量 A* 寻路器\n * @en Incremental A* Pathfinder\n *\n * @zh 支持时间切片的 A* 算法实现,可跨多帧执行搜索\n * @en A* algorithm implementation with time slicing, can execute search across multiple frames\n *\n * @example\n * ```typescript\n * const map = createGridMap(100, 100);\n * const pathfinder = createIncrementalAStarPathfinder(map);\n *\n * // Request path (non-blocking)\n * const request = pathfinder.requestPath(0, 0, 99, 99);\n *\n * // Process over multiple frames\n * function gameLoop() {\n * const progress = pathfinder.step(request.id, 100);\n *\n * if (progress.state === PathfindingState.Completed) {\n * const result = pathfinder.getResult(request.id);\n * console.log('Path found:', result?.path);\n * } else if (progress.state === PathfindingState.InProgress) {\n * requestAnimationFrame(gameLoop);\n * }\n * }\n * gameLoop();\n * ```\n */\nexport class IncrementalAStarPathfinder implements IIncrementalPathfinder {\n private readonly map: IPathfindingMap;\n private readonly sessions: Map<number, PathfindingSession> = new Map();\n private nextRequestId: number = 0;\n\n private readonly affectedRegions: ChangeRegion[] = [];\n private readonly maxRegionAge: number = 5000;\n\n private readonly cache: PathCache | null;\n private readonly enableCache: boolean;\n private mapVersion: number = 0;\n\n private cacheHits: number = 0;\n private cacheMisses: number = 0;\n\n /**\n * @zh 创建增量 A* 寻路器\n * @en Create incremental A* pathfinder\n *\n * @param map - @zh 寻路地图实例 @en Pathfinding map instance\n * @param config - @zh 配置选项 @en Configuration options\n */\n constructor(map: IPathfindingMap, config?: IIncrementalPathfinderConfig) {\n this.map = map;\n this.enableCache = config?.enableCache ?? false;\n this.cache = this.enableCache ? new PathCache(config?.cacheConfig) : null;\n }\n\n /**\n * @zh 请求寻路(非阻塞)\n * @en Request pathfinding (non-blocking)\n */\n requestPath(\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: IIncrementalPathfindingOptions\n ): IPathRequest {\n const id = this.nextRequestId++;\n const priority = options?.priority ?? 50;\n const opts = { ...DEFAULT_PATHFINDING_OPTIONS, ...options };\n\n const request: IPathRequest = {\n id,\n startX,\n startY,\n endX,\n endY,\n options: opts,\n priority,\n createdAt: Date.now()\n };\n\n if (this.cache) {\n const cached = this.cache.get(startX, startY, endX, endY, this.mapVersion);\n if (cached) {\n this.cacheHits++;\n const session: PathfindingSession = {\n request,\n state: cached.found ? PathfindingState.Completed : PathfindingState.Failed,\n options: opts,\n openList: new IndexedBinaryHeap<AStarNode>((a, b) => a.f - b.f),\n nodeCache: new Map(),\n startNode: this.map.getNodeAt(startX, startY)!,\n endNode: this.map.getNodeAt(endX, endY)!,\n endPosition: { x: endX, y: endY },\n nodesSearched: cached.nodesSearched,\n framesUsed: 0,\n initialDistance: 0,\n result: {\n requestId: id,\n found: cached.found,\n path: [...cached.path],\n cost: cached.cost,\n nodesSearched: cached.nodesSearched,\n framesUsed: 0,\n isPartial: false\n },\n affectedByChange: false\n };\n this.sessions.set(id, session);\n return request;\n }\n this.cacheMisses++;\n }\n\n const startNode = this.map.getNodeAt(startX, startY);\n const endNode = this.map.getNodeAt(endX, endY);\n\n if (!startNode || !endNode || !startNode.walkable || !endNode.walkable) {\n const session: PathfindingSession = {\n request,\n state: PathfindingState.Failed,\n options: opts,\n openList: new IndexedBinaryHeap<AStarNode>((a, b) => a.f - b.f),\n nodeCache: new Map(),\n startNode: startNode!,\n endNode: endNode!,\n endPosition: endNode?.position ?? { x: endX, y: endY },\n nodesSearched: 0,\n framesUsed: 0,\n initialDistance: 0,\n result: this.createEmptyResult(id),\n affectedByChange: false\n };\n this.sessions.set(id, session);\n return request;\n }\n\n if (startNode.id === endNode.id) {\n const session: PathfindingSession = {\n request,\n state: PathfindingState.Completed,\n options: opts,\n openList: new IndexedBinaryHeap<AStarNode>((a, b) => a.f - b.f),\n nodeCache: new Map(),\n startNode,\n endNode,\n endPosition: endNode.position,\n nodesSearched: 1,\n framesUsed: 0,\n initialDistance: 0,\n result: {\n requestId: id,\n found: true,\n path: [startNode.position],\n cost: 0,\n nodesSearched: 1,\n framesUsed: 0,\n isPartial: false\n },\n affectedByChange: false\n };\n this.sessions.set(id, session);\n return request;\n }\n\n const initialDistance = this.map.heuristic(startNode.position, endNode.position);\n const openList = new IndexedBinaryHeap<AStarNode>((a, b) => a.f - b.f);\n const nodeCache = new Map<string | number, AStarNode>();\n\n const startAStarNode: AStarNode = {\n node: startNode,\n g: 0,\n h: initialDistance * opts.heuristicWeight,\n f: initialDistance * opts.heuristicWeight,\n parent: null,\n closed: false,\n opened: true,\n heapIndex: -1\n };\n\n nodeCache.set(startNode.id, startAStarNode);\n openList.push(startAStarNode);\n\n const session: PathfindingSession = {\n request,\n state: PathfindingState.InProgress,\n options: opts,\n openList,\n nodeCache,\n startNode,\n endNode,\n endPosition: endNode.position,\n nodesSearched: 0,\n framesUsed: 0,\n initialDistance,\n result: null,\n affectedByChange: false\n };\n\n this.sessions.set(id, session);\n return request;\n }\n\n /**\n * @zh 执行一步搜索\n * @en Execute one step of search\n */\n step(requestId: number, maxIterations: number): IPathProgress {\n const session = this.sessions.get(requestId);\n if (!session) {\n return EMPTY_PROGRESS;\n }\n\n if (session.state !== PathfindingState.InProgress) {\n return this.createProgress(session);\n }\n\n session.framesUsed++;\n let iterations = 0;\n\n while (!session.openList.isEmpty && iterations < maxIterations) {\n const current = session.openList.pop()!;\n current.closed = true;\n session.nodesSearched++;\n iterations++;\n\n if (current.node.id === session.endNode.id) {\n session.state = PathfindingState.Completed;\n session.result = this.buildResult(session, current);\n\n if (this.cache && session.result.found) {\n const req = session.request;\n this.cache.set(\n req.startX, req.startY,\n req.endX, req.endY,\n {\n found: true,\n path: session.result.path,\n cost: session.result.cost,\n nodesSearched: session.result.nodesSearched\n },\n this.mapVersion\n );\n }\n\n return this.createProgress(session);\n }\n\n this.expandNeighbors(session, current);\n\n if (session.nodesSearched >= session.options.maxNodes) {\n session.state = PathfindingState.Failed;\n session.result = this.createEmptyResult(requestId);\n return this.createProgress(session);\n }\n }\n\n if (session.openList.isEmpty && session.state === PathfindingState.InProgress) {\n session.state = PathfindingState.Failed;\n session.result = this.createEmptyResult(requestId);\n }\n\n return this.createProgress(session);\n }\n\n /**\n * @zh 暂停寻路\n * @en Pause pathfinding\n */\n pause(requestId: number): void {\n const session = this.sessions.get(requestId);\n if (session && session.state === PathfindingState.InProgress) {\n session.state = PathfindingState.Paused;\n }\n }\n\n /**\n * @zh 恢复寻路\n * @en Resume pathfinding\n */\n resume(requestId: number): void {\n const session = this.sessions.get(requestId);\n if (session && session.state === PathfindingState.Paused) {\n session.state = PathfindingState.InProgress;\n }\n }\n\n /**\n * @zh 取消寻路\n * @en Cancel pathfinding\n */\n cancel(requestId: number): void {\n const session = this.sessions.get(requestId);\n if (session && (session.state === PathfindingState.InProgress ||\n session.state === PathfindingState.Paused)) {\n session.state = PathfindingState.Cancelled;\n session.result = this.createEmptyResult(requestId);\n }\n }\n\n /**\n * @zh 获取寻路结果\n * @en Get pathfinding result\n */\n getResult(requestId: number): IIncrementalPathResult | null {\n const session = this.sessions.get(requestId);\n return session?.result ?? null;\n }\n\n /**\n * @zh 获取当前进度\n * @en Get current progress\n */\n getProgress(requestId: number): IPathProgress | null {\n const session = this.sessions.get(requestId);\n return session ? this.createProgress(session) : null;\n }\n\n /**\n * @zh 清理已完成的请求\n * @en Clean up completed request\n */\n cleanup(requestId: number): void {\n const session = this.sessions.get(requestId);\n if (session) {\n session.openList.clear();\n session.nodeCache.clear();\n this.sessions.delete(requestId);\n }\n }\n\n /**\n * @zh 通知障碍物变化\n * @en Notify obstacle change\n */\n notifyObstacleChange(\n minX: number,\n minY: number,\n maxX: number,\n maxY: number\n ): void {\n this.mapVersion++;\n\n if (this.cache) {\n this.cache.invalidateRegion(minX, minY, maxX, maxY);\n }\n\n const region: ChangeRegion = {\n minX,\n minY,\n maxX,\n maxY,\n timestamp: Date.now()\n };\n this.affectedRegions.push(region);\n\n for (const session of this.sessions.values()) {\n if (session.state === PathfindingState.InProgress ||\n session.state === PathfindingState.Paused) {\n if (this.sessionAffectedByRegion(session, region)) {\n session.affectedByChange = true;\n }\n }\n }\n\n this.cleanupOldRegions();\n }\n\n /**\n * @zh 清理所有请求\n * @en Clear all requests\n */\n clear(): void {\n for (const session of this.sessions.values()) {\n session.openList.clear();\n session.nodeCache.clear();\n }\n this.sessions.clear();\n this.affectedRegions.length = 0;\n }\n\n /**\n * @zh 清空路径缓存\n * @en Clear path cache\n */\n clearCache(): void {\n if (this.cache) {\n this.cache.invalidateAll();\n this.cacheHits = 0;\n this.cacheMisses = 0;\n }\n }\n\n /**\n * @zh 获取缓存统计信息\n * @en Get cache statistics\n */\n getCacheStats(): { enabled: boolean; hits: number; misses: number; hitRate: number; size: number } {\n if (!this.cache) {\n return { enabled: false, hits: 0, misses: 0, hitRate: 0, size: 0 };\n }\n\n const total = this.cacheHits + this.cacheMisses;\n const hitRate = total > 0 ? this.cacheHits / total : 0;\n\n return {\n enabled: true,\n hits: this.cacheHits,\n misses: this.cacheMisses,\n hitRate,\n size: this.cache.getStats().size\n };\n }\n\n /**\n * @zh 检查会话是否被障碍物变化影响\n * @en Check if session is affected by obstacle change\n */\n isAffectedByChange(requestId: number): boolean {\n const session = this.sessions.get(requestId);\n return session?.affectedByChange ?? false;\n }\n\n /**\n * @zh 清除会话的变化标记\n * @en Clear session's change flag\n */\n clearChangeFlag(requestId: number): void {\n const session = this.sessions.get(requestId);\n if (session) {\n session.affectedByChange = false;\n }\n }\n\n // =========================================================================\n // 私有方法 | Private Methods\n // =========================================================================\n\n /**\n * @zh 展开邻居节点\n * @en Expand neighbor nodes\n */\n private expandNeighbors(session: PathfindingSession, current: AStarNode): void {\n const neighbors = this.map.getNeighbors(current.node);\n\n for (const neighborNode of neighbors) {\n if (!neighborNode.walkable) {\n continue;\n }\n\n let neighbor = session.nodeCache.get(neighborNode.id);\n\n if (!neighbor) {\n neighbor = {\n node: neighborNode,\n g: Infinity,\n h: 0,\n f: Infinity,\n parent: null,\n closed: false,\n opened: false,\n heapIndex: -1\n };\n session.nodeCache.set(neighborNode.id, neighbor);\n }\n\n if (neighbor.closed) {\n continue;\n }\n\n const movementCost = this.map.getMovementCost(current.node, neighborNode);\n const tentativeG = current.g + movementCost;\n\n if (!neighbor.opened) {\n neighbor.g = tentativeG;\n neighbor.h = this.map.heuristic(neighborNode.position, session.endPosition) *\n session.options.heuristicWeight;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n neighbor.opened = true;\n session.openList.push(neighbor);\n } else if (tentativeG < neighbor.g) {\n neighbor.g = tentativeG;\n neighbor.f = neighbor.g + neighbor.h;\n neighbor.parent = current;\n session.openList.update(neighbor);\n }\n }\n }\n\n /**\n * @zh 创建进度对象\n * @en Create progress object\n */\n private createProgress(session: PathfindingSession): IPathProgress {\n let estimatedProgress = 0;\n\n if (session.state === PathfindingState.Completed) {\n estimatedProgress = 1;\n } else if (session.state === PathfindingState.InProgress && session.initialDistance > 0) {\n const bestNode = session.openList.peek();\n if (bestNode) {\n const currentDistance = bestNode.h / session.options.heuristicWeight;\n estimatedProgress = Math.max(0, Math.min(1,\n 1 - (currentDistance / session.initialDistance)\n ));\n }\n }\n\n return {\n state: session.state,\n nodesSearched: session.nodesSearched,\n openListSize: session.openList.size,\n estimatedProgress\n };\n }\n\n /**\n * @zh 构建路径结果\n * @en Build path result\n */\n private buildResult(session: PathfindingSession, endNode: AStarNode): IIncrementalPathResult {\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 requestId: session.request.id,\n found: true,\n path,\n cost: endNode.g,\n nodesSearched: session.nodesSearched,\n framesUsed: session.framesUsed,\n isPartial: false\n };\n }\n\n /**\n * @zh 创建空结果\n * @en Create empty result\n */\n private createEmptyResult(requestId: number): IIncrementalPathResult {\n return {\n requestId,\n found: false,\n path: [],\n cost: 0,\n nodesSearched: 0,\n framesUsed: 0,\n isPartial: false\n };\n }\n\n /**\n * @zh 检查会话是否被区域影响\n * @en Check if session is affected by region\n */\n private sessionAffectedByRegion(session: PathfindingSession, region: ChangeRegion): boolean {\n for (const astarNode of session.nodeCache.values()) {\n if (astarNode.opened || astarNode.closed) {\n const pos = astarNode.node.position;\n if (pos.x >= region.minX && pos.x <= region.maxX &&\n pos.y >= region.minY && pos.y <= region.maxY) {\n return true;\n }\n }\n }\n\n const start = session.request;\n const end = session.endPosition;\n\n if ((start.startX >= region.minX && start.startX <= region.maxX &&\n start.startY >= region.minY && start.startY <= region.maxY) ||\n (end.x >= region.minX && end.x <= region.maxX &&\n end.y >= region.minY && end.y <= region.maxY)) {\n return true;\n }\n\n return false;\n }\n\n /**\n * @zh 清理过期的变化区域\n * @en Clean up expired change regions\n */\n private cleanupOldRegions(): void {\n const now = Date.now();\n let i = 0;\n while (i < this.affectedRegions.length) {\n if (now - this.affectedRegions[i].timestamp > this.maxRegionAge) {\n this.affectedRegions.splice(i, 1);\n } else {\n i++;\n }\n }\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建增量 A* 寻路器\n * @en Create incremental A* pathfinder\n *\n * @param map - @zh 寻路地图实例 @en Pathfinding map instance\n * @returns @zh 增量 A* 寻路器实例 @en Incremental A* pathfinder instance\n */\nexport function createIncrementalAStarPathfinder(map: IPathfindingMap): IncrementalAStarPathfinder {\n return new IncrementalAStarPathfinder(map);\n}\n","/**\n * @zh 路径验证器\n * @en Path Validator\n */\n\nimport type { IPoint, IPathfindingMap } from './IPathfinding';\nimport type { IPathValidator, IPathValidationResult } from './IIncrementalPathfinding';\n\n// =============================================================================\n// 路径验证器 | Path Validator\n// =============================================================================\n\n/**\n * @zh 路径验证器\n * @en Path Validator\n *\n * @zh 用于检查现有路径在地图变化后是否仍然有效\n * @en Used to check if an existing path is still valid after map changes\n *\n * @example\n * ```typescript\n * const validator = new PathValidator();\n * const result = validator.validatePath(path, 0, path.length, map);\n *\n * if (!result.valid) {\n * console.log('Path invalid at index:', result.invalidIndex);\n * // Trigger replanning from current position\n * }\n * ```\n */\nexport class PathValidator implements IPathValidator {\n /**\n * @zh 验证路径段的有效性\n * @en Validate path segment validity\n *\n * @param path - @zh 要验证的路径 @en Path to validate\n * @param fromIndex - @zh 起始索引 @en Start index\n * @param toIndex - @zh 结束索引 @en End index\n * @param map - @zh 地图实例 @en Map instance\n * @returns @zh 验证结果 @en Validation result\n */\n validatePath(\n path: readonly IPoint[],\n fromIndex: number,\n toIndex: number,\n map: IPathfindingMap\n ): IPathValidationResult {\n const end = Math.min(toIndex, path.length);\n\n for (let i = fromIndex; i < end; i++) {\n const point = path[i];\n const x = Math.floor(point.x);\n const y = Math.floor(point.y);\n\n if (!map.isWalkable(x, y)) {\n return { valid: false, invalidIndex: i };\n }\n\n if (i > fromIndex) {\n const prev = path[i - 1];\n if (!this.checkLineOfSight(prev.x, prev.y, point.x, point.y, map)) {\n return { valid: false, invalidIndex: i };\n }\n }\n }\n\n return { valid: true, invalidIndex: -1 };\n }\n\n /**\n * @zh 检查两点之间的视线(使用 Bresenham 算法)\n * @en Check line of sight between two points (using Bresenham algorithm)\n *\n * @param x1 - @zh 起点 X @en Start X\n * @param y1 - @zh 起点 Y @en Start Y\n * @param x2 - @zh 终点 X @en End X\n * @param y2 - @zh 终点 Y @en End Y\n * @param map - @zh 地图实例 @en Map instance\n * @returns @zh 是否有视线 @en Whether there is line of sight\n */\n private checkLineOfSight(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap\n ): boolean {\n const ix1 = Math.floor(x1);\n const iy1 = Math.floor(y1);\n const ix2 = Math.floor(x2);\n const iy2 = Math.floor(y2);\n\n let dx = Math.abs(ix2 - ix1);\n let dy = Math.abs(iy2 - iy1);\n let x = ix1;\n let y = iy1;\n\n const sx = ix1 < ix2 ? 1 : -1;\n const sy = iy1 < iy2 ? 1 : -1;\n\n if (dx > dy) {\n let err = dx / 2;\n while (x !== ix2) {\n if (!map.isWalkable(x, y)) {\n return false;\n }\n err -= dy;\n if (err < 0) {\n y += sy;\n err += dx;\n }\n x += sx;\n }\n } else {\n let err = dy / 2;\n while (y !== iy2) {\n if (!map.isWalkable(x, y)) {\n return false;\n }\n err -= dx;\n if (err < 0) {\n x += sx;\n err += dy;\n }\n y += sy;\n }\n }\n\n return map.isWalkable(ix2, iy2);\n }\n}\n\n// =============================================================================\n// 障碍物变化管理器 | Obstacle Change Manager\n// =============================================================================\n\n/**\n * @zh 障碍物变化记录\n * @en Obstacle change record\n */\nexport interface IObstacleChange {\n /**\n * @zh X 坐标\n * @en X coordinate\n */\n readonly x: number;\n\n /**\n * @zh Y 坐标\n * @en Y coordinate\n */\n readonly y: number;\n\n /**\n * @zh 变化前是否可通行\n * @en Was walkable before change\n */\n readonly wasWalkable: boolean;\n\n /**\n * @zh 变化时间戳\n * @en Change timestamp\n */\n readonly timestamp: number;\n}\n\n/**\n * @zh 障碍物变化区域\n * @en Obstacle change region\n */\nexport interface IChangeRegion {\n /**\n * @zh 最小 X 坐标\n * @en Minimum X coordinate\n */\n readonly minX: number;\n\n /**\n * @zh 最小 Y 坐标\n * @en Minimum Y coordinate\n */\n readonly minY: number;\n\n /**\n * @zh 最大 X 坐标\n * @en Maximum X coordinate\n */\n readonly maxX: number;\n\n /**\n * @zh 最大 Y 坐标\n * @en Maximum Y coordinate\n */\n readonly maxY: number;\n}\n\n/**\n * @zh 障碍物变化管理器\n * @en Obstacle Change Manager\n *\n * @zh 跟踪地图障碍物变化,用于触发动态重规划\n * @en Tracks map obstacle changes, used to trigger dynamic replanning\n *\n * @example\n * ```typescript\n * const manager = new ObstacleChangeManager();\n *\n * // Record change when obstacle is added/removed\n * manager.recordChange(10, 20, true); // Was walkable, now blocked\n *\n * // Get affected region for notification\n * const region = manager.getAffectedRegion();\n * if (region) {\n * pathfinder.notifyObstacleChange(\n * region.minX, region.minY,\n * region.maxX, region.maxY\n * );\n * }\n *\n * // Clear after notification\n * manager.flush();\n * ```\n */\nexport class ObstacleChangeManager {\n private readonly changes: Map<string, IObstacleChange> = new Map();\n private epoch: number = 0;\n\n /**\n * @zh 记录障碍物变化\n * @en Record obstacle change\n *\n * @param x - @zh X 坐标 @en X coordinate\n * @param y - @zh Y 坐标 @en Y coordinate\n * @param wasWalkable - @zh 变化前是否可通行 @en Was walkable before change\n */\n recordChange(x: number, y: number, wasWalkable: boolean): void {\n const key = `${x},${y}`;\n this.changes.set(key, {\n x,\n y,\n wasWalkable,\n timestamp: Date.now()\n });\n }\n\n /**\n * @zh 获取影响区域\n * @en Get affected region\n *\n * @returns @zh 影响区域或 null(如果没有变化)@en Affected region or null if no changes\n */\n getAffectedRegion(): IChangeRegion | null {\n if (this.changes.size === 0) {\n return null;\n }\n\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n\n for (const change of this.changes.values()) {\n minX = Math.min(minX, change.x);\n minY = Math.min(minY, change.y);\n maxX = Math.max(maxX, change.x);\n maxY = Math.max(maxY, change.y);\n }\n\n return { minX, minY, maxX, maxY };\n }\n\n /**\n * @zh 获取所有变化\n * @en Get all changes\n *\n * @returns @zh 变化列表 @en List of changes\n */\n getChanges(): IObstacleChange[] {\n return Array.from(this.changes.values());\n }\n\n /**\n * @zh 检查是否有变化\n * @en Check if there are changes\n *\n * @returns @zh 是否有变化 @en Whether there are changes\n */\n hasChanges(): boolean {\n return this.changes.size > 0;\n }\n\n /**\n * @zh 获取当前 epoch\n * @en Get current epoch\n *\n * @returns @zh 当前 epoch @en Current epoch\n */\n getEpoch(): number {\n return this.epoch;\n }\n\n /**\n * @zh 清空变化记录并推进 epoch\n * @en Clear changes and advance epoch\n */\n flush(): void {\n this.changes.clear();\n this.epoch++;\n }\n\n /**\n * @zh 清空所有状态\n * @en Clear all state\n */\n clear(): void {\n this.changes.clear();\n this.epoch = 0;\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建路径验证器\n * @en Create path validator\n *\n * @returns @zh 路径验证器实例 @en Path validator instance\n */\nexport function createPathValidator(): PathValidator {\n return new PathValidator();\n}\n\n/**\n * @zh 创建障碍物变化管理器\n * @en Create obstacle change manager\n *\n * @returns @zh 障碍物变化管理器实例 @en Obstacle change manager instance\n */\nexport function createObstacleChangeManager(): ObstacleChangeManager {\n return new ObstacleChangeManager();\n}\n","/**\n * @zh 网格地图实现\n * @en Grid Map Implementation\n */\n\nimport type {\n IPathfindingMap,\n IPathNode,\n IPoint,\n HeuristicFunction\n} from '../core/IPathfinding';\nimport { createPoint, octileDistance } from '../core/IPathfinding';\n\n// =============================================================================\n// 网格节点 | Grid Node\n// =============================================================================\n\n/**\n * @zh 网格节点\n * @en Grid node\n */\nexport class GridNode implements IPathNode {\n readonly id: number;\n readonly position: IPoint;\n readonly x: number;\n readonly y: number;\n cost: number;\n walkable: boolean;\n\n constructor(x: number, y: number, width: number, walkable: boolean = true, cost: number = 1) {\n this.x = x;\n this.y = y;\n this.id = y * width + x;\n this.position = createPoint(x, y);\n this.walkable = walkable;\n this.cost = cost;\n }\n}\n\n// =============================================================================\n// 移动方向 | Movement Directions\n// =============================================================================\n\n/**\n * @zh 4方向偏移 (上下左右)\n * @en 4-directional offsets (up, down, left, right)\n */\nexport const DIRECTIONS_4 = [\n { dx: 0, dy: -1 }, // Up\n { dx: 1, dy: 0 }, // Right\n { dx: 0, dy: 1 }, // Down\n { dx: -1, dy: 0 } // Left\n] as const;\n\n/**\n * @zh 8方向偏移 (含对角线)\n * @en 8-directional offsets (including diagonals)\n */\nexport const DIRECTIONS_8 = [\n { dx: 0, dy: -1 }, // Up\n { dx: 1, dy: -1 }, // Up-Right\n { dx: 1, dy: 0 }, // Right\n { dx: 1, dy: 1 }, // Down-Right\n { dx: 0, dy: 1 }, // Down\n { dx: -1, dy: 1 }, // Down-Left\n { dx: -1, dy: 0 }, // Left\n { dx: -1, dy: -1 } // Up-Left\n] as const;\n\n// =============================================================================\n// 网格地图配置 | Grid Map Options\n// =============================================================================\n\n/**\n * @zh 网格地图配置\n * @en Grid map options\n */\nexport interface IGridMapOptions {\n /** @zh 是否允许对角移动 @en Allow diagonal movement */\n allowDiagonal?: boolean;\n /** @zh 对角移动代价 @en Diagonal movement cost */\n diagonalCost?: number;\n /** @zh 是否避免穿角 @en Avoid corner cutting */\n avoidCorners?: boolean;\n /** @zh 启发式函数 @en Heuristic function */\n heuristic?: HeuristicFunction;\n}\n\n/**\n * @zh 默认网格地图配置\n * @en Default grid map options\n */\nexport const DEFAULT_GRID_OPTIONS: Required<IGridMapOptions> = {\n allowDiagonal: true,\n diagonalCost: Math.SQRT2,\n avoidCorners: true,\n heuristic: octileDistance\n};\n\n// =============================================================================\n// 网格地图 | Grid Map\n// =============================================================================\n\n/**\n * @zh 网格地图\n * @en Grid Map\n *\n * @zh 基于二维数组的网格地图实现,支持4方向和8方向移动\n * @en Grid map implementation based on 2D array, supports 4 and 8 directional movement\n *\n * @example\n * ```typescript\n * // Create a 10x10 grid\n * const grid = new GridMap(10, 10);\n *\n * // Set some cells as obstacles\n * grid.setWalkable(5, 5, false);\n * grid.setWalkable(5, 6, false);\n *\n * // Use with pathfinder\n * const pathfinder = new AStarPathfinder(grid);\n * const result = pathfinder.findPath(0, 0, 9, 9);\n * ```\n */\nexport class GridMap implements IPathfindingMap {\n readonly width: number;\n readonly height: number;\n private readonly nodes: GridNode[][];\n private readonly options: Required<IGridMapOptions>;\n\n constructor(width: number, height: number, options?: IGridMapOptions) {\n this.width = width;\n this.height = height;\n this.options = { ...DEFAULT_GRID_OPTIONS, ...options };\n this.nodes = this.createNodes();\n }\n\n /**\n * @zh 创建网格节点\n * @en Create grid nodes\n */\n private createNodes(): GridNode[][] {\n const nodes: GridNode[][] = [];\n\n for (let y = 0; y < this.height; y++) {\n nodes[y] = [];\n for (let x = 0; x < this.width; x++) {\n nodes[y][x] = new GridNode(x, y, this.width, true, 1);\n }\n }\n\n return nodes;\n }\n\n /**\n * @zh 获取指定位置的节点\n * @en Get node at position\n */\n getNodeAt(x: number, y: number): GridNode | null {\n if (!this.isInBounds(x, y)) {\n return null;\n }\n return this.nodes[y][x];\n }\n\n /**\n * @zh 检查坐标是否在边界内\n * @en Check if coordinates are within bounds\n */\n isInBounds(x: number, y: number): boolean {\n return x >= 0 && x < this.width && y >= 0 && y < this.height;\n }\n\n /**\n * @zh 检查位置是否可通行\n * @en Check if position is walkable\n */\n isWalkable(x: number, y: number): boolean {\n const node = this.getNodeAt(x, y);\n return node !== null && node.walkable;\n }\n\n /**\n * @zh 设置位置是否可通行\n * @en Set position walkability\n */\n setWalkable(x: number, y: number, walkable: boolean): void {\n const node = this.getNodeAt(x, y);\n if (node) {\n node.walkable = walkable;\n }\n }\n\n /**\n * @zh 设置位置的移动代价\n * @en Set movement cost at position\n */\n setCost(x: number, y: number, cost: number): void {\n const node = this.getNodeAt(x, y);\n if (node) {\n node.cost = cost;\n }\n }\n\n /**\n * @zh 获取节点的邻居\n * @en Get neighbors of a node\n */\n getNeighbors(node: IPathNode): GridNode[] {\n const neighbors: GridNode[] = [];\n const { x, y } = node.position;\n const directions = this.options.allowDiagonal ? DIRECTIONS_8 : DIRECTIONS_4;\n\n for (let i = 0; i < directions.length; i++) {\n const dir = directions[i];\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 const neighbor = this.nodes[ny][nx];\n\n if (!neighbor.walkable) {\n continue;\n }\n\n if (this.options.avoidCorners && dir.dx !== 0 && dir.dy !== 0) {\n const hNode = this.nodes[y][x + dir.dx];\n const vNode = this.nodes[y + dir.dy][x];\n\n if (!hNode.walkable || !vNode.walkable) {\n continue;\n }\n }\n\n neighbors.push(neighbor);\n }\n\n return neighbors;\n }\n\n /**\n * @zh 遍历节点的邻居(零分配)\n * @en Iterate over neighbors (zero allocation)\n */\n forEachNeighbor(node: IPathNode, callback: (neighbor: GridNode) => boolean | void): void {\n const { x, y } = node.position;\n const directions = this.options.allowDiagonal ? DIRECTIONS_8 : DIRECTIONS_4;\n\n for (let i = 0; i < directions.length; i++) {\n const dir = directions[i];\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 const neighbor = this.nodes[ny][nx];\n\n if (!neighbor.walkable) {\n continue;\n }\n\n if (this.options.avoidCorners && dir.dx !== 0 && dir.dy !== 0) {\n const hNode = this.nodes[y][x + dir.dx];\n const vNode = this.nodes[y + dir.dy][x];\n\n if (!hNode.walkable || !vNode.walkable) {\n continue;\n }\n }\n\n if (callback(neighbor) === false) {\n return;\n }\n }\n }\n\n /**\n * @zh 计算启发式距离\n * @en Calculate heuristic distance\n */\n heuristic(a: IPoint, b: IPoint): number {\n return this.options.heuristic(a, b);\n }\n\n /**\n * @zh 计算移动代价\n * @en Calculate movement cost\n */\n getMovementCost(from: IPathNode, to: IPathNode): number {\n const dx = Math.abs(from.position.x - to.position.x);\n const dy = Math.abs(from.position.y - to.position.y);\n\n // Diagonal movement\n if (dx !== 0 && dy !== 0) {\n return to.cost * this.options.diagonalCost;\n }\n\n // Cardinal movement\n return to.cost;\n }\n\n /**\n * @zh 从二维数组加载地图\n * @en Load map from 2D array\n *\n * @param data - @zh 0=可通行,非0=不可通行 @en 0=walkable, non-0=blocked\n */\n loadFromArray(data: number[][]): void {\n for (let y = 0; y < Math.min(data.length, this.height); y++) {\n for (let x = 0; x < Math.min(data[y].length, this.width); x++) {\n this.nodes[y][x].walkable = data[y][x] === 0;\n }\n }\n }\n\n /**\n * @zh 从字符串加载地图\n * @en Load map from string\n *\n * @param str - @zh 地图字符串,'.'=可通行,'#'=障碍 @en Map string, '.'=walkable, '#'=blocked\n */\n loadFromString(str: string): void {\n const lines = str.trim().split('\\n');\n\n for (let y = 0; y < Math.min(lines.length, this.height); y++) {\n const line = lines[y];\n for (let x = 0; x < Math.min(line.length, this.width); x++) {\n this.nodes[y][x].walkable = line[x] !== '#';\n }\n }\n }\n\n /**\n * @zh 导出为字符串\n * @en Export to string\n */\n toString(): string {\n let result = '';\n\n for (let y = 0; y < this.height; y++) {\n for (let x = 0; x < this.width; x++) {\n result += this.nodes[y][x].walkable ? '.' : '#';\n }\n result += '\\n';\n }\n\n return result;\n }\n\n /**\n * @zh 重置所有节点为可通行\n * @en Reset all nodes to walkable\n */\n reset(): void {\n for (let y = 0; y < this.height; y++) {\n for (let x = 0; x < this.width; x++) {\n this.nodes[y][x].walkable = true;\n this.nodes[y][x].cost = 1;\n }\n }\n }\n\n /**\n * @zh 设置矩形区域的通行性\n * @en Set walkability for a rectangle region\n */\n setRectWalkable(\n x: number,\n y: number,\n width: number,\n height: number,\n walkable: boolean\n ): void {\n for (let dy = 0; dy < height; dy++) {\n for (let dx = 0; dx < width; dx++) {\n this.setWalkable(x + dx, y + dy, walkable);\n }\n }\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Function\n// =============================================================================\n\n/**\n * @zh 创建网格地图\n * @en Create grid map\n */\nexport function createGridMap(\n width: number,\n height: number,\n options?: IGridMapOptions\n): GridMap {\n return new GridMap(width, height, options);\n}\n","/**\n * @zh 路径平滑算法\n * @en Path Smoothing Algorithms\n */\n\nimport type {\n IPathfindingMap,\n IPathSmoother,\n IPoint\n} from '../core/IPathfinding';\nimport { createPoint } from '../core/IPathfinding';\n\n// =============================================================================\n// 视线检测 | Line of Sight\n// =============================================================================\n\n/**\n * @zh 使用 Bresenham 算法检测视线\n * @en Line of sight check using Bresenham algorithm\n */\nexport function bresenhamLineOfSight(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap\n): boolean {\n // Round to grid coordinates\n let ix1 = Math.floor(x1);\n let iy1 = Math.floor(y1);\n const ix2 = Math.floor(x2);\n const iy2 = Math.floor(y2);\n\n const dx = Math.abs(ix2 - ix1);\n const dy = Math.abs(iy2 - iy1);\n\n const sx = ix1 < ix2 ? 1 : -1;\n const sy = iy1 < iy2 ? 1 : -1;\n\n let err = dx - dy;\n\n while (true) {\n if (!map.isWalkable(ix1, iy1)) {\n return false;\n }\n\n if (ix1 === ix2 && iy1 === iy2) {\n break;\n }\n\n const e2 = 2 * err;\n\n if (e2 > -dy) {\n err -= dy;\n ix1 += sx;\n }\n\n if (e2 < dx) {\n err += dx;\n iy1 += sy;\n }\n }\n\n return true;\n}\n\n/**\n * @zh 使用射线投射检测视线(更精确)\n * @en Line of sight check using ray casting (more precise)\n */\nexport function raycastLineOfSight(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n map: IPathfindingMap,\n stepSize: number = 0.5\n): boolean {\n const dx = x2 - x1;\n const dy = y2 - y1;\n const distance = Math.sqrt(dx * dx + dy * dy);\n\n if (distance === 0) {\n return map.isWalkable(Math.floor(x1), Math.floor(y1));\n }\n\n const steps = Math.ceil(distance / stepSize);\n const stepX = dx / steps;\n const stepY = dy / steps;\n\n let x = x1;\n let y = y1;\n\n for (let i = 0; i <= steps; i++) {\n if (!map.isWalkable(Math.floor(x), Math.floor(y))) {\n return false;\n }\n x += stepX;\n y += stepY;\n }\n\n return true;\n}\n\n// =============================================================================\n// 路径简化器(拐点移除)| Path Simplifier (Waypoint Removal)\n// =============================================================================\n\n/**\n * @zh 路径简化器 - 移除不必要的拐点\n * @en Path Simplifier - Removes unnecessary waypoints\n *\n * @zh 使用视线检测移除可以直接到达的中间点\n * @en Uses line of sight to remove intermediate points that can be reached directly\n */\nexport class LineOfSightSmoother implements IPathSmoother {\n private readonly lineOfSight: typeof bresenhamLineOfSight;\n\n constructor(lineOfSight: typeof bresenhamLineOfSight = bresenhamLineOfSight) {\n this.lineOfSight = lineOfSight;\n }\n\n smooth(path: readonly IPoint[], map: IPathfindingMap): IPoint[] {\n if (path.length <= 2) {\n return [...path];\n }\n\n const result: IPoint[] = [path[0]];\n let current = 0;\n\n while (current < path.length - 1) {\n // Find the furthest point we can see from current\n let furthest = current + 1;\n\n for (let i = path.length - 1; i > current + 1; i--) {\n if (this.lineOfSight(\n path[current].x,\n path[current].y,\n path[i].x,\n path[i].y,\n map\n )) {\n furthest = i;\n break;\n }\n }\n\n result.push(path[furthest]);\n current = furthest;\n }\n\n return result;\n }\n}\n\n// =============================================================================\n// 曲线平滑器 | Curve Smoother\n// =============================================================================\n\n/**\n * @zh Catmull-Rom 样条曲线平滑\n * @en Catmull-Rom spline smoothing\n */\nexport class CatmullRomSmoother implements IPathSmoother {\n private readonly segments: number;\n private readonly tension: number;\n\n /**\n * @param segments - @zh 每段之间的插值点数 @en Number of interpolation points per segment\n * @param tension - @zh 张力 (0-1) @en Tension (0-1)\n */\n constructor(segments: number = 5, tension: number = 0.5) {\n this.segments = segments;\n this.tension = tension;\n }\n\n smooth(path: readonly IPoint[], _map: IPathfindingMap): IPoint[] {\n if (path.length <= 2) {\n return [...path];\n }\n\n const result: IPoint[] = [];\n\n // Add phantom points at the ends\n const points = [\n path[0],\n ...path,\n path[path.length - 1]\n ];\n\n for (let i = 1; i < points.length - 2; i++) {\n const p0 = points[i - 1];\n const p1 = points[i];\n const p2 = points[i + 1];\n const p3 = points[i + 2];\n\n for (let j = 0; j < this.segments; j++) {\n const t = j / this.segments;\n const point = this.interpolate(p0, p1, p2, p3, t);\n result.push(point);\n }\n }\n\n // Add final point\n result.push(path[path.length - 1]);\n\n return result;\n }\n\n /**\n * @zh Catmull-Rom 插值\n * @en Catmull-Rom interpolation\n */\n private interpolate(\n p0: IPoint,\n p1: IPoint,\n p2: IPoint,\n p3: IPoint,\n t: number\n ): IPoint {\n const t2 = t * t;\n const t3 = t2 * t;\n\n const tension = this.tension;\n\n const x =\n 0.5 *\n ((2 * p1.x) +\n (-p0.x + p2.x) * t * tension +\n (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 * tension +\n (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3 * tension);\n\n const y =\n 0.5 *\n ((2 * p1.y) +\n (-p0.y + p2.y) * t * tension +\n (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 * tension +\n (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3 * tension);\n\n return createPoint(x, y);\n }\n}\n\n// =============================================================================\n// 组合平滑器 | Combined Smoother\n// =============================================================================\n\n/**\n * @zh 组合路径平滑器\n * @en Combined path smoother\n *\n * @zh 先简化路径,再用曲线平滑\n * @en First simplify path, then smooth with curves\n */\nexport class CombinedSmoother implements IPathSmoother {\n private readonly simplifier: LineOfSightSmoother;\n private readonly curveSmoother: CatmullRomSmoother;\n\n constructor(curveSegments: number = 5, tension: number = 0.5) {\n this.simplifier = new LineOfSightSmoother();\n this.curveSmoother = new CatmullRomSmoother(curveSegments, tension);\n }\n\n smooth(path: readonly IPoint[], map: IPathfindingMap): IPoint[] {\n // First simplify\n const simplified = this.simplifier.smooth(path, map);\n\n // Then curve smooth\n return this.curveSmoother.smooth(simplified, map);\n }\n}\n\n// =============================================================================\n// 工厂函数 | Factory Functions\n// =============================================================================\n\n/**\n * @zh 创建视线平滑器\n * @en Create line of sight smoother\n */\nexport function createLineOfSightSmoother(\n lineOfSight?: typeof bresenhamLineOfSight\n): LineOfSightSmoother {\n return new LineOfSightSmoother(lineOfSight);\n}\n\n/**\n * @zh 创建曲线平滑器\n * @en Create curve smoother\n */\nexport function createCatmullRomSmoother(\n segments?: number,\n tension?: number\n): CatmullRomSmoother {\n return new CatmullRomSmoother(segments, tension);\n}\n\n/**\n * @zh 创建组合平滑器\n * @en Create combined smoother\n */\nexport function createCombinedSmoother(\n curveSegments?: number,\n tension?: number\n): CombinedSmoother {\n return new CombinedSmoother(curveSegments, tension);\n}\n"],"mappings":"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","names":["createPoint","x","y","EMPTY_PATH_RESULT","found","path","cost","nodesSearched","manhattanDistance","a","b","Math","abs","euclideanDistance","dx","dy","sqrt","chebyshevDistance","max","octileDistance","D","D2","SQRT2","min","DEFAULT_PATHFINDING_OPTIONS","maxNodes","heuristicWeight","allowDiagonal","avoidCorners","IndexedBinaryHeap","compare","heap","size","length","isEmpty","push","item","heapIndex","bubbleUp","pop","undefined","result","last","sinkDown","peek","update","index","contains","remove","clear","parentIndex","parent","halfLength","leftIndex","rightIndex","smallest","smallestItem","left","right","DEFAULT_PATH_CACHE_CONFIG","maxEntries","ttlMs","enableApproximateMatch","approximateRange","PathCache","config","cache","accessOrder","Map","get","startX","startY","endX","endY","mapVersion","key","generateKey","entry","getApproximate","isValid","delete","removeFromAccessOrder","updateAccessOrder","result","set","size","evictLRU","timestamp","Date","now","invalidateAll","clear","length","invalidateRegion","minX","minY","maxX","maxY","keysToDelete","path","point","x","y","push","getStats","maxSize","cleanup","age","range","sx","sy","ex","ey","adjustPathForApproximate","newStartX","newStartY","newEndX","newEndY","newPath","oldStart","oldEnd","index","indexOf","splice","lruKey","shift","createPathCache","IncrementalAStarPathfinder","map","config","sessions","Map","nextRequestId","affectedRegions","maxRegionAge","cache","enableCache","mapVersion","cacheHits","cacheMisses","PathCache","cacheConfig","requestPath","startX","startY","endX","endY","options","id","priority","opts","DEFAULT_PATHFINDING_OPTIONS","request","createdAt","Date","now","cached","get","session","state","found","PathfindingState","Completed","Failed","openList","IndexedBinaryHeap","a","b","f","nodeCache","startNode","getNodeAt","endNode","endPosition","x","y","nodesSearched","framesUsed","initialDistance","result","requestId","path","cost","isPartial","affectedByChange","set","walkable","position","createEmptyResult","heuristic","startAStarNode","node","g","h","heuristicWeight","parent","closed","opened","heapIndex","push","InProgress","step","maxIterations","EMPTY_PROGRESS","createProgress","iterations","isEmpty","current","pop","buildResult","req","expandNeighbors","maxNodes","pause","Paused","resume","cancel","Cancelled","getResult","getProgress","cleanup","clear","delete","notifyObstacleChange","minX","minY","maxX","maxY","invalidateRegion","region","timestamp","values","sessionAffectedByRegion","cleanupOldRegions","length","clearCache","invalidateAll","getCacheStats","enabled","hits","misses","hitRate","size","total","getStats","isAffectedByChange","clearChangeFlag","neighbors","getNeighbors","neighborNode","neighbor","Infinity","movementCost","getMovementCost","tentativeG","update","estimatedProgress","bestNode","peek","currentDistance","Math","max","min","openListSize","reverse","astarNode","pos","start","end","i","splice","createIncrementalAStarPathfinder","PathValidator","validatePath","path","fromIndex","toIndex","map","end","Math","min","length","i","point","x","floor","y","isWalkable","valid","invalidIndex","prev","checkLineOfSight","x1","y1","x2","y2","ix1","iy1","ix2","iy2","dx","abs","dy","sx","sy","err","ObstacleChangeManager","changes","Map","epoch","recordChange","wasWalkable","key","set","timestamp","Date","now","getAffectedRegion","size","minX","Infinity","minY","maxX","maxY","change","values","max","getChanges","Array","from","hasChanges","getEpoch","flush","clear","createPathValidator","createObstacleChangeManager","GridNode","x","y","width","walkable","cost","id","position","createPoint","DIRECTIONS_4","dx","dy","DIRECTIONS_8","DEFAULT_GRID_OPTIONS","allowDiagonal","diagonalCost","Math","SQRT2","avoidCorners","heuristic","octileDistance","GridMap","height","options","nodes","createNodes","getNodeAt","isInBounds","isWalkable","node","setWalkable","setCost","getNeighbors","neighbors","directions","i","length","dir","nx","ny","neighbor","hNode","vNode","push","forEachNeighbor","callback","a","b","getMovementCost","from","to","abs","loadFromArray","data","min","loadFromString","str","lines","trim","split","line","toString","result","reset","setRectWalkable","createGridMap","bresenhamLineOfSight","x1","y1","x2","y2","map","ix1","Math","floor","iy1","ix2","iy2","dx","abs","dy","sx","sy","err","isWalkable","e2","raycastLineOfSight","stepSize","distance","sqrt","steps","ceil","stepX","stepY","x","y","i","LineOfSightSmoother","lineOfSight","smooth","path","length","result","current","furthest","push","CatmullRomSmoother","segments","tension","_map","points","p0","p1","p2","p3","j","t","point","interpolate","t2","t3","createPoint","CombinedSmoother","curveSegments","simplifier","curveSmoother","simplified","createLineOfSightSmoother","createCatmullRomSmoother","createCombinedSmoother"]}
|