1. 已知三角形的三个顶点坐标,判断某个点是否在三角形中(在三角形的边上,我们也视作在三角形中),本文给出了三种方法。

算法1:利用面积法

如上图所示,如果点P在三角形ABC的内部,则三个小三角形PAB, PBC, PAC的面积之和 = ABC的面积,反之则不相等。

已知三角形的三个顶点坐标求其面积,可以根据向量的叉乘

  该算法详见后面代码中的函数:IsPointInTriangle1

算法2: 

  首先看一下这个问题,如何判断某两个点在某条直线的同一侧(代码中函数:IsPointAtSameSideOfLine)?

  

  根据向量的叉乘以及右手螺旋定则,AB^AM (^表示叉乘,这里向量省略了字母上面的箭头符号)的方向为向外指出屏幕,AB^AN也是向外指出屏幕,但AB^AO的方向是向内指向屏幕,因此M,N在直线AB的同侧,M ,O在直线AB的两侧。实际计算时,只需要考虑叉积的数值正负。

假设以上各点坐标为A(0,0), B(4,0), M(1,2), N(3,4), O(3,-4), 则:

AB^AM = (4,0)^(1,2) = 4*2 - 0*1 = 8

AB^AN = (4,0)^(3,4) = 4*4 – 0*3 = 16

AB^AO = (4,0)^(3,-4) = 4*-4 – 0*3 = –16

  由上面的数值可知,可以根据数值的正负判断叉乘后向量的方向。即,如果叉积AB^AM 和 AB^AN的结果同号,那么M,N两点就在直线的同侧,否则不在同一侧。特殊地,如果点M在直线AB上,则AB^AM的值为0。(如果是在三维坐标系中,求出的叉积是一个向量,可以根据两个向量的点积结果正负来判断两个向量的是否指向同一侧)

  以上的问题解决了,就很容易的用来判断某个点是否在三角形内,如果P在三角形ABC内部,则满足以下三个条件:P,A在BC的同侧、P,B在AC的同侧、PC在AB的同侧。某一个不满足则表示P不在三角形内部。

该算法详见后面代码中的函数:IsPointInTriangle2

算法3:

  该方法也用到了向量。对于三角形ABC和一点P,可以有如下的向量表示:

  

p点在三角形内部的充分必要条件是:1 >= u >= 0,   1 >= v >= 0,   u+v <= 1。

  已知A,B,C,P四个点的坐标,可以求出u,v,把上面的式子分别点乘向量AC和向量AB

  

解方程得到:

  

解出u,v后只需要看他们是否满足“1 >= u >= 0, 1 >= v >= 0, u+v <= 1”,如满足,则,p 在三角形内。

(u = 0时,p在AB上, v = 0时,p在AC上,两者均为0时,p和A重合)

该算法详见后面代码中的函数:IsPointInTriangle3

