求解直线与平面的交点

微信公众号:幼儿园的学霸

目录

文章目录

  • 求解直线与平面的交点
  • 目录
  • 前言
  • 数学模型推导
  • 编程实现
  • 参考资料

前言

直线与平面的交点求解相关的内容在网上已经有很多资料进行介绍,目前所看到的博文在数学模型建立上都是正确的,但是其编程实现却存在问题,导致只有部分情况下能够正确求出直线与平面的交点,另外一些情况下求出的交点却是错误的.本文对原理进行推导并实现正确的编码.

数学模型推导

已知经过两点 P 1 ( x 1 , y 1 , z 1 ) , P 2 ( x 2 , y 2 , z 2 ) P_1(x_1,y_1,z_1),P_2(x_2,y_2,z_2) P1​(x1​,y1​,z1​),P2​(x2​,y2​,z2​)的直线与平面 a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0相交于点P,求点P的坐标.
该问题几何模型如下:

求解该问题的一种方法是建立方程组,联立求解点的坐标.该方法在数学实现上非常直观,但是求方程组的解稍微麻烦.

另一种是通过向量法进行求解.推导过程如下:
设 m = P 1 P → P 1 P 2 → , 则 O P → = O P 1 → + P 1 P → = O P 1 → + m ∗ P 1 P 2 → 设 m = \frac{\overrightarrow {P_1P}}{\overrightarrow{P_1P_2}},则 \\ \overrightarrow {OP} = \overrightarrow {OP_1} + \overrightarrow {P_1P} =\overrightarrow {OP_1} + m*\overrightarrow {P_1P_2} 设m=P1​P2​ ​P1​P ​​,则OP =OP1​ ​+P1​P ​=OP1​ ​+m∗P1​P2​ ​
其中:
m = P 1 P → P 1 P 2 → = P 1 D → P 1 D 2 → = ∣ P 1 D → ∣ ∣ P 1 D 2 → ∣ m = \frac{\overrightarrow {P_1P}}{\overrightarrow{P_1P_2}} = \frac{\overrightarrow {P_1D}}{\overrightarrow{P_1D_2}} = \frac{\lvert \overrightarrow {P_1D}\rvert } {\lvert \overrightarrow{P_1D_2} \rvert} m=P1​P2​ ​P1​P ​​=P1​D2​ ​P1​D ​​=∣P1​D2​ ​∣∣P1​D ​∣​

∣ P 1 D → ∣ \lvert \overrightarrow {P_1D}\rvert ∣P1​D ​∣为点P1到平面的距离,计算公式如下:
∣ P 1 D → ∣ = ∣ a x 1 + b y 1 + c z 1 + d ∣ a 2 + b 2 + c 2 \lvert \overrightarrow {P_1D}\rvert = \frac{\lvert {ax_1+by_1+cz_1+d} \rvert} {\sqrt{a^2+b^2+c^2}} ∣P1​D ​∣=a2+b2+c2 ​∣ax1​+by1​+cz1​+d∣​
另外:
∣ P 1 D 2 → ∣ = ∣ P 1 P 2 → ∣ c o s θ = ∣ P 1 P 2 → ∣ ∗ ∣ P 1 P 2 → ⋅ P 1 D 2 → ∣ ∣ P 1 P 2 → ∣ ∣ P 1 D 2 → ∣ = ∣ P 1 P 2 → ⋅ P 1 D 2 → ∣ P 1 D 2 → ∣ ∣ {\lvert \overrightarrow{P_1D_2} \rvert} = {\lvert \overrightarrow{P_1P_2} \rvert}cos{\theta} = {\lvert \overrightarrow{P_1P_2} \rvert} * \frac{\lvert{\overrightarrow{P_1P_2} \cdot \overrightarrow{P_1D_2} } \rvert} {\lvert{\overrightarrow{P_1P_2}} \rvert \lvert{\overrightarrow{P_1D_2}} \rvert} \\ =\lvert{ \overrightarrow{P_1P_2} \cdot \frac{\overrightarrow{P_1D_2}}{\lvert{\overrightarrow{P_1D_2}} \rvert} } \rvert ∣P1​D2​ ​∣=∣P1​P2​ ​∣cosθ=∣P1​P2​ ​∣∗∣P1​P2​ ​∣∣P1​D2​ ​∣∣P1​P2​ ​⋅P1​D2​ ​∣​=∣P1​P2​ ​⋅∣P1​D2​ ​∣P1​D2​ ​​∣

