class Hash {
constructor(spacing, maxNumObj){
this.tableSize = maxNumObj;
this.spacing = spacing;
this.cellStart = new Int32Array(this.tableSize+1);
this.cellEntries = new Int32Array(maxNumObj);
this.queryIds = new Int32Array(maxNumObj);
this.querySize = 0;
}
hashCoords(xi, yi) {
const h = (xi*92837111)^(yi*689287499);
return Math.abs(h) % this.tableSize;
}
intCoord (coord) {
return Math.floor(coord / this.spacing);
}
hashPos(p){
return this.hashCoords(
this.intCoord(p.x),
this.intCoord(p.y)
);
}
create(parts) {
let numObjects = Math.min(parts.length, this.cellEntries.length);
this.cellStart.fill(0);
this.cellEntries.fill(0);
for (let i=0;i<numObjects;i++){
const h = this.hashPos(parts[i])
this.cellStart[h]++;
}
let s = 0;
for (let i=0;i<=this.tableSize;i++){
s += this.cellStart[i];
this.cellStart[i] = s;
}
this.cellStart[this.tableSize] = s;
for (let i=0;i<numObjects;i++){
const h = this.hashPos(parts[i]);
this.cellStart[h]--;
this.cellEntries[this.cellStart[h]] = i;
}
}
query(p, maxDist) {
let x0 = this.intCoord(p.x) - maxDist;
let y0 = this.intCoord(p.y) - maxDist;
let x1 = this.intCoord(p.x) + maxDist;
let y1 = this.intCoord(p.y) + maxDist;
this.querySize = 0;
for(let xi = x0;xi<=x1;xi++){
for(let yi = y0;yi<=y1;yi++){
const h = this.hashCoords(xi,yi);
const start = this.cellStart[h];
let end = this.cellStart[h+1];
for (let i = start;i<end;i++){
this.queryIds[this.querySize] = this.cellEntries[i];
this.querySize ++;
}
}
}
return this.queryIds.slice(0, this.querySize)
}
}