大白二维计算几何模板

</pre><pre code_snippet_id="275812" snippet_file_name="blog_20140404_1_7192597" name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<cstdlib>
#include<stack>
using namespace std;

#define inf 0x3f3f3f3f
#define eps 1e-7
#define LL long long
#define ULL unsigned long long
#define MP make_pair
#define pb push_back
#define ls ( i << 1 )
#define rs ( ls | 1 )
#define md ( ( ll[i] + rr[i] ) >> 1 )
#define mxn 5020
#define PI acos( -1.0 )


// 角度转换为弧度
double torad( double deg ) {
	return deg / 180 * PI;
}

int dcmp( double x ) {  //OK
	if( fabs( x ) < eps )
		return 0;
	return x < 0 ? -1: 1;
}


struct point {
	double x, y;
	point( double x = 0, double y = 0 ): x( x ), y( y ) {}
	point operator + ( const point &b ) const {
		return point( x + b.x, y + b.y );
	}
	point operator - ( const point &b ) const {
		return point( x - b.x, y - b.y );
	}
	point operator * ( const double &k ) const {
		return point( x * k, y * k );
	}
	point operator / ( const double &k ) const {
		return point( x / k, y / k );
	}
	bool operator < ( const point &b ) const {
		if( dcmp( x - b.x ) != 0 )
			return x < b.x;
		return y < b.y;
	}
	bool operator == ( const point &b ) const {
		return dcmp( x - b.x ) == 0 && dcmp( y - b.y ) == 0;
	}
	double len() {
		return sqrt( x * x + y * y );
	}
};
struct Line {
	point v, p;
	double ang; //极角
	Line() {}
	Line( point v, point p ): v( v ), p( p ) {
		ang = atan2( v.y, v.x );
	}
	point get_point( double t ) {
		return v * t + p;
	}
	bool operator < ( const Line &L ) const {
		return ang < L.ang;
	}
};
// 圆
struct circle {
	point c;
	double r;
	circle(){}
	circle( point c, double r ): c( c ), r( r ){}
	//圆心角为a的点
	point get_point( double a ) {
		return point( c.x + cos( a ) * r, c.y + sin( a ) * r );
	}
};
double cross( point A, point B ) {  // 叉乘 OK
	return A.x * B.y - A.y * B.x;
}
double dot( point A, point B ) { //OK
	return A.x * B.x + A.y * B.y;
}
// 极角
double angle( point v ) {   //OK
	return atan2( v.y, v.x );
}

double angle( point A, point B ) {  //向量A和向量B的夹角
	return acos( dot( A, B ) / A.len() / B.len() );
}


double area( point A, point B, point C ) { // 三角形面积
	return fabs( cross( A - B, A - C ) ) / 2;
}

point rotate( point A, double rad ) {  // 向量A旋转rad弧度
	return point( A.x * cos( rad ) - A.y * sin( rad ), A.x * sin( rad ) + A.y * cos( rad ) );
}

point Normal( point A ) {// 单位法线
	double L = A.len();
	return point( - A.y / L, A.x / L );
}
// 直线的交点,P 和 Q是直线上的点, v和w是方向向量
point GetLineIntersection( point P, point v, point Q, point w ) {
	point u = P - Q;
	double t = cross( w, u ) / cross( v, w );
	return P + v * t;
}
// 点到直线的距离
double DisToLine( point P, point A, point B ) {  //OK
	point v1 = B - A, v2 = P - A;
	return fabs( cross( v1, v2 ) / v1.len() );
}
// 点到线段的距离
double DisToSeg( point P, point A, point B ) {
	if( A == B )
		return ( P - A ).len();
	point v1 = B - A, v2 = P - A, v3 = P - B;
	if( dcmp( dot( v1, v2 ) ) < 0 )
		return v2.len();
	if( dcmp( dot( v1, v3 ) ) > 0 )
		return v3.len();
	return fabs( cross( v1, v2 ) / v1.len() );
}
// 点在直线的投影
point GetLinePro( point P, point A, point B ) {
	point v = B - A;
	return A + v * ( dot( v, P - A ) / dot( v, v ) );
}
// 线段规范相交
bool SegProInters( point a1, point a2, point b1, point b2 ) {
	double c1 = cross( a2 - a1, b1 - a1 ), c2 = cross( a2 - a1, b2 - a1 ),
		c3 = cross( b2 - b1, a1 - b1 ), c4 = cross( b2 - b1, a2 - b1 );
	return dcmp( c1 ) * dcmp( c2 ) < 0 && dcmp( c3 ) * dcmp( c4 ) < 0;
}
// 点在线段上
bool Ons( point P, point a1, point a2 ) {
	return dcmp( cross( a1 - P, a2 - P ) ) == 0 && dcmp( dot( a1 - P, a2 - P ) ) < 0;
}
//多边形有向面积
double PolygonArea( point *p, int n ) {
	double area = 0;
	for( int i = 1; i < n - 1; ++i ) 
		area += cross( p[i] - p[0], p[i+1] - p[0] );
	return area / 2;
}
int GetLineCirIns( Line L, circle C, double &t1, double &t2, vector<point> &sol ) {
	double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y;
	double e = a * a + c * c, f = 2 * ( a * b + c * d ), g = b * b + d * d - C.r * C.r;
	double delta = f * f - 4 * e * g;
	if( dcmp( delta ) < 0 )
		return 0;
	if( dcmp( delta ) == 0 ) {
		t1 = t2 = - f / ( 2 * e );
		sol.pb( L.get_point( t1 ) );
		return 1;
	}
	t1 = ( - f - sqrt( delta ) ) / ( 2 * e );
	sol.push_back( L.get_point( t1 ) );
	t2 = ( - f + sqrt( delta ) ) / ( 2 * e );
	sol.push_back( L.get_point( t2 ) );
	return 2;
}
// 两圆相交
int getCCins( circle c1, circle c2, vector<point> &sol ) {
	double d = ( c1.c - c2.c ) .len();
	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( fabs( 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 * c2.r * d ) );
	point p1 = c1.get_point( a - da ), p2 = c1.get_point( a + da );
	sol.push_back( p1 );
	if( p1 == p2 )
		return 1;
	sol.push_back( p2 );
	return 2;
}
// 过点p到圆c的切线,v[i]是第i条切线。返回切线条数
int getTangents( point p, circle c, point *v ) {
	point u = c.c - p;
	double dist = u.len();
	if( dist < c.r )
		return 0;
	if( dcmp( dist - c.r ) == 0 ) {
		v[0] = rotate( u, PI / 2 );
		return 1;
	}
	double ang = asin( c.r / dist );
	v[0] = rotate( u, - ang );
	v[1] = rotate( u, + ang );
	return 2;
}

