計算幾何模板啦啦啦啦

計算幾何模板啦啦啦

別的不多說.. 給出計算幾何模板..
(這個模板大多數都是從劉汝佳《算法競賽入門經典》中摘錄的..)

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <complex>
#include <deque>
using namespace std;

struct Point {
    double x, y;
    Point ( double x=0, double y=0 ) : x(x), y(y) {} //構造函數,方便代碼編寫
};

typedef Point Vector;

//向量+向量=向量 點+向量=點
Vector operator + ( Vector A, Vector B ){ return Vector ( A.x+B.x, A.y+B.y ); }
//點-點=向量
Vector operator - ( Vector A, Vector B ){ return Vector ( A.x-B.x, A.y-B.y ); }
//向量*數=向量
Vector operator * ( Vector A, double p ){ return Vector ( A.x*p, A.y*p ); }
//向量/數=向量
Vector operator / ( Vector A, double p ){ return Vector ( A.x/p, A.y/p ); }

//精度
const double eps = 1e-10;

double _max ( double x, double y ){ return x > y ? x : y; }
double _min ( double x, double y ){ return x < y ? x : y; }
double _abs ( double x ){ return x < 0 ? -x : x; }
int zero ( double x ){ return _abs (x) < eps ? 1 : 0; }
int dcmp ( double x ){
    if ( zero (x) == 1 ) return 0;
    return x < 0 ? -1 : 1;
}

bool operator == ( const Point &a, const Point &b ){
    return zero (a.x-b.x) && zero (a.y-b.y);
}

double Dot ( Vector A, Vector B ){ return A.x*B.x + A.y*B.y; }
double Length ( Vector A ){ return sqrt ( Dot ( A, A ) ); }
//acos返回餘弦弧度
double Angle ( Vector A, Vector B ){ return acos ( Dot ( A, B ) / Length (A) / Length (B) ); }

double Cross ( Vector A, Vector B ){ return A.x*B.y - A.y*B.x; }
double Area2 ( Point A, Point B, Point C ){ return Cross ( B-A, C-A ); }

//rad是弧度
Vector Rotate ( Vector A, double rad ){
    return Vector ( A.x*cos(rad)-A.y*sin(rad), A.x*sin(rad)+A.y*cos(rad) );
}

//向量的單位法向量
Vector Normal ( Vector A ){
    double L = Length (A);
    return Vector ( -A.y/L, A.x/L );
}

//求直線P+tv和Q+tw的交點(參數式)
Point GetLineIntersection ( Point P, Vector v, Point Q, Vector w ){
    Vector u = P-Q;
    double t = Cross ( w, u ) / Cross ( v, w );
    return P+v*t;
}

//求p1、p2構成的直線和p3、p4構成的直線的交點(兩點式)
Point GetLineIntersectionB ( Point p1, Point p2, Point p3, Point p4 ){
    double a1, b1, c1, a2, b2, c2;

    a1 = p1.y-p2.y;
    b1 = p2.x-p1.x;
    c1 = p1.x*p2.y-p1.y*p2.x;

    a2 = p3.y-p4.y;
    b2 = p4.x-p3.x;
    c2 = p3.x*p4.y-p3.y*p4.x;

    return Point ( (c1*b2-c2*b1)/(a2*b1-a1*b2), (c2*a1-c1*a2)/(a2*b1-a1*b2) );
}

//求點到直線的距離
double DistanceToLine ( Point P, Point A, Point B ){
    Vector v1 = B-A, v2 = P-A;
    return _abs ( Cross ( v1, v2 ) ) / Length (v1);
}

//求點到線段的距離
double DistanceToSegment ( Point P, Point A, Point B ){
    if ( A == B ) return Length (P-A);
    Vector v1 = B-A, v2 = P-A, v3 = P-B;
    if ( dcmp ( Dot ( v1, v2 ) ) < 0 ) return Length (v2);
    else if ( dcmp ( Dot ( v1, v3 ) ) > 0 ) return Length (v3);
    else return _abs ( Cross ( v1, v2  ) ) / Length (v1);
}

//求點在直線上的投影
Point GetLineProjection ( Point P, Point A, Point B ){
    Vector v = B-A;
    return A+v*( Dot ( v, P-A ) / Dot ( v, v ) );
}

//判斷線段相交(規範相交)
bool SegmentProperIntersection ( Point p1, Point p2, Point p3, Point p4 ){
    if ( Cross ( p1-p3, p2-p3 ) * Cross ( p1-p4, p2-p4 ) < 0 && Cross ( p3-p1, p4-p1 ) * Cross ( p3-p2, p4-p2 ) < 0 ) return true;
    return false;
}

