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