如何判断一点在三角形内
假定在右手坐标系中的三角形3点坐标为A,B,C,判断P是否在ABC之内
( 主要来自 3D引擎研发QQ群(38224573 )的各位朋友的讨论 ,我仅仅算做个总结吧,特别感谢各位朋友的热情支持。 )
方法1:三个Perplane的方法
设AB,BC,AC边上的垂直平面为Perplane[3],垂直朝向内侧的法向为n[3]
1)先根据任意两边叉出法向N
N = AB.CrossProduct(AC);
N.Normalize();
D = A.DotProduct( N );
2)如果P在三角形所在平面之外,可直接判定不在平面之内( 假定方程为 ax+by+cz+d = 0 )
if( P.DotProduct( N ) + D > 0 ) return false;
3)然后法向和各边叉出垂直平面的法向
n[0] = N.CrossProduct(AB); //朝向内侧
n[0].Normalize();
Perplane[0].dist = A.DotProduct(n[0]);
Perplane[0].normal = n[0];
同样方法求得Perplane[1],Perlane[2];
3)因为三个Perplane都朝向三角形内侧,P在三角形内的条件是同时在三个Perplane前面;如果给定点P在任意一个垂直平面之后,那么可判定P在三角形外部
for( int i = 0;i<3;j++ )
{
if( P.DotProduct( Perplane[i].normal ) + Perplane[i].dist < 0 )
return false;
}
return true;//如果P没有在任意一条边的外面,可判断定在三角形之内,当然包括在边上的情况
方法2:三个部分面积与总面积相等的方法
S(PAB) + S(PAC) + S( PBC) = S(ABC) 则判定在三角形之内
用矢量代数方法计算三角形的面积为
S = 1/2*|a|*|b|*sin(theta)
= 1/2*|a|*|b|*sqrt(1-cos^2(theta))
= 1/2*|a|*|b|*sqrt(1- (a.DotProduct(b)/(|a|*|b|))^2);
另一种计算面积的方法是 S = 1/2*|a.CrossProduct(b)|
比较一下,发现后者的精确度和效率都高于前者,因为前者需要开方和求矢量长度,矢量长度相当于一次点乘,三个点乘加一个开方,显然不如
后者一次叉乘加一次矢量长度(注,一次叉乘计算相当于2次点乘,一次矢量长度计算相当于一次点乘),后者又对又快。
S(ABC) = AB.CrossProduct(AC);//*0.5;
S(PAB) = PA.CrossProduct(PB);//*0.5;
S(PBC) = PB.CrossProduct(PC);//*0.5;
S(PAC) = PC.CrossProduct(PA);//*0.5;
if( S(PAB) + S(PBC) + S(PAC) == S(ABC) )
return true;
return false;
另一种计算三角形面积的矢量方法是 1/2*a.CrossProdcuct(b) ,CrossProduct = ( y1*z2 - y2*z1 , x1*z2 - x2*z1, x1*y2 - x2*z1 )
可以看到CrossProduct 的计算要比DotProduct多3个乘法计算,效率没有上面的方法高
方法3:三个向量归一化后相加为0
这个方法很怪异,发现自http://flipcode.spaces.live.com/blog/cns!8e578e7901a88369!903.entry 下面的一个回帖
如上图三角形ABC,P为AB外侧一点,N1,N2,N3 分别为BP,AP,CP的归一化矢量;NM为N1,N2夹角的角平分线
可以看出角A-P-B是三角形内角,必然小于180度,那么角N1-P-N2等于A-P-B;NM是N1-P-N2的角平分线,那么角B-P-N等于角N-P-A,而CPN必然小于其中一个,
即小于180/2 = 90度。结论是角N1,N2的合矢量方向与N3的夹角为锐角。所以N1,N2,N3的合向量模大于1.
这里注意,N3不一定在N1,N2之间,不能假定N2-P-N3 和N3-P-N1这两个角一定是锐角
同样可以推导出如果P在三角形内,N1+N2+N3必然小于0;若N1+N2+N3 = 0则P在三角形的边上。
有没有更简单的推导方法?
这个方法看起来很精巧,但是善于优化的朋友会立刻发现,三个矢量归一化,需要三个开方。迭代式开方太慢了,而快速开方有的时候又不满足精度要求。
方法4:重心坐标之和为1
{
BaryCenter = ( S(PAB)/S(PABC),S(PBC)/S(PABC),S(PAC)/S(PABC)) // 点P在三角形内的重心坐标
if( BaryCenter.x + BaryCenter.y + BaryCenter.z >0.f )
return false
return true;
}
其中S(PAB),S(ABC),S(PBC),S(PBC) 用上述的方法二种提到的计算三角形面积方法计算。
综合比较
方法1必须求叉乘,虽然可以通过首先排除不在平面内的点,但是后面仍要求三个叉乘和3个点乘(当然还可排除法优化)
方法2看起来之需要求4个点乘,如果用叉乘方法计算面积,可能会导致效率低下
方法3是看起来是最精巧的方法,但是效率也不能保证...3个开方
方法4和方法2的效率差不多
如何判断一点在三角形内相关推荐
- 射线与三角形求交,并判断是否在三角形内的完整代码(带测试)
// Det.cpp : Defines the entry point for the console application. // #include "stdafx.h" # ...
- 几种方法判断平面点在三角形内
最近在做一个Unity实现的3D建模软件,其中需要在模型表面进行操作的时候,需要用到点和三角形位置关系的判定算法.由于一个模型往往是几千个三角片,所以这个判定算法必须高效,否则会影响最终程序的整体性能 ...
- 阿里云天池超级码力在线编程大赛初赛 第2场 ABCD(A.计算几何 判断点在三角形内 D.大施罗德数/超级卡特兰数)
心得 打了一下被群友吐槽的比赛,阅读体验极差 阴间题面,读题1小时,AC5min,原题警告 思路来源 https://blog.csdn.net/PleasantlY1/article/details ...
- [fzu 2273]判断两个三角形的位置关系
首先判断是否相交,就是枚举3*3对边的相交关系. 如果不相交,判断包含还是相离,就是判断点在三角形内还是三角形外.两边各判断一次. //http://acm.fzu.edu.cn/problem.ph ...
- 海伦公式判断点和三角形的关系
一 海伦公式 如果有一个三角形,它的三边分别为 $a, b ,c $, 则三角形的面积为 A=s(s−a)(s−b)(s−c)A = \sqrt{s(s-a)(s-b)(s-c)}A=s(s−a)(s ...
- 判断某一点是否在三角形内
1.同向法 假设点P位于三角形内,会有这样一个规律,当我们沿着ABCA的方向在三条边上行走时,你会发现点P始终位于边AB,BC和CA的右侧.我们就利用这一点,但是如何判断一个点在线段的左侧还是右侧呢? ...
- 给定三角形ABC和一点P(x, y),判断P是否在三角形内
解题思路: 根据点P与三角形其中两点所形成的三角形面积之和与三角形ABC面积进行比较,如果相等则点P在三角形内,不相等则不在三角形ABC内. 解题步骤: 一.根据给定的三点坐标计算三角形的面积: 二. ...
- 重心法-判断一点是否在三角形内
1. 叉乘(X) 详细定义可以参考:叉积定义. 在三维坐标系中,如果 a = (a1, a2, a3), b = (b1, b2, b3),那么a x b = (a2b3 - a3b2, a3b1 - ...
- 判断点是否在三角形内
本文只是翻译和整理,原文在此http://www.blackpawn.com/texts/pointinpoly/default.html 概述 给定三角形ABC和一点P(x,y,z),判断点P是否在 ...
最新文章
- 我从吴恩达 AI For Everyone 中学到的十个重要 AI 观
- Awk中调用shell命令
- 摘要:ASP.NET的路由
- java.awt.action 命令模式_java设计模式之命令模式
- OWIN的理解和实践(三) –Middleware开发入门
- 请简要说明一下CyclicBarrier和CountDownLatch的区别?
- C/C++混合编程——extern C
- python可以代替按键精灵吗_Python 假装自己是按键精灵
- 企业信息管理系统汇总
- 【JAVA】IOStream
- 小米蓝牙耳机使用说明_小米10手机专用?小米“真无线蓝牙耳机Air 2s”评测
- 数学建模系列--插值算法
- oracle的五种元素,五种元素
- HTML translate方法,HTML canvas translate()用法及代码示例
- 5操作系统的运行机制和体系结构
- 微信任务(投票)分发平台
- Android Surface 介绍
- 节气丨大雪至,人间至此雪盛时,岁暮天寒,顺问冬安
- PHP网站从服务器下载文件到本地
- XSS之xss-labs-level3
热门文章
- Acunetix WVS安装、破解+Web漏洞扫描
- 【转】国外SCI、EI检索期刊
- 浙江移动服务器维护升级时间,中国移动终于“良心了”!10年不换号的老用户,将获得这3大特权...
- 专家预言未来机器人性XX爱OO或成常态,并利于身心健康
- JS内置DATE对象部分函数对日期的支持只到1901年
- Ender的模拟赛D2T1 wait【min-max反演】
- java 正则最小匹配_正则表达式实现最小匹配功能的方法
- 机器视觉毕业设计 深度学习驾驶人脸疲劳检测系统 - python opencv
- 计算机视觉辅助系统价格,驾驶辅助系统计算机视觉技术
- 前端程序员需要了解的原生微信小程序-基础知识