java - 2D Rope Simulation -


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. simulation

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