unity计算三维空间下点到线,点到面,线到线,线到面,面到面最短距离的点的方法

本文主要是介绍unity计算三维空间下点到线,点到面,线到线,线到面,面到面最短距离的点的方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通用的一个方法GetDistance,计算两个点的距离,不开平方

/// <summary>
/// 获取两个点的距离,不开平方
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
public static float GetDistance(Vector3 a, Vector3 b)
{float num = a.x - b.x;float num2 = a.y - b.y;float num3 = a.z - b.z;return num * num + num2 * num2 + num3 * num3;
}

1.计算一条线段上到一个点距离最短的点

/// <summary>
/// 获取一个点到一条线段的最近点
/// </summary>
/// <param name="point"></param>
/// <param name="lineStart"></param>
/// <param name="lineEnd"></param>
/// <returns></returns>
public static Vector3 PointToLineSegmentDistance(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
{Vector3 lineDirection = lineEnd - lineStart;Vector3 pointDirection = point - lineStart;float lineLength = lineDirection.magnitude;lineDirection.Normalize();float dotProduct = Vector3.Dot(pointDirection, lineDirection);dotProduct = Mathf.Clamp(dotProduct, 0f, lineLength);Vector3 closestPoint = lineStart + lineDirection * dotProduct;return closestPoint;
}

2.计算一个三角形内距离一个点最短的点

/// <summary>
/// 获取一个点到一个三角形内最短距离的点
/// </summary>
/// <param name="a">三角形顶点a</param>
/// <param name="b">三角形顶点b</param>
/// <param name="c">三角形顶点c</param>
/// <param name="pos"></param>
/// <returns></returns>
public static Vector3 GetPosInTriangle(Vector3 a, Vector3 b, Vector3 c, Vector3 pos)
{Vector3 normal = Vector3.Cross(b - a, c - a).normalized;Vector3 toPoint = pos - a;float distance = Vector3.Dot(toPoint, normal);Vector3 targetPos = pos - distance * normal;if(PointInTriangle(targetPos, a, b, c))return targetPos;else{Vector3 p1 = PointToLineSegmentDistance(pos, a, b);Vector3 p2 = PointToLineSegmentDistance(pos, a, c);Vector3 p3 = PointToLineSegmentDistance(pos, b, c);float d1 = Vector3.Distance(p1, pos);float d2 = Vector3.Distance(p2, pos);float d3 = Vector3.Distance(p3, pos);if (d1 <= d2 && d1 <= d3)return p1;else if (d2 <= d3 && d2 <= d1)return p2;else /*if(d3 <= d1 && d3 <= d2)*/return p3;//return default;}
}/// <summary>
/// 判断一个点是否在三角形内
/// </summary>
/// <param name="pos"></param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="c"></param>
/// <returns></returns>
public static bool PointInTriangle(Vector3 pos, Vector3 a, Vector3 b, Vector3 c)
{var v0 = c - a;var v1 = b - a;var v2 = pos - a;var dot00 = Vector3.Dot(v0, v0);var dot01 = Vector3.Dot(v0, v1);var dot02 = Vector3.Dot(v0, v2);var dot11 = Vector3.Dot(v1, v1);var dot12 = Vector3.Dot(v1, v2);var invDenom = 1 / (dot00 * dot11 - dot01 * dot01);var u = (dot11 * dot02 - dot01 * dot12) * invDenom;var v = (dot00 * dot12 - dot01 * dot02) * invDenom;// 如果u和v都在[0,1]的范围内,那么点P在三角形ABC内return (u >= 0) && (v >= 0) && (u + v < 1);
}

3.计算两条线段间距离最短的两个点,此方法不是最优方法,还需修改

/// <summary>
/// 计算两个线段的最近点
/// 此方法需要修改,现在实现的方法不是最好的方法,存在误差
/// </summary>
/// <param name="line1Point1"></param>
/// <param name="line1Point2"></param>
/// <param name="line2Point1"></param>
/// <param name="lin2Point2"></param>
/// <param name="value1"></param>
/// <param name="value2"></param>
public static float LineToLine(Vector3 line1Point1, Vector3 line1Point2, Vector3 line2Point1, Vector3 lin2Point2, out Vector3 value1, out Vector3 value2)
{List<Vector3> points = new List< Vector3>();value1 = Vector3.zero ; value2 = Vector3.zero ;//这边的方法需要修改,目前是将线段1按每距离0.1米加一个点(包括两个端点)float dis = Vector3.Distance(line1Point1, line1Point2);int count = (int)(dis * 10);Vector3 dir = (line1Point2 - line1Point1).normalized;points.Add(line1Point1);for (int i = 1; i <= count; i++){points.Add(dir * 0.1f * i + line1Point1);}points.Add(line1Point2);float minDis = float.MaxValue;//然后使用每个点计算到另一线段距离最短的点,最后比较得到距离最短的点foreach (var item in points){Vector3 p = PointToLineSegmentDistance(item, line2Point1, lin2Point2);float d = GetDistance(p, item);if(d < minDis){minDis = d;value1 = item;value2 = p;}}return minDis;
}

4.计算一条线段到一个三角面距离最短的两个点

/// <summary>
/// 计算一条线段到一个三角面距离最短的两个点
/// </summary>
/// <param name="linePoints"></param>
/// <param name="triPoints"></param>
/// <param name="value1"></param>
/// <param name="value2"></param>
public static void LineToTriangle(List<Vector3> linePoints, List<Vector3> triPoints, out Vector3 value1, out Vector3 value2)
{value1 = Vector3.zero;value2 = Vector3.zero;Vector3 pos = default;//判断线段与三角面是否相交,若相交,则距离最短的点为交点if (LineIntersectsTriangle(linePoints[0], linePoints[1], triPoints[0], triPoints[1], triPoints[2],out pos)){value1 = pos;value2 = pos;return;}//不相交的话,分别计算这条边与三角形三条边距离最短的点Vector3 p1 = default;Vector3 p2 = default;float dis1 = LineToLine(linePoints[0], linePoints[1], triPoints[0], triPoints[1], out p1, out p2);Vector3 p3 = default;Vector3 p4 = default;float dis2 = LineToLine(linePoints[0], linePoints[1], triPoints[0], triPoints[2], out p3, out p4);Vector3 p5 = default;Vector3 p6 = default;float dis3 = LineToLine(linePoints[0], linePoints[1], triPoints[2], triPoints[1], out p5, out p6);//分别计算线段的端点到三角形距离最短的点Vector3 p7 = GetPosInTriangle(triPoints[0], triPoints[1], triPoints[2], linePoints[0]);Vector3 p8 = GetPosInTriangle(triPoints[0], triPoints[1], triPoints[2], linePoints[1]);float dis4 = GetDistance(p7, linePoints[0]);float dis5 = GetDistance(p8, linePoints[1]);//比较得到最短距离的点float min = Mathf.Min(dis1, dis2, dis3, dis4, dis5);if(min == dis1){value1 = p1;value2 = p2;return;}else if(min == dis2){value1 = p3;value2 = p4;return;}else if(min == dis3){value1 = p5;value2 = p6;return;}else if(min == dis4){value1 = p7;value2 = linePoints[0];return;}else{value1 = p8;value2 = linePoints[1];return;}
}/// <summary>
/// 判断线段是否与一个三角面有交点,并得到这个交点
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="v0"></param>
/// <param name="v1"></param>
/// <param name="v2"></param>
/// <param name="pos"></param>
/// <returns></returns>
public static bool LineIntersectsTriangle(Vector3 a, Vector3 b, Vector3 v0, Vector3 v1, Vector3 v2, out Vector3 pos)
{// 计算三角形的法线Vector3 triangleNormal = Vector3.Cross(v1 - v0, v2 - v0).normalized;pos = default;// 计算线段的方向Vector3 lineDirection = b - a;// 计算线段与平面的交点float denominator = Vector3.Dot(triangleNormal, lineDirection);if (denominator != 0){// 线段与平面不平行,计算交点float t = Vector3.Dot(v0 - a, triangleNormal) / denominator;if (t >= 0 && t <= 1){// 交点在线段内部Vector3 intersectionPoint = a + t * lineDirection;// 检查交点是否在三角形内部if (PointInTriangle(intersectionPoint, v0, v1, v2)){pos = intersectionPoint;return true;}else{return false;}}else{return false;}}else{return false;}
}

5.计算两个三角形间距离最短的两个点

/// <summary>
/// 计算两个三角形间距离最短的两个点
/// </summary>
/// <param name="tri1"></param>
/// <param name="tri2"></param>
/// <param name="value1"></param>
/// <param name="value2"></param>
public static void GetPosInTriangles(List<Vector3> tri1, List<Vector3> tri2, out Vector3 value1, out Vector3 value2)
{//分别计算三角形1的三条边到三角形2的最短距离Vector3 p1 = default;Vector3 p2 = default;LineToTriangle(new List<Vector3>() { tri1[0], tri1[1] }, tri2, out p1, out p2);Vector3 p3 = default;Vector3 p4 = default;LineToTriangle(new List<Vector3>() { tri1[0], tri1[2] }, tri2, out p3, out p4);Vector3 p5 = default;Vector3 p6 = default;LineToTriangle(new List<Vector3>() { tri1[1], tri1[2] }, tri2, out p5, out p6);//Vector3 p11 = default;//Vector3 p21 = default;//LineToTriangle(new List<Vector3>() { tri2[0], tri2[1] }, tri1, out p11, out p21);//Vector3 p31 = default;//Vector3 p41 = default;//LineToTriangle(new List<Vector3>() { tri2[0], tri2[2] }, tri1, out p31, out p41);//Vector3 p51 = default;//Vector3 p61 = default;//LineToTriangle(new List<Vector3>() { tri2[1], tri2[2] }, tri1, out p51, out p61);float dis1 = GetDistance(p1, p2);float dis2 = GetDistance(p3, p4);float dis3 = GetDistance(p5, p6);//float dis4 = GetDistance(p11, p21);//float dis5 = GetDistance(p31, p41);//float dis6 = GetDistance(p51, p61);//比较得到面之间距离最短的点float min = Mathf.Min(dis1, dis2, dis3/*, dis4, dis5, dis6*/);if(min == dis1){value1 = p1;value2 = p2;return;}else if(min == dis2){value1 = p3;value2 = p4;return;}else/* if(min == dis3)*/{value1 = p5;value2 = p6;return;}//else if(min == dis4)//{//    value1 = p11;//    value2 = p21;//    return;//}//else if(min == dis5)//{//    value1 = p31;//    value2 = p41;//    return;//}//else//{//    value1 = p51;//    value2 = p61;//    return;//}
}

这篇关于unity计算三维空间下点到线,点到面,线到线,线到面,面到面最短距离的点的方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/934774

相关文章

最详细安装 PostgreSQL方法及常见问题解决

《最详细安装PostgreSQL方法及常见问题解决》:本文主要介绍最详细安装PostgreSQL方法及常见问题解决,介绍了在Windows系统上安装PostgreSQL及Linux系统上安装Po... 目录一、在 Windows 系统上安装 PostgreSQL1. 下载 PostgreSQL 安装包2.

SQL中redo log 刷⼊磁盘的常见方法

《SQL中redolog刷⼊磁盘的常见方法》本文主要介绍了SQL中redolog刷⼊磁盘的常见方法,将redolog刷入磁盘的方法确保了数据的持久性和一致性,下面就来具体介绍一下,感兴趣的可以了解... 目录Redo Log 刷入磁盘的方法Redo Log 刷入磁盘的过程代码示例(伪代码)在数据库系统中,r

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Python中__init__方法使用的深度解析

《Python中__init__方法使用的深度解析》在Python的面向对象编程(OOP)体系中,__init__方法如同建造房屋时的奠基仪式——它定义了对象诞生时的初始状态,下面我们就来深入了解下_... 目录一、__init__的基因图谱二、初始化过程的魔法时刻继承链中的初始化顺序self参数的奥秘默认

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

Spring 基于XML配置 bean管理 Bean-IOC的方法

《Spring基于XML配置bean管理Bean-IOC的方法》:本文主要介绍Spring基于XML配置bean管理Bean-IOC的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录一. spring学习的核心内容二. 基于 XML 配置 bean1. 通过类型来获取 bean2. 通过

基于Python实现读取嵌套压缩包下文件的方法

《基于Python实现读取嵌套压缩包下文件的方法》工作中遇到的问题,需要用Python实现嵌套压缩包下文件读取,本文给大家介绍了详细的解决方法,并有相关的代码示例供大家参考,需要的朋友可以参考下... 目录思路完整代码代码优化思路打开外层zip压缩包并遍历文件:使用with zipfile.ZipFil

Python处理函数调用超时的四种方法

《Python处理函数调用超时的四种方法》在实际开发过程中,我们可能会遇到一些场景,需要对函数的执行时间进行限制,例如,当一个函数执行时间过长时,可能会导致程序卡顿、资源占用过高,因此,在某些情况下,... 目录前言func-timeout1. 安装 func-timeout2. 基本用法自定义进程subp

Python列表去重的4种核心方法与实战指南详解

《Python列表去重的4种核心方法与实战指南详解》在Python开发中,处理列表数据时经常需要去除重复元素,本文将详细介绍4种最实用的列表去重方法,有需要的小伙伴可以根据自己的需要进行选择... 目录方法1:集合(set)去重法(最快速)方法2:顺序遍历法(保持顺序)方法3:副本删除法(原地修改)方法4: