計(jì)算幾何

typedef double db;
const db eps=1e-6;

//點(diǎn).向量
struct point
{
    db x,y,len2,angle;
    point() {}
    point(db _x,db _y){set(_x,_y);}
    void set(db _x,db _y)
    {
        x=_x,y=_y;
        len2=x*x+y*y;
        angle=atan2(y,x);
    }
    void print(){printf("(%.6f,%.6f)",(double)x,(double)y);}
    void println(){print();puts("");}
    //逆時(shí)針旋轉(zhuǎn)
    point rotate(db alpha)
    {
        db _x=x*cos(alpha)-y*sin(alpha);
        db _y=x*sin(alpha)+y*cos(alpha);
        return point(_x,_y);
    }
    //向量夾角
    db get_angle(point &p)
    {
        return acos((*this)*p/length()/p.length());
    }
    db length(){return sqrt(len2);}
    point operator+(const point &p){return point(x+p.x,y+p.y);}
    point operator-(const point &p){return point(x-p.x,y-p.y);}
    point operator*(const db k){return point(k*x,k*y);}
    point operator/(const db k){return point(x/k,y/k);}
    db operator*(const point &p){return x*p.x+y*p.y;}
    db operator^(const point &p){return x*p.y-y*p.x;}
    bool operator==(const point &p){return fabs(x-p.x)<eps && fabs(y-p.y)<eps;}
};

//線
struct line
{
    point st,ed,vec;
    db len2,angle;
    line() {}
    line(point s,point e) {set(s,e);}
    void set(point s,point e)
    {
        st=s,ed=e,vec=e-s;
        len2=vec.len2;
        angle=atan2(vec.y,vec.x);
    }
    //延長k倍
    line operator*(db k){return line(st,st+vec*k);}
    //靠近st的1/k分點(diǎn)
    point operator/(db k){return st+vec/k;}
    db length(){return sqrt(len2);}
    //點(diǎn)在直線左側(cè)
    bool on_left(point p){return (vec^(p-st))>eps;}
    //點(diǎn)在直線上
    bool on_line(point p){return fabs(vec^(p-st))<eps;}
    //點(diǎn)在線段上
    bool on_segment(point p)
    {
        if(p.x+eps<min(st.x,ed.x) || p.x-eps>max(st.x,ed.x))
            return false;
        if(p.y+eps<min(st.y,ed.y) || p.y-eps>max(st.y,ed.y))
            return false;
        return on_line(p);
    }
    //直線平行
    bool parallel(line l){return fabs(vec^l.vec)<eps;}
    //直線重合
    bool coincidence(line l){return on_line(l.st) && on_line(l.ed);}
    //直線交點(diǎn)
    point get_intersection(line l)
    {
        db x1=st.x,y1=st.y,x2=ed.x,y2=ed.y;
        db x3=l.st.x,y3=l.st.y,x4=l.ed.x,y4=l.ed.y;
        db k1=(x4-x3)*(y2-y1),k2=(x2-x1)*(y4-y3);
        db x=(k1*x1-k2*x3+(y3-y1)*(x2-x1)*(x4-x3))/(k1-k2);
        db y=(k2*y1-k1*y3+(x3-x1)*(y2-y1)*(y4-y3))/(k2-k1);
        return point(x,y);
    }
    //線段相交
    bool segment_intersection(line l)
    {
        if(coincidence(l))
            return on_segment(l.st) || on_segment(l.ed)
                || l.on_segment(st) || l.on_segment(ed);
        return ((l.st-st)^vec)*((l.ed-st)^vec)<=0
            && ((st-l.st)^l.vec)*((ed-l.st)^l.vec)<=0;
    }
    //線段中垂線
    line vertical_bisector()
    {
        db x1=st.x,y1=st.y,x2=ed.x,y2=ed.y;
        db xm=(x1+x2)/2.0,ym=(y1+y2)/2.0;
        return line(point(xm+ym-y1,ym-xm+x1),point(xm-ym+y1,ym+xm-x1));
    }
    //直線旋轉(zhuǎn)
    line rotate(db alpha)
    {
        point v=vec.rotate(alpha);
        return line(st,st+v);
    }
    //垂線
    line vertical(point p)
    {
        point l(vec.y,-vec.x);
        l=l*(distance(p)/l.length());
        if(on_line(p+l))return line(p,p+l);
        else return line(p,p-l);
    }
    //直線夾角
    db get_angle(line l){return vec.get_angle(l.vec);}
    //點(diǎn)到直線的距離
    db distance(point p){return fabs((p-st)^(p-ed))/(length());}
    //中點(diǎn)
    point midpoint(){return point((st.x+ed.x)/2,(st.y+ed.y)/2);}
    void print(){st.print();putchar('-');ed.print();}
    void println(){print();puts("");}
};

