繁体   English   中英

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

[英]Plane sweep algorithm: How to order the segments after intersection point

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

我正在使用 std::set 结构来实现状态结构,但是我在重新排序包含点“p”并且它们的上端点是点“p”的段时遇到问题。 它们具有相同的坐标点,这意味着我不能将它们插入 std::set 中,因为它不允许重复值......我试图用它们的下端点插入它们,但是,它们将失去顺序它们与“p”正下方的扫掠线相交。

书中的伪代码如下:

  1. 将 U(p) ∪C(p) 中的线段插入到 Tao 中。 Tao 中各段的顺序应对应于它们与 p 正下方的扫描线相交的顺序。 如果有一个水平段,它在所有包含 p 的段中排在最后。
  2. (∗ 删除并重新插入 C(p) 的片段会颠倒它们的顺序。∗)

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

任何的想法?

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

最好的事物,

使用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必须是某种优先级队列。

编写比较函数,使主要排序在 y 上,次要排序在 x 上。 然后您可以插入具有重复 y 值的段,只要 x 不同。 (如果您有两个相同的段,则无论如何都需要专门处理相交测试)。

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

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

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

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

编辑

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM