xxxxxxxxxx
218
// Display parameters
var cnv = {
w: 500,
h: 500
};
var pivot = {
x: cnv.w / 2,
y: cnv.h / 2
};
var fr = 60;
var tracer;
const loops = 10;
// The parameters of the problem
const g = 9.8;
const dt = 1.0 / fr / loops;
// The variables of the problem
var dp;
var vp;
var im;
var lumamap;
function preload() {
im = loadImage('acc2e.jpg');
}
function setup() {
createCanvas(im.width, im.height);
im.loadPixels();
frameRate(fr);
cnv.w = im.width;
cnv.h = im.height;
pivot = {
x: cnv.w / 2,
y: cnv.h / 2
};
lumamap = new Array(floor(im.pixels.length/4));
for(let i = 0; i < im.pixels.length - 1; i += 4) {
let R = im.pixels[i];
let G = im.pixels[i+1];
let B = im.pixels[i+2];
let luma = 0.2126*R + 0.7152*G + 0.0722*B;
lumamap[floor((i+1)/4)] = luma;
}
// let writer = createWriter('luma.txt');
// writer.write(lumamap);
// writer.close();
dp1 = new DoublePendulum(1, 1, 1, 1, 0.54);
dp2 = new DoublePendulum(1, 1, 1, 1, 0.6);
dp1.initialize(dt, 3, 3, 0, 0);
dp2.initialize(dt, 3, 3.005, 0, 0);
dp1.setColor(120, 120, 120);
dp2.setColor(120, 120, 120);
dp1.pivot = createVector(pivot.x, pivot.y);
dp2.pivot = createVector(pivot.x, pivot.y);
vp1 = dp1.loc2;
vp2 = dp2.loc2;
background(28);
// image(im, 0, 0);
}
function draw() {
// background(220);
for(let i = 0; i < loops*2; i++) {
let w1 = 1.9*exp(-(dp1.mom2**2)/10) + 0.7;
let w2 = 1.9*exp(-(dp2.mom2**2)/10) + 0.7;
let c1 = mapxy(dp1.loc2.x, dp1.loc2.y);
let c2 = mapxy(dp2.loc2.x, dp2.loc2.y);
// console.log(dp.loc2.x, dp.loc2.y);
strokeWeight(w1);
strokeCap(SQUARE);
try {
stroke(c1, c1, 0, 230);
} catch (error) {
console.log(0, c1, 0);
console.error(error);
}
// console.log(c);
// point(dp.loc2.x, dp.loc2.y);
line(vp1.x, vp1.y, dp1.loc2.x, dp1.loc2.y);
if(frameCount <= 9000) {
strokeWeight(w2);
stroke(c2*0.75, 0, 0, 180);
line(vp2.x, vp2.y, dp2.loc2.x, dp2.loc2.y);
}
vp1 = dp1.loc2;
vp2 = dp2.loc2;
// dp.paint();
dp1.step();
dp2.step();
dp1.integrate();
dp2.integrate();
}
}
// function mouseDragged() {
// let alp = mapxy(pmouseX, pmouseY);
// // console.log(mouseX);
// strokeCap(SQUARE);
// strokeWeight(10);
// stroke(220, 220, 0, alp);
// line(pmouseX, pmouseY, mouseX, mouseY);
// }
function mapxy(x, y) {
let idx = floor(x) + floor(y)*im.width;
// console.log(im.width);
return lumamap[idx];
}
class DoublePendulum {
constructor(len1 = 1, len2 = 1, m1 = 1, m2 = 1, fac = 0.5) {
this.length1 = len1;
this.length2 = len2;
this.mass1 = m1;
this.mass2 = m2;
this.pvt = createVector(0, 0);
this.Lscale = fac * cnv.h / (len1 + len2);
}
initialize(dt, theta1 = 0, theta2 = 0, ptheta1 = 0, ptheta2 = 0) {
this.dt = dt;
this.q1 = theta1;
this.q2 = theta2;
this.p1 = ptheta1;
this.p2 = ptheta2;
}
setColor(r, g, b) {
this.bob1 = color(r, g, b);
function lighten(clr) {
return (255 - clr)*0.3 + clr;
}
this.bob2 = color(lighten(r), lighten(g), lighten(b));
}
set pivot(vec) {
this.pvt = vec;
}
step() {
let q1 = this.q1;
let q2 = this.q2;
let p1 = this.p1;
let p2 = this.p2;
let l1 = this.length1;
let l2 = this.length2;
let m1 = this.mass1;
let m2 = this.mass2;
let dq = q1 - q2;
let h1 = (p1 * p2 * sin(dq)) / (l1 * l2 * (m1 + m2 * (sin(dq)) ** 2));
let h2 = (m2 * l2 * l2 * p1 * p1 + (m1 + m2) * l1 * l1 * p2 * p2 - 2 * m2 * l1 * l2 * p1 * p2 * cos(dq)) / (2 * l1 * l1 * l2 * l2 * (m1 + m2 * (sin(dq)) ** 2) ** 2);
this.dq1 = (l2 * p1 - l1 * p2 * cos(dq)) / (l1 * l1 * l2 * (m1 + m2 * (sin(dq)) ** 2));
this.dq2 = (-m2 * l2 * p1 * cos(dq) + (m1 + m2) * l1 * p2) / (m2 * l1 * l2 * l2 * (m1 + m2 * (sin(dq)) ** 2));
this.dp1 = -((m1 + m2) * g * l1 * sin(q1) + h1 - h2 * sin(2 * dq));
this.dp2 = -(m2 * g * l2 * sin(q2) - h1 + h2 * sin(2 * dq));
}
integrate() {
// Euler method
this.q1 = this.q1 + this.dt * this.dq1;
this.q2 = this.q2 + this.dt * this.dq2;
this.p1 = this.p1 + this.dt * this.dp1;
this.p2 = this.p2 + this.dt * this.dp2;
}
get loc1() {
let x = this.pvt.x + this.length1 * this.Lscale * sin(this.q1);
let y = this.pvt.y + this.length1 * this.Lscale * cos(this.q1);
return createVector(x, y);
}
get loc2() {
let x = this.loc1.x + this.length2 * this.Lscale * sin(this.q2);
let y = this.loc1.y + this.length2 * this.Lscale * cos(this.q2);
return createVector(x, y);
}
get mom1() {
return this.p1;
}
get mom2() {
return this.p2;
}
paint() {
ellipseMode(CENTER);
fill(5);
ellipse(this.pvt.x, this.pvt.y, 5);
stroke(20);
fill(this.bob1);
line(this.pvt.x, this.pvt.y, this.loc1.x, this.loc1.y);
ellipse(this.loc1.x, this.loc1.y, 12);
fill(this.bob2);
line(this.loc1.x, this.loc1.y, this.loc2.x, this.loc2.y);
ellipse(this.loc2.x, this.loc2.y, 12);
}
}