计算几何进阶及模板

半平面交

一条直线将平面分为两个半平面

直线是有向的,不妨规定每条直线取沿直线方向的左边作为半平面

n条直线左边的半平面的交就是半平面交

半平面交的结果是一个凸多边形,由顶点表示,当然特殊情况的话可能无界,为一个点、线段、空等

形象的比喻:相当于一块蛋糕你不断的用刀切,舍弃刀右边的部分,最后剩下的一块就是半平面交的结果

多边形的核

凸多边形的核就是本身,其他多边形的核是所有边的半平面交的结果

如何算半平面交

首先先引入有向直线的定义

struct Line
{
    Point p;
    Vector v;
    double ang;
    Line (){}
    Line (Point p,Vector v):p(p),v(v) { ang=atan2(v.y,v.x); }
    bool operator < (const Line &L) const {
		return ang<L.ang;
	} 
}; // 由一个点和一个方向向量组成 

这里提供两个算法:

O(N^2)的算法

大概思路

枚举多边形的每一条边(不妨设他为AB),算出这条直线切割后的多边形,然后继续用下一条边切割这个剩下的多边形,最后切割完成的多边形就是核

那么如何算出每条直线切割之后的多边形呢?

1.点在直线的左边 -> 添加进多边形

2.如果两条直线AB和CD有交点,且这个交点在线段CD上,那么把交点加入到多边形中

代码如下

polygon CutPolygon(polygon poly2, Point A,Point B)//用有向直线去切割多边形
{
    polygon newpoly;
    int m = 0,n = poly2.sz;
    for(int i = 0; i < n; i++)
    {
        Point C = poly2.a[i], D = poly2.a[(i+1)%n];//切割如下图
        if(dcmp(Cross(B-A, C-A)) >= 0) newpoly.a[m++] = C;  
        if(dcmp(Cross(B-A, C-D)) != 0) {
            Point ip = GetIntersection(A, B-A, C, D-C);
            if(OnSegment(ip, C, D)) newpoly.a[m++] = ip;//判断ip是不是在线段CD上
        } 
    }
    newpoly.sz = m;
    return newpoly;
}

double Get_Kernel(polygon poly)
{
    polygon knl;
    knl.a[0] = Point(-INF,-INF); knl.a[1] = Point(INF,-INF); 
	knl.a[2] = Point(INF,INF); knl.a[3] = Point(-INF,INF);
    knl.sz = 4;  //初始大平面
    for(int i = 0; i < poly.sz; i++)  //不停地用多边形的边去切割平面
    {
        Point A = poly.a[i], B = poly.a[(i+1)%poly.sz];
        knl = CutPolygon(knl,A,B);
     }
    double ans = 0;//求核的面积,可以自己修改
 
    for(int i = 0; i < knl.sz; i++)
        ans += area(knl.a[i], knl.a[(i+1)%knl.sz]);
    return ans;
}

O(NlogN)的算法

占坑 明天补

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值