显然, P 1 D 2 → ∣ P 1 D 2 → ∣ \frac{\overrightarrow{P_1D_2}}{\lvert{\overrightarrow{P_1D_2}} \rvert} ∣P1​D2​ ​∣P1​D2​ ​​表示平面的单位法向量,其用坐标的形式表示如下:
P 1 D 2 → ∣ P 1 D 2 → ∣ = ( a , b , c ) a 2 + b 2 + c 2 \frac{\overrightarrow{P_1D_2}}{\lvert{\overrightarrow{P_1D_2}} \rvert} = \frac{(a,b,c)}{\sqrt{a^2+b^2+c^2}} ∣P1​D2​ ​∣P1​D2​ ​​=a2+b2+c2 ​(a,b,c)​
因此:
∣ P 1 D 2 → ∣ = ∣ P 1 P 2 → ⋅ P 1 D 2 → ∣ P 1 D 2 → ∣ ∣ = P 1 D 2 → ∣ P 1 D 2 → ∣ = ∣ a ( x 2 − x 1 ) + b ( y 2 − y 1 ) + c ( z 2 − z 1 ) a 2 + b 2 + c 2 ∣ {\lvert \overrightarrow{P_1D_2} \rvert} = \lvert{ \overrightarrow{P_1P_2} \cdot \frac{\overrightarrow{P_1D_2}}{\lvert{\overrightarrow{P_1D_2}} \rvert} } \rvert = \frac{\overrightarrow{P_1D_2}}{\lvert{\overrightarrow{P_1D_2}} \rvert} \\ = \lvert{ \frac{a(x_2-x_1)+b(y_2-y_1)+c(z_2-z_1)}{\sqrt{a^2+b^2+c^2}} } \rvert ∣P1​D2​ ​∣=∣P1​P2​ ​⋅∣P1​D2​ ​∣P1​D2​ ​​∣=∣P1​D2​ ​∣P1​D2​ ​​=∣a2+b2+c2 ​a(x2​−x1​)+b(y2​−y1​)+c(z2​−z1​)​∣

综上,可得:
m = ∣ P 1 D → ∣ ∣ P 1 D 2 → ∣ = ∣ a x 1 + b y 1 + c z 1 + d a ( x 2 − x 1 ) + b ( y 2 − y 1 ) + c ( z 2 − z 1 ) ∣ O P → = O P 1 → + P 1 P → = O P 1 → + m ∗ P 1 P 2 → 或 ( x , y , z ) = ( x 1 , y 1 , z 1 ) + m ∗ ( x 2 − x 1 , y 2 − y 1 , z 2 − z 1 ) m = \frac{\lvert \overrightarrow {P_1D}\rvert } {\lvert \overrightarrow{P_1D_2} \rvert} = \lvert{\frac{ax_1+by_1+cz_1+d}{a(x_2-x_1)+b(y_2-y_1)+c(z_2-z_1)} } \rvert \\ \overrightarrow {OP} = \overrightarrow {OP_1} + \overrightarrow {P_1P} =\overrightarrow {OP_1} + m*\overrightarrow {P_1P_2} \\ 或 (x,y,z) = (x_1,y_1,z_1) + m*(x_2-x_1,y_2-y_1,z_2-z_1) m=∣P1​D2​ ​∣∣P1​D ​∣​=∣a(x2​−x1​)+b(y2​−y1​)+c(z2​−z1​)ax1​+by1​+cz1​+d​∣OP =OP1​ ​+P1​P ​=OP1​ ​+m∗P1​P2​ ​或(x,y,z)=(x1​,y1​,z1​)+m∗(x2​−x1​,y2​−y1​,z2​−z1​)

编程实现

