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

时间:2021-10-24 06:13:56

The project I'm working on needs to render an ESRI shape file, which can have a large number of polygons/shapes. When I add all these polygons, lines, points, etc to the canvas I'm using, it gets really slow.

我正在研究的项目需要渲染一个ESRI形状文件,它可以有大量的多边形/形状。当我将所有这些多边形,线条,点等添加到我正在使用的画布时,它变得非常慢。

To draw the shapes on the map, I'm creating a Path object, and setting it's Data property to a StreamGeometry. I originally used a Polygon, but according to MSDN a StreamGeometry is much lighter weight.

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

How can I improve the performance? Would converting the finished product to a Bitmap, or VisualBrush help? Is there a more efficient way of to render all these shapes onto the canvas?

如何提高性能?将成品转换为Bitmap,还是VisualBrush帮助?有没有更有效的方法将所有这些形状渲染到画布上?

EDIT: I forgot to mention that this needs to be able to work in a Partial-Trust XBAP.

编辑:我忘了提到这需要能够在部分信任XBAP中工作。

8 个解决方案

#1


7  

No need to resort to GDI, you just need to move down a layer in the WPF API's and combine your geometry into fewer visuals. Pablo Fermicola has some useful information about picking which layer to use depending on your performance needs.

无需使用GDI,只需在WPF API中向下移动一层,并将几何体组合成更少的视觉效果。 Pablo Fermicola提供了一些有用的信息,可根据您的性能需求选择要使用的层。

I've managed to get excellent performance using DrawingVisual and the DrawingContext class.

我已经设法使用DrawingVisual和DrawingContext类获得了出色的性能。

#2


2  

You could try using GDI+ or direct x instead of WPF.

您可以尝试使用GDI +或直接x而不是WPF。

I did a similar project (rendering Map data via WPF), for an MSDN magazine article I wrote about a year ago.

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

It was just something I wrote rather quickly (the article + the app took about 1 week), and was designed to just be a "this is something neat you can do", and so I didn't focus on performance much. In any case, I ran into the same problem. Once the number of polygons on the canvas got large, the rendering performance started to suffer. For example, resizing the window would involve about a 1/2 second delay or so.

这只是我写得相当快的东西(文章+应用程序花了大约1周),并且被设计成只是“这是你可以做的事情”,所以我没有太多关注性能。无论如何,我遇到了同样的问题。一旦画布上的多边形数量变大,渲染性能就开始下降。例如,调整窗口大小将涉及大约1/2秒的延迟。

A lot of this has to do with the overhead of WPF. It's primarily designed as an GUI toolkit, rather than a high performance graphic engine. That means it focuses on feature richness over efficent rendering. With smaller numbers of objects (what is likely to be found in most GUI applications), the performance is pretty good and the databinding, animation, and declarative style features (and all the event routing and other things they require) can really come in handy.

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

When drawing a map, however, the sheer volume of data can cause all those neat data binding features to cause perf problems, as you seem well aware.

但是,在绘制地图时,如您所知,大量数据可能会导致所有这些整齐的数据绑定功能导致性能问题。

If you don't need declarative styling and animation, then I would just eliminate WPF, and use GDI+ to draw the map your self. It basicly involves setting up the right transformation matrix to get the map to draw onto a control surface, and then iterating through all the polygons and calling a bunch of DrawPolygon methods.

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

To enable interaction you will have to write your own hit testing code, and you will have to redraw the map anytime the form is resized. You will also have to hand code any animations or style changes or things like that you want to do (such as highlighting regions when the mouse is over them). But, it shouldn't be that difficult to write that code. I would imaging you could do it in about 1.5 weeks.

要启用交互,您必须编写自己的命中测试代码,并且必须在调整表单大小时重绘地图。您还必须手动编写任何动画或样式更改或您想要做的事情(例如,当鼠标悬停在区域上时突出显示区域)。但是,编写代码应该不难。我会想象你可以在大约1.5周内做到这一点。

Doing it that way, however, should improve performance, because it would come down to doing only about 20-30K vector transformations, which doesn't take much processor power on most modern CPU's. You could also look into using Direct X, which would allow you to take advantage of the GPU as well, which could give an even bigger performance boost.

但是,这样做应该可以提高性能,因为它只能做大约20-30K的矢量转换,这在大多数现代CPU上都不需要太多的处理器能力。您还可以考虑使用Direct X,它可以让您利用GPU,这可以提供更大的性能提升。

#3


1  

You may be limited by the performance of the canvas widget. If you have the option of using a 3rd party toolkit look at QT. It has a high performance canvas widget that is designed to render complex shapes quickly. This has already been used for at least one GIS application, so it has some track record in this space.

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

