zoukankan      html  css  js  c++  java
  • 计算几何板子

    才知道为啥我们ACM教练说计算几何是一个性价比很高的东西,因为ACM让带纸质材料啊!所以只要板子我有,那计算几何确实就变得可做了。

    const db PI = acos(-1);
    In int dcmp(db x)							       //比较两个实数大小 
    {
    	if(fabs(x) < eps) return 0;
    	return x < 0 ? -1 : 1;
    }
    struct Vec								       //向量类 
    {
    	db x, y;
    	In Vec operator - (const Vec& oth)const {return (Vec){x - oth.x, y - oth.y};}
    	In Vec operator + (const Vec& oth)const {return (Vec){x + oth.x, y + oth.y};}	
    	In db operator ^ (const Vec& oth)const	{return x * oth.x + y * oth.y;}	//点积 
    	In db operator * (const Vec& oth)const {return x * oth.y - y * oth.x;}	//差积 
    	In Vec operator * (const db& a)const {return (Vec){x * a, y * a};}
    	In int operator == (const Vec& oth)const {return !dcmp(x - oth.x) && !dcmp(y - oth.y);}
    	friend In db dis(const Vec& A) {return sqrt(A.x * A.x + A.y * A.y);}	//模长 
    	friend In Vec rot(const Vec& A, const db& a) {return (Vec){A.x * cos(a) - A.y * sin(a), A.x * sin(a) + A.y * cos(a)};}	//旋转(逆时针) 
    	In bool operator < (const Vec& oth)const {return x < oth.x || (!dcmp(x - oth.x) && y < oth.y);}
    };
    struct Lin								      //直线类 
    {
    	Vec A, v;
    	friend In Lin mov(const Lin& l, const db& d)		//将直线沿垂直于该直线的左侧平移d个单位 
    	{
    		db dv = dis(l.v);
    		Vec tp = (Vec){-l.v.y, l.v.x} * (1.0 / dv);
    		return (Lin){l.A + tp * d, l.v};
    	}
    	In Vec Point(const db& t) {return A + v * t;}		//求直线上的点 
    };
    struct Cir								      //圆类 
    {
    	Vec C; db r;
    	In Vec Point(const db& a) {return C + (Vec){cos(a) * r, sin(a) * r};}
    };
    
    In db Ang(Vec A) {return atan2(A.y, A.x);}				      //求向量角度 
    In db changeAng(db a)							      //将一个角转换到[0,2PI) 
    {
    	a -= PI * 2 * floor(a / (2 * PI));
    	return a < 0 ? a + PI * 2 : a;
    }
    
    In bool onSeg(Vec A, Vec p1, Vec p2)					      //A在线段p1p2上,dcmp小于等于/小于0表示含/不含端点 
    {
    	return dcmp((p1 - A) * (p2 - A)) == 0 && dcmp((p1 - A) ^ (p2 - A)) < 0;
    }
    In bool Cross(Vec A, Vec B, Vec C, Vec D)				      //判断两条线段是否相交 
    {
    	if(onSeg(A, C, D) || onSeg(B, C, D) || onSeg(C, A, B) || onSeg(D, A, B)) return 1;	//加上这一句表示算端点 
    	return dcmp((B - A) * (C - A)) * dcmp((B - A) * (D - A)) < 0 && dcmp((D - C) * (A - C)) * dcmp((D - C) * (B - C)) < 0;
    }
    In Vec getCross(Vec A, Vec B, Vec C, Vec D)				      //计算两条直线的交点 
    {
    	Vec v = B - A, w = D - C, u = A - C;
    	db tp = (w * u) / (v * w);
    	return A + v * tp;
    }
    In db getDisPtL(Vec P, Vec A, Vec B)					      //计算点P到直线AB的距离 
    {
    	db S = (B - A) * (P - A);
    	return fabs(S) / dis(B - A);
    }
    In db getLAD(Vec V)							      //计算直线的倾斜角(角度制) 
    {
    	db ang = atan(V.y / V.x) / PI * 180;
    	while(ang < 0) ang += 360;
    	while(dcmp(ang - 180) >= 0) ang -= 180;
    	return ang; 
    }
    
    In bool disCC(Cir C1, Cir C2)						      //判断两圆是否相离(包含外切) 
    {      
    	return dcmp(dis(C1.C - C2.C) - (C1.r + C2.r)) >= 0;
    }
    In int getCrossCL(Lin l, Cir C, vector<Vec>& ans)		              //求直线和圆的交点,结果储存在ans中,返回交点个数 
    {
    	db a = l.v.x, b = l.A.x - C.C.x, c = l.v.y, d = l.A.y - C.C.y;
    	db e = a * a + c * c, f = (a * b + c * d) * 2, g = b * b + d * d - C.r * C.r;
    	db del = f * f - e * g * 4;
    	if(dcmp(del) < 0) return 0;
    	if(dcmp(del) == 0) {ans.push_back(l.Point(-f / (e * 2))); return 1;}
    	ans.push_back(l.Point((-f - sqrt(del)) / (e * 2)));
    	ans.push_back(l.Point((-f + sqrt(del)) / (e * 2)));
    	return 2;
    }
    In int getCrossCC(Cir C1, Cir C2, vector<Vec>& ans)		              //计算两个圆的交点 
    {      
    	db d = dis(C1.C - C2.C);
    	if(dcmp(d) == 0) return dcmp(C1.r - C2.r) ? 0 : -1;
    	if(dcmp(d - C1.r - C2.r) > 0 || dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;
    	db a = Ang(C2.C - C1.C), d1 = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (C1.r * d * 2));//acos(d / 2 / C1.r);
    	Vec p1 = C1.Point(a + d1), p2 = C1.Point(a - d1);
    	ans.push_back(p1); if(p1 == p2) return 1;
    	ans.push_back(p2); return 2;
    }
    
    In db calcS(Vec* p, int n)						     //计算一个多边形的面积 
    {
    	db ret = 0;
    	for(int i = 2; i < n; ++i)
    		ret += (p[i] - p[1]) * (p[i + 1] - p[1]);
    	return fabs(ret / 2); 
    }
    
    In int PiP(Vec A, Vec* p, int n)					     //判定点是否在多边形内 
    {
    	int wn = 0;
    	p[0] = p[n]; 
    	for(int i = 1; i <= n; ++i)
    	{
    		Vec p1 = p[i - 1], p2 = p[i]; 
    		if(onSeg(A, p1, p2)) return -1;
    		int k = dcmp((p2 - p1) * (A - p1));
    		int d1 = dcmp(p1.y - A.y), d2 = dcmp(p2.y - A.y);
    		if(k > 0 && d1 <= 0 && d2 > 0) wn++;
    		if(k < 0 && d2 <= 0 && d1 > 0) wn--;
    	}
    	p[0] = (Vec){0, 0};
    	return wn != 0;
    }
    
    Vec S;									    //求凸包,返回凸包数组st和大小top. 
    In bool cmpP(Vec A, Vec B)
    {
    	db s = (A - S) * (B - S);
    	return dcmp(s) ? s > 0 : dis(A - S) < dis(B - S);
    }
    In db calcP(Vec A, Vec B, Vec C) {return (B - A) * (C - A);}
    In void getPol(Vec* p, int n, Vec* st, int& top)
    {
    	int id = 1;
    	for(int i = 2; i <= n; ++i)
    		if(p[i].x < p[id].x || (!dcmp(p[i].x - p[id].x) && p[i].y < p[id].y)) id = i;
    	if(id ^ 1) swap(p[1], p[id]);
    	S = p[1];
    	sort(p + 2, p + n + 1, cmpP);
    	st[top = 1] = p[1];
    	for(int i = 2; i <= n; ++i)
    	{
    		while(top > 1 && calcP(st[top - 1], st[top], p[i]) < 0) top--;
    		st[++top] = p[i];
    	}	
    }
    
  • 相关阅读:
    在SplendidCRM中添加用户控件
    SPendidCRM:给HK的ImageInfoEntryEditView增加一个checkbox,用于判断特殊类型的PODS记录
    html button 跳转ASP.NET页面跳转技术总结
    让<li>不显示超出内容,显示... (编程方法和CSS方法)
    SplendidCRM Popup.aspx的hyperlink字段配置的易错点
    asp.net 个别页面URL参数出现中文乱码的解决方法
    解决:工具箱里边没了Dev控件
    DevControlgridview的属性说明 (转)
    DevControlgridview的属性说明 (转)
    VM如何设置U盘启动
  • 原文地址:https://www.cnblogs.com/mrclr/p/14070759.html
Copyright © 2011-2022 走看看