#pragma once
//GYDevillersTriangle.h
/* 快速检测空间三角形相交算法的代码实现(Devillers & Guigue算法)
博客原地址:http://blog.csdn.net/fourierfeng/article/details/11969915# Devillers & Guigue算法(简称Devillers 算法) 通过三角形各顶点构成的行列式正负的几何意义来判断三角形中点、线、面之间的相对位置关系,
从而判断两三角形是否相交。其基本原理如下:给定空间四个点:a(ax, ay, az), b = (bx, by, bz), c = (cx, cy, cz), d = (dx, dy, dz), 定义行列式如下: [a, b, c, d] 采用右手螺旋法则定义了四个空间点的位置关系。
[a, b, c, d] > 0 表示 d 在 a、b、c 按逆时针顺序所组成的三角形的正法线方向(即上方);
[a, b, c, d] < 0 表示 d 在 △abc的下方; [a, b, c, d] = 0 表示四点共面。 设两个三角形T1和T2,顶点分别为:V10,V11,V12和V20,V21,V22,
三角形所在的平面分别为π1和π2,其法向量分别为N1和N2.算法先判别三角形和另一个三角形所在的平面的相互位置关系, 提前排除不相交的情况。
通过计算[V20, V21, V22, V1i].(i = 0, 1, 2)来判断T1和π2的关系:如果所有的行列式的值都不为零且同号,则T1和T2不相交;否则T1和π2相交。
相交又分为如下几种情况:
a)如果所有的行列式的值为零,则T1和T2共面,转化为共面的线段相交问题。
b)如果其中一个行列式的值为零,而其他两个行列式同号,则只有一个点在平面内,测试顶点是否则T2内部,是则相交,否则不相交;
c)否则T1的顶点位于平面π2两侧(包含T1的一条边在平面π2中的情况)。 再按照类似的方法对 T 2 和 π 1 作进一步的测试。如果通过测试, 则每个三角形必有确定的一点位于另一个三角形所在平面的一侧,
而另外两点位于其另一侧。算法分别循环置换每个三角形的顶点, 以使V10(V20)位于π2(π1)的一侧,另两个点位于其另一侧;
同时对顶点V21,V22(V11, V12)进行交换操作,以确保V10(V20)位于π2(π1)的上方,即正法线方向。
经过以上的预排除和置换操作,V10的邻边V10V11,V10V12和V20的邻边V20V21和V20V22与两平面的交线L相交于固定形式的点上,
分别记为i,j,k,l(i<j, k<l), 如图:(参看原博客)
这些点在L上形成的封闭区间为i1 = [i, j], i2 = [k, l].至此,两个三角形的相交测试问题转换为封闭区间i1,i2的重叠问题。
若重叠则相交,否则不相交。由于交点形式固定,只需满足条件k <= j且i <= l即表明区间重叠,条件还可进一步缩减为判别式
(1)是否成立:
[V10, V11, V20, V21] <= 0 && [V10, V12, V22, V20] <= 0 判别式(1)
*/ typedef float float3[]; enum TopologicalStructure
{
INTERSECT, NONINTERSECT
}; struct Triangle
{
//float3 Normal_0;
float3 Vertex_1, Vertex_2, Vertex_3;
}; /*******************************************************************************************************/
//Devillers算法主函数
TopologicalStructure judge_triangle_topologicalStructure(Triangle* tri1, Triangle* tri2); //返回bool值
bool isTriangleTntersect(Triangle* tri1, Triangle* tri2)
{
TopologicalStructure intersectSt = judge_triangle_topologicalStructure(tri1, tri2);
if (intersectSt == INTERSECT)
return true;
return false;
}
//GYDevillersTriangle.cpp
#include "GYDevillersTriangle.h"
#pragma once struct point
{
float x, y;
}; //三维点拷贝为二维点
static void copy_point(point& p, float3 f)
{
p.x = f[];
p.y = f[];
} //四点行列式
inline float get_vector4_det(float3 v1, float3 v2, float3 v3, float3 v4)
{
float a[][];
for (int i = ; i != ; ++i)
{
a[][i] = v1[i] - v4[i];
a[][i] = v2[i] - v4[i];
a[][i] = v3[i] - v4[i];
} return a[][] * a[][] * a[][]
+ a[][] * a[][] * a[][]
+ a[][] * a[][] * a[][]
- a[][] * a[][] * a[][]
- a[][] * a[][] * a[][]
- a[][] * a[][] * a[][];
} //利用叉积计算点p相对线段p1p2的方位
inline double direction(point p1, point p2, point p) {
return (p.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p.y - p1.y);
} //确定与线段p1p2共线的点p是否在线段p1p2上
inline int on_segment(point p1, point p2, point p) {
double max = p1.x > p2.x ? p1.x : p2.x;
double min = p1.x < p2.x ? p1.x : p2.x;
double max1 = p1.y > p2.y ? p1.y : p2.y;
double min1 = p1.y < p2.y ? p1.y : p2.y;
if (p.x >= min && p.x <= max && p.y >= min1 && p.y <= max1)
{
return ;
}
else
{
return ;
}
} //判断线段p1p2与线段p3p4是否相交的主函数
inline int segments_intersert(point p1, point p2, point p3, point p4) {
double d1, d2, d3, d4;
d1 = direction(p3, p4, p1);
d2 = direction(p3, p4, p2);
d3 = direction(p1, p2, p3);
d4 = direction(p1, p2, p4);
if (d1 * d2 < && d3 * d4 < )
{
return ;
}
else if (d1 == && on_segment(p3, p4, p1) == )
{
return ;
}
else if (d2 == && on_segment(p3, p4, p2) == )
{
return ;
}
else if (d3 == && on_segment(p1, p2, p3) == )
{
return ;
}
else if (d4 == && on_segment(p1, p2, p4) == )
{
return ;
}
return ;
} //判断同一平面的直线和三角形是否相交
inline bool line_triangle_intersert_inSamePlane(Triangle* tri, float3 f1, float3 f2)
{
point p1, p2, p3, p4; copy_point(p1, f1); copy_point(p2, f2); copy_point(p3, tri->Vertex_1); copy_point(p4, tri->Vertex_2); if (segments_intersert(p1, p2, p3, p4))
{
return true;
} copy_point(p3, tri->Vertex_2); copy_point(p4, tri->Vertex_3); if (segments_intersert(p1, p2, p3, p4))
{
return true;
} copy_point(p3, tri->Vertex_1); copy_point(p4, tri->Vertex_3); if (segments_intersert(p1, p2, p3, p4))
{
return true;
} return false;
} inline void get_central_point(float3 centralPoint, Triangle* tri)
{
centralPoint[] = (tri->Vertex_1[] + tri->Vertex_2[] + tri->Vertex_3[]) / ; centralPoint[] = (tri->Vertex_1[] + tri->Vertex_2[] + tri->Vertex_3[]) / ; centralPoint[] = (tri->Vertex_1[] + tri->Vertex_2[] + tri->Vertex_3[]) / ;
} //向量之差
inline void get_vector_diff(float3& aimV, const float3 a, const float3 b)
{
aimV[] = b[] - a[]; aimV[] = b[] - a[]; aimV[] = b[] - a[];
} //向量内积
inline float Dot(const float3& v1, const float3& v2)
{
return v1[] * v2[] + v1[] * v2[] + v1[] * v2[];
} //重心法判断点是否在三角形内部
inline bool is_point_within_triangle(Triangle* tri, float3 point)
{
float3 v0;
get_vector_diff(v0, tri->Vertex_1, tri->Vertex_3);
float3 v1;
get_vector_diff(v1, tri->Vertex_1, tri->Vertex_2);
float3 v2;
get_vector_diff(v2, tri->Vertex_1, point);
float dot00 = Dot(v0, v0);
float dot01 = Dot(v0, v1);
float dot02 = Dot(v0, v2);
float dot11 = Dot(v1, v1);
float dot12 = Dot(v1, v2);
float inverDeno = / (dot00* dot11 - dot01* dot01);
float u = (dot11* dot02 - dot01* dot12) * inverDeno;
if (u < || u > ) // if u out of range, return directly
{
return false;
}
float v = (dot00* dot12 - dot01* dot02) * inverDeno;
if (v < || v > ) // if v out of range, return directly
{
return false;
}
return u + v <= ;
} //判断同一平面内的三角形是否相交
inline bool triangle_intersert_inSamePlane(Triangle* tri1, Triangle* tri2)
{
if (line_triangle_intersert_inSamePlane(tri2, tri1->Vertex_1, tri1->Vertex_2))
{
return true;
}
else if (line_triangle_intersert_inSamePlane(tri2, tri1->Vertex_2, tri1->Vertex_3))
{
return true;
}
else if (line_triangle_intersert_inSamePlane(tri2, tri1->Vertex_1, tri1->Vertex_3))
{
return true;
}
else
{
float3 centralPoint1, centralPoint2; get_central_point(centralPoint1, tri1); get_central_point(centralPoint2, tri2); if (is_point_within_triangle(tri2, centralPoint1) || is_point_within_triangle(tri1, centralPoint2))
{
return true;
} return false;
}
} //Devillers算法主函数
TopologicalStructure judge_triangle_topologicalStructure(Triangle* tri1, Triangle* tri2)
{
//设tri1所在的平面为p1,tri2所在的平面为p2
float p1_tri2_vertex1 = get_vector4_det(tri1->Vertex_1, tri1->Vertex_2, tri1->Vertex_3, tri2->Vertex_1); float p1_tri2_vertex2 = get_vector4_det(tri1->Vertex_1, tri1->Vertex_2, tri1->Vertex_3, tri2->Vertex_2); float p1_tri2_vertex3 = get_vector4_det(tri1->Vertex_1, tri1->Vertex_2, tri1->Vertex_3, tri2->Vertex_3); if (p1_tri2_vertex1 > && p1_tri2_vertex2 > && p1_tri2_vertex3 > )
{
return NONINTERSECT;
} if (p1_tri2_vertex1 < && p1_tri2_vertex2 < && p1_tri2_vertex3 < )
{
return NONINTERSECT;
} if (p1_tri2_vertex1 == && p1_tri2_vertex2 == && p1_tri2_vertex3 == )
{
if (triangle_intersert_inSamePlane(tri1, tri2))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
} if (p1_tri2_vertex1 == && p1_tri2_vertex2 * p1_tri2_vertex3 > )
{
if (is_point_within_triangle(tri1, tri2->Vertex_1))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
}
else if (p1_tri2_vertex2 == && p1_tri2_vertex1 * p1_tri2_vertex3 > )
{
if (is_point_within_triangle(tri1, tri2->Vertex_2))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
}
else if (p1_tri2_vertex3 == && p1_tri2_vertex1 * p1_tri2_vertex2 > )
{
if (is_point_within_triangle(tri1, tri2->Vertex_3))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
} float p2_tri1_vertex1 = get_vector4_det(tri2->Vertex_1, tri2->Vertex_2, tri2->Vertex_3, tri1->Vertex_1); float p2_tri1_vertex2 = get_vector4_det(tri2->Vertex_1, tri2->Vertex_2, tri2->Vertex_3, tri1->Vertex_2); float p2_tri1_vertex3 = get_vector4_det(tri2->Vertex_1, tri2->Vertex_2, tri2->Vertex_3, tri1->Vertex_3); if (p2_tri1_vertex1 > && p2_tri1_vertex2 > && p2_tri1_vertex3 > )
{
return NONINTERSECT;
} if (p2_tri1_vertex1 < && p2_tri1_vertex2 < && p2_tri1_vertex3 < )
{
return NONINTERSECT;
} if (p2_tri1_vertex1 == && p2_tri1_vertex2 * p2_tri1_vertex3 > )
{
if (is_point_within_triangle(tri2, tri1->Vertex_1))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
} if (p2_tri1_vertex2 == && p2_tri1_vertex1 * p2_tri1_vertex3 > )
{
if (is_point_within_triangle(tri2, tri1->Vertex_2))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
} if (p2_tri1_vertex3 == && p2_tri1_vertex1 * p2_tri1_vertex2 > )
{
if (is_point_within_triangle(tri2, tri1->Vertex_3))
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
} float* tri1_a = tri1->Vertex_1, *tri1_b = tri1->Vertex_2, *tri1_c = tri1->Vertex_3
, *tri2_a = tri2->Vertex_1, *tri2_b = tri2->Vertex_2, *tri2_c = tri2->Vertex_3; float* m; float im; if (p2_tri1_vertex2 * p2_tri1_vertex3 >= && p2_tri1_vertex1 != )
{
if (p2_tri1_vertex1 < )
{
m = tri2_b;
tri2_b = tri2_c;
tri2_c = m; im = p1_tri2_vertex2;
p1_tri2_vertex2 = p1_tri2_vertex3;
p1_tri2_vertex3 = im;
}
}
else if (p2_tri1_vertex1 * p2_tri1_vertex3 >= && p2_tri1_vertex2 != )
{
m = tri1_a;
tri1_a = tri1_b;
tri1_b = tri1_c;
tri1_c = m; if (p2_tri1_vertex2 < )
{
m = tri2_b;
tri2_b = tri2_c;
tri2_c = m; im = p1_tri2_vertex2;
p1_tri2_vertex2 = p1_tri2_vertex3;
p1_tri2_vertex3 = im;
}
}
else if (p2_tri1_vertex1 * p2_tri1_vertex2 >= && p2_tri1_vertex3 != )
{
m = tri1_a; tri1_a = tri1_c; tri1_c = tri1_b; tri1_b = m; if (p2_tri1_vertex3 < )
{
m = tri2_b;
tri2_b = tri2_c;
tri2_c = m; im = p1_tri2_vertex2;
p1_tri2_vertex2 = p1_tri2_vertex3;
p1_tri2_vertex3 = im;
}
} if (p1_tri2_vertex2 * p1_tri2_vertex3 >= && p1_tri2_vertex1 != )
{
if (p1_tri2_vertex1 < )
{
m = tri1_b;
tri1_b = tri1_c;
tri1_c = m;
}
}
else if (p1_tri2_vertex1 * p1_tri2_vertex3 >= && p1_tri2_vertex2 != )
{
m = tri2_a; tri2_a = tri2_b; tri2_b = tri2_c; tri2_c = m; if (p1_tri2_vertex2 < )
{
m = tri1_b;
tri1_b = tri1_c;
tri1_c = m;
}
}
else if (p1_tri2_vertex1 * p1_tri2_vertex2 >= && p1_tri2_vertex3 != )
{
m = tri2_a; tri2_a = tri2_c; tri2_c = tri2_b; tri2_b = m; if (p1_tri2_vertex3 < )
{
m = tri1_b;
tri1_b = tri1_c;
tri1_c = m;
}
} if (get_vector4_det(tri1_a, tri1_b, tri2_a, tri2_b) <= && get_vector4_det(tri1_a, tri1_c, tri2_c, tri2_a) <= )
{
return INTERSECT;
}
else
{
return NONINTERSECT;
}
}

[算法]检测空间三角形相交算法(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. 关于JQuery设置checkbox checked 的问题

    近日做一个关于JQuery表单验证,有一个比较奇葩的要求,即checkbox是为必填项,textbox不是必填的. 而checkbox与textbox又是相关的,填写了textbox,则其上方的che ...

  2. 导入excle数据将excle数据插入到数据库

    实现功能是,用户可以直接导入对应数据,或者用户下载模板,填写数据,导入模板数据.easyui实现 前台页面 { text : '日清导入', iconCls : 'icon-print', handl ...

  3. Neusoft(3)增加自己的内核模块

    Linux版本 Ubuntu12.04LTS,内核版本为3.2.0-26-generic-ape 具体方法如下: 1.建立源文件,假设文件目录为path,文件名为hello.c源代码如下: #incl ...

  4. DBConfigReader.java

    package com.vcredit.ddcash.batch.util; import java.sql.Connection;import java.sql.PreparedStatement; ...

  5. IOS第17天(1,Quartz2D图片水印)

    ****图片 水印 #import "HMViewController.h" @interface HMViewController () @property (weak, non ...

  6. [转]MongoDB学习 C#驱动操作MongoDB

    下载驱动 驱动的下载有两种方式:一种是在C#项目中通过NuGet进行安装,另一种是通过下面的链接:https://github.com/mongodb/mongo-csharp-driver/rele ...

  7. Vim ide for shell development

    Source : This article is part of the ongoing Vi / Vim Tips and Tricks Series. As a Linux sysadmin or ...

  8. Opensuse enable sound and mic card

    Install application pavucontrol Run pavucontrol You will see the configuration about sound card and ...

  9. 7.2.12. MySQL如何优化ORDER BY

    在某些情况中,MySQL可以使用一个索引来满足ORDER BY子句,而不需要额外的排序. 即使ORDER BY不确切匹配索引,只要WHERE子句中的所有未使用的索引部分和所有额外的ORDER BY 列 ...

  10. Windows上搭建Kafka运行环境

    完整解决方案请参考: Setting Up and Running Apache Kafka on Windows OS   在环境搭建过程中遇到两个问题,在这里先列出来,以方便查询: 1. \Jav ...