UVA12304 2D Geometry 110 in 1!

UVA12304 2D Geometry 110 in 1!

计算几何

基础函数都在里面啦!

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#define db double
using namespace std;
map<string,int>opt;
const db eps=1e-7;
const db Pi=acos(-1.0);
db a,b,c,d,e,f,r,r1,r2;
int q0=0,Q0=0;
db q[15];
string s;
// 等于
bool Equ(db x,db y)
{
    return fabs(x-y)<eps;
}
// 不等于
bool NEqu(db x,db y)
{
    return fabs(x-y)>=eps;
}
// 小于
bool Sm(db x,db y)
{
    return y-x>eps;
}
// 小于等于
bool Le(db x,db y)
{
    return y-x>-eps;
}
// 大于
bool Bg(db x,db y)
{
    return x-y>eps;
}
// 大于等于
bool Ge(db x,db y)
{
    return x-y>-eps;
}
// 角度转正数
db Posi(db x)
{
    if (x>=0)
        return x-(int)(x/360.0)*360.0; else
    if (Equ((int)(x/360.0)*360.0,x))
        return 0.0; else
        return x+((int)(-x/360.0)+1)*360.0;
}
// 角度转0~180度(不包含180度)
db Stan(db x)
{
    x=Posi(x);
    if (Ge(x,180.0))
        x-=180.0;
    return x;
}
// 弧度转角度
db Turn(db x)
{
    return Posi(x/Pi*180.0);
}
// 点(向量表示)
struct Point
{
    db x,y;
    Point (db xx=0.0,db yy=0.0)
    {
        x=xx,y=yy;
    }
    void read()
    {
        scanf("%lf%lf",&x,&y);
    }
    void print()
    {
        printf("%.5lf %.5lf\n",x,y);
    }
    bool operator < (const Point &A) const
    {
        if (!Equ(x,A.x))
            return Sm(x,A.x);
        return Sm(y,A.y);
    }
}A,B,C,D,E,F,G,H,I,J,K,O,O1,O2,Q[15];
// 加法
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,db B)
{
    return Point(B*A.x,B*A.y);
}
Point operator * (db B,Point A)
{
    return Point(B*A.x,B*A.y);
}
// 数除
Point operator / (Point A,db B)
{
    return Point(A.x/B,A.y/B);
}
Point operator / (db B,Point A)
{
    return Point(A.x/B,A.y/B);
}
// 点积
db operator * (Point A,Point B)
{
    return A.x*B.x+A.y*B.y;
}
// 叉积
db operator ^ (Point A,Point B)
{
    return A.x*B.y-A.y*B.x;
}
// 等于
bool operator == (Point A,Point B)
{
    return Equ(A.x,B.x) && Equ(A.y,B.y);
}
// 不等于
bool operator != (Point A,Point B)
{
    return !Equ(A.x,B.x) || !Equ(A.y,B.y);
}
// 模长
db Len(Point A)
{
    return sqrt(A.x*A.x+A.y*A.y);
}
// 中点
Point Mid(Point A)
{
    return Point(0.5*A.x,0.5*A.y);
}
// 垂直向量
Point Verc(Point A)
{
    return Point(-A.y,A.x);
}
// 两点间距离
db Dis(Point A,Point B)
{
    return Len(A-B);
}
// 两点中点
Point Mid(Point A,Point B)
{
    return Point(0.5*(A.x+B.x),0.5*(A.y+B.y));
}
// 极角
db Angle(Point A)
{
    return atan2(A.y,A.x);
}
// 三角形角度(c边所对的角)
db Angle(db a,db b,db c)
{
    return acos((a*a+b*b-c*c)/(2.0*a*b));
}
// 旋转(将点A绕原点旋转角度k)
Point Rot(Point A,db k)
{
    db s=sin(k),c=cos(k);
    return Point(A.x*c-A.y*s,A.x*s+A.y*c);
}
// 旋转(将点A绕点B旋转角度k)
Point Rot(Point A,Point B,db k)
{
    Point C=A-B;
    db s=sin(k),c=cos(k);
    return Point(B.x+C.x*c-C.y*s,B.y+C.x*s+C.y*c);
}
// 做点A关于点B的对称点
Point Sym(Point A,Point B)
{
    return Point(2.0*B.x-A.x,2.0*B.y-A.y);
}
// 直线
struct Line
{
    // P表示直线上一点,t表示方向向量
    // L=P+kt
    Point P,t;
    Line (Point A=Point(0.0,0.0),Point B=Point(0.0,0.0))
    {
        P=A,t=B;
    }
    void print()
    {
        printf("P: %.5lf %.5lf\n",P.x,P.y);
        printf("t: %.5lf %.5lf\n",t.x,t.y);
    }
}L1,L2,L3,L4,L5,L6,L7,L8,L9,L10;
// 把两点转为直线
Line ToLine(Point A,Point B)
{
    return Line(A,B-A);
}
// 将指定的k值代入直线
Point Get(Line A,db k)
{
    return A.P+k*A.t;
}
// 得到直线上随机一点
Point Get_Rand(Line A)
{
    return A.P+19.19191919*A.t;
}
// 求中垂线
Line Median (Point A,Point B)
{
    return Line(Mid(A,B),Verc(B-A));
}
// 做平行线
Line Para(Point A,Line L)
{
    return Line(A,L.t);
}
// 做垂线
Line Verc(Point A,Line L)
{
    return Line(A,Verc(L.t));
}
// 求直线交点
Point Cross (Line L1,Line L2)
{
    Point A=Get(L1,1.0),B=Get(L1,-1.0);
    Point C=Get(L2,1.0),D=Get(L2,-1.0);
    db S1=(C-A)^(C-B);
    db S2=(D-A)^(D-B);
    Point del=D-C;
    return Point(C.x+del.x*S1/(S1-S2),C.y+del.y*S1/(S1-S2));
}
// 点到直线垂足
Point Pedal(Point A,Line L)
{
    Line L1=Verc(A,L);
    return Cross(L1,L);
}
// 判断是否在直线上
bool OnLine(Point C,Line L)
{
    Point A=Get(L,1.0),B=Get(L,-1.0);
    return Equ((C-A)^(C-B),0.0);
}
// 截取射线AB上AC=k
Point Cut(Point A,Point B,db k)
{
    Point del=B-A;
    del=(del/Len(del))*k;
    return A+del;
}
// 直线与x轴夹角
db Angle(Line A)
{
    return Angle(A.t);
}
// 圆(圆心O、半径r)
struct Circle
{
    Point O;
    db r;
    Circle (Point A=Point(0.0,0.0),db k=0.0)
    {
        O=A,r=k;
    }
    void read()
    {
        scanf("%lf%lf%lf",&O.x,&O.y,&r);
    }
}C1,C2,C3,C4,C5,C6;
int main()
{
    opt["CircumscribedCircle"]=1;
    opt["InscribedCircle"]=2;
    opt["TangentLineThroughPoint"]=3;
    opt["CircleThroughAPointAndTangentToALineWithRadius"]=4;
    opt["CircleTangentToTwoLinesWithRadius"]=5;
    opt["CircleTangentToTwoDisjointCirclesWithRadius"]=6;
    while (cin >> s)
    {
        switch (opt[s])
        {
            case 1:
                A.read(),B.read(),C.read();
                L1=Median(A,B),L2=Median(A,C);
                D=Cross(L1,L2);
                printf("(%.6lf,%.6lf,%.6lf)\n",D.x,D.y,Dis(A,D));
                break;
            case 2:
                A.read(),B.read(),C.read();
                a=Dis(B,C),b=Dis(A,C),c=Dis(A,B);
                D=B+(C-B)*(c/(c+b)),E=A+(C-A)*(c/(a+c));
                L1=ToLine(A,D),L2=ToLine(B,E);
                F=Cross(L1,L2);
                L3=ToLine(A,C);
                G=Pedal(F,ToLine(A,C));
                printf("(%.6lf,%.6lf,%.6lf)\n",F.x,F.y,Dis(F,G));
                break;
            case 3:
                C1.read(),A.read();
                q0=0;
                O=C1.O,a=Dis(O,A),b=C1.r;
                if (Sm(a,b))
                    q0=0; else
                    {
                        c=sqrt(a*a-b*b);
                        d=atan(c/b);
                        B=Rot(A,O,d),C=Rot(A,O,-d);
                        D=Cut(O,B,b),E=Cut(O,C,b);
                        q[++q0]=Angle(ToLine(A,D));
                        if (D!=E)
                            q[++q0]=Angle(ToLine(A,E));
                    }
                for (int i=1;i<=q0;++i)
                    q[i]=Stan(Turn(q[i]));
                sort(q+1,q+q0+1);
                if (!q0)
                    puts("[]"); else
                if (q0==1)
                    printf("[%.6lf]\n",q[1]); else
                    printf("[%.6lf,%.6lf]\n",q[1],q[2]);
                break;
            case 4:
                A.read(),B.read(),C.read(),scanf("%lf",&r);
                Q0=0;
                L1=ToLine(B,C);
                D=Pedal(A,L1);
                a=Dis(A,D);
                if (Equ(a,r+r))
                    Q[++Q0]=Mid(A,D); else
                if (!Bg(a,r+r))
                {
                    if (OnLine(A,L1))
                    {
                        L2=Verc(A,L1);
                        E=Get_Rand(L2);
                        G=Cut(A,E,r),H=Cut(A,E,-r);
                        Q[++Q0]=G,Q[++Q0]=H;
                    } else
                    {
                        b=sqrt(r*r-(r-a)*(r-a));
                        if (B==D)
                            swap(B,C);
                        E=Cut(D,B,b),F=Cut(D,B,-b);
                        L2=Verc(E,L1),L3=Verc(F,L1);
                        G=Pedal(A,L2),H=Pedal(A,L3);
                        I=Cut(E,G,r),J=Cut(F,H,r);
                        Q[++Q0]=I,Q[++Q0]=J;
                    }
                }
                sort(Q+1,Q+Q0+1);
                if (Q0==0)
                    puts("[]"); else
                    {
                        printf("[(%.6lf,%.6lf)",Q[1].x,Q[1].y);
                        for (int i=2;i<=Q0;++i)
                            printf(",(%.6lf,%.6lf)",Q[i].x,Q[i].y);
                        putchar(']'),putchar('\n');
                    }
                break;
            case 5:
                A.read(),B.read(),C.read(),D.read(),scanf("%lf",&r);
                Q0=0;
                L1=ToLine(A,B),L2=ToLine(C,D);
                E=Cross(L1,L2);
                L3=Verc(E,L1),L4=Verc(E,L2);
                F=Get_Rand(L3);
                H=Cut(E,F,r),I=Cut(E,F,-r);
                L5=Para(H,L1),L6=Para(I,L1);
                F=Get_Rand(L4);
                H=Cut(E,F,r),I=Cut(E,F,-r);
                L7=Para(H,L2),L8=Para(I,L2);
                Q[++Q0]=Cross(L5,L7),Q[++Q0]=Cross(L5,L8);
                Q[++Q0]=Cross(L6,L7),Q[++Q0]=Cross(L6,L8);
                sort(Q+1,Q+Q0+1);
                if (Q0==0)
                    puts("[]"); else
                    {
                        printf("[(%.6lf,%.6lf)",Q[1].x,Q[1].y);
                        for (int i=2;i<=Q0;++i)
                            printf(",(%.6lf,%.6lf)",Q[i].x,Q[i].y);
                        putchar(']'),putchar('\n');
                    }
                break;
            case 6:
                C1.read(),C2.read(),scanf("%lf",&r);
                if (C1.r<C2.r)
                    swap(C1,C2);
                Q0=0;
                O1=C1.O,O2=C2.O,r1=C1.r,r2=C2.r;
                a=Dis(O1,O2);
                r1+=r,r2+=r;
                if (Equ(a,r1+r2))
                    Q[++Q0]=Cut(O1,O2,r1); else
                if (!Bg(a,r1+r2))
                {
                    b=r1*((a*a+r1*r1-r2*r2)/(2.0*a*r1));
                    c=sqrt(r1*r1-b*b);
                    A=Cut(O1,O2,b);
                    L3=ToLine(O1,O2);
                    L4=Verc(A,L3);
                    B=Get_Rand(L4);
                    Q[++Q0]=Cut(A,B,c);
                    Q[++Q0]=Cut(A,B,-c);
                }
                sort(Q+1,Q+Q0+1);
                if (Q0==0)
                    puts("[]"); else
                    {
                        printf("[(%.6lf,%.6lf)",Q[1].x,Q[1].y);
                        for (int i=2;i<=Q0;++i)
                            printf(",(%.6lf,%.6lf)",Q[i].x,Q[i].y);
                        putchar(']'),putchar('\n');
                    }
                break;
            default:
                puts("Error");
                break;
        }
    }
    return 0;
}
上一篇:SQLServer空间查询geometry


下一篇:制作浮雕效果等高线的原理与实践