1. #pragma once
  2. //GYDevillersTriangle.h
  3. /* 快速检测空间三角形相交算法的代码实现(Devillers & Guigue算法)
  4. 博客原地址:http://blog.csdn.net/fourierfeng/article/details/11969915#
  5.  
  6. Devillers & Guigue算法(简称Devillers 算法) 通过三角形各顶点构成的行列式正负的几何意义来判断三角形中点、线、面之间的相对位置关系,
  7. 从而判断两三角形是否相交。其基本原理如下:给定空间四个点:a(ax, ay, az), b = (bx, by, bz), c = (cx, cy, cz), d = (dx, dy, dz), 定义行列式如下:
  8.  
  9. [a, b, c, d] 采用右手螺旋法则定义了四个空间点的位置关系。
  10. [a, b, c, d] > 0 表示 d 在 a、b、c 按逆时针顺序所组成的三角形的正法线方向(即上方);
  11. [a, b, c, d] < 0 表示 d 在 △abc的下方; [a, b, c, d] = 0 表示四点共面。
  12.  
  13. 设两个三角形T1和T2,顶点分别为:V10,V11,V12和V20,V21,V22,
  14. 三角形所在的平面分别为π1和π2,其法向量分别为N1和N2.算法先判别三角形和另一个三角形所在的平面的相互位置关系, 提前排除不相交的情况。
  15. 通过计算[V20, V21, V22, V1i].(i = 0, 1, 2)来判断T1和π2的关系:如果所有的行列式的值都不为零且同号,则T1和T2不相交;否则T1和π2相交。
  16. 相交又分为如下几种情况:
  17. a)如果所有的行列式的值为零,则T1和T2共面,转化为共面的线段相交问题。
  18. b)如果其中一个行列式的值为零,而其他两个行列式同号,则只有一个点在平面内,测试顶点是否则T2内部,是则相交,否则不相交;
  19. c)否则T1的顶点位于平面π2两侧(包含T1的一条边在平面π2中的情况)。
  20.  
  21. 再按照类似的方法对 T 2 和 π 1 作进一步的测试。如果通过测试, 则每个三角形必有确定的一点位于另一个三角形所在平面的一侧,
  22. 而另外两点位于其另一侧。算法分别循环置换每个三角形的顶点, 以使V10(V20)位于π2(π1)的一侧,另两个点位于其另一侧;
  23. 同时对顶点V21,V22(V11, V12)进行交换操作,以确保V10(V20)位于π2(π1)的上方,即正法线方向。
  24. 经过以上的预排除和置换操作,V10的邻边V10V11,V10V12和V20的邻边V20V21和V20V22与两平面的交线L相交于固定形式的点上,
  25. 分别记为i,j,k,l(i<j, k<l), 如图:(参看原博客)
  26. 这些点在L上形成的封闭区间为i1 = [i, j], i2 = [k, l].至此,两个三角形的相交测试问题转换为封闭区间i1,i2的重叠问题。
  27. 若重叠则相交,否则不相交。由于交点形式固定,只需满足条件k <= j且i <= l即表明区间重叠,条件还可进一步缩减为判别式
  28. (1)是否成立:
  29. [V10, V11, V20, V21] <= 0 && [V10, V12, V22, V20] <= 0 判别式(1)
  30. */
  31.  
  32. typedef float float3[];
  33.  
  34. enum TopologicalStructure
  35. {
  36. INTERSECT, NONINTERSECT
  37. };
  38.  
  39. struct Triangle
  40. {
  41. //float3 Normal_0;
  42. float3 Vertex_1, Vertex_2, Vertex_3;
  43. };
  44.  
  45. /*******************************************************************************************************/
  46. //Devillers算法主函数
  47. TopologicalStructure judge_triangle_topologicalStructure(Triangle* tri1, Triangle* tri2);
  48.  
  49. //返回bool值
  50. bool isTriangleTntersect(Triangle* tri1, Triangle* tri2)
  51. {
  52. TopologicalStructure intersectSt = judge_triangle_topologicalStructure(tri1, tri2);
  53. if (intersectSt == INTERSECT)
  54. return true;
  55. return false;
  56. }
  1. //GYDevillersTriangle.cpp
  2. #include "GYDevillersTriangle.h"
  3. #pragma once
  4.  
  5. struct point
  6. {
  7. float x, y;
  8. };
  9.  
  10. //三维点拷贝为二维点
  11. static void copy_point(point& p, float3 f)
  12. {
  13. p.x = f[];
  14. p.y = f[];
  15. }
  16.  
  17. //四点行列式
  18. inline float get_vector4_det(float3 v1, float3 v2, float3 v3, float3 v4)
  19. {
  20. float a[][];
  21. for (int i = ; i != ; ++i)
  22. {
  23. a[][i] = v1[i] - v4[i];
  24. a[][i] = v2[i] - v4[i];
  25. a[][i] = v3[i] - v4[i];
  26. }
  27.  
  28. return a[][] * a[][] * a[][]
  29. + a[][] * a[][] * a[][]
  30. + a[][] * a[][] * a[][]
  31. - a[][] * a[][] * a[][]
  32. - a[][] * a[][] * a[][]
  33. - a[][] * a[][] * a[][];
  34. }
  35.  
  36. //利用叉积计算点p相对线段p1p2的方位
  37. inline double direction(point p1, point p2, point p) {
  38. return (p.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p.y - p1.y);
  39. }
  40.  
  41. //确定与线段p1p2共线的点p是否在线段p1p2上
  42. inline int on_segment(point p1, point p2, point p) {
  43. double max = p1.x > p2.x ? p1.x : p2.x;
  44. double min = p1.x < p2.x ? p1.x : p2.x;
  45. double max1 = p1.y > p2.y ? p1.y : p2.y;
  46. double min1 = p1.y < p2.y ? p1.y : p2.y;
  47. if (p.x >= min && p.x <= max && p.y >= min1 && p.y <= max1)
  48. {
  49. return ;
  50. }
  51. else
  52. {
  53. return ;
  54. }
  55. }
  56.  
  57. //判断线段p1p2与线段p3p4是否相交的主函数
  58. inline int segments_intersert(point p1, point p2, point p3, point p4) {
  59. double d1, d2, d3, d4;
  60. d1 = direction(p3, p4, p1);
  61. d2 = direction(p3, p4, p2);
  62. d3 = direction(p1, p2, p3);
  63. d4 = direction(p1, p2, p4);
  64. if (d1 * d2 < && d3 * d4 < )
  65. {
  66. return ;
  67. }
  68. else if (d1 == && on_segment(p3, p4, p1) == )
  69. {
  70. return ;
  71. }
  72. else if (d2 == && on_segment(p3, p4, p2) == )
  73. {
  74. return ;
  75. }
  76. else if (d3 == && on_segment(p1, p2, p3) == )
  77. {
  78. return ;
  79. }
  80. else if (d4 == && on_segment(p1, p2, p4) == )
  81. {
  82. return ;
  83. }
  84. return ;
  85. }
  86.  
  87. //判断同一平面的直线和三角形是否相交
  88. inline bool line_triangle_intersert_inSamePlane(Triangle* tri, float3 f1, float3 f2)
  89. {
  90. point p1, p2, p3, p4;
  91.  
  92. copy_point(p1, f1);
  93.  
  94. copy_point(p2, f2);
  95.  
  96. copy_point(p3, tri->Vertex_1);
  97.  
  98. copy_point(p4, tri->Vertex_2);
  99.  
  100. if (segments_intersert(p1, p2, p3, p4))
  101. {
  102. return true;
  103. }
  104.  
  105. copy_point(p3, tri->Vertex_2);
  106.  
  107. copy_point(p4, tri->Vertex_3);
  108.  
  109. if (segments_intersert(p1, p2, p3, p4))
  110. {
  111. return true;
  112. }
  113.  
  114. copy_point(p3, tri->Vertex_1);
  115.  
  116. copy_point(p4, tri->Vertex_3);
  117.  
  118. if (segments_intersert(p1, p2, p3, p4))
  119. {
  120. return true;
  121. }
  122.  
  123. return false;
  124. }
  125.  
  126. inline void get_central_point(float3 centralPoint, Triangle* tri)
  127. {
  128. centralPoint[] = (tri->Vertex_1[] + tri->Vertex_2[] + tri->Vertex_3[]) / ;
  129.  
  130. centralPoint[] = (tri->Vertex_1[] + tri->Vertex_2[] + tri->Vertex_3[]) / ;
  131.  
  132. centralPoint[] = (tri->Vertex_1[] + tri->Vertex_2[] + tri->Vertex_3[]) / ;
  133. }
  134.  
  135. //向量之差
  136. inline void get_vector_diff(float3& aimV, const float3 a, const float3 b)
  137. {
  138. aimV[] = b[] - a[];
  139.  
  140. aimV[] = b[] - a[];
  141.  
  142. aimV[] = b[] - a[];
  143. }
  144.  
  145. //向量内积
  146. inline float Dot(const float3& v1, const float3& v2)
  147. {
  148. return v1[] * v2[] + v1[] * v2[] + v1[] * v2[];
  149. }
  150.  
  151. //重心法判断点是否在三角形内部
  152. inline bool is_point_within_triangle(Triangle* tri, float3 point)
  153. {
  154. float3 v0;
  155. get_vector_diff(v0, tri->Vertex_1, tri->Vertex_3);
  156. float3 v1;
  157. get_vector_diff(v1, tri->Vertex_1, tri->Vertex_2);
  158. float3 v2;
  159. get_vector_diff(v2, tri->Vertex_1, point);
  160. float dot00 = Dot(v0, v0);
  161. float dot01 = Dot(v0, v1);
  162. float dot02 = Dot(v0, v2);
  163. float dot11 = Dot(v1, v1);
  164. float dot12 = Dot(v1, v2);
  165. float inverDeno = / (dot00* dot11 - dot01* dot01);
  166. float u = (dot11* dot02 - dot01* dot12) * inverDeno;
  167. if (u < || u > ) // if u out of range, return directly
  168. {
  169. return false;
  170. }
  171. float v = (dot00* dot12 - dot01* dot02) * inverDeno;
  172. if (v < || v > ) // if v out of range, return directly
  173. {
  174. return false;
  175. }
  176. return u + v <= ;
  177. }
  178.  
  179. //判断同一平面内的三角形是否相交
  180. inline bool triangle_intersert_inSamePlane(Triangle* tri1, Triangle* tri2)
  181. {
  182. if (line_triangle_intersert_inSamePlane(tri2, tri1->Vertex_1, tri1->Vertex_2))
  183. {
  184. return true;
  185. }
  186. else if (line_triangle_intersert_inSamePlane(tri2, tri1->Vertex_2, tri1->Vertex_3))
  187. {
  188. return true;
  189. }
  190. else if (line_triangle_intersert_inSamePlane(tri2, tri1->Vertex_1, tri1->Vertex_3))
  191. {
  192. return true;
  193. }
  194. else
  195. {
  196. float3 centralPoint1, centralPoint2;
  197.  
  198. get_central_point(centralPoint1, tri1);
  199.  
  200. get_central_point(centralPoint2, tri2);
  201.  
  202. if (is_point_within_triangle(tri2, centralPoint1) || is_point_within_triangle(tri1, centralPoint2))
  203. {
  204. return true;
  205. }
  206.  
  207. return false;
  208. }
  209. }
  210.  
  211. //Devillers算法主函数
  212. TopologicalStructure judge_triangle_topologicalStructure(Triangle* tri1, Triangle* tri2)
  213. {
  214. //设tri1所在的平面为p1,tri2所在的平面为p2
  215. float p1_tri2_vertex1 = get_vector4_det(tri1->Vertex_1, tri1->Vertex_2, tri1->Vertex_3, tri2->Vertex_1);
  216.  
  217. float p1_tri2_vertex2 = get_vector4_det(tri1->Vertex_1, tri1->Vertex_2, tri1->Vertex_3, tri2->Vertex_2);
  218.  
  219. float p1_tri2_vertex3 = get_vector4_det(tri1->Vertex_1, tri1->Vertex_2, tri1->Vertex_3, tri2->Vertex_3);
  220.  
  221. if (p1_tri2_vertex1 > && p1_tri2_vertex2 > && p1_tri2_vertex3 > )
  222. {
  223. return NONINTERSECT;
  224. }
  225.  
  226. if (p1_tri2_vertex1 < && p1_tri2_vertex2 < && p1_tri2_vertex3 < )
  227. {
  228. return NONINTERSECT;
  229. }
  230.  
  231. if (p1_tri2_vertex1 == && p1_tri2_vertex2 == && p1_tri2_vertex3 == )
  232. {
  233. if (triangle_intersert_inSamePlane(tri1, tri2))
  234. {
  235. return INTERSECT;
  236. }
  237. else
  238. {
  239. return NONINTERSECT;
  240. }
  241. }
  242.  
  243. if (p1_tri2_vertex1 == && p1_tri2_vertex2 * p1_tri2_vertex3 > )
  244. {
  245. if (is_point_within_triangle(tri1, tri2->Vertex_1))
  246. {
  247. return INTERSECT;
  248. }
  249. else
  250. {
  251. return NONINTERSECT;
  252. }
  253. }
  254. else if (p1_tri2_vertex2 == && p1_tri2_vertex1 * p1_tri2_vertex3 > )
  255. {
  256. if (is_point_within_triangle(tri1, tri2->Vertex_2))
  257. {
  258. return INTERSECT;
  259. }
  260. else
  261. {
  262. return NONINTERSECT;
  263. }
  264. }
  265. else if (p1_tri2_vertex3 == && p1_tri2_vertex1 * p1_tri2_vertex2 > )
  266. {
  267. if (is_point_within_triangle(tri1, tri2->Vertex_3))
  268. {
  269. return INTERSECT;
  270. }
  271. else
  272. {
  273. return NONINTERSECT;
  274. }
  275. }
  276.  
  277. float p2_tri1_vertex1 = get_vector4_det(tri2->Vertex_1, tri2->Vertex_2, tri2->Vertex_3, tri1->Vertex_1);
  278.  
  279. float p2_tri1_vertex2 = get_vector4_det(tri2->Vertex_1, tri2->Vertex_2, tri2->Vertex_3, tri1->Vertex_2);
  280.  
  281. float p2_tri1_vertex3 = get_vector4_det(tri2->Vertex_1, tri2->Vertex_2, tri2->Vertex_3, tri1->Vertex_3);
  282.  
  283. if (p2_tri1_vertex1 > && p2_tri1_vertex2 > && p2_tri1_vertex3 > )
  284. {
  285. return NONINTERSECT;
  286. }
  287.  
  288. if (p2_tri1_vertex1 < && p2_tri1_vertex2 < && p2_tri1_vertex3 < )
  289. {
  290. return NONINTERSECT;
  291. }
  292.  
  293. if (p2_tri1_vertex1 == && p2_tri1_vertex2 * p2_tri1_vertex3 > )
  294. {
  295. if (is_point_within_triangle(tri2, tri1->Vertex_1))
  296. {
  297. return INTERSECT;
  298. }
  299. else
  300. {
  301. return NONINTERSECT;
  302. }
  303. }
  304.  
  305. if (p2_tri1_vertex2 == && p2_tri1_vertex1 * p2_tri1_vertex3 > )
  306. {
  307. if (is_point_within_triangle(tri2, tri1->Vertex_2))
  308. {
  309. return INTERSECT;
  310. }
  311. else
  312. {
  313. return NONINTERSECT;
  314. }
  315. }
  316.  
  317. if (p2_tri1_vertex3 == && p2_tri1_vertex1 * p2_tri1_vertex2 > )
  318. {
  319. if (is_point_within_triangle(tri2, tri1->Vertex_3))
  320. {
  321. return INTERSECT;
  322. }
  323. else
  324. {
  325. return NONINTERSECT;
  326. }
  327. }
  328.  
  329. float* tri1_a = tri1->Vertex_1, *tri1_b = tri1->Vertex_2, *tri1_c = tri1->Vertex_3
  330. , *tri2_a = tri2->Vertex_1, *tri2_b = tri2->Vertex_2, *tri2_c = tri2->Vertex_3;
  331.  
  332. float* m;
  333.  
  334. float im;
  335.  
  336. if (p2_tri1_vertex2 * p2_tri1_vertex3 >= && p2_tri1_vertex1 != )
  337. {
  338. if (p2_tri1_vertex1 < )
  339. {
  340. m = tri2_b;
  341. tri2_b = tri2_c;
  342. tri2_c = m;
  343.  
  344. im = p1_tri2_vertex2;
  345. p1_tri2_vertex2 = p1_tri2_vertex3;
  346. p1_tri2_vertex3 = im;
  347. }
  348. }
  349. else if (p2_tri1_vertex1 * p2_tri1_vertex3 >= && p2_tri1_vertex2 != )
  350. {
  351. m = tri1_a;
  352. tri1_a = tri1_b;
  353. tri1_b = tri1_c;
  354. tri1_c = m;
  355.  
  356. if (p2_tri1_vertex2 < )
  357. {
  358. m = tri2_b;
  359. tri2_b = tri2_c;
  360. tri2_c = m;
  361.  
  362. im = p1_tri2_vertex2;
  363. p1_tri2_vertex2 = p1_tri2_vertex3;
  364. p1_tri2_vertex3 = im;
  365. }
  366. }
  367. else if (p2_tri1_vertex1 * p2_tri1_vertex2 >= && p2_tri1_vertex3 != )
  368. {
  369. m = tri1_a;
  370.  
  371. tri1_a = tri1_c;
  372.  
  373. tri1_c = tri1_b;
  374.  
  375. tri1_b = m;
  376.  
  377. if (p2_tri1_vertex3 < )
  378. {
  379. m = tri2_b;
  380. tri2_b = tri2_c;
  381. tri2_c = m;
  382.  
  383. im = p1_tri2_vertex2;
  384. p1_tri2_vertex2 = p1_tri2_vertex3;
  385. p1_tri2_vertex3 = im;
  386. }
  387. }
  388.  
  389. if (p1_tri2_vertex2 * p1_tri2_vertex3 >= && p1_tri2_vertex1 != )
  390. {
  391. if (p1_tri2_vertex1 < )
  392. {
  393. m = tri1_b;
  394. tri1_b = tri1_c;
  395. tri1_c = m;
  396. }
  397. }
  398. else if (p1_tri2_vertex1 * p1_tri2_vertex3 >= && p1_tri2_vertex2 != )
  399. {
  400. m = tri2_a;
  401.  
  402. tri2_a = tri2_b;
  403.  
  404. tri2_b = tri2_c;
  405.  
  406. tri2_c = m;
  407.  
  408. if (p1_tri2_vertex2 < )
  409. {
  410. m = tri1_b;
  411. tri1_b = tri1_c;
  412. tri1_c = m;
  413. }
  414. }
  415. else if (p1_tri2_vertex1 * p1_tri2_vertex2 >= && p1_tri2_vertex3 != )
  416. {
  417. m = tri2_a;
  418.  
  419. tri2_a = tri2_c;
  420.  
  421. tri2_c = tri2_b;
  422.  
  423. tri2_b = m;
  424.  
  425. if (p1_tri2_vertex3 < )
  426. {
  427. m = tri1_b;
  428. tri1_b = tri1_c;
  429. tri1_c = m;
  430. }
  431. }
  432.  
  433. if (get_vector4_det(tri1_a, tri1_b, tri2_a, tri2_b) <= && get_vector4_det(tri1_a, tri1_c, tri2_c, tri2_a) <= )
  434. {
  435. return INTERSECT;
  436. }
  437. else
  438. {
  439. return NONINTERSECT;
  440. }
  441. }