#include<string>#include<sstream>#include<fstream>#include<cstdio>#include<cstring>#include<iostream>#include<vector>#include<stack>#include<queue>#include<list>#include<algorithm>#include<ctime>#include<unordered_map>#include<map>#include<typeinfo>#include<cmath>#include<ctime>#include<climits>using namespace std;//类定义:二维向量
class Vector2d
{
public:double x_;double y_;public:Vector2d(double x, double y):x_(x), y_(y){}Vector2d():x_(0), y_(0){}//二维向量叉乘, 叉乘的结果其实是向量,方向垂直于两个向量组成的平面,这里我们只需要其大小和方向double CrossProduct(const Vector2d vec){return x_*vec.y_ - y_*vec.x_;}//二维向量点积double DotProduct(const Vector2d vec){return x_ * vec.x_ + y_ * vec.y_;}//二维向量减法Vector2d Minus(const Vector2d vec) const{return Vector2d(x_ - vec.x_, y_ - vec.y_);}//判断点M,N是否在直线AB的同一侧static bool IsPointAtSameSideOfLine(const Vector2d &pointM, const Vector2d &pointN, const Vector2d &pointA, const Vector2d &pointB){Vector2d AB = pointB.Minus(pointA);Vector2d AM = pointM.Minus(pointA);Vector2d AN = pointN.Minus(pointA);//等于0时表示某个点在直线上return AB.CrossProduct(AM) * AB.CrossProduct(AN) >= 0;}
};//三角形类
class Triangle
{
private:Vector2d pointA_, pointB_, pointC_;public:Triangle(Vector2d point1, Vector2d point2, Vector2d point3):pointA_(point1), pointB_(point2), pointC_(point3){//todo 判断三点是否共线
    }//计算三角形面积double ComputeTriangleArea(){//依据两个向量的叉乘来计算,可参考http://blog.csdn.net/zxj1988/article/details/6260576Vector2d AB = pointB_.Minus(pointA_);Vector2d BC = pointC_.Minus(pointB_);return fabs(AB.CrossProduct(BC) / 2.0);}bool IsPointInTriangle1(const Vector2d pointP){double area_ABC = ComputeTriangleArea();double area_PAB = Triangle(pointP, pointA_, pointB_).ComputeTriangleArea();double area_PAC = Triangle(pointP, pointA_, pointC_).ComputeTriangleArea();double area_PBC = Triangle(pointP, pointB_, pointC_).ComputeTriangleArea();if(fabs(area_PAB + area_PBC + area_PAC - area_ABC) < 0.000001)return true;else return false;}bool IsPointInTriangle2(const Vector2d pointP){return Vector2d::IsPointAtSameSideOfLine(pointP, pointA_, pointB_, pointC_) &&Vector2d::IsPointAtSameSideOfLine(pointP, pointB_, pointA_, pointC_) &&Vector2d::IsPointAtSameSideOfLine(pointP, pointC_, pointA_, pointB_);}bool IsPointInTriangle3(const Vector2d pointP){Vector2d AB = pointB_.Minus(pointA_);Vector2d AC = pointC_.Minus(pointA_);Vector2d AP = pointP.Minus(pointA_);double dot_ac_ac = AC.DotProduct(AC);double dot_ac_ab = AC.DotProduct(AB);double dot_ac_ap = AC.DotProduct(AP);double dot_ab_ab = AB.DotProduct(AB);double dot_ab_ap = AB.DotProduct(AP);double tmp = 1.0 / (dot_ac_ac * dot_ab_ab - dot_ac_ab * dot_ac_ab);double u = (dot_ab_ab * dot_ac_ap - dot_ac_ab * dot_ab_ap) * tmp;if(u < 0 || u > 1)return false;double v = (dot_ac_ac * dot_ab_ap - dot_ac_ab * dot_ac_ap) * tmp;if(v < 0 || v > 1)return false;return u + v <= 1;}bool IsPointInTriangle4(const Vector2d pointP){Vector2d PA = pointA_.Minus(pointP);Vector2d PB = pointB_.Minus(pointP);Vector2d PC = pointC_.Minus(pointP);double t1 = PA.CrossProduct(PB);double t2 = PB.CrossProduct(PC);double t3 = PC.CrossProduct(PA);return t1*t2 >= 0 && t1*t3 >= 0;}
};int main()
{Triangle tri(Vector2d(0,0), Vector2d(6,6), Vector2d(12,0));srand(time(0));for(int i = 0; i < 20; ++i){Vector2d point((rand()*1.0 / RAND_MAX) * 12, (rand()*1.0 / RAND_MAX) * 6);cout<<point.x_<<" "<<point.y_<<":     ";cout<<tri.IsPointInTriangle1(point)<<" ";cout<<tri.IsPointInTriangle2(point)<<" ";cout<<tri.IsPointInTriangle3(point)<<" ";cout<<tri.IsPointInTriangle4(point)<<endl;}
}

转载于:https://www.cnblogs.com/icmzn/p/10746610.html

