Unity求一条直线与平面的交点
这个是面试官经常考的一个问题,我们先把它变成一个数学问题。
已知一个平面上的一点P0和法向量n,一条直线上的点L0和方向L,求该直线与该平面的交点P
如下图
首先我们分析一下我们知道平面和直线的法向量,知道平面和直线上的一点,求直线与平面上的交点p。
这里我们就要引入点积的概念。点积的几何意义(百度百科直接粘的)
和
,它们的夹角为
,则内积定义为以下实数: [2]
而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求一条直线与平面的交点相关推荐
- Revit求直线与平面的交点
直线与平面的交点有两种情况,交点在平面内或平面外,计算出交点后需确定此交点是否在已知平面内. 代码如下: /// <summary> /// 计算直线与平面的交点 /// </sum ...
- java两条直线交点_求两条直线的交点坐标
看UdaCity机器学习大纲,发现入门班中有一条:编写算法计算一组直线或平面的交点. 遂从最简单的直角坐标系两条直线的交点开始, 直线1的方程解析式: 2x-y=0; 直线2的方程解析式: 4x-5y ...
- 给定两个数组arrx和arry,长度都为N。代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点?
问题描述: 给定两个数组arrx和arry,长度都为N.代表二维平面上有N个点,第i个点的x 坐标和y坐标分别为arrx[i]和arry[i],返回求一条直线最多能穿过多少个点? 思想 坐标系中两个点 ...
- zoj 1560 Hansel and Grethel(求两条直线的交点)
题目地址 题目大意:给出2个点及其各自夹角,求2条直线的交点 解题思路:数学公式推导,用tan()求斜率时要将角度转换成弧度 #include <iostream> #include &l ...
- 用矢量变换的方法求两条直线的交点
求两条直线的交点,最常见的写法是列出两条直线的方程,联立求解. 但这种办法的弊端很大: 1 )算法是坐标系相关的,要考虑直线是水平还是垂直,写出很多判断条件,增加了程序的不稳定性 ...
- 求解直线与平面的交点
求解直线与平面的交点 微信公众号:幼儿园的学霸 目录 文章目录 求解直线与平面的交点 目录 前言 数学模型推导 编程实现 参考资料 前言 直线与平面的交点求解相关的内容在网上已经有很多资料进行介绍,目 ...
- 如何求直线与平面的交点(两种方式)
一:代数方式 我们假设它们的交点为P,既然我们有一个平面,那么平面上面的一个点P0和平面的normal(垂直于平面的向量)我们是肯定知道的. 根据3D数学知识,(P-P0) · normal = 0( ...
- PCL:求两条直线交点
使用PCL库中的直线拟合方法,可以拟合出来多条直线,可以对这多条直线求交点(前提是直线相交). 对应实现代码如下: 见链接:https://blog.csdn.net/m0_37957160/ar ...
- 求两条直线(线段)的交点
转自: http://blog.csdn.net/dgq8211/article/details/7952825 如图,如何求得直线 AB 与直线 CD 的交点P? 以上内容摘自<算法艺术与信息 ...
最新文章
- java 算法--洗牌算法
- linux程序移植到vxworks,VxWorks入门(一):VxWorks Vs Linux
- 学习笔记Hadoop(七)—— Hadoop集群的安装与部署(4)—— 配置Hadoop集群
- Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)
- 思科路由器动态NAT配置
- [Unity] FlowCanvas 使用注意事项
- 韭菜翻盘致富!加拿大学者发布比特币的价格预测模型
- 【转】URL和URI的区别
- Spring BeanFactory、ApplicationContext IOC 容器获取与使用
- 批量创建文本文档、word、excel、ppt-批处理(二)
- 《信息学奥赛一本通·初赛真题解析》
- C++模板函数 学习记录
- 接口测试用例生成工具介绍及应用
- AndroidTV开发-实现APP开机自启动
- 成立不到半年,正面 PK 星巴克,luckin coffee是什么来路?
- 微服务架构的简单实现-Stardust
- 用c语言编写字母循环,C语言输入循环字母
- 怎样实现cmd命令窗口的快速复制粘贴操作
- 基于vue的移动端Icon图标拖拽(改变定位和使用transform)
- 一键装机linux_linux系统学习第十八天《搭建一键装机平台》终结篇-阿里云开发者社区...
热门文章
- python浮点型是什么_实例讲解Python中浮点型的基本内容
- 如何让浏览器的左上角显示自己的logo的小诀窍
- 舞动你的文字,巧用CSS中marquee属性
- 史上最全openstack-T版安装,学不会你打我
- 我和小伙伴们一起学Unity3D(六)碰撞与触发器
- bat 批处理 批量调整 srt 字幕文件时间
- 第二章 高级语言及其语法描述
- 如何实现身份证输入框的输入效果
- 网络层(王道视频笔记)
- Graph Signal Processing——Part I: Graphs, Graph Spectra, and Spectral Clustering (文献翻译)