Public
Edited
Jun 25, 2023
Insert cell
Insert cell
rope = {
let rope = d3.range(100, 300, 30).map((x) => new Particle(x, 100));
rope_svg.update(rope);
return rope;
}
Insert cell
rope_svg = {
const height = 300;
const svg = d3.create("svg").attr("width", width).attr("height", height);

let nodes = svg.selectAll("circle");

return Object.assign(svg.node(), {
update(data) {
debugger;
nodes = nodes
.data(data, (d) => d.id)
.join(
(enter) => {
enter
.append("circle")
.attr("cx", (d) => d.pos.x)
.attr("cy", (d) => d.pos.y)
.attr("r", 10);
},
(update) =>
update.attr("cx", (d) => d.pos.x).attr("cy", (d) => d.pos.y),
(exit) => exit.remove()
);
}
});
}
Insert cell
Insert cell
viewof step = Inputs.button("Step")
Insert cell
{
step;
simulateVerlet(0.1, rope);
console.log("simulating");
rope_svg.update(rope);
}
Insert cell
function simulateVerlet(dt, particles) {
for (let p of particles) {
let positionCopy = p.pos;
p.pos = p.pos.sub(p.previousPosition.add(p.getAcceleration().mul(dt ** 2)));
p.previousPosition = positionCopy;
}
}
Insert cell
function relaxConstraint(p1, p2, desiredDistance) {
let direction = p2.sub(p1).norm;
let ddist = p1.distance(p2) - desiredDistance;
p1 = p1.add(direction.mul(ddist).div(2));
p2 = p2.sub(direction.mul(ddist).div(2));
return [p1, p2];
}
Insert cell
function jakobsen(constraints, n) {
for (var i = 0; i < n; i++) {
}
}
Insert cell
jakobsen("h", 3)
Insert cell
data = relaxConstraint(p1, p2, 1)
Insert cell
Insert cell
Insert cell
class Particle {
constructor(x, y, id, fixed) {
this.pos = new Vector(x, y);
this.previousPosition = new Vector(x, y);
this.fixed = fixed === undefined ? false : true;
this.id = id === undefined ? `${x},${y}` : id;
}

getAcceleration() {
return new Vector(0, -10);
}
}
Insert cell
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}

distance(other) {
let dx = this.x - other.x;
let dy = this.y - other.y;
return Math.hypot(dx, dy);
}

add(other) {
if (other instanceof Vector)
return new Vector(this.x + other.x, this.y + other.y);
else return new Vector(this.x + other, this.y + other);
}

sub(other) {
if (other instanceof Vector)
return new Vector(this.x - other.x, this.y - other.y);
else return new Vector(this.x - other, this.y - other);
}

mul(other) {
if (other instanceof Vector)
return new Vector(this.x * other.x, this.y * other.y);
else return new Vector(this.x * other, this.y * other);
}

div(other) {
if (other instanceof Vector)
return new Vector(this.x / other.x, this.y / other.y);
else return new Vector(this.x / other, this.y / other);
}

dot(other) {
return this.x * other.x + this.y * other.y;
}

get length() {
return Math.sqrt(this.dot(this));
}

get norm() {
return this.div(this.length);
}

normalize() {}
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more