How to get three non-colonial points on the plane? - C ++

I am trying to implement a linear plane intersection algorithm. According to Wikipedia, I need three non-colonial points on a plane to do this.

So I tried to implement this algorithm in C ++. Something is definitely wrong, because it makes no sense that I can choose any x and y coordinates, and they will fit the plane. What if the plane is vertical and along the x axis? Then no point with y = 1 would be in the plane.

I understand that this problem has been posted a lot on StackOverflow, and I see many solutions where the plane is defined by three points. But I have only a normal position. And I can’t check my algorithm for crossing the line plane before disassembling my non-colonial point finder.

The problem right now is that I am dividing by normal.z, and this obviously will not work when normal.z is 0.

I am testing this plane: Plane * p = new Plane (Color (), Vec3d (0.0,0.0,0.0.0), Vec3d (0.0,1.0,0.0)); // second parameter: position, third parameter: normal

The current code gives the wrong answer:

{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 

Here is my code:

 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; } 

I understand that maybe I'm trying to solve this problem completely wrong. If yes, indicate the specific implementation of this. I am sure that it should exist when I see so many line crossing implementations.

Thanks in advance.

+4
source share
3 answers

A plane can be defined in several ways. A point on the plane and a normal vector are usually used. To get a normal vector of three points ( P1 , P2 , P3 ), we take the transverse product of the side of the triangle

 P1 = {x1, y1, z1}; P2 = {x2, y2, z2}; P3 = {x3, y3, z3}; N = UNIT( CROSS( P2-P1, P3-P1 ) ); Plane P = { P1, N } 

The opposite, to go from point P1 and normal N to three points, you start from any direction G not in normal N , so DOT(G,N)!=0 . Two orthogonal directions along the plane then

 //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; 

The line is determined by the point and direction. Usually two points ( Q1 , Q2 ) define a line

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

The intersection of the line and the plane is determined by a point on the line r=Q1+t*E , which intersects the plane such that DOT(r-P1,N)=0 . This is solved for the scalar distance t along the line as

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

and location as

 r = Q1+(t*E); 

NOTE. DOT() returns the dot product of two vectors, CROSS() cross product and UNIT() unit vector (with magnitude = 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]); 
+5
source

One approach that you can easily implement is to see where the plane intersects the coordinate axes. For the plane defined by the equation aX + bY + cZ - d = 0 , hold two variables at point 0 and solve for the third. Thus, the solutions will be (assuming a , b , c and d all non-zero):

 (d/a, 0, 0) (0, d/b, 0) (0, 0, d/c) 

You will need to consider cases when one or more coefficients are 0, so you will not get degenerate or colline solutions. As an example, if exactly one of the coefficients is 0 (say a=0 ), you use instead

 (1, d/b, 0) (0, d/b, 0) (0, 0, d/c) 

If exactly two of the coefficients are 0 (say a=0 and b=0 ), you can use:

 (1, 0, d/c) (0, 1, d/c) (0, 0, d/c) 

If d=0 , the plane intersects the three axes at the origin, and you can use:

 (1, 0, -a/c) (0, -c/b, 1) (-b/a, 1, 0) 

You will need to work out simulation cases for d and exactly one other coefficient is 0, as well as d , and the other two are 0. There should be a total of 16 cases, but there are a few things that come to mind that should make this somewhat more manageable .

+2
source

Where N=(Nx,Ny,Nz) is normal, you can project the points N , (Ny,Nz,Nx) , (Nz,Nx,Ny) onto the plane: they are guaranteed to be different.

Alternatively, if P and Q are in the plane, P+t(QP)xN also in the plane for any t!=0 , where x is the transverse product.

Alternatively, if M!=N is an arbitrary vector, K=MxN and L=KxN are collinear with the plane, and any point P on the plane can be written as p=Origin+sK+tL for some s,t .

+1
source

Source: https://habr.com/ru/post/1384721/


All Articles