This project has moved and is read-only. For the latest updates, please go here.

TileAsyncLayer Flicker

Topics: Algorithms, SharpMap v0.9 / v1.x, WinForms Controls
Dec 18, 2011 at 7:14 AM
Edited Dec 18, 2011 at 7:18 AM


I have updated my solution to the latest version of SharpMap v0.9 (AnyCPU).

I was just playing around with the TileAsyncLayer today. I have 2 layers, i.e., a vector layer with polygons from the SQL 2008 database and a label layer for these polygons. I have actually created a new custom map control that derives from the MapBox, so that it contains a toolbar for Zoom, Opacity, etc. along with a Title bar and a Legend bar.

As a new feature, the user can click on Google Map/Satellite button to add that as a background layer. I have got the transforms working and the map is displayed correctly. Hats off, you guys make this so easy!

In my derived MapBox, I am also doing extensive hit testing (NTS True Intersection testing) in the mouse events. As a result, I end up calling Refresh very often, which is fine because the number of features being displayed are relatively small in number and manageable.

But my problem now is that the TileAsyncLayer gets refreshed too! I do not want to refresh these layers if the user did not pan the map or change the zoom.

So how do I achieve this?


Dec 18, 2011 at 9:06 AM

when calling Refresh the map (including all layers gets redrawn).

Depending on what you want to do, most often its enough to call Invalidate(). That will redraw the control (not redrawing the layers) and call the OnPaint methods etc.

So, if not a layerredraw from datasource is required, you should call Invalidate()

Dec 18, 2011 at 11:03 AM

A layer redraw is indeed required. For example, the user can click on a polygon to select it, or double click to edit it. So, whenever a user clicks on a polygon, I need to redraw the layer so that the selected polygon has a different style applied to it.

But I don't want to redraw the background layers.


Dec 18, 2011 at 11:49 AM

OK, this has been discussed earlier if we should implement som caching strategy for every layer independently.

What you could do is:

* Modify the TileAsyncLayer to not redraw from source if the extent havn't changed
* Hook into OnPaint for MapBox and there call a method on you layers that draws only the selected features and instead use Invalidate(), this will however draw selected features on top of all other layers.

We could probably and an override to Refresh that does only redraw one or many specified layers.

Dec 18, 2011 at 12:56 PM
Edited Dec 18, 2011 at 12:57 PM
* Modify the TileAsyncLayer to not redraw from source if the extent havn't changed

How do I do that?

I tried adding the check in OnMapNewTileAvaliable method of TileAsyncLayer. It draws only the first tile and nothing else! Worse, after panning a little bit, the one tile that was drawn also is gone!

Dec 20, 2011 at 7:28 AM

Hello Kraghavk, why don't you just add a "selected" vector layer with a GeometryFeatureProvider as datasource.

If you add it to VariableLayerCollection, all you need to do is update the datasource and "touch" the timer.

That way you do not have to call refresh at all.

Hth FObermaier

Jan 8, 2012 at 3:50 PM
Edited Jan 8, 2012 at 3:50 PM

Hi FObermaier,

Sorry for the late response. Haven't looked at this project since Christmas.

Anyway, it's not just this problem. I have begun to notice other minor problems with the current implementation of TileAsyncLayer.

For instance, if the user is continuously zooming, you actually get to notice that the map redraws itself 3 to 4 times before displaying the final image for the current zoom level. There has to be a way to stop any currently running render threads, if the map is being refreshed again. I don't see any point letting the previous "Render" complete, when we are going to overwrite immediately!

Another usability issue because of background threads drawing onto the screen is, sometimes Pan seems to give incorrect feedback. Initially when you pan, a preview of the panned image is drawn. If OnMapNewTileAvailable event happens to fire at this time, the "Pan preview" is overwritten. So, for a moment, it looks like the map is not panning, while in fact it is in memory! Just that the image is being drawn incorrectly.

So, for me there seems to be 2 problems to be tackled:

  1. Provide a way to refresh only selected layers.
  2. Abort all currently running TileAsyncLayer.GetTileOnThread threads, if we are doing a complete refresh again immediately.

Will start fleshing out some code to handle these. Any guidance/directions for the SharpMap team is more than welcome. Once I am satisfied with the patch, I can submit it back to you guys.