You can wrap QT as an ActiveX control or use the Qyoto/Kimono .Net bindings to interface to a .Net application. Troll Tech have just revamped their website and I can't find the downloadable demo they used to have there but it shows the QGraphicsView widget rendering a very large vector drawing and zooming out in real time.

您可以将QT包装为ActiveX控件,或使用Qyoto / Kimono .Net绑定来连接到.Net应用程序。 Troll Tech刚刚修改了他们的网站,我找不到他们曾经拥有的可下载演示,但它显示了QGraphicsView小部件渲染非常大的矢量绘图并实时缩小。

#4


0  

You are about to discover the motivation behind GPUs and insanely overclocked and cooled-down graphics cards. And double-buffering.

您即将发现GPU背后的动机以及疯狂超频和冷却的显卡。并且双缓冲。

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

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

After all you have n objects that /somehow/ have to get rendered (unless you can figure out which objects are hidden behind other objects but that doesn't help you much since you'd have to look at n! object relations).

毕竟你有/ n某种/必须要渲染的n个对象(除非你可以弄清楚哪些对象隐藏在其他对象后面,但这对你没什么帮助,因为你必须看看n!对象关系)。

Besides: maybe it pays off to leave the orthodox OOP approach and go procedural instead.

此外:也许离开正统的OOP方法并转而采用程序是值得的。

#5


0  

@xmjx

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

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

My thought here was that my slowdown could be caused by having n number of objects on a canvas, versus 1 bitmap. That said, I don't know the performance, or what happens in the background when converting a canvas with n number of objects to a Bitmap.

我的想法是,我的减速可能是由于画布上有n个对象而不是1个位图造成的。也就是说,我不知道性能,或者在将具有n个对象的画布转换为Bitmap时在后台发生的事情。

I would prefer not to use a Bitmap, so that I can allow the user to interact (modify/delte) with the shape/polygons.

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

#6


0  

If performance is an issue then you want to avoid Visual Brushes. These brushes are best used to project some visible part of the screen to another place on the screen. They cause a large performance hit because these brushes automatically update when the brush's content changes.

如果性能是一个问题,那么你想避免使用Visual Brushes。这些画笔最适合用于将屏幕的某些可见部分投影到屏幕上的另一个位置。它们会导致性能大幅下降,因为这些画笔会在画笔内容发生变化时自动更新。

Any usage of this brush will be software rendered, and will not be able to take advantage of the hardware capabilities of your graphic card.

此画笔的任何使用都将是软件渲染,并且无法利用图形卡的硬件功能。

More info from MSDN on VisualBrush

来自MSDN的VisualBrush的更多信息

#7


0  

Use DrawingGroup and add/remove Drawing objects to solve this. See my answer to a similar question about DrawingVisual performance with Opacity=0. I think my answer actually fits this question better.

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

#8


0  

if you do not have to show ALL polygons at once (e.g. due to zooming, panning etc), check out the virtualizing canvas sample here

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

#1


7  

No need to resort to GDI, you just need to move down a layer in the WPF API's and combine your geometry into fewer visuals. Pablo Fermicola has some useful information about picking which layer to use depending on your performance needs.

无需使用GDI,只需在WPF API中向下移动一层,并将几何体组合成更少的视觉效果。 Pablo Fermicola提供了一些有用的信息,可根据您的性能需求选择要使用的层。

I've managed to get excellent performance using DrawingVisual and the DrawingContext class.

我已经设法使用DrawingVisual和DrawingContext类获得了出色的性能。

#2


2  

You could try using GDI+ or direct x instead of WPF.

您可以尝试使用GDI +或直接x而不是WPF。

I did a similar project (rendering Map data via WPF), for an MSDN magazine article I wrote about a year ago.

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

It was just something I wrote rather quickly (the article + the app took about 1 week), and was designed to just be a "this is something neat you can do", and so I didn't focus on performance much. In any case, I ran into the same problem. Once the number of polygons on the canvas got large, the rendering performance started to suffer. For example, resizing the window would involve about a 1/2 second delay or so.

这只是我写得相当快的东西(文章+应用程序花了大约1周),并且被设计成只是“这是你可以做的事情”,所以我没有太多关注性能。无论如何,我遇到了同样的问题。一旦画布上的多边形数量变大,渲染性能就开始下降。例如,调整窗口大小将涉及大约1/2秒的延迟。

A lot of this has to do with the overhead of WPF. It's primarily designed as an GUI toolkit, rather than a high performance graphic engine. That means it focuses on feature richness over efficent rendering. With smaller numbers of objects (what is likely to be found in most GUI applications), the performance is pretty good and the databinding, animation, and declarative style features (and all the event routing and other things they require) can really come in handy.

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