/*!* 求直线与平面的交点* @param p1* @param p2 直线经过的两点p1,p2* @param plane 平面参数 ax+by+cz+d=0* @param crossP 交点* @return true--直线与平面相交;false--直线与平面平行(或者位于平面内)* @author liheng*/
bool GetLinePlaneCrossP(Eigen::Vector3f p1,Eigen::Vector3f p2,const Eigen::Vector4f& plane,Eigen::Vector3f& crossP)
{//求分子P1Dauto P1D = plane[0]*p1[0] + plane[1]*p1[1] + plane[2]*p1[2]+plane[3];//ax1+by1+cz1+d//or采用向量点乘方式P1D = std::abs( P1D );auto P2D = plane[0]*p2[0] + plane[1]*p2[1] + plane[2]*p2[2]+plane[3];P2D = std::abs( P2D );//保证P2离平面比较近if( P1D<P2D ){std::swap(p1,p2);//点交换P1D = P2D;//距离交换}const Eigen::Vector3f P1P2 = p2-p1;//求分母P1D2auto P1D2 = plane[0]*P1P2[0] + plane[1]*P1P2[1] + plane[2]*P1P2[2];P1D2 = std::abs(P1D2);if( P1D2<FLT_EPSILON )return false;//平行auto m = P1D/P1D2;crossP = p1 + m*P1P2;return true;
}下面函数同样可以
///*!
// * 求直线与平面的交点
// * @param p1
// * @param p2 直线经过的两点p1,p2
// * @param plane 平面参数 ax+by+cz+d=0
// * @param crossP 交点
// * @return true--直线与平面相交;false--直线与平面平行(或者位于平面内)
// * @author liheng
// */
//bool GetLinePlaneCrossP(const Eigen::Vector3f& p1,const Eigen::Vector3f& p2,const Eigen::Vector4f& plane,Eigen::Vector3f& crossP)
//{
//    //求分子P1D
//    auto P1D = plane[0]*p1[0] + plane[1]*p1[1] + plane[2]*p1[2]+plane[3];//ax1+by1+cz1+d//or采用向量点乘方式
//
//    const Eigen::Vector3f P1P2 = p2-p1;
//
//    //求分母P1D2
//    auto P1D2 = plane[0]*P1P2[0] + plane[1]*P1P2[1] + plane[2]*P1P2[2];
//    if( std::abs(P1D2)<FLT_EPSILON )
//        return false;//平行
//
//    auto m = P1D/P1D2;
//    crossP = p1 - m*P1P2;//注意:此处是 负号- 同时求m时无绝对值符号
//
//    return true;
//}int main(int argc, char ** argv )
{Eigen::Vector3f p1(0,0,5),p2(0,0,-10),crossP;Eigen::Vector4f plane(0,0,1,0);//z=0GetLinePlaneCrossP(p1,p2,plane,crossP);std::cout<<"crossP:"<<crossP<<std::endl;return 0;
}

上面的2个函数均可以求出直线与平面交点.不论输入的两点在平面两侧或位于平面同一侧,以及两点到平面的距离排序.

粗略的python版本如下

#!/usr/bin/env python3
#coding=utf-8#============================#
#Program:main.py
#
#Date:20-6-23
#Author:liheng
#Version:V1.0
#============================#import numpy as npx1,y1,z1 = 0,0,10
x2,y2,z2 = 0,0,5
a,b,c,d = 0,0,1,0# p1 = np.array([x1,y1,z1])#
# p2 = np.array([x2,y2,z2])
# plane_normal = np.array([a,b,c]) #a,b,c,d平面方程系数
#
# P1D = np.vdot(p1,plane_normal)+d
# P1D = np.abs(P1D)
#
# P2D = np.vdot(p2,plane_normal)+d
# P2D = np.abs(P2D)
#
# if P1D<P2D:#点1靠近平面,交换点1 2
#     p1,p2 = p2,p1
#     P1D = P2D
#
# P1D2 = np.vdot(p2-p1,plane_normal)
# P1D2 = np.abs(P1D2)
#
# n = P1D / P1D2
# p = p1 + n*(p2- p1)#所求交点
# print(p)//or
p1 = np.array([x1,y1,z1])#
p2 = np.array([x2,y2,z2])
plane_normal = np.array([a,b,c]) #a,b,c,d平面方程系数P1D = np.vdot(p1,plane_normal)+d
P1D2 = np.vdot(p2-p1,plane_normal)n = P1D / P1D2
p = p1 - n*(p2- p1)#所求交点
print(p)

参考资料

1求直线与平面的交点
2.空间内直线于平面交点

