【问题标题】:Algorithm to Fill In a Closed 2D Curve [closed]填充闭合二维曲线的算法[关闭]
【发布时间】:2014-09-21 21:59:17
【问题描述】:

我需要找到一种绘制封闭二维曲线内部的方法。这条曲线实际上是使用双三次贝塞尔曲线创建的,但我相信这并不重要。

目前绘制的形状内不应有“洞”。所以它会被完全填满。似乎受限的德劳内三角剖分是要走的路?但似乎有不同的方法可以做到这一点。我正在寻找一种快速而简单的解决方案(但会实施使其工作所需的东西)。

Illustrator 等程序具有这种功能(或 SVG——带有选项填充)。

我正在寻找:

  • 实现此目的的技术
  • 指向我解释算法的论文/文档
  • SVG 渲染器的源代码是否可以在某处获得?

编辑:

  • 应用程序使用 OpenGL。我自己画曲线。只需要找到一种方法来填充它们。
  • 形状可以是凹的也可以是凸的

【问题讨论】:

  • 一个好的答案取决于您正在绘制的环境。例如,Windows 直接支持使用贝塞尔轮廓绘制填充形状。 PostScript 和 PDF 也是如此。另一方面,如果你直接操作位,那么问题就变成了:你能画出轮廓吗?
  • 将贝塞尔曲线展平为直线并使用剪耳法。
  • @Logicrat:是的,抱歉问题不够清楚。我正在使用 OpenGL。我自己画贝塞尔曲线,现在只需要画里面。
  • 如果你用线段来近似贝塞尔曲线,你可以把这个形状当作一个多边形。您可以直接使用 OpenGL 渲染凹多边形。请参阅此问题/答案:stackoverflow.com/questions/25422846/…
  • cs.haifa.ac.il/~gordon/crit.pdf(如果有帮助,我还将它作为更大的 OpenGL 项目的一部分实现)。

标签: c++ algorithm graphics vector-graphics bezier


【解决方案1】:

可以使用Scanline 方法填充多边形。原理很简单:移动一条水平线并保留它遇到的边缘列表。它被称为活动列表。然后成对地从左到右连接交叉点。当边缘按纵坐标递增排序时,可以有效地完成活动列表从一个扫描线到下一个扫描线的更新。

这适用于凹/凸多边形和带孔的多边形,甚至是交叉的。

要填充贝塞尔路径,您可以将其展平,即将其变为多边多边形。

基于扫描线的想法,直接的方法也是可能的:首先将贝塞尔曲线分解为 单调 部分,即仅在水平线上相遇一次的部分。这可以通过检测曲线最大值和最小值(方程是二次的)对三次贝塞尔曲线进行解析。

现在您可以将曲线多边形完全视为多边形,因为您知道每边都有一个交点。有一个稍微微妙的点,计算交点。但是,由于您知道贝塞尔弧(相同端点之间的线段)的良好近似值,并且您可以从一条扫描线到下一条扫描线递增地更新相交,这一事实使这一点得到了缓解。

在图片上,原始端点显示为蓝色。已添加拆分 endoints 以获得单调部分(省略其他控制点)。虚线显示近似形状并具有相同拓扑的多边形(相同的活动列表,与扫描线的交点数量相同)。

【讨论】:

  • 谢谢 Yves - 这是一个非常好的解决方案。正如您在评论中建议的那样,我对所有方法都感兴趣。请问这个图是怎么做的?您使用的是哪个应用程序?
  • MS Word,使用形状工具。
  • 我没有详细说明找到交点的方法,这涉及求解三次方程。当然可以使用卡尔达诺公式,但数值方法应该更好。可能是牛顿法,也可能是割线法。使用后者,在某种程度上,您将“即时”拉平曲线。
【解决方案2】:

如果您必须使用多边形填充,除了拉平曲线以获得直边之外别无选择。

然后使用多边形填充图元。

如果你只有一个三角形填充图元,你可以

  • 通过ear clipping 对多边形进行三角剖分,或在monotone polygons 中分解,或

  • 使用简单的扫描线方法:如果您通过每个顶点绘制一条水平线,您将把多边形切成三角形和梯形。梯形可以切成两个三角形。为提高效率,请使用活动列表方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多