计算几何模板 ①
Posted harry-bh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算几何模板 ①相关的知识,希望对你有一定的参考价值。
包含一些点与直线,线段的操作
凸包的构建与判断之类的操作
#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;
}
以上是关于计算几何模板 ①的主要内容,如果未能解决你的问题,请参考以下文章