看了很多博客对这个问题都写的逻辑混乱,还漏掉了某些情况,实在看不下去了。所以本人按自己对几何的理解手写了一版,可能并不是最优解法,但是力求简洁,百行之内完成任务。

1 理论部分

1.1 两个三角形a,b存在三种关系:

  • 相交
  • 包含
  • 外离

1.2 相交的判断:

  • 是否有边相交:遍历三角形a和b的3条边,判断是否有相交线段
  • 是否有点在边上:分别遍历三角形a和b的点,判断是否在另一三角的边上
  • 是否有顶点重合:遍历三角形a和b的点,判断是否坐标相同

其中,判断有边相交:

  • 首先利用两外积的方向是否异号判断两线段是否相交dcmp(c1)*dcmp(c2) < 0(图左)
  • 再进一步限定为线段相交避免图右侧的情况(见代码seg部分):

其中,判断点是否在边上:

  • 首先利用点到线上两点外积为0判断点是否在线上(dcmp(cross(p - a1, p - a2)) == 0
  • 再进一步利用内积是否为负限定为在线段上dcmp(dot(p - a1, p - a2)) < 0(见代码os)

为了方便确定符号,限定精度,设计了dcmp函数,并用Vector的别名区分point的意义(见代码)。

1.3 包含的判断:

  • 遍历a中的点,判断是否在三角形b中
  • 遍历b中的点,判断是否在三角形a中
  • 判断点是否在三角形中:
    • 按顺序计算点和三角形顶点和边的外积,三条边同号说明在内部(见下图和代码ist部分) :

2 C++手撕平面内两个三角形是否相交

#include <bits/stdc++.h>
using namespace std;struct point {double x, y;point() { };point(double _x, double _y) { x = _x; y = _y; }
};
//两点坐标的加减乘:
typedef point Vector;
Vector operator + (point a, point b) {return Vector(a.x + b.x, a.y + b.y);
}
Vector operator - (point a, point b) {return Vector(a.x - b.x, a.y-b.y);
}
Vector operator * (point a, point b) {return Vector(a.x * b.x, a.y * b.y);
}
//点乘:
double  dot (Vector a, Vector b) {return a.x * b.y + a.y * b.y;
}
//叉乘:
double cross(Vector a, Vector b) {return a.x * b.y - a.y * b.x;
}
//精度:
const double eps = 1e-6;
//重要的分类:
int dcmp(double x) {if (fabs(x) < eps) return 0;else return x < 0 ? -1 : 1;
}
//判断两点是否相等:
bool operator == (const point& a, const point& b) {return (dcmp(a.x - b.x) == 0 & dcmp(a.y - b.y) == 0);
}
//判断两线段是否相交(不包括端点):
bool seg(point a1, point a2, point b1, point b2) {double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1);double d1 = cross(b2 - b1, a1 - b1), d2 = cross(b2 - b1, a2 - b1);return dcmp(c1)*dcmp(c2) < 0 && dcmp(d1)*dcmp(d2) < 0;
}
//判断(三角形)顶点p是否在(另一三角形的)某边a1a2(不包括端点)上:
bool os(point p,point a1,point a2) {return (dcmp(cross(p - a1, p - a2)) == 0 && dcmp(dot(p - a1, p - a2)) < 0 );
}
//判断点p是否在三角形t内部:
bool ist(point p,point * t) {return (dcmp(cross(t[1] - t[0], p - t[0])) > 0&& dcmp(cross(t[2] - t[1], p - t[1])) > 0&& dcmp(cross(t[0] - t[2], p - t[2])) > 0)||(dcmp(cross(t[1] - t[0], p - t[0])) <0&& dcmp(cross(t[2] - t[1], p - t[1])) < 0&& dcmp(cross(t[0] - t[2], p - t[2])) < 0);
}
void main()
{//构造三角形a,b:point a[3], b[3];cout << "请输入三角形a的三个顶点的坐标x,y:" << endl;cin >> a[0].x >> a[0].y >> a[1].x >> a[1].y >> a[2].x >> a[2].y;cout << "请输入三角形b的三个顶点的坐标x,y:" << endl;cin >> b[0].x >> b[0].y >> b[1].x >> b[1].y >> b[2].x >> b[2].y;//判断是否相交:bool flag = false;for (int i = 0; i < 3; ++i) {for (int j = 0; j < 3; ++j) {if (seg(a[i], a[(i + 1) % 3], b[j], b[(j + 1) % 3])) { flag = true; break; }if (os(a[i], b[j], b[(j + 1) % 3])) { flag = true; break; }if (a[i] == b[j]) { flag = true; break; }}}if (flag) cout << "三角形a、b的关系为:相交";else {//判断是否包含,否则外离if (ist(a[0], b) && ist(a[1], b) && ist(a[2], b)) flag = true;else if (ist(b[0], a) && ist(b[1], a) && ist(b[2], a)) flag = true;if (flag) cout << "三角形a、b的关系为:包含";else cout << "三角形a、b的关系为:外离";}
}

3 测试

3.1 外离:

3.2 包含

