計算幾何模板 ①
阿新 • • 發佈:2018-11-21
包含一些點與直線,線段的操作
凸包的構建與判斷之類的操作
#include<cmath> #include<cstring> #include<vector> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; const double eps=1e-6; const double Pi=acos(-1.00); inline int dcmp(double x) { if(x>eps)return 1; return x<-eps?-1:0; } struct Vector { double x,y; Vector(double X=0,double Y=0) { x=X,y=Y; } bool operator < (const Vector &b)const { return dcmp(x-b.x)==0?y<b.y:x<b.x; } bool operator == (const Vector &b)const { return dcmp(x-b.x)==0&&dcmp(y-b.y)==0; } }p[5]; double dabs(Vector a) { return sqrt(a.x*a.x+a.y*a.y); } typedef Vector Point; 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 b){return Vector(a.x*b,a.y*b);} Vector operator / (Vector a,double b){return Vector(a.x/b,a.y/b);} struct Line { Point s,e; Line(Point X=Vector(),Point Y=Vector()) { s=X,e=Y; } }; typedef Line Segment; double dot(Vector a,Vector b) { return a.x*b.x+a.y*b.y; } double cross(Vector a,Vector b) { return a.x*b.y-a.y*b.x; } double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } bool on_seg(Point a,Segment a1) { Point b=a1.s,c=a1.e; return dcmp(cross(b-a,c-a))==0&&min(b.x,c.x)<=a.x&&a.x<=max(b.x,c.x)&&min(b.y,c.y)<=a.y&&a.y<=max(b.y,c.y); } Point get_cross(Point a,Point b,Point c,Point d) { double t=cross(b-a,c-a)/(cross(b-a,c-a)+cross(d-a,b-a)); return Point(c.x+(d.x-c.x)*t,c.y+(d.y-c.y)*t); } bool is_cross(Line a1,Line a2) { Point a=a1.s,b=a1.e,c=a2.s,d=a2.e; int c1=dcmp(cross(b-a,c-a)); int c2=dcmp(cross(b-a,d-a)); int o1=dcmp(cross(d-c,b-c)); int o2=dcmp(cross(d-c,a-c)); if(c1*c2<=0&&o1*o2<=0)return true; if(c1==0&&on_seg(c,a1))return true; if(c2==0&&on_seg(d,a1))return true; if(o1==0&&on_seg(b,a2))return true; if(o2==0&&on_seg(a,a2))return true; return false; } Point get_nearest_point_on_segment(Point a,Line a1) { Point b=a1.s,c=a1.e; double t=dot(a-b,c-b)/dot(c-b,c-b); if(dcmp(t)!=-1&&dcmp(1-t)!=-1)return Vector(b.x+(c.x-b.x)*t,b.y+(c.y-b.y)*t); if(dist(a,b)<dist(a,c))return b; return c; } bool is_cross_line(Line a1,Segment a2) { Point a=a1.s,b=a1.e,c=a2.s,d=a2.e; int c1=dcmp(cross(b-a,c-a)); int c2=dcmp(cross(b-a,d-a)); if(c1*c2<=0)return true; return false; } struct Circle { Point O; double R; Circle(Point o=Vector(),double r=0) { O=o,R=r; } }; Point Base; bool cmp_ang(const Point &a,const Point &b) { int tmp=dcmp(cross(a-Base,b-Base)); if(tmp==0)return dist(Base,a)<dist(Base,b); else return tmp>0; } void sort_point(Point *s,int L,int R,Point base) { Base=base; sort(s+L,s+1+R,cmp_ang); return; } struct Polygon { Point node[10025]; Line edge[10025]; int cnt; double C; double A; void build_edge() { for(int i=1;i<cnt;i++)edge[i]=Line(node[i],node[i+1]); edge[cnt]=Line(node[cnt],node[1]); return; } bool is_convex_hull() { bool s[3]; memset(s,0,sizeof(s)); for(int i=1;i<cnt-1;i++) { s[dcmp(cross(node[i+1]-node[i],node[i+2]-node[i]))+1]=true; if(s[0]&&s[2])return false; } s[dcmp(cross(node[cnt-1]-node[cnt-2],node[cnt]-node[cnt-2]))+1]=true; s[dcmp(cross(node[cnt]-node[cnt-1],node[1]-node[cnt-1]))+1]=true; s[dcmp(cross(node[1]-node[cnt],node[2]-node[cnt]))+1]=true; if(s[0]&&s[2])return false; return true; } int is_in_polygon(Point a) { Line ray; ray.s=a; ray.e=Vector(-100000000.0,a.y); int ans=0; for(int i=1;i<=cnt;i++) { Point s1=edge[i].s,s2=edge[i].e; if(on_seg(a,edge[i]))return 0; if(dcmp(s1.y-s2.y)==0)continue; if(on_seg(s1,ray)) { if(dcmp(s1.y-s2.y)>0)ans++; } else if(on_seg(s2,ray)) { if(dcmp(s2.y-s1.y)>0)ans++; } else if(is_cross(ray,edge[i]))ans++; } if(ans%2==1)return 1; return -1; } bool circle_is_in_polygon(Circle a) { if(is_in_polygon(a.O)<0)return false; for(int i=1;i<=cnt;i++) if(dcmp(dist(a.O,get_nearest_point_on_segment(a.O,edge[i]))+eps-a.R)<0)return false; return true; } void get_convex_hull(Point *s,int num) { if(num==0) { cnt=0; return; } if(num==1) { cnt=1; node[1]=s[1]; return; } if(num==2) { cnt=2; node[2]=s[2]; node[1]=s[1]; return ; } for(int i=1;i<=num;i++) if(s[i]<s[1])swap(s[1],s[i]); sort_point(s,2,num,s[1]); cnt=2; node[1]=s[1],node[2]=s[2]; for(int i=3;i<=num;i++) { while(cnt>=2&&dcmp(cross(node[cnt]-node[cnt-1],s[i]-node[cnt-1]))<=0)cnt--; node[++cnt]=s[i]; } return; } double get_Circumference() { C=0; for(int i=1;i<=cnt;i++) C+=dist(edge[i].s,edge[i].e); return C; } double get_Area() { A=0; for(int i=1;i<cnt;i++)A+=cross(node[i],node[i+1])/2; A+=cross(node[cnt],node[1])/2; return A; } }; bool is_cross_polygon(Polygon a,Polygon b) { for(int i=1;i<=a.cnt;i++) for(int j=1;j<=b.cnt;j++) if(is_cross(a.edge[i],b.edge[j]))return true; return false; } int main() { return 0; }