计算点、线、面等元素之间的交点、交线、封闭区域面积和闭合集(续5)

 

单调链的说明: 对于折线L = {p1p2p3pn}xipi的横坐标,若xi<=xi+1,或xi>=xi+1,则称折线为关于x轴的单调增(或减)链。同样,对于y轴也适用。
    
     

平面上多条线段求交问题。
     对于平面上的
N条线段,若使用最直接的方法,即两两求其交点,则(N-1) + (N-2)+1 = N(N-1)/2次运算,时间复杂度是O(n2)。这种方法对交点个数接近N(N-1)/2的情况可行,但大多数情况下,N条线段形成的交点个数是较少的,此时算法可调整成与输入线段个数和输出的交点个数相关的效率更高的方法,如Bentley-Ottmann 算法。


      算法的思路是,以
X轴升序构造顶点队列和初始化扫描线链表后,对顶点队列中所有元素开始循环:
      当取出的元素为线段的左端点时,首先将此条线段插入到扫描线段链表中,同时以
Y轴的升序重排链表中所有元素,然后分别计算此条线段与扫描线段链表中上下相邻线段的相交情况,若有交点,则将交点插入到顶点队列中。

当取出的元素为线段的右端点时,首先将此条线段从扫描线段链表中删除,然后计算此时与此条线段上下相邻的那两条线段之间的相交情况,如果有交点,但在顶点队列中还不存在,则将其插入顶点队列。

当取出的元素为交点时,首先将这个交点增加到最后要输出的结果集合中。然后得到这个交点从属的两条线段,交换它们在扫描线链表中的位置后,分别与新邻接的线段求交点,如果有交点,但在顶点队列中还不存在,则将其插入顶点队列。

以上3种情况分别处理后,从顶点队列中移走这个取出的元素。

当循环处理完毕,结果集合中的元素即为所有的交点。

这种方法最后以一次循环取代了最直接的两两线段求交点的两次循环。不过,需要注意的是,当交点个数接近n2级别时,Bentley-Ottmann算法的效率比直接两两求其交点的方法低下。

参考代码:

int intersect_Polygon( Polygon Pn )

{

    EventQueue Eq(Pn);              //顶点队列

    SweepLine   SL(Pn);              //扫描线链表

    Point       e;                 // 当前的顶点

    SLseg*      s;                 // 当前的线段

    Point       singlepoint;     //准备求得的交点

    PointList   PL;                  //所有求得的交点保存在其中

    while (Eq != EMPTY)              //循环开始,直到队列为空

    {      

        e = Eq->next();              //得到开头顶点元素

        if (e->type == LEFT) {     // 当为线段的开始顶点

            s = SL.add(e);         // 增加此顶点所属的线段到扫描线链表中

            if (SL.intersect( s, s->above, singlepoint))      //判断此顶点所属的线段与处于其上的线段是否相交

            {

                 Eq->insert(singlepoint);      // 插入交点到顶点队列中

                 SL.record(s, s->above, singlepoint);//在扫描线链表中记录此交点的上下线段

            }

            if (SL.intersect( s, s->below, singlepoint))

                 Eq->insert(singlepoint);      // 插入交点到顶点队列中

        }

        else if(e->type == RIGHT)    //当为线段的结束顶点

        {                    

            s = SL.find(e);          // 从扫描线链表中找到此顶点所属的线段

            if (SL.intersect( s->above, s->below,singlepoint))        //判断此线段的上下两相邻线段是否相交

                 if(Eq->find(singlepoint) == false)   //如果求得的交点还不存在于顶点队列中

                    Eq->insert(singlepoint)      //插入这个新求的交点到顶点队列中

                

            SL.remove(s);          // 从扫描线链表中移走此顶点所属的线段

        }

        else                         //当为交点

        {

            PL.add(e);               //保存结果到最后的输出集合中

            SLseg*      sE1 = SL.findrecord(e,ABOVE);//得到此交点在扫描线链表中的第一条线段

            SLseg*      sE2 = SL.findrecord(e,BELOW);//得到此交点在扫描线链表中的第二条线段

            SL.swap(sE1,sE2);    //交换两条线段在链表中的位置,从几何上可看作:通过顶点后,两条线段的上下位置关系交换

            if (SL.intersect( sE2, sE2->above,singlepoint))       //判断新的上下两相邻线段是否相交

                 if(Eq->find(singlepoint) == false)                    //如果求得的交点还不存在于顶点队列中

                     Eq->insert(singlepoint)                           //插入这个新求的交点到顶点队列中

            if (SL.intersect( sE1, sE1->below,singlepoint))           //判断新的上下两相邻线段是否相交

                 if(Eq->find(singlepoint) == false)                    //如果求得的交点还不存在于顶点队列中

                     Eq->insert(singlepoint)                           //插入这个新求的交点到顶点队列中

        }

        Eq->remove(e);               //此元素处理完毕,将其弹出

    }

    return 1;    

}

转载于:https://www.cnblogs.com/wuhanhoutao/archive/2008/03/17/1109980.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算几何算法(含源代码) ㈠ 的基本运算 1. 平面上两之间距离 1 2. 判断两是否重合 1 3. 矢量叉乘 1 4. 矢量乘 2 5. 判断是否在线段上 2 6. 求一饶某旋转后的坐标 2 7. 求矢量夹角 2 ㈡ 线段及直线的基本运算 1. 线段的关系 3 2. 求线段所在直线线的垂足 4 3. 线段的最近 4 4. 线段所在直线的距离 4 5. 到折线集的最近距离 4 6. 判断圆是否在多边形内 5 7. 求矢量夹角余弦 5 8. 求线之间的夹角 5 9. 判断线段是否相交 6 10.判断线段是否相交但不交在端处 6 11.求线段所在直线的方程 6 12.求直线的斜率 7 13.求直线的倾斜角 7 14.求关于某直线的对称 7 15.判断两条直线是否相交及求直线交点 7 16.判断线段是否相交,如果相交返回交点 7 ㈢ 多边形常用算法模块 1. 判断多边形是否简单多边形 8 2. 检查多边形顶的凸凹性 9 3. 判断多边形是否凸多边形 9 4. 求多边形面积 9 5. 判断多边形顶的排列方向,方法一 10 6. 判断多边形顶的排列方向,方法二 10 7. 射线法判断是否在多边形内 10 8. 判断是否在凸多边形内 11 9. 寻找集的graham算法 12 10.寻找集凸包的卷包裹法 13 11.判断线段是否在多边形内 14 12.求简单多边形的重心 15 13.求凸多边形的重心 17 14.求肯定在给定多边形内的一个 17 15.求从多边形外一出发到该多边形的切线 18 16.判断多边形的核是否存在 19 ㈣ 圆的基本运算 1 .是否在圆内 20 2 .求不共线的三所确定的圆 21 ㈤ 矩形的基本运算 1.已知矩形三坐标,求第4坐标 22 ㈥ 常用算法的描述 22 ㈦ 补充 1.两圆关系: 24 2.判断圆是否在矩形内: 24 3.到平面的距离: 25 4.是否在直线同侧: 25 5.镜面反射线: 25 6.矩形包含: 26 7.两圆交点: 27 8.两圆公共面积: 28 9. 圆和直线关系: 29 10. 内切圆: 30 11. 求切: 31 12. 线段的左右旋: 31 13.公式: 32
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值