Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Creating an Interactive Map in ASP.NET 2.0 Using SharpMap

0.00/5 (No votes)
25 Nov 2005 1  
An article on how to create a web map application using SharpMap in ASP.NET 2.0.

Introduction

Showing maps on the web is becoming more and more common. The most well-known ones are Google Maps and Microsoft's Virtual Earth. Creating your own websites with interactive maps require you to get hold on the map-data and convert this data to dynamically generated images to be displayed in a webpage. This article covers the basics of map data and uses the free .NET 2.0 map engine SharpMap for generating maps in an ASP.NET 2.0 application.

Background

Although this article is not meant as a big tutorial on how the Geographic Information Systems and the map data work, a few primers are necessary if you are new to this area. Map data can be divided into two categories: Vectordata and rasterdata. One example of rasterdata is satellite imagery, like the ones available on the Google Maps. Although there are several other kinds of rasterdata, images of the real world are among the most common.

Much of the map data we know are just a simple representation of the world as we know it. For instance, can a road be represented by a line, a lake by a polygon, and a train station as a point. Having data available as vectordata makes it easy to render your own maps with your own colors and styles, size and zoom level, and you are free to select the data you want, or if there is something you want to leave out.

The biggest problem is often to get hold on the data (especially the good and the detailed ones). It is expensive to make and maintain them, so the data-owners often tend to demand money for it. There are several countries (including the United States) that give away their national maps for free, so check out with your national cadastre and if they give any data away. There are also several websites offering free map data. I haven't included any map data in the example, since I wouldn't risk overlooking any limitations in some of the free data available on the net, so you would have to find some data yourself to test the example in this article.

One thing you have to be aware of is that even if you get data from different sources they are stored in the same coordinate system, datum and projection. If they aren't they won't match up when you put them together.

The most well-known coordinate system is the longitude/latitude system representing a coordinate anywhere on the earth using decimal degrees. Other systems are only meant for local areas using meters as units, and so on. The datum defines the shape of the earth by approximating it as an ellipsoid. Since the Earth isn't an ellipsoid, some datums are created to fit local areas with a small error, while others try to fit with an average of the whole Earth. The most popular one is the WGS84 (World Geodetic Datum 1984), which is used by the Global Positioning System. Having data in different datums can cause large shifts in the data, so having all your data in the same datum can be crucial. The last thing you should be aware of is the projection. The projection defines how the ellipsoid is mapped onto a flat piece of paper. There are a bunch of projections, some made to preserve angles, some preserve area, etc.

Transforming your vectordata into a bitmap viewable in a browser requires you to transform the polygons, lines and points from a world coordinate system into an image coordinate system, and rendering them object-by-object on the bitmap.

SharpMap is an engine that helps you render the vectordata onto a bitmap that can be stored on the disk or sent to a browser. SharpMap is developed on .NET 2.0 platform and uses GDI+ to render the objects you specify, and you have all the great GDI+ brushes and pens at your disposal. Currently, it supports reading the ESRI Shapefile format (which is the most common) or reading directly from a PostGreSQL Spatial database, but can easily be extended to read more formats through its provider model. SharpMap also supports ECW and JPEG2000 raster images and retrieving data from external WMS servers, which won't be covered here.

SharpMap is free and can be downloaded from its webpage.

Using the Code

The basic usage of SharpMap consists of defining your layers of data, the styles they should render with, defining the view and in the end the actual rendering of the map. Creating an interactive map application, requires you to send a map to the browser, and handle the click-events on the image, so that he or she can zoom or pan the map:

//Defining a layer


SharpMap.Layers.VectorLayer layCountries = 
      new SharpMap.Layers.VectorLayer("Countries");
//Set the datasource to a shapefile in the App_data folder


layCountries.DataSource = new SharpMap.Providers.ShapeFile(
      Server.MapPath(@"~\App_data\countries.shp"), true);

The above code defines a new data layer named "Countries" and points the DataSource to a ShapeFile containing the countries of the world. The true-parameter in the DataSource specifies that the SharpMap should use a file-based Spatial Indexer. The spatial index will help SharpMap render the maps much faster by using the spatial index to quickly find the objects visible in the view. The index can take several seconds to create, so using a file-based index will allow SharpMap to store a spatial index on the disc for faster load-times later when the application is restarted. When working in an ASP.NET context, the index is stored in memory throughout the lifetime of the application, so this is an issue after the application_start event. Secondly, we need to define the style of the layer:

//Set fill-style to green


