这个是面试官经常考的一个问题,我们先把它变成一个数学问题。

已知一个平面上的一点P0和法向量n,一条直线上的点L0和方向L,求该直线与该平面的交点P

如下图

首先我们分析一下我们知道平面和直线的法向量,知道平面和直线上的一点,求直线与平面上的交点p。

这里我们就要引入点积的概念。点积的几何意义(百度百科直接粘的)

设二维空间内有两个向量

 

 

,它们的夹角为

 

,则内积定义为以下实数: [2]

该定义只对二维和三维空间有效。
这个运算可以简单地理解为:在点积运算中,第一个向量投影到第二个向量上(这里,向量的顺序是不重要的,点积运算是可交换的),然后通过除以它们的标量长度来“标准化”。这样,这个分数一定是小于等于1的,可以简单地转化成一个角度值。
简单点来说当我们使用Vector3.Dot来处理两个标准化的向量的时候会得到两个向量角度的COS值。
也就是说如果两个向量垂直的话,cos值为0,也就是说两个向量垂直的话点积为0.

而p和po组成的直线肯定与平面法向量n垂直。

这里我们就能推倒出已知的公式1:(p-p0)*n=0

      而由于交点p是属于直线上的一点,所以我们能推倒出公式2:P=L0+dL;

     然后我们把公式2导入到公式1得到:

      (L0+dL-P0)*n=0

      (L0-P0)*n+dL*n=0(点乘满足分配率)

      (p0-L0)*n=dL*n

       d=(p0-L0)*n/L*n(点乘满足结合律)

     只要我们求出d的值带入公式2就能求出交点P.

*************************************************************************************************    

最后又引申出一个问题,如果这个平面是有边界的,那么我们就还得求一下这个平面是否与直线相交。

这里我用了个简单方法。首先你必须知道这个平面所有的顶点,然后这个多边形必须是凸多边形。

那么它必定满足如下规律,如图

      如果该点位于平面内,那么由改点到顶点组成的向量之间的夹角之和必定等于360度,

      如果位于平面外,那么由改点到顶点组成的向量之间的夹角之和必定小于360度,

      所以我们只要求出夹角之和就能求出改点是否位于平面内。

     当然这个只适用于凸多边形,如果有更好地办法,欢迎评论讨论。

********************************************************************************************

    我在Unity中自己创建了一个三角面mesh,然后自己设置一条直线。求交点P,然后赋予小球这个位置。

   在三角面内为红色,在三角面外围蓝色。以下是实现截图。


   


   

实现代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class S001 : MonoBehaviour
{public Material mat;//三角形材质private Mesh mesh;//三角形meshprivate GameObject GoSphere;//交点private Vector3 vecLinePoint;//直线的方向//面需要的点private List<Vector3> vertices = new List<Vector3>();//生成三边面时用到的vertices和indexprivate List<int> triangles = new List<int>();//直线public List<Vector3> veclines;void OnDrawGizmos(){if (veclines.Count > 1){Gizmos.DrawLine(veclines[0], veclines[1]);}}private void Awake(){this.gameObject.AddComponent<MeshFilter>();this.gameObject.AddComponent<MeshRenderer>();mesh = new Mesh();AddFrontFace();//为点和index赋值mesh.vertices = vertices.ToArray();mesh.triangles = triangles.ToArray();//重新计算顶点和法线mesh.RecalculateBounds();mesh.RecalculateNormals();//将生成的面赋值给组件GetComponent<MeshFilter>().mesh = mesh;GetComponent<MeshRenderer>().material = mat;print(mesh.normals[0]);//直线的两个点veclines.Add(new Vector3(0,1,-10));veclines.Add(new Vector3(0.11f,0.36f,3));GoSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);GoSphere.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f);}float i = 0;void Update(){if (i > 2){vecLinePoint = (veclines[1] - veclines[0]);//计算直线的方向Vector3 vec = GetIntersectWithLineAndPlane(veclines[0], vecLinePoint, mesh.normals[0], mesh.vertices[0]);//print(vec.x+"*******"+vec.y+"*********"+vec.z);GoSphere.transform.position = vec;//赋值bool k = IsVecPosPlane(mesh.vertices, vec);//交点是否在多边形内部if (k)//如果在范围内是红色,在范围外是蓝色{GoSphere.GetComponent<Renderer>().material.color = Color.red;}else{GoSphere.GetComponent<Renderer>().material.color = Color.blue;}print(k);//计算位置i = 0;}else{i += Time.deltaTime;}}/// <summary>/// 计算直线与平面的交点/// </summary>/// <param name="point">直线上某一点</param>/// <param name="direct">直线的方向</param>/// <param name="planeNormal">垂直于平面的的向量</param>/// <param name="planePoint">平面上的任意一点</param>/// <returns></returns>private Vector3 GetIntersectWithLineAndPlane(Vector3 point, Vector3 direct, Vector3 planeNormal, Vector3 planePoint){float d = Vector3.Dot(planePoint - point, planeNormal) / Vector3.Dot(direct.normalized, planeNormal);//print(d);return d * direct.normalized + point;}/// <summary>/// 确定坐标是否在平面内/// </summary>/// <returns></returns>private bool IsVecPosPlane(Vector3[] vecs, Vector3 pos){float RadianValue = 0;Vector3 vecOld = Vector3.zero;Vector3 vecNew = Vector3.zero;for (int i = 0; i < vecs.Length; i++){if (i == 0){vecOld = vecs[i] - pos;}if (i == vecs.Length - 1){vecNew = vecs[0] - pos;}else{vecNew = vecs[i + 1] - pos;}RadianValue += Mathf.Acos(Vector3.Dot(vecOld.normalized, vecNew.normalized)) * Mathf.Rad2Deg;vecOld = vecNew;}if (Mathf.Abs(RadianValue - 360) < 0.1f){return true;}else{return false;}//vecOld = vecs[0] - pos;//vecNew = vecs[1] - pos;//RadianValue += Mathf.Acos(Vector3.Dot(vecOld.normalized, vecNew.normalized)) * Mathf.Rad2Deg;//vecOld = vecs[1] - pos;//vecNew = vecs[2] - pos;//RadianValue += Mathf.Acos(Vector3.Dot(vecOld.normalized, vecNew.normalized)) * Mathf.Rad2Deg;//vecOld = vecs[2] - pos;//vecNew = vecs[0] - pos;//RadianValue += Mathf.Acos(Vector3.Dot(vecOld.normalized, vecNew.normalized)) * Mathf.Rad2Deg;}void AddFrontFace(){//添加4个点vertices.Add(new Vector3(0, 0, 0));vertices.Add(new Vector3(0, 1, 0));vertices.Add(new Vector3(1, 0, 0));triangles.Add(0);triangles.Add(1);triangles.Add(2);}
}

