📝 Added sandbox (code sketchbook)
This commit is contained in:
parent
b475595f7f
commit
b5daf18b1a
142 changed files with 100702 additions and 0 deletions
342
sandbox/simulating_vines/app2.js
Normal file
342
sandbox/simulating_vines/app2.js
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
(function () {
|
||||
var canvas = document.getElementById("vines");
|
||||
var context = canvas.getContext("2d");
|
||||
var canvasb = document.getElementById("leaves");
|
||||
var contextb = canvasb.getContext("2d");
|
||||
var leaves = [];
|
||||
|
||||
// Resize canvas
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
canvasb.width = window.innerWidth;
|
||||
canvasb.height = window.innerHeight;
|
||||
|
||||
// Clear canvas
|
||||
context.fillStyle = "#89f1d7";
|
||||
context.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Calculate distance from point to line
|
||||
function distancePointToLine(point, line) {
|
||||
var L = Math.sqrt(
|
||||
Math.pow(line[1].x - line[0].x, 2) + Math.pow(line[1].y - line[0].y, 2)
|
||||
);
|
||||
var r =
|
||||
((point.x - line[0].x) * (line[1].x - line[0].x) +
|
||||
(point.y - line[0].y) * (line[1].y - line[0].y)) /
|
||||
Math.pow(L, 2);
|
||||
var s =
|
||||
((line[0].y - point.y) * (line[1].x - line[0].x) -
|
||||
(line[0].x - point.x) * (line[1].y - line[0].y)) /
|
||||
Math.pow(L, 2);
|
||||
if (r >= 0 && r <= 1) {
|
||||
return Math.abs(s) * L;
|
||||
} else {
|
||||
return Math.min(
|
||||
Math.sqrt(
|
||||
Math.pow(point.x - line[0].x, 2) + Math.pow(point.y - line[0].y, 2)
|
||||
),
|
||||
Math.sqrt(
|
||||
Math.pow(point.x - line[1].x, 2) + Math.pow(point.y - line[1].y, 2)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw leaf
|
||||
function drawLeaf(leaf) {
|
||||
leaf.size = Math.max(10, leaf.size);
|
||||
contextb.save();
|
||||
contextb.translate(leaf.x, leaf.y);
|
||||
contextb.rotate(leaf.angle);
|
||||
contextb.translate(-leaf.x, -leaf.y);
|
||||
contextb.fillStyle = "#ff0078";
|
||||
contextb.beginPath();
|
||||
contextb.moveTo(leaf.x, leaf.y);
|
||||
contextb.bezierCurveTo(
|
||||
leaf.x + leaf.size,
|
||||
leaf.y,
|
||||
leaf.x + leaf.size * 2,
|
||||
leaf.y + leaf.size,
|
||||
leaf.x,
|
||||
leaf.y + leaf.size * 4
|
||||
);
|
||||
contextb.bezierCurveTo(
|
||||
leaf.x - leaf.size * 2,
|
||||
leaf.y + leaf.size,
|
||||
leaf.x - leaf.size,
|
||||
leaf.y,
|
||||
leaf.x,
|
||||
leaf.y
|
||||
);
|
||||
contextb.closePath();
|
||||
contextb.fill();
|
||||
contextb.restore();
|
||||
}
|
||||
|
||||
// Draw vine
|
||||
function drawVinesWithLattice(
|
||||
lattice,
|
||||
seeds,
|
||||
interations,
|
||||
sort,
|
||||
prune,
|
||||
minLength,
|
||||
maxLength
|
||||
) {
|
||||
var t = 1;
|
||||
var maxLineWidth = 10;
|
||||
|
||||
// Create initial branches
|
||||
var branches = [];
|
||||
for (var i in seeds) {
|
||||
branches.push({
|
||||
points: [
|
||||
{ x: seeds[i].x, y: seeds[i].y },
|
||||
{ x: seeds[i].x, y: seeds[i].y },
|
||||
{ x: seeds[i].x, y: seeds[i].y },
|
||||
{ x: seeds[i].x, y: seeds[i].y },
|
||||
],
|
||||
angle: 0,
|
||||
distanceToLattice: 1000,
|
||||
lineWidth: 6,
|
||||
active: true,
|
||||
leaf: false,
|
||||
});
|
||||
}
|
||||
|
||||
// Animation function
|
||||
function tick() {
|
||||
// Draw branches
|
||||
contextb.clearRect(0, 0, canvasb.width, canvasb.height);
|
||||
for (var i in branches) {
|
||||
var ax =
|
||||
(-branches[i].points[0].x +
|
||||
3 * branches[i].points[1].x -
|
||||
3 * branches[i].points[2].x +
|
||||
branches[i].points[3].x) /
|
||||
6;
|
||||
var ay =
|
||||
(-branches[i].points[0].y +
|
||||
3 * branches[i].points[1].y -
|
||||
3 * branches[i].points[2].y +
|
||||
branches[i].points[3].y) /
|
||||
6;
|
||||
var bx =
|
||||
(branches[i].points[0].x -
|
||||
2 * branches[i].points[1].x +
|
||||
branches[i].points[2].x) /
|
||||
2;
|
||||
var by =
|
||||
(branches[i].points[0].y -
|
||||
2 * branches[i].points[1].y +
|
||||
branches[i].points[2].y) /
|
||||
2;
|
||||
var cx = (-branches[i].points[0].x + branches[i].points[2].x) / 2;
|
||||
var cy = (-branches[i].points[0].y + branches[i].points[2].y) / 2;
|
||||
var dx =
|
||||
(branches[i].points[0].x +
|
||||
4 * branches[i].points[1].x +
|
||||
branches[i].points[2].x) /
|
||||
6;
|
||||
var dy =
|
||||
(branches[i].points[0].y +
|
||||
4 * branches[i].points[1].y +
|
||||
branches[i].points[2].y) /
|
||||
6;
|
||||
context.lineWidth = branches[i].lineWidth;
|
||||
context.beginPath();
|
||||
context.moveTo(
|
||||
ax * Math.pow(t, 3) + bx * Math.pow(t, 2) + cx * t + dx,
|
||||
ay * Math.pow(t, 3) + by * Math.pow(t, 2) + cy * t + dy
|
||||
);
|
||||
context.lineTo(
|
||||
ax * Math.pow(t + 0.1, 3) +
|
||||
bx * Math.pow(t + 0.1, 2) +
|
||||
cx * (t + 0.1) +
|
||||
dx,
|
||||
ay * Math.pow(t + 0.1, 3) +
|
||||
by * Math.pow(t + 0.1, 2) +
|
||||
cy * (t + 0.1) +
|
||||
dy
|
||||
);
|
||||
context.stroke();
|
||||
context.closePath();
|
||||
|
||||
// Draw leaf
|
||||
if (branches[i].leaf) {
|
||||
if (branches[i].active) {
|
||||
var x1 = ax * Math.pow(t, 3) + bx * Math.pow(t, 2) + cx * t + dx;
|
||||
var y1 = ay * Math.pow(t, 3) + by * Math.pow(t, 2) + cy * t + dy;
|
||||
var x2 =
|
||||
ax * Math.pow(t + 0.1, 3) +
|
||||
bx * Math.pow(t + 0.1, 2) +
|
||||
cx * (t + 0.1) +
|
||||
dx;
|
||||
var y2 =
|
||||
ay * Math.pow(t + 0.1, 3) +
|
||||
by * Math.pow(t + 0.1, 2) +
|
||||
cy * (t + 0.1) +
|
||||
dy;
|
||||
branches[i].leaf.x = x2;
|
||||
branches[i].leaf.y = y2;
|
||||
branches[i].leaf.angle = Math.atan2(y2 - y1, x2 - x1) - Math.PI / 2;
|
||||
branches[i].leaf.size = branches[i].lineWidth * 2;
|
||||
} else {
|
||||
branches[i].leaf.size = (branches[i].lineWidth + t) * 2;
|
||||
}
|
||||
drawLeaf(branches[i].leaf);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw leaves
|
||||
for (var i in leaves) {
|
||||
drawLeaf(leaves[i]);
|
||||
}
|
||||
|
||||
// When finished drawing splines, create a new set of branches
|
||||
t += 0.02;
|
||||
if (t >= 1) {
|
||||
var new_branches = [];
|
||||
for (var j = branches.length - 1; j >= 0; j--) {
|
||||
if (branches[j].active) {
|
||||
// Split branch into two
|
||||
for (var k = 0; k < 2; k++) {
|
||||
// Generate random deviation from previous angle
|
||||
var angle = branches[j].angle - (Math.random() * 180 - 90);
|
||||
|
||||
// Determine closest lattice point
|
||||
var distance = 100000;
|
||||
for (var l in lattice) {
|
||||
var result = distancePointToLine(
|
||||
branches[j].points[3],
|
||||
lattice[l]
|
||||
);
|
||||
if (result < distance) distance = result;
|
||||
}
|
||||
|
||||
// Generate random length
|
||||
var length = Math.random() * (maxLength - minLength) + minLength;
|
||||
|
||||
// Calculate new point
|
||||
var x2 =
|
||||
branches[j].points[3].x +
|
||||
Math.sin((Math.PI * angle) / 180) * length;
|
||||
var y2 =
|
||||
branches[j].points[3].y -
|
||||
Math.cos((Math.PI * angle) / 180) * length;
|
||||
|
||||
// Add to new branch array
|
||||
new_branches.push({
|
||||
points: [
|
||||
branches[j].points[1],
|
||||
branches[j].points[2],
|
||||
branches[j].points[3],
|
||||
{ x: x2, y: y2 },
|
||||
],
|
||||
angle: angle,
|
||||
distanceToLattice: distance,
|
||||
lineWidth: 6,
|
||||
active: true,
|
||||
leaf: {
|
||||
x: x2,
|
||||
y: y2,
|
||||
angle: 0,
|
||||
},
|
||||
parent: branches[j],
|
||||
});
|
||||
|
||||
// "Deactivate" branch
|
||||
branches[j].active = false;
|
||||
}
|
||||
|
||||
// Grow branch
|
||||
} else {
|
||||
branches[j].lineWidth++;
|
||||
if (branches[j].lineWidth > maxLineWidth) {
|
||||
leaves.push(branches[j].leaf);
|
||||
branches.splice(j, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort branches by distance to lattice
|
||||
new_branches.sort(function (a, b) {
|
||||
return a.distanceToLattice - b.distanceToLattice;
|
||||
});
|
||||
|
||||
// If over 10 branches, prune the branches furthest from the lattice
|
||||
if (prune) {
|
||||
if (sort) {
|
||||
while (new_branches.length > 20) new_branches.pop();
|
||||
} else {
|
||||
while (new_branches.length > 20) {
|
||||
new_branches.splice(
|
||||
Math.floor(Math.random() * new_branches.length),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove leaves from parent
|
||||
for (var i = 0; i < new_branches.length; i++) {
|
||||
new_branches[i].parent.leaf = false;
|
||||
}
|
||||
|
||||
// Replace old branch array with new
|
||||
branches = branches.concat(new_branches);
|
||||
interations--;
|
||||
t = 0;
|
||||
}
|
||||
|
||||
// Keep on animating
|
||||
if (interations > 0) {
|
||||
requestAnimationFrame(tick);
|
||||
}
|
||||
}
|
||||
tick();
|
||||
}
|
||||
|
||||
// Setup lattice
|
||||
var space = canvas.height / 3;
|
||||
var lattice = [];
|
||||
for (var y = -space * 4; y < space * 4; y += space) {
|
||||
lattice.push([
|
||||
{ x: 0, y: y + canvas.height },
|
||||
{ x: canvas.width, y: y },
|
||||
]);
|
||||
}
|
||||
|
||||
// Draw lattice
|
||||
context.strokeStyle = "rgba(0, 0, 0, 0.1)";
|
||||
context.lineWidth = canvas.height * 0.05;
|
||||
context.lineCap = "square";
|
||||
for (var i in lattice) {
|
||||
context.beginPath();
|
||||
context.moveTo(lattice[i][0].x, lattice[i][0].y);
|
||||
context.lineTo(lattice[i][1].x, lattice[i][1].y);
|
||||
context.stroke();
|
||||
}
|
||||
context.strokeStyle = "#ff0078";
|
||||
|
||||
// Create vines
|
||||
var minLength = canvas.width * 0.05;
|
||||
var maxLength = canvas.width * 0.1;
|
||||
var iterations = 20;
|
||||
var seeds = [
|
||||
{ x: -5, y: space },
|
||||
{ x: space, y: -5 },
|
||||
{ x: -5, y: space * 3 },
|
||||
{ x: canvas.width + 5, y: space },
|
||||
{ x: space * 3, y: canvas.height + 5 },
|
||||
];
|
||||
drawVinesWithLattice(
|
||||
lattice,
|
||||
seeds,
|
||||
iterations,
|
||||
true,
|
||||
true,
|
||||
minLength,
|
||||
maxLength
|
||||
);
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue