Dont afraid maps. Google maps v3, v2, ovi, yandex maps. Maps is your friend. Try them, love them. I`ll show how to cook them

Wednesday, March 17, 2010

I`ll carve you into tiles

Mission:Make loading a bit faster, and a bit cleaner

Goal:Load data in set of information tiles

loading data blocks via custom map type

Step 1. Load data into map

Lets request server for tiles in visible viewport



$.get("ajax/load-map-data?SE="+MySECorner.toString()+"&NE="+MyNECorner.toString()+"&zoom"+currentZoom,

      function(data){

        //wow! i got the data for map!

        //forwhole visible viewport( and just for it)

      });


Step 2. Kill users, server and youself

Just answer two single things
  • will you rerequest data if maps is moved by pixel
  • can you cache request
If first answer is "no" and second is "no" - close this page. You allready find nirvana :)

And if you still here - you loading your data in wrong way, yet. Until now.

Step 3. How google loads image for tiles?

He(it?) loads it in.. tiles, segments 256x256 pixels :)

Step 4. Think! Why not to do same?

If you load you marker data in set of tiles -
  • you can Perfectly cache them
  • Map shift below 256px will not produce any requests to server
  • Normal browser can perform 4-6 request to one server at one moment, so you`ll ask tiles in parrallel, 4-6 times faster
Define your own tile source, not for image tiles, but for data tiles





var ServerFetchedTiles=[];



function ServerFetchMapType() {

}



ServerFetchMapType.prototype.tileSize = new google.maps.Size(256,256);

ServerFetchMapType.prototype.maxZoom = 32;

ServerFetchMapType.prototype.name = "Server Tile #s";

ServerFetchMapType.prototype.alt  = "Server Data Tile Map Type";      



ServerFetchMapType.prototype.getTile = function(coord, zoom, ownerDocument) {

  var addr=this.getAddr(coord,zoom);

  //test - may be we allready load this block?

  if(ServerFetchedTiles[addr]){

    return

  }

  $.get("ajax/load-map-tile?"+addr,

      function(data){

        ServerFetchedTiles[addr]=data;

        //wow! i got the data just for this tile

        //and any map moving is nothing for me!

      });

};



//and add this tile overlay to current map type

map.overlayMapTypes.insertAt(0, new ServerFetchMapType() );




And you can request tiles in two ways - as google do (x,y,z), or as latlngbox.
I write some code for second variant( i think you`ll use second at the begining )



//we can request tile as tile(x,y,z)

ServerFetchMapType.prototype.getAddrXY = function(coord, zoom){

   return "x="+coord.x+"&y="+coor.y+"&z="+zoom;

}



//or as latlng box

ServerFetchMapType.prototype.getAddrLatLng = function(coord, zoom){

    

    //helper function for mercator projection

   var mercator = function(point){

     //

     var numtiles=Math.pow(2,point.zoom);

     var bitmapsize=numtiles*256;

     var bitmaporigo       =bitmapsize/2;

     var pixelsperlondegree=bitmapsize/360;

     var pixelsperlonradian=bitmapsize/(2*Math.PI);

     

     var lat=bitmaporigo+(pixelsperlondegree*point.x);

     var ged2rad=((point.t*Math.PI)/180.0);

     var sn=Math.sin(deg2rad);

     var lng=((bitmaporigo - 0.5 * log((1+sn)/(1-sn)) * pixelsperlonradian));

     return new google.maps.LatLng(lat,lng);

   }

   var point1={x:coord.x*256,y:coord.y*256,z:zoom} ;

   var point2={x:(coord.x+1)*256,y:(coord.y+1)*256,z:zoom} ;

   var ne=mercator(point1);

   var sw=mercator(point2);

   return "NE="+ne.toString()+"&SW="+sw.toString()+"&z="+zoom;

}


more info about map tiles can be found at google code, and there they point this idea somehow.
Idea - you can load not only images

Step 5. Enjoy

Now try to impliment pieces of this into your own code. Or see how it works on

What lasts?

Ask one question - what you will do if there is no data for tile( you are viewing siberia ), may be just load tile for other zoom( currrent_zoom-2? ).
And how to do it?(we do it).



Homework: and why cites, listed above use other technics? Benefits of quadtree?
( ps: in this mode tiles can he cached on file level. For dirrect nginx access )



All of sections, i list here, is allready done by me. I need just to wrap code into article, and, yap, english article :)

If you want to know more - ask

Load data into google maps. And do it as google do

1 comment:

  1. kashey there are lots of bugs in this code bro, the mercator function has some bugs , i fixed somthing but i dont know if its ok now, it gives me thiese values

    NE=(90, 67.0800315827073)&SW=(90, -91.8723804030451)&z=10
    NE=(90, -91.8723804030451)&SW=(90, 42.957327474228805)&z=10
    NE=(90, 67.0800315827073)&SW=(90, -91.8723804030451)&z=10
    etc..
    are they ok?

    ReplyDelete