Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF drawing performance with large numbers of geometries

I have problems with WPF drawing performance. There are a lot of small EllipseGeometry objects (1024 ellipses, for example), which are added to three separate GeometryGroups with different foreground brushes. After, I render it all on simple Image control. Code:

DrawingGroup tmpDrawing = new DrawingGroup();
GeometryGroup onGroup = new GeometryGroup();
GeometryGroup offGroup = new GeometryGroup();
GeometryGroup disabledGroup = new GeometryGroup();

for (int x = 0; x < DisplayWidth; ++x)
{
    for (int y = 0; y < DisplayHeight; ++y)
    {
        if (States[x, y] == true) onGroup.Children.Add(new EllipseGeometry(new Rect((double)x * EDGE, (double)y * EDGE, EDGE, EDGE)));
        else if (States[x, y] == false) offGroup.Children.Add(new EllipseGeometry(new Rect((double)x * EDGE, (double)y * EDGE, EDGE, EDGE)));
        else disabledGroup.Children.Add(new EllipseGeometry(new Rect((double)x * EDGE, (double)y * EDGE, EDGE, EDGE)));
    }
}

tmpDrawing.Children.Add(new GeometryDrawing(OnBrush, null, onGroup));
tmpDrawing.Children.Add(new GeometryDrawing(OffBrush, null, offGroup));
tmpDrawing.Children.Add(new GeometryDrawing(DisabledBrush, null, disabledGroup));
DisplayImage.Source = new DrawingImage(tmpDrawing);

It works fine, but takes too much time - >0.5s on Core 2 Quad, >2s on Pentium 4. I need <0.1s everywhere. All Ellipses, how you can see, are equal. Background of control, where is my DisplayImage, is solid (black, for example), so we can use this fact. I tried to use 1024 Ellipse elements instead of Image with EllipseGeometries, and it was working much faster (~0.5s), but not enough. How to speed up it?

Regards, Oleg Eremeev

P.S. Sorry for my English.

like image 583
Alec Mev Avatar asked Mar 06 '10 18:03

Alec Mev


2 Answers

I left my old rendering method, but creating new EllipseGeometry object each time was bad idea, so I optimized it in this way:

for (int x = 0; x < newWidth; ++x)
{
    for (int y = 0; y < newHeight; ++y)
    {
        States[x, y] = null;
        OnEllipses[x, y] = new EllipseGeometry(new Rect((double)x * EDGE + 0.5f, (double)y * EDGE + 0.5f, EDGE - 1f, EDGE - 1f));
        OffEllipses[x, y] = new EllipseGeometry(new Rect((double)x * EDGE + 0.5f, (double)y * EDGE + 0.5f, EDGE - 1f, EDGE - 1f));
        DisabledEllipses[x, y] = new EllipseGeometry(new Rect((double)x * EDGE + 0.5f, (double)y * EDGE + 0.5f, EDGE - 1f, EDGE - 1f));
    }
}

// . . .

DrawingGroup tmpDrawing = new DrawingGroup();
GeometryGroup onGroup = new GeometryGroup();
GeometryGroup offGroup = new GeometryGroup();
GeometryGroup disabledGroup = new GeometryGroup();

for (int x = 0; x < DisplayWidth; ++x)
{
    for (int y = 0; y < DisplayHeight; ++y)
    {
        if (States[x, y] == true) onGroup.Children.Add(OnEllipses[x, y]);
        else if (States[x, y] == false) offGroup.Children.Add(OffEllipses[x, y]);
        else disabledGroup.Children.Add(DisabledEllipses[x, y]);
    }
}

tmpDrawing.Children.Add(new GeometryDrawing(OnBrush, null, onGroup));
tmpDrawing.Children.Add(new GeometryDrawing(OffBrush, null, offGroup));
tmpDrawing.Children.Add(new GeometryDrawing(DisabledBrush, null, disabledGroup));
DisplayImage.Source = new DrawingImage(tmpDrawing);

For x = 128 and y = 8 it works really fast, even on Pentium III systems.

like image 114
Alec Mev Avatar answered Nov 15 '22 22:11

Alec Mev


Even if I am a little late: This post by Charles Petzold helped a lot in a similar scenario.

like image 36
Jens Avatar answered Nov 15 '22 22:11

Jens