uva 11836(两个四面体最短距离)
来源:互联网 发布:h3c 5500 端口聚合 编辑:程序博客网 时间:2024/05/18 02:46
题意:给出两个四面体的四个顶点坐标(保证四两个面体不相交,且体积大于0),输出两个四面体的最近距离。
题解:要求最近距离分3种情况:
1.顶点到另一个四面体的某面距离
2.顶点到另一个四面体的某条边距离
3.两个四面体的边与边的最短距离(异面线段最短距离)
异面线段最短距离又分两种情况,两条线段所在直线的公垂线的最小距离点对是否都在线段上,如果在那么公垂线的距离就是异面线段最短距离,否则就是两对端点计算四个点距的最短距离了。
#include <cstdio>#include <cmath>#include <algorithm>using namespace std;const double eps = 1e-9;const double PI = acos(-1);struct Point3 { double x, y, z; Point3(double x = 0, double y = 0, double z = 0):x(x), y(y), z(z) {}};typedef Point3 Vector3;int dcmp(double x) { if (fabs(x) < eps) return 0; return x < 0 ? -1 : 1;}Vector3 operator + (Vector3 A, Vector3 B) { return Vector3(A.x + B.x, A.y + B.y, A.z + B.z); }Vector3 operator - (Vector3 A, Vector3 B) { return Vector3(A.x - B.x, A.y - B.y, A.z - B.z); }Vector3 operator * (Vector3 A, double b) { return Vector3(A.x * b, A.y * b, A.z * b); }Vector3 operator / (Vector3 A, double b) { return Vector3(A.x / b, A.y / b, A.z / b); }bool operator == (Vector3 A, Vector3 B) { return !dcmp(A.x - B.x) && !dcmp(A.y - B.y); }double Dot (Vector3 A, Vector3 B) { return A.x * B.x + A.y * B.y + A.z * B.z; }double Length(Vector3 A) { return sqrt(Dot(A, A)); }double Angle(Vector3 A, Vector3 B) { return acos(Dot(A, B) / Length(A) / Length(B)); }double torad(double deg) { return deg / 180.0 * PI; }Vector3 Cross(Vector3 A, 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(Point3 A, Point3 B, Point3 C) { return Length(Cross(B - A, C - A)); }double DistanceToPlane(const Point3& p, const Point3& p0, const Vector3& n) { return fabs(Dot(p - p0, n));}Point3 GetPlaneProjection(const Point3& p, const Point3& p0, const Vector3& n) { return p - n * Dot(p - p0, n);}double DistanceToSegment(Point3 P, Point3 A, Point3 B) { if (A == B) return Length(P - A); Vector3 v1 = B - A, v2 = P - A, v3 = P - B; if (dcmp(Dot(v1, v2)) < 0) return Length(v2); if (dcmp(Dot(v1, v3)) > 0) return Length(v3); return Length(Cross(v1, v2)) / Length(v1);}bool PointInTri(Point3 P, Point3 P0, Point3 P1, 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)) == 0;}double MinSegmentToSegmentDis(Point3 p1, Point3 p2, Point3 p3, Point3 p4) { Vector3 v = Cross(p2 - p1, p4 - p3); //公垂直线 double A = Dot(Cross(p2 - p1, v), p3 - p1); double B = Dot(Cross(p2 - p1, v), p4 - p1); double C = Dot(Cross(p3 - p4, v), p1 - p4); double D = Dot(Cross(p3 - p4, v), p2 - p4); if (dcmp(A * B) <= 0 && dcmp(C * D) <= 0) return fabs(Dot(p1 - p3, v)) / Length(v); return min(min(DistanceToSegment(p1, p3, p4), DistanceToSegment(p2, p3, p4)), min(DistanceToSegment(p3, p1, p2), DistanceToSegment(p4, p1, p2))); }Point3 P1[4], P2[4];int main() { int t; scanf("%d", &t); while (t--) { for (int i = 0; i < 4; i++) scanf("%lf%lf%lf", &P1[i].x, &P1[i].y, &P1[i].z); for (int i = 0; i < 4; i++) scanf("%lf%lf%lf", &P2[i].x, &P2[i].y, &P2[i].z); double res = 1e18; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { Vector3 v1 = P2[(j + 1) % 4] - P2[j], v2 = P2[(j + 2) % 4] - P2[j]; double z = (v2.y * v1.x - v1.y * v2.x) / (v1.y * v2.z - v2.y * v1.z); double y; if (dcmp(v1.y)) y = (-z * v1.z - v1.x) / v1.y; else y = (-z * v2.z - v2.x) / v2.y; Vector3 n = Vector3(1.0, y, z); n = n / Length(n); Point3 p = GetPlaneProjection(P1[i], P2[j], n); if (PointInTri(p, P2[j], P2[(j + 1) % 4], P2[(j + 2) % 4])) res = min(res, DistanceToPlane(P1[i], P2[j], n)); } for (int j = i + 1; j < 4; j++) res = min(res, DistanceToSegment(P1[i], P2[i], P2[j])); } for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { Vector3 v1 = P1[(j + 1) % 4] - P1[j], v2 = P1[(j + 2) % 4] - P1[j]; double z = (v2.y * v1.x - v1.y * v2.x) / (v1.y * v2.z - v2.y * v1.z); double y; if (dcmp(v1.y)) y = (-z * v1.z - v1.x) / v1.y; else y = (-z * v2.z - v2.x) / v2.y; Vector3 n = Vector3(1.0, y, z); n = n / Length(n); Point3 p = GetPlaneProjection(P2[i], P1[j], n); if (PointInTri(p, P1[j], P1[(j + 1) % 4], P1[(j + 2) % 4])) res = min(res, DistanceToPlane(P2[i], P1[j], n)); } for (int j = i + 1; j < 4; j++) res = min(res, DistanceToSegment(P2[i], P1[i], P1[j])); } for (int i = 0; i < 4; i++) for (int j = i + 1; j < 4; j++) for (int k = 0; k < 4; k++) for (int l = k + 1; l < 4; l++) res = min(res, MinSegmentToSegmentDis(P1[i], P1[j], P2[k], P2[l])); printf("%.2lf\n", res); } return 0;}
0 0
- uva 11836(两个四面体最短距离)
- UVa 11836Star War 四面体四面体之间的距离(三维几何)
- 两个面之间的最短距离算法(记录)
- 两个单词之间的最短距离
- UVA 152-Tree's a Crowd(暴力求解三维坐标求最短距离)
- poj 3608 Bridge Across Islands(两个凸包的最短距离)
- 在二维数组寻找两个定点的最短距离(递归)
- POJ 3862 Asteroids(两个三维凸包的重心到表面最短距离和)
- 最短距离
- 最短距离
- 最短距离
- 最短距离
- PAT程序设计练习——甲级1003(任意两个城市最短距离、Floyd最短路径算法)
- UVa 10263 Railway (点到线段的最短距离)
- Floyd算法,求图中两个点之间的最短距离
- Hard 大文本找两个单词最短距离 @CareerCup
- 给出两个单词,找到它们的最短距离
- bfs两个起点求两者共同的最短距离
- Django分页的基本实现办法
- Android基础知识杂记
- SSH框架总结
- HDU-OJ-1029 Ignatius and the Princess IV-出现至少(N+1)/2次的数
- scala学习:Scala文件的读取、写入、控制台输入操作代码
- uva 11836(两个四面体最短距离)
- 简单的HTML5在线画板
- 管道,信号量,共享内存,socket的实际使用场景和NSPipe管道的使用
- 汇编语言实现电子闹钟
- 《小强升职记》 读书笔记
- 用C#生成KML路径文件(上篇)
- Teaching Mario to play with himself: AI, machine learning, and Super Mario Bros.
- pdo对象认识与应用
- 数据结构学习笔记(二)---单链表