如何对旋转矩形点进行排序?

时间:2013-04-02 10:57:16

标签: algorithm

enter image description here

旋转矩形的度数小于90。 它可以是时钟方式或逆时针方式。我喜欢将这些点排序为矩形的原始序列。 像文本注释一样,1,2,3,4 ......

我的算法是: 1.找到左,右,上,下最多的点, 2.比较top.x和bottom.x 3.根据比较值,可以找到四角序列。 4.从四个角点,计算矩形边缘的线函数,然后排列其他点。

我不确定是否还有另一种更有效或更优雅的算法来解决这个问题。 谢谢。

1 个答案:

答案 0 :(得分:1)

假设矩形已顺时针旋转了小于90度的量。在这种情况下,请注意顶行中的第(i + 1)个点始终位于第i个点的下方和右侧。所以我们可以剥离行:

  1. 按y坐标(即从上到下)按递减顺序对所有点进行排序。
  2. 将这些已排序的点放在链接列表中。 (这不是必需的,但可以提高点移除效率。)
  3. 设置i = 1。
  4. 设置lastX = -inf。
  5. 将p设置为指向已排序的点列表中的第一个元素。如果没有剩余元素,我们就完成了。
  6. 从p开始,扫描点列表,直到找到x co-ord大于lastX的点,表示它位于前一点的右侧。 (在每一行的第一次迭代中,这将始终采用列表中的第一个点。)
  7. 如果可以找到这样的观点:

    • 从链接列表中删除此点并将其标记为i。
    • 将p设置为列表中的下一个点。
    • 设置i = i + 1。
    • 将lastX设置为刚刚添加的点的x坐标。
    • 转到6以找到此行中的下一个点。

    否则:

    • 我们已完成此行,其中的所有点都已从链接列表中删除。转到4开始下一行。
  8. 这是一个O(n ^ 2)算法,因为一旦找到了行中最右边的点,它就会浪费地遍历所有剩余的点,然后从顶部开始处理下一行。这可能已经足够了,但是时间复杂度可以减少到O(nlog n),方法是维护一个单独的链表,其中包含从左到右排序的所有点,并在每个节点中提供一个额外的字段。从上到下列表,指向从左到右列表中的相应节点。由于顶行中最右边的点始终是整个点集中最右边的点,因此我们可以通过测试刚删除的点是否与整个点中的最后一点相对应来检测行何时在O(1)时间内完成从左到右的清单。每当从顶部到底部列表中删除一个点时,它也必须从左到右列表中删除。

    但是如果矩形是逆时针旋转的呢?作为评论者n.m.指出,没有进一步的信息,没有办法将这种情况与顺时针旋转区分开来:逆时针旋转d度的n×m矩形看起来就像是顺时针旋转了(90-d)度的m×n矩形。如果您有其他信息可以区分这些情况,那么可以使用与之前相同的算法处理逆时针旋转,但要注意第一行(或任何行)的宽度,然后重新排列标签。