现在的位置: 首页 > 综合 > 正文

POJ 1410 Intersection

2017年10月18日 ⁄ 综合 ⁄ 共 2429字 ⁄ 字号 评论关闭

判断线段与多边形是否相交。

模板:

#include <stdio.h>
#include <math.h>
#include <algorithm>

using namespace std;
#define Pi 3.14159265358979
#define PRECISION 1e-8

//点
typedef struct {
    double x,y;
} POINT;

//直线两点的表达
struct LINE{
    POINT p1,p2;
};

//多边形结构体
struct POLY{
    int n;
    double area;
    POINT plist[15];
};

//与0作比较,小于精度则认为是和0相等
int cmpzero(double d){
    return (fabs(d) < PRECISION)?0:(d>0?1:-1);
}

//向量点积
double dotdet(double x1,double y1,double x2,double y2){
    return x1*x2 + y1 * y2;
}

//向量叉积
double cross_det(double x1,double y1,double x2,double y2){
    return x1*y2 - x2*y1;
}

//右手螺旋定则,1:a在cd右侧;-1:a在cd左侧;0:三点共线
int cross(POINT &a,POINT &c,POINT &d){
    return cmpzero(cross_det(a.x - c.x,a.y - c.y,d.x - c.x,d.y - c.y));
}

//在cross(a,c,d) == 0的基础上,可判断点a是否在cd内部
int between(POINT &a,POINT &c,POINT &d){
    return cmpzero(dotdet(c.x - a.x,c.y - a.y, d.x - a.x, d.y - a.y)) != 1;
}

//两线段相交情况:0:不想交,1:规范相交,-1:不规范相交(交于端点或重合)
int seg_intersect(POINT &a,POINT &b,POINT &c,POINT &d){
    int a_cd = cross(a,c,d);
    if(a_cd == 0 && between(a,c,d)){return 2;}
    int b_cd = cross(b,c,d);
    if(b_cd == 0 && between(b,c,d)){return 2;}
    int c_ab = cross(c,a,b);
    if(c_ab == 0 && between(c,a,b)){return 2;}
    int d_ab = cross(d,a,b);
    if(d_ab == 0 && between(d,a,b)){return 2;}
    if((a_cd^b_cd) == -2 && (c_ab ^ d_ab) == -2){
        return 1;
    }
    return 0;
}

//使用有向面积法判断点是否在多边形内
int point_in_poly(POLY &p,POINT &pt){
    double s = 0.0;
    for(int i = 0; i < p.n; i++){
        s += fabs(cross_det(p.plist[i].x - pt.x,p.plist[i].y - pt.y,p.plist[(i+1)%p.n].x - pt.x,p.plist[(i+1)%p.n].y - pt.y));
    }
    if(cmpzero(s - p.area) == 0 ){
        return 1;
    }
    return 0;
}

//计算多边形面积
void area(POLY &p){
    double s = p.plist[0].y * (p.plist[p.n - 1].x - p.plist[1].x);
    for(int i = 1; i < p.n; i++){
        s += p.plist[i].y * (p.plist[i - 1].x - p.plist[(i+1)%p.n].x);
    }
    p.area = s;
}

//判断线段是否与多边形相交
int rec_seg_intersect(POLY &p,LINE &l){
    if(point_in_poly(p,l.p1) && point_in_poly(p,l.p2)){return 1;}
    else if(seg_intersect(l.p1,l.p2,p.plist[0],p.plist[1])
            || seg_intersect(l.p1,l.p2,p.plist[1],p.plist[2])
            || seg_intersect(l.p1,l.p2,p.plist[2],p.plist[3])
            || seg_intersect(l.p1,l.p2,p.plist[3],p.plist[0]))
            return 1;
    return 0;
}

int main() {
    int n,m,i,min;
    int T;
    POLY rec;
    LINE l;
    double xleft,ytop,xright,ybottom;
    scanf("%d",&T);
    while(T--){
        scanf("%lf%lf%lf%lf",&l.p1.x,&l.p1.y,&l.p2.x,&l.p2.y);
        scanf("%lf%lf%lf%lf",&xleft,&ytop,&xright,&ybottom);
        if(xleft > xright){swap(xleft,xright);}
        if(ytop < ybottom){swap(ytop,ybottom);}
        rec.n = 4;
        rec.plist[0].x = xleft, rec.plist[0].y = ytop;
        rec.plist[1].x = xleft, rec.plist[1].y = ybottom;
        rec.plist[2].x = xright, rec.plist[2].y = ybottom;
        rec.plist[3].x = xright, rec.plist[3].y = ytop;
        area(rec);
        puts(rec_seg_intersect(rec,l)?"T":"F");
    }
    return 0;
}

参考文章:

http://hi.baidu.com/novosbirsk/item/cbce6f06174e1e16cc34ea13

抱歉!评论已关闭.