xxxxxxxxxx
127
let points = [];
const dist_between = 50;
const n = 5;
let start, end;
let drag = null;
function setup() {
createCanvas(400, 400);
setupPoints();
}
function draw() {
background(220);
drawPoints();
}
function mousePressed() {
let m = createVector(mouseX, mouseY);
if(end.dist(m) < 6) {
drag = end;
}
if(start.dist(m) < 6) {
drag = start;
}
}
function mouseDragged() {
if(drag) {
drag.x = mouseX;
drag.y = mouseY;
doIK();
}
}
function mouseReleased() {
drag = null;
}
function setupPoints() {
points = [];
for(let i = 0; i < n; i ++) {
points.push(createVector(width/2 - ((n - 1) * dist_between)/2 + i * dist_between, height/2));
}
start = createVector(points[0].x, points[0].y);
end = createVector(points[n-1].x, points[n-1].y);
}
function drawPoints() {
fill(0);
stroke(0);
for(let i = 0; i < n; i ++) {
if(i > 0) {
line(points[i].x, points[i].y, points[i-1].x, points[i-1].y);
}
ellipse(points[i].x, points[i].y, 5, 5);
}
fill(255, 0, 0);
ellipse(end.x, end.y, 6, 6);
fill(0, 255, 0);
ellipse(start.x, start.y, 6, 6);
}
function doIK() {
const maxIt = 6;
let it = 0;
while(it < maxIt) {
let s = points[0].equals(start);
let e = points[n - 1].equals(end);
if(s && e) {
break;
} else if(s) {
moveTowardsEnd();
} else if(e) {
moveTowardsStart();
} else {
moveTowardsEnd();
}
it ++;
}
}
function moveTowardsStart() {
points[0].x = start.x;
points[0].y = start.y;
for(let i = 1; i < n; i ++) {
let p = points[i];
let pre = points[i-1];
let d = p.dist(pre)
if(d > dist_between) {
// move towards pre
points[i] = moveTowards(p, pre, d - dist_between);
}
}
}
function moveTowardsEnd() {
points[n-1].x = end.x;
points[n-1].y = end.y;
for(let i = n-2; i >= 0; i --) {
let p = points[i];
let pre = points[i+1];
let d = p.dist(pre)
if(d > dist_between) {
// move towards pre
points[i] = moveTowards(p, pre, d - dist_between);
}
}
}
function moveTowards(p, target, d) {
let b = p5.Vector.sub(target, p);
b.setMag(d);
b.add(p);
return b;
}