具有质量碰撞问题的 2D 粒子 (JAVA)

2D particles with mass collision problem (JAVA)

初步

您好,我正在尝试为具有质量的粒子建模 2D 粒子碰撞。物理公式是

我的代码中的粒子有时会正确碰撞,但大多数时候只是粘在一起并开始不受控制地加速(参见下面的可运行 gif)。

代码和问题

我有一个粒子类型的 ArrayList,它有参数 x y VelX VelY, mass(它从0.5 到 1.5) 和其他一些不重要的。 Particleclass里面的collide方法是

public boolean collide(Particle other){
    return Math.abs(this.x-other.x) < width 
            && Math.abs(this.y-other.y) < height;
}

在主程序中我运行函数

public void actionPerformed(ActionEvent e) {


    for(Particle particle : particleList) {

        ArrayList<Particle> particleList2 = (ArrayList<Particle>) particleList.clone();
        particleList2.remove(particleList.indexOf(particle));

        for(Particle particle2 : particleList2) {
            if(particle.collide(particle2)) {
                
                particle.setVelY(velCollision(particle, particle2, 'y')[0]);
                particle2.setVelY(velCollision(particle, particle2, 'y')[1]);
                particle.setVelX(velCollision(particle, particle2, 'x')[0]);
                particle2.setVelX(velCollision(particle, particle2, 'x')[1]);
                
            }
        }
        particle.setX(particle.getX() + particle.getVelX());
        particle.setY(particle.getY() + particle.getVelY());
    }

    repaint();
}

其中velCollision方法如下

public double[] velCollision(Particle p1 , Particle p2 , char dir) {
    double v1i=0,v2i=0,v1f=0,v2f=0;
    double m1 = p1.getMass() , m2 = p2.getMass();
    if (dir == 'x') {
        v1i = p1.getVelX();
        v2i = p2.getVelX();
    } else {
        v1i = p1.getVelY();
        v2i = p2.getVelY();
    }
    v1f = ((m1-m2)/(m1+m2))*v1i + (2*m2/(m1+m2))*v2i;
    v2f = ((m2-m1)/(m1+m2))*vi2 + (2*m1/(m1+m2))*v1i;
    return new double[] {v1f, v2f};
}

我用

绘制所有东西
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;

    for(Particle particle : particleList) {
        Shape circle = new Arc2D.Double(particle.getX(),particle.getY(),particle.getWidth(),
                particle.getHeight(),
                0 , 360, Arc2D.CHORD);
        g2d.fill(circle);
    }

}

这是我输出的一些运行功能

可运行文件 (GIF)

<a href="https://gyazo.com/79f0247a29935aea1f083d4aa3fa1a91"><img src="https://i.gyazo.com/79f0247a29935aea1f083d4aa3fa1a91.gif" alt="Image from Gyazo" width="300"/></a>

   <a href="https://gyazo.com/5e88ccc6710cd6f508fd43c0b1bf8601"><img src="https://i.gyazo.com/5e88ccc6710cd6f508fd43c0b1bf8601.gif" alt="Image from Gyazo" width="300"/></a>

我真的不确定我做错了什么以及导致这个问题的原因。如果我更改 velCollision 方法,使两个粒子的速度对称反转(两个粒子的质量 = 1),那么程序 运行 就可以正常运行,并且粒子会正确碰撞。只有当我引入这个质量差异因子时,我的输出是错误的。

编辑

Particle class :

import java.awt.Color;

public class Particle{
private double x;
private double y;
private double width;
private double height;
private double mass;
private double velX;
private double velY;
private float[] color;


public Particle(double x, double y, double width, double height, double velX, double velY,double mass, float[] color) {
    this.x = x;
    this.y=y;
    this.width=width;
    this.height=height;
    this.velX=velX;
    this.velY = velY;
    this.mass=mass;
    this.color=color;
    
}
public double getMass() {
    return mass;
}
public void setMass(double mass) {
    this.mass=mass;
}
public float[] getColor() {
    return color;
}
public void setColor(float[] color) {
    this.color=color;
}
public double getVelX() {
    return velX;
}

public void setVelX(double velX) {
    this.velX = velX;
}
public double getVelY() {
    return velY;
}

public void setVelY(double velY) {
    this.velY = velY;
}

public double getX() {
    return x;
}

public void setX(double x) {
    this.x = x;
}

public double getY() {
    return y;
}

public void setY(double y) {
    this.y = y;
}

public double getWidth() {
    return width;
}

public void setWidth(double width) {
    this.width = width;
}

public double getHeight() {
    return height;
}

public void setHeight(double height) {
    this.height = height;
}

public boolean collide(Particle other){
    return Math.abs(this.x-other.x) < width 
            && Math.abs(this.y-other.y) < height;
}

}

我可能发现了你的逻辑错误:

particle.setVelY(velCollision(particle, particle2, 'y')[0]);
particle2.setVelY(velCollision(particle, particle2, 'y')[1]);
particle.setVelX(velCollision(particle, particle2, 'x')[0]);
particle2.setVelX(velCollision(particle, particle2, 'x')[1]);

particle.setVelY(velCollision(particle, particle2, 'y')[0]); 的第一次调用更改了 particle 的字段,当您调用 particle2.setVelY(velCollision(particle, particle2, 'y')[1]); 时,它使用与第一次调用不同的值(因为第一次调用更改了值).只需调用您的方法一次并将 return 值保存在临时变量中。

像这样:

tempArrayY = velCollision(particle, particle2, 'y'); // is this correct?
tempArrayX = velCollision(particle, particle2, 'x'); // are both independent?
particle.setVelY(tempArrayY[0]);
particle2.setVelY(tempArrayY[1]);
particle.setVelX(tempArrayX)[0]);
particle2.setVelX(tempArrayX)[1]);