平面扫描算法:如何在交点之后对段进行排序

时间:2016-10-14 07:09:27

标签: c++ algorithm computational-geometry

我试图在C ++代码中实现基于本书的段交叉的平面扫描算法:http://www.cs.uu.nl/geobook/。他们建议使用平衡二叉搜索树来实现平面扫描的状态结构。

我使用std :: set结构来实现状态结构,但我在重新排序包含点" p"的段时遇到问题。并且他们的上端点是" p"。它们具有相同的坐标点,这意味着我无法在std :: set中插入它们,因为它不允许重复值...我试图用它们的下端点插入它们但是,它们将失去顺序它们在#34; p"。

之下的扫描线相交

书中的伪代码说明如下:

  
      
  1. 将U(p)∪C(p)中的片段插入Tao。 Tao中段的顺序应该与它们相交的顺序相对应   p下方的扫描线。如果存在水平线段,则会出现   包含p。
  2. 的所有细分中的最后一个   
  3. (*删除并重新插入C(p)的段会颠倒它们的顺序。*)
  4.   

我不知道他们将如何改变他们的顺序。当我在状态结构中插入片段时,我按照他们的x上端点坐标对它们进行排序。我不知道如何在十字路口之后交换订单。

有什么想法吗?

更新:这本书在这里:https://books.google.com/books?id=C8zaAWuOIOcC但有一些页面不会出现。它在第2章,第24,25和26页。希望它有助于提供一些背景

最佳,

3 个答案:

答案 0 :(得分:2)

使用std::set时,假设您使用std::set的拟合比较器,常见y值上的两个或多个项目的外观应该不成问题。我建议,除了y值,比较和按斜率排序。 (std::set的比较器示例

我建议不要使用std :: set,而是使用std :: vector。使用std :: vector可以交换(std :: swap)对某些线段的引用,如果线段开始/结束,也可以在O(log n)时插入/删除,其中n是线段的数量。我们的想法是,您可以通过交换与交叉点对应的线段,在整个线扫描中保持正确的状态顺序,只有事件队列是优先级队列。 (由于@Sneftel的评论而删除,感谢您的见解。)

关于扫描线算法的一般方法: 状态(sweep line status)确实表示线扫描中特定(当前)时间线段的顺序。对于扫描线状态,根据我的理解,应该使用平衡二叉树(如@Sneftel所述)。然后,通过交换对应于交叉点的线段,您可以在整个线扫描中保持正确的状态顺序,只有event queue必须是某种优先级队列。

答案 1 :(得分:-2)

编写比较函数,因此主要排序在y上,次要在x上。然后,只要x不同,就可以插入具有重复y值的段。 (如果你有两个相同的部分,你需要专门为交叉口测试处理)。

答案 2 :(得分:-2)

用作平面扫描状态数据结构的std::set的排序谓词必须如下工作:

  1. 必须(动态)计算给定段与扫描线当前位置的扫描线的交点坐标。

  2. 如果是平局(当两个线段看起来与同一坐标处的扫描线相交时),它还必须比较两个线段的角度 - 这将允许找出线段中的线段的顺序。扫描线未来位置的状态。

  3. 请注意,上面的要求1.意味着谓词对象必须保持对扫描线位置变量的引用,以便它可以在扫描线前进时正确地比较段。扫描线位置无法存储在谓词本身中,因为您将无法从算法中更新它(std::set不通过引用提供对其谓词的访问权限。)

    修改

    请注意,维护集合中段的正确顺序(即根据需要交换它们)的责任仍然在于算法 - 具有此类谓词的std::set不会自动重新排序其元素。