【问题标题】:Finding good starting points for Douglas-Peucker algorithm for closed polygons为封闭多边形寻找道格拉斯-普克算法的良好起点
【发布时间】:2012-01-16 08:20:48
【问题描述】:

我正在尝试使用 Douglas-Peucker 算法减少多边形的顶点 - 这对于线条和路径非常有效。

我的问题是我要优化的多边形是封闭的。选择2个随机相邻点时,优化运行良好 - 除了开始和结束点 - 由于它们是固定的并且无法优化。

有没有好的选择起点的方法?

【问题讨论】:

    标签: algorithm optimization polygon


    【解决方案1】:

    我会随机选择一个点(例如:所有点列表中的“第一个”点)并找到最远的点。这类似于算法在寻找离线段最远点时的普通步骤。

    【讨论】:

    • 问题是:如果我有一个由边缘上的几个顶点组成的矩形形状,它可能会切割边缘 - 留下梯形而不是矩形。它还可能导致构建具有 5 个顶点而不是 1 个顶点的矩形。
    • @Andreas Löw:这就是 Douglas-Peucker 算法的问题。不保证最佳。它是贪婪的,不会做任何后退。您可以尝试选择所有可能的起点并评估结果。但如果形状保证是矩形,可能会有更好的算法。
    【解决方案2】:

    我可能完全误解了这里的问题,但听起来您只是想将 Douglas-Peucker 算法 (http://en.wikipedia.org/wiki/Ramer–Douglas–Peucker_algorithm) 应用于多边形。您不能将多边形视为起点和终点相同的线的唯一原因是因为算法要求您让这两个点不同。

    所以我建议在多边形上选择两个相距很远的任意点,然后运行 ​​Douglas-Peucker 算法两次,一次用于点之间顺时针方向的路径,一次用于点之间的路径逆时针走。

    您的任意点保证在最终解决方案中,否则它会尽可能接近算法的直线近似值。

    如果这还不够,您应该搜索 LOD 或细节级别,因为这就是计算机图形学中通常所说的这个问题,尽管您可能会找到一堆关于解决多面体问题的页面相当复杂的树结构,这可能是也可能不是您正在寻找的。

    【讨论】:

      【解决方案3】:

      我在我的 javascript 库中做了类似的事情,在那里我找到了彼此相距最远的两个点,并使用它们来优化多边形。

      这里是 sn-p 我相信你可以适应你使用的任何语言:

      function polygonPeuckerReduce(path, tolerance) {
          var points = [];
          if (path.length < 3) {
              return points.concat(path);
          } else {
              var widest = 0.0, startIndex = 0;
              // find the widest part of the polygon (only start index is necessary)
              for (var i = 0, l = path.length; i < l; i++) {
                  var point = path[i];
                  for (var j = i + 1; j < l; j++) {
                      var distance = point.distanceTo(path[j]);
                      if (distance > widest) {
                          startIndex = i;
                          widest = distance;
                      }
                  }
              }
      
              // re-order the points with the new starting point (faster method)
              points = path.splice(startIndex, path.length).concat(path);
      
              return PEUCKER_INTERNAL(points, tolerance); // the magic
          }
      }
      

      【讨论】:

        【解决方案4】:

        另一种可能性是扫描所有三个连续顶点的集合,并选择距离连接其前任和后继顶点的线最远的两个顶点,即选择属于原始数据集中两个最大角的两个顶点。修复这两个顶点,然后将 Douglas-Peucker 应用于中间顶点。

        如果您的所有点都间隔很近,这可能会很吵。在这种情况下,您可以从每个输入顶点在两个方向上向外工作,而不是简单地考虑三个顶点的连续集合,使用 Douglas-Peucker 跳过每个方向上不必要的顶点。这将导致更大、更宽的三元组。再次找到距离连接前驱/后继顶点的线最远的两个顶点,修复它们,然后将 Douglas-Peucker 应用于中间顶点。

        其他变化是可能的,但这应该比其他答案中描述的“随机”或“最远”提供更好的起点。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-23
          • 2020-10-01
          • 2010-09-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-29
          相关资源
          最近更新 更多