//三角形
struct triangle
{
    point v[4];line e[4];
    triangle(point p1,point p2,point p3)
    {
        point p[4]={point(),p1,p2,p3};
        set(p);
    }
    triangle(point p[]) {set(p);}
    //構(gòu)造逆時(shí)針三角形(注意特判三點(diǎn)共線)
    void set(point p[])
    {
        for(int i=1;i<=3;++i)v[i]=p[i];
        if(!line(v[1],v[2]).on_left(v[3]))
            swap(v[2],v[3]);
        for(int i=1;i<=2;++i)e[i].set(v[i],v[i+1]);
        e[3].set(v[3],v[1]);
    }
    bool inside(point p)
    {
        return e[1].on_left(p)==e[2].on_left(p)
            && e[1].on_left(p)==e[3].on_left(p);
    }
    //重心(中線交點(diǎn))
    point gravity(){return (v[1]+v[2]+v[3])/3;}
    //外心
    point circum_center()
    {
        line l1=e[1].vertical_bisector();
        line l2=e[2].vertical_bisector();
        return l1.get_intersection(l2);
    }
    //內(nèi)心
    point inscribed_center()
    {
        db a=e[2].length(),b=e[3].length(),c=e[1].length();
        db x=(a*v[1].x+b*v[2].x+c*v[3].x)/(a+b+c);
        db y=(a*v[1].y+b*v[2].y+c*v[3].y)/(a+b+c);
        return point(x,y);
    }
    //垂心
    point orthocenter()
    {
        line l1=e[1].vertical(v[3]);
        line l2=e[2].vertical(v[1]);
        return l1.get_intersection(l2);
    }
    //周長
    db perimeter()
    {
        db sum=0.0;
        for(int i=1;i<=3;++i)sum+=e[i].length();
        return sum;
    }
    //面積
    db area(){return fabs((v[3]-v[1])^(v[2]-v[1]))/2;}
    void print(){for(int i=1;i<=3;++i){v[i].print();if(i!=3)putchar('-');}}
    void println(){print();puts("");}
};

//矩形
struct rectangle
{
    point v[5];line e[5];
    rectangle(point p1,point p2)
    {
        point p[5]={point(),point(p1.x,p1.y),point(p1.x,p2.y),
                            point(p2.x,p1.y),point(p2.x,p2.y)};
        set(p);
    }
    rectangle(point p1,point p2,point p3,point p4)
    {
        point p[5]={point(),p1,p2,p3,p4};
        set(p);
    }
    rectangle(point p[]) {set(p);}
    //構(gòu)造出順時(shí)針或逆時(shí)針的矩形(注意特判四點(diǎn)共線)
    void set(point p[])
    {
        for(int i=1;i<=4;++i)v[i].set(p[i].x,p[i].y);
        if(!line(v[1],v[2]).parallel(line(v[3],v[4])))
            swap(v[2],v[3]);
        if(!line(v[1],v[4]).parallel(line(v[2],v[3])))
            swap(v[3],v[4]);
        for(int i=1;i<=3;++i)e[i].set(v[i],v[i+1]);
        e[4].set(v[4],v[1]);
    }
    //點(diǎn)在矩形內(nèi)或矩形上
    bool inside(point p)
    {
        bool flag=true;
        for(int i=1;i<=4;++i)
        {
            if(e[i].on_segment(p))return true;
            if(e[i].on_left(p)!=e[1].on_left(p))
                flag=false;
        }
        return flag;
    }
    bool inside(line l){return inside(l.st) && inside(l.ed);}
    bool intersection(line l)
    {
        for(int i=1;i<=4;++i)
            if(e[i].segment_intersection(l))
                return true;
        return false;
    }
    void print(){for(int i=1;i<=4;++i){v[i].print();if(i!=4)putchar('-');}}
    void println(){print();puts("");}
};

