基礎計算幾何
阿新 • • 發佈:2018-05-02
lap 交點 端點 位置 相交 rotate opera n) highlight
結構體的定義
struct point { double x, y; point(double _x, double _y):x(_x), y(_y){} // 點-點=向量 point operator-(const point &v){ return point(x-v.x, y-v.y); } }; int dcmp(double x){ if (fabs(x)<eps) return 0; else return x<0?-1:1; } bool operator == (const point &a, const point &b){ return (dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0); } typedef point Vector; // Vector表示向量
點
//點積 double Dot(Vector a, Vector b){return a.x*b.x+a.y*b.y;} //線段的長度 double Lenth(Vector a){return sqrt(Dot(a, a));} //向量的夾角(弧度) double Angle(Vector a, Vector b){return acos(Dot(a, b)/Lenth(a)/Lenth(b));} //叉積 double Cross(Vector a, Vector b){return a.x*b.y-a.y*b.x;} //三角形有向面積的2倍 double Area2(point a, point b, point c){return Cross(b-a, c-a);} //向量旋轉,a為逆時針旋轉的角度 // rad是弧度 point Rotate(Vector a, double rad){ return point(a.x*cos(rad)-a.y*sin(rad), a.x*sin(rad)+a.y*cos(rad)); } //計算向量的單位法線 point Normal(Vector a){ double L = Lenth(a); return point(-a.y/L, a.x/L); }
直線
// 兩條直線的交點 // 兩條直線為 p+tv, q+tw,其中p, q為兩直線上的一點, v,w是直線所在方向的向量, // 交點在第一條直線的參數為t1, 第二條直線的參數為t2 // t1 = (cross(w,u)/cross(v,w)); t2 = (cross(v,u)/cross(v,w)); // 調用前要確保兩直線有唯一交點,當且僅當兩直線不共線 point Getline(point p, Vector v, point q, Vector w){ point u = p-q; double t = Cross(w, u)/Cross(v, w); return point(p.x+v.x*t, p.y+v.y*t); } //點到直線的距離 double Dis(point p, point a, point b){ Vector v1 = b-a, v2 = p-a; return fabs(Cross(v1, v2)/Lenth(v1)); } //點到線段的距離 //點p在直線的投影可能在直線上,也可能不在直線上 double Dis2(point p, point a, point b){ if (a==b) return Lenth(p-a); Vector v1=b-a, v2 = p-a, v3=p-b; if (dcmp(Dot(v1, v2))<0) return Lenth(v2); // 註意大小於號 if (dcmp(Dot(v1, v3))>0) return Lenth(v3); else return fabs(Cross(v1, v2)/Lenth(v1)); } //點在線段上的投影 point Getline2(point p, point a, point b){ Vector v = b-a; double f = Dot(v, p-a)/Dot(v, v); return point(a.x+v.x*f, a.y+v.y*f); } //線段相交判定(交點不在端點的位置,且兩直線僅有唯一交點) bool Inter(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 OneInter(point p, point a1, point a2){ return dcmp(Cross(a1-p, a2-p))==0 && dcmp(Dot(a1-p, a2-p))<0; } // 視題目要求是否特判兩直線有端點重合的情況
多邊形
//多邊形面積(有方向) vector<point>ve; double ConvexArea(int n){ double area = 0; for(int i = 1; i < n-1; i++){ area += Cross(ve[i]-ve[0], ve[i+1]-ve[0]); } return area/2; }
整體一起
const double eps = 1e-10; const double pi = acos(-1.0); struct point { double x, y; point(double _x, double _y):x(_x), y(_y){} // 點-點=向量 point operator-(const point &v){ return point(x-v.x, y-v.y); } }; int dcmp(double x){ if (fabs(x)<eps) return 0; else return x<0?-1:1; } bool operator == (const point &a, const point &b){ return (dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0); } typedef point Vector; // Vector表示向量 //點積 double Dot(Vector a, Vector b){return a.x*b.x+a.y*b.y;} //線段的長度 double Lenth(Vector a){return sqrt(Dot(a, a));} //向量的夾角(弧度) double Angle(Vector a, Vector b){return acos(Dot(a, b)/Lenth(a)/Lenth(b));} //叉積 double Cross(Vector a, Vector b){return a.x*b.y-a.y*b.x;} //三角形有向面積的2倍 double Area2(point a, point b, point c){return Cross(b-a, c-a);} //向量旋轉,a為逆時針旋轉的角度 // rad是弧度 point Rotate(Vector a, double rad){ return point(a.x*cos(rad)-a.y*sin(rad), a.x*sin(rad)+a.y*cos(rad)); } //計算向量的單位法線 point Normal(Vector a){ double L = Lenth(a); return point(-a.y/L, a.x/L); } // 兩條直線的交點 // 兩條直線為 p+tv, q+tw,其中p, q為兩直線上的一點, v,w是直線所在方向的向量, // 交點在第一條直線的參數為t1, 第二條直線的參數為t2 // t1 = (cross(w,u)/cross(v,w)); t2 = (cross(v,u)/cross(v,w)); // 調用前要確保兩直線有唯一交點,當且僅當兩直線不共線 point Getline(point p, Vector v, point q, Vector w){ point u = p-q; double t = Cross(w, u)/Cross(v, w); return point(p.x+v.x*t, p.y+v.y*t); } //點到直線的距離 double Dis(point p, point a, point b){ Vector v1 = b-a, v2 = p-a; return fabs(Cross(v1, v2)/Lenth(v1)); } //點到線段的距離 //點p在直線的投影可能在直線上,也可能不在直線上 double Dis2(point p, point a, point b){ if (a==b) return Lenth(p-a); Vector v1=b-a, v2 = p-a, v3=p-b; if (dcmp(Dot(v1, v2))<0) return Lenth(v2); // 註意大小於號 if (dcmp(Dot(v1, v3))>0) return Lenth(v3); else return fabs(Cross(v1, v2)/Lenth(v1)); } //點在線段上的投影 point Getline2(point p, point a, point b){ Vector v = b-a; double f = Dot(v, p-a)/Dot(v, v); return point(a.x+v.x*f, a.y+v.y*f); } //線段相交判定(交點不在端點的位置,且兩直線僅有唯一交點) bool Inter(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 OneInter(point p, point a1, point a2){ return dcmp(Cross(a1-p, a2-p))==0 && dcmp(Dot(a1-p, a2-p))<0; } // 視題目要求是否特判兩直線有端點重合的情況 //多邊形面積(有方向) vector<point>ve; double ConvexArea(int n){ double area = 0; for(int i = 1; i < n-1; i++){ area += Cross(ve[i]-ve[0], ve[i+1]-ve[0]); } return area/2; }
基礎計算幾何