Using SharpMap as a Google Earth Network Link

Since Google Earth is so popular, I thought why not join in and have SharpMap serve maps for GE? It is quite simple to make your own GE Network Link, and here are a few pointers, and you can download a demo web application you can use as well.

The GE Network Link basically works by requesting an XML webpage (well Google calls it KML), telling GE where to get the image tiles and where they should be placed on the globe. GE also adds a 'BBOX=minx,miny,maxx,maxy' querystring to the request so you can return a custom KML response containing the most appropriate tile(s). A response could look like this:

<?xml version="1.0" encoding="UTF-8" ?>
<kml xmlns="
http://earth.google.com/kml/2.0">
<Document>
  <open>1</open>
  <GroundOverlay>
    <open>1</open>
    <Icon>
      <href>http://localhost/TileServer.ashx?BBOX=-180,-90,0,90&size=512</href>
    </Icon>
    <LatLonBox>
      <north>90</north>
      <south>-90</south>
      <east>0</east>
      <west>-180</west>
      <rotation>0</rotation>
    </LatLonBox>
  </GroundOverlay>
</Document>
</kml>

You can add as many "GroundOverlays" as you like. For instance you can cover a requested BBOX with as many tiles as you like. That way you can increase the image size/resolution or cover a larger or smaller area than initially requested while getting quicker responses. You can read more about the KML format here.

Creating the KML is pretty straight-forward in ASP.NET, so I wont cover that here (but download the example and see for yourself).

Creating the image tile is easily done using SharpMap. Add an HttpHandler to you webpage, and create the following ProcessRequest method to render and return the map:

public void ProcessRequest(HttpContext context)

{

    //Get tilesize in request url

    int tilesize = int.Parse(context.Request.QueryString["size"]);

    //Get boundingbox requested

    string[] strbox = context.Request.QueryString["BBOX"].Split(new char[] { ',' });

    SharpMap.Geometries.BoundingBox box = new SharpMap.Geometries.BoundingBox

            (double.Parse(strbox[0]), double.Parse(strbox[1]),

            double.Parse(strbox[2]), double.Parse(strbox[3]));

 

    //Call custom method that sets up the map with the requested tilesize

    SharpMap.Map myMap = MapHelper.InitializeMap(new System.Drawing.Size(tilesize, tilesize));

    //Center on requested tile and set the appropriate view width

    myMap.Center = box.GetCentroid();

    myMap.Zoom = box.Width;

 

    //Render the map

    System.Drawing.Bitmap b = (System.Drawing.Bitmap)myMap.GetMap();

    //Create a PNG image which supports transparency

    context.Response.Clear();

    context.Response.Expires = 10000000;

    context.Response.ContentType = "image/png";

    System.IO.MemoryStream MS = new System.IO.MemoryStream();

    //Set background to the transparent color which will be see-through in Google Earth

    b.MakeTransparent(myMap.BackColor);

    b.Save(MS, System.Drawing.Imaging.ImageFormat.Png);

    byte[] buffer = MS.ToArray();

    //Send image response

    context.Response.OutputStream.Write(buffer, 0, buffer.Length);

    // tidy up 

    b.Dispose();

    context.Response.End();

}

The last thing we need to do is add the network link to GE. The easiest way to do this is to do this from within GE. From the menu Select Add –> Network link. Type a name for your network link and set the location to the URL of the XML service. Under “View-Based Refresh” , set the “When” parameter to “After camera stops”, and click OK, and you should be set to go !

Unfortunately GE doesn't provide you with the same smooth image transitions that it use for its own tiles, so you will have to do with the rather crude way of showing big red squares until the tiles have been loaded. Furthermore the BBOX GE requests isn't always very accurate, especially if you are looking south at an angle you will notice the BBOX is very much off.

The small demo application you can download below shows a world map with each country’s population density shown on a colorscale from blue to red. Copy the files to a virtual directory (make sure it runs as its own web-application, at least the sub-folders are located at the root of the webapplication). Set the network-link to point to the URL of the default.aspx page.

Download GoogleEarthServer.zip (270,65 KB)

GE also supports vectordata to be served as KML. It could be interesting to see who comes up with a "SharpMap KML Vector Server" first :-)

Comments (1) -

  • Nice work Morten!

    looks like a charm!

    Is there any possibility to do bring google maps into sharpmap. as raster layer
    for example?

    BR
    Christian

Add comment