Intersection
题意: 给出一个矩形和一条线段,问是否存在交点。注意这里的矩形是实心的,所以线段在矩形内部也算相交,并且这题要求的是求非规范相交,即端点重合算相交,并且给出的矩形的坐标也不是按照左上角和右下角的顺序给出的,还需要自己判断一下,所以这题坑很多。
题解: 知道了上面这些坑点就很好做了,把矩形看成四条线段判断和线段的相交情况,然后在判断一下线段是否在矩形内部。
// #include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
using namespace std;
const double pi = acos((double)(-1));
#define inf 0x3f3f3f3f
#define ll long long
#define eps 1e-8
const int maxn = 110;
const int mod = 1e9 + 7;
int sgn(double x){ //判断x是否为0
if(fabs(x) < eps) return 0;
else return x < 0?-1:1;
}
int dcmp(double x, double y){ //比较两个浮点数
if(fabs(x - y) < eps) return 0;
else return x < y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point B){return Point(x + B.x,y + B.y);}
Point operator - (Point B){return Point(x - B.x,y - B.y);}
Point operator * (double k){return Point(x*k,y*k);}
Point operator / (double k){return Point(x/k,y/k);}
bool operator == (Point B){return sgn(x - B.x) == 0 && sgn(y - B.y) == 0;}
}P[maxn];
typedef Point Vector; //用点的数据结构定义向量
struct Line{
Point p1,p2;
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //y = kx + b
p1 = p;
if(sgn(angle - pi/2) == 0){p2 = (p1 + Point(0,1));}
else {p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax + by + c = 0
if(sgn(a) == 0){
p1 = Point(0, -c/b);
p2 = Point(1, -c/b);
}
else if(sgn(b) == 0){
p1 = Point(-c/a,0);
p2 = Point(-c/a,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c - a)/b);
}
}
}L[maxn];
bool cmp(const Line &v1, const Line &v2){
if(v1.p1.x != v2.p1.x) return v1.p1.x < v2.p1.x;
return v1.p1.y < v2.p1.y;
}
typedef Line Segment;
double Dist(Point A,Point B){
return sqrt((A.x - B.x)*(A.x - B.x) + (A.y - B.y)*(A.y - B.y));
}
double Dot(Vector A,Vector B){return A.x*B.x + A.y*B.y;} //计算向量点积,>0锐角,<0钝角,=0直角 A·B = fabs(A)*fabs(B)*cos(angle)
double Len(Vector A){return sqrt(Dot(A,A));} //计算向量长度
double Len2(Vector A){return Dot(A,A);} //向量长度的平方
double Angle(Vector A,Vector B){return acos(Dot(A,B)/Len(A)/Len(B));} //计算两向量的夹角
double Cross(Vector A,Vector B){return A.x*B.y - A.y*B.x;} //计算向量叉积,叉积有正负,A×B>0(B在A的逆时针方向),B×A<0 A×B = fabs(A)*fabs(B)*sin(angle)
double Area(Vector A,Vector B,Vector C){return Cross(B- A,C - A);} //以A为公共点的两向量构成的平行四边形面积
Vector Rotate(Vector A,double rad){ //计算一个点逆时针选择rad度后的点
return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));
}
Vector Normal(Vector A){return Vector(-A.y/Len(A),A.x/Len(A));} //求该向量的法向量
bool Parallel(Vector A,Vector B){return sgn(Cross(A,B)) == 0;} //用叉积判断两向量是否平行或重合
int Point_line_relation(Point p, Line v){ //点和线的位置关系
int c = sgn(Cross(p - v.p1, v.p2 - v.p1));
if(c < 0) return 1; //p在v的左边(上面)
if(c > 0) return 2; //p在v的右边(下面)
return 0;
}
bool Point_on_seg(Point p, Line v){ //0为不在线段上,1为在线段上
return sgn(Cross(p - v.p1, v.p2 - v.p1)) == 0 && sgn(Dot(p - v.p1, p - v.p2)) <=0;
}
double Dis_point_line(Point p, Line v){ //点到直线的距离
return fabs(Cross(p - v.p1, v.p2 - v.p1))/Dist(v.p1, v.p2);
}
Point Point_line_proj(Point p, Line v){ //点在直线上的投影
double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
return v.p1 + (v.p2 - v.p1) * k;
}
Point Point_line_symmetry(Point p, Line v){ //点关于直线的对称点
Point q = Point_line_proj(p, v);
return Point(2 * q.x - p.x, 2 * q.y - p.y);
}
double Dis_point_seg(Point p, Segment v){ //点到线段的距离
if(sgn(Dot(p - v.p1, v.p2 - v.p1)) < 0 || sgn(Dot(p - v.p2, v.p1 - v.p2)) < 0)
return min(Dist(p, v.p1), Dist(p, v.p2));
return Dis_point_line(p, v);
}
int Line_relation(Line v1, Line v2){ //两条直线的位置关系
if(sgn(Cross(v1.p2 - v1.p1, v2.p2 - v2.p1)) == 0){
if(Point_line_relation(v1.p1, v2) == 0) return 1; //重合
else return 0; //平行
}
return 2; //相交
}
Point Cross_point(Point a, Point b, Point c, Point d){ //求两条直线的交点,Line1:ab,Line2:cd,两直线不平行不共线
double s1 = Cross(b - a, c - a);
double s2 = Cross(b - a, d - a);
return Point(c.x * s2 - d.x * s1, c.y * s2 - d.y * s1) / (s2 - s1);
}
bool Cross_segment(Point a, Point b, Point c, Point d){ //两线段是否规范相交 即如果一条线段的一个端点恰在另一条线段上则不视为相交;如果两条线段部分重合,也不视为相交。
double c1 = Cross(b - a, c - a), c2 = Cross(b - a, d - a);
double d1 = Cross(d - c, a - c), d2 = Cross(d - c, b - c);
return sgn(c1) * sgn(c2) < 0 && sgn(d1) * sgn(d2) < 0; //1:相交,0:不相交,端点重合不相交
}
bool Cross_segment1(Point a, Point b, Point c, Point d){ //两线段是否非规范相交
return
max(a.x, b.x) >= min(c.x, d.x)&&
max(c.x, d.x) >= min(a.x, b.x)&&
max(a.y, b.y) >= min(c.y, d.y)&&
max(c.y, d.y) >= min(a.y, b.y)&&
sgn(Cross(b - a, c - a)) * sgn(Cross(b - a, d - a)) <= 0&&
sgn(Cross(d - c, a - c)) * sgn(Cross(d - c, b - c)) <= 0;
}
int n;
double X1, X2, Y1, Y2, topx, topy, botx, boty, X3, X4, Y3, Y4;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
while(n--){
cin>>X1>>Y1>>X2>>Y2>>X3>>Y3>>X4>>Y4;
topx = max(X3, X4);
botx = min(X3, X4);
topy = max(Y3, Y4);
boty = min(Y3, Y4);
P[1].x = X1;
P[1].y = Y1;
P[2].x = X2;
P[2].y = Y2;
P[3].x = topx;
P[3].y = topy;
P[4].x = topx;
P[4].y = boty;
P[5].x = botx;
P[5].y = boty;
P[6].x = botx;
P[6].y = topy;
int f = 0;
if(Cross_segment1(P[1], P[2], P[3], P[4])) f = 1;
if(Cross_segment1(P[1], P[2], P[3], P[6])) f = 1;
if(Cross_segment1(P[1], P[2], P[5], P[4])) f = 1;
if(Cross_segment1(P[1], P[2], P[5], P[6])) f = 1;
if(max(X1, X2) < topx && max(Y1, Y2) < topy && min(X1, X2) > botx && min(Y1, Y2) > boty) f = 1;
if(f) cout<<"T"<<endl;
else cout<<"F"<<endl;
}
return 0;
}