JSFiddle - React, Tailwind, and code Playground

by jcubed111

HTML

<canvas width=500 height=500 id=main></canvas>
<div id="count"></div>

CSS

body{
    background: #123;
    color: #eee;
}

JavaScript

const ctx = document.getElementById('main').getContext('2d');

class Point{
	constructor(x, y) {
    	this.x = x;
        this.y = y;
        this.adjacents = [];
        this.marked = false;
    }
    
    *[Symbol.iterator]() {
        yield this.x;
        yield this.y;
    }
    
    markRecursive() {
    	this.marked = true;
        this.adjacents.filter(q => !q.marked).forEach(q => q.markRecursive());
    }
}

function pointDist([x1, y1], [x2, y2]) {
	return Math.sqrt((x1-x2)**2 + (y1-y2)**2);
}

let points = [];
let w = 500, h = 500;
let r = 35;

for(let i=0; i < w*h/r/r; i++) {
	let testPoint = new Point(
    	r + Math.random() * (w - 2*r),
    	r + Math.random() * (h - 2*r),
    );
    if(points.every(p => pointDist(testPoint, p) >= 2*r)) {
    	points.push(testPoint);
    }
}

// connect close point
points.forEach(p => points.filter(
	q => p != q && pointDist(p, q) < 3.5*r
).forEach(
	q => p.adjacents.push(q)
));

// remove loose points
points.find(p => p.adjacents.length > 4).markRecursive();
points = points.filter(p => p.marked); // typically this removes < 1 point


function render() {
	ctx.clearRect(0, 0, w, h);
    points.forEach(p => {
    	ctx.fillStyle = p.marked ? '#bbb' : '#f22';
    	ctx.beginPath();
        ctx.arc(...p, 5, 0, Math.PI*2);
        ctx.fill();
        
        ctx.setLineDash([5]);
        ctx.beginPath();
    	ctx.strokeStyle = '#888';
        p.adjacents.filter(q => p.x < q.x).forEach(q => {
        	ctx.moveTo(...p);
            ctx.lineTo(...q);
        });
        ctx.stroke();
        
        // ctx.strokeStyle = '#000';
        // ctx.beginPath();
        // ctx.arc(...p, r, 0, Math.PI*2);
        // ctx.stroke();
    })
}
render();


document.getElementById('count').innerText = points.length;