Unity求一条直线与平面的交点相关推荐

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

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

  2. java两条直线交点_求两条直线的交点坐标

    看UdaCity机器学习大纲,发现入门班中有一条:编写算法计算一组直线或平面的交点. 遂从最简单的直角坐标系两条直线的交点开始, 直线1的方程解析式: 2x-y=0; 直线2的方程解析式: 4x-5y ...

  3. 给定两个数组arrx和arry,长度都为N。代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点?

    问题描述: 给定两个数组arrx和arry,长度都为N.代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点? 思想 坐标系中两个点 ...

  4. zoj 1560 Hansel and Grethel(求两条直线的交点)

    题目地址 题目大意:给出2个点及其各自夹角,求2条直线的交点 解题思路:数学公式推导,用tan()求斜率时要将角度转换成弧度 #include <iostream> #include &l ...

  5. 用矢量变换的方法求两条直线的交点

    求两条直线的交点,最常见的写法是列出两条直线的方程,联立求解.     但这种办法的弊端很大:     1 )算法是坐标系相关的,要考虑直线是水平还是垂直,写出很多判断条件,增加了程序的不稳定性    ...

  6. 求解直线与平面的交点

    求解直线与平面的交点 微信公众号:幼儿园的学霸 目录 文章目录 求解直线与平面的交点 目录 前言 数学模型推导 编程实现 参考资料 前言 直线与平面的交点求解相关的内容在网上已经有很多资料进行介绍,目 ...

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

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

  8. PCL:求两条直线交点

    使用PCL库中的直线拟合方法,可以拟合出来多条直线,可以对这多条直线求交点(前提是直线相交).   对应实现代码如下: 见链接:https://blog.csdn.net/m0_37957160/ar ...

  9. 求两条直线(线段)的交点

    转自: http://blog.csdn.net/dgq8211/article/details/7952825 如图,如何求得直线 AB 与直线 CD 的交点P? 以上内容摘自<算法艺术与信息 ...

最新文章

  1. java 算法--洗牌算法
  2. linux程序移植到vxworks,VxWorks入门(一):VxWorks Vs Linux
  3. 学习笔记Hadoop(七)—— Hadoop集群的安装与部署(4)—— 配置Hadoop集群
  4. Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)
  5. 思科路由器动态NAT配置
  6. [Unity] FlowCanvas 使用注意事项
  7. 韭菜翻盘致富!加拿大学者发布比特币的价格预测模型
  8. 【转】URL和URI的区别
  9. Spring BeanFactory、ApplicationContext IOC 容器获取与使用
  10. 批量创建文本文档、word、excel、ppt-批处理(二)
  11. 《信息学奥赛一本通·初赛真题解析》
  12. C++模板函数 学习记录
  13. 接口测试用例生成工具介绍及应用
  14. AndroidTV开发-实现APP开机自启动
  15. 成立不到半年,正面 PK 星巴克,luckin coffee是什么来路?
  16. 微服务架构的简单实现-Stardust
  17. 用c语言编写字母循环,C语言输入循环字母
  18. 怎样实现cmd命令窗口的快速复制粘贴操作
  19. 基于vue的移动端Icon图标拖拽(改变定位和使用transform)
  20. 一键装机linux_linux系统学习第十八天《搭建一键装机平台》终结篇-阿里云开发者社区...

热门文章

  1. python浮点型是什么_实例讲解Python中浮点型的基本内容
  2. 如何让浏览器的左上角显示自己的logo的小诀窍
  3. 舞动你的文字,巧用CSS中marquee属性
  4. 史上最全openstack-T版安装,学不会你打我
  5. 我和小伙伴们一起学Unity3D(六)碰撞与触发器
  6. bat 批处理 批量调整 srt 字幕文件时间
  7. 第二章 高级语言及其语法描述
  8. 如何实现身份证输入框的输入效果
  9. 网络层(王道视频笔记)
  10. Graph Signal Processing——Part I: Graphs, Graph Spectra, and Spectral Clustering (文献翻译)