计算几何二维模板

来源:互联网 发布:纳什 数据库 编辑:程序博客网 时间:2024/05/16 09:01

以POJ1127作为例题分析模板

/**    题意: 这道题目问的是:给你一些线段,求出哪些线段是相连的,哪些是不相连的。相连包括间接相连,        即这两条线段本身不直接相连,而是通过其它线段的连接而间接相连。解决这道题目的关键要解决两个问题:        1.判断两条线段是否直接相连,即它们相交与否,这是一个几何问题;        2.如果某两条线段不相交,那么它们是否通过其它线段的连接而间接相连。如果把相连的线段看做是一个集合,        这个问题变成判断这两条线段是否处于同一个集合中,我们可以用并查集这个数据结构去解决这个问题。    关键:判断两个线段是否有交点(交点在线段上) 有两个思路        1.快速排斥试验和跨立试验        /**        bool isIntersect(Point p1,Point p2,Point q1,Point q2)        {            ///快速排斥 - 两条线段所构成的矩形有相交            if(max(p1.x,p2.x)<min(q1.x,q2.x)||max(q1.x,q2.x)<min(p1.x,p2.x)||max(p1.y,p2.y)<min(q1.y,q2.y)||max(q1.y,q2.y)<min(p1.y,p2.y))                return 0;            ///跨立试验 如果 p1p2 跨立 q1q2 则 p1-q1,p2-q1一定在q2 - q1两侧 同理 q1-p1,q2-p1 在 p2 - p1 两侧            if(dot(q2 - q1,p1 - q1)*dot(q2 - q1,p2 - q1)<=0 && dot(p2 - p1,q1 - p1)*dot(p2 - p1,q2 - p1)<=0)                return 1;            else                return 0;        }        2.求交点,判断交点在两条线段上 || 平行的时候要特殊判断是否有重合        /**        if(平行) // 两条线段向量 det 外积 == 0        {            特殊判断下是否存在重合            bool flag = online(ben[i].a,ben[j])||online(ben[i].b,ben[j])||online(ben[j].a,ben[i])||online(ben[j].b,ben[i]);            return flag;        }        else    //相交        {            通过等分定理利用外积求出的面积比=线段比 => 交点            判断交点是否同时满足在两条线段上online(交点,line a) && online(交点,line b);        }*/#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const double eps = 1e-10;const double pi = acos(-1.0);int cmp(double x,double b){    if(fabs(x - b) < eps) return 0;    if(x > b) return 1;    return -1;}struct point{    double x,y;    point() {}    point(double a,double b):x(a),y(b){}    void input() {        scanf("%lf%lf",&x,&y);    }    friend point operator + (const point &a,const point &b){        return point(a.x+b.x,a.y+b.y);    }    friend point operator - (const point &a,const point &b){        return point(a.x-b.x,a.y-b.y);    }    friend bool operator == (const point &a,const point &b){        return !cmp(a.x,b.x) && !cmp(a.y,b.y);    }    friend point operator * (const point &a,const double &b){        return point(a.x*b,a.y*b);    }    friend point operator * (const double &a,const point &b){        return point(a*b.x,a*b.y);    }    friend point operator / (const point &a,const double &b){        return point(a.x/b,a.y/b);    }    double norm() {        return sqrt(x*x + y*y);    }};double det(const point &a,const point &b){    return a.x * b.y - a.y * b.x;}double dot(const point &a,const point &b){    return a.x*b.x + a.y*b.y;}double dist(const point &a,const point &b){    return (a - b).norm();}point rotate_point(const point &p,double angle){    double tx = p.x,ty = p.y;    return point(tx * cos(angle) - ty * sin(angle),tx * sin(angle) + ty * cos(angle));}struct line{    point a,b;    line() {}    line(point x,point y):a(x),b(y){}    void input(){        a.input();        b.input();    }};line point_make_line(const point &a,const point &b){    return line(a,b);}double dis_point_segment(const point &p,const line &s){    if(cmp(dot(p-s.a,s.b-s.a),0) < 0) return dist(p,s.a);    if(cmp(dot(p-s.b,s.a-s.b),0) < 0) return dist(p,s.b);    return fabs(det(s.a-p,s.b-p) / dist(s.a,s.b));}void pointprojline(const point &p,const line &s,point &cp){    double r = dot(p-s.a,s.b-s.a) / dot(s.b-s.a,s.b-s.a);    cp = s.a + r * (s.b - s.a);}bool pointonsegment(const point &p,const line &s){    return cmp(det(p-s.a,s.b-s.a),0) == 0 && cmp(dot(p-s.a,p-s.b),0) <=0;}bool parallel(const line &x,const line &y){    return !cmp(det(x.a - x.b,y.a - y.b),0);}bool line_make_point(const line &x,const line &y,point &res){    if(parallel(x,y)) return false;    double s1 = det(x.a - y.a,y.b - y.a);    double s2 = det(x.b - y.a,y.b - y.a);    res = (s1 * x.b - s2 * x.a) / (s1 - s2);    return true;}line move_d(const line &x,const double &len){    point d = x.b - x.a;    d = d / d.norm();    d = rotate_point(d,pi / 2);    return line(x.a + d * len,x.b + d * len);}const int maxn = 20;line ben[maxn];/// Union findint pnt[maxn],urank[maxn];void initunion() {    memset(pnt,0,sizeof(pnt));    memset(urank,0,sizeof(urank));    for(int i=0;i<maxn;i++) pnt[i] = i , urank[i] = 0;}int ufind(int x) {    if(x!=pnt[x]) pnt[x] = ufind(pnt[x]);    return pnt[x];}void umerge(int x,int y) {    if(urank[x = ufind(x)] > urank[ y = ufind(y) ]) pnt[y] = x;    else {        pnt[x] = y;        urank[y] += (urank[x] == urank[y]);    }}int main(){    int n;    while(~scanf("%d",&n),n)    {        initunion();        memset(ben,0,sizeof(ben));        for(int i=1;i<=n;i++) ben[i].input();        point temp;        for(int i=1;i<=n;i++)        {            for(int j=i+1;j<=n;j++)            {                if(line_make_point(ben[i],ben[j],temp) && pointonsegment(temp,ben[i]) && pointonsegment(temp,ben[j]))                    umerge(i,j);                else {                    bool flag = pointonsegment(ben[i].a,ben[j]) || pointonsegment(ben[i].b,ben[j])                                ||pointonsegment(ben[j].a,ben[i]) || pointonsegment(ben[j].b,ben[i]);                    if(flag) umerge(i,j);                }            }        }        int u,v;        while(scanf("%d%d",&u,&v),u+v)        {            u = ufind(u);            v = ufind(v);            if ( u == v) cout<<"CONNECTED"<<endl;            else cout<<"NOT CONNECTED"<<endl;        }    }    return 0;}
原创粉丝点击