i'm trying make 2d rope simulation, behaves strangely , jumps around when run it. never settles down, if never loses kinetic energy, though have friction coefficient. 
public class rope { private static final double friction_coef = 0.9; public double maxstretchlength; private vec2d gravity = new vec2d(); private final list<node> nodes = new arraylist<>(); public rope(final int nodes, final int length, final vec2d startinglocation) { (int = 0; < nodes; i++) { final node node = new node(); node.location = startinglocation; node.velocity = new vec2d(); if (i != 0) { node.above = getnodes().get(i - 1); getnodes().get(i - 1).below = node; } getnodes().add(node); } maxstretchlength = length / nodes; } public void draw(final graphics g) { final int radius = 5; (final node n : getnodes()) { g.setcolor(color.red); g.filloval((int) n.location.x - radius, (int) n.location.y - radius, radius * 2, radius * 2); if (n.above != null) { g.setcolor(color.blue); g.drawline((int) n.location.x, (int) n.location.y, (int) n.above.location.x, (int) n.above.location.y); } } } public void update() { (final node n : getnodes()) { vec2d force = gravity; if (!n.isfixed()) { force = force.plus(n.above.location.minus(n.location).multiply(friction_coef)); // equal , opposite force if (!n.above.isfixed()) { n.above.velocity = n.above.velocity.plus(force.multiply(-1)); } } n.velocity = n.velocity.plus(force); if (n.isfixed()) { n.velocity = new vec2d(0, 0); } } (final node n : getnodes()) { n.location = n.location.plus(n.velocity); } } public void applygravity(final vec2d v) { gravity = gravity.plus(v); } public list<node> getnodes() { return nodes; } public static class node { public vec2d location; public vec2d velocity; public node above; public node below; public double distance(final node other) { return other.location.distance(location); } public boolean isfixed() { return above == null; } } } public class vec2d extends point2d.double { /* * (non-javadoc) * * @see java.awt.geom.point2d.double#point2d.double() */ public vec2d() { super(); } /* * (non-javadoc) * * @see java.awt.geom.point2d.double#point2d.double() */ public vec2d(final double x, final double y) { super(x, y); } /** * copy constructor */ public vec2d(final vec2d v) { x = v.x; y = v.y; } /** * @return radius (length, modulus) of vector in polar coordinates */ public double getr() { return math.sqrt(x * x + y * y); } /** * @return angle (argument) of vector in polar coordinates in * range [-pi/2, pi/2] */ public double gettheta() { return math.atan2(y, x); } /* * (non-javadoc) * * @see java.awt.geom.point2d.double#setlocation(double, double) */ public void set(final double x, final double y) { super.setlocation(x, y); } /** * sets vector given polar arguments. * * @param r * new radius * @param t * new angle, in radians */ public void setpolar(final double r, final double t) { super.setlocation(r * math.cos(t), r * math.sin(t)); } /** sets vector's radius, preserving angle. */ public void setr(final double r) { final double t = gettheta(); setpolar(r, t); } /** sets vector's angle, preserving radius. */ public void settheta(final double t) { final double r = getr(); setpolar(r, t); } /** sum of vector , rhs */ public vec2d plus(final vec2d rhs) { return new vec2d(x + rhs.x, y + rhs.y); } /** difference of vector , rhs: - rhs */ public vec2d minus(final vec2d rhs) { return new vec2d(x - rhs.x, y - rhs.y); } public boolean equals(final vec2d rhs) { return x == rhs.x && y == rhs.y; } /** product of vector , scalar */ public vec2d multiply(final double scalar) { return new vec2d(scalar * x, scalar * y); } /** dot product of vector , rhs */ public double dotproduct(final vec2d rhs) { return x * rhs.x + y * rhs.y; } /** * since vector2d works in x-y plane, (u x v) points directly along * z axis. function returns value on z axis (u x v) * reaches. * * @return signed magnitude of (this x rhs) */ public double crossproduct(final vec2d rhs) { return x * rhs.y - y * rhs.x; } /** product of components of vector: compenentproduct( <x y>) = x*y. */ public double componentproduct() { return x * y; } /** componentwise product: <this.x*rhs.x, this.y*rhs.y> */ public vec2d componentwiseproduct(final vec2d rhs) { return new vec2d(x * rhs.x, y * rhs.y); } /** * alias getr() * * @return length of */ public double length() { return getr(); } /** * returns new vector same direction vector * length 1, except in case of 0 vectors, return copy of * themselves. */ public vec2d unitvector() { double length = getr(); if (length != 0) return new vec2d(x / length, y / length); return new vec2d(0, 0); } /** polar version of vector, radius in x , angle in y */ public vec2d topolar() { return new vec2d(math.sqrt(x * x + y * y), math.atan2(y, x)); } /** rectangular version of vector, assuming radius in x , angle in y */ public vec2d torect() { return new vec2d(x * math.cos(y), x * math.sin(y)); } /** @return standard string representation of vector: "<x, y>" */ @override public string tostring() { return "<" + x + ", " + y + ">"; } }
force.plus(n.above.location.minus(n.location).multiply(friction_coef)); you scale force friction coefficient. that's not how friction works. must either calculate damping force function of internode velocity (not distance) , subtract elastic force, or apply static friction subtracting fixed amount elastic force.
Comments
Post a Comment