c++ - 如何在平面上获得三个非共线点? - C++

标签 c++ math computational-geometry linear-algebra

我正在尝试实现线平面相交算法。根据Wikipedia为此,我需要平面上的三个非共线点。

因此我尝试实现 this algorithm然而,在 C++ 中。肯定有问题,因为我可以选择任何 x 和 y 坐标并且它们将适合平面是没有意义的。如果平面是垂直的并且沿 x 轴怎么办? y=1 的点不会在平面上。

我意识到这个问题已经在 StackOverflow 上发布了很多,而且我看到了很多解决方案,其中平面由 3 个点定义。但是我只有一个普通的和一个位置。在我整理出我的非共线点查找器之前,我无法测试我的线面相交算法。

现在的问题是,我正在除以 normal.z,当 normal.z 为 0 时,这显然不起作用。

我正在测试这个平面:Plane* p = new Plane(Color(), Vec3d(0.0,0.0,0.0), Vec3d(0.0,1.0,0.0));//第二个参数:position,第三个参数:normal

当前代码给出了这个不正确的答案:

{0 , 0 , 0} // alright, this is the original
{12.8377 , 17.2728 , -inf} // obviously this is not a non-colinear point on the given plane

这是我的代码:

std::vector<Vec3d>* Plane::getThreeNonColinearPoints() {
    std::vector<Vec3d>* v = new std::vector<Vec3d>();

    v->push_back(Vec3d(position.x, position.y, position.z)); // original position can serve as one of the three non-colinear points.

    srandom(time(NULL));

    double rx, ry, rz, start;

    rx = Plane::fRand(10.0, 20.0);
    ry = Plane::fRand(10.0, 20.0);
    // Formula from here: http://en.wikipedia.org/wiki/Plane_(geometry)#Definition_with_a_point_and_a_normal_vector
    // nx(x-x0) + ny(y-y0) + nz(z-z0) = 0
    // |-----------------| <- this is "start"
    //I'll try to insert position as x0,y0,z0 and normal as nx,ny,nz, and solve the equation
    start = normal.x * (rx - position.x) + normal.y * (ry - position.y);
    // nz(z-z0) = -start
    start = -start;
    // (z-z0) = start/nz
    start /= normal.z; // division by zero
    // z = start+z0
    start += position.z;
    rz = start;

    v->push_back(Vec3d(rx, ry, rz));

    // TODO one more point

    return v;
}

我意识到我可能试图解决这个完全错误的问题。如果是这样,请链接此的具体实现。当我看到如此多的线-面相交实现时,我确信它一定存在。

提前致谢。

最佳答案

平面可以用多种方式定义。通常使用平面上的一个点和一个法 vector 。要从三个点 (P1, P2, P3 ) 获取法 vector ,取三角形边的叉积

P1 = {x1, y1, z1};
P2 = {x2, y2, z2};
P3 = {x3, y3, z3};

N = UNIT( CROSS( P2-P1, P3-P1 ) );
Plane P = { P1, N }

相反,要从一个点 P1 和正常的 N 到三个点,您可以从任何方向 G 开始 不是 沿着正常的 N 这样 DOT(G,N)!=0。则沿平面的两个正交方向为

//try G={0,0,1} or {0,1,0} or {1,0,0}
G = {0,0,1};
if( MAG(CROSS(G,N))<TINY ) { G = {0,1,0}; }
if( MAG(CROSS(G,N))<TINY ) { G = {1,0,0}; }
U = UNIT( CROSS(N, G) );  
V = CROSS(U,N);
P2 = P1 + U;
P3 = P1 + V;

一条线由一个点和一个方向定义。通常有两个点 (Q1, Q2) 定义线

Q1 = {x1, y1, z1};
Q2 = {x2, y2, z2};
E = UNIT( Q2-Q1 );
Line L = { Q1, E }

直线和平面的交点由与平面相交的直线 r=Q1+t*E 上的点定义,这样 DOT(r-P1,N)= 0。这对于沿线的标量距离 t 求解为

t = DOT(P1-Q1,N)/DOT(E,N);

位置为

r = Q1+(t*E);

注意:DOT() 返回两个 vector 的点积,CROSS() 返回叉积,UNIT() 单位 vector (幅度=1)。

DOT(P,Q) = P[0]*Q[0]+P[1]*Q[1]+P[2]*Q[2];
CROSS(P,Q) = { P[1]*Q[2]-P[2]*Q[1], P[2]*Q[0]-P[0]*Q[2], P[0]*Q[1]-P[1]*Q[0] };
UNIT(P) = {P[0]/sqrt(DOT(P,P)), P[1]/sqrt(DOT(P,P)), P[2]/sqrt(DOT(P,P))};
t*P =  { t*P[0], t*P[1], t*P[2] };
MAG(P) = sqrt(P[0]*P[0]+P[1]*P[1]+P[2]*P[2]);

关于c++ - 如何在平面上获得三个非共线点? - C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8387199/

相关文章:

c++ - 如何在 QImage 中显示此数据缓冲区

python - 使用 Sympy 集成时遇到问题

c++ - 将一个点变成另一个点的算法

c++ - C - 将指针转换为指向 void 的指针

c++ - 如何编译同时使用 MPI 和 HDF5 的 C++ 文件?

c++ - 对于 C++ 中的指针,delete 命令真正对内存有什么作用?

javascript - 用 JavaScript 模拟非洲村庄的分形

javascript - 画出三 Angular 形的高

algorithm - 找到具有最大 top-K 点总和的区域

algorithm - 如果每个点的每个坐标都是有理数,则 O(n) 时间内的凸包