计算几何模板啦啦啦
别的不多说.. 给出计算几何模板..
(这个模板大多数都是从刘汝佳《算法竞赛入门经典》中摘录的..)
#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;
}