Creating a Custom Map

Tags: Tutorial, Google Maps, Custom Map

Google Maps come with very detailed satellite maps for most of the globe and are expanding their road map coverage almost daily so the need to make your own custom map using your own map graphics may not be necessary. But if you want to show a historical map, a fantasy map, augment Google's map or something else this tutorial is for you. I will go through the steps of making a custom map. The tutorial will be in two parts, the first will focus on setting up your map page, while the second will show you how to set up your tile server. I will write a seperate tutorial on how to display WMS maps.

Before you begin to set up your custom make sure you are entitled to use the images you are publishing.

A normal map holds the three built-in map types from Google, normal map, satellite map and hybrid map. These are represented by the GoogleNormalMap, GoogleSatelliteMap and GoogleHybridMap, respectively.

A custom map is essentially a holder for the different tile layers that make up the map. The first two of the above map types has only one tile layer each and in the Google Maps .NET Control these tile layers are represented by the built-in NormalMapTileLayer and SatelliteTileLayer. The hybrid map consists of two tile layers, the SatelliteTileLayer and the built-in StreetMapTileLayer. These tile layers can be combined with custom tile layers created from the CustomTileLayer class into a custom map from the CustomMapType class.

To create a custom tile layer you can use either a tile layer from the WMSTileLayer class (covered in another tutorial) or the GoogleTileLayer class. In this tutorial we will use a pre-defined tile layer (NormalMapTileLayer) and create our own using the GoogleTileLayer class. The GoogleTileLayer class uses Google style map tiles, but can be modified easily. At minimum you will need to provide an ID and a URL for the map tile server. You can also restrict the available zoom levels and it is a good idea to set the IsPng property to true if you are using .png files for your tiles (the default is false, setting it to true displays the png files properly in Internet Explorer).

NormalMapTileLayer ntl = new NormalMapTileLayer("ntl");

GoogleTileLayer gtl = new GoogleTileLayer();
gtl.ID = "gtl";
gtl.IsPng = true;
gtl.MinZoomLevel = 0;
gtl.MaxZoomLevel = 17;
gtl.Version1ZoomOrder = false;
gtl.BaseUrls.Add("http://www.reimers.dk/demos/mapbase2.aspx?");

As you can see the predefined tile layer requires no further ado. The GoogleTileLayer properties are easy to set and that is all that is required to create your custom tile layer.

Next step is to create your custom map type using the CustomMapType class. To make it work you will need to give it a unique ID and set some name to display in the map type control (unless you don't use the map type control). Apart from that all you need to do is to add the tile layers you want to use for the custom map. Watch out that you add them in the right order. The tile layers are ordered according to the index number in the custom map's Layers collection, i.e. index 0 is under index 1 etc. To create a custom map using the above tile layers with the normal map below we could use the following code:

CustomMapType cmt = new CustomMapType();

cmt.ID = "cmt";
cmt.Name = "XML Demo";
cmt.Layers.Add(ntl);
cmt.Layers.Add(gtl);

Now that we have our custom map we need to tell the control to render it. By default the control displays the three default map types, but this can be modified by altering the MapTypes collection in the map options. For the purposes of this demo we will simply show the custom map and so will clear the other maps and add our custom map, like so:

GoogleMap1.Options.MapTypes.Clear();
GoogleMap1.Options.MapTypes.Add(cmt);

This is almost it. Now we need to set up the page that serves the map tiles. To do this we need to create a file (either an .aspx page, but probably more suitably an .ashx handler) that reads the tile request and returns the right tile file. This is done by reading the x, y and zoom values in the request's querystring and then finding the corresponding file. The response stream is cleared  and the file is sent in its place as if the file itself had been requested, like so:

protected void Page_Load(object sender, EventArgs e)
{
	string x = Request.QueryString["x"];
	string y = Request.QueryString["y"];
	string z = Request.QueryString["zoom"];
	string mapfile = String.Format("/demos/x{0}y{1}z{2}.png", x, y, z);

	if (!System.IO.File.Exists(Server.MapPath(mapfile)))
	{
		mapfile = "/demos/black.png";
	}

	Response.Clear();
	Response.ContentType = "image/png";
	Response.WriteFile(Server.MapPath(mapfile));
	Response.End();
}

Once these steps have been taken you should have your custom map up and running.

Latest Tweets