我的大脑一直在我一直在研究的线段-汽缸相交例程上融化。
/// Line segment VS <cylinder>
// - cylinder (A, B, r) (start point, end point, radius)
// - line has starting point (x0, y0, z0) and ending point (x0+ux, y0+uy, z0+uz) ((ux, uy, uz) is "direction")
// => start = (x0, y0, z0)
// dir = (ux, uy, uz)
// A
// B
// r
// optimize? (= don't care for t > 1)
// <= t = "time" of intersection
// norm = surface normal of intersection point
void CollisionExecuter::cylinderVSline(const Ogre::Vector3& start, const Ogre::Vector3& dir, const Ogre::Vector3& A, const Ogre::Vector3& B, const double r,
const bool optimize, double& t, Ogre::Vector3& normal) {
t = NaN;
// Solution : http://www.gamedev.net/community/forums/topic.asp?topic_id=467789
double cxmin, cymin, czmin, cxmax, cymax, czmax;
if (A.z < B.z) { czmin = A.z - r; czmax = B.z + r; } else { czmin = B.z - r; czmax = A.z + r; }
if (A.y < B.y) { cymin = A.y - r; cymax = B.y + r; } else { cymin = B.y - r; cymax = A.y + r; }
if (A.x < B.x) { cxmin = A.x - r; cxmax = B.x + r; } else { cxmin = B.x - r; cxmax = A.x + r; }
if (optimize) {
if (start.z >= czmax && (start.z + dir.z) > czmax) return;
if (start.z <= czmin && (start.z + dir.z) < czmin) return;
if (start.y >= cymax && (start.y + dir.y) > cymax) return;
if (start.y <= cymin && (start.y + dir.y) < cymin) return;
if (start.x >= cxmax && (start.x + dir.x) > cxmax) return;
if (start.x <= cxmin && (start.x + dir.x) < cxmin) return;
}
Ogre::Vector3 AB = B - A;
Ogre::Vector3 AO = start - A;
Ogre::Vector3 AOxAB = AO.crossProduct(AB);
Ogre::Vector3 VxAB = dir.crossProduct(AB);
double ab2 = AB.dotProduct(AB);
double a = VxAB.dotProduct(VxAB);
double b = 2 * VxAB.dotProduct(AOxAB);
double c = AOxAB.dotProduct(AOxAB) - (r*r * ab2);
double d = b * b - 4 * a * c;
if (d < 0) return;
double time = (-b - sqrt(d)) / (2 * a);
if (time < 0) return;
Ogre::Vector3 intersection = start + dir * time; /// intersection point
Ogre::Vector3 projection = A + (AB.dotProduct(intersection - A) / ab2) * AB; /// intersection projected onto cylinder axis
if ((projection - A).length() + (B - projection).length() > AB.length()) return; /// THIS IS THE SLOW SAFE WAY
//if (projection.z > czmax - r || projection.z < czmin + r ||
// projection.y > cymax - r || projection.y < cymin + r ||
// projection.x > cxmax - r || projection.x < cxmin + r ) return; /// THIS IS THE FASTER BUGGY WAY
normal = (intersection - projection);
normal.normalise();
t = time; /// at last
}
我曾想过这种方法可以加快发现交点的投影是否位于圆柱体长度内的速度。但是,它不起作用,我也无法真正获得它,因为它看起来是如此合乎逻辑:
如果投影点的x,y或z坐标不在圆柱范围内,则应将其视为外部。看来这在实践中不起作用。
任何帮助将不胜感激!
干杯,
比尔·科西亚斯
编辑:似乎问题与边界情况有关,即,当圆柱体平行于轴之一时。舍入误差进入方程式,“优化”将停止正常工作。
也许,如果逻辑是正确的,那么通过插入一些容忍度(如:)可以解决问题:
if (projection.z > czmax - r + 0.001 || projection.z < czmin + r - 0.001 || ... etc...
最佳答案
圆柱是圆形的,对吗?您可以变换坐标,以使圆柱的中心线充当Z轴。然后,您将遇到一条直线与一个圆相交的二维问题。相交点将沿线的长度以从0到1的参数表示,因此您可以计算它们在该坐标系中的位置,并与圆柱体的顶部和底部进行比较。
您应该能够以封闭形式进行所有操作。没有容忍度。当然,您将获得奇异和虚构的解决方案。您似乎已经想到了所有这些,所以我想我不确定这个问题是什么。
关于c++ - 尝试优化直线与圆柱相交,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4078401/