@daneren2005/shared-memory-objects 1.6.1 → 1.6.3

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.
Files changed (47) hide show
  1. package/README.md +3 -2
  2. package/dist/allocated-memory.js +1 -2
  3. package/dist/cached-item-list.js +1 -2
  4. package/dist/constant-string.js +13 -14
  5. package/dist/local-pool.js +5 -6
  6. package/dist/lock/read-write-lock.js +0 -1
  7. package/dist/lock/simple-lock.js +0 -1
  8. package/dist/memory-buffer.js +1 -2
  9. package/dist/memory-heap.js +24 -25
  10. package/dist/serialize-object.js +4 -5
  11. package/dist/shared-list.js +43 -44
  12. package/dist/shared-map.js +74 -75
  13. package/dist/shared-pointer-list.js +15 -16
  14. package/dist/shared-pool.d.ts +1 -0
  15. package/dist/shared-pool.js +36 -32
  16. package/dist/shared-pool.js.map +1 -1
  17. package/dist/shared-stack.js +33 -34
  18. package/dist/shared-string.js +19 -20
  19. package/dist/shared-vector.js +23 -24
  20. package/dist/spatial/shared-quadtree.js +81 -82
  21. package/dist/spatial/shared-quadtree.js.map +1 -1
  22. package/dist/spatial/shared-spatial-grid.js +104 -110
  23. package/dist/spatial/shared-spatial-grid.js.map +1 -1
  24. package/dist/spatial/shared-spatial-map.d.ts +2 -0
  25. package/dist/spatial/shared-spatial-map.js +205 -202
  26. package/dist/spatial/shared-spatial-map.js.map +1 -1
  27. package/dist/spatial/spatial-entity.js +1 -2
  28. package/dist/spatial/spatial-neighbors.js +1 -2
  29. package/dist/utils/16-from-32-array.js +1 -2
  30. package/dist/utils/16-from-32-float.js +1 -2
  31. package/dist/utils/16-from-32-int.js +1 -2
  32. package/dist/utils/16-from-32-uint.js +1 -2
  33. package/dist/utils/16-from-64-array.js +1 -2
  34. package/dist/utils/16-from-64-float.js +1 -2
  35. package/dist/utils/16-from-64-int.js +1 -2
  36. package/dist/utils/16-from-64-uint.js +1 -2
  37. package/dist/utils/32-from-64-float.js +1 -2
  38. package/dist/utils/32-from-64-int.js +1 -2
  39. package/dist/utils/32-from-64-uint.js +1 -2
  40. package/dist/utils/array-type.js +1 -2
  41. package/dist/utils/atomic-math.js +1 -2
  42. package/dist/utils/float32-atomics.js +1 -2
  43. package/dist/utils/float64-atomics.js +1 -2
  44. package/dist/utils/hash.js +1 -2
  45. package/dist/utils/pointer.js +1 -2
  46. package/dist/utils/typedarray.js +1 -2
  47. package/package.json +11 -11
