Public
Edited
Jan 21
Importers
Insert cell
Insert cell
{
const ctx = DOM.context2d(width, height);
ctx.strokeStyle = "#ccc";


// pick a random particle and query its neighbours
const pi = Math.floor(Math.random()*parts.length)


for(let i=0;i<=width;i+=spacing) {
for(let j=0;j<=height;j+=spacing){
ctx.strokeRect(i, j,w,h);
}
}


for(let frame = 0; frame< 1000; frame++) {
// ctx.clearRect(0,0, width, height);
hash.create(parts)
const resids = hash.query(parts[pi], 0)
for (let i=0;i<parts.length;i++){
if (resids.includes(i))
ctx.fillStyle ="red";
else
ctx.fillStyle ="blue";
ctx.beginPath();
ctx.arc(parts[i].x, parts[i].y, 0.3, 0,6.28)
ctx.fill();
parts[i].x += Math.cos(i/10)
parts[i].y += Math.sin(i/10)
}

yield ctx.canvas
}


return ctx.canvas;
}
Insert cell
class Hash {
constructor(spacing, maxNumObj){
// this.numCells = tabSz;
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)
}
}
Insert cell
hash = new Hash(spacing, parts.length)
Insert cell
class Particle {
constructor(x,y,c){
this.x=x;
this.y=y;
this.c = c;
}
}
Insert cell
parts = Array.from({length: 6000}, () => new Particle(Math.random()*width, Math.random()*height, ["red", "blue", "green", "cyan"][Math.floor(Math.random()*4)]))
Insert cell
height = width*0.5
Insert cell
h= spacing
Insert cell
w = spacing
Insert cell
spacing = height/10;
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more