3D线段和平面相交 - 续

3D Line Segment and Plane Intersection - Contd

本文关键字:面相 平面 3D      更新时间:2023-10-16

在Krlzlx的建议之后,我将其发布为一个新问题。

从这里:

3D线段和平面相交

我对此算法有问题,我已经实现了它:

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的大小太大了?

pseudocode(不需要向量归一化):

 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)