Intersection
给出二维平面中一条线段和一个矩形,问线段和矩形是否有交点,矩形包括边和内部。
解题思路先判断线段和四条边是否相交,如果没交点,再继续判断线段是否在矩形内。
判断线段相交需要使用快速排斥实验和跨立实验。
直接使用跨立实验会有问题,比如其中一条线段退化成一个点的情况,可以通过跨立实验,但是不能通过快速排斥实验:
代码#include参考资料using namespace std; const int N = 1e5 + 5; typedef struct Point { int x, y; Point operator-(const Point temp) { Point T; T.x = x - temp.x; T.y = y - temp.y; return T; } bool operator==(const Point temp) { if (x == temp.x && y == temp.y) return 1; return 0; } } Vector; double cross(Vector A, Vector B) { return A.x * B.y - B.x * A.y; } const double eps = 0; int sign(double x) { if (x < eps) return -1; else if (x > eps) return 1; return 0; } bool f(Point a1, Point a2, Point b1, Point b2) { if (max(a1.x, a2.x) < min(b1.x, b2.x) || max(a1.y, a2.y) < min(b1.y, b2.y) || max(b1.x, b2.x) < min(a1.x, a2.x) || max(b1.y, b2.y) < min(a1.y, a2.y)) return 0; //先通过快速排斥实验 double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1); double c3 = cross(b2 - b1, a2 - b1), c4 = cross(b2 - b1, a1 - b1); return sign(c1) * sign(c2) <= 0 && sign(c3) * sign(c4) <= 0; } bool f2(Point X, Point A, Point B, Point C, Point D) { if (cross(A - X, B - X) * cross(C - X, D - X) < eps) return 1; return 0; } void solve() { Point A, B, C, D, E, F; cin >> E.x >> E.y >> F.x >> F.y; cin >> A.x >> A.y >> D.x >> D.y; B.x = A.x, B.y = D.y; C.x = D.x, C.y = A.y; if (f(A, B, E, F) || f(B, D, E, F) || f(C, D, E, F) || f(A, C, E, F) || (f2(E, A, B, C, D) && f2(E, A, C, B, D)) || (f2(F, A, B, C, D) && f2(F, A, C, B, D))) printf("Tn"); else printf("Fn"); } int main() { int t; cin >> t; while (t--) solve(); return 0; }
- 【计算几何】快速排斥实验和跨立实验



