C++ 气粒模拟碰撞计算C++;

C++ 气粒模拟碰撞计算C++;,c++,C++,我觉得这是一个相当复杂的问题,我希望我能把它放在一个足够小的空间,使它可以理解。我现在正在写代码给 模拟箱内的理想气体粒子。在计算了两个粒子到达最近点所需的时间后,我正在计算两个粒子是否会碰撞。(使用正面碰撞的示例) 在这段代码中,我需要找出两个粒子是否会发生碰撞,然后再计算碰撞的时间和方式等。 因此,我的两个教区: Main.cpp Vector vp1(0,0,0); Vector vv1(1,0,0); Vector vp2(12,0,0); Vector vv2(-1,0,0); Par

我觉得这是一个相当复杂的问题,我希望我能把它放在一个足够小的空间,使它可以理解。我现在正在写代码给

模拟箱内的理想气体粒子。在计算了两个粒子到达最近点所需的时间后,我正在计算两个粒子是否会碰撞。(使用正面碰撞的示例)

在这段代码中,我需要找出两个粒子是否会发生碰撞,然后再计算碰撞的时间和方式等。 因此,我的两个教区:

Main.cpp

Vector vp1(0,0,0);
Vector vv1(1,0,0);
Vector vp2(12,0,0);
Vector vv2(-1,0,0);
Particle Particle1(1, vp1, vv1);
Particle Particle2(1, vp2, vv2);
Particle1.timeToCollision(Particle2);
在我的程序中,我将粒子定义为:

头文件

class Particle {
private:

    Vector p;   //position
    Vector v;   //velocity
    double radius;   //radius

public:

    Particle();

    Particle(double r, const Vector Vecp, const Vector Vecv);

    void setPosition(Vector);
    void setVelocity(Vector);

    Vector getPosition() const;
    Vector getVelocity() const;

    double getRadius() const;

    void move(double t);

    double timeToCollision(const Particle particle);

    void collideParticles(Particle);

    ~Particle();
};
Vector
是另一个简单地给出
x
y
z
值的类。它还包含多个用于处理这些问题的函数


和我需要帮助的部分,在
.cpp
中(忽略cout start和字母等,它们是我的代码退出测试的简单检查。)

给定方程式:

我已经编写了代码来为我做点积和模,并且:

在哪里

s
是在时间上行驶的距离
tac

