c++ - 3D 线段和平面相交 - 续

标签 c++ algorithm math vector collision-detection

根据 krlzlx 的建议,我将其发布为一个新问题。

从这里开始:

3D Line Segment and Plane Intersection

这个算法我有问题,我是这样实现的:

template <class T>
class AnyCollision {
   public:
    std::pair<bool, T> operator()(Point3d &ray, Point3d &rayOrigin, Point3d &normal, Point3d &coord) const {

    // get d value
    float d = (normal.x * coord.x) + (normal.y * coord.y) + (normal.z * coord.z);

    if (((normal.x * ray.x) + (normal.y * ray.y) + (normal.z * ray.z)) == 0) {
        return std::make_pair(false, T());
    }

    // Compute the X value for the directed line ray intersecting the plane
    float a = (d - ((normal.x * rayOrigin.x) + (normal.y * rayOrigin.y) + (normal.z * rayOrigin.z)) / ((normal.x * ray.x) + (normal.y * ray.y) + (normal.z * ray.z)));

    // output contact point
    float rayMagnitude = (sqrt(pow(ray.x, 2) + pow(ray.y, 2) + pow(ray.z, 2)));
    Point3d rayNormalised((ray.x / rayMagnitude), (ray.y / rayMagnitude), (ray.z / rayMagnitude));
    Point3d contact((rayOrigin.x + (rayNormalised.x * a)), (rayOrigin.y + (rayNormalised.y * a)), (rayOrigin.z + (rayNormalised.z * a))); //Make sure the ray vector is normalized
    return std::make_pair(true, contact);

};

Point3d 定义为:

class Point3d {
   public:
    double x;
    double y;
    double z;

    /**
     * constructor
     *
     * 0 all elements
     */
    Point3d() {
        x = 0.0;
        y = 0.0;
        z = 0.0;
    }

我被迫使用这个结构,因为在更大的系统中我运行的组件是这样定义的,它不能改变。

我的代码编译正常,但测试时我得到了不正确的点值。 x, y, z 的比例是正确的,但大小是错误的。

例如如果:

rayOrigin.x = 0;
rayOrigin.y = 0;
rayOrigin.z = 0;

ray.x = 3;
ray.y = -5;
ray.z = 12;

normal.x = -3;
normal.y = 12;
normal.z = 0;

coord.x = 7;
coord.y = -5;
coord.z = 10;

我希望重点是:

(0.63, 1.26, 1.89)

但是,它是:

(3.52, -5.87, 14.09)

5.09 级太大了。

我还测试了:

rayOrigin.x = 0;
rayOrigin.y = 0;
rayOrigin.z = 0;

ray.x = 2;
ray.y = 3;
ray.z = 3;

normal.x = 4;
normal.y = 1;
normal.z = 0;

p0.x = 2;
p0.y = 1;
p0.z = 5;

我希望重点是:

(1.64, 2.45, 2.45)

但是,它是:

(3.83761, 5.75642, 5.75642)

2.34 级太大了?

最佳答案

伪代码(不需要 vector 归一化):

 Diff = PlaneBaseCoordinate - RayOrigin
 d = Normal.dot.Diff
 e = Normal.dot.RayVector 

if (e)
   IntersectionPoint = RayOrigin + RayVector * d / e
otherwise
  ray belongs to the plane or is parallel

快速检查:

Ray (0,0,0)  (2,2,2)    //to catch possible scale issues
Plane (0,1,0) (0,3,0)   //plane y=1
Diff = (0,1,0)
d = 3
e = 6
IntersectionPoint = (0,0,0) + (2,2,2) * 3 / 6 = (1, 1, 1) 

关于c++ - 3D 线段和平面相交 - 续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47649507/

相关文章:

c++ - ADO 命令说我正在插入 NULL,而我不是

c++ - 模板特化结构大小

algorithm - 算法复杂度的 Big Oh 表示法

c# - 矩阵的左上象限的最大和可以通过反转行和列来形成

vb.net - 在数组中查找正方形

c++ - 如何加快这个盒子堆叠变化?

c++ - 树中两个节点之间的最小距离

java - Math.atan 不工作

javascript - 计算两点之间的最短路径

c++ - 相对素数