二维平面上判断点是否在三角形内相关推荐

  1. 在二维平面上,有一个机器人从原点 (0, 0) 开始。给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束。

    在二维平面上,有一个机器人从原点 (0, 0) 开始.给出它的移动顺序,判断这个机器人在完成移动后是否在 (0, 0) 处结束. 移动顺序由字符串表示.字符 move[i] 表示其第 i 次移动.机器 ...

  2. 现在,我们用大炮来打蚊子:蚊子分布在一个M×N格的二维平面上,每只蚊子占据一格。向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意:

    目录 输入格式: 输出格式: 输入样例: 输出样例: 正确答案: 现在,我们用大炮来打蚊子:蚊子分布在一个M×N格的二维平面上,每只蚊子占据一格.向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意: ...

  3. 二维平面上点与线段关系的判定

    二维平面上点与线段关系的判定 问题的基本模型是:已知平面上一线段AB,判定平面上一点C相对于AB的位置(C不和AB共线). 通过向量叉积来判定线段与点的的位置关系. 例题:Toys (http://p ...

  4. Java黑皮书课后题第10章:*10.15(几何:边框)边框是指包围一个二维平面上点集的最小矩形,编写一个方法,为二维平面上一系列点返回一个边框

    *10.15编写一个方法,为二维平面上一系列点返回一个边框 题目 程序 代码 Test15.java Test13_MyRectangle2D.java 运行结果 题目 点击这里跳转编程练习题10.1 ...

  5. 可视化 —— 二维平面上的散列点在坐标轴方向上的移动

    二维平面可以通过平面直角坐标系表示: 二维平面上不同的散列点,也就是平面直角坐标系上的不同的点, 其在坐标轴方向上的移动,分别在以下两个方向上的移动: 在 xx 轴方向上,(x1,y1)(x_1, y ...

  6. JavaScript:实现计算二维平面上两点之间的距离算法(附完整源码)

    JavaScript:实现计算二维平面上两点之间的距离算法 /*Calculate the mathematical properties involving coordinatesCalculate ...

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

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

  8. 判断一个点在三角形内

    http://www.gimoo.net/t/1505/5557e812d7390.html 判断点是否在三角形内 本文只是翻译和整理,原文在此http://www.blackpawn.com/tex ...

  9. 利用叉乘快速判断点是否在三角形内

    利用叉乘快速判断点是否在三角形内 判断P是否在三角形ABC内: 向量: pa = P - A,  ca = C - A; ba = B - A; 如果向量 cross(ca, pa)与向量 cross ...

最新文章

  1. mysql ef vs
  2. Spring Cloud实战小贴士:Ribbon的饥饿加载(eager-load)模式
  3. python解释器是什么-python解释器都有什么
  4. QWidget: Must construct a QApplication before a QPaintDevice
  5. Python学习基础必备知识点:字典dict详解
  6. 剑指前端(前端入门笔记系列)——数组(基本语法)
  7. 4.6上午口语练习 阅读词汇
  8. Zookeeper数据一致性原理
  9. Flutter社区和资源传送门
  10. 《转》阿里负责人揭秘面试潜规则
  11. 【层级多标签文本分类】基于预训练语言模型的BERT-CNN多层级专利分类研究
  12. 【sm2算法】基于mbedtls开源库国密算法的使用(二)
  13. 青年志愿者演讲稿合集15篇
  14. 新手小白,做二次剪辑的必备工具,帮你快人一步
  15. mysql 大文本_MySQL长文本存储类型
  16. Java程序员面试分类真题(后附答案解析)
  17. 开源语音助手_开源语音助手软件入门
  18. HTML项目立项,作为承建方,其项目立项的第一步工作是()。A.编制立项申请书B.项目论证C.项目 - 信管网...
  19. Excel教程:必会的大数据录入技巧|Excel入门
  20. Opencv中使用ocl模块遇到的问题

热门文章

  1. python全栈构图_Python全栈-magedu-2018-笔记5
  2. docker xware下载慢_win7环境下Docker快速构建及阿里云容器加速配置
  3. hget如何获取多个value_《深入微服务》之 如何给老婆解释什么是微服务的基础框架SpringBoot?...
  4. Lc1047删除字符串中所有重复项
  5. UnityShader16:点光源和聚光灯
  6. OpenGL基础46:切线空间
  7. 有下界的最小费用可行流2.0(bzoj 3876: [Ahoi2014]支线剧情)
  8. 福州大学第十四届程序设计竞赛-重现赛(Record)
  9. matlab 实现行程编码 对二值图像进行编解码
  10. python网络爬虫系列教程——python网络数据爬虫误区,让你的爬虫更像人类