计算几何二维模板

以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 find
int 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值