平面几何 学习笔记

定义

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值排序,按斜率优化那样就好,同样可以写叉积

原文地址:https://www.cnblogs.com/acha/p/6431769.html