layCountries.Style.Fill = new SolidBrush(Color.Green);
//Set the polygons to have a black outline


layCountries.Style.Outline = System.Drawing.Pens.Black;
layCountries.Style.EnableOutline = true;

The country layer will now render with a green fill, with black borders. You could also use a TextureBrush to fill it with an image or any other brush that GDI+ offers. Let us add a rail-road theme as well. Usually a rail-road is represented as a thick dotted line. We can do this by adding the following code:

//Defining a railroad


layer SharpMap.Layers.VectorLayer layRail = new
//Set the datasource to a shapefile in the App_data


SharpMap.Layers.VectorLayer("Railroads"); 
folder layRail.DataSource = 
    new SharpMap.Providers.ShapeFile(
        Server.MapPath(@"~\App_data\railroads.shp"), true);
//Define a black 3px wide pen


myRail.Style.Line = new Pen(Color.Black,3);
//Set a dash-pattern


myRail.Style.Line.DashPattern = new float[] { 4.0f, 2.0f };

Lastly, we need to define our map and add the layer to it:

//Create a map rendering initialized 400 x 200 pixels


SharpMap.Map myMap = new SharpMap.Map(new Size(400,200));
//Add the layer


myMap.Layers.Add(layCountried);
//Zoom the map to the extents of all added layers:


myMap.ZoomToExtents();
//Render the map


Image imgMap = myMap.GetMap();

And that's it ! Now grab hold of the imgMap and do whatever you want with it. You can stream it to a browser, save it to disk, print it, etc. Luckily, SharpMap has some helper-classes for sending the image to the browser and standard ASP.NET methods can help us to easily create an interactive map in a browser. SharpMap has classes for storing a map in the cache, and an HttpHandler for retrieving it again. To enable the HttpHandler, add the following handler to your web.config file, by adding a verb to the HttpHandler settings:

<?xml version="1.0"?>
<configuration>
    <system.web>
        <httpHandlers>
            <add verb="*" path="GetMap.aspx" 
                type="SharpMap.Web.HttpHandler,SharpMap"/>
        </httpHandlers>
    </system.web>
</configuration>

This will make SharpMap handle any request to the file GetMap.aspx. You can of course change the path attribute to anything you like to avoid any conflicts with the existing pages. Now all we have to do is feed our generated image to SharpMap's cache and return a path to the browser. When storing the image in the cache, SharpMap returns an ID of the map that you can use to send to the client, as shown below:

//Place the map in the cache and leave it 


//there for 5 minutes


string imgID = SharpMap.Web.Caching.InsertIntoCache(5, 
                    imgMap, Session.SessionID, Context);
//Set the ImageUrl of our ASP.NET image-control to the 


//handler and the returned ID


imgMap.ImageUrl = 
   "getmap.aspx?ID=" + HttpUtility.UrlEncode(imgID);

If you change the ASP.NET image to an ImageButton instead, the client can click the map, and you can request the point where the client clicked. So all we have to do to react to the click, is to get the click coordinate from the event, convert it from image coordinates to world coordinates and react accordingly. Clicking the map would normally result in centering on the click point and zoom in/out if the user has chosen to zoom. This is done by setting the Zoom and Center properties of the map:

protected void imgMap_Click(object sender, ImageClickEventArgs e)
{ 
    //Center map


    myMap.Center = SharpMap.Utilities.Transform.MapToWorld(
                   new System.Drawing.Point(e.X, e.Y), myMap);    
    //Zoom in 2x


    myMap.Zoom *= 0.5;
    //Call function that renders the map and returns 


    //it to the client


    CreateMap();
}

The zoom-value defines the width of the map in world coordinate units. In a longitude/latitude based map, zooming to the extents of the world would require you to set the zoom to 360. We can easily add a set of radio-buttons where the user can select either "Pan," "Zoom in" or "Zoom out." The zoom-value is then set according to the selected tool. I have implemented this approach in the example.

Points of Interest

There are still a lot of features in SharpMap that haven't been covered, and I will later cover some of the aspects of tuning the rendering speed, creating advanced layout, utilizing connection-pooling and combining maps with data from online resources and an AJAX approach. Developing SharpMap has been a great experience, and the hands-on work has taught me much more about the API design, generics, other new .NET 2.0 features, than any book has done (and there is still much work to be done and much more to be learnt). I've also been amazed by the speed and quality you can get by just using GDI+ for rendering your map.

History

  • 24th November, 2005 - initial article version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here