uva 11275

题意:三维空间有两个三角形,问两者是否有公共点。
题解:如果相交,三角形的某条边一定经过另一个三角形的内部,边上,或者顶点。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
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);
}
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));
}
//点p到平面p0 - n的距离,n必须为单位法向量
double DistanceToPlane(const Point3& p, const Point3& p0, const Vector3& n) {
    return fabs(Dot(p - p0, n));
}
//点p在平面上的投影i,n必须为单位法向量
Point3 GetPlaneProjection(const Point3& p, const Point3& p0, const Vector3& n) {
    return p - n * Dot(p - p0, n);
}
//直线p1p2到平面p0-n的交点
Point3 LinePlaneIntersection(Point3 p1, Point3 p2, Point3 p0, Vector3 n) {
    Vector3 v = p2 - p1;
    double t = Dot(n, p0 - p1) / Dot(n, p2 - p1);//判断分母是否为0
    return p1 + v * t; //如果是线段,判断t是不是在0和1之间
}
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));
}
//点p是否在三角形P0P1P2中,假定p在三角形所在平面内
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;
}
//判断线段和三角形是否相交
//三角形p0p1p2和线段ab
bool TriSegmentIntersection(Point3 P0, Point3 P1, Point3 P2, Point3 A, Point3 B, Point3& P) {
    Vector3 n = Cross(P1 - P0, P2 - P0);
    if (dcmp(Dot(n, B - A)) == 0)
        return false; // 平行或共面
    double t = Dot(n, P0 - A) / Dot(n, B - A);
    if (dcmp(t) < 0 || dcmp(t - 1) > 0)
        return false; //交点不在线段AB上
    P = A + (B - A) * t;
    return PointInTri(P, P0, P1, P2); //判断交点是否在三角形内
}
//点p到直线AB的距离,面积法
double DistanceToLine(Point3 P, Point3 A, Point3 B) {
    Vector3 v1 = B - A, v2 = P - A;
    return Length(Cross(v1, v2)) / Length(v1);
}
//点到线段AB的距离
double DistanceToSegment(Point3 P, Point3 A, Point3 B) {
    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);
}
//四面体体积
double Volume6(Point3 A, Point3 B, Point3 C, Point3 D) {
    return Dot(D - A, Cross(B - A, C - A));
}

bool TriTriIntersection(Point3* Tri1, Point3* Tri2) {
    Point3 P;
    for (int i = 0; i < 3; i++) {
        if (TriSegmentIntersection(Tri1[0], Tri1[1], Tri1[2], Tri2[i], Tri2[(i + 1) % 3], P))
            return true;
        if (TriSegmentIntersection(Tri2[0], Tri2[1], Tri2[2], Tri1[i], Tri1[(i + 1) % 3], P))
            return true;
    }
    return false;
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        Point3 Tri1[3], Tri2[3];
        for (int i = 0; i < 3; i++)
            scanf("%lf%lf%lf", &Tri1[i].x, &Tri1[i].y, &Tri1[i].z);
        for (int i = 0; i < 3; i++)
            scanf("%lf%lf%lf", &Tri2[i].x, &Tri2[i].y, &Tri2[i].z);
        printf("%d\n", TriTriIntersection(Tri1, Tri2) ? 1 : 0);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值