SGU 227 The art to the broad masses!(圆弧求交点)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=227

题意:给定一些圆弧。求圆弧的交点。

思路:求出圆心交点。判断交点在不在圆弧内用叉积。



int DB(double x)
{
    if(x>1e-10) return 1;
    if(x<-1e-10) return -1;
    return 0;
}


class point
{
public:
    double x,y;

    point(){}
    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    void get()
    {
        RD(x,y);
    }

    point operator+(point a)
    {
        return point(x+a.x,y+a.y);
    }

    point operator-(point a)
    {
        return point(x-a.x,y-a.y);
    }

    double operator*(point a)
    {
        return x*a.y-y*a.x;
    }

    point operator*(double t)
    {
        return point(x*t,y*t);
    }

    double operator^(point a)
    {
        return x*a.x+y*a.y;
    }

    double getLen()
    {
        return sqrt(x*x+y*y);
    }

    point operator/(double t)
    {
        return point(x/t,y/t);
    }

    double getAng(point a)
    {
        return atan2(*this*a,*this^a);
    }

    int operator==(const point &a) const
    {
        return DB(x-a.x)==0&&DB(y-a.y)==0;
    }

    int operator<(const point &a) const
    {
        if(DB(x-a.x)) return x<a.x;
        return y<a.y;
    }

    point adjust(double p)
    {
        point t=*this;
        double x=p/t.getLen();
        return point(x*t.x,x*t.y);
    }

    point zhuanNi(double ang)
    {
        return point(x*cos(ang)-y*sin(ang),x*sin(ang)+y*cos(ang));
    }

    point zhuanShun(double ang)
    {
        return point(x*cos(ang)+y*sin(ang),-x*sin(ang)+y*cos(ang));
    }

    point vertical()
    {
        return point(y,-x);
    }

    void print()
    {
        if(DB(x)==0) x=0;
        if(DB(y)==0) y=0;
        printf("%.3lf %.3lf\n",x,y);
    }
};

const int N=55;
point p[N][3],O[N];
vector<point> ans;
double R[N];
int n,d[N];

point getCross(point a,point b,point p,point q)
{
    double s1=(a-p)*(b-p);
    double s2=(b-q)*(a-q);
    return (p*s2+q*s1)/(s1+s2);
}

int cmp(point a,point b)
{
    if(DB(a.x-b.x)) return a.x<b.x;
    return a.y<b.y;
}

point getCenter(point a,point b,point c)
{
    point M1=(a+b)/2,dir1=(b-a).vertical();
    point M2=(b+c)/2,dir2=(c-b).vertical();
    return getCross(M1,M1+dir1,M2,M2+dir2);
}

int isInside(point a,int t)
{
    return DB((p[t][0]-p[t][2])*(a-p[t][2]))*d[t];
}


void judge(int x,int y)
{
    if(!isInside(p[x][0],y)&&!isInside(p[x][2],y)&&d[x]==d[y])
    {
        puts("Infinity");
        exit(0);
    }
    if(isInside(p[x][0],y)>0||isInside(p[x][2],y)>0||isInside(p[y][0],x)>0||isInside(p[y][2],x)>0)
    {
        puts("Infinity");
        exit(0);
    }
    if(!isInside(p[x][0],y)) ans.pb(p[x][0]);
    if(!isInside(p[x][2],y)) ans.pb(p[x][2]);
}

void calCross(int x,int y,point &a,point &b)
{
    double L=(O[x]-O[y]).getLen();
    double ang=(sqr(R[y])+sqr(L)-sqr(R[x]))/(2*R[y]*L);
    ang=acos(ang);
    point A=O[x]-O[y],B;

    B=A.zhuanNi(ang);
    B=B.adjust(R[y]);
    a=O[y]+B;

    B=A.zhuanShun(ang);
    B=B.adjust(R[y]);
    b=O[y]+B;
}

void deal()
{
    int i,j,k,t;
    double L;
    point a,b;
    for(i=1;i<=n;i++) for(j=i+1;j<=n;j++)
    {
        if(O[i]==O[j]&&!DB(R[i]-R[j]))
        {
            judge(i,j);
            continue;
        }
        L=(O[i]-O[j]).getLen();
        if(DB(L-(R[i]+R[j]))>0||DB(L-fabs(R[i]-R[j]))<0) continue;
        calCross(i,j,a,b);
        if(isInside(a,i)>=0&&isInside(a,j)>=0) ans.pb(a);
        if(isInside(b,i)>=0&&isInside(b,j)>=0) ans.pb(b);
    }
}

int main()
{
    RD(n);
    int i;
    FOR1(i,n)
    {
        p[i][0].get();
        p[i][2].get();
        p[i][1].get();
        O[i]=getCenter(p[i][0],p[i][1],p[i][2]);
        d[i]=DB((p[i][0]-p[i][2])*(p[i][1]-p[i][2]));
        R[i]=(O[i]-p[i][0]).getLen();
    }
    deal();
    sort(ans.begin(),ans.end(),cmp);
    int S=unique(ans.begin(),ans.end())-ans.begin();
    PR(S);
    for(i=0;i<S;i++) ans[i].print();
    return 0;
}

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值