archive complete
This commit is contained in:
13
projects/cubic_bezier_curve/cLine.js
Normal file
13
projects/cubic_bezier_curve/cLine.js
Normal file
@@ -0,0 +1,13 @@
|
||||
class cLine {
|
||||
constructor(a, b, col = color(180, 180, 180, 140), w = 2) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.col = col;
|
||||
this.w = w;
|
||||
}
|
||||
drawLine() {
|
||||
stroke(this.col);
|
||||
strokeWeight(this.w);
|
||||
line(this.a.x, this.a.y, this.b.x, this.b.y);
|
||||
}
|
||||
}
|
||||
44
projects/cubic_bezier_curve/cPoint.js
Normal file
44
projects/cubic_bezier_curve/cPoint.js
Normal file
@@ -0,0 +1,44 @@
|
||||
class cPoint {
|
||||
constructor(x, y, kind = 'control') {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.kind = kind;
|
||||
this.r = 9;
|
||||
}
|
||||
set changeX(nx) { this.x = nx; }
|
||||
set changeY(ny) { this.y = ny; }
|
||||
get changeX() { return this.x; }
|
||||
get changeY() { return this.y; }
|
||||
|
||||
isHit(mx, my, r = HIT_R) {
|
||||
return dist(mx, my, this.x, this.y) <= r;
|
||||
}
|
||||
|
||||
drawPoint(hovered = false, selected = false, styleOverride = null) {
|
||||
strokeWeight(2);
|
||||
if (styleOverride) {
|
||||
stroke(...styleOverride.stroke);
|
||||
fill(...styleOverride.fill);
|
||||
} else {
|
||||
if (this.kind === 'end') {
|
||||
stroke(0, 220, 90, 240);
|
||||
fill(40, 240, 120, 200);
|
||||
} else if (this.kind === 'control') {
|
||||
stroke(240, 140, 0, 240);
|
||||
fill(255, 180, 40, 200);
|
||||
} else {
|
||||
stroke(140, 160);
|
||||
fill(190, 160);
|
||||
}
|
||||
}
|
||||
|
||||
if (selected) {
|
||||
stroke(255, 255, 0);
|
||||
strokeWeight(3);
|
||||
} else if (hovered) {
|
||||
stroke(255);
|
||||
}
|
||||
|
||||
circle(this.x, this.y, this.r * 2);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<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>
|
||||
<script src="cPoint.js"></script>
|
||||
<script src="cLine.js"></script>
|
||||
<!-- <script src="quadCurve.js"></script> -->
|
||||
<script src="cubicCurve.js"></script>
|
||||
<!-- <script src="vectorForm.js"></script> -->
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
<script src="sketch.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
239
projects/cubic_bezier_curve/sketch.js
Normal file
239
projects/cubic_bezier_curve/sketch.js
Normal file
@@ -0,0 +1,239 @@
|
||||
let p = [], v = [];
|
||||
let lines = [];
|
||||
let theta = (3 / 2) * Math.PI, t = 0;
|
||||
let paused = false;
|
||||
let showLabels = false;
|
||||
let showInterPoints = true;
|
||||
|
||||
let hoverIndex = -1;
|
||||
let selectedIndex = -1;
|
||||
let prevMouse = { x: 0, y: 0 };
|
||||
let draggingAll = false;
|
||||
const HIT_R = 10;
|
||||
const MAX_TRAIL = 1000;
|
||||
|
||||
function setup() {
|
||||
createCanvas(1000, 800);
|
||||
initCubicCurve(true);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
background(32);
|
||||
|
||||
stroke(120, 120, 120, 180);
|
||||
strokeWeight(2);
|
||||
noFill();
|
||||
beginShape();
|
||||
vertex(p[0].x, p[0].y);
|
||||
vertex(p[1].x, p[1].y);
|
||||
vertex(p[2].x, p[2].y);
|
||||
vertex(p[3].x, p[3].y);
|
||||
endShape();
|
||||
|
||||
if (!paused) {
|
||||
if (theta > TWO_PI) theta = 0;
|
||||
theta += 0.01;
|
||||
t = (sin(theta) + 1) / 2; // 0..1
|
||||
}
|
||||
|
||||
lerpCubicCurve();
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
lines[i].drawLine();
|
||||
}
|
||||
|
||||
drawCurve();
|
||||
drawPointsAndLabels();
|
||||
drawHUD();
|
||||
}
|
||||
|
||||
function drawCurve() {
|
||||
if (v.length > MAX_TRAIL) v.splice(0, v.length - MAX_TRAIL);
|
||||
|
||||
stroke(0, 255, 0, 200);
|
||||
strokeWeight(5);
|
||||
noFill();
|
||||
beginShape();
|
||||
for (let i = 0; i < v.length; i++) {
|
||||
vertex(v[i].x, v[i].y);
|
||||
}
|
||||
endShape();
|
||||
}
|
||||
|
||||
function drawPointsAndLabels() {
|
||||
push();
|
||||
noStroke();
|
||||
fill(255, 70, 70, 230);
|
||||
circle(p[9].x, p[9].y, 14);
|
||||
pop();
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const hovered = (i === hoverIndex);
|
||||
const selected = (i === selectedIndex);
|
||||
p[i].drawPoint(hovered, selected);
|
||||
if (showLabels) {
|
||||
noStroke();
|
||||
fill(255);
|
||||
textSize(14);
|
||||
textAlign(LEFT, BOTTOM);
|
||||
text(`P${i}`, p[i].x + 10, p[i].y - 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (showLabels) {
|
||||
noStroke(); fill(220);
|
||||
textSize(12); textAlign(LEFT, BOTTOM);
|
||||
text(`P4`, p[4].x + 8, p[4].y - 8);
|
||||
}
|
||||
|
||||
if (showInterPoints) {
|
||||
const styleMid = {
|
||||
stroke: [80, 180, 255, 100],
|
||||
fill: [80, 180, 255, 50]
|
||||
};
|
||||
for (let i = 4; i <= 8; i++) {
|
||||
p[i].drawPoint(false, false, styleMid);
|
||||
if (showLabels) {
|
||||
noStroke(); fill(200);
|
||||
textSize(12); textAlign(LEFT, BOTTOM);
|
||||
text(`P${i}`, p[i].x + 8, p[i].y - 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawHUD() {
|
||||
noStroke();
|
||||
fill(255);
|
||||
textSize(14);
|
||||
textAlign(LEFT, TOP);
|
||||
const hud = [
|
||||
`t = ${t.toFixed(3)}`,
|
||||
`Space = ${paused ? 'Resume' : 'Pause'}`,
|
||||
`H = Toggle points 5..8 | L = Toggle labels | R = Reset`,
|
||||
`Drag a handle (P0..P3). Hold Shift to move the entire curve.`
|
||||
];
|
||||
for (let i = 0; i < hud.length; i++) {
|
||||
text(hud[i], 12, 12 + i * 18);
|
||||
}
|
||||
}
|
||||
|
||||
function initCubicCurve(resetPositions = true) {
|
||||
p.length = 0;
|
||||
v.length = 0;
|
||||
lines.length = 0;
|
||||
theta = (3 / 2) * Math.PI;
|
||||
t = 0;
|
||||
|
||||
if (resetPositions) {
|
||||
p[0] = new cPoint(width * 0.15, height * 0.75, 'end');
|
||||
p[1] = new cPoint(width * 0.35, height * 0.20, 'control');
|
||||
p[2] = new cPoint(width * 0.65, height * 0.20, 'control');
|
||||
p[3] = new cPoint(width * 0.85, height * 0.75, 'end');
|
||||
} else {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (!p[i]) p[i] = new cPoint(width * (0.15 + i * 0.2), height / 2, i === 0 || i === 3 ? 'end' : 'control');
|
||||
}
|
||||
}
|
||||
|
||||
// Derived points
|
||||
p[4] = new cPoint(0, 0, 'derived');
|
||||
p[5] = new cPoint(0, 0, 'derived');
|
||||
p[6] = new cPoint(0, 0, 'derived');
|
||||
p[7] = new cPoint(0, 0, 'derived');
|
||||
p[8] = new cPoint(0, 0, 'derived');
|
||||
p[9] = new cPoint(0, 0, 'derived');
|
||||
|
||||
lines[0] = new cLine(p[4], p[5], color(160, 160, 160, 200), 2);
|
||||
lines[1] = new cLine(p[5], p[6], color(160, 160, 160, 200), 2);
|
||||
|
||||
lines[2] = new cLine(p[7], p[8], color(200, 200, 200, 220), 3);
|
||||
}
|
||||
|
||||
function lerpCubicCurve() {
|
||||
// Level 1
|
||||
p[4].changeX = (1 - t) * p[0].x + t * p[1].x;
|
||||
p[4].changeY = (1 - t) * p[0].y + t * p[1].y;
|
||||
|
||||
p[5].changeX = (1 - t) * p[1].x + t * p[2].x;
|
||||
p[5].changeY = (1 - t) * p[1].y + t * p[2].y;
|
||||
|
||||
p[6].changeX = (1 - t) * p[2].x + t * p[3].x;
|
||||
p[6].changeY = (1 - t) * p[2].y + t * p[3].y;
|
||||
|
||||
// Level 2
|
||||
p[7].changeX = (1 - t) * p[4].x + t * p[5].x;
|
||||
p[7].changeY = (1 - t) * p[4].y + t * p[5].y;
|
||||
|
||||
p[8].changeX = (1 - t) * p[5].x + t * p[6].x;
|
||||
p[8].changeY = (1 - t) * p[5].y + t * p[6].y;
|
||||
|
||||
// Final on-curve
|
||||
p[9].changeX = (1 - t) * p[7].x + t * p[8].x;
|
||||
p[9].changeY = (1 - t) * p[7].y + t * p[8].y;
|
||||
|
||||
v.push(new cPoint(p[9].x, p[9].y, 'derived'));
|
||||
}
|
||||
|
||||
function mouseMoved() {
|
||||
hoverIndex = -1;
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (p[i].isHit(mouseX, mouseY)) {
|
||||
hoverIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mousePressed() {
|
||||
prevMouse.x = mouseX;
|
||||
prevMouse.y = mouseY;
|
||||
|
||||
selectedIndex = -1;
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (p[i].isHit(mouseX, mouseY)) {
|
||||
selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
draggingAll = keyIsDown(SHIFT) && selectedIndex === -1;
|
||||
}
|
||||
|
||||
function mouseDragged() {
|
||||
const dx = mouseX - prevMouse.x;
|
||||
const dy = mouseY - prevMouse.y;
|
||||
|
||||
if (selectedIndex >= 0) {
|
||||
p[selectedIndex].changeX = mouseX;
|
||||
p[selectedIndex].changeY = mouseY;
|
||||
v.length = 0;
|
||||
} else if (draggingAll) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
p[i].changeX = p[i].x + dx;
|
||||
p[i].changeY = p[i].y + dy;
|
||||
}
|
||||
v.length = 0;
|
||||
}
|
||||
|
||||
prevMouse.x = mouseX;
|
||||
prevMouse.y = mouseY;
|
||||
return false;
|
||||
}
|
||||
|
||||
function mouseReleased() {
|
||||
selectedIndex = -1;
|
||||
draggingAll = false;
|
||||
}
|
||||
|
||||
function keyPressed() {
|
||||
if (key === ' ') {
|
||||
paused = !paused;
|
||||
} else if (key === 'R' || key === 'r') {
|
||||
initCubicCurve(true);
|
||||
} else if (key === 'H' || key === 'h') {
|
||||
showInterPoints = !showInterPoints;
|
||||
} else if (key === 'L' || key === 'l') {
|
||||
showLabels = !showLabels;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
class cLine{
|
||||
constructor(p1, p2){
|
||||
this.p1 = p1;
|
||||
this.p2 = p2;
|
||||
}
|
||||
|
||||
drawLine(){
|
||||
stroke(255, 50);
|
||||
strokeWeight(3);
|
||||
|
||||
line(this.p1.x, this.p1.y, this.p2.x, this.p2.y);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
class cPoint{
|
||||
constructor(x,y) {this.x = x; this.y=y;}
|
||||
|
||||
drawPoint(){
|
||||
strokeWeight(14);
|
||||
stroke(255, 200);
|
||||
|
||||
point(this.x, this.y);
|
||||
}
|
||||
get getX(){return this.x;}
|
||||
get getY(){return this.y;}
|
||||
set changeX(_x){this.x = _x;}
|
||||
set changeY(_y){this.y = _y;}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
let p = [], v=[];
|
||||
let lines = [];
|
||||
let theta=3/2 * Math.PI, t=0, clicks=0;
|
||||
|
||||
function setup(){
|
||||
createCanvas(1000, 800);
|
||||
|
||||
initCubicCurve();
|
||||
}
|
||||
|
||||
function draw(){
|
||||
background(63);
|
||||
|
||||
for(let i = 0; i < p.length; i++){
|
||||
p[i].drawPoint();
|
||||
}
|
||||
|
||||
if(clicks > 3){
|
||||
for(let i = 0; i < lines.length; i++){
|
||||
lines[i].drawLine();
|
||||
}
|
||||
|
||||
lerpCubicCurve();
|
||||
drawCurve();
|
||||
}
|
||||
}
|
||||
|
||||
function drawCurve(){
|
||||
if (v.length > 100*Math.PI){v=[];}
|
||||
stroke(0, 255, 0, 200);
|
||||
strokeWeight(5);
|
||||
|
||||
beginShape(LINES);
|
||||
for (let i=0; i < v.length; i++){
|
||||
vertex(v[i].x, v[i].y);
|
||||
}
|
||||
endShape();
|
||||
}
|
||||
|
||||
function mouseClicked(){
|
||||
if (clicks < 5) {
|
||||
p[clicks].changeX = mouseX;
|
||||
p[clicks].changeY = mouseY;
|
||||
} else {
|
||||
let c = clicks % 4;
|
||||
p[c].changeX = mouseX;
|
||||
p[c].changeY = mouseY;
|
||||
}
|
||||
v=[];
|
||||
clicks ++;
|
||||
t=0;
|
||||
theta=3/2 * Math.PI;
|
||||
}
|
||||
|
||||
function mouseDragged(){
|
||||
p[0].changeX = mouseX;
|
||||
p[0].changeY = mouseY;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function initCubicCurve(){
|
||||
p[0] = new cPoint(0,0);
|
||||
p[1] = new cPoint(0,0);
|
||||
p[2] = new cPoint(0,0);
|
||||
p[3] = new cPoint(0,0);
|
||||
|
||||
p[4] = new cPoint(0, 0);
|
||||
p[5] = new cPoint(0, 0);
|
||||
p[6] = new cPoint(0, 0);
|
||||
|
||||
p[7] = new cPoint(0, 0);
|
||||
p[8] = new cPoint(0, 0);
|
||||
|
||||
p[9] = new cPoint(0, 0);
|
||||
|
||||
lines[0] = new cLine(p[0], p[1]);
|
||||
lines[1] = new cLine(p[1], p[2]);
|
||||
lines[2] = new cLine(p[2], p[3]);
|
||||
|
||||
lines[3] = new cLine(p[4], p[5]);
|
||||
lines[4] = new cLine(p[5], p[6]);
|
||||
|
||||
lines[5] = new cLine(p[7], p[8]);
|
||||
}
|
||||
|
||||
function lerpCubicCurve(){
|
||||
p[4].changeX = (1-t)*p[0].x + t * p[1].x;
|
||||
p[4].changeY = (1-t)*p[0].y + t * p[1].y;
|
||||
|
||||
p[5].changeX = (1-t)*p[1].x + t * p[2].x;
|
||||
p[5].changeY = (1-t)*p[1].y + t * p[2].y;
|
||||
|
||||
p[6].changeX = (1-t)*p[2].x + t * p[3].x;
|
||||
p[6].changeY = (1-t)*p[2].y + t * p[3].y;
|
||||
|
||||
p[7].changeX = (1-t)*p[4].x + t * p[5].x;
|
||||
p[7].changeY = (1-t)*p[4].y + t * p[5].y;
|
||||
|
||||
p[8].changeX = (1-t)*p[5].x + t * p[6].x;
|
||||
p[8].changeY = (1-t)*p[5].y + t * p[6].y;
|
||||
|
||||
p[9].changeX = (1-t)*p[7].x + t * p[8].x;
|
||||
p[9].changeY = (1-t)*p[7].y + t * p[8].y;
|
||||
|
||||
v.push(new cPoint(p[9].x, p[9].y));
|
||||
|
||||
if (theta > 2*Math.PI){theta=0;}
|
||||
theta += 0.01;
|
||||
t = (Math.sin(theta) + 1) / 2;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
let p = [], v=[];
|
||||
let lines = [];
|
||||
let theta=3/2 * Math.PI, t=0, clicks=0;
|
||||
|
||||
function setup(){
|
||||
createCanvas(1000, 800);
|
||||
|
||||
initQuadCurve();
|
||||
}
|
||||
|
||||
function draw(){
|
||||
background(63);
|
||||
|
||||
for(let i = 0; i < p.length; i++){
|
||||
p[i].drawPoint();
|
||||
}
|
||||
|
||||
if(clicks > 2){
|
||||
for(let i = 0; i < lines.length; i++){
|
||||
lines[i].drawLine();
|
||||
}
|
||||
|
||||
lerpQuadCurve();
|
||||
drawCurve();
|
||||
}
|
||||
}
|
||||
|
||||
function drawCurve(){
|
||||
if (v.length > 100*Math.PI){v=[];}
|
||||
stroke(0, 255, 0, 200);
|
||||
strokeWeight(5);
|
||||
|
||||
beginShape(LINES);
|
||||
for (let i=0; i < v.length; i++){
|
||||
vertex(v[i].x, v[i].y);
|
||||
}
|
||||
endShape();
|
||||
}
|
||||
|
||||
function mouseClicked(){
|
||||
if (clicks < 3){
|
||||
p[clicks].changeX = mouseX;
|
||||
p[clicks].changeY = mouseY;
|
||||
} else {
|
||||
let c = clicks % 3;
|
||||
p[c].changeX = mouseX;
|
||||
p[c].changeY = mouseY;
|
||||
}
|
||||
v=[];
|
||||
clicks ++;
|
||||
t=0;
|
||||
theta=3/2 * Math.PI;
|
||||
}
|
||||
|
||||
function initQuadCurve(){
|
||||
p[0] = new cPoint(0,0);
|
||||
p[1] = new cPoint(0,0);
|
||||
p[2] = new cPoint(0,0);
|
||||
|
||||
p[3] = new cPoint(0, 0);
|
||||
p[4] = new cPoint(0, 0);
|
||||
p[5] = new cPoint(p[0].x, p[0].y);
|
||||
|
||||
lines[0] = new cLine(p[0], p[1]);
|
||||
lines[1] = new cLine(p[1], p[2]);
|
||||
lines[2] = new cLine(p[3], p[4]);
|
||||
}
|
||||
|
||||
function lerpQuadCurve(){
|
||||
p[3].changeX = (1-t)*p[0].x + t * p[1].x;
|
||||
p[3].changeY = (1-t)*p[0].y + t * p[1].y;
|
||||
|
||||
p[4].changeX = (1-t)*p[1].x + t * p[2].x;
|
||||
p[4].changeY = (1-t)*p[1].y + t * p[2].y;
|
||||
|
||||
p[5].changeX = (1-t)*p[3].x + t * p[4].x;
|
||||
p[5].changeY = (1-t)*p[3].y + t * p[4].y;
|
||||
|
||||
v.push(new cPoint(p[5].x, p[5].y));
|
||||
|
||||
if (theta > 2*Math.PI){theta=0;}
|
||||
theta += 0.01;
|
||||
t = (Math.sin(theta) + 1) / 2;
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
let t=0, theta=0;
|
||||
let t1,t2,t3,t4;
|
||||
|
||||
function setup(){
|
||||
createCanvas(1000, 1000);
|
||||
}
|
||||
|
||||
function draw(){
|
||||
background(15,26,38);
|
||||
theta += 0.01;
|
||||
t = (Math.sin(theta)+1)/2;
|
||||
|
||||
t1 = (-t)^3 + 3*t^2 - 3*t + 1;
|
||||
|
||||
strokeWeight(5);
|
||||
textSize(40);
|
||||
|
||||
noFill();
|
||||
stroke(217, 16, 75);
|
||||
rect(50, 175, 750, 50);
|
||||
text('1.00', 850, 215);
|
||||
fill(217, 16, 75);
|
||||
rect(50, 175, t1*325, 50);
|
||||
|
||||
noFill();
|
||||
stroke(51, 185, 255);
|
||||
rect(50, 375, 750, 50);
|
||||
text('1.00', 850, 415);
|
||||
|
||||
stroke(16, 255, 171);
|
||||
rect(50, 575, 750, 50);
|
||||
text('1.00', 850, 615);
|
||||
|
||||
stroke(221, 192, 76);
|
||||
rect(50, 775, 750, 50);
|
||||
text('1.00', 850, 815);
|
||||
}
|
||||
@@ -1,9 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<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>
|
||||
</head>
|
||||
|
||||
<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>Right‑click</b> shows or hides the contour lines produced by the algorithm.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var reso = 50;
|
||||
var cols, rows;
|
||||
@@ -17,7 +67,7 @@
|
||||
|
||||
cols = width / reso + 1;
|
||||
rows = height / reso + 1;
|
||||
|
||||
|
||||
for (var i = 0; i < cols * rows; i++)
|
||||
field[i] = Math.floor(random(2));
|
||||
}
|
||||
@@ -27,104 +77,104 @@
|
||||
const cBlue = color(55, 120, 232);
|
||||
const cGreen = color(146, 232, 55);
|
||||
|
||||
for (var i = 0; i < cols * rows; i++){
|
||||
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);
|
||||
|
||||
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;}
|
||||
|
||||
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]);
|
||||
|
||||
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) {
|
||||
switch (s) {
|
||||
case 1:
|
||||
fill(cGreen);
|
||||
triangle(x + reso*0.5, y + reso*0.5, c[0], c[1], d[0], d[1]);
|
||||
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]);
|
||||
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]);
|
||||
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]);
|
||||
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);
|
||||
rect(d[0], d[1], reso, reso * 0.5);
|
||||
break;
|
||||
case 12:
|
||||
fill(cGreen);
|
||||
rect(d[0], d[1], reso, reso*0.5);
|
||||
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]);
|
||||
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]);
|
||||
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]);
|
||||
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);
|
||||
rect(a[0], a[1], reso * 0.5, reso);
|
||||
break;
|
||||
case 9:
|
||||
fill(cGreen);
|
||||
rect(a[0], a[1], reso*0.5, reso);
|
||||
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]);
|
||||
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]);
|
||||
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]);
|
||||
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); }
|
||||
if (draw_lines) {drawLines(s, a, b, c, d);}
|
||||
}
|
||||
}
|
||||
|
||||
function getState(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);
|
||||
function drawLines(s, a, b, c, d) {
|
||||
stroke(232, 229, 55);
|
||||
strokeWeight(reso * 0.1);
|
||||
switch(s) {
|
||||
switch (s) {
|
||||
case 1: case 14:
|
||||
line(c[0], c[1], d[0], d[1]);
|
||||
break;
|
||||
@@ -157,17 +207,18 @@
|
||||
noStroke();
|
||||
}
|
||||
|
||||
function mousePressed(){
|
||||
if (mouseButton == LEFT){
|
||||
var x = Math.floor((mouseX + 0.5*reso) / reso);
|
||||
var y = Math.floor((mouseY + 0.5*reso) / reso);
|
||||
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){
|
||||
} else if (mouseButton == RIGHT) {
|
||||
draw_lines = !draw_lines;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
if($_SERVER['HTTP_X_FORWARDED_PROTO'] !== 'https') {
|
||||
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
|
||||
die();
|
||||
}
|
||||
?>
|
||||
<DOCTYPE! html>
|
||||
<html>
|
||||
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
|
||||
<script>
|
||||
var r = 10; //circle size
|
||||
var k = 30;
|
||||
var grid = [];
|
||||
var w = r / Math.sqrt(2);
|
||||
var active = [];
|
||||
var cols, rows;
|
||||
var ordered = [];
|
||||
|
||||
function setup() {
|
||||
createCanvas(900, 900);
|
||||
background(0);
|
||||
strokeWeight(4);
|
||||
colorMode(HSB);
|
||||
|
||||
|
||||
cols = floor(width / w);
|
||||
rows = floor(height / w);
|
||||
for (var i = 0; i < cols * rows; i++) {
|
||||
grid[i] = undefined;
|
||||
}
|
||||
|
||||
|
||||
var x = width / 2;
|
||||
var y = height / 2;
|
||||
var i = floor(x / w);
|
||||
var j = floor(y / w);
|
||||
var pos = createVector(x, y);
|
||||
grid[i + j * cols] = pos;
|
||||
active.push(pos);
|
||||
|
||||
}
|
||||
|
||||
function draw() {
|
||||
background(0);
|
||||
|
||||
|
||||
for (var total = 0; total < 30; total++) {
|
||||
if (active.length > 0) {
|
||||
var randIndex = floor(random(active.length));
|
||||
var pos = active[randIndex];
|
||||
var found = false;
|
||||
for (var n = 0; n < k; n++) {
|
||||
var sample = p5.Vector.random2D();
|
||||
var m = random(r, 2 * r);
|
||||
sample.setMag(m);
|
||||
sample.add(pos);
|
||||
|
||||
var col = floor(sample.x / w);
|
||||
var row = floor(sample.y / w);
|
||||
|
||||
if (col > -1 && row > -1 && col < cols && row < rows && !grid[col + row * cols]) {
|
||||
var flag = true;
|
||||
for (var i = -1; i <= 1; i++) {
|
||||
for (var j = -1; j <= 1; j++) {
|
||||
var index = (col + i) + (row + j) * cols;
|
||||
var neighbor = grid[index];
|
||||
if (neighbor) {
|
||||
var d = p5.Vector.dist(sample, neighbor);
|
||||
if (d < r) {
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
found = true;
|
||||
grid[col + row * cols] = sample;
|
||||
active.push(sample);
|
||||
ordered.push(sample);
|
||||
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
active.splice(randIndex, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < ordered.length; i++) {
|
||||
|
||||
stroke(255, 0, 255);
|
||||
strokeWeight(r * 0.5);
|
||||
point(ordered[i].x, ordered[i].y);
|
||||
}
|
||||
|
||||
for (var i = 0; i < active.length; i++) {
|
||||
if (ordered[i]) {
|
||||
stroke(i % 360, 100, 100);
|
||||
strokeWeight(r * 0.5);
|
||||
point(active[i].x, active[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</html>
|
||||
104
projects/poisson_distribution.html
Normal file
104
projects/poisson_distribution.html
Normal file
@@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
|
||||
<script>
|
||||
var r = 10; //circle size
|
||||
var k = 30;
|
||||
var grid = [];
|
||||
var w = r / Math.sqrt(2);
|
||||
var active = [];
|
||||
var cols, rows;
|
||||
var ordered = [];
|
||||
|
||||
function setup() {
|
||||
createCanvas(900, 900);
|
||||
background(0);
|
||||
strokeWeight(4);
|
||||
colorMode(HSB);
|
||||
|
||||
|
||||
cols = floor(width / w);
|
||||
rows = floor(height / w);
|
||||
for (var i = 0; i < cols * rows; i++) {
|
||||
grid[i] = undefined;
|
||||
}
|
||||
|
||||
|
||||
var x = width / 2;
|
||||
var y = height / 2;
|
||||
var i = floor(x / w);
|
||||
var j = floor(y / w);
|
||||
var pos = createVector(x, y);
|
||||
grid[i + j * cols] = pos;
|
||||
active.push(pos);
|
||||
|
||||
}
|
||||
|
||||
function draw() {
|
||||
background(0);
|
||||
|
||||
|
||||
for (var total = 0; total < 30; total++) {
|
||||
if (active.length > 0) {
|
||||
var randIndex = floor(random(active.length));
|
||||
var pos = active[randIndex];
|
||||
var found = false;
|
||||
for (var n = 0; n < k; n++) {
|
||||
var sample = p5.Vector.random2D();
|
||||
var m = random(r, 2 * r);
|
||||
sample.setMag(m);
|
||||
sample.add(pos);
|
||||
|
||||
var col = floor(sample.x / w);
|
||||
var row = floor(sample.y / w);
|
||||
|
||||
if (col > -1 && row > -1 && col < cols && row < rows && !grid[col + row * cols]) {
|
||||
var flag = true;
|
||||
for (var i = -1; i <= 1; i++) {
|
||||
for (var j = -1; j <= 1; j++) {
|
||||
var index = (col + i) + (row + j) * cols;
|
||||
var neighbor = grid[index];
|
||||
if (neighbor) {
|
||||
var d = p5.Vector.dist(sample, neighbor);
|
||||
if (d < r) {
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) {
|
||||
found = true;
|
||||
grid[col + row * cols] = sample;
|
||||
active.push(sample);
|
||||
ordered.push(sample);
|
||||
|
||||
//break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
active.splice(randIndex, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < ordered.length; i++) {
|
||||
|
||||
stroke(255, 0, 255);
|
||||
strokeWeight(r * 0.5);
|
||||
point(ordered[i].x, ordered[i].y);
|
||||
}
|
||||
|
||||
for (var i = 0; i < active.length; i++) {
|
||||
if (ordered[i]) {
|
||||
stroke(i % 360, 100, 100);
|
||||
strokeWeight(r * 0.5);
|
||||
point(active[i].x, active[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
</html>
|
||||
@@ -1,69 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
|
||||
|
||||
<script>
|
||||
var values = [];
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
|
||||
function setup() {
|
||||
createCanvas(windowWidth -20, windowHeight-20);
|
||||
stroke(255);
|
||||
background(0);
|
||||
|
||||
for (let i = 0; i < width; i++) {
|
||||
values[i] = random(height);
|
||||
line(i, height, i, height - values[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function draw() {
|
||||
stroke(243);
|
||||
background(21);
|
||||
|
||||
for (let i = 0; i < width; i++) {
|
||||
line(i, height, i, height - values[i]);
|
||||
}
|
||||
for (let n = 0; n < 50; n++) {
|
||||
if (values[j] > values[j + 1]) {
|
||||
tmp = values[j]
|
||||
values[j] = values[j + 1];
|
||||
values[j + 1] = tmp;
|
||||
}
|
||||
|
||||
if (i < values.length) {
|
||||
j += 1;
|
||||
if (j >= values.length) {
|
||||
j = 0;
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
stroke(0, 255, 0);
|
||||
for (let i = 0; i < width; i++) {
|
||||
line(i, height, i, height - values[i]);
|
||||
}
|
||||
|
||||
noLoop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function bSort() {
|
||||
let tmp;
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
for (let j = 0; j < values.length - i - 1; j++) {
|
||||
if (values[j] > values[j + 1]) {
|
||||
tmp = values[j]
|
||||
values[j] = values[j + 1];
|
||||
values[j + 1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
@@ -1,133 +0,0 @@
|
||||
<!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 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.slidecontainer {
|
||||
width: 100%;
|
||||
/* Width of the outside container */
|
||||
}
|
||||
|
||||
/* The slider itself */
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
/* Override default CSS styles */
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
/* Full-width */
|
||||
height: 25px;
|
||||
/* Specified height */
|
||||
background: #d3d3d3;
|
||||
/* Grey background */
|
||||
outline: none;
|
||||
/* Remove outline */
|
||||
opacity: 1;
|
||||
/* Set transparency (for mouse-over effects on hover) */
|
||||
-webkit-transition: .2s;
|
||||
/* 0.2 seconds transition on hover */
|
||||
transition: opacity .2s;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
/* Override default look */
|
||||
appearance: none;
|
||||
width: 25px;
|
||||
/* Set a specific slider handle width */
|
||||
height: 25px;
|
||||
/* Slider handle height */
|
||||
background: #434343;
|
||||
/* Grey background */
|
||||
cursor: pointer;
|
||||
/* Cursor on hover */
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 25px;
|
||||
/* Set a specific slider handle width */
|
||||
height: 25px;
|
||||
/* Slider handle height */
|
||||
background: #434343;
|
||||
/* Grey background */
|
||||
cursor: pointer;
|
||||
/* Cursor on hover */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<div class="slidecontainer">
|
||||
<input type="range" min="2" max="11" step="1" value="2" class="slider" id="myRange">
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
let vMargin, hMargin, arrowHeight, t, lineNum;
|
||||
let lineMove = true;
|
||||
|
||||
function setup() {
|
||||
createCanvas(windowWidth, windowHeight * 0.6);
|
||||
hMargin = 12;
|
||||
arrowHeight = 25;
|
||||
t = 0;
|
||||
lineNum = 1;
|
||||
}
|
||||
|
||||
function windowResized() {
|
||||
resizeCanvas(windowWidth, windowHeight * 0.6);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
background(43);
|
||||
angleMode(DEGREES);
|
||||
lineNum = document.getElementById('myRange').value;
|
||||
|
||||
drawLine(hMargin, lineNum + 1);
|
||||
|
||||
if (lineMove) {
|
||||
t++;
|
||||
}
|
||||
|
||||
if (t == 360) {
|
||||
t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function drawLine(hm, vm) {
|
||||
//let changex = map(sin(t), -1, 1, -22, 22);
|
||||
let changex = sin(t) * 18;
|
||||
vm /= 10;
|
||||
for (let j = 1; j < vm - 1; j++) {
|
||||
|
||||
stroke(255, 34, 63);
|
||||
strokeWeight(4);
|
||||
line(width / hm, j * height / vm, width / 2, j * height / vm); //red line
|
||||
|
||||
stroke(69, 98, 255);
|
||||
line(width / 2, j * height / vm, (hm - 1) * width / hm, j * height / vm); //blue line
|
||||
|
||||
stroke(255);
|
||||
line(width / hm, j * height / vm, width / hm + changex, (j * height / vm) - arrowHeight); //left top
|
||||
line(width / hm + changex, (j * height / vm) + arrowHeight, width / hm, j * height / vm); //left bottom
|
||||
|
||||
line((hm - 1) * width / hm + changex, j * height / vm + arrowHeight, (hm - 1) * width / hm, j * height / vm); //right bottom
|
||||
line(width / 2 - changex, j * height / vm + arrowHeight, width / 2, j * height / vm); //center bottom
|
||||
|
||||
line((hm - 1) * width / hm, j * height / vm, (hm - 1) * width / hm + changex, (j * height / vm) - arrowHeight); //right bottom
|
||||
line(width / 2, j * height / vm, width / 2 - changex, (j * height / vm) - arrowHeight); //center top
|
||||
}
|
||||
}
|
||||
|
||||
function mouseClicked() {
|
||||
lineMove = !lineMove;
|
||||
}
|
||||
</script>
|
||||
|
||||
</html>
|
||||
166
projects/warping_lines.html
Executable file
166
projects/warping_lines.html
Executable file
@@ -0,0 +1,166 @@
|
||||
<!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 {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.intro {
|
||||
max-width: 900px;
|
||||
margin: 20px auto 10px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.intro h1 {
|
||||
margin: 0 0 6px;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.intro p {
|
||||
margin: 4px 0 14px;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.slidecontainer {
|
||||
width: 100%;
|
||||
/* Width of the outside container */
|
||||
}
|
||||
|
||||
/* The slider itself */
|
||||
.slider {
|
||||
-webkit-appearance: none;
|
||||
/* Override default CSS styles */
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
/* Full-width */
|
||||
height: 25px;
|
||||
/* Specified height */
|
||||
background: #d3d3d3;
|
||||
/* Grey background */
|
||||
outline: none;
|
||||
/* Remove outline */
|
||||
opacity: 1;
|
||||
/* Set transparency (for mouse-over effects on hover) */
|
||||
-webkit-transition: .2s;
|
||||
/* 0.2 seconds transition on hover */
|
||||
transition: opacity .2s;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
/* Override default look */
|
||||
appearance: none;
|
||||
width: 25px;
|
||||
/* Set a specific slider handle width */
|
||||
height: 25px;
|
||||
/* Slider handle height */
|
||||
background: #434343;
|
||||
/* Grey background */
|
||||
cursor: pointer;
|
||||
/* Cursor on hover */
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 25px;
|
||||
/* Set a specific slider handle width */
|
||||
height: 25px;
|
||||
/* Slider handle height */
|
||||
background: #434343;
|
||||
/* Grey background */
|
||||
cursor: pointer;
|
||||
/* Cursor on hover */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="intro">
|
||||
<h1>Oscillating Arrow Field Visualizer</h1>
|
||||
<p>
|
||||
A sketch to <s>hopefully</s> demonstrate the illusion of the <a
|
||||
href="https://en.wikipedia.org/wiki/M%C3%BCller-Lyer_illusion">Müller-Lyer Illusion</a>
|
||||
</p>
|
||||
<p>The lines - that are the same length, should look longer and shorter based on the angle of the arrow heads.
|
||||
</p>
|
||||
<p>
|
||||
Increasing the value adds more horizontal slices, creating a denser and more detailed pattern.
|
||||
Tap or click to pause and resume the motion.
|
||||
</p>
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<input type="range" min="2" max="11" step="1" value="2" class="slider" id="myRange">
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let vMargin, hMargin, arrowHeight, t, lineNum;
|
||||
let lineMove = true;
|
||||
|
||||
function setup() {
|
||||
createCanvas(windowWidth, windowHeight * 0.6);
|
||||
hMargin = 12;
|
||||
arrowHeight = 25;
|
||||
t = 0;
|
||||
lineNum = 1;
|
||||
}
|
||||
|
||||
function windowResized() {
|
||||
resizeCanvas(windowWidth, windowHeight * 0.6);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
background(43);
|
||||
angleMode(DEGREES);
|
||||
lineNum = document.getElementById('myRange').value;
|
||||
|
||||
drawLine(hMargin, lineNum + 1);
|
||||
|
||||
if (lineMove) {
|
||||
t++;
|
||||
}
|
||||
|
||||
if (t == 360) {
|
||||
t = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function drawLine(hm, vm) {
|
||||
//let changex = map(sin(t), -1, 1, -22, 22);
|
||||
let changex = sin(t) * 18;
|
||||
vm /= 10;
|
||||
for (let j = 1; j < vm - 1; j++) {
|
||||
|
||||
stroke(255, 34, 63);
|
||||
strokeWeight(4);
|
||||
line(width / hm, j * height / vm, width / 2, j * height / vm); //red line
|
||||
|
||||
stroke(69, 98, 255);
|
||||
line(width / 2, j * height / vm, (hm - 1) * width / hm, j * height / vm); //blue line
|
||||
|
||||
stroke(255);
|
||||
line(width / hm, j * height / vm, width / hm + changex, (j * height / vm) - arrowHeight); //left top
|
||||
line(width / hm + changex, (j * height / vm) + arrowHeight, width / hm, j * height / vm); //left bottom
|
||||
|
||||
line((hm - 1) * width / hm + changex, j * height / vm + arrowHeight, (hm - 1) * width / hm, j * height / vm); //right bottom
|
||||
line(width / 2 - changex, j * height / vm + arrowHeight, width / 2, j * height / vm); //center bottom
|
||||
|
||||
line((hm - 1) * width / hm, j * height / vm, (hm - 1) * width / hm + changex, (j * height / vm) - arrowHeight); //right bottom
|
||||
line(width / 2, j * height / vm, width / 2 - changex, (j * height / vm) - arrowHeight); //center top
|
||||
}
|
||||
}
|
||||
|
||||
function mouseClicked() {
|
||||
lineMove = !lineMove;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user