Posted by: murrayhking | July 16, 2010

touchMapLite framework notes


Having looked at openlayers, we had problems with performance on mobile devices.  A latency problem especially  when dragging/panning the map.

A new framework has recently appeared that addresses that issue called touchMapLite.
http://wiki.openstreetmap.org/wiki/TouchMapLight

touchMapLite screen shot from iphone

touchMapLite screen shot from iphone

Its very lightweight at (35k) and based on the pano.js library http://code.google.com/p/panojs/.
Its in the early development stage but we were impressed with it.

Conversely, Openlayers 2.8 is about 700k, although you can optimise this by using a build script to specify only the javascript files your setup requires. For us, that typically reduces our openlayers lib to about half the size.

Of course you are losing a lot of potential functionally when compared with openlayers and it has great documentation. If you just care about rendering performance and maybe basic use of markers then this small library might be the way to go. There isn’t much in the way of documentation with touchMapLite although there are some helpful samples that come with the source.

Another caveat is the type of map source you are displaying for example one source we are using is in British National Grid EPSG:27700 projection with units in meters.

So we had to override some fairly low level functions to cope with this projection. We had to use our own javascript utilities (the coordamatic library) for unit and projection changes to get it working eg

projection changes

touchMapLite.js

latlon2pan: function(lat,lon) {
//use uk national grid
var coords ;
coords = this.natgrid.toLocalSystem(lat, lon);

var northings = coords[0];

var panNGLat = 1-(northings/this.EXTENT);

var eastings = coords[1];

var panNGLon = eastings/this.EXTENT;

return {x: panNGLon, y:panNGLat};
}

NOTE. So the actual units range required by the underlying rendering engine are 0.0 – 1.0

so x=0.5,y=0.5 would give you the centre of the map near equatorial guinea.

unit changes

touchMapLite.tileUrlProvider.WMS.js

resolutionAtZoomLevel: function(zoom){

return this.initialResolution / Math.pow(2,zoom);
}
pixelsToMetersAtZoom: function(ptPixels, zoom)
{
var resolution = this.resolutionAtZoomLevel(zoom);
var ptMeters  = ptPixels * resolution;
return ptMeters;

},
//create the wms bounding box
//convert google y to TMS   =  (2**zoom - 1) - tygoogle

var ytms  =(Math.pow(2, zoom) -1) – yIndex;

var bbLeftMeters = this.pixelsToMetersAtZoom(xIndex * this.tileSize, zoom );
var bbRightMeters =  this.pixelsToMetersAtZoom( (xIndex+1) * this.tileSize, zoom );
var bbTopMeters =  this.pixelsToMetersAtZoom( (ytms+1)  * this.tileSize, zoom );
var bbBottomMeters =  this.pixelsToMetersAtZoom( ytms * this.tileSize, zoom );

So we had a quite bit of work to get one of our map sources to work with it.

in openlayers you can simply this declare this at map construction time.

var map = new OpenLayers.Map('map',
 { projection: new OpenLayers.Projection("EPSG:27700"), units: "m",
maxExtent: bounds, resolutions: [2000,400,100,50,25,10.16,5,2.5,0.625]});

However this might not be a very common use case and if you are just using common map sources …

Google,TMS and WMS,lat, long, Spherical Mercator projection it should work out the box.
However the performance difference is noticeable between the two libs. touchMapLite gives a user experience closer to a native application.

Potential off-line application?

There is code in touchMapLite that uses some HTML5 storage features. HTML5 canvas is used to base64 requested images and store them in a client-side SQL database. This would be a nice feature for an off-line application for use when travelling to remote parts of the country for field trips, hillwalking etc. I suppose you could use a cache.manifest instead when you are sure of the locations of your tile images but this technique would lose the flexibility of the canvas/sql approach.

fetchTileFromCache: function(image,z,x,y,src)
{

var tileObject = new Object;

tileObject.image = image;
tileObject.provider = this.id;
tileObject.x = x;
tileObject.y = y;
tileObject.z = z;
tileObject.src = src;
tileObject.tiles = this;

if(this.db){ //  && document.getElementById('cache') && document.getElementById('cache').checked
this.db.transaction(function (tx)
{
tx.executeSql("SELECT data FROM tiles WHERE
provider = ? AND x = ? AND y = ? AND z = ?",
 [tileObject.provider, tileObject.x, tileObject.y, tileObject.z], function(tx, result) {
if(!result.rows.length){

tileObject.tiles.populateCache(tileObject);
} else {

tileObject.image.src = result.rows.item(0).data;
}
}, function(tx, error) {

tileObject.tiles.populateCache(tileObject);
});

});
} else {
image.src = src;
}
}


touchMapLite screen shot from iphone

touchMapLite screen shot from iphone

Here is our example of using touchMapLite using a WMS map source.
http://mab.edina.ac.uk/geomobile-test/osopen.html

It uses the ordnance survey products stack which has been recently been made freely available. https://www.ordnancesurvey.co.uk/opendatadownload/products.html.
We have used a local map-server installation to serve up the osopen stack.

Advertisements

Responses

  1. […] mapping app using OpenLayers. We also created a mobile app using this datasource, as desribed in a previous post on the TouchMapLite […]

  2. This is pretty slick… I’m going to give it a shot with some of my mapdata.

  3. can i create this open layer application in iphone without using phone gap. i just want to use this open layer application which is build from my own xcode native codes? can i do that thing in xcode.
    please reply me.

    • You could probably embed a UIWebView component in your app and display your openlayers map within that keeping you native for the app store and the likes.

  4. Pretty great post. I just stumbled upon your weblog and wanted to
    say that I have really loved surfing around your
    weblog posts. In any case I will be subscribing in your
    feed and I’m hoping you write once more soon!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: