I am trying to update the path of a chain (currently being stored in my code as a array of points) by moving one end of it up. I need the start of the chain to remain fixed in its location and the end up will be moving upwards.
The chain is a series of links that are rigid and have roughly 20-30 degrees of available bend/movement between each link. The array of points is ordered so that the first entry is the point that will be moving up, and the last point is fixed.
I started by creating the chain in its default state:
I've created a method moveUp
that takes in the points, how high to move the last point up to and a step for how much movement per iteration of the loop defined in the method. My logic for the method is basically:
- Loop until the first point has reached the correct height
- If it's the very first point, just move it up by
step
- If the distance between the previous point and next point is
step
then I break the loop. - If the distance between the previous point and the next point is greater than
step*2
then I move the point to be a distance ofstep
from the previous point - If the distance between the previous and next is less than
step*2
then I create a circle on previous and next with a radius ofstep
and use the intersection of these circles to find where to move the point to. (since there can be 2 intersects, I just pick the one that is closer to the original point). Once this step has ran I tell the loop to break after updating the point, since everything after that should not need to move.
Until the chain uncoils a bit on the right side, everything works:
But once I go much more then this, the chain starts to "pull away" from the fixed point on the left:
How can I update my logic/method to make it so this won't pull away from the fixed point and give me a decent looking path for my chain? Here is the code below for the moveUp method (note this uses a custom programming language, so if something is not clear in the below snippet, let me know I can clarify):
private point2D[] moveUp( point2D[] original, double height, double step=0.75inch ) {
if ( original.any() ) {
int count = 0;
while( height - original.first.y >= step ) {
count++;
if ( count > 100 ) {
pln("Too many iterations...");
break;
}
bool shouldStop = false;
for( p in original, index=i ) {
point2D old = p;
if ( i=0 ) {
p = p + (0,step);
} else {
if ( !last ) {
point2D prev = original[i-1];
point2D next = original[i+1];
line2D l( prev, next );
if ( l.length() == step ) {
break;
} else if ( l.length() > step*2 ) {
l.extendP0(-step);
p = l.p0;
} else {
circle prevC( prev, 0.75inch );
circle nextC( next, 0.75inch );
var intersect = this.ins(prevC,nextC);
if ( intersect.count == 0 ) {
pln("No intersection found...".eAngry);
} else {
point2D choice = intersect.p0;
if ( intersect.count > 1 ) {
double distP0 = p.distance(choice);
double distP1 = p.distance(intersect.p1);
if ( distP1 < distP0 ) {
choice = intersect.p1;
}
}
p = choice;
shouldStop = true;
}
}
}
}
original[i] = p;
if ( shouldStop ) { break; }
}
}
}
return original;
}