//判斷線段相交(非規範相交)
bool SegmentImproperIntersection ( Point p1, Point p2, Point p3, Point p4 ){
    //正常相交
    if ( Cross ( p1-p3, p2-p3 ) * Cross ( p1-p4, p2-p4 ) < 0 && Cross ( p3-p1, p4-p1 ) * Cross ( p3-p2, p4-p2 ) < 0 ) return true;
    //p1在y上
    if ( Cross ( p3-p1, p4-p1 ) == 0 && _min(p3.x,p4.x) <= p1.x && p1.x <= _max(p3.x,p4.x) && _min(p3.y,p4.y) <= p1.y && p1.y <= _max(p3.y,p4.y) ) return true;
    //p2在y上
    if ( Cross ( p3-p2, p4-p2 ) == 0 && _min(p3.x,p4.x) <= p2.x && p2.x <= _max(p3.x,p4.x) && _min(p3.y,p4.y) <= p2.y && p2.y <= _max(p3.y,p4.y) ) return true;
    //p3在x上
    if ( Cross ( p1-p3, p2-p3 ) == 0 && _min(p1.x,p2.x) <= p3.x && p3.x <= _max(p1.x,p2.x) && _min(p1.y,p2.y) <= p3.y && p3.y <= _max(p1.y,p2.y) ) return true;
    //p4在x上
    if ( Cross ( p1-p4, p2-p4 ) == 0 && _min(p1.x,p2.x) <= p4.x && p4.x <= _max(p1.x,p2.x) && _min(p1.y,p2.y) <= p4.y && p4.y <= _max(p1.y,p2.y) ) return true;
    return false;
}

//多邊形的有向面積
double PolygonArea ( Point *p, int n ){
    double area = 0.0;
    for ( int i = 2; i < n; i ++ ){
        area += Cross ( p[i]-p[1], p[i+1]-p[1] );
    }
    return area/2.0;
}

struct Circle {
    Point c;
    double r;
    Circle ( Point c=0, double r=0 ) : c(c), r(r) {}
    Point point ( double a ){ //知道極角求圓上座標
        return Point ( c.x+cos(a)*r, c.y+sin(a)*r );
    }
};

struct Line {
    Point p1, p2;
};

vector <Point> sol;

//求直線和圓的交點,返回交點的個數
int GetLineCircleIntersection ( Line L, Circle C ){
    Point p, p1, p2;
    p = GetLineProjection ( C.c, L.p1, L.p2 );
    double dis = Length ( C.c-p );
    if ( zero(dis-C.r) == 1 ){ sol.push_back (p); return 1; }
    if ( dis > C.r ) return 0;
    Vector v = (L.p2-L.p1) / Length (L.p2-L.p1);
    double t = sqrt ( C.r*C.r - dis*dis );
    p1 = p+v*t;
    p2 = p-v*t;
    sol.push_back (p1);
    sol.push_back (p2);
    return 2;
}

//求極角
double angle ( Vector v ){ return atan2 ( v.y, v.x ); }

//兩圓相交,返回交點個數
int GetCircleCircleIntersection ( Circle C1, Circle C2 ){
    double d = Length (C1.c-C2.c);
    if ( dcmp (d) == 0 ){
        if ( dcmp (C1.r-C2.r) == 0 ) return -1; //兩圓重合
        return 0;
    }
    if ( dcmp (C1.r+C2.r-d) < 0 ) return 0;
    if ( dcmp ( _abs (C1.r-C2.r)-d ) > 0 ) return 0;

    double a = angle (C2.c-C1.c);
    double da = acos ( (C1.r*C1.r+d*d-C2.r*C2.r) / (2*C1.r*d) );
    Point p1 = C1.point (a-da), p2 = C1.point (a+da);

    sol.push_back (p1);
    if ( p1 == p2 ) return 1;
    sol.push_back (p2);
    return 2;
}

const double PI = acos (-1);
Vector v[2];
//過p作圓C的切線
int GetTarget ( Point p, Circle C ){
    Vector u = C.c - p;
    double dis = Length (u);
    if ( dis < C.r ) return 0;
    else if ( dcmp (dis-C.r) == 0 ){
        v[0] = Rotate ( u, PI/2 );
        return 1;
    }
    else {
        double ang = asin (C.r/dis);
        v[0] = Rotate ( u, -ang );
        v[1] = Rotate ( u, +ang );
        return 2;
    }
}

//求兩圓的公切線
Point a[10], b[10];
int GetTangents ( Circle A, Circle B ){
    int cnt = 0;
    if ( A.r < B.r ){ swap ( A, B ); swap ( a, b ); }
    double d2 = (A.c.x-B.c.x)*(A.c.x-B.c.x) + (A.c.y-B.c.y)*(A.c.y-B.c.y);
    double rdiff = A.r-B.r;
    double rsum = A.r+B.r;
    if ( d2 < rdiff*rdiff ) return 0;

    double base = atan2 ( B.c.y-A.c.y, B.c.x-A.c.x );
    if ( zero (d2) && A.r == B.r ) return -1;
    if ( zero ( rdiff*rdiff-d2 ) ){
        cnt ++;
        a[cnt] = A.point (base); b[cnt] = B.point (base);
        return 1;
    }

    double ang = acos ((A.r-B.r)/sqrt(d2));
    cnt ++; a[cnt] = A.point (base+ang); b[cnt] = B.point (base+ang);
    cnt ++; a[cnt] = A.point (base-ang); b[cnt] = B.point (base-ang);
    if ( zero ( rsum*rsum-d2 ) ){
        cnt ++; a[cnt] = A.point (base); b[cnt] = B.point (PI+base);
    }
    else if ( d2 > rsum*rsum ){
        double ang = acos ((A.r+B.r)/sqrt(d2));
        cnt ++; a[cnt] = A.point (base+ang); b[cnt] = B.point (PI+base+ang);
        cnt ++; a[cnt] = A.point (base-ang); b[cnt] = B.point (PI+base-ang);
    }
    return cnt;
}
int main (){
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章