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

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

 #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. 【string】KMP, 扩展KMP,trie,SA,ACAM,SAM,最小表示法

    [KMP] 学习KMP,我们先要知道KMP是干什么的. KMP?KMPLAYER?看**? 正如AC自动机,KMP为什么要叫KMP是因为它是由三个人共同研究得到的- .- 啊跑题了. KMP就是给出一 ...

  2. Struts2自定义拦截器实例—登陆权限验证

    版本:struts2.1.6 此实例实现功能:用户需要指定用户名登陆,登陆成功进入相应页面执行操作,否则返回到登陆页面进行登陆,当直接访问操作页面(登陆后才能访问的页面)时则不允许,须返回登陆页面. ...

  3. leetcode5 Implement strstr() 实现strstr函数功能

    Implement strstr() 实现strstr函数功能 whowhoha@outlook.com Question: Implement strstr(). Returns the index ...

  4. 单例模式Java“完美”实现

    我们通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案. public cl ...

  5. POJ 1220 NUMBER BASE CONVERSION(较复杂的进制转换)

    题目链接 题意 : 给你一个a进制的数串s,让你转化成b进制的输出. A = 10, B = 11, ..., Z = 35, a = 36, b = 37, ..., z = 61,0到9还是原来的 ...

  6. 在RedHat5.4 LINUX 安装mySQL数据库

    linux下mysql 最新版安装图解教程 1. 查看当前安装的linux版本 通过上图中的数据可以看出安装的版本为RedHat5.4,所以我们需要下载RedHat5.4对应的mysql安装包

  7. 解决浮层弹出如何加上datepicker,并且浮动在上面

    最近在做一个弹出层上弹出的对话框中能弹出一个截止时间的选择框,这个选择框使用datepicker来做. 效果大致是这样的: 但是在做的时候,遇到一个问题,datepicker在弹出层的时候,时间选择框 ...

  8. 如何用Java语言向串口读写数据

    原作者:赛迪网作者 shihuchen ,我在他的基础上进行了部分修改 [赛迪网讯]串口, RS-232-C(又称EIA RS-232-C,以下简称RS232)是在1970年由美国电子工业协会(EIA ...

  9. 组策略限制添加用户作为服务登录导致ITAtomcat服务无法启动(log on as a service)

    [故障类型]:ITA tomcat服务器无法启动. [关 键 词]:Logon as a service  作为服务登录  tomcat  loggeter [适用版本]:FusionCloud So ...

  10. R语言中的箱图介绍 boxplot

    画箱图的函数: boxplot()##help(boxplot)查询具体用法   图例的解释: 如下图,是两个简单的箱图. 中间的箱子的上下边,分别是第三,一个四分位数. 中间的黑线是第二四分位数(中 ...