Public
Edited
Dec 1, 2022
1 fork
1 star
Insert cell
Insert cell
class Wave {
constructor(id, frequencyNumerator, frequencyDenominator) {
this.id = id;
this.fn = frequencyNumerator;
this.fd = frequencyDenominator;
this.closed = true;
}

value(p) {
let frequencyModulator = this.fn/this.fd;
let f = frequencyModulator*2*Math.PI/p.size;
if (this.closed) {
return Math.sin(f*p.x)*Math.sin(f*p.y);
} else {
return Math.cos(f*p.x)*Math.cos(f*p.y);
}
}
};

Insert cell
class WavePool {
constructor() {
this.waves = [];
this.normalize = true;
}

add(wave) {
this.waves.push(wave);
}

value(p) {
var value = 0;
for (var i = 0; i < this.waves.length; i ++) {
value += this.waves[i].value(p);
}
value = Math.abs(value);
var normalizer = 1;
if (this.normalize) normalizer = this.waves.length;
return (value / normalizer);
}
};

Insert cell
class WaveController {

constructor(wavepool) {
this.waveCount = 0;
this.pool = wavepool;
}

getWave(waveId) {
return this.pool.get(waveId);
}

newWave() {
var waveId = "wave"+ (this.waveCount ++);
var wave = new Wave(waveId, 1,2);
wave.closed = false;
this.pool.add(wave);
}
}
Insert cell
function randomInt(lessThan){
var selection = Math.floor(Math.random()*(lessThan));
return selection;
}
Insert cell
function randomRange(greaterThan, lessThan){
var shifted = randomInt(lessThan - greaterThan);
return lessThan - shifted;
};
Insert cell
class RandomPoint {
constructor(size) {
this.x = randomRange(0,size);
this.y = randomRange(0,size);
this.size = size;
}
perturb(){
this.x = this.x + randomRange(-this.size/10,this.size/10);
this.y = this.y + randomRange(-this.size/10,this.size/10);
}
};
Insert cell
{
var colourBase = 200;
var invertColour = true;

function increaseHue () {
if (colourBase < 360) { colourBase += 2}
else {colourBase = 0}
}
function decreaseHue () {
if (colourBase > 0) {colourBase -=2}
else {colourBase = 360}
}
function invertHue() {
invertColour = !invertColour;
}
function range(n) {
return Array.from((Array(n)).keys()) ;
}

function hslColorChooser(level) {
var l = Math.floor(level * 100);
if (invertColour) {
l = Math.floor(100 - l);
}
return "hsl("+ colourBase + ", 50%, " + l +"%)";
};

function randomInt(lessThan){
var selection = Math.floor(Math.random()*(lessThan));
return selection;
};


const size = 400;
let piles = 500;

let sandcount = 200; //amount of sand in one push
let dotSize = 3; //initial dot size

let sand = [];

let wavepool = new WavePool();
var waveController = new WaveController(wavepool);
waveController.newWave();
waveController.newWave();
waveController.newWave();
wavepool.waves[0].fn += 2;
wavepool.waves[0].fn += 1;
const svg = d3.create('svg')
.attr('width', size)
.attr('height', size);

for(var p=0;p<piles;p++){
for (var i = 0; i < sandcount; i ++){
let p = new RandomPoint(size);
sand.push(p);
}
//draw circles
svg.selectAll("circle")
.data(sand)
.enter().append("circle")
.attr("cx", function(s) {
return s.x;})
.attr("cy", function(s) {
return s.y;})
.attr("r", function(s) { return dotSize; })
.attr("class","dot")
.style("fill", function(s){
let value = wavepool.value(s);
return hslColorChooser(value);
});
await Promises.delay(10)
yield svg.node();

}
}
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