double Particle::timeToCollision(const Particle particle){
    Vector r2 = particle.getPosition();
    Vector r1 = p;
    Vector v2 = particle.getVelocity();
    Vector v1 = v;
    Vector r0 = r2 - r1;
    Vector v = v2 - v1;

    double modv;
    double tca;
    double result = 0;
    double bsqr;

    modv = getVelocity().modulus();

    cout << "start" << endl;

    if(modv < 0.0000001){
        cout << "a" << endl;
        result = FLT_MAX;
    }else{
        cout << "b" << endl;
        tca = ((--r0).dot(v)) / v.modulusSqr();

// -- is an overridden operator that gives the negation ( eg (2, 3, 4) to (-2, -3, -4) )
        if (tca < 0) {
            cout << "c" << endl;
            result = FLT_MAX;
        }else{
            cout << "d" << endl;
            Vector s(v.GetX(), v.GetY(), v.GetZ());
            s.Scale(tca);
            cout << getVelocity().GetX() << endl;
            cout << getVelocity().GetY() << endl;
            cout << getVelocity().GetZ() << endl;

            double radsqr = radius * radius;
            double bx = (r0.GetX() * r0.GetX() - (((r0).dot(v)) *((r0).dot(v)) / v.modulusSqr()));
            double by = (r0.GetY() * r0.GetY() - (((r0).dot(v)) *((r0).dot(v)) / v.modulusSqr()));
            double bz=(r0.GetZ() * r0.GetZ() - (((r0).dot(v)) * ((r0).dot(v)) / v.modulusSqr()));

            if (bsqr < 4 * radsqr) {
                cout << "e" << endl;
                result = FLT_MAX;
            } else {
            }
            cout << "tca: " << tca << endl;
        }
    }
    cout << "fin" << endl;
    return result;
}
双粒子::时间集合(常量粒子){
向量r2=particle.getPosition();
向量r1=p;
向量v2=粒子。getVelocity();
向量v1=v;
向量r0=r2-r1;
向量v=v2-v1;
双modv;
双tca;
双结果=0;
双bsqr;
modv=getVelocity().模数();

您的代码中可能有几个错误。您从未将
result
设置为与
0
FLT\u MAX
不同的值。您也从未计算过
bsqr
。我猜,如果
bsqr<4r^2
而不是相反,则会发生冲突。(我不明白为什么
4r^2
而不是
r^2
,但是没问题)。因为你隐藏了你的向量实现,我使用了一个通用的向量库。我还建议不要使用手工制作的东西。看看犰狳或艾根

在这里,您可以尝试使用Eigen

#include <iostream>
#include <limits>
#include <type_traits>
#include "Eigen/Dense"

struct Particle {
    double radius;
    Eigen::Vector3d p;
    Eigen::Vector3d v;
};

template <class FloatingPoint>
    std::enable_if_t<std::is_floating_point<FloatingPoint>::value, bool>
        almost_equal(FloatingPoint x, FloatingPoint y, unsigned ulp=1)
        {
            FloatingPoint max = std::max(std::abs(x), std::abs(y));
            return std::abs(x-y) <= std::numeric_limits<FloatingPoint>::epsilon()*max*ulp;
        }

double timeToCollision(const Particle& left, const Particle& right){
    Eigen::Vector3d r0 = right.p - left.p;
    Eigen::Vector3d v  = right.v - left.v;

    double result = std::numeric_limits<double>::infinity();

    double vv = v.dot(v);
    if (!almost_equal(vv, 0.)) {
        double tca = (-r0).dot(v) / vv;
        if (tca >= 0) {
            Eigen::Vector3d s = tca*v;
            double bb = r0.dot(r0) - s.dot(s);
            double radius = std::max(left.radius, right.radius);
            if (bb < 4*radius*radius)
                result = tca;
        }
    }
    return result;
}

int main()
{
    Eigen::Vector3d vp1 {0,0,0};
    Eigen::Vector3d vv1 {1,0,0};
    Eigen::Vector3d vp2 {12,0,0};
    Eigen::Vector3d vv2 {-1,0,0};
    Particle p1 {1, vp1, vv1};
    Particle p2 {1, vp2, vv2};
    std::cout << timeToCollision(p1, p2) << '\n';
}
#包括
#包括
#包括
#包括“本征/密集”
结构粒子{
双半径;
本征::矢量3D p;
本征::矢量3D v;
};
模板
std::如果启用,则启用
几乎相等(浮点x,浮点y,无符号ulp=1)
{
浮点数max=std::max(std::abs(x),std::abs(y));
返回标准::abs(x-y)=0){
本征::矢量3D s=tca*v;
双bb=r0.点(r0)-s.点(s);
双半径=标准::最大值(左半径,右半径);
如果(bb<4*半径*半径)
结果=tca;
}
}
返回结果;
}
int main()
{
本征::向量3D vp1{0,0,0};
本征::向量3d vv1{1,0,0};
本征::向量3D vp2{12,0,0};
本征::向量3D vv2{-1,0,0};
粒子p1{1,vp1,vv1};
粒子p2{1,vp2,vv2};

std::cout我为一个措辞非常拙劣的问题道歉,这个问题太长太大,很难理解。幸运的是,我发现自己的答案比最初预期的要简单得多

double Particle::timeToCollision(const Particle particle){

    Vector r2=particle.getPosition();
    Vector r1=p;
    Vector v2=particle.getVelocity();
    Vector v1=v;
    Vector r0=r2-r1;
    Vector v=v2-v1;

    double modv;
    double tca = ((--r0).dot(v)) / v.modulusSqr();
    double bsqr;

    double result=0;

    double rColTestx=r0.GetX()+v.GetX()*tca;
    double rColTesty=r0.GetY()+v.GetY()*tca;
    double rColTestz=r0.GetZ()+v.GetZ()*tca;

    Vector rtColTest(rColTestx, rColTesty, rColTestz);


    modv=getVelocity().modulus();

    cout << "start " << endl;

    if(modv<0.0000001){
        cout << "a" << endl;
        result=FLT_MAX;
    }else{
        cout << "b" << endl;

        if (tca < 0) {
            cout << "c" << endl;
            result=FLT_MAX;
        }else{
            cout << "d" << endl;
            Vector s(v.GetX(), v.GetY(), v.GetZ());
            s.Scale(tca);

            cout << getVelocity().GetX() << endl;
            cout << getVelocity().GetY() << endl;
            cout << getVelocity().GetZ() << endl;


           double radsqr= radius*radius;

            bsqr=rtColTest.modulusSqr();

            if (bsqr < 4*radsqr) {
                cout << "e" << endl;
                cout << "collision occurs" << endl;
                result = FLT_MAX;
            } else {
                cout << "collision does not occurs" << endl;
            }

        }

    }
    cout << "fin" << endl;
    return result;

}
双粒子::时间集合(常量粒子){
向量r2=particle.getPosition();
向量r1=p;
向量v2=粒子。getVelocity();
向量v1=v;
向量r0=r2-r1;
向量v=v2-v1;
双modv;
双tca=((-r0).dot(v))/v.modulesSqr();
双bsqr;
双结果=0;
双rColTestx=r0.GetX()+v.GetX()*tca;
双rColTesty=r0.GetY()+v.GetY()*tca;
双rColTestz=r0.GetZ()+v.GetZ()*tca;
向量rtColTest(rColTestx,rColTesty,rColTestz);
modv=getVelocity().模数();

cout什么是
getVelocity().modules()
doingI-see。它是v的L_2-范数。你从来没有为
double bsqr;
设置过值。它有随机内容。但是你使用比较
bsqr<4*radsqr
。你的确切输出是什么?@Maikel
double bsqr;
是b^2的值,它需要是一个双精度,粒子中心1和2之间的距离为时间tca,因此如果它大于4r^2,我知道粒子不会碰撞。在这种情况下,两个粒子的半径都是1。您仍然没有设置它。您也没有设置
结果
。定义您的输出或“您得到垃圾”的含义这对我来说是非常复杂的,因为我仍然把自己放在编程的入门阶段。谢谢你的贡献。看看函数<代码> TimeToCOLISION<代码>。它有你一半的长度,而且是直的。其余的源代码只是为了完成这个例子,使它可以编译。