//圓
struct circle
{
    point c;db r;
    circle() {}
    circle(point p,db _r){set(p,_r);}
    void set(point p,db _r){c=p,r=_r;}
    //外接圓
    static circle circum_circle(triangle t)
    {
        point p=t.circum_center();
        return circle(p,line(p,t.v[1]).length());
    }
    //內(nèi)接圓
    static circle inscribed_circle(triangle t)
    {
        point p=t.inscribed_center();
        return circle(p,t.area()*2/t.perimeter());
    }
    //點(diǎn)在圓內(nèi)或圓上
    bool inside(point p){return line(p,c).len2<=r*r;}
    void print(){c.print(),printf(" r:%.2f",(double)r);}
    void println(){print();puts("");}
};

struct polygon
{
    const static int __=1e3+5;
    point v[__];int n;
    polygon() {}
    polygon(point p[],int n)
    {
        for(int i=1;i<=n;++i)v[i]=p[i];
        v[0]=p[n],v[n+1]=p[1];
        this->n=n;
    }
    db area()
    {
        db res=0.0;
        for(int i=1;i<=n;++i)
            res+=v[i]^v[i+1];
        return fabs(res)/2;
    }
};

球體積交 && 球體積并

const ld pi=acos(-1);

ld pow2(ld x){return x*x;}

ld pow3(ld x){return x*x*x;}

ld dis(ld x1,ld y1,ld z1,ld x2,ld y2,ld z2)
{
    return pow2(x1-x2)+pow2(y1-y2)+pow2(z1-z2);
}

ld cos(ld a,ld b,ld c){return (b*b+c*c-a*a)/(2*b*c);}

ld cap(ld r,ld h){return pi*(r*3-h)*h*h/3;}

//2球體積交
ld sphere_intersect(ld x1,ld y1,ld z1,ld r1,ld x2,ld y2,ld z2,ld r2)
{
    ld d=dis(x1,y1,z1,x2,y2,z2);
    //相離
    if(d>=pow2(r1+r2))return 0;
    //包含
    if(d<=pow2(r1-r2))return pow3(min(r1,r2))*4*pi/3;
    //相交
    ld h1=r1-r1*cos(r2,r1,sqrt(d)),h2=r2-r2*cos(r1,r2,sqrt(d));
    return cap(r1,h1)+cap(r2,h2);
}

//2球體積并
ld sphere_union(ld x1,ld y1,ld z1,ld r1,ld x2,ld y2,ld z2,ld r2)
{
    ld d=dis(x1,y1,z1,x2,y2,z2);
    //相離
    if(d>=pow2(r1+r2))return (pow3(r1)+pow3(r2))*4*pi/3;
    //包含
    if(d<=pow2(r1-r2))return pow3(max(r1,r2))*4*pi/3;
    //相交
    ld h1=r1+r1*cos(r2,r1,sqrt(d)),h2=r2+r2*cos(r1,r2,sqrt(d));
    return cap(r1,h1)+cap(r2,h2);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末烫葬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子坑傅,更是在濱河造成了極大的恐慌件豌,老刑警劉巖疮方,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茧彤,居然都是意外死亡骡显,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門曾掂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惫谤,“玉大人,你說我怎么就攤上這事珠洗∈遥” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵险污,是天一觀的道長痹愚。 經(jīng)常有香客問我,道長蛔糯,這世上最難降的妖魔是什么拯腮? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮蚁飒,結(jié)果婚禮上动壤,老公的妹妹穿的比我還像新娘。我一直安慰自己淮逻,他們只是感情好琼懊,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著爬早,像睡著了一般哼丈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上筛严,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天醉旦,我揣著相機(jī)與錄音,去河邊找鬼桨啃。 笑死车胡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的照瘾。 我是一名探鬼主播匈棘,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼析命!你這毒婦竟也來了主卫?” 一聲冷哼從身側(cè)響起逃默,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎队秩,沒想到半個(gè)月后笑旺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昼浦,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡馍资,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了关噪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸟蟹。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖使兔,靈堂內(nèi)的尸體忽然破棺而出建钥,到底是詐尸還是另有隱情,我是刑警寧澤虐沥,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布熊经,位于F島的核電站,受9級(jí)特大地震影響欲险,放射性物質(zhì)發(fā)生泄漏镐依。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一天试、第九天 我趴在偏房一處隱蔽的房頂上張望槐壳。 院中可真熱鬧,春花似錦喜每、人聲如沸务唐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枫笛。三九已至,卻和暖如春刚照,著一層夾襖步出監(jiān)牢的瞬間崇堰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工涩咖, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留海诲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓檩互,卻偏偏與公主長得像特幔,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闸昨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容