挺全的二维几何模板,持续修改中

//转自白书
struct Point
{
	double x,y;
	Point(double xx,double yy)
	{
		x=xx;
		y=yy;
	}
	Point()
	{
		x=0;
		y=0;
	}
};
typedef Point Vector;
Vector operator+(Vector A,Vector B)
{
	return Vector(A.x+B.x,A.y+B.y);
}
Vector operator-(Point A,Point B)
{
	return Vector(A.x-B.x,A.y-B.y);
}
Vector operator*(Vector A,double p)
{
	return Vector(A.x*p,A.y*p);
}
Vector operator/(Vector A,double p)
{
	return Vector(A.x/p,A.y/p);
}
Vector operator*(double p,Vector A)
{
	return Vector(A.x*p,A.y*p);
}
Vector operator/(double p,Vector A)
{
	return Vector(A.x/p,A.y/p);
}
bool operator<(const Point& a,const Point& b)
{
	return a.x<b.x||(a.x==b.x&&a.y<b.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;
}
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 Length(Vector a)
{
    //计算长度
	return sqrt(Dot(a,a));
}
double Angle(Vector A,Vector B)
{
    //计算AB夹角
    return acos(Dot(A,B)/Length(A)/Length(B));
}
double Area2(Point A,Point B,Point C)
{
    //计算三角形ABC的面积的二倍
    return Cross(B-A,C-A);
}
Vector Rotate(Vector a,double rad)
{
    //向量逆时针旋转rad角
    //rad弧度
    return Vector(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
Vector Normal(Vector a)
{
    //计算向量的单位法线,即左转90度,长度归一化。
    //用前确保A不是零向量
    double l=Length(a);
    return Vector(-a.y/l,a.x/l);
}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
{
    //求解直线P+t*v  Q+t*w 的交点
    //用前确保两条直线有唯一交点
    //当且仅当cross(v,w)!=0
    Vector u=P-Q;
    double t=Cross(w,u)/Cross(v,w);
    return P+v*t;
}
double DistanceToLine(Point p,Point a,Point b)
{
	//计算点P到直线AB距离
	Point v1=b-a;
	Point v2=p-a;
	return fabs(Cross(v1,v2))/Length(v1);
	//如果不取绝对值,得的是有向距离
}
double DistanceToSegment(Point p,Point a,Point b)
{
    //计算点P到线段AB距离
    if(a==b)
    {
        return Length(p-a);
    }
    Vector v1=b-a,v2=p-a,v3=p-b;
    if(dcmp(Dot(v1,v2))<0)
    {
        return Length(v2);
    }
    else
    if(dcmp(Dot(v1,v3))>0)
    {
        return Length(v3);
    }
    else
    {
        return fabs(Cross(v1,v2))/Length(v1);
    }
}
Point GetLineProjection(Point p,Point a,Point b)
{
    //求点在直线上投影
    //AB直线:A+tv , 投影Q的参数为 t0
    //由 Dot(v,P-(A+t0*v))==0 得出
    Vector v=b-a;
    return a+v*(Dot(v,p-a)/Dot(v,v));
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
    //线段相交判定
    double c1=Cross(a2-a1,b1-a1);
    double c2=Cross(a2-a1,b2-a1);
    double c3=Cross(b2-b1,a1-b1);
    double c4=Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
bool OnSegment(Point p,Point a1,Point a2)
{
    //判断一个点在线段上
    return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
double ConvexPolygonArea(Point* p,int n)
{
    //从第一个顶点出发把凸多边形分成 n-2 个三角形
    double area=0;
    for(int i=1;i<n-1;i++)
    {
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    }
    return area/2;
}
//-------------------------------------------------
struct Circle
{
    Point c;
    double r;
    Circle()
    {

    }
    Circle(Point cc,double rr)
    {
        c=cc;
        r=rr;
    }
    Point point(double a)
    {
        //通过圆心角来求坐标
        return Point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
};
struct Line
{
    Point v;
    Point p;
    Point point(double a)
    {
        return v+a*(p-v);
    }
};
int getLineCircleIntersection(Line l,Circle cc,double& t1,double& t2,vector<Point>& sol)
{
    //直线和圆的交点,直线为AB,圆的圆心为C,半径为R,第一种方法是解方程组
    //设交点为P=A+t*(B-A),代入圆方程整理后先得到 (a*t+b)^2+(c*t+d)^2=r^2
    //进一步整理后得到一元二次方程 e*t^2+f*t+g=0
    //根据判别式的值可以区分3种情况,
    //
    //函数返回的是交点个数,参数sol存放的是交点本身
    //没有清空,可以反复调用函数,把所有的交点放在一个sol里
    //---
    //另一种方法是几何法
    //先求C在AB上的投影P,AB的单位向量V
    //交点P-LV,P+LV,由勾股定理算出
    double a=l.v.x;
    double b=l.p.x-cc.c.x;
    double c=l.v.y;
    double d=l.p.y-cc.c.y;
    double e=a*a+c*c;
    double f=2*(a*b+c*d);
    double g=b*b+d*d-cc.r*cc.r;
    double delta=f*f-4*e*g;//判别式
    if(dcmp(delta)<0)
    {
        return 0;//相离
    }
    if(dcmp(delta)==0)
    {
        t1=t2=-f/(2*e);
        sol.push_back(l.point(t1));
        return 1;//相切
    }
    t1=(-f-sqrt(delta))/(2*e);
    sol.push_back(l.point(t1));
    t2=(-f+sqrt(delta))/(2*e);
    sol.push_back(l.point(t2));
    return 2;//相交
}
double angle(Vector v)
{
    //计算向量的极角
    return atan2(v.y,v.x);
}
int getCircleCircleIntersection(Circle c1,Circle c2,vector<Point>& sol)
{
    double d=Length(c1.c-c2.c);
    if(dcmp(d)==0)
    {
        if(dcmp(c1.r-c2.r)==0)
        return -1;//两圆重合
        return 0;
    }
    if(dcmp(c1.r+c2.r-d)<0)
    return 0;
    if(dcmp(fabs(c1.r-c2.r)-d)>0)
    return 0;

    double a=angle(c2.c-c1.c);//向量C1C2的极角
    double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
    //计算C1C2到C1P1的角
    Point p1=c1.point(a-da);
    Point p2=c1.point(a+da);
    sol.push_back(p1);
    if(p1==p2)
    return 1;
    sol.push_back(p2);
    return 2;
}
int getTangents(Point p,Circle c,Vector* v)
{
    //过点p到圆C的切线,v[i]是第i条切线的向量,返回切线条数
    Vector u=c.c-p;
    double dist=Length(u);
    if(dist<c.r)
    return 0;
    else
    if(dcmp(dist-c.r)==0)
    {
        v[0]=Rotate(u,PI/2);
        return 1;
    }
    else
    {
        double ang=asin(c.r/dist);
        v[0]=Rotate(u,-ang);
        v[1]=Rotate(u,ang);
        return 2;
    }
}
int getTangents(Circle a,Circle b,Point* aa,Point* bb)
{
    //返回切线条数,-1表示无穷条切线
    //a[i]和b[i]分别表示第i条切线在圆A和圆B上的切点
    int cnt=0;
    if(a.r<b.r)
    {
        swap(a,b);
        swap(aa,bb);
    }
    int d2=(a.c.x-b.c.x)*(a.c.x-b.c.x)+(a.c.y-b.c.y)*(a.c.y-b.c.y);
    int rdiff=a.r-b.r;
    int rsum=a.r+b.r;
    if(d2<rdiff*rdiff)
    {
        return 0;//内含
    }
    double base=atan2(b.c.y-a.c.y,b.c.x-a.c.x);
    if(d2==0&&a.r==b.r)
    return -1;//无穷多条切线
    if(d2==rdiff*rdiff)
    {
        aa[cnt]=a.point(base);
        bb[cnt]=b.point(base);
        cnt++;
        return 1;//内切,1条
    }
    //有外公切线
    double ang=acos((a.r-b.r)/sqrt(d2));
    aa[cnt]=a.point(base+ang);
    bb[cnt]=b.point(base+ang);
    cnt++;
    aa[cnt]=a.point(base-ang);
    bb[cnt]=b.point(base-ang);
    cnt++;

    if(d2==rsum*rsum)
    {
        aa[cnt]=a.point(base);
        bb[cnt]=b.point(base+PI);
        cnt++;//一条内公切线
    }
    else
    if(d2>rsum*rsum)
    {
        double ang=acos((a.r+b.r)/sqrt(d2));
        aa[cnt]=a.point(base+ang);
        bb[cnt]=b.point(PI+base+ang);
        cnt++;
        aa[cnt]=a.point(base-ang);
        bb[cnt]=b.point(PI+base-ang);
        cnt++;//两条内公切线
    }
    return cnt;
}
Circle CircumscribedCircle(Point p1,Point p2,Point p3)
{
    //三角形外接圆
    double bx=p2.x-p1.x;
    double by=p2.y-p1.y;
    double cx=p3.x-p1.x;
    double cy=p3.y-p1.y;
    double d=2*(bx*cy-cx*by);
    double ccx=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d+p1.x;
    double ccy=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d+p1.y;
    Point p=Point(ccx,ccy);
    return Circle(p,Length(p1-p));
}
Circle InscribedCircle(Point p1,Point p2,Point p3)
{
    //三角形内切圆
    double a=Length(p2-p3);
    double b=Length(p3-p1);
    double c=Length(p1-p2);
    Point p=(p1*a+p1*b+p3*c)/(a+b+c);
    return Circle(p,DistanceToLine(p,p1,p2));
}
double torad(double deg)
{
    //角度转弧度
    return deg/180*PI;
}
void get_coord(double r,double lat,double lng,double& x,double& y,double& z)
{
    //经纬度(角度)转化为空间坐标
    lat=torad(lat);
    lng=torad(lng);
    x=r*cos(lat)*cos(lng);
    y=r*cos(lat)*sin(lng);
    z=r*sin(lat);
}
//求球面上两点最短距离,走大圆弧
//半径r,弦长d,圆心角 2arcsin(d/2r)
struct Polygon
{
    int n;
    Point p[1000];
    Polygon(int nn,Point* pp)
    {
        n=nn;
        for(int q=0;q<n;q++)
        {
            p[q]==pp[q];
        }
    }
    Point operator[](int a) const
    {
        return p[a];
    }
};
int isPointInPolygon(Point p,Polygon po)
{
    //假想有一条向右的射线,统计多边形穿过这条射线正反多少次,把这个数记为绕数
    //逆时穿过加1,顺时针穿过减1
    int wn=0;
    int n=po.n;
    for(int i=0;i<n;i++)
    {
        if(OnSegment(p,po[i],po[(i+1)%n]))
        return -1;//在边界上
        int k=dcmp(Cross(po[(i+1)%n]-po[i],p-po[i]));
        int d1=dcmp(po[i].y-p.y);
        int d2=dcmp(po[(i+1)%n].y-p.y);
        if(k>0&&d1<=0&&d2>0)
        wn++;
        if(k<0&&d1<=0&&d2>0)
        wn--;
    }
    if(wn!=0)
    return 1;//内部
    return 0;//外部
}
//点在凸多边形内判定更简单,只要判断是否在所有边的左边
//各顶点按逆时针顺序
int ConvexHull(Point* p,int n,Point* ch)
{
    //计算凸包,输入点数组p,个数为n,输出点数组ch,函数返回凸包顶点数
    //输入不能有重复点,函数执行完后输入点的顺序被破坏
    //如果不希望在凸包的边上有输入点,把两个<=改成<
    //在精度要求高时建议用dcmp比较
    sort(p,p+n);
    int m=0;
    for(int i=0;i<n;i++)
    {
        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)
        m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)
        m--;
        ch[m++]=p[i];
    }
    if(n>1)
    m--;
    return m;
}

来份更全的

using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
int dcmp(double x){
	if(fabs(x)<eps)return 0;
	return x>0?1:-1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0){
		x=_x;y=_y;
	}
};
Point operator + (Point a,Point b){ 
	return Point(a.x+b.x,a.y+b.y);
}
Point operator - (Point a,Point b){
	return Point(a.x-b.x,a.y-b.y);
}
Point operator * (Point a,double p){
	return Point(a.x*p,a.y*p);
}
Point operator / (Point a,double p){
	return Point(a.x/p,a.y/p);
}
bool operator < (const Point &a,const Point &b){//重载大小排序,
	return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
bool operator == (const Point &a,const Point &b){//重载相等
	return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Point a,Point b){//点积
	return a.x*b.x+a.y*b.y;
}
double Cross(Point a,Point b){//叉积
	return a.x*b.y-a.y*b.x;
}
double Length(Point a){//向量长度
	return sqrt(Dot(a,a));
}
double Angle(Point a,Point b){//a->b顺时针为负,逆时针为正。
	return acos(Dot(a,b)/Length(a)/Length(b));
}
Point Rotate(Point a,double rad){  //向量逆时针旋转,rad为弧度。
	return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
double Area2(Point a,Point b,Point c){//三角形面积二倍。
	return fabs(Cross(b-a,c-a));
}
Point Normal(Point a){//计算向量的单位法线,即左转90度,长度归一化。
	double l=Length(a);//用前确保A不是零向量
	return Point(-a.y/l,a.x/l);  
}
Point GetLineIntersection(Point P,Point v,Point Q,Point w){
	Point u=P-Q;//求解直线P+t*v  Q+t*w 的交点
	double t=Cross(w,u)/Cross(v,w);//用前确保两条直线有唯一交点
	return P+v*t;//当且仅当cross(v,w)!=0
}
double DistanceToLine(Point p,Point a,Point b){
	Point v1=b-a;//计算点P到直线AB距离
	Point v2=p-a;//如果不取绝对值,得的是有向距离
	return fabs(Cross(v1,v2))/(Length(v1));
}
double DistanceToSegment(Point p,Point a,Point b){
	if(a==b)return Length(p-a);//点到线段AB的距离。
	Point v1=b-a,v2=p-a,v3=p-b;
	if(dcmp(Dot(v1,v2))<0)return Length(v2);
	else if(dcmp(Dot(v1,v3))>0)return Length(v3);
	else return fabs(Cross(v1,v2))/Length(v1);
}
Point GetLineProjection(Point p,Point a,Point b){
    //求点在直线上投影
    //AB直线:A+tv , 投影Q的参数为 t0
    //由 Dot(v,P-(A+t0*v))==0 得出	
	Point v=b-a;
	return a+v*(Dot(v,p-a)/Dot(v,v));
}
void getLineGenralEquation(Point p1,Point p2,double &a,double &b,double &c){
	a=p2.y-p1.y;//直线两点式转一般式。
	b=p1.x-p2.x;
	c=-a*p1.x-b*p1.y;
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){
	//线段相交判定
    double c1=Cross(a2-a1,b1-a1);
    double c2=Cross(a2-a1,b2-a1);
    double c3=Cross(b2-b1,a1-b1);
    double c4=Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}
bool OnSegment(Point p,Point a1,Point a2){
    //判断一个点在线段上
    return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}
double ConvexPolygonArea(Point* p,int n){
    //从第一个顶点出发把凸多边形分成 n-2 个三角形
    double area=0;
    for(int i=1;i<n-1;i++)area+=Cross(p[i]-p[0],p[i+1]-p[0]);
    return area/2;
}
struct Circle{
    Point c;
    double r;
    Circle(){}
    Circle(Point cc,double rr){
        c=cc; r=rr;
    }
    Point point(double a){
        //通过圆心角来求坐标
        return Point(c.x+cos(a)*r,c.y+sin(a)*r);
    }
};
struct Line{
    //有向直线,左边就是对应的半平面
    Point p,v;
    double ang;
    Line(){}
    Line(Point pp,Point vv){
        p=pp;v=vv;
        ang=atan2(v.y,v.x);
    }
    Point point(double a){
        return p+(v*a);
    }
    bool operator<(const Line& L) const{
        return ang<L.ang;
    }
};
bool OnLeft(Line l,Point pp){
    //点P在有向直线的左边,线上不算
    return Cross(l.v,pp-l.p)>0;
}
Point GetLineIntersection(Line a,Line b){
    //二直线相交,假设交点唯一存在
    Point u=a.p-b.p;
    double t=Cross(b.v,u)/Cross(a.v,b.v);
    return a.p+a.v*t;
}
int getLineCircleIntersection(Line l,Circle cc,double& t1,double& t2,vector<Point>& sol){
    //直线和圆的交点,直线为AB,圆的圆心为C,半径为R,第一种方法是解方程组
    //设交点为P=A+t*(B-A),代入圆方程整理后先得到 (a*t+b)^2+(c*t+d)^2=r^2
    //进一步整理后得到一元二次方程 e*t^2+f*t+g=0
    //根据判别式的值可以区分3种情况,
    //
    //函数返回的是交点个数,参数sol存放的是交点本身
    //没有清空,可以反复调用函数,把所有的交点放在一个sol里
    //---
    //另一种方法是几何法
    //先求C在AB上的投影P,AB的单位向量V
    //交点P-LV,P+LV,由勾股定理算出
    double a=l.v.x;
    double b=l.p.x-cc.c.x;
    double c=l.v.y;
    double d=l.p.y-cc.c.y;
    double e=a*a+c*c;
    double f=2*(a*b+c*d);
    double g=b*b+d*d-cc.r*cc.r;
    double delta=f*f-4*e*g;//判别式
    if(dcmp(delta)<0)return 0;//相离
    if(dcmp(delta)==0){
        t1=t2=-f/(2*e);
        sol.push_back(l.point(t1));
        return 1;//相切
    }
    t1=(-f-sqrt(delta))/(2*e);sol.push_back(l.point(t1));
    t2=(-f+sqrt(delta))/(2*e);sol.push_back(l.point(t2));
    return 2;//相交
}
double angle(Point v){
    //计算向量的极角
    return atan2(v.y,v.x);
}
int getCircleCircleIntersection(Circle c1,Circle c2,vector<Point>& sol){  //计算两圆交点
    double d=Length(c1.c-c2.c);
    if(dcmp(d)==0){
        if(dcmp(c1.r-c2.r)==0)return -1;//两圆重合
        return 0;
    }
    if(dcmp(c1.r+c2.r-d)<0)return 0;
    if(dcmp(fabs(c1.r-c2.r)-d)>0)return 0;
    double a=angle(c2.c-c1.c);//向量C1C2的极角
    double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));//计算C1C2到C1P1的角
    Point p1=c1.point(a-da);Point p2=c1.point(a+da);
    sol.push_back(p1);if(p1==p2)return 1;
    sol.push_back(p2);
    return 2;
}
int getTangents(Point p,Circle c,Point* v){
    //过点p到圆C的切线,v[i]是第i条切线的向量,返回切线条数
    Point u=c.c-p;
    double dist=Length(u);
    if(dist<c.r)return 0;
    else if(dcmp(dist-c.r)==0){
        v[0]=Rotate(u,pi/2);
        return 1;
    }
    else{
        double ang=asin(c.r/dist);
        v[0]=Rotate(u,-ang);v[1]=Rotate(u,ang);
        return 2;
    }
}
int getTangents(Circle a,Circle b,Point* aa,Point* bb){
    //返回切线条数,-1表示无穷条切线,a[i]和b[i]分别表示第i条切线在圆A和圆B上的切点
    int cnt=0;
    if(a.r<b.r)swap(a,b), swap(aa,bb);
    int d2=(int)((a.c.x-b.c.x)*(a.c.x-b.c.x)+(a.c.y-b.c.y)*(a.c.y-b.c.y));
    int rdiff=(int)(a.r-b.r),rsum=(int)(a.r+b.r);
    if(d2<rdiff*rdiff)return 0;//内含
    double base=atan2(b.c.y-a.c.y,b.c.x-a.c.x);
    if(d2==0&&a.r==b.r) return -1;//无穷多条切线
    if(d2==rdiff*rdiff){
        aa[cnt]=a.point(base);
        bb[cnt]=b.point(base);
        cnt++;
        return 1;//内切,1条
    }
    //有外公切线
    double ang=acos((a.r-b.r)/sqrt(d2));
    aa[cnt]=a.point(base+ang);
    bb[cnt]=b.point(base+ang);
    cnt++;
    aa[cnt]=a.point(base-ang);
    bb[cnt]=b.point(base-ang);
    cnt++;
    if(d2==rsum*rsum){
        aa[cnt]=a.point(base);
        bb[cnt]=b.point(base+pi);
        cnt++;//一条内公切线
    }
    else
    if(d2>rsum*rsum){
        double ang=acos((a.r+b.r)/sqrt(d2));
        aa[cnt]=a.point(base+ang);
        bb[cnt]=b.point(pi+base+ang);
        cnt++;
        aa[cnt]=a.point(base-ang);
        bb[cnt]=b.point(pi+base-ang);
        cnt++;//两条内公切线
    }
    return cnt;
}

Circle CircumscribedCircle(Point p1,Point p2,Point p3){
    //三角形外接圆
    double bx=p2.x-p1.x,by=p2.y-p1.y;
    double cx=p3.x-p1.x,cy=p3.y-p1.y;
    double d=2*(bx*cy-cx*by);
    double ccx=(cy*(bx*bx+by*by)-by*(cx*cx+cy*cy))/d+p1.x;
    double ccy=(bx*(cx*cx+cy*cy)-cx*(bx*bx+by*by))/d+p1.y;
    Point p=Point(ccx,ccy);
    return Circle(p,Length(p1-p));
}
Circle InscribedCircle(Point p1,Point p2,Point p3){
    //三角形内切圆
    double a=Length(p2-p3),b=Length(p3-p1);
    double c=Length(p1-p2);
    Point p=(p1*a+p1*b+p3*c)/(a+b+c);
    return Circle(p,DistanceToLine(p,p1,p2));
}
double torad(double deg){
    //角度转弧度
    return deg/180*pi;
}
void get_coord(double r,double lat,double lng,double& x,double& y,double& z){
    //经纬度(角度)转化为空间坐标
    lat=torad(lat);lng=torad(lng);
    x=r*cos(lat)*cos(lng);y=r*cos(lat)*sin(lng);
    z=r*sin(lat);
}
//求球面上两点最短距离,走大圆弧
//半径r,弦长d,圆心角 2arcsin(d/2r)
struct Polygon{
    int n;
    Point p[1000];
    Polygon(){ n=0;}
    Polygon(int nn,Point* pp){
        n=nn;
        for(int q=0;q<n;q++) p[q]=pp[q];
    }
    Point operator[](int a) const{
        return p[a];
    }
};
int isPointInPolygon(Point p,Polygon po){
    //假想有一条向右的射线,统计多边形穿过这条射线正反多少次,把这个数记为绕数
    //逆时穿过加1,顺时针穿过减1
    int wn=0, n=po.n;
    for(int i=0;i<n;i++){
        if(OnSegment(p,po[i],po[(i+1)%n]))return -1;//在边界上
        int k=dcmp(Cross(po[(i+1)%n]-po[i],p-po[i]));
        int d1=dcmp(po[i].y-p.y);
        int d2=dcmp(po[(i+1)%n].y-p.y);
        if(k>0&&d1<=0&&d2>0)wn++;
        if(k<0&&d2<=0&&d1>0)wn--;
    }
    if(wn!=0) return 1;//内部
    return 0;//外部
}
//点在凸多边形内判定更简单,只要判断是否在所有边的左边
//各顶点按逆时针顺序
int ConvexHull(Point* p,int n,Point* ch)
{
    //计算凸包,输入点数组p,个数为n,输出点数组ch,函数返回凸包顶点数
    //输入不能有重复点,函数执行完后输入点的顺序被破坏
    //如果不希望在凸包的边上有输入点,把两个<=改成<
    //在精度要求高时建议用dcmp比较
    sort(p,p+n);
    //n=unique(p,p+n)-p;
    int m=0;
    for(int i=0;i<n;i++){
        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--){
        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    if(n>1)m--;
    return m;
}

double diameter(Point* o,int n,Point *p){
    //求点集直径(最大距离),旋转卡壳
    int num=ConvexHull(o,n,p);
    int mi=0,ma=0;
    for(int q=0;q<num;q++){
        if(p[q]<p[mi])mi=q;
        if(p[ma]<p[q])ma=q;
    }
    int v=ma;
    double ans=(p[mi].x-p[ma].x)*(p[mi].x-p[ma].x)+(p[mi].y-p[ma].y)*(p[mi].y-p[ma].y);
    ans=max(ans,(p[num-1].x-p[ma].x)*(p[num-1].x-p[ma].x)+(p[num-1].y-p[ma].y)*(p[num-1].y-p[ma].y));
    ans=max(ans,(p[mi].x-p[ma-1].x)*(p[mi].x-p[ma-1].x)+(p[mi].y-p[ma-1].y)*(p[mi].y-p[ma-1].y));
    ans=max(ans,(p[num-1].x-p[ma-1].x)*(p[num-1].x-p[ma-1].x)+(p[num-1].y-p[ma-1].y)*(p[num-1].y-p[ma-1].y));
    for(;mi<v;mi++){
        for(;;){
            int a=dcmp(Cross(p[mi+1]-p[mi],p[ma+1]-p[ma]));
            if(a==0){
                ans=max(ans,(p[mi].x-p[ma].x)*(p[mi].x-p[ma].x)+(p[mi].y-p[ma].y)*(p[mi].y-p[ma].y));
                ans=max(ans,(p[mi+1].x-p[ma].x)*(p[mi+1].x-p[ma].x)+(p[mi+1].y-p[ma].y)*(p[mi+1].y-p[ma].y));
                ans=max(ans,(p[mi].x-p[ma+1].x)*(p[mi].x-p[ma+1].x)+(p[mi].y-p[ma+1].y)*(p[mi].y-p[ma+1].y));
                ans=max(ans,(p[mi+1].x-p[ma+1].x)*(p[mi+1].x-p[ma+1].x)+(p[mi+1].y-p[ma+1].y)*(p[mi+1].y-p[ma+1].y));
                ma++;
                break;
            }
            if(a>0){
                ans=max(ans,(p[mi].x-p[ma].x)*(p[mi].x-p[ma].x)+(p[mi].y-p[ma].y)*(p[mi].y-p[ma].y));
                ans=max(ans,(p[mi].x-p[ma+1].x)*(p[mi].x-p[ma+1].x)+(p[mi].y-p[ma+1].y)*(p[mi].y-p[ma+1].y));
                ma++;
            }
            if(a<0){
                ans=max(ans,(p[mi+1].x-p[ma].x)*(p[mi+1].x-p[ma].x)+(p[mi+1].y-p[ma].y)*(p[mi+1].y-p[ma].y));
                ans=max(ans,(p[mi+1].x-p[ma+1].x)*(p[mi+1].x-p[ma+1].x)+(p[mi+1].y-p[ma+1].y)*(p[mi+1].y-p[ma+1].y));
                break;
            }
        }
    }
    return ans;
}
int HalfplaneIntersection(Line* l,int n,Point* poly){
    sort(l,l+n);
    int first,last;
    Point *p=new Point[n];Line *q=new Line[n];
    q[first=last=0]=l[0];
    for(int i=1;i<n;i++){
        while(first<last&&!OnLeft(l[i],p[last-1]))last--;
        while(first<last&&!OnLeft(l[i],p[first]))first++;
        q[++last]=l[i];
        if(fabs(Cross(q[last].v,q[last-1].v))<eps){
            last--;
            if(OnLeft(q[last],l[i].p))q[last]=l[i];
        }
        if(first<last)p[last-1]=GetLineIntersection(q[last-1],q[last]);
    }
    while(first<last&&!OnLeft(q[first],p[last-1]))last--;
    if(last-first<=1)return 0;
    p[last]=GetLineIntersection(q[last],q[first]);
    int m=0;
    for(int i=first;i<=last;i++)poly[m++]=p[i];
    return m;
}
void FindBorder(Point* p,int n){
    //寻找多边形边界
    int num;
    Point ans[10005],z[205];
    double x[205];
    int a,min1=0;
    for(int q=0;q<n;q++)if(p[q]<p[min1])min1=q;
    p[n]=p[0];ans[0]=p[min1];
    double s=-pi;num=1;
    for(int idx=0;;idx++){
        a=0;
        for(int q=0;q<n;q++)
            if(p[q]==ans[num-1]){
                z[a]=p[(q+1)%n];
                x[a]=atan2(-p[q].y+z[a].y,-p[q].x+z[a].x)-s-2*pi;
                for(;dcmp(x[a])<=0;)x[a]+=2*pi;
                a++;z[a]=p[(q+n-1)%n];
                x[a]=atan2(-p[q].y+z[a].y,-p[q].x+z[a].x)-s-2*pi;
                for(;dcmp(x[a])<=0;)x[a]+=2*pi;
                a++;
            }
        for(int q=0;q<n;q++)
            if(OnSegment(ans[num-1],p[q],p[q+1])){
                z[a]=p[(q+1)];
                x[a]=atan2(-ans[num-1].y+z[a].y,-ans[num-1].x+z[a].x)-s-2*pi;
                for(;dcmp(x[a])<=0;)x[a]+=2*pi;
                a++;
                z[a]=p[q];
                x[a]=atan2(-ans[num-1].y+z[a].y,-ans[num-1].x+z[a].x)-s-2*pi;
                for(;dcmp(x[a])<=0;)x[a]+=2*pi;
                a++;
            }
        int mi=0;
        for(int q=0;q<a;q++)if(x[q]<x[mi])mi=q;
        double ma=101000000;
        Point f=z[mi],g;
        for(int q=0;q<n;q++)
            if(SegmentProperIntersection(z[mi],ans[num-1],p[q],p[q+1])){
                g=GetLineIntersection(z[mi],z[mi]-ans[num-1],p[q],p[q]-p[q+1]);
                if(Length(g-ans[num-1])<ma)ma=Length(g-ans[num-1]),f=g;
            }
        ans[num]=f;
        s=atan2(ans[num-1].y-ans[num].y,ans[num-1].x-ans[num].x);num++;
        if(ans[num-1]==ans[0])break;
    }
    printf("%d\n",num-1);
    for(int q=0;q<num-1;q++)
        printf("%.4lf %.4lf\n",ans[q].x,ans[q].y);
}
Polygon cutPolygon(Polygon& po,Point a,Point s){
    //切割多边形,返回直线左边的部分,要正反调用两次
    Point x,c;Polygon ans;
    int sum=0;
    for(int q=0;q<po.n;q++){
        x=po[q];
        c=po[(q+1)%po.n];
        if(OnLeft(Line(a,s-a),x)||OnSegment(x,a,s))ans.p[sum]=x,sum++;
        if(SegmentProperIntersection(x,c,a,s))ans.p[sum]=GetLineIntersection(x,c-x,a,s-a),sum++;
    }
    ans.n=sum;
    return ans;
}
struct Point3{
    double x,y,z;
    Point3(){
        x=0;y=0;z=0;
    }
    Point3(double xx,double yy,double zz){
        x=xx;y=xx;z=zz;
    }
    bool operator==(Point3 p) const{
        return dcmp(x-p.x)==0&&dcmp(y-p.y)==0&&dcmp(z-p.z)==0;
    }
};
Point3 operator+(Point3 a,Point3 b){
    return Point3(a.x+b.x,a.y+b.y,a.z+b.z);
}
Point3 operator-(Point3 a,Point3 b){
    return Point3(a.x-b.x,a.y-b.y,a.z-b.z);
}
Point3 operator*(Point3 a,double p){
    return Point3(a.x*p,a.y*p,a.z*p);
}
Point3 operator/(Point3 a,double p){
    return Point3(a.x/p,a.y/p,a.z/p);
}
double Dot(Point3 a,Point3 b){
    return a.x*b.x+a.y*b.y+a.z*b.y;
}
double Length(Point3 a){
    return sqrt(Dot(a,a));
}
double Angle(Point3 a,Point3 b){
    return acos(Dot(a,b)/Length(a)/Length(b));
}
//平面用点法式表示(p0,n),p0是平面上一个点,n 是平面法向量
double DistanceToPlane(Point3 &p,Point3 &p0,Point3 &n){
    //点p到平面 p0-n 的的距离,n 是单位向量
    return fabs(Dot(p-p0,n));
    //如果不取绝对值,得到的是有向距离
}
Point3 GetPlaneProjection(Point3 &p,Point3 &p0,Point3 &n){
    //点 p 在平面 p0-n 上的投影,n 是单位向量
    return p-n*Dot(p-p0,n);
}
Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Point3 p0,Point3 n){
    //直线 p1-p2 到平面 p0-n 的交点,分母为 0 对应直线和平面平行,直线在平面上
    Point3 v=p2-p1;
    double t=(Dot(n,p0-p1)/Dot(n,p2-p1));//判断分母是否为 0
    return p1+v*t;//如果是线段,判断 t 是不是在 0 和 1 之间
}
Point3 Cross(Point3 a,Point3 b){
    return Point3(a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x);
}
double Area2(Point3 a,Point3 b,Point3 c){
    return Length(Cross(b-a,c-a));
}
bool PointInTri(Point3 p,Point3 p0,Point3 p1,Point3 p2){
    //判断点在三角形内,先判断是否在三角形所在的平面,再用面积关系
    double area1=Area2(p,p0,p1);
    double area2=Area2(p,p2,p1);
    double area3=Area2(p,p0,p2);
    return dcmp(area1+area2+area3-Area2(p0,p1,p2))==0;
}
bool TriSegIntersection(Point3 p0,Point3 p1,Point3 p2,Point3 a,Point3 b,Point3 &p){
    //判断线段和三角形是否相交,没有考虑线段在平面上的情况
    Point3 n=Cross(p1-p0,p2-p0);
    if(dcmp(Dot(n,b-a))==0)return false;
    else{
        double t=Dot(n,p0-a)/Dot(n,b-a);
        if(dcmp(t)<0||dcmp(t-1)>0)return false;
        p=a+(b-a)*t;//计算交点
        return PointInTri(p,p0,p1,p2);//判断交点在三角形内
    }
}
double DistanceToLine(Point3 p,Point3 a,Point3 b){
    //点 p 到直线 ab 距离
    Point3 v1=b-a,v2=p-a;
    return Length(Cross(v1,v2))/Length(v1);
}
double DistanceToSegment(Point3 p,Point3 a,Point3 b){
    //点 p 到线段 ab 距离
    if(a==b)return Length(p-a);
    Point3 v1=b-a,v2=p-a,v3=p-b;
    if(dcmp(Dot(v1,v2))<0) return Length(v2);
    else if(dcmp(Dot(v1,v3))>0) return Length(v3);
    else return Length(Cross(v1,v2))/Length(v1);
}
double Volume6(Point3 a,Point3 b,Point3 c,Point3 d){
    return Dot(d-a,Cross(b-a,c-a));
}
double TriCir(Point a,Point s,Point d,Circle c,vector<Point> v){
    //三角形与圆面积交
    //其中圆心是 a ,三角形 abc
    double x1=Length(s-a),x2=Length(d-a);
    double vv,bb;
    if(dcmp(x1-c.r)<=0&&dcmp(x2-c.r)<=0)return Area2(a,s,d)/2;
    if(dcmp(x1-c.r)>0&&dcmp(x2-c.r)>0){
        if(DistanceToLine(c.c,s,d)>=c.r)return Angle(d-a,s-a)*c.r*c.r/2;
        else{
            v.clear();
            getLineCircleIntersection(Line(s,d-s),c,vv,bb,v);vv=Angle(v[0]-a,v[1]-a);
            return min(Angle(v[0]-a,d-a)+Angle(v[1]-a,s-a),Angle(v[1]-a,d-a)+Angle(v[0]-a,s-a))/2*c.r*c.r+sin(Angle(v[0]-a,v[1]-a))/2*c.r*c.r;
        }
    }
    if(dcmp(x1-c.r)>0&&dcmp(x2-c.r)<=0){
        v.clear();
        getLineCircleIntersection(Line(s,d-s),c,vv,bb,v);
        if(OnSegment(v[1],s,d)){
            v[0]=v[1];printf("$$");
        }
       return Area2(a,d,v[0])/2+Angle(v[0]-a,s-a)*c.r*c.r/2;
    }
    if(dcmp(x1-c.r)<=0&&dcmp(x2-c.r)>0){
        v.clear();
        getLineCircleIntersection(Line(s,d-s),c,vv,bb,v);
        if(OnSegment(v[1],s,d))v[0]=v[1];
        return Area2(a,s,v[0])/2+Angle(v[0]-a,d-a)*c.r*c.r/2;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值