uva 11275 3D Triangles
题意:三维空间中,给出两个三角形的左边,问是否相交。
面积法判断点在三角形内:
- #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的更多相关文章
- uva 11275 3D Triangles (3D-Geometry)
uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem= ...
- UVA 12075 - Counting Triangles(容斥原理计数)
题目链接:12075 - Counting Triangles 题意:求n * m矩形内,最多能组成几个三角形 这题和UVA 1393类似,把总情况扣去三点共线情况,那么问题转化为求三点共线的情况,对 ...
- [ACM_几何] F. 3D Triangles (三维三角行相交)
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28235#problem/A 题目大意:给出三维空间两个三角形三个顶点,判断二者是否有公共 ...
- UVA 12075 Counting Triangles
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...
- UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
先看第一题,有n*m个点,求在这些点中,有多少条直线,经过了至少两点,且不是水平的也不是竖直的. 分析:由于对称性,我们只要求一个方向的线即可.该题分成两个过程,第一个过程是求出n*m的矩形中,dp[ ...
- 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 ...
- IGeometryCollection Interface
Come from ArcGIS Online IGeometryCollection Interface Provides access to members that can be used fo ...
- Matlab geom3d函数注释
Matlab geom3d函数解析 geom3d函数库 geom3d库的目的是处理和可视化三维几何原语,如点.线.平面.多面体等.它提供了操作三维几何原语的底层功能,使得开发更复杂的几何算法变得更加容 ...
- uva 12508 - Triangles in the Grid(几何+计数)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011328934/article/details/35244875 题目链接:uva 12508 ...
随机推荐
- Spring MVC控制层的返回类型--String类型与Bean类型
SpringMVC控制层的返回类型形式多样,现拿其中的两种--String类型与Bean类型作以说明. 一.测试项目的结构 说明:(jsp的名字没起好) 控制层:UserController.java ...
- 解决WIN8 磁盘100 活动占用100% win8硬盘一直响
一.先看最终效果: 二.再说解决办法: 1.任务管理器关闭进程 taskhost.exe和类似于taskhostxx.exe开头的进程. 2.在电源管理里面设置2分钟不使用硬盘则关闭硬盘,看我的截 ...
- 获取属性名:PropertyNameHelper
获取属性名:PropertyNameHelper namespace NCS.Infrastructure.Querying { public static class PropertyNameHel ...
- spoj 394
每段可以连续的串的可能性是个Fibonacci数列 但是直接dp更好吧~~ #include <cstdio> #include <cstring> using names ...
- HTTPS访问:weblogic下配置SSL
进入Weblogic安装路径下的JDK安装目录bin文件下,通过keytool工具生成密钥对(标识密钥库) 输入命令,生成密钥 keytool.exe -genkey -v -alias weblog ...
- easyui源码翻译1.32+API翻译全篇导航 (提供下载源码)
前言 EasyUI每个组件都会有 属性.方法.事件 属性 所有的属性都定义在jQuery.fn.{plugin}.defaults里面.例如,对话框属性定义在jQuery.fn.dialog.defa ...
- iOS 10 使用相机及相簿闪退的问题修正
http://www.cnblogs.com/onechen/p/5935579.html
- [企业级linux安全管理]- 安全管理基础(1)
1. 操作条件: (1)装有 Cent OS Linux 操作系统的虚拟机一台 2. 背景: 某企业有一台服务器,其信息如下: (1) 该服务器上存在管理员 root,密码为 root,另存有一些 ...
- Android EditView 阻止软键盘自动弹出
最近再做一个查询内的小应用,界面最上面是一个EditText查询框,进行Activity后,总会弹起软键盘.这样就挡住了查询框下面的其他查询条件 控件,感觉很不友好.所以现在要做的就是在进入Activ ...
- 一篇文章教会你,如何做到招聘要求中的“要有扎实的Java基础
来历 本文来自于一次和群里猿友的交流,具体的情况且听LZ慢慢道来. 一日,LZ在群里发话,“招人啦.” 然某群友曰,“群主,俺想去.” LZ回之,“你年几何?” 群友曰,“两年也.” LZ憾言之,“惜 ...