3.3 有点在三角形内部的相交:

3.4 无点在三角内部的相交:

这种六芒星的情况很多人都漏掉了,点均在三角外不等价于相交:

C++检测平面内两个三角形是否相交(逻辑清晰,手撕精简版)相关推荐

  1. PCL点云处理之平面内两直线求交点(五十)

    PCL点云处理之平面内两直线求交点(五十) 一.两点求直线 二.两直线求交点 二.代码 一.两点求直线 设两个点为 (x1, y1) , (x2, y2),则有: A = y2 - y1 B = x1 ...

  2. 判断平面上两条直线是否相交

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 判断平面 ...

  3. C++实现空间中两个三角形位置关系(相交、平行)的判断

    两个空间三角形相交关系的判断: 分别判断三角形trangle_1 的三条边与三角形trangle_2 的位置关系,三角形trangle_2 的三条边与三角形trangle_1 的位置关系. --求解三 ...

  4. 二维平面内两直线交点计算

    对于几何关系的计算,两点确定一条直线,两直线的交点的计算经常见到.最简单matlab编程方法是通过两点列出直线方程,使用matlab工具解方程.但是计算时发现速度较为缓慢. 表达式定义 空间直线的表达 ...

  5. 射线和三角形的相交检测(ray triangle intersection test)

    http://www.cnblogs.com/graphics/archive/2010/08/09/1795348.html 本文以Fast, Minimum Storage Ray Triangl ...

  6. 平面内两条线段的位置关系(相交)判定与交点求解

    http://www.cnblogs.com/devymex/archive/2010/08/19/1803885.html 概念 平面内两条线段位置关系的判定在很多领域都有着广泛的应用,比如游戏.C ...

  7. OpenCV检测平面物体

    OpenCV检测平面物体 检测平面物体 检测平面物体 本教程的目的是学习如何使用features2d和calib3d模块来检测场景中已知的平面对象. 测试数据:使用数据文件夹中的图像,例如box.pn ...

  8. HDU 4631 Sad Love Story 平面内最近点对

    http://acm.hdu.edu.cn/showproblem.php?pid=4631 题意: 在平面内依次加点,求每次加点后最近点对距离平方的和 因为是找平面最近点对...所以加点以后这个最短 ...

  9. c语言 两条线段位置,C++/STL实现判断平面内两条线段的位置关系代码示例

    概念 平面内两条线段位置关系的判定在很多领域都有着广泛的应用,比如游戏.CAD.图形处理等,而两线段交点的求解又是该算法中重要的一环.本文将尽可能用通俗的语言详细的描述一种主流且性能较高的判定算法. ...

  10. 两平面平行但不重合的条件是_____黑龙江省大庆外国语学校高中数学_第二章《2.2_直线、平面平行的判定及其性质》单元测试5_新人教A版必修3...

    黑龙江省大庆外国语学校高一数学必修二第二章<2.2 直线.平面平 行的判定及其性质>单元测试5 一.选择题1.若两个平面互相平行,则分别在这两个平行平面内的直线( ) A.平行 B.异面 ...

最新文章

  1. python粘性拓展_Python基础之:拓展解决问题的思路
  2. 浅谈 javascript 中的this绑定问题
  3. 猫哥教你写爬虫 006--条件判断和条件嵌套
  4. CodeSalt | Python数据结构的实现 — 链表
  5. java变量名转字符串_JS中将变量转为字符串
  6. idea 不能及时编译_您是否能及时编译?
  7. 解决$router.go(-1)返回上一层页面不刷新页面问题
  8. 象过河软件试用版_比肩许银川蒋川王天一,象棋软件下出神一样的残局,看完叹为观止...
  9. java打印等腰三角形_Java 后台开发面试题分享三
  10. 无心剑中译奥修《顺其自然》
  11. cimco edit v5_iA Writer for Mac(写作软件)v5.6.3
  12. launch edge 和 latch edge 延迟以及静态时序分析相关概念
  13. wcdma系统随机接入过程的流程图_一种随机接入方法与流程
  14. Prometheus架构与实践分享
  15. 读秀数据库的用法+全国图书馆参考咨询联盟
  16. 液压伺服比例控制及PLC应用—学习笔记1
  17. ref可以写成变量吗?写在循环v-for里的时候怎么办?
  18. 相似性和相异性的度量
  19. Windows10修改用户名、密码
  20. Java如何计算2个时间段内共有几天几小时几分几秒

热门文章

  1. linux配置中端代理
  2. canvas绘制五角星
  3. 单片机C语言LED点阵编程,基于单片机的8*8 LED点阵显示技术
  4. 声音莫名从扬声器切换到听筒_扬声器听筒的切换
  5. 基于Django 文档1.11 自解+补完 学习django ---part1
  6. 联想服务器光驱安装win7系统,联想光盘安装win7系统教程
  7. ntp版本导致时间同步不成功问题
  8. PHP+新浪微博开放平台+新浪云平台(SAE)
  9. u盘坏了在计算机不显示,U盘在电脑上不能显示怎么办
  10. 【板栗糖GIS】Win11如何取消打印机任务