【问题标题】:Calculating a boundary around several linked rectangles计算几个链接矩形周围的边界
【发布时间】:2010-09-22 07:58:01
【问题描述】:

我正在做一个项目,我需要在一组矩形周围创建一个边界。

让我们以这张图片为例来说明我想要完成的事情。

编辑:无法使图像标签正常工作,因此这是完整链接: http://www.flickr.com/photos/21093416@N04/3029621742/

我们有矩形 A 和 C,它们通过一个特殊的链接矩形 B 链接。您可以将其视为图中的两个节点 (A,C) 和它们之间的边 (B)。这意味着矩形以下列方式具有彼此的指针:A->B, AC, C->B

每个矩形都有四个顶点存储在一个数组中,其中索引 0 位于左下角,索引 3 位于右下角。

我想“遍历”这个链接结构并计算构成它周围边界(红线)的顶点。关于如何实现这一点,我已经有了一些小想法,但想知道你们中的一些更倾向于数学的人是否有一些巧妙的技巧。

我在这里发布这个的原因只是有人可能以前解决过类似的问题,并且有一些我可以使用的想法。我不希望任何人坐下来仔细思考这个问题。在等待答案的同时,我将并行研究解决方案。

非常感谢任何输入。

【问题讨论】:

  • 线条总是垂直还是水平?可以重叠吗?
  • 是的,可能有重叠,这必须是它自己的情况。目前,线条将始终是水平和垂直的。

标签: c++ graphics geometry


【解决方案1】:

使用示例,其中矩形相互垂直,因此可以由四个值(两个 x 坐标和两个 y 坐标)表示:

 1 2 3 4 5 6

1 +---+---+
   | |
2 + A +---+---+
   | |乙|
3 + + +---+---+
   | | | | |
4 +---+---+---+---+ +
               | |
5 + C +
               | |
6 +---+---+

1)将所有x坐标(左右)收集到一个列表中,然后对其进行排序并删除重复项

1 3 4 5 6

2) 将所有 y 坐标(包括顶部和底部)收集到一个列表中,然后对其进行排序并删除重复项

1 2 3 4 6

3) 通过唯一 x 坐标之间的间隙数 * 唯一 y 坐标之间的间隙数创建一个二维数组。每个单元只需要一位,因此在 c++ 中,vector 可能会为您提供一个非常节省内存的版本

4 * 4

4) 将所有矩形绘制到此网格中

1 3 4 5 6 1 +---+ | 1 | 0 0 0 2 +---+---+---+ | 1 | 1 | 1 | 0 3 +---+---+---+---+ | 1 | 1 | 1 | 1 | 4 +---+---+---+---+ 0 0 | 1 | 1 | 6 +---+---+

5) 对于网格中的每个单元格,对于每个边缘,如果在该基本方向上它旁边的单元格没有被绘制,则为该边缘绘制边界线


在问题中,矩形被描述为四个向量,每个向量代表一个角。如果每个矩形都可以与其他矩形进行任意且不同的旋转,那么我上面概述的方法将行不通。寻找复杂多边形周围路径的问题通常由矢量图形光栅器解决,解决问题的一个好方法是使用像 Cairo 这样的库来为您完成这项工作!

【讨论】:

【解决方案2】:

这个问题的通用解决方案是根据扫描线实现布尔运算。您可以找到一个简短的讨论 here 来帮助您入门。来自文字:

“布尔算法的基础是扫描线。对于基本原理,本书:Computational Geometry an Introduction Franco P. Preparata 和 Michael Ian Shamos 非常好。”

我拥有这本书,虽然它现在在办公室,所以我无法查找您应该阅读的页码,尽管第 8 章关于矩形的几何形状可能是最好的起点。

【讨论】:

    【解决方案3】:
    1. 分别计算所有 3 个矩形的边界之和
    2. 计算 A 和 B 的重叠矩形,并从总和中减去它
    3. 对 B 和 C 的重叠矩形执行相同操作

    (从 A 和 B 获取重叠矩形,取中间 2 个 X 位置,以及中间 2 个 Y 位置)

    示例 (x1,y1) - (x2,y2):

    • 矩形 A:(1,1) - (3,4)
    • 矩形 B:(3,2) - (5,4)
    • 矩形 C:(4,3) - (6,6)

    计算:

    1. 10 + 8 + 10 = 28
    2. X 坐标排序 = 1,3,3,5 中间两个是 3 和 3
      Y 坐标排序 = 1,2,4,4 中间两个是 2 和 4
      所以:(3,2) - (3,4) : 边界 = 4
    3. X 坐标排序 = 3,4,5,6 中间两个是 4 和 5
      Y 坐标排序 = 2,3,4,6 中间两个是 3 和 4
      所以:(4,3) - (5,4) : boundery = 4
    4. 28 - 4 - 4 = 20

    这是我的可视化示例:

       1   2   3   4   5   6
    
    1  +---+---+
       |       |   
    2  +   A   +---+---+
       |       | B     |
    3  +       +   +---+---+
       |       |   |   |   |
    4  +---+---+---+---+   +
                   |       | 
    5              +   C   +
                   |       |
    6              +---+---+
    

    【讨论】:

    • 我不确定你想用你的算法实现什么。它将如何帮助我在矩形周围创建边界多边形?在您的示例中,这将包含以下几点:(1,1),(3,1),(3,2),(5,2),(5,3),(6,3),(6, 6),(4,6),(4,4),(1,4)
    • 如果我数一下,它是 20,正如我计算的那样。如果你有不同的例子,请告诉我。我将解释如何计算那个。
    【解决方案4】:

    一个简单的技巧应该是:

    1. 从第一个矩形创建一个区域
    2. 将其他矩形添加到区域中
    3. 获取区域的边界(不知何故?:P)

    【讨论】:

    • 我投票支持这个,因为我认为你走在正确的轨道上。
    【解决方案5】:

    经过一番思考,我最终可能会做这样的事情:

    伪代码:

     LinkRectsConnectedTo(Rectangle rectangle,Edge startEdge) // Edge can be West,North,East,South 
        for each edge in rectangle starting with the edge facing last rectangle
           add vertices in the edge to the final boundary polygon
           if edge is connected to another rectangle
              if edge not equals startEdge
                 recursively call LinkRectsConnectedTo(rectangle,startEdge)
    

    显然,这个伪代码需要稍微改进一下,可能无法涵盖所有​​情况,但我想我可能已经解决了我自己的问题。

    【讨论】:

    • 嗯,经过进一步思考,必须采取一些步骤来处理内部循环和重叠。这件事正在失控。
    【解决方案6】:

    我还没有完全想到这一点,但我想知道你是否不能这样做:

    • 列出所有边。
    • 获取所有 P1.X = P2.X 的边
    • 在该列表中,获取 X 相等的对
    • 对于每一对,用一条或两条边替换它们不重叠的部分
    • 做一些聪明的事情来让边缘按正确的顺序排列

    你的矩形是否总是水平对齐的,如果不是,你需要做同样的事情,但 Y 也一样? 并且他们总是保证是感动的吗?如果不是,算法不会被破坏,但“正确的顺序”将无法定义。

    【讨论】:

    • 矩形总是相互接触的,所有的线都是水平的或垂直的。
    猜你喜欢
    • 2011-03-06
    • 1970-01-01
    • 2011-10-30
    • 2020-08-04
    • 2015-02-13
    • 1970-01-01
    • 2021-11-11
    • 2018-01-17
    • 2021-11-07
    相关资源
    最近更新 更多