【问题标题】:Best way to calculate Ramer-Douglas-Peucker tolerance计算 Ramer-Douglas-Peucker 公差的最佳方法
【发布时间】:2021-05-16 11:40:11
【问题描述】:

我正在使用 Ramer Douglas Peucker 算法的实现来减少地图路线的点数。例如,如果我有超过 500 个点,我想以一个容差运行算法,该容差将点数减少到 500 以下,同时尽可能接近它。到目前为止,我尝试过的非常低效的方法如下:

simp = coordSimplify(data.tableData, 0)
while (simp.length > 400) {
    i += 0.0001;
    simp = coordSimplify(data.tableData, i);
}

但我意识到这会大大减慢整个过程。

如何让整个过程更有效率?我在考虑某种二进制斩波算法,但后来我不确定每次如何计算上限和下限。

TIA

【问题讨论】:

  • 你看过人们在 github 上的实现吗?
  • 这里和那里一点点 - 为什么?
  • github 是有史以来最好的编程资源之一。我曾经在那里找到了一个完整的(!)“故障单系统”,一家公司已经工作了一年多......完成并完善了它......然后在github上放弃了它!您应该非常彻底地寻找与您的想法相似的“现有艺术”,因为“有人已经完成了”并且他们可能会戴上它github 或 sourceforge。 Actum Ne Agas: 不要做已经完成的事情。™
  • 我知道如何使用 Github。

标签: javascript douglas-peucker


【解决方案1】:

建议尝试以下几行,这实际上是一种二分搜索,寻找位于目标点长度范围simpTargetLosimpTargetHi 内的epsilon 值(使用术语https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm)。

(请注意,我没有对此进行测试,因为我无权访问coordSimplify(),因此可能存在一些语法错误,但逻辑应该是合理的。)

// Set the acceptable result.
let simpTargetLo = 490;
let simpTargetHi = 510;

// Set the initial epsilon range which needs to be outside the estimated solution.
let epsilonLo = 0;
let epsilonHi = 1;
let epsilonMid;

// Calculate the initial low and high simp values.
let simpLo = coordSimplify(data.tableData, epsilonLo);
let simpHi = coordSimplify(data.tableData, epsilonHi);
let simpMid;

// Ensure that the initial simp values fall outside the target range.
if ( !( simpLo.length <= simpTargetLo && simpTargetHi <= simpHi.length ) ) {
  throw new Error( `Initial epsilon need expanding.\n  epsilonLo ${epsilonLo} returns ${simpLo.length}\n  epsilonHi ${epsilonHi} returns ${simpHi.length}` );
}

// Finally, let's ensure we don't get into an infinite loop in the event that
// their is no solution or the solution oscillates outside the target range.
let iterations = 0;
let maxIterations = 100;

do {
  
  // Calculate the simp at the midpoint of the low and high epsilon.
  epsilonMid = ( epsilonLo + epsilonHi ) / 2;
  simpMid = coordSimplify(data.tableData, epsilonMid );
  
  // Narrow the epsilon low and high range if the simp result is still outside
  // both the target low and high.
  if ( simpMid.length < simpTargetLo ) {
    epsilonLo = epsilonMid;
  } else if ( simpTargetHi < simpMid.length ) {
    epsilonHi = epsilonMid;
  } else {
    // Otherwise, we have a solution!
    break;
  }
  
  iterations++;
  
while( iterations < maxIterations );

if ( iterations < maxIterations ) {
  console.log( `epsilon ${epsilonMid} returns ${simpMid.length}` );
} else {
  console.log( `Unable to find solution.` );
}

请注意,除了假设 coordSimplify() 在本质上是相当连续的之外,这种缩小到解决方案的方法取决于初始 epsilonLoepsilonHi 的正确选择...

【讨论】:

    猜你喜欢
    • 2018-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-27
    • 2015-03-08
    • 2015-10-09
    • 2016-05-19
    • 1970-01-01
    相关资源
    最近更新 更多