平面几何 学习笔记
定义
struct pt{
db x,y;
pt(db _x=0.0,db _y=0.0){x=_x; y=_y;}
}p[M],s[M]; int tot;//p为点集,s为栈
struct line{
pt P,v;
line(pt pp=pt(),pt vv=pt()){P=pp; v=vv;}
};
bool eq(db x,db y){return fabs(x-y)<=eps;}
bool neq(db x,db y){return !eq(x,y);}
bool le(db x,db y){return eq(x,y)||x<y;}
bool ge(db x,db y){return eq(x,y)||x>y;}
bool operator <(pt x,pt y){return (x.y!=y.y)?(x.y<y.y):(x.x<y.x);}//这里最好不要写精度特判了,会很奇怪,到时看情况吧
bool operator ==(pt x,pt y){return eq(x.x,y.x)&&eq(x.y,y.y);};
pt operator -(pt x,pt y){return pt(x.x-y.x,x.y-y.y);}
pt operator +(pt x,pt y){return pt(x.x+y.x,x.y+y.y);}
pt operator *(pt x,db d){return pt(x.x*d,x.y*d);}
pt operator /(pt x,db d){return pt(x.x/d,x.y/d);}
基本函数
db dot(pt x,pt y){//点积
return x.x*y.x+x.y*y.y;
}
db cross(pt x,pt y){//叉积
return x.x*y.y-x.y*y.x;
}
db length(pt x){//向量长度
return sqrt(dot(x,x));
}
db area(pt x,pt y,pt z){// >0 y在下, <0 y在上
return cross(y-x,z-x);//算面积的话 逆时针给出 x,y,z
}
db shadow(pt x,pt y,pt to){//x-y向量在x-to向量上的投影
return dot(y-x,to-x)/length(to-x);
}
pt lf_90(pt x){//向量左转90度
return pt(-x.y,x.x);
}
pt rt_90(pt x){//向量右转90度
return pt(x.y,-x.x);
}
bool cmp(pt x,pt y){//逆时针极角排序
db tp=area(p[1],x,y);
if(eq(tp,0)) return length(x-p[1])<length(y-p[1]);//length别忘了减p[1]
return tp>0;
}
判断点是否在多边形内(多边形可凹)
判断的时候点向右射一条射线
判断多边形边向上穿过射线几次,向下穿过几次
上加一次,下加一次
若最后值为0,在多边形外
否则在内
特别的,穿过端点会有bug,我们把每条边y值较大的点看成空心的就好了
代码现没有,看书
直线/线段/射线
可以统计成线上一点 P 和方向向量 v的组合
写成P+tv,用 t 的取值范围确定直线/线段
pt intersection(Line x,Line y){//两线交点
// if(cross(x.v,y.v)==0) 不相交;
pt u=x.p-y.p;
db t=cross(y.v,u)/cross(x.v,y.v);//用x上表达式算时用 cross(y.v,u)
return x.p + t*x.v;
}
点到直线距离:叉积除以长度
点到线段距离:判断线段内外,内:垂线距离,外:到最近端点的距离
点在线段上判断:线段x-y,叉积=0在线上,x->p和y->p内积<0在在线段上(反向向量内积小于0)
求凸包
整个凸包,极角排序+graham
上下凸包,x值排序,按斜率优化那样就好,同样可以写叉积