17

I'm currently developing a visualization tool that draws WPF shapes such as paths, ellipses etc. on a Canvas. I've already implemented a virtualized approach where Shapes are being destroyed and created on the fly depending on their visibility. However, even with only like 600 ellipses visible, the application seems to struggle.

What are my options to speed things up? I'm thinking rendering grouped Shapes (let's say 500 at a time) as transparent bitmaps and only painting these on the Canvas. But I don't know whether that's a good idea... From what I gather this requires some sort of hack, if transformations were applied:

     VisualBrush shapeBrush = new VisualBrush(shape);  

     DrawingVisual drawingVisual = new DrawingVisual();  
     DrawingContext drawingContext = drawingVisual.RenderOpen();  

     using (drawingContext)  
     {  
        drawingContext.DrawRectangle(shapeBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));  
     }  
     renderTarget.Render(drawingVisual);  

What about using a big WritableBitmap? Would that be another approach?

kitsune
  • 11,516
  • 13
  • 57
  • 78

3 Answers3

7

WPF under the covers works with drawings and geometries - when you say you're working with shapes, are these actual UIElements? Such elements are quite a bit more heavy-weight. If you use just basic (preferably stream-) geometries to draw drawings, you'll get the best performance in my experience.

I managed to get up to around 10000 dots with a reasonable framerate with that approach, but anything more complex than a dot starts slowing things down (say, round dots or even just rectangles). Still, basic geometries and basic drawings are the way to go if you want to avoid as much WPF overhead as possible.

A Writeable bitmap is clearly eventually faster, but that means rending all those shapes yourself, or, caching the result bitmap if it's mostly static. Also, you'll generally want to apply transformations before rendering to bitmap rather than applying them to the rendered bitmap itself.

Eamon Nerbonne
  • 47,023
  • 20
  • 101
  • 166
  • I'm currently using this approach: a VirtualPath class that stores the Path data and returns a WPF System.Windows.Shapes.Path as soon as its boundaries are visible. – kitsune Sep 29 '09 at 08:09
  • Thanks for pointing me to StreamGeometry, I didn't know this class yet – kitsune Sep 29 '09 at 08:09
  • 2
    @kitsune, did you ever complete your "virtualpath that returns a path as soon as visible" trick? I think I could benefit from this in one of my projects – Brady Moritz Feb 13 '12 at 17:43
4

I'm aware this is an old question, I'm just answering in the interest of the community.

I researched the topic a bit, and the best I've found is to manually create DrawingVisuals like you say. It saves a lot of internal work to WPF, so it ends up being a lot faster. I used the technique to create a lightweight chart that can have couple hundred points. Here's the article I inspired myself from, you might already know about it.

http://blogs.microsoft.co.il/blogs/tamir/archive/2008/03/02/how-to-high-performance-graphics-in-wpf.aspx

EDIT: New URL http://khason.net/blog/how-to-high-performance-graphics-in-wpf/
EDIT: Newer URL: http://dedjo.blogspot.com/2008/03/how-to-high-performance-graphics-in-wpf.html

Good luck.

quetzalcoatl
  • 32,194
  • 8
  • 68
  • 107
Djof
  • 603
  • 1
  • 7
  • 20
-2

A brute-force approach might be to implement an ActiveX control and render the graphics directly using Win32. However, this will be somewhat fiddly. QT's canvas control might be a more warm and fluffy approach to the same end and it's noted for rendering this type of thing fairly quickly. Troll provide an ActiveX wrapper for the commercial versions of QT so it might be easier to integate.

ConcernedOfTunbridgeWells
  • 64,444
  • 15
  • 143
  • 197