几何模板

#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector> 
#include<algorithm>
#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const double eps = 1e-8;
int dcmp(double x) {
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1 : 1;
}
struct point{
    double x,y;
    point(){}
    point(double _x,double _y)
    {
        x=_x;y=_y;
    }
    double operator ^(const point &c)const
    {
        return x*c.y - y*c.x;
    }
};
point operator + (point A, point B) { return point(A.x + B.x, A.y + B.y); }
point operator - (point A, point B) { return point(A.x - B.x, A.y - B.y); }
point operator * (point A, double p) { return point(A.x * p, A.y * p); }
point operator / (point A, double p) { return point(A.x/p, A.y/p); }
bool operator < (const point& a, const point& b) {
    return a.x < b.x || (a.x == b.x && a.y < b.y); //   逆时针求凸包a.y < b.y || (a.y == b.y && a.x < b.x);
}
bool operator == (const point& a, const point& b) {
    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
struct LINE{
    point a,b;
    LINE(){}
    LINE(point _a,point _b){
        a=_a;b=_b;
    }
};

double Dot(point A, point B) { return A.x * B.x + A.y * B.y; } //点积
double Cross(point A, point B) { return A.x * B.y - A.y * B.x; } //叉积
double intersection(point A,point B,point C,point D) // 求两直线交点的x坐标 
{
	double area1=Cross(B-A,C-A);
	double area2=Cross(B-A,D-A);
	int c=dcmp(area1);
	int d=dcmp(area2);
 
	if(c*d<0) //CD在AB的两侧,规范相交
		return (area2*C.x - area1*D.x)/(area2-area1);  //黑书P357交点计算公式
 
	if(c*d==0)   //CD的其中一个端点在AB上,不规范相交
		if(c==0)
			return C.x;//C在AB上,返回AB与CD非规范相交时的交点C的横坐标
		else
			return D.x;//D在AB上,返回AB与CD非规范相交时的交点D的横坐标
 
	return -99999;  //CD在AB同侧,无交点,返回 负无穷
}
//两直线交点(点,向量,点,向量)
point Getlinenode(point P, point v, point Q, point w) {
//    printf("w.x=%f,w.y=%f\n",w.x,w.y);
    point u = P - Q;
    double t = Cross(w, u) / Cross(v, w);
    return P + v * t;
}
 //判断两线段是否相交(不包括端点)
bool seg_seg_Cross(point s1,point e1,point s2,point e2)
{
    ///第一步,快速排斥实验
    if(!(min(s1.x,e1.x)<=max(s2.x,e2.x)&&min(s2.x,e2.x)<=max(s1.x,e1.x)&&
       min(s1.y,e1.y)<=max(s2.y,e2.y)&&min(s2.y,e2.y)<=max(s1.y,e1.y))) return false;
 
    double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
    double c3=Cross(s1-s2,e2-s2),c4=Cross(e2-s2,e1-s2);
    if(dcmp(c1*c2)>=0&&dcmp(c3*c4)>=0) return 1;
    return 0;
}
//判断线段相交
bool inter(LINE l1,LINE l2)
{
    return
    max(l1.a.x,l1.b.x) >= min(l2.a.x,l2.b.x) &&
    max(l2.a.x,l2.b.x) >= min(l1.a.x,l1.b.x) &&
    max(l1.a.y,l1.b.y) >= min(l2.a.y,l2.b.y) &&
    max(l2.a.y,l2.b.y) >= min(l1.a.y,l1.b.y) &&
    dcmp((l2.a-l1.b)^(l1.a-l1.b))*dcmp((l2.b-l1.b)^(l1.a-l1.b)) <= 0 &&
    dcmp((l1.a-l2.b)^(l2.a-l2.b))*dcmp((l1.b-l2.b)^(l2.a-l2.b)) <= 0;
}

//判断点在线段上
bool OnSeg(point P,LINE L)
{
    return
    dcmp((L.a-P)^(L.b-P)) == 0 &&
    dcmp((P.x - L.a.x) * (P.x - L.b.x)) <= 0 &&
    dcmp((P.y - L.a.y) * (P.y - L.b.y)) <= 0;
}
//判断直线与线段相交,s1e1表示直线,s2e2表示线段
bool line_seg_Cross(point s1,point e1,point s2,point e2) 
{
    double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
    //==0表示,相交于端点也认定为相交
    if(dcmp(c1*c2)>=0) return true;
    return false;
}
//点距离 
double distance(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
// 点集凸包
// 如果不希望在凸包的边上有输入点,把两个 <= 改成 <
// 如果不介意点集被修改,可以改成传递引用
vector<point> ConvexHull(vector<point> p) {
    // 预处理,删除重复点
    sort(p.begin(), p.end());
    p.erase(unique(p.begin(), p.end()), p.end());
 
    int n = p.size();
    int m = 0;
    vector<point> ch(n+1);
    for(int i = 0; i < n; i++) {
        while(m > 1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--;
        ch[m++] = p[i];
    }
    int k = m;
    for(int i = n-2; i >= 0; i--) {
        while(m > k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-2]) < 0) m--;
        ch[m++] = p[i];
    }
    if(n > 1) m--;
    ch.resize(m);
    return ch;
}
bool OnSegment(const point& p, const point& a1, const point& a2) {
    return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
}
//点是否在凸包内 
int IsPointInPolygon(const point& p, const vector<point>& poly) {
    int wn = 0;
    int n = poly.size();
    for(int i=0; i<n; ++i) {
        const point& p1 = poly[i];
        const point& p2 = poly[(i+1)%n];
        if(p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1;//在边界上
        int k = dcmp(Cross(p2-p1, p-p1));
        int d1 = dcmp(p1.y - p.y);
        int d2 = dcmp(p2.y - p.y);
        if(k > 0 && d1 <= 0 && d2 > 0) wn++;
        if(k < 0 && d2 <= 0 && d1 > 0) wn--;
    }
    if(wn != 0) return 1;
    return 0;
}
bool SegmentProperIntersection(const point& a1, const point& a2, const point& b1, const point& b2) {
    double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
           c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
 //判断2个凸包是否相交 
bool ConvexPolygonDisjoint(const vector<point> ch1, const vector<point> ch2) {
    int c1 = ch1.size();
    int c2 = ch2.size();
    for(int i=0; i<c1; ++i)
        if(IsPointInPolygon(ch1[i], ch2) != 0) return false;
    for(int i=0; i<c2; ++i)
        if(IsPointInPolygon(ch2[i], ch1) != 0) return false;
    for(int i=0; i<c1; ++i)
        for(int j=0; j<c2; ++j)
            if(SegmentProperIntersection(ch1[i], ch1[(i+1)%c1], ch2[j], ch2[(j+1)%c2])) return false;
    return true;
}


LINE l[10];
//极角排序  速度快,精度小 
int cmps(point aa,point bb){
	return atan2(aa.y,aa.x) < atan2(bb.y,bb.x);
}
//关于c点极角排序 
bool cmp2(point a,point b) 
{
    point c;//原点
    c.x = 0 , c.y = 0;//可修改 
    if(Cross(a-c,b-c)>0) return 1;
    return 0;
}
int Quadrant(point a)	//象限排序,注意包含四个坐标轴
{
    if(a.x>0&&a.y>=0)  return 1;
    if(a.x<=0&&a.y>0)  return 2;
    if(a.x<0&&a.y<=0)  return 3;
    if(a.x>=0&&a.y<0)  return 4;
}
bool cmp3(point a,point b)  //先按象限从小到大排序 再按极角从小到大排序
{
    if(Quadrant(a)==Quadrant(b))//返回值就是象限
        return cmps(a,b);
    else Quadrant(a)<Quadrant(b);
}

int main(){
	int n;
	scanf("%d",&n);
	double xx,xxx,yy,yyy;
	int f;
	while(n--){
		f=0;
		scanf("%lf %lf %lf %lf",&l[0].a.x,&l[0].a.y,&l[0].b.x,&l[0].b.y);
		scanf("%lf %lf %lf %lf",&xx,&yy,&xxx,&yyy);
		double mxx = max(xx,xxx),mixx = min(xx,xxx);
		xx = mixx , xxx = mxx;
		double myy = max(yy,yyy),miyy = min(yy,yyy);
		yy = miyy , yyy = myy;
		if(l[0].a.x < l[0].b.x){
			swap(l[0].a , l[0].b);
		}
		l[1].a.x = xx , l[1].a.y = yy , l[1].b.x = xx , l[1].b.y = yyy;
		l[2].a.x = xx , l[2].a.y = yy , l[2].b.x = xxx , l[2].b.y = yy;
		l[3].a.x = xxx , l[3].a.y = yyy , l[3].b.x = xx , l[3].b.y = yyy;
		l[4].a.x = xxx , l[4].a.y = yyy , l[4].b.x = xxx , l[4].b.y = yy;
		for(int i=1;i<=4;i++){
			if(l[i].a.x > l[i].b.x) swap(l[i].a,l[i].b);
			if( inter(l[0],l[i]) || (OnSeg(l[0].a,l[i]) || (OnSeg(l[0].b,l[i]))  )/*OnSeg(l[0].a,l[i]) || OnSeg(l[0].b,l[i])|| line_seg_Cross(l[0].a,l[0].b,l[i].a,l[i].b)*/){
				f=1;
				break;
			}
		} 
		if(l[0].a.x+eps < xxx && l[0].a.x >eps+ xx && l[0].a.y > eps+yy && l[0].a.y+eps < yyy)
		f=1;
		if(f==0){
			cout << "F" <<endl;
		}
		else{
			cout << "T" <<endl;
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值