我认为这是一个相当复杂的问题,我希望我可以将它放入足够小的空间以使其易于理解。我现在正在编写代码
模拟盒子内的理想气体颗粒。我计算两个粒子是否会碰撞,计算出它们到达最近点的时间。 (使用他们碰撞的例子。)
在这部分代码中,我需要找出它们是否会碰撞两个粒子,然后计算它们在什么时间碰撞以及它们如何碰撞等。 因此,对于我的两个颗粒:
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开头和字母等,它们是我的代码退出测试的简单检查。)
给出方程:
我已经编写了代码来为我做点积和模数:
其中
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;
}
我有计算几个方面的等式,tca
指的是最接近的时间。
正如我在代码中所写,我需要检查b > 4 r^2
是否已成功,我已经做了一些尝试,并编写了X
的{{1}},Y
和Z
组件出去但是我得到了垃圾回答。
我只是需要帮助来确定我是否已经犯了错误或者我应该走的方向。
我之前的所有代码都按预期工作,并且我已经为每个代码编写了多个测试。
如果您认为我遗漏了任何信息,请通知我。
任何帮助非常感谢。
答案 0 :(得分:1)
您的代码中有几处错误。您从未将result
设置为与0
或FLT_MAX
不同的值。你也永远不会计算bsqr
。我想如果bsqr < 4r^2
发生碰撞而不是相反。 (我不明白为什么4r^2
而不是r^2
,但没关系。由于你隐藏了矢量实现,我使用了一个通用的矢量库。我还建议不要使用手工制作的东西。看看犰狳或igen。
在这里,您将尝试使用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';
}
答案 1 :(得分:0)
我对一个措辞非常糟糕的问题表示道歉,这个问题很长而且很笨重。幸运的是,我发现自己的答案比最初预期的要容易得多。
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;
}
对不起它的大部分代码。 FLT_MAX也来自cfloat lib。在我的问题中,我没有对此进行统计。我发现这适用于我在纸上计算的几个例子。
要明确,return result
和result=0
是任意的。我后来编辑返回时间,但这部分并不需要或想要。