24

我有一个由二维点列表组成的路径。我想把这些变成一条三角形,以渲染一条具有指定厚度的纹理线(以及其他类似的东西)。所以本质上,二维点列表需要成为一个顶点列表,指定多边形的轮廓,如果渲染将渲染线条。问题在于处理角连接、斜接、帽等。生成的多边形需要在没有过度绘制、干净连接等的意义上是“完美的”,以便它可以被挤出或以其他方式玩弄。

是否有任何简单的资源可以提供算法洞察力、代码或更多关于有效执行此操作的信息?

我绝对不想要一个完整的 2D 矢量库(cairo、antigrain、OpenVG 等),其中包含曲线、弧线、破折号和所有的花里胡哨。我一直在为 OpenVG 实现和其他东西挖掘多个源代码树以找到一些见解,但这一切都非常令人费解。

我绝对愿意自己编写代码,但是有许多退化的情况(小段 + 粗宽度 + 尖角)会产生各种连接问题。即使是一点点帮助,也能节省我处理所有这些问题的时间。

编辑:如果你只是从一个顶点到另一个顶点,这是一个导致丑陋的退化案例之一的例子。红色是原始路径。橙色块是以指定宽度绘制的矩形,对齐并以每个线段为中心。

4

9 回答 9

4

哦,好吧 - 我已经尝试自己解决这个问题。我在一个试图解决零透支问题的解决方案上浪费了两个月。正如您已经发现的那样,您不能同时处理所有退化的情况并实现零透支。

但是,您可以使用混合方法:

为自己编写一个例程,检查连接是否可以从简单的几何图形构建而没有问题。为此,您必须检查连接角度、线宽和连接线段的长度(比宽度短的线段是 PITA)。通过一些启发式方法,您应该能够理清所有琐碎的案例。

我不知道您的平均线数据是什么样的,但在我的情况下,超过 90% 的宽线没有退化的情况。

对于所有其他行:

您很可能已经发现,如果您容忍过度绘制,生成几何图形会容易得多。这样做,让多边形 CSG 算法和曲面细分算法来完成这项艰巨的工作。

我已经评估了大多数可用的镶嵌包,最后我选择了 GLU 镶嵌器。它快速、健壮、永不崩溃(与大多数其他算法不同)。它是免费的,许可证允许我将它包含在商业程序中。镶嵌的质量和速度还可以。您不会获得 delaunay 三角测量质量,但由于您只需要三角形进行渲染,这不是问题。

由于我不喜欢 tesselator API,我从免费的 SGI OpenGL 参考实现中提取了 tesselation 代码,重写了整个前端并添加了内存池以减少分配数量。这样做花了两天时间,但这是非常值得的(就像因素五的性能提升)。顺便说一句,该解决方案最终以商业 OpenVG 实现 :-)

如果您在 PC 上使用 OpenGL 进行渲染,您可能希望将曲面细分/CSG 作业从 CPU 移动到 GPU,并使用模板缓冲区或 z 缓冲区技巧来消除过度绘制。这比 CPU 细分要容易得多,甚至可能更快。

于 2009-03-27T06:35:35.493 回答
3

我刚刚发现了这个惊人的工作:

http://www.codeproject.com/Articles/226569/Drawing-polylines-by-tessellation

它似乎完全符合您的要求,并且它的许可证甚至允许在商业应用程序中使用它。另外,作者在详细说明他的方法方面做得非常出色。我可能会在某个时候试一试,以替换我自己的不太完美的实现。

于 2014-10-27T23:35:13.923 回答
2

一个简单的方法在我脑海中浮现。

平分每个 2d 顶点的角度,这将创建一个漂亮的斜接线。然后沿着那条线向内和向外移动,你的“厚度”(或厚度除以二?)的量,你现在有你的内部和外部多边形点。移动到下一个点,重复相同的过程,沿途构建新的多边形点。然后应用三角剖分来获得渲染就绪的顶点。

于 2009-03-26T21:03:56.287 回答
1

我最终不得不弄脏自己的手并写了一个小ribbonizer来解决类似的问题。

对我来说,问题是我想要 OpenGL 中的粗线条没有我在 iPhone 上使用 OpenGL 看到的那种伪影。在查看了各种解决方案之后;贝塞尔曲线之类的——我认为自己制作可能是最简单的。有几种不同的方法。

一种方法是找到两个线段之间的相交角度,然后沿着该相交线移动距离表面一定距离,并将其视为带状顶点。我试过了,但它看起来并不直观;色带宽度会有所不同。

另一种方法是实际计算线段表面的法线,并使用它来计算该线段的理想色带边缘,并在色带段之间进行实际的相交测试。这工作得很好,除了对于尖角,带状线段交叉点太远(如果段间角度接近 180')。

我用两种方法解决了锐角问题。Paul Bourke 线相交算法(我以未优化的方式使用)建议检测相交是否在路段内。由于两个段是相同的,我只需要测试其中一个段是否相交。然后我可以仲裁如何解决这个问题;通过捏造两端之间的最佳点或戴上端盖 - 两种方法看起来都不错 - 端盖方法可能会抛弃 opengl 的多边形正面/背面排序。

http://paulbourke.net/geometry/lineline2d/

在此处查看我的源代码:https ://gist.github.com/1474156

于 2011-12-13T22:27:39.053 回答
0

我想我会使用曲面细分算法。确实,在大多数情况下,使用这些的目的是减少顶点数量以优化渲染,但在您的情况下,您可以参数化以保留所有细节 - 优化的可能性可能会派上用场。

网络上有许多曲面细分算法和代码——几年前我在一个 DLL 中封装了一个纯 C 语言,用于与 Delphi 风景渲染器一起使用,它们对于高级图形编码教程等来说并不少见。

于 2009-03-26T19:24:37.947 回答
0

我也对此感兴趣,因为我想完善我的地图应用程序 ( Kosmos ) 的道路绘制。我使用的一种解决方法是绘制折线两次,一次用较粗的线,一次用较细的线,用不同的颜色。但这并不是真正的多边形,它只是一种模拟多边形的快速方法。在此处查看一些示例:http ://wiki.openstreetmap.org/wiki/Kosmos_Rendering_Help#Rendering_Options

我不确定这是否是您需要的。

于 2009-03-26T19:32:46.460 回答
0

看看德劳内三角测量是否有帮助。

于 2009-03-26T20:53:17.950 回答
0

就我而言,我有能力透支。我只是在折线的每个顶点上绘制半径 = 宽度/2 的圆。

工件以这种方式被掩盖,并且很容易实现,如果您可以忍受“圆角”和一些过度绘制。

于 2010-01-11T12:14:55.227 回答
0

从您的图像看来,您正在使用 FILL 并使用橙色围绕线段绘制框。这样做肯定会造成糟糕的透支。所以首先要做的是不渲染黑色边框,填充颜色可以是不透明的。

为什么你不能使用 GL_LINES 原语来做你想做的事情?您可以指定宽度、过滤、平滑度、纹理任何内容。您可以使用 glDrawArrays() 渲染所有顶点。我知道这不是您的想法,但是当您专注于 2D 绘图时,这可能是更简单的方法。(搜索纹理线条等)

于 2010-01-13T04:50:25.387 回答