Wednesday, April 7, 2010

Porting SharpMap to Silverlight - first attempts

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.

First, I removed all the files that I didn't need. I included only those that I needed to retrieve data (shapefiles) and render a map.

System.Drawing
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.

System.Data
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.

System.Xml
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:

  1. Raster. This would work just fine but my purpose was to implement vector rendering to SL, I had raster already working in BruTile.
  2. Vectors read from db or file. This is not allowed from the SL sandbox.
  3. 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.

Finally Rendering
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.

So far it seems there are not many complications. I am currently investigating how I could use System.Data for the file and db data providers, while having a System.Data free Silverlight version. I believe it is possible to also support WPF and WinForms without too much maintenance. Support for Windows Phone 7 should be easy.

1 comment:

HFisher said...

Hi Paul,
I am looking to use SpatiaLite in a WP7 app using SilverLight in MS Visual Studio 2010 Express for Windows Phone.
Since SharpMap has a link with SpatiaLite and you have successfully ported SharpMap to SilverLight, I am wondering the following...
Do you think it is possible to produce a WP7 app using SharpMap with SpatiaLite database?

Regards Hayden