平面几何 学习笔记

定义

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值