Search code examples
c#winformsoptimizationgeometrypaint

C# Drawing (paint)


I'm developing an application which is basically drawing geo data. I have DataSets implemented which holds all sorts of data including coordinates. I'm using conversion from cartesian to screen in order for them to appear correctly on the screen. I am using WinForms and paint event.

However, my question is here. How do I optimize or speed up the drawing. If I have around 2000 points (elipses) and 1000 lines perse.. the moving around is kinda slow.

Mouse move is also invalidating the paint event, so every time I pan around, It actually refreshes the paint event.

How do I make the drawing faster? Like more data there is to draw the slower the panning becomes (obviously by refreshing paint event every mouse movement).

In paint event I iterate through my tables in dataset with foreach loop. Example: foreach(DataRow r in ...Tables["points"].Select()) {}

EDIT:: Mouse move is Invalidating not refreshing. Upon holding middle mouse button I can pan around my view meaning I will only show the drawing that fall into my screen (I've done so by comapring each row I run into if it fall inside my screen, then I draw it). Zooming out to see the whole content is very heavy. (8000+ points)

Code is nothing special. Paint event -> Foreach (DataRow in table) -> get coords -> check if it's visible and it falls into the boundaries of screen -> draw

I could write whole content to memory bitmap and display the bitmap. But that would mean writing every new bitmap of every change. Like if I select a point it changes color, same goes for line etc...


Solution

  • A simple optimization is not invoke Invalidate on each mouse move. I suppose you need show information under cursor. In that case, you can wait until cursor is stopped: save time and mouse position and, after some time (1 second, for example) if mouse position si the same, then invalidate. Is the same approach that usually you do when you make a search in a database after change text in some TextBox. Instead of making a query on each KeyPress, you wait a bit of time: if user continues writing, you don't make the query. After some time without changes in the TextBox, you perform the query.

    Another optimization is paint into a Bitmap the things that never change. For example, suppose that you paint:

    1 Blue background for the sea and brown for the land

    2 You paint a dot in each point of interest

    3 Next to that dots, you paint some icon (house, forest, clouds... something relevant for your case)

    4 You highlight the dots on mouse over

    5 You paint a bubble with text about that location

    You can paint 1, 2 and 3 in a bitmap because that information never change. Then, when you invalidate, instead of painting all the sea, land, dots... you paint your bitmap into the screen. And after that, you can paint other things (points 4 and 5). But you change paint 1, 2 and 3 of 2000 points for copy a bitmap. At the end, you are preprocessing and reusing things that you know that can be reused instead of paint one and again.

    If you can move in your map, you can divide your map in squares and process them separate. In this way, you can move and reuse many of this squares and only repaint new zones of your map.

    There are lots of things that you can do, but it depends on the details of your application.