当前位置:网站首页>The calculation and source code of the straight line intersecting the space plane
The calculation and source code of the straight line intersecting the space plane
2022-07-30 07:50:00 【sunset stained ramp】
目的:in writing a graphics project,It is common to encounter situations where three-dimensional planes intersect.It is also the foundation of graphics
A space plane is the same as a straight line,There are two main expressions.
1)General algebraic expression: a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0
2)geometric expression(都是列向量): ( P , N ) (P,N) (P,N),where is a point on the plane, N N N为平面的法向量.Its translation into algebraic expression is ( P − O ) T ∗ N = 0 (P-O)^T*N=0 (P−O)T∗N=0(Needs to be transposed to a row vector)
在后续的计算中,在写C++代码中,Generally inclined to geometric expression.Because it is more intuitive,It is also useful for subsequent calculations.Below I will introduce the algorithm for the intersection of two planes based on the geometric expression,Give lastC++代码.
方法一:
Suppose two planes are :
( P 1 , N 1 ) = > ( X − P 1 ) T ∗ N 1 = 0 ( 1 ) (P_1,N_1)=>(X-P_1)^T*N_1=0 \space \space \space(1) (P1,N1)=>(X−P1)T∗N1=0 (1)
( P 2 , N 2 ) = > ( X − P 2 ) T ∗ N 2 = 0 ( 2 ) (P_2,N_2)=>(X-P_2)^T*N_2=0 \space \space \space(2) (P2,N2)=>(X−P2)T∗N2=0 (2)
There are three situations in which two spatial planes intersect
1:The intersection is a straight line.
2:if the planes are parallel,no intersection.
3:in the case of co-planarity,相交,But not flat.
The following describes the case where the planes intersect as straight lines:
A representation of a straight line where two planes intersect: O 3 O_3 O3 (起始顶点); N 3 N_3 N3(方向).
1)First calculate the direction of the line of intersection N 3 N_3 N3, Because the direction of the line of intersection is found to be perpendicular to bothplane1和plane2The normal vector of the two planes.叉乘 N 1 × N 2 N_1\times N_2 N1×N2,得到如下:
N 3 = N 1 × N 2 ( 3 ) N_3 = N_1\times N_2 \space \space (3) N3=N1×N2 (3)
The red is the normal vector of the obtained plane intersection.(图像中的)
2)Need to find a vertex on the line.It can be any vertex,最好的是 P 1 P_1 P1, P 2 P_2 P2Vertices are projected onto lines P 1 ′ , P 2 ′ P_1',P_2' P1′,P2′的中点.为了方便讲述,This blog is only used P 1 P_1 P1A point projected onto a line P P P,如下图
它是平面 ( P 1 , N 3 ) (P_1,N_3) (P1,N3)and the intersection of the line.将 P 1 , N 3 P_1,N_3 P1,N3写成如下格式:
( P 1 , N 3 ) = > ( X − P 1 ) T ∗ N 3 = 0 ( 4 ) (P_1,N_3)=>(X-P_1)^T*N_3=0 \space \space \space(4) (P1,N3)=>(X−P1)T∗N3=0 (4)
因此用(1)(2)(4)A system of linear equations can be formed as :
组成新的平面.Then use the intersection of three planes to get vertices.如下图示意:
The third normal vector can be expressed as :
( X − P 1 ) T ∗ N 1 = 0 ( X − P 2 ) T ∗ N 2 = 0 ( X − P 1 ) T ∗ N 3 = 0 \begin{gathered} (X-P_1)^T*N_1=0 \\ (X-P_2)^T*N_2=0\\ (X-P_1)^T*N_3=0 \end{gathered} (X−P1)T∗N1=0(X−P2)T∗N2=0(X−P1)T∗N3=0
Unpacking the formula can be obtained as follows:
X T ∗ N 1 = P 1 T ∗ N 1 X T ∗ N 2 = P 2 T ∗ N 2 X T ∗ N 3 = P 1 T ∗ N 3 \begin{gathered} X^T*N_1=P_1^T*N_1 \\ X^T*N_2=P_2^T*N_2\\ X^T*N_3=P_1^T*N_3 \end{gathered} XT∗N1=P1T∗N1XT∗N2=P2T∗N2XT∗N3=P1T∗N3
其中 X X X为未知数,它是向量,The vertices on the line can be obtained by the above formula X ∗ X^* X∗,它的值也就是 P = X ∗ P=X^* P=X∗.
The code for this part will be added later.It is also very simple as follows:
#include<Eigen/Eigen>
#include<iostream>
#include<vector>
/* m=[n1, n2, n3] */
Eigen::Matrix3f ConstructMatrix3fFromVectors(Eigen::Vector3f& n1, Eigen::Vector3f& n2, Eigen::Vector3f& n3)
{
Eigen::Matrix3f m;
m.block<1, 3>(0, 0) = n1;
m.block<1, 3>(1, 0) = n2;
m.block<1, 3>(2, 0) = n3;
return m;
}
float Pnt3d2PlaneDist(Eigen::Vector3f& ppnt, Eigen::Vector3f& pdir, Eigen::Vector3f& pnt)
{
float sd = pdir.norm();
if (sd < 1e-8)
return std::numeric_limits<float>::max();
float sb = std::abs(pdir.dot(ppnt - pnt));
float d = sb / sd;
return d;
}
int ComputeLineFromTwoPlanes(Eigen::Vector3f& src_pnt, Eigen::Vector3f& src_dir,
Eigen::Vector3f& tgt_pnt, Eigen::Vector3f& tgt_dir, Eigen::Vector3f& lpnt, Eigen::Vector3f& ldir)
{
ldir = src_dir.cross(tgt_dir);
//Determines whether two planes are coplanar,或者平行
if ((std::abs(ldir[0]) + std::abs(ldir[1]) + std::abs(ldir[2])) < 1e-6) //Determine whether two planes are parallel
{
float dist = Pnt3d2PlaneDist(tgt_pnt, tgt_dir, src_pnt);
if (dist < 1e-4)
return 0; //共面
else
return 1; //平行面
}
//Calculate the vertices projected onto the line
float pn1 = src_pnt.dot(src_dir);
float pn2 = tgt_pnt.dot(tgt_dir);
float pn3 = src_pnt.dot(ldir);
Eigen::Vector3f b = Eigen::Vector3f(pn1, pn2, pn3);
Eigen::Matrix3f A = ConstructMatrix3fFromVectors(src_dir, tgt_dir, ldir);
lpnt = A.inverse()*b;
return 2;
}
//test adjugate matrix
int main(int argc, char** argv)
{
Eigen::Vector3f sor_c_pnt = Eigen::Vector3f(3.84935, 0.742589, 1.38037);
Eigen::Vector3f sor_c_dir = Eigen::Vector3f(-0.999087, -0.0426946, -0.00180283);
Eigen::Vector3f tgt_c_pnt = Eigen::Vector3f(2.73047, 0.188734, 1.95757);
Eigen::Vector3f tgt_c_dir = Eigen::Vector3f(0.0486091, -0.99881, 0.00407396);
Eigen::Vector3f lpnt, ldir;
ComputeLineFromTwoPlanes(sor_c_pnt, sor_c_dir, tgt_c_pnt, tgt_c_dir, lpnt, ldir);
std::cerr <<"lpnt, dir: " << lpnt.transpose() <<", " << ldir.transpose() << std::endl;
return 0;
}
运行的结果如下:
方法二:
If the expression of the function is a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0. The expressions for the two planes are
a 1 x + b 1 y + c 1 z + d 1 = 0 ( 5 ) a_1x+b_1y+c_1z+d_1=0 \space \space \space (5) a1x+b1y+c1z+d1=0 (5)
a 2 x + b 2 y + c 2 z + d 2 = 0 ( 6 ) a_2x+b_2y+c_2z+d_2=0 \space \space \space (6) a2x+b2y+c2z+d2=0 (6)
It can be written in the form of a vector as :
N 1 T × X = − d 1 ( 7 ) N_1^T \times X=-d_1 \space \space \space (7) N1T×X=−d1 (7)
N 2 T × X = − d 2 ( 8 ) N_2^T \times X=-d_2 \space \space \space (8) N2T×X=−d2 (8)
1:Calculate the straight line direction:使用同样的方法,可以得到 N 3 = N 1 × N 2 N_3=N_1 \times N_2 N3=N1×N2,
2:Find a vertex on the line:Because both planes are vertices,So finding the best vertex is not considered.我们使用youtube上的一个视频,它的介绍如下:
Suppose one of the axes is 0( z = 0 z=0 z=0).Then make up the following formula.
a 1 x + b 1 y + d 1 = 0 a 2 x + b 2 y + d 2 = 0 \begin{gathered} a_1x+b_1y+d_1=0 \\ a_2x+b_2y+d_2=0 \end{gathered} a1x+b1y+d1=0a2x+b2y+d2=0
The resulting vertex is P = ( 0 , y s , z s ) P=(0,y_s,z_s) P=(0,ys,zs)
但是在实际的代码中,Selected for axis 0 0 0need to be considered.我们知道,for an axis,If it contributes almost nothing,可能会出现问题.Just if in the equation a 1 x + b 1 y + c 1 z + d 1 = 0 ( 5 ) a_1x+b_1y+c_1z+d_1=0 \space \space \space (5) a1x+b1y+c1z+d1=0 (5),如果 c 1 = 10000 , a 1 = 0.0001 , b 1 = 100 c_1=10000,a_1=0.0001, b_1=100 c1=10000,a1=0.0001,b1=100,Then it might be possible to find computational x x x会非常大.Such an intersection exists x x xThe on-axis coefficients are very small,means it follows x x x轴平行.Therefore, in the actual calculation of the intersection,We need to calculate the main axis of the plane intersection.It has normal vectors N 3 N_3 N3表示.
如果 N 3 N_3 N3中 x x x系数最大.We assume that the intersection line is P = ( 0 , y , z ) P=(0,y,z) P=(0,y,z),Then enter the equation as :
b 1 y + c 1 z + d 1 = 0 b 2 y + c 2 z + d 2 = 0 \begin{gathered} b_1y+c_1z+d_1=0 \\ b_2y+c_2z+d_2=0 \end{gathered} b1y+c1z+d1=0b2y+c2z+d2=0
如果 N 3 N_3 N3中 y y y系数最大.We assume that the intersection line is P = ( x , 0 , z ) P=(x,0,z) P=(x,0,z)
a 1 x + c 1 z + d 1 = 0 a 2 x + c 2 z + d 2 = 0 \begin{gathered} a_1x+c_1z+d_1=0 \\ a_2x+c_2z+d_2=0 \end{gathered} a1x+c1z+d1=0a2x+c2z+d2=0
如果 N 3 N_3 N3中 z z z系数最大.We assume that the intersection line is P = ( 0 , y , z ) P=(0,y,z) P=(0,y,z)
a 1 y + b 1 z + d 1 = 0 a 2 y + b 2 z + d 2 = 0 \begin{gathered} a_1y+b_1z+d_1=0 \\ a_2y+b_2z+d_2=0 \end{gathered} a1y+b1z+d1=0a2y+b2z+d2=0
具体实现代码如下:
int GetIntersectionLineFromTwoPlanesFunction(Eigen::Vector4f& sor_fun, Eigen::Vector4f& tgt_fn,
Eigen::Vector3f& lpnt3d, Eigen::Vector3f& ldir3d)
{
Eigen::Vector3f sorn = Eigen::Vector3f(sor_fun[0], sor_fun[1], sor_fun[2]);
Eigen::Vector3f tgtn = Eigen::Vector3f(tgt_fn[0], tgt_fn[1], tgt_fn[2]);
Eigen::Vector3f ln = sorn.cross(tgtn);
ldir3d = ln;
//Judge the three axes,Find the largest axis
if ((std::abs(ln[0]) + std::abs(ln[1]) + std::abs(ln[2])) < 1e-6) //Determine whether two planes are parallel
{
Eigen::Vector3f sm_pnt;
SamplePnt3dFromPlaneFnc(sor_fun, sm_pnt);
float dist = Pnt3d2PlaneDist(tgt_fn, sm_pnt);
if (dist < 1e-4)
return 0; //共面
else
return 1; //平行面
}
int max_cn = FindMaxCoordFromVec3D(ln);
float d1, d2;
d1 = sor_fun[3];
d2 = tgt_fn[3];
if (max_cn == 0)
{
lpnt3d[0] = 0.0f;
lpnt3d[1] = (d2*sorn[2] - d1*tgtn[2]) / ln[0]; //ln[0]为b_1,c_1和b_2,c_2的矩阵det|A|
lpnt3d[2] = (d1*tgtn[1] - d2*sorn[1]) / ln[0];
return 2;
}
else if (max_cn == 1)
{
lpnt3d[0] = (d1*tgtn[2] - d2*sorn[2]) / ln[1]; //ln[1]为a_1,c_1和a_2,c_2的矩阵det|A|
lpnt3d[1] = 0.0f;
lpnt3d[2] = (d2*sorn[0] - d1*tgtn[0]) / ln[1];
return 3;
}
else
{
lpnt3d[0] = (d2*sorn[1] - d1*tgtn[1]) / ln[2]; //ln[2]为a_1,b_1和a_2,b_2的矩阵det|A|
lpnt3d[1] = (d1*tgtn[0] - d2*sorn[0]) / ln[2];
lpnt3d[2] = 0.0f;
return 4;
}
}
FindMaxCoordFromVec3D(ln);This is to find the longest axis.
如果上述2,3Case planes are parallel or coplanar:
First get a point on the plane,Then calculate the distance from this vertex to the plane.因此如下:
SamplePnt3dFromPlaneFnc(sor_fun, sm_pnt);This is going to any point on the plane
Pnt3d2PlaneDist(tgt_fn, sm_pnt); 计算点到平面的距离.It is used to determine whether two faces are coplanar.
There is also a better way to intersect planes,But I haven't fully understood it yet,The link to paste it is below:
http://tbirdal.blogspot.com/2016/10/a-better-approach-to-plane-intersection.html
边栏推荐
- STL源码剖析:bound friend template friend代码测试和理解
- mysql常用命令以及mysqldump备份
- 测开基础知识01
- openstack删除计算节点
- MYSQL-GROUP BY 用法 全网最精,通熟易懂的话解释
- 让百度地图生成器里的“标注”内容展开--解决方案
- Distance calculation from space vertex to straight line and its source code
- Test Development Engineer Growth Diary 008 - Talking About Some Bugs/Use Case Management Platform/Collaboration Platform
- 黑盒测试的概念及测试方法
- The Society of Mind - Marvin Minsky
猜你喜欢
Camera coordinate system, world coordinate system, pixel coordinate system conversion, and Fov conversion of OPENGLDEFocal Length and Opengl
Required request body is missing 问题解决
Multithreading basics (multithreaded memory, security, communication, thread pools and blocking queues)
(GGG)JWT
RAID磁盘阵列
分布式系统中的开创者—莱斯利·兰伯特
The CTO said I was not advised to use SELECT *, why is that?
05-Theos
Advanced multi-threading (CountDownLatch, deadlock, thread-safe collection class)
不会吧,Log4j 漏洞还没有完全修复?
随机推荐
Software Testing Terminology - Scenario Testing
MySQL什么时候用表锁,什么时候用行锁?
远程连接服务器的MySql
Test Development Engineer Growth Diary 008 - Talking About Some Bugs/Use Case Management Platform/Collaboration Platform
Rapidly develop GraphScope graph analysis applications
MongoDB - query
Required request body is missing 问题解决
空间顶点到平面的距离计算的证明及其源码
Mastering JESD204B (3) – Debugging of AD6676
让百度地图生成器里的“标注”内容展开--解决方案
Test the basics 02
图解关系数据库设计思想,这也太形象了
AI can identify race from X-rays, but no one knows why
Selenium02
MongoDB-介绍,数据类型,基本语句
Swagger使用方式,告别postman
STL源码剖析:class template explicit specialization代码测试和理解
手机端滚动至页面指定位置
LVM and disk quotas
(GGG)JWT