[算法]检测空间三角形相交算法(Devillers & Guigue算法)的更多相关文章

  1. 3D空间中射线与三角形的交叉检測算法

    引言 射线Ray,在3D图形学中有非常多重要的应用.比方,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检測等等都能够使用射线Ray来完毕. 所以,在本次博客中,将会简单的像大家介绍下 ...

  2. 目标检测算法(1)目标检测中的问题描述和R-CNN算法

    目标检测(object detection)是计算机视觉中非常具有挑战性的一项工作,一方面它是其他很多后续视觉任务的基础,另一方面目标检测不仅需要预测区域,还要进行分类,因此问题更加复杂.最近的5年使 ...

  3. Kosaraju 算法检测有向图的强连通性

    给定一个有向图 G = (V, E) ,对于任意一对顶点 u 和 v,有 u --> v 和 v --> u,亦即,顶点 u 和 v 是互相可达的,则说明该图 G 是强连通的(Strong ...

  4. Iconfinder 如何杜绝盗版,哈希算法检测图像重复

    原地址:http://blog.jobbole.com/65914/ 本文由 伯乐在线 - 小鱼 翻译自 Silviu Tantos.欢迎加入技术翻译小组.转载请参见文章末尾处的要求. [伯乐在线导读 ...

  5. 蓝桥 ADV-230 算法提高 12-1三角形 【数学公式】

      算法提高 12-1三角形   时间限制:1.0s   内存限制:256.0MB      问题描述 为二维空间中的点设计一个结构体,在此基础上为三角形设计一个结构体.分别设计独立的函数计算三角形的 ...

  6. Java实现 蓝桥杯 算法训练 数字三角形

    算法训练 数字三角形 时间限制:1.0s 内存限制:256.0MB 问题描述 (图3.1-1)示出了一个数字三角形. 请编一个程序计算从顶至底的某处的一条路 径,使该路径所经过的数字的总和最大. ●每 ...

  7. 从K近邻算法谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/v_july_v/article/details/8203674 ,感谢july的辛勤劳动 前言 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章 ...

  8. 经典算法题每日演练——第十一题 Bitmap算法

    原文:经典算法题每日演练--第十一题 Bitmap算法 在所有具有性能优化的数据结构中,我想大家使用最多的就是hash表,是的,在具有定位查找上具有O(1)的常量时间,多么的简洁优美, 但是在特定的场 ...

  9. 算法实践——舞蹈链(Dancing Links)算法求解数独

    在“跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题”一文中介绍了舞蹈链(Dancing Links)算法求解精确覆盖问题. 本文介绍该算法的实际运用,利用舞蹈链(Dancin ...

随机推荐

  1. centos下安装php后连接不上mysql

    安装完php后需要安装php的扩展比如: 安装php的扩展yum install php-mysql php-gd php-imap php-ldap php-odbc php-pear php-xm ...

  2. CKPT进程工作机制

    CKPT进程工作示意图 2.CKPT进程工作机制 检查点进程被触发的条件为: a> 当发生日志组切换时: b>  用户提交了事务时(commit): c>  Redo log buf ...

  3. Orale介绍

    Oracle数据库: 是甲骨文公司的一款关系数据库管理系统 具有网格计算的框架 数据量大,并发操作比较多,实时性要求高,采取ORACLE数据库 Oracle数据库的体系结构包括物理存储结构和逻辑存储结 ...

  4. php课程---Json格式规范需要注意的小细节

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Programming Lan ...

  5. Math-基本功能

    <script type="text/javascript"> /* *演示Math对象.该对象中的方法都是静态的.不需要new,直接Math调用即可 */ var n ...

  6. c# 文件遍历

    DirectoryInfo TheFolder=new DirectoryInfo(folderFullName); //遍历文件夹 foreach(DirectoryInfo NextFolder ...

  7. C输入输出函数与缓冲区

    #转 对C语言输入输出流和缓冲区的深入理解C语言缓冲区(缓存)详解缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的 ...

  8. 如何获取imageView中当前内容的相关信息并比较?

    public class MainActivity extends Activity implements OnClickListener{ private Button button; privat ...

  9. iOS系统提供开发环境下命令行编译工具:xcodebuild

    iOS系统提供开发环境下命令行编译工具:xcodebuild[3] xcodebuild 在介绍xcodebuild之前,需要先弄清楚一些在XCode环境下的一些概念[4]: Workspace:简单 ...

  10. webstorm svn 报错

    webstorm    svn 报错Cannot run program "svn": CreateProcess error=2, The system cannot find ...