I try to do a 2D rope simulation, but it behaves strangely and jumps when I run it. He also never settles, as if he never loses kinetic energy, although I have a coefficient of friction.
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) {
for (int i = 0; i < 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;
for (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() {
for (final Node n : getNodes()) {
Vec2D force = gravity;
if (!n.isFixed()) {
force = force.plus(n.above.location.minus(n.location).multiply(FRICTION_COEF));
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);
}
}
for (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 {
public Vec2D() {
super();
}
public Vec2D(final double x, final double y) {
super(x, y);
}
public Vec2D(final Vec2D v) {
x = v.x;
y = v.y;
}
public double getR() {
return Math.sqrt(x * x + y * y);
}
public double getTheta() {
return Math.atan2(y, x);
}
public void set(final double x, final double y) {
super.setLocation(x, y);
}
public void setPolar(final double r, final double t) {
super.setLocation(r * Math.cos(t), r * Math.sin(t));
}
public void setR(final double r) {
final double t = getTheta();
setPolar(r, t);
}
public void setTheta(final double t) {
final double r = getR();
setPolar(r, t);
}
public Vec2D plus(final Vec2D rhs) {
return new Vec2D(x + rhs.x, y + rhs.y);
}
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;
}
public Vec2D multiply(final double scalar) {
return new Vec2D(scalar * x, scalar * y);
}
public double dotProduct(final Vec2D rhs) {
return x * rhs.x + y * rhs.y;
}
public double crossProduct(final Vec2D rhs) {
return x * rhs.y - y * rhs.x;
}
public double componentProduct() {
return x * y;
}
public Vec2D componentwiseProduct(final Vec2D rhs) {
return new Vec2D(x * rhs.x, y * rhs.y);
}
public double length() {
return getR();
}
public Vec2D unitVector() {
double length = getR();
if (length != 0)
return new Vec2D(x / length, y / length);
return new Vec2D(0, 0);
}
public Vec2D toPolar() {
return new Vec2D(Math.sqrt(x * x + y * y), Math.atan2(y, x));
}
public Vec2D toRect() {
return new Vec2D(x * Math.cos(y), x * Math.sin(y));
}
@Override
public String toString() {
return "<" + x + ", " + y + ">";
}
}
source
share