Skip to content

Instantly share code, notes, and snippets.

@martijnkunstman
Created December 20, 2021 08:07
Show Gist options
  • Select an option

  • Save martijnkunstman/95a75ffce163da900bd9413ca2505c26 to your computer and use it in GitHub Desktop.

Select an option

Save martijnkunstman/95a75ffce163da900bd9413ca2505c26 to your computer and use it in GitHub Desktop.
spacial hash
let canvasWidth = 600;
let canvasHeight = 500;
let spacialHash;
let boids = [];
let diameter = 10;
let boidsCount = 2000;
let useSpacialHash = true;
let grid = diameter;
let counter = 0;
let log = true;
function neighbors(arr, m, n) {
// define what a neighbor is
let v = [
[-1, -1],
[-1, 0],
[-1, 1],
[0, -1],
[0, 0],
[0, 1],
[1, -1],
[1, 0],
[1, 1]
];
// filter edges & map
return v
.filter(
([h, j]) =>
h + m >= 0 && h + m < arr.length && j + n >= 0 && j + n < arr[0].length
)
.map(([h, j]) => arr[h + m][j + n]);
}
function setup() {
createCanvas(canvasWidth, canvasHeight);
spacialHash = new SpatialHash({ w: canvasWidth, h: canvasHeight }, grid);
for (let a = 0; a < boidsCount; a++) {
let boid = new Boid(random(0, canvasWidth), random(0, canvasHeight));
boids.push(boid);
spacialHash.insert(boid);
}
}
function draw() {
counter = 0;
spacialHash.clear();
for (let a = 0; a < boids.length; a++) {
boids[a].update();
spacialHash.insert(boids[a]);
}
background(150);
let xx = Math.floor(mouseX / grid);
let yy = Math.floor(mouseY / grid);
fill(255);
rect(xx * grid, yy * grid, grid, grid);
//get all 8 border cells in grid...
fill(200);
rect((xx - 1) * grid, (yy - 1) * grid, grid, grid);
rect((xx - 1) * grid, yy * grid, grid, grid);
rect((xx - 1) * grid, (yy + 1) * grid, grid, grid);
rect((xx + 1) * grid, (yy - 1) * grid, grid, grid);
rect((xx + 1) * grid, yy * grid, grid, grid);
rect((xx + 1) * grid, (yy + 1) * grid, grid, grid);
rect(xx * grid, (yy - 1) * grid, grid, grid);
rect(xx * grid, (yy + 1) * grid, grid, grid);
for (a = 0; a < spacialHash.hashTable.length; a++) {
for (let b = 0; b < spacialHash.hashTable[a].length; b++) {
for (let c = 0; c < spacialHash.hashTable[a][b].length; c++) {
fill(255);
//check overlay
if (useSpacialHash) {
spacialHash.hashTable[a][b][c].checkOverlay(
neighbors(spacialHash.hashTable, a, b)
);
} else {
spacialHash.hashTable[a][b][c].checkOverlay(boids);
}
//
if (a >= yy - 1 && a <= yy + 1 && b >= xx - 1 && b <= xx + 1) {
fill(51);
}
circle(
spacialHash.hashTable[a][b][c].x,
spacialHash.hashTable[a][b][c].y,
diameter
);
}
}
}
fill(0, 0, 255);
textSize(32);
text(Math.round(frameRate())+"-"+counter, 10, 30);
}
class Boid {
constructor(x, y) {
this.x = x;
this.y = y;
this.direction = { x: Math.random() - 0.5, y: Math.random() - 0.5 };
this.w = canvasWidth;
this.h = canvasHeight;
}
checkOverlay(parents) {
parents = [].concat(...parents);
for (let a = 0; a < parents.length; a++) {
counter++;
let disx = parents[a].x - this.x;
let disy = parents[a].y - this.y;
if (disx != 0 && disy != 0) {
if (Math.hypot(disx, disy) < diameter) {
fill(255, 0, 0);
}
}
}
}
update() {
this.x = this.x + this.direction.x;
this.y = this.y + this.direction.y;
if (this.x < diameter) {
this.direction.x = -this.direction.x;
this.x = diameter;
}
if (this.y < diameter) {
this.direction.y = -this.direction.y;
this.y = diameter;
}
if (this.x > this.w - diameter) {
this.direction.x = -this.direction.x;
this.x = this.w - diameter;
}
if (this.y > this.h - diameter) {
this.direction.y = -this.direction.y;
this.y = this.h - diameter;
}
}
}
class SpatialHash {
constructor(bounds, gridSize) {
this.gridSize = gridSize;
this.hashTable = [];
this.horizontal = Math.ceil(bounds.w / gridSize);
this.vertical = Math.ceil(bounds.h / gridSize);
for (let a = 0; a < this.vertical; a++) {
this.hashTable.push([]);
for (let b = 0; b < this.horizontal; b++) {
this.hashTable[a].push([]);
}
}
}
clear() {
for (let a = 0; a < this.vertical; a++) {
for (let b = 0; b < this.horizontal; b++) {
this.hashTable[a][b] = [];
}
}
}
insert(object) {
this.hashTable[Math.floor(object.y / this.gridSize)][
Math.floor(object.x / this.gridSize)
].push(object);
}
find(point) {
return this.hashTable;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
html, body {
margin:0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment