题意:三维空间中,给出两个三角形的左边,问是否相交。

面积法判断点在三角形内:

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<memory.h>
#include<cstdlib>
#include<vector>
#define clc(a,b) memset(a,b,sizeof(a))
#define LL long long int
#define up(i,x,y) for(i=x;i<=y;i++)
#define w(a) while(a)
const double inf=0x3f3f3f3f;
const double PI = acos(-1.0);
using namespace std; struct Point3
{
double x, y, z;
Point3(double x=, double y=, double z=):x(x),y(y),z(z) { }
}; typedef Point3 Vector3; Vector3 operator + (const Vector3& A, const Vector3& B)
{
return Vector3(A.x+B.x, A.y+B.y, A.z+B.z);
}
Vector3 operator - (const Point3& A, const Point3& B)
{
return Vector3(A.x-B.x, A.y-B.y, A.z-B.z);
}
Vector3 operator * (const Vector3& A, double p)
{
return Vector3(A.x*p, A.y*p, A.z*p);
}
Vector3 operator / (const Vector3& A, double p)
{
return Vector3(A.x/p, A.y/p, A.z/p);
} const double eps = 1e-;
int dcmp(double x)
{
if(fabs(x) < eps) return ;
else return x < ? - : ;
} double Dot(const Vector3& A, const Vector3& B)
{
return A.x*B.x + A.y*B.y + A.z*B.z;
}
double Length(const Vector3& A)
{
return sqrt(Dot(A, A));
}
double Angle(const Vector3& A, const Vector3& B)
{
return acos(Dot(A, B) / Length(A) / Length(B));
}
Vector3 Cross(const Vector3& A, const Vector3& B)
{
return Vector3(A.y*B.z - A.z*B.y, A.z*B.x - A.x*B.z, A.x*B.y - A.y*B.x);
}
double Area2(const Point3& A, const Point3& B, const Point3& C)
{
return Length(Cross(B-A, C-A));
} Point3 read_point3()
{
Point3 p;
scanf("%lf%lf%lf", &p.x, &p.y, &p.z);
return p;
} // 点在三角形P0, P1, P2中
bool PointInTri(const Point3& P, const Point3& P0, const Point3& P1, const Point3& P2)
{
double area1 = Area2(P, P0, P1);
double area2 = Area2(P, P1, P2);
double area3 = Area2(P, P2, P0);
return dcmp(area1 + area2 + area3 - Area2(P0, P1, P2)) == ;
} // 三角形P0P1P2是否和线段AB相交
bool TriSegIntersection(const Point3& P0, const Point3& P1, const Point3& P2, const Point3& A, const Point3& B, Point3& P)
{
Vector3 n = Cross(P1-P0, P2-P0);
if(dcmp(Dot(n, B-A)) == ) return false; // 线段A-B和平面P0P1P2平行或共面
else // 平面A和直线P1-P2有惟一交点
{
double t = Dot(n, P0-A) / Dot(n, B-A);
if(dcmp(t) < || dcmp(t-) > ) return false; // 不在线段AB上
P = A + (B-A)*t; // 交点
return PointInTri(P, P0, P1, P2);
}
} bool TriTriIntersection(Point3* T1, Point3* T2)
{
Point3 P;
for(int i = ; i < ; i++)
{
if(TriSegIntersection(T1[], T1[], T1[], T2[i], T2[(i+)%], P)) return true;
if(TriSegIntersection(T2[], T2[], T2[], T1[i], T1[(i+)%], P)) return true;
}
return false;
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
Point3 T1[], T2[];
for(int i = ; i < ; i++) T1[i] = read_point3();
for(int i = ; i < ; i++) T2[i] = read_point3();
printf("%d\n", TriTriIntersection(T1, T2) ? : );
}
return ;
}

用Barycentric坐标法判断点在三角形内(重心法)

 #include<cstdio>
#include<cmath>
using namespace std; struct Point3
{
double x, y, z;
Point3(double x=, double y=, double z=):x(x),y(y),z(z) { }
}; typedef Point3 Vector3; Vector3 operator + (const Vector3& A, const Vector3& B)
{
return Vector3(A.x+B.x, A.y+B.y, A.z+B.z);
}
Vector3 operator - (const Point3& A, const Point3& B)
{
return Vector3(A.x-B.x, A.y-B.y, A.z-B.z);
}
Vector3 operator * (const Vector3& A, double p)
{
return Vector3(A.x*p, A.y*p, A.z*p);
}
Vector3 operator / (const Vector3& A, double p)
{
return Vector3(A.x/p, A.y/p, A.z/p);
} const double eps = 1e-;
int dcmp(double x)
{
if(fabs(x) < eps) return ;
else return x < ? - : ;
} double Dot(const Vector3& A, const Vector3& B)
{
return A.x*B.x + A.y*B.y + A.z*B.z;
}
double Length(const Vector3& A)
{
return sqrt(Dot(A, A));
}
double Angle(const Vector3& A, const Vector3& B)
{
return acos(Dot(A, B) / Length(A) / Length(B));
}
Vector3 Cross(const Vector3& A, const Vector3& B)
{
return Vector3(A.y*B.z - A.z*B.y, A.z*B.x - A.x*B.z, A.x*B.y - A.y*B.x);
}
double Area2(const Point3& A, const Point3& B, const Point3& C)
{
return Length(Cross(B-A, C-A));
} Point3 read_point3()
{
Point3 p;
scanf("%lf%lf%lf", &p.x, &p.y, &p.z);
return p;
} // 点在三角形P0, P1, P2中
// http://www.blackpawn.com/texts/pointinpoly/default.html
bool PointInTri(const Point3& P, const Point3& P0, const Point3& P1, const Point3& P2)
{
Vector3 v0 = P2 - P0;
Vector3 v1 = P1 - P0;
Vector3 v2 = P - P0; // Compute dot products
double dot00 = Dot(v0, v0);
double dot01 = Dot(v0, v1);
double dot02 = Dot(v0, v2);
double dot11 = Dot(v1, v1);
double dot12 = Dot(v1, v2); // Compute barycentric coordinates
double invDenom = / (dot00 * dot11 - dot01 * dot01);
double u = (dot11 * dot02 - dot01 * dot12) * invDenom;
double v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle
return (dcmp(u) >= ) && (dcmp(v) >= ) && (dcmp(u + v - ) <= );
} // 三角形P0P1P2是否和线段AB相交
bool TriSegIntersection(const Point3& P0, const Point3& P1, const Point3& P2, const Point3& A, const Point3& B, Point3& P)
{
Vector3 n = Cross(P1-P0, P2-P0);
if(dcmp(Dot(n, B-A)) == ) return false; // 线段A-B和平面P0P1P2平行或共面
else // 平面A和直线P1-P2有惟一交点
{
double t = Dot(n, P0-A) / Dot(n, B-A);
if(dcmp(t) < || dcmp(t-) > ) return false; // 不在线段AB上
P = A + (B-A)*t; // 交点
return PointInTri(P, P0, P1, P2);
}
} bool TriTriIntersection(Point3* T1, Point3* T2)
{
Point3 P;
for(int i = ; i < ; i++)
{
if(TriSegIntersection(T1[], T1[], T1[], T2[i], T2[(i+)%], P)) return true;
if(TriSegIntersection(T2[], T2[], T2[], T1[i], T1[(i+)%], P)) return true;
}
return false;
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
Point3 T1[], T2[];
for(int i = ; i < ; i++) T1[i] = read_point3();
for(int i = ; i < ; i++) T2[i] = read_point3();
printf("%d\n", TriTriIntersection(T1, T2) ? : );
}
return ;
}

证明可以参考http://www.cnblogs.com/graphics/archive/2010/08/05/1793393.html

三角形的三个点在同一个平面上,如果选中其中一个点,其他两个点不过是相对该点的位移而已,比如选择点A作为起点,那么点B相当于在AB方向移动一段距离得到,而点C相当于在AC方向移动一段距离得到。

所以对于平面内任意一点,都可以由如下方程来表示

P = A +  u * (C – A) + v * (B - A) // 方程1

如果系数u或v为负值,那么相当于朝相反的方向移动,即BA或CA方向。那么如果想让P位于三角形ABC内部,u和v必须满足什么条件呢?有如下三个条件

u >= 0

v >= 0

u + v <= 1

几个边界情况,当u = 0且v = 0时,就是点A,当u = 0,v = 1时,就是点B,而当u = 1, v = 0时,就是点C

整理方程1得到P – A = u(C - A) + v(B - A)

令v0 = C – A, v1 = B – A, v2 = P – A,则v2 = u * v0 + v * v1,现在是一个方程,两个未知数,无法解出u和v,将等式两边分别点乘v0和v1的到两个等式

(v2) • v0 = (u * v0 + v * v1) • v0

(v2) • v1 = (u * v0 + v * v1) • v1

注意到这里u和v是数,而v0,v1和v2是向量,所以可以将点积展开得到下面的式子。

v2 • v0 = u * (v0 • v0) + v * (v1 • v0)  // 式1

