Improving GdalRasterLayer rendering time

Topics: SharpMap v0.9 / v1.x
Developer
Mar 20, 2014 at 4:48 PM
The GdalRasterLayer can be refactored a little bit to allow to cache the image rendered in situations when the map or the layer are not changed. Suppose for example that there are a few layers showed on the mapbox, and the user makes changes to the other layers, why do we have to go though the process to render a new image for the background when it is not changed at all?

To achieve this goal we could simply cache the internal image created by the layer, and use it when the rendering context is not changed.
Coordinator
Mar 20, 2014 at 4:53 PM
I would say it's better to create a general cache-layer that can take any layer and cache it as long as the extent / zoom is not changed. I think this has been a topic before and there is some code for that in the discussion forum
Developer
Mar 20, 2014 at 5:13 PM
Edited Mar 20, 2014 at 5:18 PM
I agree, anyway that's a greater effort. I think that you can anyway start that path by changing the GetPreview method, or by adding a new one that returns the calculated Bitmap, this way we (as users) could add a bare bone caching logic inside the Render method of a subclass.
Coordinator
Mar 20, 2014 at 5:20 PM
Try GdalRasterLayerCachingProxy.cs
Developer
Mar 20, 2014 at 6:50 PM
Thank you, I didn't notice that class, you saved my life because I was trying to do the same approch to avoid the need to change the SM source. I used it successfully, this wrapper anyway misses two methods that I added by subclassing it, CoordinateTransformation and ReverseCoordinateTransformation, and it does not implement ICanQueryLayer, quite easy to solve it.
Editor
Mar 20, 2014 at 9:11 PM
i think a generic cache layer would be pretty easy to implement and is a good idea. I might knock one up quickly tomorrow to see if i can get it working.
Developer
Mar 21, 2014 at 9:27 AM
The problem here is that the render method uses directly the Graphics object, so I don't see any way to cache the result other than doing the same thing done on the GdalRasterLayerCachingProxy, that is redirecting the rendering onto a temporary bitmap and doing a merge on the real surface.

My idea is to provide a base implementation by removing from the existing GdalProxy all the methods of the raster layer, and then creating a proxy subclass for every layer.

If you implemented the INotifyPropertyChange on the base layer class (again, please add the partial attribute to every class) then the proxy class could just hook to the PropertyChange event to listen for any redraw need of any layer and the problem could be solved by just one class.

I have to do this soon, so if you have a better idea let me know.
Coordinator
Mar 21, 2014 at 11:08 AM
If you implemented the INotifyPropertyChange on the base layer class (again, please add the partial attribute to every class) then the proxy class could just hook to the PropertyChange event to listen for any redraw need of any layer and the problem could be solved by just one class.
This seems to be valid, could be done by PostSharp (AOP) (we do have an open source license for that)
Developer
Mar 21, 2014 at 11:50 AM
I don't like PS, it's just my taste of course, maybe I'm wrong, but the fact to be forced to use an external tool (and force the users) to enhance the c# compiler makes me wish to use a more powerfull language, like Nemerle :)

Ok the reasons for this hate: all these post-build tools make the devs happy, but they pay a small price, called build time. If there are alternatives I prefer to look at them.

Easing the devs with the INotifyPropertychange is a known problem, I like for example this solution:

http://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist

There are also good alternatives, but more complex, that go through a factory class that uses custom attributes attached to properties to build proxies at runtime with all required logic. It's still AOP, done with factories rather than a postbuild action.