【发布时间】:2014-04-28 16:19:11
【问题描述】:
我有一些地理数据(下图将河流的路径显示为红点),我想使用多段三次贝塞尔曲线对其进行近似。通过关于 stackoverflow here 和 here 的其他问题,我从“Graphics Gems”中找到了 Philip J. Schneider 的算法。我成功地实现了它,并且可以报告即使有数千个点它也非常快。不幸的是,速度带来了一些缺点,即拟合非常草率。考虑下图:
红点是我的原始数据,蓝线是施耐德算法创建的多段贝塞尔曲线。如您所见,算法的输入是一个容差,至少与绿线所示的一样高。然而,该算法创建了一个有太多急转弯的贝塞尔曲线。您也可以在图像中看到这些不必要的急转弯。很容易想象所显示数据的贝塞尔曲线具有较少的急转弯,同时仍保持最大容差条件(只需将贝塞尔曲线稍微推向洋红色箭头的方向)。问题似乎是该算法从我的原始数据中选择数据点作为各个贝塞尔曲线的端点(洋红色箭头点表示一些嫌疑人)。由于贝塞尔曲线的端点被这样限制,很明显该算法有时会产生相当尖锐的曲率。
我正在寻找的是一种算法,它可以用具有两个约束的多段贝塞尔曲线来近似我的数据:
- 多段贝塞尔曲线与数据点的距离不得超过一定距离(这是由 Schneider 算法提供的)
- 多段贝塞尔曲线绝不能产生过于尖锐的曲率。检查此标准的一种方法是沿多段贝塞尔曲线滚动具有最小曲率半径的圆,并检查它是否沿其路径接触曲线的所有部分。虽然似乎有一个更好的方法涉及cross product of the first and second derivative
遗憾的是,我发现创建更好拟合的解决方案要么仅适用于单个贝塞尔曲线(并且省略了如何为多段贝塞尔曲线中的每条贝塞尔曲线找到良好起点和终点的问题)或不允许最小值曲率约束。我觉得最小曲率约束是这里的棘手条件。
这里是另一个例子(这是手绘的,不是 100% 精确的):
假设图一显示了曲率约束(圆必须沿着整条曲线拟合)以及任何数据点与曲线的最大距离(恰好是绿色圆的半径) .图二中红色路径的成功近似显示为蓝色。该近似值尊重曲率条件(圆可以在整个曲线内滚动并在任何地方接触它)以及距离条件(以绿色显示)。图三显示了路径的不同近似值。虽然它尊重距离条件,但很明显圆不再适合曲率。图四显示了一条无法用给定约束近似的路径,因为它太尖了。这个例子应该说明为了正确近似路径中的一些尖角转弯,算法必须选择不属于路径的控制点。图 3 表明,如果选择了沿路径的控制点,曲率约束将不再满足。此示例还表明,算法必须在某些输入上退出,因为不可能用给定的约束来逼近它。
这个问题有解决方案吗?解决方案不必很快。如果处理 1000 个点需要一天时间,那很好。解决方案也不必是最优的,因为它必须导致最小二乘拟合。
最后我会用 C 和 Python 实现这个,但我也可以阅读大多数其他语言。
【问题讨论】:
-
这需要一个非常重要的问题:您是想使用贝塞尔曲线,还是真的想为您的数据拟合一个函数?因为如果你想做好的科学,你绝对不想要贝塞尔曲线。
-
@Mike'Pomax'Kamermans 函数将每个输入与一个输出相关联。正如您在上面看到的,一个 x 值可以有多个 y 值。一个函数对那里有什么帮助?
-
与您使用贝塞尔“函数”的方式相同。如果您想要准确地描绘河流,使用多边形贝塞尔曲线有点奇怪。你想要通过点的曲线,所以至少我们正在考虑应用 Catmull-Rom 曲线(有趣的事实:两者都是 Hermite 样条并且是彼此的表示,除了 Catmull-Rom 曲线通过特定的“通过点”速度:几乎正是您对河流数据建模所需要的)
-
我不希望曲线通过点。正如我在我的问题中指出的那样,施耐德的算法会产生我不希望曲线通过某些点的结果。我想近似河流,而不是精确地追踪它。通过使用样条曲线,我重用了我作为控制点的点。我不想要那个。我想要一个平滑的近似值。
-
很公平,但这就是您遇到“您有主观要求”的地方。您的帖子实际上并没有将它们正式化,要求保持模糊:“超过一定距离”、“过于尖锐的曲率”等不是我们可以帮助您解决的问题,除非您获得更精确的信息。对你来说,“一定距离”是什么意思,“太尖锐”是什么意思,等等。你有一个详细的问题,但它有错误的细节。
标签: python c algorithm bezier approximation