1. 程式人生 > >計算幾何模板專頁

計算幾何模板專頁

ntp 相等 cmp 兩個 prop view double abs img

2018-2-23改

技術分享圖片
  1 #include<cstdio>
  2 #include<cmath>
  3 using namespace std;
  4 namespace X
  5 {
  6     const double eps=1e-10;
  7     struct Point
  8     {
  9         double x,y;
 10         Point(double x=0,double y=0):x(x),y(y){}
 11     };
 12     typedef Point Vec;
13 Vec operator+(const Vec& a,const Vec& b) 14 { 15 return Vec(a.x+b.x,a.y+b.y); 16 } 17 Vec operator-(const Vec& a,const Vec& b) 18 { 19 return Vec(a.x-b.x,a.y-b.y); 20 } 21 Vec operator*(const double& a,const Vec& b)
22 { 23 return Vec(a*b.x,a*b.y); 24 } 25 Vec operator*(const Vec& a,const double& b) 26 { 27 return Vec(b*a.x,b*a.y); 28 } 29 Vec operator/(const Vec& a,const double& b) 30 { 31 return Vec(a.x/b,a.y/b); 32 } 33
int dcmp(double x) 34 //正為1,負為-1,0為0 35 { 36 if(fabs(x)<eps) return 0; 37 return x<0?-1:1; 38 } 39 bool operator==(const Vec& a,const Vec& b) 40 //判向量相等 41 { 42 return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; 43 } 44 double dot(const Vec& a,const Vec& b) 45 //點積 46 { 47 return a.x*b.x+a.y*b.y; 48 } 49 double cross(const Vec& a,const Vec& b) 50 //叉積 51 { 52 return a.x*b.y-a.y*b.x; 53 } 54 double len(const Vec& x) 55 //向量長度 56 { 57 return sqrt(dot(x,x)); 58 } 59 double angle(const Vec& a,const Vec& b) 60 //夾角,0~180° 61 { 62 return acos(dot(a,b)/len(a)/len(b)); 63 } 64 double angle1(const Vec& a,const Vec& b) 65 //夾角,帶方向,a到b逆時針為正,順時針為負,共線為0 66 { 67 return acos(dot(a,b)/len(a)/len(b))*(dcmp(cross(a,b))); 68 } 69 Vec rotate(const Vec& a,const double& rad) 70 //旋轉,正為逆時針,負為順時針 71 { 72 return Vec(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad)); 73 } 74 Vec normal(const Vec& x) 75 //單位法線,左轉90°後除以自身長度 76 { 77 double l=len(x); 78 return Vec(-x.y/l,x.x/l); 79 } 80 Vec normal1(const Vec& x) 81 //法線,不歸一化 82 { 83 return Vec(-x.y,x.x); 84 } 85 Point lineline(const Point& p,const Vec& v,const Point& q,const Vec& w) 86 //直線交點,GetLineIntersection 87 { 88 return p+v*cross(w,p-q)/cross(v,w); 89 } 90 double ptline(const Point& p,const Point& a,const Point& b) 91 //point_to_line,點到直線距離,DistanceToLine 92 { 93 Vec v1=b-a,v2=p-a; 94 return fabs(cross(v1,v2)/len(v1)); 95 } 96 double ptseg(const Point& p,const Point& a,const Point& b) 97 //point_to_segment,點到線段距離,DistanceToSegment 98 { 99 if(a==b) return len(p-a); 100 //Vec v1=b-a,v2=a-p,v3=p-b; 101 Vec v1=b-a,v2=p-a,v3=p-b; 102 if(dcmp(dot(v1,v2))<0) return len(v2); 103 else if(dcmp(dot(v1,v3))>0) return len(v3); 104 else return fabs(cross(v1,v2)/len(v1)); 105 } 106 double area2(const Point& a,const Point& b,const Point& c) 107 //叉積對應平行四邊形的面積 108 { 109 return cross(b-a,c-a); 110 } 111 double thrarea(const Point& a,const Point& b,const Point& c) 112 //三角形面積,絕對值 113 { 114 return fabs(cross(b-a,c-a)/2); 115 } 116 bool ifpar(const Vec& a,const Vec& b) 117 //ifParallel 118 //是否共線/平行 119 { 120 return dcmp(cross(a,b))==0; 121 } 122 Point pointline(const Point& p,const Point& a,const Vec& v) 123 //點在直線上投影,GetLineProjection 124 { 125 return a+v*(dot(p-a,v)/dot(v,v)); 126 } 127 bool ifsegseg(const Point& a1,const Point& a2,const Point& b1,const Point& b2) 128 //SegmentProperIntersection,線段相交判定,不包含端點,不允許共線。有交點時求交點直接用直線交點即可 129 //此處就是求兩條線段的兩個端點是否都分別在另一條線段的兩側 130 { 131 double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1), 132 c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1); 133 return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0; 134 } 135 bool ifonseg(const Point& p,const Point& a1,const Point& a2) 136 //OnSegment,點是否在線段上,不含端點 137 //這樣就能判定向量p a1與p a2共線,且方向相反 138 { 139 return dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0; 140 } 141 bool ifonseg1(const Point& p,const Point& a1,const Point& a2) 142 //點是否在線段上,含端點 143 { 144 return (dcmp(cross(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<0)||p==a1||p==a2; 145 } 146 bool ifsegseg1(const Point& a1,const Point& a2,const Point& b1,const Point& b2) 147 //線段相交判定,包含端點,允許共線 148 { 149 double c1=cross(a2-a1,b1-a1),c2=cross(a2-a1,b2-a1), 150 c3=cross(b2-b1,a1-b1),c4=cross(b2-b1,a2-b1); 151 return (dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0) 152 ||ifonseg(a1,b1,b2)//(dcmp(c1)==0&&dcmp(c2)==0)|| 153 ||ifonseg(a2,b1,b2)||ifonseg(b1,a1,a2)||ifonseg(b2,a1,a2) 154 ||a1==b1||a1==b2||a2==b1||a2==b2; 155 } 156 double polyarea(Point p[],int n) 157 //PolygonArea,有向面積,要求點按順序能組成多邊形(不會邊相交,可以凹),如果順時針轉就是負,逆時針就是正(未驗證) 158 { 159 double ans=0; 160 for(int i=1;i<n-1;i++) 161 ans+=cross(p[i]-p[0],p[i+1]-p[0]); 162 return ans/2; 163 } 164 }; 165 using namespace X; 166 int main() 167 { 168 169 return 0; 170 }
View Code

計算幾何模板專頁