计算几何模板专页

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
原文地址:https://www.cnblogs.com/hehe54321/p/8462602.html