求解直线与平面的交点相关推荐

  1. Unity求一条直线与平面的交点

    这个是面试官经常考的一个问题,我们先把它变成一个数学问题. 已知一个平面上的一点P0和法向量n,一条直线上的点L0和方向L,求该直线与该平面的交点P 如下图 首先我们分析一下我们知道平面和直线的法向量 ...

  2. Revit求直线与平面的交点

    直线与平面的交点有两种情况,交点在平面内或平面外,计算出交点后需确定此交点是否在已知平面内. 代码如下: /// <summary> /// 计算直线与平面的交点 /// </sum ...

  3. 计算直线与平面的交点

    设直线上一点 p,以及其方向 dir 则直线公式可写作  p+t*dir 设平面法向量为nml,平面上一点 p0 方法一: 直线与平面相交时,必满足 dot ( (p+t*dir-p0),nml)=0 ...

  4. 如何求直线与平面的交点(两种方式)

    一:代数方式 我们假设它们的交点为P,既然我们有一个平面,那么平面上面的一个点P0和平面的normal(垂直于平面的向量)我们是肯定知道的. 根据3D数学知识,(P-P0) · normal = 0( ...

  5. 三维空间直线与平面交点

    三维空间直线与平面交点 已知 公式推导 最后一个等式 已知 平面描述: 平面的法向 VP(x,y,z)V_{P}(x,y,z)VP​(x,y,z), 平面上的一个点 PP(x,y,z)P_{P}(x, ...

  6. 计算三维空间中直线和三角形的交点

    计算三维空间中直线和三角形的交点 前言 一.计算平面方程 1.1 平面不过原点 1.2 平面过原点 1.3 平面过 zzz 轴 1.4 平面为 yOzyOzyOz 平面 二.计算直线方程 三.计算交点 ...

  7. ad走线画直线_作为立体几何的热点,直线与平面的平行关系,到处都是考试的影子...

    在高考数学里,空间直线与平面的平行有关的知识内容和题型,一直是近几年高考命题的热点,成为立体几何重要的基础考点.如何巧妙快速的判定空间直线与平面平行位置关系,如何在平面内寻找一条直线,探索该直线与平面 ...

  8. 直线与直线、直线与圆、直线与矩形的交点

    求直线与直线.直线与圆.直线与矩形的交点 直线与直线的交点:a1x + b1x + c1x = 0 与 a2x + b2x + c2x = 0的交点坐标可直接根据公式x = (b1c2 - b2c1) ...

  9. 向量叉乘求三维空间中两直线(或线段)的交点

    1.2D空间的直线相交 在二维空间中,利用两个直线方程y = kx + b我们可以直接计算出交点,但是这种方法麻烦了些,并且套用到三维空间用公式就更麻烦了,接下来介绍的是如何利用向量叉乘求出直线交点. ...

最新文章

  1. 一阵骚操作,我把SQL执行效率提高了10000000倍!
  2. 《head first java 》读书笔记(四)
  3. JDK5.0新特性系列---11.4线程 Condition
  4. ElementUI的el-cascader级联选择器各个属性的设置
  5. 【python】【scrapy】使用方法概要(三)
  6. WiFi---AP+STA共存模式(ESP8266)
  7. vba抓取网页数据到excel_抓取网页数据,上班也能看股票
  8. 【操作系统】对换、分页和分段方式-思维导图
  9. 使用HQL语句的按照参数名字查询数据库信息的时候 “=:”和参数之间不能存在空格,否则会报错...
  10. 操作系统-管程、进程和线程之间的差别
  11. 【数据治理】数据元、元数据、主数据、参考数据概述
  12. 手机屏碎了,怎样辨别是外屏坏还是内屏坏,看完这篇文章就明白了
  13. python如何设计一个排队系统
  14. Unity 判断鼠标点击的是单击还是双击
  15. spring注解开发配置spring父子容器
  16. Python 如何被证明是 2021 年的转折点语言
  17. QT作为设备接入阿里云平台
  18. centos安装Nvidia显卡驱动(3090)
  19. 墙裂推荐!Pycharm里6大神器插件!
  20. Xgen Animwires 随笔01

热门文章

  1. 电子学会青少年软件编程 Python编程等级考试三级真题解析(判断题)2021年3月
  2. 平方和与和平方的差是多少?
  3. Pandas简易入门(四)
  4. 2020-06-19 云运维linux centos7.2 文件管理基础知识总结
  5. 神经网络的偏差和方差,神经网络均方误差公式
  6. Linux***与提权:技巧总结篇
  7. 什么是渗透测试?如何学习渗透测试?
  8. Lighttpd libdir默认库文件路径分析及修改操作说明
  9. 房产装修源码 php,房屋装修方案网站模板
  10. 本地推送通知和远程推送通知