@flare-engine/pathfinding 0.4.8 → 0.4.11
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.mts +6 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +264 -220
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +264 -220
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["SQRT2","heapCreate","heapGrow","heapPush","heapPop"],"sources":["../src/grid.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"sourcesContent":["/**\n * Grid data structure for tile-based pathfinding.\n * Uses a flat Uint8Array: 0 = blocked, 1+ = walkable (value = movement cost).\n */\n\nexport interface Grid {\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n}\n\nexport interface GridConfig {\n width: number;\n height: number;\n /** Pre-filled grid data. Length must equal width * height. */\n data?: Uint8Array;\n /** Default cost for all cells when `data` is not provided. 0 = blocked, 1+ = walkable cost. Default 1. */\n defaultCost?: number;\n}\n\nexport function createGrid(config: GridConfig): Grid {\n const { width, height, defaultCost = 1 } = config;\n if (width <= 0 || height <= 0) {\n throw new RangeError('Grid dimensions must be positive');\n }\n const w = width | 0;\n const h = height | 0;\n let data: Uint8Array;\n if (config.data) {\n if (config.data.length !== w * h) {\n throw new RangeError(`Grid data length ${config.data.length} does not match ${w}x${h}`);\n }\n data = config.data;\n } else {\n data = new Uint8Array(w * h);\n if (defaultCost > 0) {\n data.fill(defaultCost);\n }\n }\n return { width: w, height: h, data };\n}\n\nexport function inBounds(grid: Grid, x: number, y: number): boolean {\n return x >= 0 && y >= 0 && x < grid.width && y < grid.height;\n}\n\nexport function isWalkable(grid: Grid, x: number, y: number): boolean {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return false;\n return grid.data[(y | 0) * grid.width + (x | 0)]! > 0;\n}\n\nexport function getCost(grid: Grid, x: number, y: number): number {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return 0;\n return grid.data[(y | 0) * grid.width + (x | 0)]!;\n}\n\nexport function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = walkable ? 1 : 0;\n}\n\nexport function setCost(grid: Grid, x: number, y: number, cost: number): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = cost > 255 ? 255 : cost < 0 ? 0 : cost | 0;\n}\n","/**\n * A* pathfinding on a Grid. Supports 4-directional and 8-directional movement\n * with weighted costs. Uses a binary min-heap for the open set.\n */\n\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\n\nexport interface PathResult {\n /** Grid coordinates from start to end, inclusive. */\n path: { x: number; y: number }[];\n /** Total movement cost. */\n cost: number;\n /** Number of nodes explored. */\n explored: number;\n}\n\nexport interface PathOptions {\n /** Allow diagonal movement. Default: true. */\n diagonal?: boolean;\n /** Custom heuristic. Default: octile distance (diagonal) or Manhattan (4-dir). */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n}\n\n// ─── Heuristics ──────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\nexport function manhattanDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.abs(ax - bx) + Math.abs(ay - by);\n}\n\nexport function octileDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = Math.abs(ax - bx);\n const dy = Math.abs(ay - by);\n return dx > dy ? dx + (SQRT2 - 1) * dy : dy + (SQRT2 - 1) * dx;\n}\n\nexport function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.max(Math.abs(ax - bx), Math.abs(ay - by));\n}\n\nexport function euclideanDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n// ─── Binary min-heap ─────────────────────────────────────────────\n\n// Indices into the heap are stored as flat integers; each entry is (f, node-index).\n// We use two parallel Float64Arrays to avoid object allocation.\ninterface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nfunction heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n // Bubble up\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n // Swap\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nfunction heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n // Sift down\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n\n// ─── Neighbors (pre-computed offsets) ────────────────────────────\n\n// 4-directional: N, E, S, W\nconst DIR4_X = [0, 1, 0, -1];\nconst DIR4_Y = [-1, 0, 1, 0];\n\n// 8-directional: N, NE, E, SE, S, SW, W, NW\nconst DIR8_X = [0, 1, 1, 1, 0, -1, -1, -1];\nconst DIR8_Y = [-1, -1, 0, 1, 1, 1, 0, -1];\nconst DIR8_COST = [1, SQRT2, 1, SQRT2, 1, SQRT2, 1, SQRT2];\n\n// ─── A* ──────────────────────────────────────────────────────────\n\nexport function findPath(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: PathOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n // Quick rejects\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n\n const diagonal = options?.diagonal !== false;\n const maxIter = options?.maxIterations ?? grid.width * grid.height;\n const heuristic = options?.heuristic ?? (diagonal ? octileDistance : manhattanDistance);\n\n const w = grid.width;\n const total = w * grid.height;\n\n // gScore and closed set\n const g = new Float64Array(total);\n g.fill(Number.POSITIVE_INFINITY);\n const closed = new Uint8Array(total);\n const cameFrom = new Int32Array(total);\n cameFrom.fill(-1);\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n g[startIdx] = 0;\n\n const heap = heapCreate(Math.min(total, 4096));\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n const dirX = diagonal ? DIR8_X : DIR4_X;\n const dirY = diagonal ? DIR8_Y : DIR4_Y;\n const dirCost = diagonal ? DIR8_COST : null;\n const dirCount = dirX.length;\n\n let explored = 0;\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return reconstructPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (closed[currentIdx]) continue;\n closed[currentIdx] = 1;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n const currentG = g[currentIdx]!;\n\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dirX[d]!;\n const ny = cy + dirY[d]!;\n if (nx < 0 || ny < 0 || nx >= w || ny >= grid.height) continue;\n\n const nIdx = ny * w + nx;\n if (closed[nIdx]) continue;\n\n const tileCost = grid.data[nIdx]!;\n if (tileCost === 0) continue;\n\n // For diagonal movement, check that both cardinal neighbors are walkable (corner-cutting)\n if (diagonal && d & 1) {\n const dx = dirX[d]!;\n const dy = dirY[d]!;\n if (!isWalkable(grid, cx + dx, cy) || !isWalkable(grid, cx, cy + dy)) continue;\n }\n\n const moveCost = dirCost ? dirCost[d]! * tileCost : tileCost;\n const tentativeG = currentG + moveCost;\n\n if (tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n const f = tentativeG + heuristic(nx, ny, ex, ey);\n heapPush(heap, f, nIdx);\n }\n }\n }\n\n return null;\n}\n\nfunction reconstructPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n const path: { x: number; y: number }[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n path.push({ x: idx % w, y: (idx / w) | 0 });\n idx = cameFrom[idx]!;\n }\n path.reverse();\n return { path, cost, explored };\n}\n","/**\n * Jump Point Search — an optimization over A* for uniform-cost grids.\n * JPS pruning is only correct when every walkable tile costs 1, so a grid with\n * any tile cost above 1 is delegated to weighted A* (`findPath`, diagonal moves)\n * after one linear scan of `grid.data`.\n *\n * JPS prunes symmetric paths by \"jumping\" along directions until hitting\n * a wall, the goal, or a forced neighbor.\n */\n\nimport type { PathResult } from './astar.js';\nimport { findPath, octileDistance } from './astar.js';\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\n\n// ─── Binary min-heap (duplicated from astar for tree-shakeability) ─\n\ninterface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nfunction heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nfunction heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nfunction heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nfunction heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n\n// ─── JPS ─────────────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\n// One pass per call, never per node: JPS pruning assumes every walkable tile costs 1.\nfunction hasWeightedCost(grid: Grid): boolean {\n const data = grid.data;\n for (let i = 0; i < data.length; i++) {\n if (data[i]! > 1) return true;\n }\n return false;\n}\n\nexport interface JpsOptions {\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n /** Custom heuristic. Default: octile distance. */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n}\n\nexport function findPathJPS(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: JpsOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n if (hasWeightedCost(grid)) {\n return findPath(grid, sx, sy, ex, ey, { ...options, diagonal: true });\n }\n\n const w = grid.width;\n const h = grid.height;\n const total = w * h;\n const maxIter = options?.maxIterations ?? total;\n const heuristic = options?.heuristic ?? octileDistance;\n\n const g = new Float64Array(total);\n g.fill(Number.POSITIVE_INFINITY);\n const closed = new Uint8Array(total);\n const cameFrom = new Int32Array(total);\n cameFrom.fill(-1);\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n g[startIdx] = 0;\n\n const heap = heapCreate(Math.min(total, 4096));\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n let explored = 0;\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return buildPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (closed[currentIdx]) continue;\n closed[currentIdx] = 1;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n\n const neighbors = identifySuccessors(grid, cx, cy, cameFrom, w, h, ex, ey);\n for (let i = 0; i < neighbors.length; i += 2) {\n const nx = neighbors[i]!;\n const ny = neighbors[i + 1]!;\n const nIdx = ny * w + nx;\n if (closed[nIdx]) continue;\n\n const dx = Math.abs(nx - cx);\n const dy = Math.abs(ny - cy);\n const diag = Math.min(dx, dy);\n const straight = Math.abs(dx - dy);\n const dist = diag * SQRT2 + straight;\n const tentativeG = g[currentIdx]! + dist;\n if (tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n heapPush(heap, tentativeG + heuristic(nx, ny, ex, ey), nIdx);\n }\n }\n }\n\n return null;\n}\n\nfunction identifySuccessors(\n grid: Grid,\n cx: number,\n cy: number,\n cameFrom: Int32Array,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number[] {\n const results: number[] = [];\n const parentIdx = cameFrom[cy * w + cx]!;\n\n if (parentIdx === -1) {\n // Start node: explore all 8 directions\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 jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) {\n results.push(jp % w, (jp / w) | 0);\n }\n }\n }\n } else {\n const px = parentIdx % w;\n const py = (parentIdx / w) | 0;\n const dx = clampDir(cx - px);\n const dy = clampDir(cy - py);\n\n if (dx !== 0 && dy !== 0) {\n // Diagonal move: check straight and diagonal successors\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (isWalkable(grid, cx + dx, cy + dy)) {\n const jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n // Forced neighbors\n if (!isWalkable(grid, cx - dx, cy) && isWalkable(grid, cx - dx, cy + dy)) {\n const jp = jump(grid, cx, cy, -dx, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy - dy) && isWalkable(grid, cx + dx, cy - dy)) {\n const jp = jump(grid, cx, cy, dx, -dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n } else if (dx !== 0) {\n // Horizontal move\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy + 1) && isWalkable(grid, cx + dx, cy + 1)) {\n const jp = jump(grid, cx, cy, dx, 1, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx, cy - 1) && isWalkable(grid, cx + dx, cy - 1)) {\n const jp = jump(grid, cx, cy, dx, -1, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n } else {\n // Vertical move\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx + 1, cy) && isWalkable(grid, cx + 1, cy + dy)) {\n const jp = jump(grid, cx, cy, 1, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n if (!isWalkable(grid, cx - 1, cy) && isWalkable(grid, cx - 1, cy + dy)) {\n const jp = jump(grid, cx, cy, -1, dy, w, h, ex, ey);\n if (jp !== -1) results.push(jp % w, (jp / w) | 0);\n }\n }\n }\n\n return results;\n}\n\nfunction jump(\n grid: Grid,\n cx: number,\n cy: number,\n dx: number,\n dy: number,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number {\n const nx = cx + dx;\n const ny = cy + dy;\n\n if (!isWalkable(grid, nx, ny)) return -1;\n if (nx === ex && ny === ey) return ny * w + nx;\n\n // Forced neighbor check\n if (dx !== 0 && dy !== 0) {\n // Diagonal\n if (\n (!isWalkable(grid, nx - dx, ny) && isWalkable(grid, nx - dx, ny + dy)) ||\n (!isWalkable(grid, nx, ny - dy) && isWalkable(grid, nx + dx, ny - dy))\n ) {\n return ny * w + nx;\n }\n // Recurse in cardinal directions\n if (jump(grid, nx, ny, dx, 0, w, h, ex, ey) !== -1) return ny * w + nx;\n if (jump(grid, nx, ny, 0, dy, w, h, ex, ey) !== -1) return ny * w + nx;\n } else if (dx !== 0) {\n // Horizontal\n if (\n (!isWalkable(grid, nx, ny + 1) && isWalkable(grid, nx + dx, ny + 1)) ||\n (!isWalkable(grid, nx, ny - 1) && isWalkable(grid, nx + dx, ny - 1))\n ) {\n return ny * w + nx;\n }\n } else {\n // Vertical\n if (\n (!isWalkable(grid, nx + 1, ny) && isWalkable(grid, nx + 1, ny + dy)) ||\n (!isWalkable(grid, nx - 1, ny) && isWalkable(grid, nx - 1, ny + dy))\n ) {\n return ny * w + nx;\n }\n }\n\n // Keep jumping (iterative for cardinal, recursive for diagonal via identifySuccessors)\n return jump(grid, nx, ny, dx, dy, w, h, ex, ey);\n}\n\nfunction clampDir(v: number): number {\n return v > 0 ? 1 : v < 0 ? -1 : 0;\n}\n\nfunction buildPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n // JPS produces jump points — we interpolate the full path\n const jumpPoints: number[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n jumpPoints.push(idx);\n idx = cameFrom[idx]!;\n }\n jumpPoints.reverse();\n\n const path: { x: number; y: number }[] = [];\n for (let i = 0; i < jumpPoints.length; i++) {\n const jpIdx = jumpPoints[i]!;\n const jx = jpIdx % w;\n const jy = (jpIdx / w) | 0;\n if (i === 0) {\n path.push({ x: jx, y: jy });\n } else {\n const prev = path[path.length - 1]!;\n // Interpolate from prev to current jump point\n let cx = prev.x;\n let cy = prev.y;\n while (cx !== jx || cy !== jy) {\n if (cx < jx) cx++;\n else if (cx > jx) cx--;\n if (cy < jy) cy++;\n else if (cy > jy) cy--;\n path.push({ x: cx, y: cy });\n }\n }\n }\n\n return { path, cost, explored };\n}\n","/**\n * Lightweight navmesh pathfinding for polygon-based environments.\n * Supports convex polygon navigation with A* over the polygon graph\n * and the Simple Stupid Funnel Algorithm for path smoothing.\n */\n\nimport type { Vec2 } from '@flare-engine/math';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface NavMeshPolygon {\n readonly id: number;\n /** Convex polygon vertices in winding order. */\n readonly vertices: readonly Vec2[];\n /** One `Portal` per adjacent polygon: the shared edge plus that neighbour's id. */\n readonly portals: readonly Portal[];\n}\n\nexport interface Portal {\n /** Neighbor polygon id. */\n neighborId: number;\n /** Left endpoint of the shared edge (from the perspective of travel). */\n a: Vec2;\n /** Right endpoint of the shared edge. */\n b: Vec2;\n}\n\nexport interface NavMesh {\n readonly polygons: readonly NavMeshPolygon[];\n}\n\nexport interface NavMeshPathResult {\n /** Smoothed world-space waypoints. */\n path: Vec2[];\n /** Polygon ids traversed. */\n corridor: number[];\n}\n\n// ─── Construction ────────────────────────────────────────────────\n\nexport function createNavMesh(polygons: NavMeshPolygon[]): NavMesh {\n return { polygons };\n}\n\n// ─── Point-in-polygon ────────────────────────────────────────────\n\nfunction pointInConvexPolygon(verts: readonly Vec2[], px: number, py: number): boolean {\n const n = verts.length;\n if (n < 3) return false;\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const a = verts[i]!;\n const b = verts[(i + 1) % n]!;\n const cross = (b.x - a.x) * (py - a.y) - (b.y - a.y) * (px - a.x);\n if (cross !== 0) {\n const s = cross > 0 ? 1 : -1;\n if (sign === 0) sign = s;\n else if (sign !== s) return false;\n }\n }\n return true;\n}\n\nexport function findPolygonAt(mesh: NavMesh, x: number, y: number): number {\n for (let i = 0; i < mesh.polygons.length; i++) {\n if (pointInConvexPolygon(mesh.polygons[i]!.vertices, x, y)) {\n return mesh.polygons[i]!.id;\n }\n }\n return -1;\n}\n\n// ─── Polygon centroid ────────────────────────────────────────────\n\nfunction centroid(verts: readonly Vec2[]): Vec2 {\n let cx = 0;\n let cy = 0;\n for (let i = 0; i < verts.length; i++) {\n cx += verts[i]!.x;\n cy += verts[i]!.y;\n }\n const n = verts.length;\n return { x: cx / n, y: cy / n };\n}\n\n// ─── A* over polygon graph ───────────────────────────────────────\n\nfunction distSq(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return dx * dx + dy * dy;\n}\n\nfunction dist(ax: number, ay: number, bx: number, by: number): number {\n return Math.sqrt(distSq(ax, ay, bx, by));\n}\n\nexport function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null {\n const startPolyId = findPolygonAt(mesh, start.x, start.y);\n const endPolyId = findPolygonAt(mesh, end.x, end.y);\n if (startPolyId === -1 || endPolyId === -1) return null;\n if (startPolyId === endPolyId) {\n return {\n path: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n corridor: [startPolyId],\n };\n }\n\n // Build index: id → polygon\n const byId = new Map<number, NavMeshPolygon>();\n for (let i = 0; i < mesh.polygons.length; i++) {\n const p = mesh.polygons[i]!;\n byId.set(p.id, p);\n }\n\n // A* on polygon graph\n const gScore = new Map<number, number>();\n const fScore = new Map<number, number>();\n const cameFrom = new Map<number, number>();\n\n gScore.set(startPolyId, 0);\n\n const endPoly = byId.get(endPolyId)!;\n const endCenter = centroid(endPoly.vertices);\n const startPoly = byId.get(startPolyId)!;\n const startCenter = centroid(startPoly.vertices);\n\n fScore.set(startPolyId, dist(startCenter.x, startCenter.y, endCenter.x, endCenter.y));\n\n // Simple array-based open set (fine for typical navmeshes with <1000 polygons)\n const open: number[] = [startPolyId];\n const inOpen = new Set<number>([startPolyId]);\n const closed = new Set<number>();\n\n while (open.length > 0) {\n // Find lowest f-score\n let bestI = 0;\n let bestF = fScore.get(open[0]!) ?? Number.POSITIVE_INFINITY;\n for (let i = 1; i < open.length; i++) {\n const f = fScore.get(open[i]!) ?? Number.POSITIVE_INFINITY;\n if (f < bestF) {\n bestF = f;\n bestI = i;\n }\n }\n const currentId = open[bestI]!;\n\n if (currentId === endPolyId) {\n // Reconstruct corridor\n const corridor: number[] = [];\n let id: number | undefined = endPolyId;\n while (id !== undefined) {\n corridor.push(id);\n id = cameFrom.get(id);\n }\n corridor.reverse();\n const path = funnelSmooth(mesh, byId, corridor, start, end);\n return { path, corridor };\n }\n\n // Remove from open\n open[bestI] = open[open.length - 1]!;\n open.length--;\n inOpen.delete(currentId);\n closed.add(currentId);\n\n const current = byId.get(currentId)!;\n const currentCenter = centroid(current.vertices);\n const currentG = gScore.get(currentId)!;\n\n for (let i = 0; i < current.portals.length; i++) {\n const portal = current.portals[i]!;\n const neighborId = portal.neighborId;\n if (closed.has(neighborId)) continue;\n\n const neighbor = byId.get(neighborId);\n if (!neighbor) continue;\n\n const portalMidX = (portal.a.x + portal.b.x) * 0.5;\n const portalMidY = (portal.a.y + portal.b.y) * 0.5;\n const tentativeG = currentG + dist(currentCenter.x, currentCenter.y, portalMidX, portalMidY);\n\n const prevG = gScore.get(neighborId);\n if (prevG !== undefined && tentativeG >= prevG) continue;\n\n gScore.set(neighborId, tentativeG);\n cameFrom.set(neighborId, currentId);\n\n const neighborCenter = centroid(neighbor.vertices);\n fScore.set(\n neighborId,\n tentativeG + dist(neighborCenter.x, neighborCenter.y, endCenter.x, endCenter.y),\n );\n\n if (!inOpen.has(neighborId)) {\n open.push(neighborId);\n inOpen.add(neighborId);\n }\n }\n }\n\n return null;\n}\n\n// ─── Simple Stupid Funnel Algorithm ──────────────────────────────\n\nfunction funnelSmooth(\n _mesh: NavMesh,\n byId: Map<number, NavMeshPolygon>,\n corridor: number[],\n start: Vec2,\n end: Vec2,\n): Vec2[] {\n if (corridor.length <= 1) {\n return [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ];\n }\n\n // Build portal list from corridor\n const portalsLeft: Vec2[] = [];\n const portalsRight: Vec2[] = [];\n\n portalsLeft.push({ x: start.x, y: start.y });\n portalsRight.push({ x: start.x, y: start.y });\n\n for (let i = 0; i < corridor.length - 1; i++) {\n const poly = byId.get(corridor[i]!)!;\n const nextId = corridor[i + 1]!;\n // Find the portal to the next polygon\n let found = false;\n for (let j = 0; j < poly.portals.length; j++) {\n if (poly.portals[j]!.neighborId === nextId) {\n portalsLeft.push(poly.portals[j]!.a);\n portalsRight.push(poly.portals[j]!.b);\n found = true;\n break;\n }\n }\n if (!found) {\n // Fallback: straight line through centroids\n const c = centroid(poly.vertices);\n portalsLeft.push(c);\n portalsRight.push(c);\n }\n }\n\n portalsLeft.push({ x: end.x, y: end.y });\n portalsRight.push({ x: end.x, y: end.y });\n\n // Simple Stupid Funnel Algorithm (Mononen)\n // Walk the portal list and maintain a funnel (apex, left, right).\n const path: Vec2[] = [];\n\n let apexPt = portalsLeft[0]!; // start point\n let leftPt = portalsLeft[0]!;\n let rightPt = portalsRight[0]!;\n let apexIdx = 0;\n let leftIdx = 0;\n let rightIdx = 0;\n\n path.push({ x: apexPt.x, y: apexPt.y });\n\n const n = portalsLeft.length;\n\n for (let i = 1; i < n; i++) {\n const pL = portalsLeft[i]!;\n const pR = portalsRight[i]!;\n\n // Try to tighten the right side\n if (triArea2(apexPt, rightPt, pR) <= 0) {\n if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {\n // Tighten\n rightPt = pR;\n rightIdx = i;\n } else {\n // Right crossed over left → left becomes new apex\n addUnique(path, leftPt);\n apexPt = leftPt;\n apexIdx = leftIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n continue;\n }\n }\n\n // Try to tighten the left side\n if (triArea2(apexPt, leftPt, pL) >= 0) {\n if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {\n // Tighten\n leftPt = pL;\n leftIdx = i;\n } else {\n // Left crossed over right → right becomes new apex\n addUnique(path, rightPt);\n apexPt = rightPt;\n apexIdx = rightIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n }\n }\n }\n\n addUnique(path, end);\n\n return path;\n}\n\nfunction addUnique(path: Vec2[], p: Vec2): void {\n const last = path[path.length - 1];\n if (!last || last.x !== p.x || last.y !== p.y) {\n path.push({ x: p.x, y: p.y });\n }\n}\n\n/** Twice the signed area of the triangle (a, b, c). Positive = CCW. */\nfunction triArea2(a: Vec2, b: Vec2, c: Vec2): number {\n return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);\n}\n\nfunction vEqual(a: Vec2, b: Vec2): boolean {\n return a.x === b.x && a.y === b.y;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["SQRT2"],"sources":["../src/grid.ts","../src/heap.ts","../src/scratch.ts","../src/astar.ts","../src/jps.ts","../src/navmesh.ts"],"sourcesContent":["/**\n * Grid data structure for tile-based pathfinding.\n * Uses a flat Uint8Array: 0 = blocked, 1+ = walkable (value = movement cost).\n */\n\nexport interface Grid {\n readonly width: number;\n readonly height: number;\n readonly data: Uint8Array;\n}\n\nexport interface GridConfig {\n width: number;\n height: number;\n /** Pre-filled grid data. Length must equal width * height. */\n data?: Uint8Array;\n /** Default cost for all cells when `data` is not provided. 0 = blocked, 1+ = walkable cost. Default 1. */\n defaultCost?: number;\n}\n\nexport function createGrid(config: GridConfig): Grid {\n const { width, height, defaultCost = 1 } = config;\n if (width <= 0 || height <= 0) {\n throw new RangeError('Grid dimensions must be positive');\n }\n const w = width | 0;\n const h = height | 0;\n let data: Uint8Array;\n if (config.data) {\n if (config.data.length !== w * h) {\n throw new RangeError(`Grid data length ${config.data.length} does not match ${w}x${h}`);\n }\n data = config.data;\n } else {\n data = new Uint8Array(w * h);\n if (defaultCost > 0) {\n data.fill(defaultCost);\n }\n }\n return { width: w, height: h, data };\n}\n\nexport function inBounds(grid: Grid, x: number, y: number): boolean {\n return x >= 0 && y >= 0 && x < grid.width && y < grid.height;\n}\n\nexport function isWalkable(grid: Grid, x: number, y: number): boolean {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return false;\n return grid.data[(y | 0) * grid.width + (x | 0)]! > 0;\n}\n\nexport function getCost(grid: Grid, x: number, y: number): number {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return 0;\n return grid.data[(y | 0) * grid.width + (x | 0)]!;\n}\n\nexport function setWalkable(grid: Grid, x: number, y: number, walkable: boolean): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = walkable ? 1 : 0;\n}\n\nexport function setCost(grid: Grid, x: number, y: number, cost: number): void {\n if (x < 0 || y < 0 || x >= grid.width || y >= grid.height) return;\n grid.data[(y | 0) * grid.width + (x | 0)] = cost > 255 ? 255 : cost < 0 ? 0 : cost | 0;\n}\n","/**\n * Binary min-heap for the A* / JPS open set.\n *\n * Entries are (f, node-index) pairs kept in two parallel typed arrays, so a\n * push allocates nothing. Module-private to the package: not exported from\n * `index.ts`.\n */\n\nexport interface Heap {\n f: Float64Array;\n idx: Int32Array;\n size: number;\n}\n\nexport function heapCreate(capacity: number): Heap {\n return {\n f: new Float64Array(capacity),\n idx: new Int32Array(capacity),\n size: 0,\n };\n}\n\n/**\n * Double the heap's backing arrays.\n *\n * Typed arrays do not throw on an out-of-range write — the store is silently\n * dropped — so without this a push past capacity increments `size`, writes\n * nothing, and every later comparison reads `undefined`. The open set then\n * degrades without any error, and the search returns a valid-looking but\n * non-optimal path. Growth is amortized O(1): allocation happens only when\n * capacity is reached, never per push.\n */\nexport function heapGrow(h: Heap): void {\n const next = h.f.length === 0 ? 16 : h.f.length * 2;\n const f = new Float64Array(next);\n f.set(h.f);\n const idx = new Int32Array(next);\n idx.set(h.idx);\n h.f = f;\n h.idx = idx;\n}\n\nexport function heapPush(h: Heap, f: number, nodeIdx: number): void {\n if (h.size === h.f.length) heapGrow(h);\n let i = h.size++;\n h.f[i] = f;\n h.idx[i] = nodeIdx;\n // Bubble up\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (h.f[parent]! <= h.f[i]!) break;\n // Swap\n const tf = h.f[parent]!;\n const ti = h.idx[parent]!;\n h.f[parent] = h.f[i]!;\n h.idx[parent] = h.idx[i]!;\n h.f[i] = tf;\n h.idx[i] = ti;\n i = parent;\n }\n}\n\nexport function heapPop(h: Heap): number {\n const result = h.idx[0]!;\n h.size--;\n if (h.size > 0) {\n h.f[0] = h.f[h.size]!;\n h.idx[0] = h.idx[h.size]!;\n // Sift down\n let i = 0;\n for (;;) {\n let smallest = i;\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n if (left < h.size && h.f[left]! < h.f[smallest]!) smallest = left;\n if (right < h.size && h.f[right]! < h.f[smallest]!) smallest = right;\n if (smallest === i) break;\n const tf = h.f[i]!;\n const ti = h.idx[i]!;\n h.f[i] = h.f[smallest]!;\n h.idx[i] = h.idx[smallest]!;\n h.f[smallest] = tf;\n h.idx[smallest] = ti;\n i = smallest;\n }\n }\n return result;\n}\n","/**\n * Per-`Grid` search scratch shared by `findPath` and `findPathJPS`.\n *\n * A search needs a g score, a came-from link and an open/closed mark per cell.\n * Instead of allocating and filling those on every call, one scratch is kept per\n * `Grid` object in a WeakMap and reused; generation stamps make a per-call fill\n * unnecessary. Module-private to the package: not exported from `index.ts`.\n */\n\nimport type { Grid } from './grid.js';\nimport type { Heap } from './heap.js';\nimport { heapCreate } from './heap.js';\n\nexport interface SearchScratch {\n /** `width * height` the arrays were sized for; a mismatch means the scratch is stale. */\n readonly total: number;\n /** g score per cell; valid only when `stamp[i] >= open`. */\n readonly g: Float64Array;\n /** Predecessor cell index per cell; valid only when `stamp[i] >= open`. */\n readonly cameFrom: Int32Array;\n /**\n * Generation stamp per cell. `open` marks a cell touched (g / cameFrom valid)\n * by the current search, `open + 1` marks it closed; anything lower is a\n * leftover from an earlier search and reads as untouched. 0 is \"never touched\".\n */\n readonly stamp: Uint32Array;\n /** Stamp value of the current search's open mark; always even, starts at 2. */\n open: number;\n /** Open-set heap; grown on demand and kept at the grown size. */\n readonly heap: Heap;\n /** JPS successor buffer: cell indices of the jump points of one expanded node, at most 8. */\n readonly succ: Int32Array;\n /** Set while a search holds this scratch, so a re-entrant search takes its own. */\n inUse: boolean;\n}\n\n// `open + 1` must fit a Uint32; `open` is always even, so this is the last usable value.\nconst MAX_OPEN = 0xfffffffe;\n\nconst scratches = new WeakMap<Grid, SearchScratch>();\n\nfunction createScratch(total: number): SearchScratch {\n return {\n total,\n g: new Float64Array(total),\n cameFrom: new Int32Array(total),\n stamp: new Uint32Array(total),\n open: 0,\n heap: heapCreate(Math.min(total, 4096)),\n succ: new Int32Array(8),\n inUse: false,\n };\n}\n\n/**\n * Hand out the scratch for `grid`, ready for a new search: generation advanced\n * (every cell reads as untouched), heap emptied, start cell untouched too — the\n * caller stamps it.\n *\n * A grid whose stored scratch is already in use (a heuristic re-entered a\n * search on the same grid) gets a fresh temporary scratch that is not stored.\n */\nexport function acquireScratch(grid: Grid): SearchScratch {\n const total = grid.width * grid.height;\n let s = scratches.get(grid);\n if (s === undefined || s.total !== total) {\n s = createScratch(total);\n scratches.set(grid, s);\n } else if (s.inUse) {\n s = createScratch(total);\n }\n s.inUse = true;\n s.heap.size = 0;\n if (s.open >= MAX_OPEN) {\n // Wrap: clear every stamp so no stale value can equal a reused generation.\n s.stamp.fill(0);\n s.open = 2;\n } else {\n s.open += 2;\n }\n return s;\n}\n\nexport function releaseScratch(s: SearchScratch): void {\n s.inUse = false;\n}\n","/**\n * A* pathfinding on a Grid. Supports 4-directional and 8-directional movement\n * with weighted costs. Uses a binary min-heap for the open set.\n */\n\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\nimport { heapPop, heapPush } from './heap.js';\nimport { acquireScratch, releaseScratch } from './scratch.js';\n\nexport interface PathResult {\n /** Grid coordinates from start to end, inclusive. */\n path: { x: number; y: number }[];\n /** Total movement cost. */\n cost: number;\n /** Number of nodes explored. */\n explored: number;\n}\n\nexport interface PathOptions {\n /** Allow diagonal movement. Default: true. */\n diagonal?: boolean;\n /** Custom heuristic. Default: octile distance (diagonal) or Manhattan (4-dir). */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n}\n\n// ─── Heuristics ──────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\nexport function manhattanDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.abs(ax - bx) + Math.abs(ay - by);\n}\n\nexport function octileDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = Math.abs(ax - bx);\n const dy = Math.abs(ay - by);\n return dx > dy ? dx + (SQRT2 - 1) * dy : dy + (SQRT2 - 1) * dx;\n}\n\nexport function chebyshevDistance(ax: number, ay: number, bx: number, by: number): number {\n return Math.max(Math.abs(ax - bx), Math.abs(ay - by));\n}\n\nexport function euclideanDistance(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return Math.sqrt(dx * dx + dy * dy);\n}\n\n// ─── Neighbors (pre-computed offsets) ────────────────────────────\n\n// 4-directional: N, E, S, W\nconst DIR4_X = [0, 1, 0, -1];\nconst DIR4_Y = [-1, 0, 1, 0];\n\n// 8-directional: N, NE, E, SE, S, SW, W, NW\nconst DIR8_X = [0, 1, 1, 1, 0, -1, -1, -1];\nconst DIR8_Y = [-1, -1, 0, 1, 1, 1, 0, -1];\nconst DIR8_COST = [1, SQRT2, 1, SQRT2, 1, SQRT2, 1, SQRT2];\n\n// ─── A* ──────────────────────────────────────────────────────────\n\nexport function findPath(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: PathOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n // Quick rejects\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n\n const diagonal = options?.diagonal !== false;\n const maxIter = options?.maxIterations ?? grid.width * grid.height;\n const heuristic = options?.heuristic ?? (diagonal ? octileDistance : manhattanDistance);\n\n const w = grid.width;\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n\n // Per-grid scratch: a cell stamped `openMark` has a valid g / cameFrom for this\n // search, `closedMark` means settled, any lower stamp reads as g = +Infinity.\n const scratch = acquireScratch(grid);\n const { g, cameFrom, stamp, heap } = scratch;\n const openMark = scratch.open;\n const closedMark = openMark + 1;\n\n stamp[startIdx] = openMark;\n g[startIdx] = 0;\n cameFrom[startIdx] = -1;\n\n const dirX = diagonal ? DIR8_X : DIR4_X;\n const dirY = diagonal ? DIR8_Y : DIR4_Y;\n const dirCost = diagonal ? DIR8_COST : null;\n const dirCount = dirX.length;\n\n let explored = 0;\n\n try {\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return reconstructPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (stamp[currentIdx] === closedMark) continue;\n stamp[currentIdx] = closedMark;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n const currentG = g[currentIdx]!;\n\n for (let d = 0; d < dirCount; d++) {\n const nx = cx + dirX[d]!;\n const ny = cy + dirY[d]!;\n if (nx < 0 || ny < 0 || nx >= w || ny >= grid.height) continue;\n\n const nIdx = ny * w + nx;\n const nStamp = stamp[nIdx]!;\n if (nStamp === closedMark) continue;\n\n const tileCost = grid.data[nIdx]!;\n if (tileCost === 0) continue;\n\n // For diagonal movement, check that both cardinal neighbors are walkable (corner-cutting)\n if (diagonal && d & 1) {\n const dx = dirX[d]!;\n const dy = dirY[d]!;\n if (!isWalkable(grid, cx + dx, cy) || !isWalkable(grid, cx, cy + dy)) continue;\n }\n\n const moveCost = dirCost ? dirCost[d]! * tileCost : tileCost;\n const tentativeG = currentG + moveCost;\n\n if (nStamp !== openMark || tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n stamp[nIdx] = openMark;\n const f = tentativeG + heuristic(nx, ny, ex, ey);\n heapPush(heap, f, nIdx);\n }\n }\n }\n\n return null;\n } finally {\n releaseScratch(scratch);\n }\n}\n\nfunction reconstructPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n const path: { x: number; y: number }[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n path.push({ x: idx % w, y: (idx / w) | 0 });\n idx = cameFrom[idx]!;\n }\n path.reverse();\n return { path, cost, explored };\n}\n","/**\n * Jump Point Search — an optimization over A* for uniform-cost grids.\n * JPS pruning is only correct when every walkable tile costs 1, so a grid with\n * any tile cost above 1 is delegated to weighted A* (`findPath`, diagonal moves)\n * after one linear scan of `grid.data`.\n *\n * JPS prunes symmetric paths by \"jumping\" along directions until hitting\n * a wall, the goal, or a forced neighbor.\n */\n\nimport type { PathResult } from './astar.js';\nimport { findPath, octileDistance } from './astar.js';\nimport type { Grid } from './grid.js';\nimport { isWalkable } from './grid.js';\nimport { heapPop, heapPush } from './heap.js';\nimport { acquireScratch, releaseScratch } from './scratch.js';\n\n// ─── JPS ─────────────────────────────────────────────────────────\n\nconst SQRT2 = Math.SQRT2;\n\n// One pass per call, never per node: JPS pruning assumes every walkable tile costs 1.\nfunction hasWeightedCost(grid: Grid): boolean {\n const data = grid.data;\n for (let i = 0; i < data.length; i++) {\n if (data[i]! > 1) return true;\n }\n return false;\n}\n\nexport interface JpsOptions {\n /** Max nodes to explore before giving up. Default: width * height. */\n maxIterations?: number;\n /** Custom heuristic. Default: octile distance. */\n heuristic?: (ax: number, ay: number, bx: number, by: number) => number;\n}\n\nexport function findPathJPS(\n grid: Grid,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n options?: JpsOptions,\n): PathResult | null {\n const sx = startX | 0;\n const sy = startY | 0;\n const ex = endX | 0;\n const ey = endY | 0;\n\n if (!isWalkable(grid, sx, sy) || !isWalkable(grid, ex, ey)) return null;\n if (sx === ex && sy === ey) return { path: [{ x: sx, y: sy }], cost: 0, explored: 0 };\n if (hasWeightedCost(grid)) {\n return findPath(grid, sx, sy, ex, ey, { ...options, diagonal: true });\n }\n\n const w = grid.width;\n const h = grid.height;\n const maxIter = options?.maxIterations ?? w * h;\n const heuristic = options?.heuristic ?? octileDistance;\n\n const startIdx = sy * w + sx;\n const endIdx = ey * w + ex;\n\n // Per-grid scratch: a cell stamped `openMark` has a valid g / cameFrom for this\n // search, `closedMark` means settled, any lower stamp reads as g = +Infinity.\n const scratch = acquireScratch(grid);\n const { g, cameFrom, stamp, heap, succ } = scratch;\n const openMark = scratch.open;\n const closedMark = openMark + 1;\n\n stamp[startIdx] = openMark;\n g[startIdx] = 0;\n cameFrom[startIdx] = -1;\n\n let explored = 0;\n\n try {\n heapPush(heap, heuristic(sx, sy, ex, ey), startIdx);\n\n while (heap.size > 0 && explored < maxIter) {\n const currentIdx = heapPop(heap);\n if (currentIdx === endIdx) {\n return buildPath(cameFrom, w, currentIdx, g[currentIdx]!, explored);\n }\n if (stamp[currentIdx] === closedMark) continue;\n stamp[currentIdx] = closedMark;\n explored++;\n\n const cx = currentIdx % w;\n const cy = (currentIdx / w) | 0;\n\n const count = identifySuccessors(grid, cx, cy, cameFrom, w, h, ex, ey, succ);\n for (let i = 0; i < count; i++) {\n const nIdx = succ[i]!;\n const nx = nIdx % w;\n const ny = (nIdx / w) | 0;\n const nStamp = stamp[nIdx]!;\n if (nStamp === closedMark) continue;\n\n const dx = Math.abs(nx - cx);\n const dy = Math.abs(ny - cy);\n const diag = Math.min(dx, dy);\n const straight = Math.abs(dx - dy);\n const dist = diag * SQRT2 + straight;\n const tentativeG = g[currentIdx]! + dist;\n if (nStamp !== openMark || tentativeG < g[nIdx]!) {\n g[nIdx] = tentativeG;\n cameFrom[nIdx] = currentIdx;\n stamp[nIdx] = openMark;\n heapPush(heap, tentativeG + heuristic(nx, ny, ex, ey), nIdx);\n }\n }\n }\n\n return null;\n } finally {\n releaseScratch(scratch);\n }\n}\n\n/**\n * Writes the cell index of each jump point reachable from (cx, cy) into `out`\n * and returns how many. At most one per direction tried — 8 from the start\n * node, 5 after a diagonal move, 3 after a cardinal one — so `out` needs 8 slots.\n */\nfunction identifySuccessors(\n grid: Grid,\n cx: number,\n cy: number,\n cameFrom: Int32Array,\n w: number,\n h: number,\n ex: number,\n ey: number,\n out: Int32Array,\n): number {\n let n = 0;\n const parentIdx = cameFrom[cy * w + cx]!;\n\n if (parentIdx === -1) {\n // Start node: explore all 8 directions\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 jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n }\n } else {\n const px = parentIdx % w;\n const py = (parentIdx / w) | 0;\n const dx = clampDir(cx - px);\n const dy = clampDir(cy - py);\n\n if (dx !== 0 && dy !== 0) {\n // Diagonal move: check straight and diagonal successors\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (isWalkable(grid, cx + dx, cy + dy)) {\n const jp = jump(grid, cx, cy, dx, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n // Forced neighbors\n if (!isWalkable(grid, cx - dx, cy) && isWalkable(grid, cx - dx, cy + dy)) {\n const jp = jump(grid, cx, cy, -dx, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (!isWalkable(grid, cx, cy - dy) && isWalkable(grid, cx + dx, cy - dy)) {\n const jp = jump(grid, cx, cy, dx, -dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n } else if (dx !== 0) {\n // Horizontal move\n if (isWalkable(grid, cx + dx, cy)) {\n const jp = jump(grid, cx, cy, dx, 0, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (!isWalkable(grid, cx, cy + 1) && isWalkable(grid, cx + dx, cy + 1)) {\n const jp = jump(grid, cx, cy, dx, 1, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (!isWalkable(grid, cx, cy - 1) && isWalkable(grid, cx + dx, cy - 1)) {\n const jp = jump(grid, cx, cy, dx, -1, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n } else {\n // Vertical move\n if (isWalkable(grid, cx, cy + dy)) {\n const jp = jump(grid, cx, cy, 0, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (!isWalkable(grid, cx + 1, cy) && isWalkable(grid, cx + 1, cy + dy)) {\n const jp = jump(grid, cx, cy, 1, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n if (!isWalkable(grid, cx - 1, cy) && isWalkable(grid, cx - 1, cy + dy)) {\n const jp = jump(grid, cx, cy, -1, dy, w, h, ex, ey);\n if (jp !== -1) out[n++] = jp;\n }\n }\n }\n\n return n;\n}\n\nfunction jump(\n grid: Grid,\n cx: number,\n cy: number,\n dx: number,\n dy: number,\n w: number,\n h: number,\n ex: number,\n ey: number,\n): number {\n // One loop iteration per cell along the ray, so a long open corridor costs no\n // stack depth; only a diagonal ray calls back in, for its two cardinal probes\n // (which loop themselves), so the depth never exceeds two frames.\n let nx = cx;\n let ny = cy;\n for (;;) {\n nx += dx;\n ny += dy;\n\n if (!isWalkable(grid, nx, ny)) return -1;\n if (nx === ex && ny === ey) return ny * w + nx;\n\n // Forced neighbor check\n if (dx !== 0 && dy !== 0) {\n // Diagonal\n if (\n (!isWalkable(grid, nx - dx, ny) && isWalkable(grid, nx - dx, ny + dy)) ||\n (!isWalkable(grid, nx, ny - dy) && isWalkable(grid, nx + dx, ny - dy))\n ) {\n return ny * w + nx;\n }\n // Probe the cardinal directions\n if (jump(grid, nx, ny, dx, 0, w, h, ex, ey) !== -1) return ny * w + nx;\n if (jump(grid, nx, ny, 0, dy, w, h, ex, ey) !== -1) return ny * w + nx;\n } else if (dx !== 0) {\n // Horizontal\n if (\n (!isWalkable(grid, nx, ny + 1) && isWalkable(grid, nx + dx, ny + 1)) ||\n (!isWalkable(grid, nx, ny - 1) && isWalkable(grid, nx + dx, ny - 1))\n ) {\n return ny * w + nx;\n }\n } else {\n // Vertical\n if (\n (!isWalkable(grid, nx + 1, ny) && isWalkable(grid, nx + 1, ny + dy)) ||\n (!isWalkable(grid, nx - 1, ny) && isWalkable(grid, nx - 1, ny + dy))\n ) {\n return ny * w + nx;\n }\n }\n }\n}\n\nfunction clampDir(v: number): number {\n return v > 0 ? 1 : v < 0 ? -1 : 0;\n}\n\nfunction buildPath(\n cameFrom: Int32Array,\n w: number,\n endIdx: number,\n cost: number,\n explored: number,\n): PathResult {\n // JPS produces jump points — we interpolate the full path\n const jumpPoints: number[] = [];\n let idx = endIdx;\n while (idx !== -1) {\n jumpPoints.push(idx);\n idx = cameFrom[idx]!;\n }\n jumpPoints.reverse();\n\n const path: { x: number; y: number }[] = [];\n for (let i = 0; i < jumpPoints.length; i++) {\n const jpIdx = jumpPoints[i]!;\n const jx = jpIdx % w;\n const jy = (jpIdx / w) | 0;\n if (i === 0) {\n path.push({ x: jx, y: jy });\n } else {\n const prev = path[path.length - 1]!;\n // Interpolate from prev to current jump point\n let cx = prev.x;\n let cy = prev.y;\n while (cx !== jx || cy !== jy) {\n if (cx < jx) cx++;\n else if (cx > jx) cx--;\n if (cy < jy) cy++;\n else if (cy > jy) cy--;\n path.push({ x: cx, y: cy });\n }\n }\n }\n\n return { path, cost, explored };\n}\n","/**\n * Lightweight navmesh pathfinding for polygon-based environments.\n * Supports convex polygon navigation with A* over the polygon graph\n * and the Simple Stupid Funnel Algorithm for path smoothing.\n */\n\nimport type { Vec2 } from '@flare-engine/math';\n\n// ─── Types ───────────────────────────────────────────────────────\n\nexport interface NavMeshPolygon {\n readonly id: number;\n /** Convex polygon vertices in winding order. */\n readonly vertices: readonly Vec2[];\n /** One `Portal` per adjacent polygon: the shared edge plus that neighbour's id. */\n readonly portals: readonly Portal[];\n}\n\nexport interface Portal {\n /** Neighbor polygon id. */\n neighborId: number;\n /** Left endpoint of the shared edge (from the perspective of travel). */\n a: Vec2;\n /** Right endpoint of the shared edge. */\n b: Vec2;\n}\n\nexport interface NavMesh {\n readonly polygons: readonly NavMeshPolygon[];\n}\n\nexport interface NavMeshPathResult {\n /** Smoothed world-space waypoints. */\n path: Vec2[];\n /** Polygon ids traversed. */\n corridor: number[];\n}\n\n// ─── Construction ────────────────────────────────────────────────\n\nexport function createNavMesh(polygons: NavMeshPolygon[]): NavMesh {\n return { polygons };\n}\n\n// ─── Point-in-polygon ────────────────────────────────────────────\n\nfunction pointInConvexPolygon(verts: readonly Vec2[], px: number, py: number): boolean {\n const n = verts.length;\n if (n < 3) return false;\n let sign = 0;\n for (let i = 0; i < n; i++) {\n const a = verts[i]!;\n const b = verts[(i + 1) % n]!;\n const cross = (b.x - a.x) * (py - a.y) - (b.y - a.y) * (px - a.x);\n if (cross !== 0) {\n const s = cross > 0 ? 1 : -1;\n if (sign === 0) sign = s;\n else if (sign !== s) return false;\n }\n }\n return true;\n}\n\nexport function findPolygonAt(mesh: NavMesh, x: number, y: number): number {\n for (let i = 0; i < mesh.polygons.length; i++) {\n if (pointInConvexPolygon(mesh.polygons[i]!.vertices, x, y)) {\n return mesh.polygons[i]!.id;\n }\n }\n return -1;\n}\n\n// ─── Per-mesh index ──────────────────────────────────────────────\n\n/**\n * Id → position index plus centroid scratch, kept per mesh object in a WeakMap.\n * The mesh stays the caller's live data: a search rebuilds the index unless\n * every live polygon still sits at the position held for its id, reads polygons\n * and portals from `mesh.polygons`, and derives each centroid it needs from the\n * live vertices — once per polygon per search, marked by a generation stamp.\n */\ninterface MeshIndex {\n /** Position in `mesh.polygons` per polygon id; the last position wins for a duplicated id. */\n readonly pos: Map<number, number>;\n /** Centroid per position; valid for the current search only where `stamp[i] === gen`. */\n cx: Float64Array;\n cy: Float64Array;\n stamp: Uint32Array;\n /** Generation of the current search; starts at 1 so an untouched stamp (0) never matches. */\n gen: number;\n}\n\n// Stamps are Uint32; past this the generation wraps and every stamp is cleared.\nconst MAX_GEN = 0xffffffff;\n\nconst indices = new WeakMap<NavMesh, MeshIndex>();\n\n/** True when `pos` is exactly the id → position map of the live polygon list. */\nfunction isCurrent(index: MeshIndex, polygons: readonly NavMeshPolygon[]): boolean {\n if (index.pos.size !== polygons.length) return false;\n for (let i = 0; i < polygons.length; i++) {\n if (index.pos.get(polygons[i]!.id) !== i) return false;\n }\n return true;\n}\n\nfunction rebuild(index: MeshIndex, polygons: readonly NavMeshPolygon[]): void {\n index.pos.clear();\n for (let i = 0; i < polygons.length; i++) index.pos.set(polygons[i]!.id, i);\n if (index.cx.length < polygons.length) {\n index.cx = new Float64Array(polygons.length);\n index.cy = new Float64Array(polygons.length);\n index.stamp = new Uint32Array(polygons.length);\n }\n}\n\n/** The mesh's index, validated against the live polygon list and advanced to a new search generation. */\nfunction acquireIndex(mesh: NavMesh): MeshIndex {\n let index = indices.get(mesh);\n if (index === undefined) {\n index = {\n pos: new Map<number, number>(),\n cx: new Float64Array(0),\n cy: new Float64Array(0),\n stamp: new Uint32Array(0),\n gen: 0,\n };\n indices.set(mesh, index);\n }\n if (!isCurrent(index, mesh.polygons)) rebuild(index, mesh.polygons);\n if (index.gen === MAX_GEN) {\n index.stamp.fill(0);\n index.gen = 1;\n } else {\n index.gen++;\n }\n return index;\n}\n\n/** Makes `cx[i]` / `cy[i]` the centroid of the live polygon at `i`, summing its vertices once per search. */\nfunction centroidAt(index: MeshIndex, polygons: readonly NavMeshPolygon[], i: number): void {\n if (index.stamp[i] === index.gen) return;\n const verts = polygons[i]!.vertices;\n let sx = 0;\n let sy = 0;\n for (let j = 0; j < verts.length; j++) {\n sx += verts[j]!.x;\n sy += verts[j]!.y;\n }\n index.cx[i] = sx / verts.length;\n index.cy[i] = sy / verts.length;\n index.stamp[i] = index.gen;\n}\n\n// ─── A* over polygon graph ───────────────────────────────────────\n\nfunction distSq(ax: number, ay: number, bx: number, by: number): number {\n const dx = ax - bx;\n const dy = ay - by;\n return dx * dx + dy * dy;\n}\n\nfunction dist(ax: number, ay: number, bx: number, by: number): number {\n return Math.sqrt(distSq(ax, ay, bx, by));\n}\n\n/**\n * A* over the polygon graph, then funnel smoothing. Keeps an id index per mesh\n * object (rebuilt when the polygon list changes) and computes each polygon's\n * centroid at most once per search; edits to the mesh between searches are seen\n * by the next one.\n */\nexport function findNavMeshPath(mesh: NavMesh, start: Vec2, end: Vec2): NavMeshPathResult | null {\n const startPolyId = findPolygonAt(mesh, start.x, start.y);\n const endPolyId = findPolygonAt(mesh, end.x, end.y);\n if (startPolyId === -1 || endPolyId === -1) return null;\n if (startPolyId === endPolyId) {\n return {\n path: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n corridor: [startPolyId],\n };\n }\n\n const polygons = mesh.polygons;\n const index = acquireIndex(mesh);\n const { pos, cx, cy } = index;\n\n // A* on polygon graph\n const gScore = new Map<number, number>();\n const fScore = new Map<number, number>();\n const cameFrom = new Map<number, number>();\n\n gScore.set(startPolyId, 0);\n\n const endPos = pos.get(endPolyId)!;\n centroidAt(index, polygons, endPos);\n const endCx = cx[endPos]!;\n const endCy = cy[endPos]!;\n const startPos = pos.get(startPolyId)!;\n centroidAt(index, polygons, startPos);\n\n fScore.set(startPolyId, dist(cx[startPos]!, cy[startPos]!, endCx, endCy));\n\n // Simple array-based open set (fine for typical navmeshes with <1000 polygons)\n const open: number[] = [startPolyId];\n const inOpen = new Set<number>([startPolyId]);\n const closed = new Set<number>();\n\n while (open.length > 0) {\n // Find lowest f-score\n let bestI = 0;\n let bestF = fScore.get(open[0]!) ?? Number.POSITIVE_INFINITY;\n for (let i = 1; i < open.length; i++) {\n const f = fScore.get(open[i]!) ?? Number.POSITIVE_INFINITY;\n if (f < bestF) {\n bestF = f;\n bestI = i;\n }\n }\n const currentId = open[bestI]!;\n\n if (currentId === endPolyId) {\n // Reconstruct corridor\n const corridor: number[] = [];\n let id: number | undefined = endPolyId;\n while (id !== undefined) {\n corridor.push(id);\n id = cameFrom.get(id);\n }\n corridor.reverse();\n const path = funnelSmooth(mesh, index, corridor, start, end);\n return { path, corridor };\n }\n\n // Remove from open\n open[bestI] = open[open.length - 1]!;\n open.length--;\n inOpen.delete(currentId);\n closed.add(currentId);\n\n const currentPos = pos.get(currentId)!;\n const current = polygons[currentPos]!;\n centroidAt(index, polygons, currentPos);\n const currentCx = cx[currentPos]!;\n const currentCy = cy[currentPos]!;\n const currentG = gScore.get(currentId)!;\n\n for (let i = 0; i < current.portals.length; i++) {\n const portal = current.portals[i]!;\n const neighborId = portal.neighborId;\n if (closed.has(neighborId)) continue;\n\n const neighborPos = pos.get(neighborId);\n if (neighborPos === undefined) continue;\n\n const portalMidX = (portal.a.x + portal.b.x) * 0.5;\n const portalMidY = (portal.a.y + portal.b.y) * 0.5;\n const tentativeG = currentG + dist(currentCx, currentCy, portalMidX, portalMidY);\n\n const prevG = gScore.get(neighborId);\n if (prevG !== undefined && tentativeG >= prevG) continue;\n\n gScore.set(neighborId, tentativeG);\n cameFrom.set(neighborId, currentId);\n\n centroidAt(index, polygons, neighborPos);\n fScore.set(neighborId, tentativeG + dist(cx[neighborPos]!, cy[neighborPos]!, endCx, endCy));\n\n if (!inOpen.has(neighborId)) {\n open.push(neighborId);\n inOpen.add(neighborId);\n }\n }\n }\n\n return null;\n}\n\n// ─── Simple Stupid Funnel Algorithm ──────────────────────────────\n\nfunction funnelSmooth(\n mesh: NavMesh,\n index: MeshIndex,\n corridor: number[],\n start: Vec2,\n end: Vec2,\n): Vec2[] {\n if (corridor.length <= 1) {\n return [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ];\n }\n\n // Build portal list from corridor\n const portalsLeft: Vec2[] = [];\n const portalsRight: Vec2[] = [];\n\n portalsLeft.push({ x: start.x, y: start.y });\n portalsRight.push({ x: start.x, y: start.y });\n\n for (let i = 0; i < corridor.length - 1; i++) {\n const polyPos = index.pos.get(corridor[i]!)!;\n const poly = mesh.polygons[polyPos]!;\n const nextId = corridor[i + 1]!;\n // Find the portal to the next polygon\n let found = false;\n for (let j = 0; j < poly.portals.length; j++) {\n if (poly.portals[j]!.neighborId === nextId) {\n portalsLeft.push(poly.portals[j]!.a);\n portalsRight.push(poly.portals[j]!.b);\n found = true;\n break;\n }\n }\n if (!found) {\n // Fallback: straight line through centroids\n centroidAt(index, mesh.polygons, polyPos);\n const c = { x: index.cx[polyPos]!, y: index.cy[polyPos]! };\n portalsLeft.push(c);\n portalsRight.push(c);\n }\n }\n\n portalsLeft.push({ x: end.x, y: end.y });\n portalsRight.push({ x: end.x, y: end.y });\n\n // Simple Stupid Funnel Algorithm (Mononen)\n // Walk the portal list and maintain a funnel (apex, left, right).\n const path: Vec2[] = [];\n\n let apexPt = portalsLeft[0]!; // start point\n let leftPt = portalsLeft[0]!;\n let rightPt = portalsRight[0]!;\n let apexIdx = 0;\n let leftIdx = 0;\n let rightIdx = 0;\n\n path.push({ x: apexPt.x, y: apexPt.y });\n\n const n = portalsLeft.length;\n\n for (let i = 1; i < n; i++) {\n const pL = portalsLeft[i]!;\n const pR = portalsRight[i]!;\n\n // Try to tighten the right side\n if (triArea2(apexPt, rightPt, pR) <= 0) {\n if (vEqual(apexPt, rightPt) || triArea2(apexPt, leftPt, pR) > 0) {\n // Tighten\n rightPt = pR;\n rightIdx = i;\n } else {\n // Right crossed over left → left becomes new apex\n addUnique(path, leftPt);\n apexPt = leftPt;\n apexIdx = leftIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n continue;\n }\n }\n\n // Try to tighten the left side\n if (triArea2(apexPt, leftPt, pL) >= 0) {\n if (vEqual(apexPt, leftPt) || triArea2(apexPt, rightPt, pL) < 0) {\n // Tighten\n leftPt = pL;\n leftIdx = i;\n } else {\n // Left crossed over right → right becomes new apex\n addUnique(path, rightPt);\n apexPt = rightPt;\n apexIdx = rightIdx;\n // Reset funnel\n leftPt = apexPt;\n rightPt = apexPt;\n leftIdx = apexIdx;\n rightIdx = apexIdx;\n // Restart scan from the portal after the new apex\n i = apexIdx;\n }\n }\n }\n\n addUnique(path, end);\n\n return path;\n}\n\nfunction addUnique(path: Vec2[], p: Vec2): void {\n const last = path[path.length - 1];\n if (!last || last.x !== p.x || last.y !== p.y) {\n path.push({ x: p.x, y: p.y });\n }\n}\n\n/** Twice the signed area of the triangle (a, b, c). Positive = CCW. */\nfunction triArea2(a: Vec2, b: Vec2, c: Vec2): number {\n return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);\n}\n\nfunction vEqual(a: Vec2, b: Vec2): boolean {\n return a.x === b.x && a.y === b.y;\n}\n"],"mappings":"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"}
|