从给定顶点查找非自相交多边形的边

时间:2014-11-19 07:39:50

标签: r algorithm geometry polygon computational-geometry

我在2-D中有一个非自相交多边形的顶点,其中x坐标是居中经度,y坐标是居中纬度。我想找到多边形的边缘。

我可以绘制顶点并查看哪些顶点相邻并查看边缘。但我的问题是如何才能获得这些优势。

例如,我正在考虑样本数据:

> data1
    vertices       lon      lat
       5         1.133179 1.027886
       4         1.094459 1.013952
       2         1.055672 1.000000
       1         1.000000 1.028578
       3         1.038712 1.042541
       6         1.116241 1.070438

点的样本图是

enter image description here

我希望有一个像这样的数组

>edges 
      ind1 ind2
[1,]    5    6
[2,]    1    3
[3,]    3    6
[4,]    1    2
[5,]    2    4
[6,]    4    5

我对这种多边形的形状感兴趣(最小面积enter image description here

我使用R-package ashape的函数alphahull得到了这个数组。但是在这个函数中,Euclidean距离用于找到点之间的距离,这在我的情况下不适用(因为我正在考虑(lon,lat)上的数据,我们可以在包distHaversine中使用geosphere距离函数})。如果多边形具有大量顶点并且具有复杂形状,则该函数给出不令人满意的结果。该多边形可以是凸的,也可以不是凸的。

现在我想要的是建立一个算法来找到非交叉多边形的边缘,其中最小面积

我们将非常感谢在此方向提供任何帮助。

2 个答案:

答案 0 :(得分:1)

查找所有可能多边形的算法:

  • 生成凸包。 请注意,任何非交叉多边形必须按顺序遍历其凸包。
  • 从凸包上的任何一点开始 生成从该点到每个内部点以及凸包上的下一个相邻点的路径列表
  • 递归地将每条路径延伸到每个剩余内部点以及凸包上的第一个自由点
  • 对于添加到路径的每个段,如果它自相交,则拒绝该路径

我不打算发布代码,但这里有67个可能的多边形,随机一组8个点。 可以想象,结果集随着点数迅速爆发(例如,n = 12 - > ~10000多边形......)

enter image description here

这里是具有最小和最大周长的多边形。

enter image description here

答案 1 :(得分:0)

  1. 将积分从lon,lat转换为笛卡儿x,yx,y,z

    • 使用球形或椭圆形表面
    • 如果尺寸足够小,您可以将(x,y,z)投影到局部曲面以避免3D计算
    • 你也可以使用lon,lat作为x,y,但要确保没有零交叉(如果然后将该轴偏移某个值,直到它没有)
  2. 现在有很多可能的策略

    • 您没有提供任何形状规则
    • 所以我假设'最小'周长/尺寸/面积和通用凹面多边形
    • 在知道内部和外面的位置
    • 之前,你不能直接进入边缘线
    • 我会按照以下方式执行此任务:find polygon基于2D点集中的find holes
  3. 修改1

    • 因为你已经拥有了所有的优势(至少这是我的印象)
    • 所以你可以从上面的算法
    • 为每个点制作旗帜
    • 将告诉您多边形内部或外部的位置
    • 例如取8个方向(N,NE,E,...)并编码哪条路被填充,哪条路空
    • 然后在每个边缘开始在空方向中间
    • 找到2条最接近它的线(以角度表示),它们与任何前一行不相交
    • 如果更多可用则使用最小的
    • direction flag
    • 灰色表示内部多边形
    • 列出所有这些可能的行(每点2个)
    • 然后搜索连接的循环
    • 要注意这个修改不是100%容易出错(我不认为那是凹多边形),
  4. 修改2

    • 使用bullet 2中的完整多边形
    • 并尝试将其边缘点与输入边缘点匹配
    • 然后使用原始多边形中的边线,但使用新点
    • 如果跳过某些点,则找到距离它最近的边线并将其除以此点
    • 这应该比子弹3更安全和准确。
  5. 简单的方法

    • 如果上面的内容太多了,那么

      1. 创建所有可能行的列表
      2. 按大小升序排序
      3. 删除所有与'short'行相交的'long'行
        • 什么是短期或长期取决于你
        • 例如,前三行可以是短行,最后三行是长行
        • 或制作平均尺码,< 0.6*avg_size> 1.2*avg_size ......
        • 或者如果你有N个点,那么前2N行很短,其余的很长(每点2行)
        • 全部测试并为您选择最佳选项...
      4. 尝试找到连接线
        • 仅查找连接一次的行(每个点不超过2行)
        • 将他们从列表中删除到最终解决方案列表
        • 在此之后,您将获得可能的行列表和找到的行列表
      5. 从与找到的行中的任何行相交的可能行中删除所有行
        • 这应删除任何不相关的行
      6. 尝试再次找到连接
        • 如果找到连接,请将第一条可能的行移至解决方案列表
        • 并转到子弹5。
        • 如果没有找到继续下一行......
        • 如果没有留下任何一行或找不到任何连接就停止。