Tuesday, October 29, 2013

UTFGrid in Bing Maps (Part 1 - Introduction)

Part 1 - Introduction
Part 2 -Bing Maps Module

UTFGrid is a technology that provides the ability to have client-side interaction over raster map-tiles. Everything is very well explained in this page (which includes a working example), but the idea is simply to have an accompanying JSON file for each map-tile containing meta-information about that image. This info is also very fast to handle in client-side.

For instance, assuming this raster tile which contains Great-Britain:


The accompanying UTFGrid file will have something that looks like an ASCII-Art representation of the image (albeit a little bit stretched):


                                 !!!! !! !!!!!!!!!!!!!!!!!!!          
                                 !!!  !!! !!!!!!!!!!!!!!!!!!!         
                                  !  !!!!! !!!!!!!!!!!!!!!!!!!        
                                     !! !! !!!!!!!!!!!!!!!!!!!        
                            ##       !!    !!!!!!!!!!!!!!!!!!!        
                          #####  !!! !    !!!!!!!!!!!!!!!!!!!!        
                       ########!!!!!      !!!!!!!!!!!!!!!!!!!!        
                      #######!!!!!!!!    !!!!!!!!!!!!!!!!!!!!!!       
                     #######!!!!!!!!!    !!!!!!!!!!!!!!!!!!!!!!       
                      ######!!!!!!!!!!   !!!!!!!!! !!!!!!!!!!!!       
                    ########!!!!!!!!!!   !! !!!!  !!!!!!!!!!!!!!      
                    ######!!!!!!!!!!!!!   !  !    !!!!!!!!!!!!!!      
                      ####!!!!!!!!!!!!!!          !!!!!!!!!!!!!!!!!   
                      ##!!!!!!!!!!!!!!!!          !!!!!!!!!!!!!!!!!!  
              #  #   ####!!!!!#!!!!!!!!!    $$    !!!!!!!!!!!!!!!!!!  
            ##############!!!###!!!!!!!    $$$     !!!!!!!!!!!!!!!!!! 
            ###############!!####!!!!      $$$      !!!!!!!!!!!!!!!!!!
            ########################!      $$       !!!!!!!!!!!!!!!!!!
            ###################### #                 !!!!!!!!!!!!!!!!!
              #####################                  !!!!!!!!!!!!!!!!!
              #####################                  !!!!!!!!!!!!!!!!!
             #######################                 !!!!!!!!!!!!!!!!!
            ########################                !!!!!!!!!!!!!!!!!!
            ########################        !!      !!!!!!!!!!!!!!!!!!
              ######################       !!!!!!!!!!!!!!!!!!!!!!!!!!!
               ### #################        !!!!!!!!!!!!!!!!!!!!!!!!!!
              ## ###################         !!!!!!!!!!!!!!!!!!!!!!!!!
                #####################        !!!!!!!!!!!!!!!!!!!!!!!!!
                ####################       !!!!!!!!!!!!!!!!!!!!!!!!!!!
                ####################       !! !!!!!!!!!!!!!!!!!!!!!!!!
               #####################           !!!!!!!!!!!!!!!!!!!!!!!
             ######################            !!!!!!!!!!!!!!!!!!!!!!!
              #####################            !!!!!!!!!!!!!!!!!!!!!!!
              #####################            !!!!!!!!!!!!!!!!!!!!!!!
           ########################           !!!!!!!!!!!!!!!!!!!!!!!!
          ######################           !!!!!!!!!!!!!!!!!!!!!!!!!!!
            ################             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           ################             !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           ##############                !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            ###########                 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            ##########                   !!   !!!!!!!!!!!!!!!!!!!!!!!!
              #####                              !!!! !!!!!!!!!!!!!!!!
                                                  !!!!!!!!!!!!!!!!!!!!
                                                !!   !!!!!!!!!!!!!!!!!
                                           !  !!!!!!!!!!!!!!!!!!!!!!!!
                                            ! !!!!!!!!!!!!!!!!!!!!!!!!
                                            !!!!!!!!!!!!!!!!!!!!!!!!!!
                                            !!!!!!!!!!!!!!!!!!!!!!!!!!
                                           !!!!!!!!!!!!!!!!!!!!!!!    
                                          !!!!!!!!!!   !!!!!  !!      
                                         !!!!!!!!!!     !             
                                         !!!!!!!!!!                   
                                       !!!!!   !!!                    
                                      !!!!!                           
                                      ! !!                            
                                  !     !                             
                                                                      
                                                         % && &&      
                                                            &&&&      
                                                       %%  &&&&&      
                                                            &&&&&&&&& 
                                                         ''  &&&&&&&&&
                                                          '  &&&&&&&&&
                                                             &&&&&&&&&

The file also contains a dictionary which maps these characters to the items they represent. Thus, in this particular case the following mappings exist:
  • ! maps to United Kingdom
  • # to the Republic of Ireland.
  • $ to Isle of Man
  • % to Guernsey (I actually have a colleague that lives there)
  • ' to Jersey
  • & to France
Last, but not least, the file also includes a dictionary with some meta-info for those "objects". For instance, as we're talking about countries it could include stuff like "name", "population", "area", "average earnings", etc.

Unfortunately there's no support for UTFGrid in Bing Maps, hence the reason for me writing this particular blog post.

Let me start by showing the end-result. Open the following page:

Demo #1

When moving the cursor over the map you should see the name and population of the corresponding country. All of this in real-time without requiring additional round-trips to the server.

Obviously this could also be useful to represent points. I've added some cities to the previous map on the next example:

Demo #2

This example contains a ton of points, but could easily scale to 10 times that. That's the beauty of this approach: as the points are rendered on the images themselves they don't bring any performance impact to the overall map.

How this was implemented:

Creating the map itself is outside the scope of this particular post. If you want to can check my previous post on using TileMill here, as the main idea is the same.

The code should be more-or-less straightforward, but the main parts are:
  • I've declared the UtfGrid using a TileLayer. I've specified a TileSource like this
var tileSource = new MM.TileSource({
    uriConstructor:  function getTilePath(tile) {

        var key = tile.levelOfDetail + "_" + tile.x + "_" + tile.y;

            if(_cache[key] == undefined) {
                loadUtfGridForTile(tile, urlTemplate);
            }

        }});
var tileLayer = new MM.TileLayer({ mercator: tileSource});
The idea is to have the getTilePath method call my the utfgrid file and store it locally for each retrieved tile.
  • The request itself is done in JSONP with the reqwest lib.
  • The trickiest code is the one that determines the x/y position of the cursor on a particular tile:

var zoom = map.getZoom();
var mouseX = e.getX();;
var mouseY = e.getY();

var point = new MM.Point(mouseX, mouseY);

var loc = map.tryPixelToLocation(point);

var worldpixel = LatLongToPixelXY(loc.latitude, loc.longitude, zoom);
var tileX = worldpixel.x / 256.0;
var tileY = worldpixel.y / 256.0;

var x = (tileX - Math.floor(tileX)) * 256;
var y = (tileY - Math.floor(tileY)) * 256;

Anyway, just view the source of the examples if you need any additional info.

Next Steps
I intend to polish this code and package it into a Bing Maps Module, as I believe it could be useful for a ton of scenarios.

Update (2013-11-16): just created a post with that. Part 2.


No comments:

Post a Comment