v2 • v1 = u * (v0 • v1) + v * (v1• v1)   // 式2

解这个方程得到

u = ((v1•v1)(v2•v0)-(v1•v0)(v2•v1)) / ((v0•v0)(v1•v1) - (v0•v1)(v1•v0))

v = ((v0•v0)(v2•v1)-(v0•v1)(v2•v0)) / ((v0•v0)(v1•v1) - (v0•v1)(v1•v0))

uva 11275 3D Triangles的更多相关文章

  1. uva 11275 3D Triangles (3D-Geometry)

    uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem= ...

  2. UVA 12075 - Counting Triangles(容斥原理计数)

    题目链接:12075 - Counting Triangles 题意:求n * m矩形内,最多能组成几个三角形 这题和UVA 1393类似,把总情况扣去三点共线情况,那么问题转化为求三点共线的情况,对 ...

  3. [ACM_几何] F. 3D Triangles (三维三角行相交)

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28235#problem/A 题目大意:给出三维空间两个三角形三个顶点,判断二者是否有公共 ...

  4. UVA 12075 Counting Triangles

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  5. UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)

    先看第一题,有n*m个点,求在这些点中,有多少条直线,经过了至少两点,且不是水平的也不是竖直的. 分析:由于对称性,我们只要求一个方向的线即可.该题分成两个过程,第一个过程是求出n*m的矩形中,dp[ ...

  6. 2D and 3D Linear Geometry Kernel ( Geometry Kernels) CGAL 4.13 -User Manual

    1 Introduction CGAL, the Computational Geometry Algorithms Library, is written in C++ and consists o ...

  7. IGeometryCollection Interface

    Come from ArcGIS Online IGeometryCollection Interface Provides access to members that can be used fo ...

  8. Matlab geom3d函数注释

    Matlab geom3d函数解析 geom3d函数库 geom3d库的目的是处理和可视化三维几何原语,如点.线.平面.多面体等.它提供了操作三维几何原语的底层功能,使得开发更复杂的几何算法变得更加容 ...

  9. uva 12508 - Triangles in the Grid(几何+计数)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011328934/article/details/35244875 题目链接:uva 12508 ...

随机推荐

  1. 【贪心】bzoj 3709:[PA2014]Bohater

    3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 653  Solved:  ...

  2. [转载]mvc使用JsonResult返回Json数据

    controller 中定义以下方法: public JsonResult UpdateSingle(int id, string actionName, string actionValue) { ...

  3. 互斥锁Mutex与信号量Semaphore的区别

    转自互斥锁Mutex与信号量Semaphore的区别 多线程编程中,常常会遇到这两个概念:Mutex和Semaphore,两者之间区别如下: 有人做过如下类比: Mutex是一把钥匙,一个人拿了就可进 ...

  4. jsp 获取表单值, 提交类型为multipart/form-data处理

    //tt.jsp<script type="text/javascript"> function doSubmit(){ alert("aaaaaa" ...

  5. 多线程 (四)GCD

    学习GCD要掌握几个概念 任务:需要执行的代码块可以看作一个任务 队列:把任务放到队列里,遵循先进先出的原则 队列又分为串行队列和并行队列 串行队列:顺序执行 并发队列:同时执行多个任务 同步:在当前 ...

  6. 【mysql的设计与优化专题(5)】慢查询详解

    查询mysql的操作信息 show status -- 显示全部mysql操作信息 show status like "com_insert%"; -- 获得mysql的插入次数; ...

  7. Git教程之使用GitHub

    我们一直用GitHub作为免费的远程仓库,如果是个人的开源项目,放到GitHub上是完全没有问题的.其实GitHub还是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人 ...

  8. DSP6455 DSP/BIOS中断配置问题(是否需要ECM-事件组合以及实例)

    2013-06-20 21:08:48 中断的配置有两种常用的方式: 一是通过CSL提供的API进行配置,这种方法相对DSP/BIOS偏底层,也比较麻烦:这种方法要求对中断系统的工作方式很清楚. 二是 ...

  9. 职责链实现的apache.chain使用

    其实职责链在老早就使用过了,以前在HW给Vodafone做金融项目的时候,使用职责链完成交易步骤,那时觉得这东西真好用,可以直接通过配置决定业务流程,现在终于有机会实践一下.       项目地址:h ...

  10. UVa 1641 ASCII Area

    题意: 就是用一个字符矩阵代表一个闭合的阴影部分,然后求阴影部分的面积. 分析: 一个'/'和'\'字符都代表半个小方块的面积. 关键就是判断'.'是否属于阴影部分,这才是本题的关键. 从第一列开始, ...