如何在画布上使用大量多边形来提高性能和内存使用率?

时间:2020-03-06 14:53:27  来源:igfitidea点击:

我正在处理的项目需要呈现一个ESRI形状文件,该文件可以具有大量的多边形/形状。当我将所有这些多边形,线,点等添加到我正在使用的画布上时,它的速度真的很慢。

为了在地图上绘制形状,我创建了一个Path对象,并将其Data属性设置为StreamGeometry。我最初使用的是Polygon,但是根据MSDN,StreamGeometry的重量要轻得多。

如何提高性能?将最终产品转换为位图或者VisualBrush帮助吗?有没有更有效的方法可以将所有这些形状渲染到画布上?

编辑:我忘了提到这需要能够在Partial-Trust XBAP中工作。

解决方案

我们将发现GPU和疯狂超频和冷却的图形卡背后的动机。和双缓冲。

并且:将事物转换为位图:渲染它有什么区别?

毕竟,我们有n个必须以某种方式渲染的对象(除非我们可以找出哪些对象隐藏在其他对象后面,但这对我们没有多大帮助,因为我们必须查看n!对象关系)。

此外:离开正统的OOP方法而改用程序性的方法也许会有所收获。

@xmjx

And: converting the thing to a bitmap: what's the difference to rendering it?

我在这里的想法是,我的减速可能是由画布上有n个对象而不是1个位图引起的。就是说,我不知道性能,也不知道将具有n个对象的画布转换为位图时在后台会发生什么。

我不希望使用位图,这样我就可以允许用户与形状/多边形进行交互(修改/删除)。

我们可能会受到canvas小部件性能的限制。如果我们可以选择使用第三方工具包,请查看QT。它具有一个高性能的画布小部件,旨在快速渲染复杂的形状。至少已经有一个GIS应用程序使用了它,因此在此空间中有一些记录。

我们可以将QT包装为ActiveX控件,也可以使用Qyoto / Kimono .Net绑定与.Net应用程序交互。 Troll Tech刚刚改造了他们的网站,但我找不到他们以前在那里可以下载的演示,但是它显示了QGraphicsView小部件,可渲染非常大的矢量图形并实时缩小。

我们可以尝试使用GDI +或者直接使用x代替WPF。

对于一年前写的MSDN杂志文章,我做了一个类似的项目(通过WPF渲染地图数据)。

这只是我写得很快的文章(这篇文章和该应用程序花了大约1周的时间),并且被设计为"这是我们可以做的整洁的事情",因此我并没有过多地关注性能。无论如何,我遇到了同样的问题。一旦画布上的多边形数量变大,渲染性能便开始下降。例如,调整窗口大小将涉及大约1/2秒的延迟。

这在很大程度上与WPF的开销有关。它主要设计为GUI工具包,而不是高性能图形引擎。这意味着它专注于功能丰富而不是有效渲染。使用较少数量的对象(在大多数GUI应用程序中很可能会找到),性能非常好,并且数据绑定,动画和声明性样式功能(以及所有事件路由和它们所需的其他东西)确实可以派上用场。

但是,绘制地图时,庞大的数据量可能会导致所有这些整洁的数据绑定功能引起性能问题,如我们所知。

如果我们不需要声明性的样式和动画,那么我将消除WPF,并使用GDI +绘制自己的地图。从根本上讲,它涉及建立正确的变换矩阵以将地图绘制到控制表面上,然后遍历所有多边形并调用一堆DrawPolygon方法。

要启用交互,我们将必须编写自己的命中测试代码,并且在重新调整表单大小时必须重新绘制地图。我们还必须手动编写任何动画或者样式更改或者我们想要执行的操作(例如,当鼠标悬停在它们上方时突出显示区域)。但是,编写该代码并不难。我想像一下我们可以在1.5周内完成。

但是,这样做可以提高性能,因为它只能进行大约20-30K的矢量转换,而这在大多数现代CPU上并不需要太多的处理器功能。我们还可以考虑使用Direct X,这也将使我们能够充分利用GPU,从而带来更大的性能提升。

无需求助于GDI,我们只需要在WPF API中向下移动一层,并将几何图形合并为更少的视觉效果。 Pablo Fermicola提供了一些有关根据性能需求选择要使用的图层的有用信息。

我已经成功地使用DrawingVisual和DrawingContext类获得了出色的性能。

如果性能是一个问题,那么我们要避免使用Visual Brushes。这些画笔最好用于将屏幕的某些可见部分投影到屏幕上的其他位置。它们会严重影响性能,因为当画笔的内容更改时,这些画笔会自动更新。

该笔刷的任何用法都将通过软件呈现,并且将无法利用图形卡的硬件功能。

MSDN上有关VisualBrush的更多信息

使用DrawingGroup并添加/删除Drawing对象来解决此问题。请参阅我对Opacity = 0时有关DrawingVisual性能的类似问题的回答。我认为我的答案实际上更适合这个问题。

如果我们不必一次显示所有多边形(例如,由于缩放,平移等原因),请在此处查看虚拟化画布示例