Over the last week I spend some time porting open source GIS library SharpMap V1 to Silverlight. My intent was to go straight towards a working version in the easiest and quickest way and try to suppress my urge to redesign. Below is how I worked through it. It might be relevant for those who have to do a similar port.
Silverlight has no System.Drawing (GDI), so my next goal was to move this into a separate dll while maintaining all functionality. I created an IRenderer interface in SharpMap and used the existing GDI rendering for the implementation. I put this in a separate assembly called GdiRendering.dll.
The IStyle class in SharpMap also depended on System.Drawing. I replaced all the System.Drawing classes in IStyle with implementation independent classes. These were converted to System.Drawing classes in the GdiRenderer.
For raster renderers there was no separation between data retrieval and rendering at all. So I introduced an IRasterProvider and an IRaster class. In the GdiRenderer this IRaster type was treated in the same way as the geometry types.
At that point all GDI was contained in the GdiRenderer.dll and I could remove the System.Drawing dll from SharpMap. Everything worked like at the start. There was no WPF or Silverlight yet.
Next was System.Data. There is none in Silverlight, so no DataTable or DataRow, yet the IProvider interface heavily depends on it. I spend some time looking for a good solution here. I was expecting to find some simple grid-like data structure, but I ended up using a List of FeatureDataRow for the table and derived FeatureDataRow from Dictionary. The downside here is there is no restriction on adding columns, you could add anything you like to it. I am open for better (and simple) solutions.
With that settled I was about to set up a Silverlight data provider so I could start on my SilverlightRendering.dll. But which provider? It turns out that the current SharpMap data providers fall in into three categories:
- Raster. This would work just fine but my purpose was to implement vector rendering to SL, I had raster already working in BruTile.
- Vectors read from db or file. This is not allowed from the SL sandbox.
- Vectors retrieved from web. That’s what I need but it turns out they all depend on XmlDocument which is not part of Silverlight.
I worked around this problem by using WPF rendering and a file based data provider. I created two project files for my SilverlightRendering.dll, one SL, one WPF, that share the same files. I developed my renderer using the WPF version. So far I have only compiled my SL version, I have yet to find out if it actually works.
With the WPF version of the SilverlightRendering.dll I managed to render Points, MultiPoints, LineStrings, MultiLineStrings, Polygons and MultiPolygons. I was happy to see that it is also possible to render Polygons with holes, this could have been a been a show stopper for a proper gis lib. The renderer currently ignores projections but there is a Silverlight version of proj.net on http://projnet.codeplex.com.