Closest lines 🌐

Create x amount points in a grid or shape and add bit of offset to its place. Filter out all points that are in its near attraction distance range, draw lines between those.

Log in to post a comment.

const turtle = new Turtle();
const total = 1000; // min=10, max=5000, step=1
const minDistance = 5; // min=1, max=50, step=1
const maxDistance = 15; // min=1, max=50, step=1
const distort = 2; // min=0, max=20, step=0.1
const shape = 1; // min=1, max=5, step=1 (Random, Columns, Grid, Spiral, Circles)
const random = new Random(shape + total + minDistance + maxDistance + distort * 10);
const opacity = 0.3; // min=0.01, max=1, step=0.01

Canvas.setpenopacity(opacity);

const points = Array.from({ length: total }, (_, idx) => {
	const distance = random.range(minDistance, maxDistance);
	switch (shape) {
		case 1: {
			return [random.range(-100, 100), random.range(-95, 95), distance];
		}
		case 2: {
			return [Math.round(random.range(-10, 10)) * 10 + random.range(-distort, distort), random.range(-95, 95), distance];
		}
		case 3: {
			return [Math.round(random.range(-10, 10)) * 10 + random.range(-distort, distort), Math.round(random.range(-10, 10)) * 10 + random.range(-distort, distort), distance];
		}
		case 4: {
			let angle = Math.PI + (idx / total) * (Math.PI * 10);
			if (distort) angle += random.range(20 / -distort, 20 / distort);
			const a = 20;
			const b = 2;
			return [(a + b * angle) * Math.sin(angle) + random.range(-distort, distort), (a + b * angle) * Math.cos(angle) + random.range(-distort, distort), distance];
		}
		case 5: {
			let angle = (idx / total) * (Math.PI * 2);
			if (distort) angle += random.range(20 / -distort, 20 / distort);
			const size = (random.range(2, 10) | 0) * 10;
			return [size * Math.sin(angle) + random.range(-distort, distort), size * Math.cos(angle) + random.range(-distort, distort), distance];
		}
	}
});

function walk(idx) {
	const point = points[idx];
	const closePoints = points.filter((p) => (p[0] - point[0]) * (p[0] - point[0]) + (p[1] - point[1]) * (p[1] - point[1]) < point[2] * point[2]);
	closePoints.forEach((p) => (turtle.jump(point), turtle.goto(p)));
	return idx < points.length - 1;
}

// Seeded random - Mulberry32
function Random(seed) {
    class Random {
        constructor(seed) { 
            this.seed = seed;
        }
        next() { 
            var t = this.seed += 0x6D2B79F5;
            t = Math.imul(t ^ t >>> 15, t | 1);
            t ^= t + Math.imul(t ^ t >>> 7, t | 61);
            return ((t ^ t >>> 14) >>> 0) / 4294967296;
        }
        range(from, to) {
            var r = this.next();
            return from + (to - from) * r;
        }
        either(a = 0, b = 1, chance = 0.5) {
            return this.next() > chance ? a : b;
        }
        shuffle(arr) {
            for (let i = arr.length - 1; i > 0; i--) {
                const j = Math.floor(this.next() * (i + 1));
                [arr[i], arr[j]] = [arr[j], arr[i]];
            }
            return arr;
        }
    }
    return new Random(seed);
}