Files
havox/projects/marching_squares.html
2026-03-31 22:19:53 +01:00

248 lines
6.4 KiB
HTML
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html>
<head>
<meta
name="viewport"
width="device-width,"
initial-scale="1.0,"
maximum-scale="1.0,"
user-scalable="0"
/>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<style>
body {
font-family:
system-ui,
-apple-system,
Segoe UI,
Roboto,
Helvetica,
Arial,
sans-serif;
margin: 16px;
background: #fafafa;
color: #222;
}
.intro {
max-width: 900px;
margin: 0 auto 18px;
padding: 0 12px;
}
.intro h1 {
font-size: 1.5rem;
margin: 0 0 6px;
}
.intro p {
margin: 4px 0 10px;
line-height: 1.45;
}
canvas {
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="intro">
<h1>Marching Squares Field Visualizer</h1>
<p>
This sketch uses the <strong>Marching Squares</strong> algorithm to
generate and display contour boundaries on a grid. Each cell is either
active or inactive, the algorithm determines the correct line or
triangle to draw based on the surrounding corners.
</p>
<p><b>Left-click</b> toggles a cell between the two states.</p>
<p>
<b>Rightclick</b> shows or hides the contour lines produced by the
algorithm.
</p>
</div>
<script>
var reso = 50;
var cols, rows;
var field = [];
var draw_lines = true;
function setup() {
createCanvas(800, 600);
cols = width / reso + 1;
rows = height / reso + 1;
for (var i = 0; i < cols * rows; i++) field[i] = Math.floor(random(2));
}
function draw() {
background(100);
const cBlue = color(55, 120, 232);
const cGreen = color(146, 232, 55);
for (var i = 0; i < cols * rows; i++) {
let x = i % cols;
let y = Math.floor(i / cols);
let c = field[i] ? cBlue : cGreen;
fill(c);
rect(x * reso - reso * 0.5, y * reso - reso * 0.5, reso, reso);
}
for (var i = 0; i < cols * rows; i++) {
if (i + cols + 1 > cols * rows) {
break;
}
var x = (i % cols) * reso;
var y = Math.floor(i / cols) * reso;
const a = [x + reso * 0.5, y];
const b = [x + reso, y + reso * 0.5];
const c = [x + reso * 0.5, y + reso];
const d = [x, y + reso * 0.5];
var s = getState(
field[i],
field[i + 1],
field[i + cols + 1],
field[i + cols]
);
noStroke();
switch (s) {
case 1:
fill(cGreen);
triangle(x + reso * 0.5, y + reso * 0.5, c[0], c[1], d[0], d[1]);
break;
case 14:
fill(cBlue);
triangle(x + reso * 0.5, y + reso * 0.5, c[0], c[1], d[0], d[1]);
break;
case 2:
fill(cGreen);
triangle(x + reso * 0.5, y + reso * 0.5, b[0], b[1], c[0], c[1]);
break;
case 13:
fill(cBlue);
triangle(x + reso * 0.5, y + reso * 0.5, b[0], b[1], c[0], c[1]);
break;
case 3:
fill(cBlue);
rect(d[0], d[1], reso, reso * 0.5);
break;
case 12:
fill(cGreen);
rect(d[0], d[1], reso, reso * 0.5);
break;
case 4:
fill(cGreen);
triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], b[0], b[1]);
break;
case 11:
fill(cBlue);
triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], b[0], b[1]);
break;
case 5:
fill(cBlue);
triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], d[0], d[1]);
triangle(x + reso * 0.5, y + reso * 0.5, b[0], b[1], c[0], c[1]);
break;
case 6:
fill(cBlue);
rect(a[0], a[1], reso * 0.5, reso);
break;
case 9:
fill(cGreen);
rect(a[0], a[1], reso * 0.5, reso);
break;
case 7:
fill(cBlue);
triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], d[0], d[1]);
break;
case 8:
fill(cGreen);
triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], d[0], d[1]);
break;
case 10:
fill(cBlue);
triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], b[0], b[1]);
triangle(x + reso * 0.5, y + reso * 0.5, c[0], c[1], d[0], d[1]);
break;
default:
break;
}
if (draw_lines) {
drawLines(s, a, b, c, d);
}
}
}
function getState(a, b, c, d) {
return d * 1 + c * 2 + b * 4 + a * 8;
}
function drawLines(s, a, b, c, d) {
stroke(232, 229, 55);
strokeWeight(reso * 0.1);
switch (s) {
case 1:
case 14:
line(c[0], c[1], d[0], d[1]);
break;
case 2:
case 13:
line(b[0], b[1], c[0], c[1]);
break;
case 3:
case 12:
line(b[0], b[1], d[0], d[1]);
break;
case 4:
case 11:
line(a[0], a[1], b[0], b[1]);
break;
case 5:
line(a[0], a[1], d[0], d[1]);
line(b[0], b[1], c[0], c[1]);
break;
case 6:
case 9:
line(a[0], a[1], c[0], c[1]);
break;
case 7:
case 8:
line(a[0], a[1], d[0], d[1]);
break;
case 10:
line(a[0], a[1], b[0], b[1]);
line(c[0], c[1], d[0], d[1]);
break;
default:
break;
}
noStroke();
}
function mousePressed() {
if (mouseButton == LEFT) {
var x = Math.floor((mouseX + 0.5 * reso) / reso);
var y = Math.floor((mouseY + 0.5 * reso) / reso);
var i = Math.floor(y * cols + x);
field[i] = (field[i] + 1) % 2;
} else if (mouseButton == RIGHT) {
draw_lines = !draw_lines;
}
}
</script>
</body>
</html>