When drawing a map, however, the sheer volume of data can cause all those neat data binding features to cause perf problems, as you seem well aware.

但是,在绘制地图时,如您所知,大量数据可能会导致所有这些整齐的数据绑定功能导致性能问题。

If you don't need declarative styling and animation, then I would just eliminate WPF, and use GDI+ to draw the map your self. It basicly involves setting up the right transformation matrix to get the map to draw onto a control surface, and then iterating through all the polygons and calling a bunch of DrawPolygon methods.

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

To enable interaction you will have to write your own hit testing code, and you will have to redraw the map anytime the form is resized. You will also have to hand code any animations or style changes or things like that you want to do (such as highlighting regions when the mouse is over them). But, it shouldn't be that difficult to write that code. I would imaging you could do it in about 1.5 weeks.

要启用交互,您必须编写自己的命中测试代码,并且必须在调整表单大小时重绘地图。您还必须手动编写任何动画或样式更改或您想要做的事情(例如,当鼠标悬停在区域上时突出显示区域)。但是,编写代码应该不难。我会想象你可以在大约1.5周内做到这一点。

Doing it that way, however, should improve performance, because it would come down to doing only about 20-30K vector transformations, which doesn't take much processor power on most modern CPU's. You could also look into using Direct X, which would allow you to take advantage of the GPU as well, which could give an even bigger performance boost.

但是,这样做应该可以提高性能,因为它只能做大约20-30K的矢量转换,这在大多数现代CPU上都不需要太多的处理器能力。您还可以考虑使用Direct X,它可以让您利用GPU,这可以提供更大的性能提升。

#3


1  

You may be limited by the performance of the canvas widget. If you have the option of using a 3rd party toolkit look at QT. It has a high performance canvas widget that is designed to render complex shapes quickly. This has already been used for at least one GIS application, so it has some track record in this space.

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

You can wrap QT as an ActiveX control or use the Qyoto/Kimono .Net bindings to interface to a .Net application. Troll Tech have just revamped their website and I can't find the downloadable demo they used to have there but it shows the QGraphicsView widget rendering a very large vector drawing and zooming out in real time.

您可以将QT包装为ActiveX控件,或使用Qyoto / Kimono .Net绑定来连接到.Net应用程序。 Troll Tech刚刚修改了他们的网站,我找不到他们曾经拥有的可下载演示,但它显示了QGraphicsView小部件渲染非常大的矢量绘图并实时缩小。

#4


0  

You are about to discover the motivation behind GPUs and insanely overclocked and cooled-down graphics cards. And double-buffering.

您即将发现GPU背后的动机以及疯狂超频和冷却的显卡。并且双缓冲。

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

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

After all you have n objects that /somehow/ have to get rendered (unless you can figure out which objects are hidden behind other objects but that doesn't help you much since you'd have to look at n! object relations).

毕竟你有/ n某种/必须要渲染的n个对象(除非你可以弄清楚哪些对象隐藏在其他对象后面,但这对你没什么帮助,因为你必须看看n!对象关系)。

Besides: maybe it pays off to leave the orthodox OOP approach and go procedural instead.

此外:也许离开正统的OOP方法并转而采用程序是值得的。

#5


0  

@xmjx

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

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

My thought here was that my slowdown could be caused by having n number of objects on a canvas, versus 1 bitmap. That said, I don't know the performance, or what happens in the background when converting a canvas with n number of objects to a Bitmap.

我的想法是,我的减速可能是由于画布上有n个对象而不是1个位图造成的。也就是说,我不知道性能,或者在将具有n个对象的画布转换为Bitmap时在后台发生的事情。

I would prefer not to use a Bitmap, so that I can allow the user to interact (modify/delte) with the shape/polygons.

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

#6


0  

If performance is an issue then you want to avoid Visual Brushes. These brushes are best used to project some visible part of the screen to another place on the screen. They cause a large performance hit because these brushes automatically update when the brush's content changes.

如果性能是一个问题,那么你想避免使用Visual Brushes。这些画笔最适合用于将屏幕的某些可见部分投影到屏幕上的另一个位置。它们会导致性能大幅下降,因为这些画笔会在画笔内容发生变化时自动更新。

Any usage of this brush will be software rendered, and will not be able to take advantage of the hardware capabilities of your graphic card.

此画笔的任何使用都将是软件渲染,并且无法利用图形卡的硬件功能。

More info from MSDN on VisualBrush

来自MSDN的VisualBrush的更多信息

#7


0  

Use DrawingGroup and add/remove Drawing objects to solve this. See my answer to a similar question about DrawingVisual performance with Opacity=0. I think my answer actually fits this question better.

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

#8


0  

if you do not have to show ALL polygons at once (e.g. due to zooming, panning etc), check out the virtualizing canvas sample here

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