Java ); } /**矢量的极坐标版本,半径为x,角度为y*/ 公共矢量2D拓扑(){ 返回新的Vec2D(Math.sqrt(x*x+y*y),Math.atan2(y,x)); } /**向量的矩形版本,假设半径为x,角度为y*/ 公共vectorect(){ 返回新的Vec2D(x*Math.cos(y),x*Math.sin(y)); } /**@return向量的标准字符串表示法:“*/ @凌驾 公共字符串toString(){ 返回“”; } }
你只需要通过摩擦系数来调整力的大小。这不是摩擦力的工作原理。您必须计算阻尼力作为节间速度(而不是距离)的函数,并从弹力中减去阻尼力,或者通过从弹力中减去固定量来施加静摩擦力。Java ); } /**矢量的极坐标版本,半径为x,角度为y*/ 公共矢量2D拓扑(){ 返回新的Vec2D(Math.sqrt(x*x+y*y),Math.atan2(y,x)); } /**向量的矩形版本,假设半径为x,角度为y*/ 公共vectorect(){ 返回新的Vec2D(x*Math.cos(y),x*Math.sin(y)); } /**@return向量的标准字符串表示法:“*/ @凌驾 公共字符串toString(){ 返回“”; } },java,2d,simulation,physics,Java,2d,Simulation,Physics,你只需要通过摩擦系数来调整力的大小。这不是摩擦力的工作原理。您必须计算阻尼力作为节间速度(而不是距离)的函数,并从弹力中减去阻尼力,或者通过从弹力中减去固定量来施加静摩擦力。Vec2D类来自Google或Geom?@MaxZoom属于我自己的类。如果你愿意,我可以把它寄出去?这是一个非常简单的不可变向量类,很容易看到。@MaxZoom好吧,我添加了它,我不太确定你的意思。如何计算阻尼力?取节点相对于其相邻节点的当前速度,乘以一个系数来检索阻尼力。我将上面的行更改为n.over.velocity.
Vec2D
类来自Google或Geom?@MaxZoom属于我自己的类。如果你愿意,我可以把它寄出去?这是一个非常简单的不可变向量类,很容易看到。@MaxZoom好吧,我添加了它,我不太确定你的意思。如何计算阻尼力?取节点相对于其相邻节点的当前速度,乘以一个系数来检索阻尼力。我将上面的行更改为n.over.velocity.减号(n.velocity)。multiply(摩擦力系数)
,但现在不是将节点拉回,而是让它们继续向下,只是越来越慢,因为你用阻尼代替了弹力。你需要两个术语。你能给我看一段代码吗?无论我尝试什么,它都不会给我想要的结果。
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));
// equal and 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);
}
}
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 {
/*
* (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 the radius (length, modulus) of the vector in polar coordinates
*/
public double getR() {
return Math.sqrt(x * x + y * y);
}
/**
* @return the angle (argument) of the vector in polar coordinates in the
* 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 the vector given polar arguments.
*
* @param r
* The new radius
* @param t
* The new angle, in radians
*/
public void setPolar(final double r, final double t) {
super.setLocation(r * Math.cos(t), r * Math.sin(t));
}
/** Sets the vector's radius, preserving its angle. */
public void setR(final double r) {
final double t = getTheta();
setPolar(r, t);
}
/** Sets the vector's angle, preserving its radius. */
public void setTheta(final double t) {
final double r = getR();
setPolar(r, t);
}
/** The sum of the vector and rhs */
public Vec2D plus(final Vec2D rhs) {
return new Vec2D(x + rhs.x, y + rhs.y);
}
/** The difference of the vector and rhs: this - 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 the vector and scalar */
public Vec2D multiply(final double scalar) {
return new Vec2D(scalar * x, scalar * y);
}
/** Dot product of the vector and rhs */
public double dotProduct(final Vec2D rhs) {
return x * rhs.x + y * rhs.y;
}
/**
* Since Vector2D works only in the x-y plane, (u x v) points directly along
* the z axis. This function returns the value on the z axis that (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 the 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);
}
/**
* An alias for getR()
*
* @return the length of this
*/
public double length() {
return getR();
}
/**
* Returns a new vector with the same direction as the vector but with
* length 1, except in the case of zero vectors, which return a 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 the vector, with radius in x and angle in y */
public Vec2D toPolar() {
return new Vec2D(Math.sqrt(x * x + y * y), Math.atan2(y, x));
}
/** Rectangular version of the vector, assuming radius in x and angle in y */
public Vec2D toRect() {
return new Vec2D(x * Math.cos(y), x * Math.sin(y));
}
/** @return Standard string representation of a vector: "<x, y>" */
@Override
public String toString() {
return "<" + x + ", " + y + ">";
}
}
force.plus(n.above.location.minus(n.location).multiply(FRICTION_COEF));