// 求两圆的切线,返回切线条数,-1表示无穷条,
// a[i] 和 b[i]分别是第i条切线在圆A和圆B上的切点
int getTangents( circle A, circle B, point *a, point *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( dcmp( rdiff * rdiff - d2 ) > 0 )
		return 0;
	double base = atan2( B.c.y - A.c.y, B.c.x - A.c.x );
	if( dcmp( d2 ) == 0 && dcmp( A.r - B.r ) == 0 )
		return -1;
	if( dcmp( d2 - rdiff * rdiff ) == 0 ) {
		a[cnt] = A.get_point( base );
		b[cnt] = B.get_point( base );
		cnt++;
		return 1;
	}
	double ang = acos( ( A.r - B.r ) / sqrt( d2 ) );
	a[cnt] = A.get_point( base + ang );
	b[cnt++] = B.get_point( base + ang );
	a[cnt] = A.get_point( base - ang );
	b[cnt++] = B.get_point( base - ang );
	if( dcmp( d2 - rsum * rsum ) == 0 ) {
		a[cnt] = A.get_point( base );
		b[cnt++] = B.get_point( PI + base );
	}
	else {
		if( dcmp( d2 - rsum * rsum ) > 0 ) {
			double ang = acos( ( A.r + B.r ) / sqrt( d2 ) );
			a[cnt] = A.get_point( base + ang );
			b[cnt++] = B.get_point( PI + base + ang );
			a[cnt] = A.get_point( base - ang );
			b[cnt++] = B.get_point( PI + base - ang );
		}
	}
	return cnt;
}

// 点在多边形内判定, -1 在边界,0,不在,1在
// 点在凸多边形内的判定, 判断点是不是在所有边的左边
int inPoly( point p, point * poly, int n ) {
	int wn = 0;
	for( int i = 0; i < n; ++i ) {
		if( Ons( p, poly[i], poly[(i+1)%n] ) )
			return -1;
		int k = dcmp( cross( poly[(i+1)%n] - poly[i], p - poly[i] ) );
		int d1 = dcmp( poly[i].y - p.y );
		int d2 = dcmp( poly[(i+1)%n].y - p.y );
		if( k > 0 && d1 <= 0 && d2 > 0 )
			wn++;
		if( k < 0 && d2 <= 0 && d1 > 0 )
			wn--;
	}
	if( wn )
		return 1;
	return 0;
}

// 凸包
int tb( point *p, int n, point *ch ) {   //OK
	sort( p, p + n );
	int m = 0;
	for( int i = 0; i < n; ++i ) {
		while( m > 1 && cross( ch[m-1] - ch[m-2], p[i] - ch[m-2] ) <= 0 )
			m--;
		ch[m++] = p[i];
	}
	int k = m;
	for( int i = n - 2; i >= 0; --i ) {
		while( m > k && cross( ch[m-1] - ch[m-2], p[i] - ch[m-2] ) <= 0 )
			m--;
		ch[m++] = p[i];
	}
	if( n > 1 )
		m--;
	return m;
}

// 点在有向线段左边
bool OnLeft( Line L, point p ) {   //OK
	return dcmp( cross( L.v, p - L.p ) ) > 0;
}
// 二直线交点,假设交点唯一存在
point GetIntersection( Line a, Line b ) {
	point u = a.p - b.p;
	double t = cross( b.v, u ) / cross( a.v, b.v );
	return a.p + a.v * t;
}

// 半平面交
int Halfins( Line *L, int n, point *poly ) { //OK
	sort( L, L + n );
	int first, last;
	point *p = new point[n];
	Line *q = new Line[n];
	q[first=last=0] = L[0];
	for( int i = 1; i < n; ++i ) {
		while( first < last && !OnLeft( L[i], p[last-1] ) ) 
			last --;
		while( first < last && !OnLeft( L[i], p[first] ) )
			first++;
		q[++last] = L[i];
		if( fabs( cross( q[last].v, q[last-1].v ) ) < eps ) {
			last--;
			if( OnLeft( q[last], L[i].p ) )
				q[last] = L[i];
		}
		if( first < last )
			p[last-1] = GetIntersection( q[last-1], q[last] );
	}
	while( first < last && !OnLeft( q[first], p[last-1] ) )
		last--;
	if( last - first <= 1 )
		return 0;
	p[last] = GetIntersection( q[last], q[first] );
	int m = 0;
	for( int i = first; i <= last; ++i )
		poly[m++] = p[i];
	return m;
}


			//		*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值