@@ -1 +1 @@
1
- {"version":3,"file":"shared-quadtree.js","names":["AllocatedMemory","SharedMap","SharedPool","NODE_POINTER_INDEX","POOL_POINTER_INDEX","MAP_POINTER_INDEX","MAX_LEVELS_INDEX","NODE_COUNT_INDEX","TYPE_INDEX","BOUNDS_INDEX","NODE_LOCK_OFFSET","NODE_HEAD_OFFSET","NODE_SIZE","ITEM_ID","ITEM_X","ITEM_Y","ITEM_W","ITEM_H","ITEM_NODE","ITEM_NEXT","ITEM_FIELDS","FLOAT32_LIMIT","FLOAT32_NULL_INDEX","FLOAT64_NULL_INDEX","DEFAULT_MAX_LEVELS","DEFAULT_MAX_ENTITIES","DEFAULT_COORD_TYPE","SharedQuadtree","memory","config","getPointer","loadRawPointer","nullIndexFor","bounds","maxEntities","getCoordTypeCode","ARRAY_TYPE","poolConfig","getCoordTypeConstructor","getSpatialPoolChunkSize","getByteMultipler","poolAllocateCount","mapAllocateCount","boundsView","nodeBlock","heads","i","poolBlock","storeRawPointer","mapBlock","getSpatialMapCapacity","maxLevels","id","x","y","width","height","node","record","index","byId","entity","entities","unique","existing","mappings","newCount","count","nextIndex","block","offset","off","oldNode","newNode","lock","unlock","first","second","out","filter","start","write","read","maxResults","maxDistance","maxDistanceSquared","candidates","nodeCandidates","queue","MinPriorityQueue","root","distanceSquaredToRect","candidateLimit","candidate","duplicate","addCandidate","halfWidth","halfHeight","childLevel","children","child","distance","nearest","nodeX","nodeY","level","midX","midY","base","nextLevel","east","south","visit","childX","childY","keys","key","makeArrayView","nx","ny","nw","nh","west","north","headIndex","lockIndex","pool","hw","hh","overlapsWest","qx","overlapsEast","qw","overlapsNorth","qy","overlapsSouth","qh","head","next","prev","prevNext","code","getArrayTypeCode","type","typeCode"],"sources":["../../src/spatial/shared-quadtree.ts"],"sourcesContent":["import type { SharedAllocatedMemory } from '../allocated-memory';\nimport AllocatedMemory from '../allocated-memory';\nimport type MemoryHeap from '../memory-heap';\nimport SharedPool, { type SharedPoolConfig } from '../shared-pool';\nimport SharedMap from '../shared-map';\nimport { lock, unlock } from '../lock/simple-lock';\nimport { getPointer, loadRawPointer, storeRawPointer } from '../utils/pointer';\nimport { ARRAY_TYPE, getArrayTypeCode, getByteMultipler, makeArrayView } from '../utils/array-type';\nimport {\n\tMinPriorityQueue, addCandidate, candidateLimit, distanceSquaredToRect,\n\ttype NeighborCandidate, type NearestNeighbor,\n} from './spatial-neighbors';\nimport { getSpatialMapCapacity, getSpatialPoolChunkSize, type SpatialEntity } from './spatial-entity';\n\n// Fixed-depth region quadtree (\"implicit\" / hierarchical grid) built for concurrent updates from many threads. Dynamic\n// subdivision is deliberately avoided: creating/redistributing/freeing nodes at runtime races with readers mid-traversal\n// (the same hazard MemoryBuffer disables compaction for). Here the tree of nodes is allocated once and never changes\n// shape, so concurrency reduces to per-cell content updates - different cells never contend.\n//\n// Node layout is implicit: node 0 is the root, the four children of node i are 4i+1..4i+4 (NW, NE, SW, SE). Bounds are\n// derived from the root bounds during descent, never stored. Each node owns an intrusive singly-linked bucket: the node\n// record holds a lock and the head item index, and each item record carries the next index. Items live in a SharedPool\n// (stable indices, recycling) and an id->itemIndex SharedMap makes update/remove O(depth) by entity id.\n//\n// Each entity is stored in the single deepest node that fully contains its rect (an item too large or straddling a\n// midline stays at an ancestor). search walks every node whose region intersects the query and returns a broad-phase\n// superset of candidate ids - the same guarantee quadtree-js's retrieve gives, without duplicating straddlers.\n//\n// The whole item record (id, coords, node, bucket link) lives in one pool at the configured precision. Float32 (the\n// default, matching a physics engine that keeps positions in Float32) keeps everything exact as long as entity ids and\n// the pool's index space both stay under 2^24 (~16.7M) - every id, pool index, node index and the NULL sentinel is a\n// Float32-exact integer there. Need more than that many entities (or ids >= 2^24)? Pass type: Float64Array.\n\n// Header (firstBlock) u32 layout\nconst NODE_POINTER_INDEX = 0;\nconst POOL_POINTER_INDEX = 1;\nconst MAP_POINTER_INDEX = 2;\nconst MAX_LEVELS_INDEX = 3;\nconst NODE_COUNT_INDEX = 4;\nconst TYPE_INDEX = 5;\n// bounds view starts at slot 6 (offset 24 bytes is 8-byte aligned, so a Float64 bounds view is valid)\nconst BOUNDS_INDEX = 6;\n\n// Per-node record: [lock, head]\nconst NODE_LOCK_OFFSET = 0;\nconst NODE_HEAD_OFFSET = 1;\nconst NODE_SIZE = 2;\n\n// Item record fields\nconst ITEM_ID = 0;\nconst ITEM_X = 1;\nconst ITEM_Y = 2;\nconst ITEM_W = 3;\nconst ITEM_H = 4;\nconst ITEM_NODE = 5;\nconst ITEM_NEXT = 6;\nconst ITEM_FIELDS = 7;\n\n// Largest exact integer range for Float32 coordinates: [0, 2^24). Ids and pool indices must stay under this to survive a\n// Float32 round-trip, so it doubles as the Float32 entity cap and the value just past every valid index.\nconst FLOAT32_LIMIT = 0x1000000;\n// End-of-list / empty-bucket sentinel, chosen per element type so it is exact in the pool's view and above every valid\n// index: 2^24 for Float32 (its first non-representable index), 0xffffffff for Float64 (well within its exact range).\nconst FLOAT32_NULL_INDEX = FLOAT32_LIMIT;\nconst FLOAT64_NULL_INDEX = 0xffffffff;\n\nconst DEFAULT_MAX_LEVELS = 4;\nconst DEFAULT_MAX_ENTITIES = 1_000_000;\nconst DEFAULT_COORD_TYPE = Float32Array;\n\ntype CoordArray = Float32Array | Float64Array;\ntype CoordArrayConstructor = Float32ArrayConstructor | Float64ArrayConstructor;\n\nexport default class SharedQuadtree {\n\tstatic readonly ALLOCATE_COUNT = 14;\n\n\tprivate memory: MemoryHeap;\n\tprivate firstBlock: AllocatedMemory;\n\tprivate pool: SharedPool<CoordArray>;\n\tprivate idMap: SharedMap<number>;\n\n\t// Reused to hand a full item record to pool.push without allocating a fresh array per insert (single writer per id)\n\tprivate insertScratch: Array<number> = [0, 0, 0, 0, 0, 0, 0];\n\n\t// Node block views over one contiguous region: Int32 for the per-node locks, Uint32 for the head indexes.\n\tprivate nodeInts: Int32Array;\n\tprivate nodeHeads: Uint32Array;\n\n\tprivate readonly maxLevels: number;\n\tprivate readonly nodeCount: number;\n\tprivate readonly coordType: number;\n\t// Empty-bucket / end-of-list sentinel for this instance's element type (see FLOAT32_NULL_INDEX)\n\tprivate readonly nullIndex: number;\n\t// Root bounds, read once (stored at the configured precision, math done in float64)\n\tprivate readonly rootX: number;\n\tprivate readonly rootY: number;\n\tprivate readonly rootWidth: number;\n\tprivate readonly rootHeight: number;\n\n\t// Number of entities currently tracked\n\tget size(): number {\n\t\treturn this.idMap.length;\n\t}\n\n\tget bounds(): QuadtreeBounds {\n\t\treturn { x: this.rootX, y: this.rootY, width: this.rootWidth, height: this.rootHeight };\n\t}\n\n\t// Element type the record is stored in (an ARRAY_TYPE code: float32 or float64)\n\tget type(): number {\n\t\treturn this.coordType;\n\t}\n\n\tconstructor(memory: MemoryHeap, config?: SharedQuadtreeConfig | SharedQuadtreeMemory) {\n\t\tthis.memory = memory;\n\n\t\tif(config && 'firstBlock' in config) {\n\t\t\tthis.firstBlock = new AllocatedMemory(memory, config.firstBlock);\n\t\t\tthis.coordType = this.firstBlock.data[TYPE_INDEX];\n\t\t\tthis.pool = new SharedPool<CoordArray>(memory, {\n\t\t\t\tfirstBlock: getPointer(loadRawPointer(this.firstBlock.data, POOL_POINTER_INDEX), memory.positionBits),\n\t\t\t});\n\t\t\tthis.idMap = new SharedMap<number>(memory, {\n\t\t\t\tfirstBlock: getPointer(loadRawPointer(this.firstBlock.data, MAP_POINTER_INDEX), memory.positionBits),\n\t\t\t});\n\t\t\tthis.maxLevels = this.firstBlock.data[MAX_LEVELS_INDEX];\n\t\t\tthis.nodeCount = this.firstBlock.data[NODE_COUNT_INDEX];\n\t\t\tthis.nullIndex = nullIndexFor(this.coordType);\n\t\t} else {\n\t\t\tlet bounds = config?.bounds ?? { x: 0, y: 0, width: 0, height: 0 };\n\t\t\tlet maxEntities = config?.maxEntities ?? DEFAULT_MAX_ENTITIES;\n\t\t\tthis.maxLevels = config?.maxLevels ?? DEFAULT_MAX_LEVELS;\n\t\t\tthis.nodeCount = SharedQuadtree.getNodeCount(this.maxLevels);\n\t\t\tthis.coordType = getCoordTypeCode(config?.type);\n\t\t\tthis.nullIndex = nullIndexFor(this.coordType);\n\n\t\t\tif(this.coordType === ARRAY_TYPE.float32 && maxEntities > FLOAT32_LIMIT) {\n\t\t\t\tthrow new Error(`Float32 SharedQuadtree supports at most ${FLOAT32_LIMIT} entities; pass type: Float64Array for more`);\n\t\t\t}\n\n\t\t\t// Inline the pool and id-map firstBlocks right after the header so the whole spine is one contiguous allocation\n\t\t\t// (the pool's own firstBlock already inlines its two stacks). The node block stays separate: it is large and\n\t\t\t// sized independently of these headers.\n\t\t\tlet poolConfig: SharedPoolConfig<CoordArray> = {\n\t\t\t\ttype: getCoordTypeConstructor(this.coordType),\n\t\t\t\tdataLength: ITEM_FIELDS,\n\t\t\t\tmaxLength: maxEntities,\n\t\t\t\tmaxChunkSize: getSpatialPoolChunkSize(maxEntities, ITEM_FIELDS, getByteMultipler(this.coordType), memory.maxAllocationLength),\n\t\t\t};\n\t\t\tlet poolAllocateCount = SharedPool.getAllocateCount(memory, poolConfig);\n\t\t\tlet mapAllocateCount = SharedMap.ALLOCATE_COUNT;\n\t\t\tthis.firstBlock = memory.allocUI32(SharedQuadtree.ALLOCATE_COUNT + poolAllocateCount + mapAllocateCount);\n\t\t\tthis.firstBlock.data[MAX_LEVELS_INDEX] = this.maxLevels;\n\t\t\tthis.firstBlock.data[NODE_COUNT_INDEX] = this.nodeCount;\n\t\t\tthis.firstBlock.data[TYPE_INDEX] = this.coordType;\n\n\t\t\tlet boundsView = this.getBoundsView();\n\t\t\tboundsView[0] = bounds.x;\n\t\t\tboundsView[1] = bounds.y;\n\t\t\tboundsView[2] = bounds.width;\n\t\t\tboundsView[3] = bounds.height;\n\n\t\t\t// Node block must fit one allocation - it is never resized. Every head starts as NULL (calloc leaves them 0,\n\t\t\t// a valid item index, so they must be initialized explicitly).\n\t\t\tlet nodeBlock = memory.allocUI32(this.nodeCount * NODE_SIZE);\n\t\t\tlet heads = new Uint32Array(nodeBlock.data.buffer, nodeBlock.bufferByteOffset, this.nodeCount * NODE_SIZE);\n\t\t\tfor(let i = 0; i < this.nodeCount; i++) {\n\t\t\t\theads[i * NODE_SIZE + NODE_HEAD_OFFSET] = this.nullIndex;\n\t\t\t}\n\t\t\tstoreRawPointer(this.firstBlock.data, NODE_POINTER_INDEX, nodeBlock.pointer);\n\n\t\t\tlet poolBlock = this.firstBlock.getSubAllocation(SharedQuadtree.ALLOCATE_COUNT, poolAllocateCount);\n\t\t\tthis.pool = new SharedPool<CoordArray>(memory, { firstBlock: poolBlock, ...poolConfig });\n\t\t\tstoreRawPointer(this.firstBlock.data, POOL_POINTER_INDEX, poolBlock.pointer);\n\n\t\t\tlet mapBlock = this.firstBlock.getSubAllocation(SharedQuadtree.ALLOCATE_COUNT + poolAllocateCount, mapAllocateCount);\n\t\t\tthis.idMap = new SharedMap<number>(memory, { firstBlock: mapBlock, capacity: getSpatialMapCapacity(maxEntities, memory.maxAllocationLength) });\n\t\t\tstoreRawPointer(this.firstBlock.data, MAP_POINTER_INDEX, mapBlock.pointer);\n\t\t}\n\n\t\tlet boundsView = this.getBoundsView();\n\t\tthis.rootX = boundsView[0];\n\t\tthis.rootY = boundsView[1];\n\t\tthis.rootWidth = boundsView[2];\n\t\tthis.rootHeight = boundsView[3];\n\n\t\tlet nodeBlock = new AllocatedMemory(memory, getPointer(loadRawPointer(this.firstBlock.data, NODE_POINTER_INDEX), memory.positionBits));\n\t\tthis.nodeInts = new Int32Array(nodeBlock.data.buffer, nodeBlock.bufferByteOffset, this.nodeCount * NODE_SIZE);\n\t\tthis.nodeHeads = new Uint32Array(nodeBlock.data.buffer, nodeBlock.bufferByteOffset, this.nodeCount * NODE_SIZE);\n\t}\n\n\t// Total nodes in a complete quadtree of the given depth: sum of 4^level for level 0..maxLevels.\n\tstatic getNodeCount(maxLevels: number): number {\n\t\treturn (Math.pow(4, maxLevels + 1) - 1) / 3;\n\t}\n\n\tget pointer(): number {\n\t\treturn this.firstBlock.pointer;\n\t}\n\n\tget usedMemory(): number {\n\t\tlet nodeBlock = new AllocatedMemory(this.memory, getPointer(loadRawPointer(this.firstBlock.data, NODE_POINTER_INDEX), this.memory.positionBits));\n\t\treturn this.firstBlock.usedMemory + nodeBlock.usedMemory + this.pool.usedMemory + this.idMap.usedMemory;\n\t}\n\n\tinsert(id: number, x: number, y: number, width = 0, height = 0) {\n\t\tif(this.idMap.get(id) !== undefined) {\n\t\t\tthis.update(id, x, y, width, height);\n\t\t\treturn;\n\t\t}\n\n\t\tlet node = this.locate(x, y, width, height);\n\t\tlet record = this.insertScratch;\n\t\trecord[ITEM_ID] = id;\n\t\trecord[ITEM_X] = x;\n\t\trecord[ITEM_Y] = y;\n\t\trecord[ITEM_W] = width;\n\t\trecord[ITEM_H] = height;\n\t\trecord[ITEM_NODE] = node;\n\t\trecord[ITEM_NEXT] = this.nullIndex;\n\t\tlet index = this.pool.push(record);\n\t\tthis.linkIntoNode(node, index);\n\t\tthis.idMap.set(id, index);\n\t}\n\n\tbulkInsert(entities: Iterable<SpatialEntity>) {\n\t\tlet byId = new Map<number, SpatialEntity>();\n\t\tfor(let entity of entities) {\n\t\t\tbyId.set(entity.id, entity);\n\t\t}\n\t\tlet unique = Array.from(byId.values());\n\t\tlet existing = this.idMap.getAll(unique.map(entity => entity.id));\n\t\tlet mappings: Array<readonly [number, number]> = [];\n\t\tlet newCount = existing.reduce<number>((count, index) => count + (index === undefined ? 1 : 0), 0);\n\t\tlet nextIndex = this.pool.reserveContiguous(newCount);\n\t\tfor(let i = 0; i < unique.length; i++) {\n\t\t\tlet entity = unique[i];\n\t\t\tlet width = entity.width ?? 0;\n\t\t\tlet height = entity.height ?? 0;\n\t\t\tif(existing[i] !== undefined) {\n\t\t\t\tthis.update(entity.id, entity.x, entity.y, width, height);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet node = this.locate(entity.x, entity.y, width, height);\n\t\t\tlet index = nextIndex++;\n\t\t\tlet block = this.pool.blockFor(index);\n\t\t\tlet offset = this.pool.blockOffset(index);\n\t\t\tblock[offset + ITEM_ID] = entity.id;\n\t\t\tblock[offset + ITEM_X] = entity.x;\n\t\t\tblock[offset + ITEM_Y] = entity.y;\n\t\t\tblock[offset + ITEM_W] = width;\n\t\t\tblock[offset + ITEM_H] = height;\n\t\t\tblock[offset + ITEM_NODE] = node;\n\t\t\tblock[offset + ITEM_NEXT] = this.nullIndex;\n\t\t\tthis.linkIntoNode(node, index);\n\t\t\tmappings.push([entity.id, index]);\n\t\t}\n\t\tthis.idMap.setAll(mappings);\n\t}\n\n\t// Move an entity to a new position. Assumes a single writer per entity id (the standard shared-memory pattern - each\n\t// worker owns a disjoint set of entities), so this entity's item fields are stable until we lock its node(s).\n\tupdate(id: number, x: number, y: number, width = 0, height = 0) {\n\t\tlet index = this.idMap.get(id);\n\t\tif(index === undefined) {\n\t\t\tthis.insert(id, x, y, width, height);\n\t\t\treturn;\n\t\t}\n\n\t\tlet block = this.pool.blockFor(index);\n\t\tlet off = this.pool.blockOffset(index);\n\t\tlet oldNode = block[off + ITEM_NODE];\n\t\tlet newNode = this.locate(x, y, width, height);\n\n\t\tif(oldNode === newNode) {\n\t\t\t// Same cell: only the coordinates change, no relinking. Lock so a concurrent reader sees a consistent record.\n\t\t\tlock(this.nodeInts, oldNode * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\t\tblock[off + ITEM_X] = x;\n\t\t\tblock[off + ITEM_Y] = y;\n\t\t\tblock[off + ITEM_W] = width;\n\t\t\tblock[off + ITEM_H] = height;\n\t\t\tunlock(this.nodeInts, oldNode * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\t\treturn;\n\t\t}\n\n\t\t// Cross-cell move: hold both node locks, ordered by index to avoid deadlock with another thread moving the reverse way.\n\t\tlet first = Math.min(oldNode, newNode);\n\t\tlet second = Math.max(oldNode, newNode);\n\t\tlock(this.nodeInts, first * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\tlock(this.nodeInts, second * NODE_SIZE + NODE_LOCK_OFFSET);\n\n\t\tthis.unlinkNoLock(oldNode, index);\n\t\tblock[off + ITEM_X] = x;\n\t\tblock[off + ITEM_Y] = y;\n\t\tblock[off + ITEM_W] = width;\n\t\tblock[off + ITEM_H] = height;\n\t\tblock[off + ITEM_NODE] = newNode;\n\t\tthis.linkNoLock(newNode, index);\n\n\t\tunlock(this.nodeInts, second * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\tunlock(this.nodeInts, first * NODE_SIZE + NODE_LOCK_OFFSET);\n\t}\n\n\tremove(id: number): boolean {\n\t\tlet index = this.idMap.get(id);\n\t\tif(index === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet node = this.pool.get(index, ITEM_NODE);\n\t\tthis.unlinkFromNode(node, index);\n\t\tthis.pool.deleteIndex(index);\n\t\tthis.idMap.delete(id);\n\t\treturn true;\n\t}\n\n\thas(id: number): boolean {\n\t\treturn this.idMap.get(id) !== undefined;\n\t}\n\n\t// Broad-phase query: ids of every entity in a node whose region intersects the given rect. Result is a superset of true\n\t// overlaps (the caller does the narrow-phase check), matching quadtree-js retrieve.\n\tsearch(x: number, y: number, width: number, height: number, filter?: (id: number) => boolean): Array<number> {\n\t\tlet out: Array<number> = [];\n\t\tthis.searchInto(out, x, y, width, height, filter);\n\t\treturn out;\n\t}\n\t// Same as search but appends into a caller-owned array so hot loops can reuse it. Returns the array.\n\tsearchInto(out: Array<number>, x: number, y: number, width: number, height: number, filter?: (id: number) => boolean): Array<number> {\n\t\tlet start = out.length;\n\t\tthis.collect(out, 0, this.rootX, this.rootY, this.rootWidth, this.rootHeight, 0, x, y, width, height);\n\t\tif(filter !== undefined) {\n\t\t\tlet write = start;\n\t\t\tfor(let read = start; read < out.length; read++) {\n\t\t\t\tlet id = out[read];\n\t\t\t\tif(filter(id)) {\n\t\t\t\t\tout[write++] = id;\n\t\t\t\t}\n\t\t\t}\n\t\t\tout.length = write;\n\t\t}\n\t\treturn out;\n\t}\n\n\tneighbors(x: number, y: number, maxResults: number, maxDistance: number, filter?: (id: number) => boolean): Array<number> {\n\t\tif(maxResults <= 0 || maxDistance < 0 || Number.isNaN(maxResults) || Number.isNaN(maxDistance)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tinterface Node {\n\t\t\tindex: number\n\t\t\tx: number\n\t\t\ty: number\n\t\t\twidth: number\n\t\t\theight: number\n\t\t\tlevel: number\n\t\t}\n\t\tmaxResults = Math.floor(maxResults);\n\t\tif(maxResults === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tlet maxDistanceSquared = maxDistance * maxDistance;\n\t\tif(maxResults === 1) {\n\t\t\treturn this.nearestNeighbor(x, y, maxDistanceSquared, filter);\n\t\t}\n\t\tlet candidates: Array<NeighborCandidate> = [];\n\t\tlet nodeCandidates: Array<NeighborCandidate> = [];\n\t\tlet queue = new MinPriorityQueue<Node>();\n\t\tlet root = { index: 0, x: this.rootX, y: this.rootY, width: this.rootWidth, height: this.rootHeight, level: 0 };\n\t\tqueue.push(root, distanceSquaredToRect(x, y, this.rootX, this.rootY, this.rootX + this.rootWidth, this.rootY + this.rootHeight));\n\n\t\twhile(queue.length > 0 && queue.priority <= candidateLimit(candidates, maxResults, maxDistanceSquared)) {\n\t\t\tlet node = queue.pop();\n\t\t\tif(node === undefined) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnodeCandidates.length = 0;\n\t\t\tthis.collectNeighborNode(nodeCandidates, node.index, x, y, maxDistanceSquared);\n\t\t\tfor(let candidate of nodeCandidates) {\n\t\t\t\tlet duplicate = false;\n\t\t\t\tfor(let existing of candidates) {\n\t\t\t\t\tif(existing.id === candidate.id) {\n\t\t\t\t\t\tduplicate = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(duplicate) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif(filter === undefined || filter(candidate.id)) {\n\t\t\t\t\taddCandidate(candidates, candidate.id, candidate.distance, maxResults);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(node.level >= this.maxLevels) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet halfWidth = node.width / 2;\n\t\t\tlet halfHeight = node.height / 2;\n\t\t\tlet childLevel = node.level + 1;\n\t\t\tlet children: Array<Node> = [\n\t\t\t\t{ index: node.index * 4 + 1, x: node.x, y: node.y, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t\t{ index: node.index * 4 + 2, x: node.x + halfWidth, y: node.y, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t\t{ index: node.index * 4 + 3, x: node.x, y: node.y + halfHeight, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t\t{ index: node.index * 4 + 4, x: node.x + halfWidth, y: node.y + halfHeight, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t];\n\t\t\tfor(let child of children) {\n\t\t\t\tlet distance = distanceSquaredToRect(x, y, child.x, child.y, child.x + child.width, child.y + child.height);\n\t\t\t\tif(distance <= candidateLimit(candidates, maxResults, maxDistanceSquared)) {\n\t\t\t\t\tqueue.push(child, distance);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn candidates.map(candidate => candidate.id);\n\t}\n\n\tprivate nearestNeighbor(\n\t\tx: number, y: number, maxDistanceSquared: number, filter: ((id: number) => boolean) | undefined,\n\t): Array<number> {\n\t\tlet nearest: NearestNeighbor = { id: undefined, distance: maxDistanceSquared };\n\t\tlet nodeCandidates: Array<NeighborCandidate> = [];\n\t\tthis.findNearest(\n\t\t\t0, this.rootX, this.rootY, this.rootWidth, this.rootHeight, 0,\n\t\t\tx, y, nearest, nodeCandidates, filter,\n\t\t);\n\t\treturn nearest.id === undefined ? [] : [nearest.id];\n\t}\n\n\tprivate findNearest(\n\t\tnode: number, nodeX: number, nodeY: number, width: number, height: number, level: number,\n\t\tx: number, y: number, nearest: NearestNeighbor,\n\t\tnodeCandidates: Array<NeighborCandidate>, filter: ((id: number) => boolean) | undefined,\n\t) {\n\t\tif(distanceSquaredToRect(x, y, nodeX, nodeY, nodeX + width, nodeY + height) > nearest.distance) {\n\t\t\treturn;\n\t\t}\n\t\tif(filter === undefined) {\n\t\t\tthis.collectNearestNode(nearest, node, x, y);\n\t\t} else {\n\t\t\tnodeCandidates.length = 0;\n\t\t\tthis.collectNeighborNode(nodeCandidates, node, x, y, nearest.distance);\n\t\t\tfor(let candidate of nodeCandidates) {\n\t\t\t\tif(filter(candidate.id)\n\t\t\t\t\t&& (candidate.distance < nearest.distance\n\t\t\t\t\t\t|| (candidate.distance === nearest.distance && (nearest.id === undefined || candidate.id < nearest.id)))) {\n\t\t\t\t\tnearest.id = candidate.id;\n\t\t\t\t\tnearest.distance = candidate.distance;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(level >= this.maxLevels) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet halfWidth = width / 2;\n\t\tlet halfHeight = height / 2;\n\t\tlet midX = nodeX + halfWidth;\n\t\tlet midY = nodeY + halfHeight;\n\t\tlet base = node * 4;\n\t\tlet nextLevel = level + 1;\n\t\tlet east = x >= midX;\n\t\tlet south = y >= midY;\n\t\tlet visit = (index: number, childX: number, childY: number) => {\n\t\t\tthis.findNearest(\n\t\t\t\tindex, childX, childY, halfWidth, halfHeight, nextLevel,\n\t\t\t\tx, y, nearest, nodeCandidates, filter,\n\t\t\t);\n\t\t};\n\t\tif(south) {\n\t\t\tif(east) {\n\t\t\t\tvisit(base + 4, midX, midY);\n\t\t\t\tvisit(base + 3, nodeX, midY);\n\t\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\t} else {\n\t\t\t\tvisit(base + 3, nodeX, midY);\n\t\t\t\tvisit(base + 4, midX, midY);\n\t\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\t}\n\t\t} else if(east) {\n\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\tvisit(base + 4, midX, midY);\n\t\t\tvisit(base + 3, nodeX, midY);\n\t\t} else {\n\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\tvisit(base + 3, nodeX, midY);\n\t\t\tvisit(base + 4, midX, midY);\n\t\t}\n\t}\n\n\tclear() {\n\t\tfor(let i = 0; i < this.nodeCount; i++) {\n\t\t\tthis.nodeHeads[i * NODE_SIZE + NODE_HEAD_OFFSET] = this.nullIndex;\n\t\t}\n\t\tthis.pool.clear();\n\t\t// SharedMap has no clear(); drop every key. Not safe to run concurrently with writers (documented on clear()).\n\t\tlet keys: Array<number> = [];\n\t\tfor(let [key] of this.idMap) {\n\t\t\tkeys.push(key);\n\t\t}\n\t\tfor(let key of keys) {\n\t\t\tthis.idMap.delete(key);\n\t\t}\n\t}\n\n\tfree() {\n\t\tlet nodeBlock = new AllocatedMemory(this.memory, getPointer(loadRawPointer(this.firstBlock.data, NODE_POINTER_INDEX), this.memory.positionBits));\n\t\tnodeBlock.free();\n\t\tthis.pool.free();\n\t\tthis.idMap.free();\n\t\tthis.firstBlock.free();\n\t}\n\n\tgetSharedMemory(): SharedQuadtreeMemory {\n\t\treturn {\n\t\t\tfirstBlock: this.firstBlock.getSharedMemory(),\n\t\t};\n\t}\n\n\tprivate getBoundsView(): CoordArray {\n\t\treturn makeArrayView(\n\t\t\tthis.coordType,\n\t\t\tthis.firstBlock.data.buffer,\n\t\t\tthis.firstBlock.bufferByteOffset + BOUNDS_INDEX * Uint32Array.BYTES_PER_ELEMENT,\n\t\t\t4,\n\t\t) as CoordArray;\n\t}\n\n\t// Deepest node index that fully contains the rect. Descends into the one child that still fully contains it; stops at a\n\t// straddle or at max depth.\n\tprivate locate(x: number, y: number, width: number, height: number): number {\n\t\tlet node = 0;\n\t\tlet nx = this.rootX;\n\t\tlet ny = this.rootY;\n\t\tlet nw = this.rootWidth;\n\t\tlet nh = this.rootHeight;\n\n\t\tfor(let level = 0; level < this.maxLevels; level++) {\n\t\t\tlet midX = nx + nw / 2;\n\t\t\tlet midY = ny + nh / 2;\n\t\t\tlet west = x >= nx && x + width <= midX && (width > 0 || x < midX);\n\t\t\tlet east = x >= midX && x + width <= nx + nw;\n\t\t\tlet north = y >= ny && y + height <= midY && (height > 0 || y < midY);\n\t\t\tlet south = y >= midY && y + height <= ny + nh;\n\n\t\t\tif(north && west) {\n\t\t\t\tnode = node * 4 + 1;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else if(north && east) {\n\t\t\t\tnode = node * 4 + 2;\n\t\t\t\tnx = midX;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else if(south && west) {\n\t\t\t\tnode = node * 4 + 3;\n\t\t\t\tny = midY;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else if(south && east) {\n\t\t\t\tnode = node * 4 + 4;\n\t\t\t\tnx = midX;\n\t\t\t\tny = midY;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate collect(out: Array<number>, node: number, nx: number, ny: number, nw: number, nh: number, level: number, qx: number, qy: number, qw: number, qh: number) {\n\t\t// Peek the head unlocked: an empty bucket has nothing to read, so the lock (and its atomics) is pure overhead. Most\n\t\t// nodes in a fixed-depth tree are empty, so skipping them dominates query cost. Taking the lock only to walk a\n\t\t// non-empty bucket preserves the snapshot guarantee - a concurrent insert we race is simply not in this snapshot.\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tif(this.nodeHeads[headIndex] !== this.nullIndex) {\n\t\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\t\tlock(this.nodeInts, lockIndex);\n\t\t\tlet index = this.nodeHeads[headIndex];\n\t\t\tlet pool = this.pool;\n\t\t\twhile(index !== this.nullIndex) {\n\t\t\t\t// One chunk resolve per item covers both fields it reads\n\t\t\t\tlet block = pool.blockFor(index);\n\t\t\t\tlet off = pool.blockOffset(index);\n\t\t\t\tout.push(block[off + ITEM_ID]);\n\t\t\t\tindex = block[off + ITEM_NEXT];\n\t\t\t}\n\t\t\tunlock(this.nodeInts, lockIndex);\n\t\t}\n\n\t\tif(level >= this.maxLevels) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet midX = nx + nw / 2;\n\t\tlet midY = ny + nh / 2;\n\t\tlet hw = nw / 2;\n\t\tlet hh = nh / 2;\n\t\tlet overlapsWest = qx < midX;\n\t\tlet overlapsEast = qx + qw > midX;\n\t\tlet overlapsNorth = qy < midY;\n\t\tlet overlapsSouth = qy + qh > midY;\n\n\t\tif(overlapsNorth && overlapsWest) {\n\t\t\tthis.collect(out, node * 4 + 1, nx, ny, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t\tif(overlapsNorth && overlapsEast) {\n\t\t\tthis.collect(out, node * 4 + 2, midX, ny, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t\tif(overlapsSouth && overlapsWest) {\n\t\t\tthis.collect(out, node * 4 + 3, nx, midY, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t\tif(overlapsSouth && overlapsEast) {\n\t\t\tthis.collect(out, node * 4 + 4, midX, midY, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t}\n\n\tprivate collectNeighborNode(\n\t\tout: Array<NeighborCandidate>, node: number, x: number, y: number, maxDistanceSquared: number,\n\t) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tif(this.nodeHeads[headIndex] === this.nullIndex) {\n\t\t\treturn;\n\t\t}\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tlet index = this.nodeHeads[headIndex];\n\t\twhile(index !== this.nullIndex) {\n\t\t\tlet block = this.pool.blockFor(index);\n\t\t\tlet off = this.pool.blockOffset(index);\n\t\t\tlet id = block[off + ITEM_ID];\n\t\t\tlet distance = distanceSquaredToRect(x, y, block[off + ITEM_X], block[off + ITEM_Y], block[off + ITEM_X] + block[off + ITEM_W], block[off + ITEM_Y] + block[off + ITEM_H]);\n\t\t\tif(distance <= maxDistanceSquared) {\n\t\t\t\tout.push({ id, distance });\n\t\t\t}\n\t\t\tindex = block[off + ITEM_NEXT];\n\t\t}\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\n\tprivate collectNearestNode(nearest: NearestNeighbor, node: number, x: number, y: number) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tif(this.nodeHeads[headIndex] === this.nullIndex) {\n\t\t\treturn;\n\t\t}\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tlet index = this.nodeHeads[headIndex];\n\t\twhile(index !== this.nullIndex) {\n\t\t\tlet block = this.pool.blockFor(index);\n\t\t\tlet off = this.pool.blockOffset(index);\n\t\t\tlet id = block[off + ITEM_ID];\n\t\t\tlet distance = distanceSquaredToRect(\n\t\t\t\tx, y, block[off + ITEM_X], block[off + ITEM_Y],\n\t\t\t\tblock[off + ITEM_X] + block[off + ITEM_W], block[off + ITEM_Y] + block[off + ITEM_H],\n\t\t\t);\n\t\t\tif(distance < nearest.distance\n\t\t\t\t|| (distance === nearest.distance && (nearest.id === undefined || id < nearest.id))) {\n\t\t\t\tnearest.id = id;\n\t\t\t\tnearest.distance = distance;\n\t\t\t}\n\t\t\tindex = block[off + ITEM_NEXT];\n\t\t}\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\n\tprivate linkIntoNode(node: number, index: number) {\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tthis.linkNoLock(node, index);\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\t// Push the item onto the node's bucket head. Caller holds the node lock.\n\tprivate linkNoLock(node: number, index: number) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tthis.pool.set(index, ITEM_NEXT, this.nodeHeads[headIndex]);\n\t\tthis.nodeHeads[headIndex] = index;\n\t}\n\n\tprivate unlinkFromNode(node: number, index: number) {\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tthis.unlinkNoLock(node, index);\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\t// Splice the item out of the node's bucket. Caller holds the node lock.\n\tprivate unlinkNoLock(node: number, index: number) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tlet head = this.nodeHeads[headIndex];\n\t\tlet next = this.pool.get(index, ITEM_NEXT);\n\t\tif(head === index) {\n\t\t\tthis.nodeHeads[headIndex] = next;\n\t\t\treturn;\n\t\t}\n\n\t\tlet prev = head;\n\t\twhile(prev !== this.nullIndex) {\n\t\t\tlet prevNext = this.pool.get(prev, ITEM_NEXT);\n\t\t\tif(prevNext === index) {\n\t\t\t\tthis.pool.set(prev, ITEM_NEXT, next);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprev = prevNext;\n\t\t}\n\t}\n}\n\nfunction getCoordTypeCode(type: CoordArrayConstructor | undefined): number {\n\tlet code = getArrayTypeCode(type ?? DEFAULT_COORD_TYPE);\n\tif(code !== ARRAY_TYPE.float32 && code !== ARRAY_TYPE.float64) {\n\t\tthrow new Error('SharedQuadtree must be Float32Array or Float64Array');\n\t}\n\treturn code;\n}\nfunction getCoordTypeConstructor(typeCode: number): CoordArrayConstructor {\n\treturn getByteMultipler(typeCode) === 2 ? Float64Array : Float32Array;\n}\nfunction nullIndexFor(typeCode: number): number {\n\treturn typeCode === ARRAY_TYPE.float32 ? FLOAT32_NULL_INDEX : FLOAT64_NULL_INDEX;\n}\n\ninterface QuadtreeBounds {\n\tx: number\n\ty: number\n\twidth: number\n\theight: number\n}\ninterface SharedQuadtreeConfig {\n\tbounds: QuadtreeBounds\n\tmaxLevels?: number\n\tmaxEntities?: number\n\ttype?: CoordArrayConstructor\n}\ninterface SharedQuadtreeMemory {\n\tfirstBlock: SharedAllocatedMemory\n}\n\nexport type { SharedQuadtreeConfig, SharedQuadtreeMemory, QuadtreeBounds, SpatialEntity };\n"],"mappings":"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"}
1
+ {"version":3,"file":"shared-quadtree.js","names":["AllocatedMemory","SharedPool","SharedMap","NODE_POINTER_INDEX","POOL_POINTER_INDEX","MAP_POINTER_INDEX","MAX_LEVELS_INDEX","NODE_COUNT_INDEX","TYPE_INDEX","BOUNDS_INDEX","NODE_LOCK_OFFSET","NODE_HEAD_OFFSET","NODE_SIZE","ITEM_ID","ITEM_X","ITEM_Y","ITEM_W","ITEM_H","ITEM_NODE","ITEM_NEXT","ITEM_FIELDS","FLOAT32_LIMIT","FLOAT32_NULL_INDEX","FLOAT64_NULL_INDEX","DEFAULT_MAX_LEVELS","DEFAULT_MAX_ENTITIES","DEFAULT_COORD_TYPE","SharedQuadtree","memory","config","getPointer","loadRawPointer","nullIndexFor","bounds","maxEntities","getCoordTypeCode","ARRAY_TYPE","poolConfig","getCoordTypeConstructor","getSpatialPoolChunkSize","getByteMultipler","poolAllocateCount","mapAllocateCount","boundsView","nodeBlock","heads","i","poolBlock","storeRawPointer","mapBlock","getSpatialMapCapacity","maxLevels","id","x","y","width","height","node","record","index","byId","entity","entities","unique","existing","mappings","newCount","count","nextIndex","block","offset","off","oldNode","newNode","lock","unlock","first","second","out","filter","start","write","read","maxResults","maxDistance","maxDistanceSquared","candidates","nodeCandidates","queue","MinPriorityQueue","root","distanceSquaredToRect","candidateLimit","candidate","duplicate","addCandidate","halfWidth","halfHeight","childLevel","children","child","distance","nearest","nodeX","nodeY","level","midX","midY","base","nextLevel","east","south","visit","childX","childY","keys","key","makeArrayView","nx","ny","nw","nh","west","north","headIndex","lockIndex","pool","hw","hh","overlapsWest","qx","overlapsEast","qw","overlapsNorth","qy","overlapsSouth","qh","head","next","prev","prevNext","code","getArrayTypeCode","type","typeCode"],"sources":["../../src/spatial/shared-quadtree.ts"],"sourcesContent":["import type { SharedAllocatedMemory } from '../allocated-memory';\nimport AllocatedMemory from '../allocated-memory';\nimport type MemoryHeap from '../memory-heap';\nimport SharedPool, { type SharedPoolConfig } from '../shared-pool';\nimport SharedMap from '../shared-map';\nimport { lock, unlock } from '../lock/simple-lock';\nimport { getPointer, loadRawPointer, storeRawPointer } from '../utils/pointer';\nimport { ARRAY_TYPE, getArrayTypeCode, getByteMultipler, makeArrayView } from '../utils/array-type';\nimport {\n\tMinPriorityQueue, addCandidate, candidateLimit, distanceSquaredToRect,\n\ttype NeighborCandidate, type NearestNeighbor,\n} from './spatial-neighbors';\nimport { getSpatialMapCapacity, getSpatialPoolChunkSize, type SpatialEntity } from './spatial-entity';\n\n// Fixed-depth region quadtree (\"implicit\" / hierarchical grid) built for concurrent updates from many threads. Dynamic\n// subdivision is deliberately avoided: creating/redistributing/freeing nodes at runtime races with readers mid-traversal\n// (the same hazard MemoryBuffer disables compaction for). Here the tree of nodes is allocated once and never changes\n// shape, so concurrency reduces to per-cell content updates - different cells never contend.\n//\n// Node layout is implicit: node 0 is the root, the four children of node i are 4i+1..4i+4 (NW, NE, SW, SE). Bounds are\n// derived from the root bounds during descent, never stored. Each node owns an intrusive singly-linked bucket: the node\n// record holds a lock and the head item index, and each item record carries the next index. Items live in a SharedPool\n// (stable indices, recycling) and an id->itemIndex SharedMap makes update/remove O(depth) by entity id.\n//\n// Each entity is stored in the single deepest node that fully contains its rect (an item too large or straddling a\n// midline stays at an ancestor). search walks every node whose region intersects the query and returns a broad-phase\n// superset of candidate ids - the same guarantee quadtree-js's retrieve gives, without duplicating straddlers.\n//\n// The whole item record (id, coords, node, bucket link) lives in one pool at the configured precision. Float32 (the\n// default, matching a physics engine that keeps positions in Float32) keeps everything exact as long as entity ids and\n// the pool's index space both stay under 2^24 (~16.7M) - every id, pool index, node index and the NULL sentinel is a\n// Float32-exact integer there. Need more than that many entities (or ids >= 2^24)? Pass type: Float64Array.\n\n// Header (firstBlock) u32 layout\nconst NODE_POINTER_INDEX = 0;\nconst POOL_POINTER_INDEX = 1;\nconst MAP_POINTER_INDEX = 2;\nconst MAX_LEVELS_INDEX = 3;\nconst NODE_COUNT_INDEX = 4;\nconst TYPE_INDEX = 5;\n// bounds view starts at slot 6 (offset 24 bytes is 8-byte aligned, so a Float64 bounds view is valid)\nconst BOUNDS_INDEX = 6;\n\n// Per-node record: [lock, head]\nconst NODE_LOCK_OFFSET = 0;\nconst NODE_HEAD_OFFSET = 1;\nconst NODE_SIZE = 2;\n\n// Item record fields\nconst ITEM_ID = 0;\nconst ITEM_X = 1;\nconst ITEM_Y = 2;\nconst ITEM_W = 3;\nconst ITEM_H = 4;\nconst ITEM_NODE = 5;\nconst ITEM_NEXT = 6;\nconst ITEM_FIELDS = 7;\n\n// Largest exact integer range for Float32 coordinates: [0, 2^24). Ids and pool indices must stay under this to survive a\n// Float32 round-trip, so it doubles as the Float32 entity cap and the value just past every valid index.\nconst FLOAT32_LIMIT = 0x1000000;\n// End-of-list / empty-bucket sentinel, chosen per element type so it is exact in the pool's view and above every valid\n// index: 2^24 for Float32 (its first non-representable index), 0xffffffff for Float64 (well within its exact range).\nconst FLOAT32_NULL_INDEX = FLOAT32_LIMIT;\nconst FLOAT64_NULL_INDEX = 0xffffffff;\n\nconst DEFAULT_MAX_LEVELS = 4;\nconst DEFAULT_MAX_ENTITIES = 1_000_000;\nconst DEFAULT_COORD_TYPE = Float32Array;\n\ntype CoordArray = Float32Array | Float64Array;\ntype CoordArrayConstructor = Float32ArrayConstructor | Float64ArrayConstructor;\n\nexport default class SharedQuadtree {\n\tstatic readonly ALLOCATE_COUNT = 14;\n\n\tprivate memory: MemoryHeap;\n\tprivate firstBlock: AllocatedMemory;\n\tprivate pool: SharedPool<CoordArray>;\n\tprivate idMap: SharedMap<number>;\n\n\t// Reused to hand a full item record to pool.push without allocating a fresh array per insert (single writer per id)\n\tprivate insertScratch: Array<number> = [0, 0, 0, 0, 0, 0, 0];\n\n\t// Node block views over one contiguous region: Int32 for the per-node locks, Uint32 for the head indexes.\n\tprivate nodeInts: Int32Array;\n\tprivate nodeHeads: Uint32Array;\n\n\tprivate readonly maxLevels: number;\n\tprivate readonly nodeCount: number;\n\tprivate readonly coordType: number;\n\t// Empty-bucket / end-of-list sentinel for this instance's element type (see FLOAT32_NULL_INDEX)\n\tprivate readonly nullIndex: number;\n\t// Root bounds, read once (stored at the configured precision, math done in float64)\n\tprivate readonly rootX: number;\n\tprivate readonly rootY: number;\n\tprivate readonly rootWidth: number;\n\tprivate readonly rootHeight: number;\n\n\t// Number of entities currently tracked\n\tget size(): number {\n\t\treturn this.idMap.length;\n\t}\n\n\tget bounds(): QuadtreeBounds {\n\t\treturn { x: this.rootX, y: this.rootY, width: this.rootWidth, height: this.rootHeight };\n\t}\n\n\t// Element type the record is stored in (an ARRAY_TYPE code: float32 or float64)\n\tget type(): number {\n\t\treturn this.coordType;\n\t}\n\n\tconstructor(memory: MemoryHeap, config?: SharedQuadtreeConfig | SharedQuadtreeMemory) {\n\t\tthis.memory = memory;\n\n\t\tif(config && 'firstBlock' in config) {\n\t\t\tthis.firstBlock = new AllocatedMemory(memory, config.firstBlock);\n\t\t\tthis.coordType = this.firstBlock.data[TYPE_INDEX];\n\t\t\tthis.pool = new SharedPool<CoordArray>(memory, {\n\t\t\t\tfirstBlock: getPointer(loadRawPointer(this.firstBlock.data, POOL_POINTER_INDEX), memory.positionBits),\n\t\t\t});\n\t\t\tthis.idMap = new SharedMap<number>(memory, {\n\t\t\t\tfirstBlock: getPointer(loadRawPointer(this.firstBlock.data, MAP_POINTER_INDEX), memory.positionBits),\n\t\t\t});\n\t\t\tthis.maxLevels = this.firstBlock.data[MAX_LEVELS_INDEX];\n\t\t\tthis.nodeCount = this.firstBlock.data[NODE_COUNT_INDEX];\n\t\t\tthis.nullIndex = nullIndexFor(this.coordType);\n\t\t} else {\n\t\t\tlet bounds = config?.bounds ?? { x: 0, y: 0, width: 0, height: 0 };\n\t\t\tlet maxEntities = config?.maxEntities ?? DEFAULT_MAX_ENTITIES;\n\t\t\tthis.maxLevels = config?.maxLevels ?? DEFAULT_MAX_LEVELS;\n\t\t\tthis.nodeCount = SharedQuadtree.getNodeCount(this.maxLevels);\n\t\t\tthis.coordType = getCoordTypeCode(config?.type);\n\t\t\tthis.nullIndex = nullIndexFor(this.coordType);\n\n\t\t\tif(this.coordType === ARRAY_TYPE.float32 && maxEntities > FLOAT32_LIMIT) {\n\t\t\t\tthrow new Error(`Float32 SharedQuadtree supports at most ${FLOAT32_LIMIT} entities; pass type: Float64Array for more`);\n\t\t\t}\n\n\t\t\t// Inline the pool and id-map firstBlocks right after the header so the whole spine is one contiguous allocation\n\t\t\t// (the pool's own firstBlock already inlines its two stacks). The node block stays separate: it is large and\n\t\t\t// sized independently of these headers.\n\t\t\tlet poolConfig: SharedPoolConfig<CoordArray> = {\n\t\t\t\ttype: getCoordTypeConstructor(this.coordType),\n\t\t\t\tdataLength: ITEM_FIELDS,\n\t\t\t\tmaxLength: maxEntities,\n\t\t\t\tmaxChunkSize: getSpatialPoolChunkSize(maxEntities, ITEM_FIELDS, getByteMultipler(this.coordType), memory.maxAllocationLength),\n\t\t\t};\n\t\t\tlet poolAllocateCount = SharedPool.getAllocateCount(memory, poolConfig);\n\t\t\tlet mapAllocateCount = SharedMap.ALLOCATE_COUNT;\n\t\t\tthis.firstBlock = memory.allocUI32(SharedQuadtree.ALLOCATE_COUNT + poolAllocateCount + mapAllocateCount);\n\t\t\tthis.firstBlock.data[MAX_LEVELS_INDEX] = this.maxLevels;\n\t\t\tthis.firstBlock.data[NODE_COUNT_INDEX] = this.nodeCount;\n\t\t\tthis.firstBlock.data[TYPE_INDEX] = this.coordType;\n\n\t\t\tlet boundsView = this.getBoundsView();\n\t\t\tboundsView[0] = bounds.x;\n\t\t\tboundsView[1] = bounds.y;\n\t\t\tboundsView[2] = bounds.width;\n\t\t\tboundsView[3] = bounds.height;\n\n\t\t\t// Node block must fit one allocation - it is never resized. Every head starts as NULL (calloc leaves them 0,\n\t\t\t// a valid item index, so they must be initialized explicitly).\n\t\t\tlet nodeBlock = memory.allocUI32(this.nodeCount * NODE_SIZE);\n\t\t\tlet heads = new Uint32Array(nodeBlock.data.buffer, nodeBlock.bufferByteOffset, this.nodeCount * NODE_SIZE);\n\t\t\tfor(let i = 0; i < this.nodeCount; i++) {\n\t\t\t\theads[i * NODE_SIZE + NODE_HEAD_OFFSET] = this.nullIndex;\n\t\t\t}\n\t\t\tstoreRawPointer(this.firstBlock.data, NODE_POINTER_INDEX, nodeBlock.pointer);\n\n\t\t\tlet poolBlock = this.firstBlock.getSubAllocation(SharedQuadtree.ALLOCATE_COUNT, poolAllocateCount);\n\t\t\tthis.pool = new SharedPool<CoordArray>(memory, { firstBlock: poolBlock, ...poolConfig });\n\t\t\tstoreRawPointer(this.firstBlock.data, POOL_POINTER_INDEX, poolBlock.pointer);\n\n\t\t\tlet mapBlock = this.firstBlock.getSubAllocation(SharedQuadtree.ALLOCATE_COUNT + poolAllocateCount, mapAllocateCount);\n\t\t\tthis.idMap = new SharedMap<number>(memory, { firstBlock: mapBlock, capacity: getSpatialMapCapacity(maxEntities, memory.maxAllocationLength) });\n\t\t\tstoreRawPointer(this.firstBlock.data, MAP_POINTER_INDEX, mapBlock.pointer);\n\t\t}\n\n\t\tlet boundsView = this.getBoundsView();\n\t\tthis.rootX = boundsView[0];\n\t\tthis.rootY = boundsView[1];\n\t\tthis.rootWidth = boundsView[2];\n\t\tthis.rootHeight = boundsView[3];\n\n\t\tlet nodeBlock = new AllocatedMemory(memory, getPointer(loadRawPointer(this.firstBlock.data, NODE_POINTER_INDEX), memory.positionBits));\n\t\tthis.nodeInts = new Int32Array(nodeBlock.data.buffer, nodeBlock.bufferByteOffset, this.nodeCount * NODE_SIZE);\n\t\tthis.nodeHeads = new Uint32Array(nodeBlock.data.buffer, nodeBlock.bufferByteOffset, this.nodeCount * NODE_SIZE);\n\t}\n\n\t// Total nodes in a complete quadtree of the given depth: sum of 4^level for level 0..maxLevels.\n\tstatic getNodeCount(maxLevels: number): number {\n\t\treturn (Math.pow(4, maxLevels + 1) - 1) / 3;\n\t}\n\n\tget pointer(): number {\n\t\treturn this.firstBlock.pointer;\n\t}\n\n\tget usedMemory(): number {\n\t\tlet nodeBlock = new AllocatedMemory(this.memory, getPointer(loadRawPointer(this.firstBlock.data, NODE_POINTER_INDEX), this.memory.positionBits));\n\t\treturn this.firstBlock.usedMemory + nodeBlock.usedMemory + this.pool.usedMemory + this.idMap.usedMemory;\n\t}\n\n\tinsert(id: number, x: number, y: number, width = 0, height = 0) {\n\t\tif(this.idMap.get(id) !== undefined) {\n\t\t\tthis.update(id, x, y, width, height);\n\t\t\treturn;\n\t\t}\n\n\t\tlet node = this.locate(x, y, width, height);\n\t\tlet record = this.insertScratch;\n\t\trecord[ITEM_ID] = id;\n\t\trecord[ITEM_X] = x;\n\t\trecord[ITEM_Y] = y;\n\t\trecord[ITEM_W] = width;\n\t\trecord[ITEM_H] = height;\n\t\trecord[ITEM_NODE] = node;\n\t\trecord[ITEM_NEXT] = this.nullIndex;\n\t\tlet index = this.pool.push(record);\n\t\tthis.linkIntoNode(node, index);\n\t\tthis.idMap.set(id, index);\n\t}\n\n\tbulkInsert(entities: Iterable<SpatialEntity>) {\n\t\tlet byId = new Map<number, SpatialEntity>();\n\t\tfor(let entity of entities) {\n\t\t\tbyId.set(entity.id, entity);\n\t\t}\n\t\tlet unique = Array.from(byId.values());\n\t\tlet existing = this.idMap.getAll(unique.map(entity => entity.id));\n\t\tlet mappings: Array<readonly [number, number]> = [];\n\t\tlet newCount = existing.reduce<number>((count, index) => count + (index === undefined ? 1 : 0), 0);\n\t\tlet nextIndex = this.pool.reserveContiguous(newCount);\n\t\tfor(let i = 0; i < unique.length; i++) {\n\t\t\tlet entity = unique[i];\n\t\t\tlet width = entity.width ?? 0;\n\t\t\tlet height = entity.height ?? 0;\n\t\t\tif(existing[i] !== undefined) {\n\t\t\t\tthis.update(entity.id, entity.x, entity.y, width, height);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet node = this.locate(entity.x, entity.y, width, height);\n\t\t\tlet index = nextIndex++;\n\t\t\tlet block = this.pool.blockFor(index);\n\t\t\tlet offset = this.pool.blockOffset(index);\n\t\t\tblock[offset + ITEM_ID] = entity.id;\n\t\t\tblock[offset + ITEM_X] = entity.x;\n\t\t\tblock[offset + ITEM_Y] = entity.y;\n\t\t\tblock[offset + ITEM_W] = width;\n\t\t\tblock[offset + ITEM_H] = height;\n\t\t\tblock[offset + ITEM_NODE] = node;\n\t\t\tblock[offset + ITEM_NEXT] = this.nullIndex;\n\t\t\tthis.linkIntoNode(node, index);\n\t\t\tmappings.push([entity.id, index]);\n\t\t}\n\t\tthis.idMap.setAll(mappings);\n\t}\n\n\t// Move an entity to a new position. Assumes a single writer per entity id (the standard shared-memory pattern - each\n\t// worker owns a disjoint set of entities), so this entity's item fields are stable until we lock its node(s).\n\tupdate(id: number, x: number, y: number, width = 0, height = 0) {\n\t\tlet index = this.idMap.get(id);\n\t\tif(index === undefined) {\n\t\t\tthis.insert(id, x, y, width, height);\n\t\t\treturn;\n\t\t}\n\n\t\tlet block = this.pool.blockFor(index);\n\t\tlet off = this.pool.blockOffset(index);\n\t\tlet oldNode = block[off + ITEM_NODE];\n\t\tlet newNode = this.locate(x, y, width, height);\n\n\t\tif(oldNode === newNode) {\n\t\t\t// Same cell: only the coordinates change, no relinking. Lock so a concurrent reader sees a consistent record.\n\t\t\tlock(this.nodeInts, oldNode * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\t\tblock[off + ITEM_X] = x;\n\t\t\tblock[off + ITEM_Y] = y;\n\t\t\tblock[off + ITEM_W] = width;\n\t\t\tblock[off + ITEM_H] = height;\n\t\t\tunlock(this.nodeInts, oldNode * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\t\treturn;\n\t\t}\n\n\t\t// Cross-cell move: hold both node locks, ordered by index to avoid deadlock with another thread moving the reverse way.\n\t\tlet first = Math.min(oldNode, newNode);\n\t\tlet second = Math.max(oldNode, newNode);\n\t\tlock(this.nodeInts, first * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\tlock(this.nodeInts, second * NODE_SIZE + NODE_LOCK_OFFSET);\n\n\t\tthis.unlinkNoLock(oldNode, index);\n\t\tblock[off + ITEM_X] = x;\n\t\tblock[off + ITEM_Y] = y;\n\t\tblock[off + ITEM_W] = width;\n\t\tblock[off + ITEM_H] = height;\n\t\tblock[off + ITEM_NODE] = newNode;\n\t\tthis.linkNoLock(newNode, index);\n\n\t\tunlock(this.nodeInts, second * NODE_SIZE + NODE_LOCK_OFFSET);\n\t\tunlock(this.nodeInts, first * NODE_SIZE + NODE_LOCK_OFFSET);\n\t}\n\n\tremove(id: number): boolean {\n\t\tlet index = this.idMap.get(id);\n\t\tif(index === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tlet node = this.pool.get(index, ITEM_NODE);\n\t\tthis.unlinkFromNode(node, index);\n\t\tthis.pool.deleteIndex(index);\n\t\tthis.idMap.delete(id);\n\t\treturn true;\n\t}\n\n\thas(id: number): boolean {\n\t\treturn this.idMap.get(id) !== undefined;\n\t}\n\n\t// Broad-phase query: ids of every entity in a node whose region intersects the given rect. Result is a superset of true\n\t// overlaps (the caller does the narrow-phase check), matching quadtree-js retrieve.\n\tsearch(x: number, y: number, width: number, height: number, filter?: (id: number) => boolean): Array<number> {\n\t\tlet out: Array<number> = [];\n\t\tthis.searchInto(out, x, y, width, height, filter);\n\t\treturn out;\n\t}\n\t// Same as search but appends into a caller-owned array so hot loops can reuse it. Returns the array.\n\tsearchInto(out: Array<number>, x: number, y: number, width: number, height: number, filter?: (id: number) => boolean): Array<number> {\n\t\tlet start = out.length;\n\t\tthis.collect(out, 0, this.rootX, this.rootY, this.rootWidth, this.rootHeight, 0, x, y, width, height);\n\t\tif(filter !== undefined) {\n\t\t\tlet write = start;\n\t\t\tfor(let read = start; read < out.length; read++) {\n\t\t\t\tlet id = out[read];\n\t\t\t\tif(filter(id)) {\n\t\t\t\t\tout[write++] = id;\n\t\t\t\t}\n\t\t\t}\n\t\t\tout.length = write;\n\t\t}\n\t\treturn out;\n\t}\n\n\tneighbors(x: number, y: number, maxResults: number, maxDistance: number, filter?: (id: number) => boolean): Array<number> {\n\t\tif(maxResults <= 0 || maxDistance < 0 || Number.isNaN(maxResults) || Number.isNaN(maxDistance)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tinterface Node {\n\t\t\tindex: number\n\t\t\tx: number\n\t\t\ty: number\n\t\t\twidth: number\n\t\t\theight: number\n\t\t\tlevel: number\n\t\t}\n\t\tmaxResults = Math.floor(maxResults);\n\t\tif(maxResults === 0) {\n\t\t\treturn [];\n\t\t}\n\t\tlet maxDistanceSquared = maxDistance * maxDistance;\n\t\tif(maxResults === 1) {\n\t\t\treturn this.nearestNeighbor(x, y, maxDistanceSquared, filter);\n\t\t}\n\t\tlet candidates: Array<NeighborCandidate> = [];\n\t\tlet nodeCandidates: Array<NeighborCandidate> = [];\n\t\tlet queue = new MinPriorityQueue<Node>();\n\t\tlet root = { index: 0, x: this.rootX, y: this.rootY, width: this.rootWidth, height: this.rootHeight, level: 0 };\n\t\tqueue.push(root, distanceSquaredToRect(x, y, this.rootX, this.rootY, this.rootX + this.rootWidth, this.rootY + this.rootHeight));\n\n\t\twhile(queue.length > 0 && queue.priority <= candidateLimit(candidates, maxResults, maxDistanceSquared)) {\n\t\t\tlet node = queue.pop();\n\t\t\tif(node === undefined) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tnodeCandidates.length = 0;\n\t\t\tthis.collectNeighborNode(nodeCandidates, node.index, x, y, maxDistanceSquared);\n\t\t\tfor(let candidate of nodeCandidates) {\n\t\t\t\tlet duplicate = false;\n\t\t\t\tfor(let existing of candidates) {\n\t\t\t\t\tif(existing.id === candidate.id) {\n\t\t\t\t\t\tduplicate = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif(duplicate) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif(filter === undefined || filter(candidate.id)) {\n\t\t\t\t\taddCandidate(candidates, candidate.id, candidate.distance, maxResults);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(node.level >= this.maxLevels) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet halfWidth = node.width / 2;\n\t\t\tlet halfHeight = node.height / 2;\n\t\t\tlet childLevel = node.level + 1;\n\t\t\tlet children: Array<Node> = [\n\t\t\t\t{ index: node.index * 4 + 1, x: node.x, y: node.y, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t\t{ index: node.index * 4 + 2, x: node.x + halfWidth, y: node.y, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t\t{ index: node.index * 4 + 3, x: node.x, y: node.y + halfHeight, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t\t{ index: node.index * 4 + 4, x: node.x + halfWidth, y: node.y + halfHeight, width: halfWidth, height: halfHeight, level: childLevel },\n\t\t\t];\n\t\t\tfor(let child of children) {\n\t\t\t\tlet distance = distanceSquaredToRect(x, y, child.x, child.y, child.x + child.width, child.y + child.height);\n\t\t\t\tif(distance <= candidateLimit(candidates, maxResults, maxDistanceSquared)) {\n\t\t\t\t\tqueue.push(child, distance);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn candidates.map(candidate => candidate.id);\n\t}\n\n\tprivate nearestNeighbor(\n\t\tx: number, y: number, maxDistanceSquared: number, filter: ((id: number) => boolean) | undefined,\n\t): Array<number> {\n\t\tlet nearest: NearestNeighbor = { id: undefined, distance: maxDistanceSquared };\n\t\tlet nodeCandidates: Array<NeighborCandidate> = [];\n\t\tthis.findNearest(\n\t\t\t0, this.rootX, this.rootY, this.rootWidth, this.rootHeight, 0,\n\t\t\tx, y, nearest, nodeCandidates, filter,\n\t\t);\n\t\treturn nearest.id === undefined ? [] : [nearest.id];\n\t}\n\n\tprivate findNearest(\n\t\tnode: number, nodeX: number, nodeY: number, width: number, height: number, level: number,\n\t\tx: number, y: number, nearest: NearestNeighbor,\n\t\tnodeCandidates: Array<NeighborCandidate>, filter: ((id: number) => boolean) | undefined,\n\t) {\n\t\tif(distanceSquaredToRect(x, y, nodeX, nodeY, nodeX + width, nodeY + height) > nearest.distance) {\n\t\t\treturn;\n\t\t}\n\t\tif(filter === undefined) {\n\t\t\tthis.collectNearestNode(nearest, node, x, y);\n\t\t} else {\n\t\t\tnodeCandidates.length = 0;\n\t\t\tthis.collectNeighborNode(nodeCandidates, node, x, y, nearest.distance);\n\t\t\tfor(let candidate of nodeCandidates) {\n\t\t\t\tif(filter(candidate.id)\n\t\t\t\t\t&& (candidate.distance < nearest.distance\n\t\t\t\t\t\t|| (candidate.distance === nearest.distance && (nearest.id === undefined || candidate.id < nearest.id)))) {\n\t\t\t\t\tnearest.id = candidate.id;\n\t\t\t\t\tnearest.distance = candidate.distance;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(level >= this.maxLevels) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet halfWidth = width / 2;\n\t\tlet halfHeight = height / 2;\n\t\tlet midX = nodeX + halfWidth;\n\t\tlet midY = nodeY + halfHeight;\n\t\tlet base = node * 4;\n\t\tlet nextLevel = level + 1;\n\t\tlet east = x >= midX;\n\t\tlet south = y >= midY;\n\t\tlet visit = (index: number, childX: number, childY: number) => {\n\t\t\tthis.findNearest(\n\t\t\t\tindex, childX, childY, halfWidth, halfHeight, nextLevel,\n\t\t\t\tx, y, nearest, nodeCandidates, filter,\n\t\t\t);\n\t\t};\n\t\tif(south) {\n\t\t\tif(east) {\n\t\t\t\tvisit(base + 4, midX, midY);\n\t\t\t\tvisit(base + 3, nodeX, midY);\n\t\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\t} else {\n\t\t\t\tvisit(base + 3, nodeX, midY);\n\t\t\t\tvisit(base + 4, midX, midY);\n\t\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\t}\n\t\t} else if(east) {\n\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\tvisit(base + 4, midX, midY);\n\t\t\tvisit(base + 3, nodeX, midY);\n\t\t} else {\n\t\t\tvisit(base + 1, nodeX, nodeY);\n\t\t\tvisit(base + 2, midX, nodeY);\n\t\t\tvisit(base + 3, nodeX, midY);\n\t\t\tvisit(base + 4, midX, midY);\n\t\t}\n\t}\n\n\tclear() {\n\t\tfor(let i = 0; i < this.nodeCount; i++) {\n\t\t\tthis.nodeHeads[i * NODE_SIZE + NODE_HEAD_OFFSET] = this.nullIndex;\n\t\t}\n\t\tthis.pool.clear();\n\t\t// SharedMap has no clear(); drop every key. Not safe to run concurrently with writers (documented on clear()).\n\t\tlet keys: Array<number> = [];\n\t\tfor(let [key] of this.idMap) {\n\t\t\tkeys.push(key);\n\t\t}\n\t\tfor(let key of keys) {\n\t\t\tthis.idMap.delete(key);\n\t\t}\n\t}\n\n\tfree() {\n\t\tlet nodeBlock = new AllocatedMemory(this.memory, getPointer(loadRawPointer(this.firstBlock.data, NODE_POINTER_INDEX), this.memory.positionBits));\n\t\tnodeBlock.free();\n\t\tthis.pool.free();\n\t\tthis.idMap.free();\n\t\tthis.firstBlock.free();\n\t}\n\n\tgetSharedMemory(): SharedQuadtreeMemory {\n\t\treturn {\n\t\t\tfirstBlock: this.firstBlock.getSharedMemory(),\n\t\t};\n\t}\n\n\tprivate getBoundsView(): CoordArray {\n\t\treturn makeArrayView(\n\t\t\tthis.coordType,\n\t\t\tthis.firstBlock.data.buffer,\n\t\t\tthis.firstBlock.bufferByteOffset + BOUNDS_INDEX * Uint32Array.BYTES_PER_ELEMENT,\n\t\t\t4,\n\t\t) as CoordArray;\n\t}\n\n\t// Deepest node index that fully contains the rect. Descends into the one child that still fully contains it; stops at a\n\t// straddle or at max depth.\n\tprivate locate(x: number, y: number, width: number, height: number): number {\n\t\tlet node = 0;\n\t\tlet nx = this.rootX;\n\t\tlet ny = this.rootY;\n\t\tlet nw = this.rootWidth;\n\t\tlet nh = this.rootHeight;\n\n\t\tfor(let level = 0; level < this.maxLevels; level++) {\n\t\t\tlet midX = nx + nw / 2;\n\t\t\tlet midY = ny + nh / 2;\n\t\t\tlet west = x >= nx && x + width <= midX && (width > 0 || x < midX);\n\t\t\tlet east = x >= midX && x + width <= nx + nw;\n\t\t\tlet north = y >= ny && y + height <= midY && (height > 0 || y < midY);\n\t\t\tlet south = y >= midY && y + height <= ny + nh;\n\n\t\t\tif(north && west) {\n\t\t\t\tnode = node * 4 + 1;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else if(north && east) {\n\t\t\t\tnode = node * 4 + 2;\n\t\t\t\tnx = midX;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else if(south && west) {\n\t\t\t\tnode = node * 4 + 3;\n\t\t\t\tny = midY;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else if(south && east) {\n\t\t\t\tnode = node * 4 + 4;\n\t\t\t\tnx = midX;\n\t\t\t\tny = midY;\n\t\t\t\tnw /= 2;\n\t\t\t\tnh /= 2;\n\t\t\t} else {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn node;\n\t}\n\n\tprivate collect(out: Array<number>, node: number, nx: number, ny: number, nw: number, nh: number, level: number, qx: number, qy: number, qw: number, qh: number) {\n\t\t// Peek the head unlocked: an empty bucket has nothing to read, so the lock (and its atomics) is pure overhead. Most\n\t\t// nodes in a fixed-depth tree are empty, so skipping them dominates query cost. Taking the lock only to walk a\n\t\t// non-empty bucket preserves the snapshot guarantee - a concurrent insert we race is simply not in this snapshot.\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tif(this.nodeHeads[headIndex] !== this.nullIndex) {\n\t\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\t\tlock(this.nodeInts, lockIndex);\n\t\t\tlet index = this.nodeHeads[headIndex];\n\t\t\tlet pool = this.pool;\n\t\t\twhile(index !== this.nullIndex) {\n\t\t\t\t// One chunk resolve per item covers both fields it reads\n\t\t\t\tlet block = pool.blockFor(index);\n\t\t\t\tlet off = pool.blockOffset(index);\n\t\t\t\tout.push(block[off + ITEM_ID]);\n\t\t\t\tindex = block[off + ITEM_NEXT];\n\t\t\t}\n\t\t\tunlock(this.nodeInts, lockIndex);\n\t\t}\n\n\t\tif(level >= this.maxLevels) {\n\t\t\treturn;\n\t\t}\n\n\t\tlet midX = nx + nw / 2;\n\t\tlet midY = ny + nh / 2;\n\t\tlet hw = nw / 2;\n\t\tlet hh = nh / 2;\n\t\tlet overlapsWest = qx < midX;\n\t\tlet overlapsEast = qx + qw > midX;\n\t\tlet overlapsNorth = qy < midY;\n\t\tlet overlapsSouth = qy + qh > midY;\n\n\t\tif(overlapsNorth && overlapsWest) {\n\t\t\tthis.collect(out, node * 4 + 1, nx, ny, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t\tif(overlapsNorth && overlapsEast) {\n\t\t\tthis.collect(out, node * 4 + 2, midX, ny, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t\tif(overlapsSouth && overlapsWest) {\n\t\t\tthis.collect(out, node * 4 + 3, nx, midY, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t\tif(overlapsSouth && overlapsEast) {\n\t\t\tthis.collect(out, node * 4 + 4, midX, midY, hw, hh, level + 1, qx, qy, qw, qh);\n\t\t}\n\t}\n\n\tprivate collectNeighborNode(\n\t\tout: Array<NeighborCandidate>, node: number, x: number, y: number, maxDistanceSquared: number,\n\t) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tif(this.nodeHeads[headIndex] === this.nullIndex) {\n\t\t\treturn;\n\t\t}\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tlet index = this.nodeHeads[headIndex];\n\t\twhile(index !== this.nullIndex) {\n\t\t\tlet block = this.pool.blockFor(index);\n\t\t\tlet off = this.pool.blockOffset(index);\n\t\t\tlet id = block[off + ITEM_ID];\n\t\t\tlet distance = distanceSquaredToRect(x, y, block[off + ITEM_X], block[off + ITEM_Y], block[off + ITEM_X] + block[off + ITEM_W], block[off + ITEM_Y] + block[off + ITEM_H]);\n\t\t\tif(distance <= maxDistanceSquared) {\n\t\t\t\tout.push({ id, distance });\n\t\t\t}\n\t\t\tindex = block[off + ITEM_NEXT];\n\t\t}\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\n\tprivate collectNearestNode(nearest: NearestNeighbor, node: number, x: number, y: number) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tif(this.nodeHeads[headIndex] === this.nullIndex) {\n\t\t\treturn;\n\t\t}\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tlet index = this.nodeHeads[headIndex];\n\t\twhile(index !== this.nullIndex) {\n\t\t\tlet block = this.pool.blockFor(index);\n\t\t\tlet off = this.pool.blockOffset(index);\n\t\t\tlet id = block[off + ITEM_ID];\n\t\t\tlet distance = distanceSquaredToRect(\n\t\t\t\tx, y, block[off + ITEM_X], block[off + ITEM_Y],\n\t\t\t\tblock[off + ITEM_X] + block[off + ITEM_W], block[off + ITEM_Y] + block[off + ITEM_H],\n\t\t\t);\n\t\t\tif(distance < nearest.distance\n\t\t\t\t|| (distance === nearest.distance && (nearest.id === undefined || id < nearest.id))) {\n\t\t\t\tnearest.id = id;\n\t\t\t\tnearest.distance = distance;\n\t\t\t}\n\t\t\tindex = block[off + ITEM_NEXT];\n\t\t}\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\n\tprivate linkIntoNode(node: number, index: number) {\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tthis.linkNoLock(node, index);\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\t// Push the item onto the node's bucket head. Caller holds the node lock.\n\tprivate linkNoLock(node: number, index: number) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tthis.pool.set(index, ITEM_NEXT, this.nodeHeads[headIndex]);\n\t\tthis.nodeHeads[headIndex] = index;\n\t}\n\n\tprivate unlinkFromNode(node: number, index: number) {\n\t\tlet lockIndex = node * NODE_SIZE + NODE_LOCK_OFFSET;\n\t\tlock(this.nodeInts, lockIndex);\n\t\tthis.unlinkNoLock(node, index);\n\t\tunlock(this.nodeInts, lockIndex);\n\t}\n\t// Splice the item out of the node's bucket. Caller holds the node lock.\n\tprivate unlinkNoLock(node: number, index: number) {\n\t\tlet headIndex = node * NODE_SIZE + NODE_HEAD_OFFSET;\n\t\tlet head = this.nodeHeads[headIndex];\n\t\tlet next = this.pool.get(index, ITEM_NEXT);\n\t\tif(head === index) {\n\t\t\tthis.nodeHeads[headIndex] = next;\n\t\t\treturn;\n\t\t}\n\n\t\tlet prev = head;\n\t\twhile(prev !== this.nullIndex) {\n\t\t\tlet prevNext = this.pool.get(prev, ITEM_NEXT);\n\t\t\tif(prevNext === index) {\n\t\t\t\tthis.pool.set(prev, ITEM_NEXT, next);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tprev = prevNext;\n\t\t}\n\t}\n}\n\nfunction getCoordTypeCode(type: CoordArrayConstructor | undefined): number {\n\tlet code = getArrayTypeCode(type ?? DEFAULT_COORD_TYPE);\n\tif(code !== ARRAY_TYPE.float32 && code !== ARRAY_TYPE.float64) {\n\t\tthrow new Error('SharedQuadtree must be Float32Array or Float64Array');\n\t}\n\treturn code;\n}\nfunction getCoordTypeConstructor(typeCode: number): CoordArrayConstructor {\n\treturn getByteMultipler(typeCode) === 2 ? Float64Array : Float32Array;\n}\nfunction nullIndexFor(typeCode: number): number {\n\treturn typeCode === ARRAY_TYPE.float32 ? FLOAT32_NULL_INDEX : FLOAT64_NULL_INDEX;\n}\n\ninterface QuadtreeBounds {\n\tx: number\n\ty: number\n\twidth: number\n\theight: number\n}\ninterface SharedQuadtreeConfig {\n\tbounds: QuadtreeBounds\n\tmaxLevels?: number\n\tmaxEntities?: number\n\ttype?: CoordArrayConstructor\n}\ninterface SharedQuadtreeMemory {\n\tfirstBlock: SharedAllocatedMemory\n}\n\nexport type { SharedQuadtreeConfig, SharedQuadtreeMemory, QuadtreeBounds, SpatialEntity };\n"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
- import { getPointer as e, loadRawPointer as t, storeRawPointer as n } from "../utils/pointer.js";
2
- import r from "../allocated-memory.js";
3
- import { ARRAY_TYPE as i, getArrayTypeCode as a, getByteMultipler as o, makeArrayView as s } from "../utils/array-type.js";
4
- import { lock as c, unlock as l } from "../lock/simple-lock.js";
5
- import u from "../shared-map.js";
6
- import d from "../shared-pool.js";
1
+ import e from "../allocated-memory.js";
2
+ import t from "../shared-pool.js";
3
+ import n from "../shared-map.js";
4
+ import { lock as r, unlock as i } from "../lock/simple-lock.js";
5
+ import { getPointer as a, loadRawPointer as o, storeRawPointer as s } from "../utils/pointer.js";
6
+ import { ARRAY_TYPE as c, getArrayTypeCode as l, getByteMultipler as u, makeArrayView as d } from "../utils/array-type.js";
7
7
  import { MinPriorityQueue as f, addCandidate as p, candidateLimit as m, distanceSquaredToRect as h } from "./spatial-neighbors.js";
8
8
  import { getSpatialMapCapacity as g, getSpatialPoolChunkSize as _ } from "./spatial-entity.js";
9
- //#region src/spatial/shared-spatial-grid.ts
10
- var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1, k = 2, A = 0, j = 1, M = 2, N = 3, P = 4, F = 0, I = 1, L = 2, R = 3, z = 4, B = 5, V = 6, H = 7, U = 8, W = 16777216, G = W, K = 4294967295, q = 50, J = 1e6, Y = 4, X = Float32Array, Z = class a {
9
+ // src/spatial/shared-spatial-grid.ts
10
+ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1, k = 2, A = 0, j = 1, M = 2, N = 3, P = 4, F = 0, I = 1, L = 2, R = 3, z = 4, B = 5, V = 6, H = 7, U = 8, W = 16777216, G = W, K = 4294967295, q = 50, J = 1e6, Y = 4, X = Float32Array, Z = class l {
11
11
  static ALLOCATE_COUNT = 18;
12
12
  memory;
13
13
  firstBlock;
@@ -65,60 +65,60 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
65
65
  get type() {
66
66
  return this.coordType;
67
67
  }
68
- constructor(s, c) {
69
- if (this.memory = s, c && "firstBlock" in c) this.firstBlock = new r(s, c.firstBlock), this.coordType = this.firstBlock.data[T], this.entityPool = new d(s, { firstBlock: e(t(this.firstBlock.data, y), s.positionBits) }), this.slotPool = new d(s, { firstBlock: e(t(this.firstBlock.data, b), s.positionBits) }), this.idMap = new u(s, { firstBlock: e(t(this.firstBlock.data, x), s.positionBits) }), this.cols = this.firstBlock.data[S], this.rows = this.firstBlock.data[C], this.cellCount = this.firstBlock.data[w], this.nullIndex = $(this.coordType);
68
+ constructor(r, i) {
69
+ if (this.memory = r, i && "firstBlock" in i) this.firstBlock = new e(r, i.firstBlock), this.coordType = this.firstBlock.data[T], this.entityPool = new t(r, { firstBlock: a(o(this.firstBlock.data, y), r.positionBits) }), this.slotPool = new t(r, { firstBlock: a(o(this.firstBlock.data, b), r.positionBits) }), this.idMap = new n(r, { firstBlock: a(o(this.firstBlock.data, x), r.positionBits) }), this.cols = this.firstBlock.data[S], this.rows = this.firstBlock.data[C], this.cellCount = this.firstBlock.data[w], this.nullIndex = $(this.coordType);
70
70
  else {
71
- let e = c?.bounds ?? {
71
+ let e = i?.bounds ?? {
72
72
  x: 0,
73
73
  y: 0,
74
74
  width: 0,
75
75
  height: 0
76
- }, t = c?.gridSize ?? q, r = c?.maxEntities ?? J, l = c?.maxSlots ?? r * Y;
77
- if (this.coordType = ee(c?.type), this.nullIndex = $(this.coordType), this.cols = Math.max(1, Math.ceil(e.width / t)), this.rows = Math.max(1, Math.ceil(e.height / t)), this.cellCount = this.cols * this.rows, this.coordType === i.float32 && (r > W || l > W)) throw Error(`Float32 SharedSpatialGrid supports at most ${W} entities and slots; pass type: Float64Array for more`);
76
+ }, a = i?.gridSize ?? q, o = i?.maxEntities ?? J, d = i?.maxSlots ?? o * Y;
77
+ if (this.coordType = ee(i?.type), this.nullIndex = $(this.coordType), this.cols = Math.max(1, Math.ceil(e.width / a)), this.rows = Math.max(1, Math.ceil(e.height / a)), this.cellCount = this.cols * this.rows, this.coordType === c.float32 && (o > W || d > W)) throw Error(`Float32 SharedSpatialGrid supports at most ${W} entities and slots; pass type: Float64Array for more`);
78
78
  let f = {
79
79
  type: Q(this.coordType),
80
80
  dataLength: U,
81
- maxLength: r,
82
- maxChunkSize: _(r, U, o(this.coordType), s.maxAllocationLength)
81
+ maxLength: o,
82
+ maxChunkSize: _(o, U, u(this.coordType), r.maxAllocationLength)
83
83
  }, p = {
84
84
  type: Q(this.coordType),
85
85
  dataLength: P,
86
- maxLength: l,
87
- maxChunkSize: _(l, P, o(this.coordType), s.maxAllocationLength)
88
- }, m = d.getAllocateCount(s, f), h = d.getAllocateCount(s, p), E = u.ALLOCATE_COUNT;
89
- this.firstBlock = s.allocUI32(a.ALLOCATE_COUNT + m + h + E), this.firstBlock.data[S] = this.cols, this.firstBlock.data[C] = this.rows, this.firstBlock.data[w] = this.cellCount, this.firstBlock.data[T] = this.coordType;
86
+ maxLength: d,
87
+ maxChunkSize: _(d, P, u(this.coordType), r.maxAllocationLength)
88
+ }, m = t.getAllocateCount(r, f), h = t.getAllocateCount(r, p), E = n.ALLOCATE_COUNT;
89
+ this.firstBlock = r.allocUI32(l.ALLOCATE_COUNT + m + h + E), this.firstBlock.data[S] = this.cols, this.firstBlock.data[C] = this.rows, this.firstBlock.data[w] = this.cellCount, this.firstBlock.data[T] = this.coordType;
90
90
  let D = this.getBoundsView();
91
- D[0] = e.x, D[1] = e.y, D[2] = e.width, D[3] = e.height, D[4] = t;
92
- let A = s.allocUI32(this.cellCount * k), j = new Uint32Array(A.data.buffer, A.bufferByteOffset, this.cellCount * k);
91
+ D[0] = e.x, D[1] = e.y, D[2] = e.width, D[3] = e.height, D[4] = a;
92
+ let A = r.allocUI32(this.cellCount * k), j = new Uint32Array(A.data.buffer, A.bufferByteOffset, this.cellCount * k);
93
93
  for (let e = 0; e < this.cellCount; e++) j[e * k + O] = this.nullIndex;
94
- n(this.firstBlock.data, v, A.pointer);
95
- let M = this.firstBlock.getSubAllocation(a.ALLOCATE_COUNT, m);
96
- this.entityPool = new d(s, {
94
+ s(this.firstBlock.data, v, A.pointer);
95
+ let M = this.firstBlock.getSubAllocation(l.ALLOCATE_COUNT, m);
96
+ this.entityPool = new t(r, {
97
97
  firstBlock: M,
98
98
  ...f
99
- }), n(this.firstBlock.data, y, M.pointer);
100
- let N = this.firstBlock.getSubAllocation(a.ALLOCATE_COUNT + m, h);
101
- this.slotPool = new d(s, {
99
+ }), s(this.firstBlock.data, y, M.pointer);
100
+ let N = this.firstBlock.getSubAllocation(l.ALLOCATE_COUNT + m, h);
101
+ this.slotPool = new t(r, {
102
102
  firstBlock: N,
103
103
  ...p
104
- }), n(this.firstBlock.data, b, N.pointer);
105
- let F = this.firstBlock.getSubAllocation(a.ALLOCATE_COUNT + m + h, E);
106
- this.idMap = new u(s, {
104
+ }), s(this.firstBlock.data, b, N.pointer);
105
+ let F = this.firstBlock.getSubAllocation(l.ALLOCATE_COUNT + m + h, E);
106
+ this.idMap = new n(r, {
107
107
  firstBlock: F,
108
- capacity: g(r, s.maxAllocationLength)
109
- }), n(this.firstBlock.data, x, F.pointer);
108
+ capacity: g(o, r.maxAllocationLength)
109
+ }), s(this.firstBlock.data, x, F.pointer);
110
110
  }
111
- let l = this.getBoundsView();
112
- this.originX = l[0], this.originY = l[1], this.rootWidth = l[2], this.rootHeight = l[3], this.cellSize = l[4];
113
- let f = new r(s, e(t(this.firstBlock.data, v), s.positionBits));
111
+ let d = this.getBoundsView();
112
+ this.originX = d[0], this.originY = d[1], this.rootWidth = d[2], this.rootHeight = d[3], this.cellSize = d[4];
113
+ let f = new e(r, a(o(this.firstBlock.data, v), r.positionBits));
114
114
  this.cellInts = new Int32Array(f.data.buffer, f.bufferByteOffset, this.cellCount * k), this.cellHeads = new Uint32Array(f.data.buffer, f.bufferByteOffset, this.cellCount * k);
115
115
  }
116
116
  get pointer() {
117
117
  return this.firstBlock.pointer;
118
118
  }
119
119
  get usedMemory() {
120
- let n = new r(this.memory, e(t(this.firstBlock.data, v), this.memory.positionBits));
121
- return this.firstBlock.usedMemory + n.usedMemory + this.entityPool.usedMemory + this.slotPool.usedMemory + this.idMap.usedMemory;
120
+ let t = new e(this.memory, a(o(this.firstBlock.data, v), this.memory.positionBits));
121
+ return this.firstBlock.usedMemory + t.usedMemory + this.entityPool.usedMemory + this.slotPool.usedMemory + this.idMap.usedMemory;
122
122
  }
123
123
  insert(e, t, n, r = 0, i = 0) {
124
124
  if (this.idMap.get(e) !== void 0) {
@@ -161,11 +161,7 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
161
161
  return;
162
162
  }
163
163
  let o = this.entityPool.blockFor(a), s = this.entityPool.blockOffset(a), c = o[s + F], l = o[s + I], u = o[s + L], d = o[s + R], f = this.colOf(t), p = this.rowOf(n), m = this.colOf(t + r), h = this.rowOf(n + i);
164
- if (f === c && p === l && m === u && h === d) {
165
- o[s + z] = t, o[s + B] = n, o[s + V] = r, o[s + H] = i;
166
- return;
167
- }
168
- this.relinkRange(e, f, p, m, h, c, l, u, d), o[s + F] = f, o[s + I] = p, o[s + L] = m, o[s + R] = h, o[s + z] = t, o[s + B] = n, o[s + V] = r, o[s + H] = i;
164
+ f === c && p === l && m === u && h === d ? (o[s + z] = t, o[s + B] = n, o[s + V] = r, o[s + H] = i) : (this.relinkRange(e, f, p, m, h, c, l, u, d), o[s + F] = f, o[s + I] = p, o[s + L] = m, o[s + R] = h, o[s + z] = t, o[s + B] = n, o[s + V] = r, o[s + H] = i);
169
165
  }
170
166
  remove(e) {
171
167
  let t = this.idMap.get(e);
@@ -208,17 +204,16 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
208
204
  distance: a
209
205
  }, u = (n, r) => {
210
206
  let a = r * this.cols + n;
211
- if (i === void 0) {
212
- this.collectNearestCell(l, a, e, t);
213
- return;
214
- }
215
- o.length = 0, this.collectNeighborCell(o, a);
216
- for (let n of o) {
217
- if (!i(n)) continue;
218
- let r = this.idMap.get(n);
219
- if (r !== void 0) {
220
- let i = this.entityPool.blockFor(r), a = this.entityPool.blockOffset(r), o = i[a + z], s = i[a + B], c = h(e, t, o, s, o + i[a + V], s + i[a + H]);
221
- (c < l.distance || c === l.distance && (l.id === void 0 || n < l.id)) && (l.id = n, l.distance = c);
207
+ if (i === void 0) this.collectNearestCell(l, a, e, t);
208
+ else {
209
+ o.length = 0, this.collectNeighborCell(o, a);
210
+ for (let n of o) {
211
+ if (!i(n)) continue;
212
+ let r = this.idMap.get(n);
213
+ if (r !== void 0) {
214
+ let i = this.entityPool.blockFor(r), a = this.entityPool.blockOffset(r), o = i[a + z], s = i[a + B], c = h(e, t, o, s, o + i[a + V], s + i[a + H]);
215
+ (c < l.distance || c === l.distance && (l.id === void 0 || n < l.id)) && (l.id = n, l.distance = c);
216
+ }
222
217
  }
223
218
  }
224
219
  }, d = Math.max(s, this.cols - 1 - s, c, this.rows - 1 - c);
@@ -269,13 +264,13 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
269
264
  for (let t of e) this.idMap.delete(t);
270
265
  }
271
266
  free() {
272
- new r(this.memory, e(t(this.firstBlock.data, v), this.memory.positionBits)).free(), this.entityPool.free(), this.slotPool.free(), this.idMap.free(), this.firstBlock.free();
267
+ new e(this.memory, a(o(this.firstBlock.data, v), this.memory.positionBits)).free(), this.entityPool.free(), this.slotPool.free(), this.idMap.free(), this.firstBlock.free();
273
268
  }
274
269
  getSharedMemory() {
275
270
  return { firstBlock: this.firstBlock.getSharedMemory() };
276
271
  }
277
272
  getBoundsView() {
278
- return s(this.coordType, this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + E * Uint32Array.BYTES_PER_ELEMENT, 5);
273
+ return d(this.coordType, this.firstBlock.data.buffer, this.firstBlock.bufferByteOffset + E * Uint32Array.BYTES_PER_ELEMENT, 5);
279
274
  }
280
275
  colOf(e) {
281
276
  let t = Math.floor((e - this.originX) / this.cellSize);
@@ -303,8 +298,8 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
303
298
  }
304
299
  }
305
300
  linkIntoCell(e, t) {
306
- let n = this.slotPool, r = this.cellInts, i = this.cellHeads, a = n.push(t), o = e * k + D, s = e * k + O;
307
- c(r, o), n.set(a, N, i[s]), i[s] = a, l(r, o);
301
+ let n = this.slotPool, a = this.cellInts, o = this.cellHeads, s = n.push(t), c = e * k + D, l = e * k + O;
302
+ r(a, c), n.set(s, N, o[l]), o[l] = s, i(a, c);
308
303
  }
309
304
  relinkRange(e, t, n, r, i, a, o, s, c) {
310
305
  let l = t > a ? t : a, u = r < s ? r : s, d = n > o ? n : o, f = i < c ? i : c, p = l <= u && d <= f, m = this.slotScratch;
@@ -327,19 +322,19 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
327
322
  }
328
323
  }
329
324
  }
330
- refreshAnchorInCell(e, t, n, r) {
331
- let i = this.nullIndex, a = this.cellInts, o = e * k + D;
332
- c(a, o);
333
- let s = this.slotPool, u = this.cellHeads[e * k + O];
334
- for (; u !== i;) {
335
- let e = s.blockFor(u), i = s.blockOffset(u);
336
- if (e[i + A] === t) {
337
- e[i + j] = n, e[i + M] = r;
325
+ refreshAnchorInCell(e, t, n, a) {
326
+ let o = this.nullIndex, s = this.cellInts, c = e * k + D;
327
+ r(s, c);
328
+ let l = this.slotPool, u = this.cellHeads[e * k + O];
329
+ for (; u !== o;) {
330
+ let e = l.blockFor(u), r = l.blockOffset(u);
331
+ if (e[r + A] === t) {
332
+ e[r + j] = n, e[r + M] = a;
338
333
  break;
339
334
  }
340
- u = e[i + N];
335
+ u = e[r + N];
341
336
  }
342
- l(a, o);
337
+ i(s, c);
343
338
  }
344
339
  unlinkRange(e, t, n, r, i) {
345
340
  let a = this.cols, o = this.nullIndex, s = this.slotPool;
@@ -351,76 +346,75 @@ var v = 0, y = 1, b = 2, x = 3, S = 4, C = 5, w = 6, T = 7, E = 8, D = 0, O = 1,
351
346
  }
352
347
  }
353
348
  }
354
- collectCell(e, t, n, r, i, a) {
355
- let o = this.nullIndex, s = this.cellInts, u = t * k + O, d = t * k + D;
356
- c(s, d);
349
+ collectCell(e, t, n, a, o, s) {
350
+ let c = this.nullIndex, l = this.cellInts, u = t * k + O, d = t * k + D;
351
+ r(l, d);
357
352
  let f = this.cellHeads[u], p = this.slotPool;
358
- for (; f !== o;) {
359
- let t = p.blockFor(f), o = p.blockOffset(f), s = t[o + j], c = t[o + M];
360
- n === (s > i ? s : i) && r === (c > a ? c : a) && e.push(t[o + A]), f = t[o + N];
353
+ for (; f !== c;) {
354
+ let t = p.blockFor(f), r = p.blockOffset(f), i = t[r + j], c = t[r + M];
355
+ n === (i > o ? i : o) && a === (c > s ? c : s) && e.push(t[r + A]), f = t[r + N];
361
356
  }
362
- l(s, d);
357
+ i(l, d);
363
358
  }
364
- linkReservedCell(e, t, n, r, i) {
365
- let a = this.slotPool, o = a.blockFor(t), s = a.blockOffset(t);
366
- o[s + A] = n, o[s + j] = r, o[s + M] = i;
359
+ linkReservedCell(e, t, n, a, o) {
360
+ let s = this.slotPool, c = s.blockFor(t), l = s.blockOffset(t);
361
+ c[l + A] = n, c[l + j] = a, c[l + M] = o;
367
362
  let u = e * k + D;
368
- c(this.cellInts, u);
363
+ r(this.cellInts, u);
369
364
  let d = e * k + O;
370
- o[s + N] = this.cellHeads[d], this.cellHeads[d] = t, l(this.cellInts, u);
365
+ c[l + N] = this.cellHeads[d], this.cellHeads[d] = t, i(this.cellInts, u);
371
366
  }
372
367
  collectNeighborCell(e, t) {
373
368
  let n = t * k + O;
374
369
  if (this.cellHeads[n] === this.nullIndex) return;
375
- let r = t * k + D;
376
- c(this.cellInts, r);
377
- let i = this.cellHeads[n];
378
- for (; i !== this.nullIndex;) {
379
- let t = this.slotPool.blockFor(i), n = this.slotPool.blockOffset(i);
380
- e.push(t[n + A]), i = t[n + N];
381
- }
382
- l(this.cellInts, r);
383
- }
384
- collectNearestCell(e, t, n, r) {
385
- let i = t * k + O;
386
- if (this.cellHeads[i] === this.nullIndex) return;
387
370
  let a = t * k + D;
388
- c(this.cellInts, a);
389
- let o = this.cellHeads[i];
371
+ r(this.cellInts, a);
372
+ let o = this.cellHeads[n];
390
373
  for (; o !== this.nullIndex;) {
391
- let t = this.slotPool.blockFor(o), i = this.slotPool.blockOffset(o), a = t[i + A], s = this.idMap.get(a);
392
- if (s !== void 0) {
393
- let t = this.entityPool.blockFor(s), i = this.entityPool.blockOffset(s), o = t[i + z], c = t[i + B], l = h(n, r, o, c, o + t[i + V], c + t[i + H]);
394
- (l < e.distance || l === e.distance && (e.id === void 0 || a < e.id)) && (e.id = a, e.distance = l);
374
+ let t = this.slotPool.blockFor(o), n = this.slotPool.blockOffset(o);
375
+ e.push(t[n + A]), o = t[n + N];
376
+ }
377
+ i(this.cellInts, a);
378
+ }
379
+ collectNearestCell(e, t, n, a) {
380
+ let o = t * k + O;
381
+ if (this.cellHeads[o] === this.nullIndex) return;
382
+ let s = t * k + D;
383
+ r(this.cellInts, s);
384
+ let c = this.cellHeads[o];
385
+ for (; c !== this.nullIndex;) {
386
+ let t = this.slotPool.blockFor(c), r = this.slotPool.blockOffset(c), i = t[r + A], o = this.idMap.get(i);
387
+ if (o !== void 0) {
388
+ let t = this.entityPool.blockFor(o), r = this.entityPool.blockOffset(o), s = t[r + z], c = t[r + B], l = h(n, a, s, c, s + t[r + V], c + t[r + H]);
389
+ (l < e.distance || l === e.distance && (e.id === void 0 || i < e.id)) && (e.id = i, e.distance = l);
395
390
  }
396
- o = t[i + N];
391
+ c = t[r + N];
397
392
  }
398
- l(this.cellInts, a);
393
+ i(this.cellInts, s);
399
394
  }
400
395
  unlinkFromCell(e, t) {
401
- let n = this.nullIndex, r = this.cellInts, i = this.cellHeads, a = e * k + D;
402
- c(r, a);
403
- let o = e * k + O, s = this.slotPool, u = n, d = i[o];
396
+ let n = this.nullIndex, a = this.cellInts, o = this.cellHeads, s = e * k + D;
397
+ r(a, s);
398
+ let c = e * k + O, l = this.slotPool, u = n, d = o[c];
404
399
  for (; d !== n;) {
405
- let e = s.blockFor(d), c = s.blockOffset(d), f = e[c + N];
406
- if (e[c + A] === t) return u === n ? i[o] = f : s.set(u, N, f), l(r, a), d;
400
+ let e = l.blockFor(d), r = l.blockOffset(d), f = e[r + N];
401
+ if (e[r + A] === t) return u === n ? o[c] = f : l.set(u, N, f), i(a, s), d;
407
402
  u = d, d = f;
408
403
  }
409
- return l(r, a), n;
404
+ return i(a, s), n;
410
405
  }
411
406
  };
412
407
  function ee(e) {
413
- let t = a(e ?? X);
414
- if (t !== i.float32 && t !== i.float64) throw Error("SharedSpatialGrid must be Float32Array or Float64Array");
408
+ let t = l(e ?? X);
409
+ if (t !== c.float32 && t !== c.float64) throw Error("SharedSpatialGrid must be Float32Array or Float64Array");
415
410
  return t;
416
411
  }
417
412
  function Q(e) {
418
- return o(e) === 2 ? Float64Array : Float32Array;
413
+ return u(e) === 2 ? Float64Array : Float32Array;
419
414
  }
420
415
  function $(e) {
421
- return e === i.float32 ? G : K;
416
+ return e === c.float32 ? G : K;
422
417
  }
423
- //#endregion
424
418
  export { Z as default };
425
419
 
426
420
  //# sourceMappingURL=shared-spatial-grid.js.map