Slippy maps

I’ve been looking at Javascript, googlemap-like maps. It seems that these are called “slippy maps”.

There’s some useful information of the Openstreetmap wiki here.

They recommend a few Javascript libraries, including LeafletJS and OpenLayers. I tried OpenLayers first, but it’s pretty big, just to get the examples working from github I’d need node.js/JVM etc…

I decided to play with LeafletJS, it was a lot quicker to get the examples working!

The LeafletJS demo pulls tile images from URLs that look like this:

https://c.tiles.mapbox.com/v3/examples.map-i875mjb7/13/4094/2724.png

I sptent some time trying to figure out how coordinates are translated into the URL. The above representing a tile near [51.505, -0.09] at zoom level 13. The 13 is obvious enough. However the latitude and longitude took some googling.

It seems that pretty much all mapping services use the Spherical Mercator projection (see wikipedia and openstreetmap ). There are a bunch of tools for making tile sets (particularly from flat images).

Anyway, I wanted to make my dataset manually at first to try things out. I created a directory structure that looks like this:

./13/4094/2723.png
./13/4094/2724.png
./13/4095/2723.png
./13/4095/2724.png
./13/4092/2723.png
./13/4092/2724.png
./13/4093/2723.png
./13/4093/2724.png

And used a modified version of the LeafletJS example, telling it to pull data from my server:

<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8" />

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <link rel="stylesheet" href="leaflet.css" />
</head>
<body>
        <div id="map" style="width: 600px; height: 400px"></div>

        <script src="leaflet.js"></script>
        <script>

                var map = L.map('map').setView([51.505, -0.09], 13);

                L.tileLayer('http://192.168.0.12/maptest/{z}/{x}/{y}.png', {
                        maxZoom: 18,
                        attribution: '41j',
                        id: 'example'
                }).addTo(map);


                var popup = L.popup();

                function onMapClick(e) {
                        popup
                                .setLatLng(e.latlng)
                                .setContent("You clicked the map at " + e.latlng.toString())
                                .openOn(map);
                }

                map.on('click', onMapClick);

        </script>
</body>
</html>

This worked pretty well, and gives me a basis for trying other stuff out.

Notes

The C code which performs this conversion replicated from the OSM wiki is as follows:

#include <math.h>
#include <iostream>

using namespace std;

int long2tilex(double lon, int z) 
{ 
	return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z))); 
}
 
int lat2tiley(double lat, int z)
{ 
	return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z))); 
}
 
double tilex2long(int x, int z) 
{
	return x / pow(2.0, z) * 360.0 - 180;
}
 
double tiley2lat(int y, int z) 
{
	double n = M_PI - 2.0 * M_PI * y / pow(2.0, z);
	return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
}

int main() {
  cout << long2tilex(-0.09,13) << endl;
  cout << lat2tiley(51.505,13) << endl;
}

Some data sources I’ve been thinking about look at.

OSM Data:
http://planet.openstreetmap.org/

Oil GIS Data:
https://www.gov.uk/oil-and-gas-offshore-maps-and-gis-shapefiles#offshore-gis-data

Comments are closed.