Querying data based on screen bounds? Use a standard grid.

johnWeeGo I know I haven't posted something code related on Virtual Earth in ages, rest assured I've just been very busy.


The 4 green boxes are the screen bounds passed to the server for data in many of my older virtual earth applications and samples, the 2 blue boxes are the standardised bounds I actually send these days.

This is the new JavaScript code I use to get the current screen bounds:

var points = new Array();
        if (map.GetMapStyle() == VEMapStyle.Birdseye) {
        var be = map.GetBirdseyeScene();
        var rect = be.GetBoundingRectangle();
        }else {
        var view = _map.GetMapView();
        //Bounds must be NW, SE. Reorder if not
        if (view.TopLeftLatLong.Latitude < view.BottomRightLatLong.Latitude) {
        var temp = view.TopLeftLatLong.Latitude;
        view.TopLeftLatLong.Latitude = view.BottomRightLatLong.Latitude;
        view.BottomRightLatLong.Latitude = temp;
        if (view.TopLeftLatLong.Longitude > view.BottomRightLatLong.Longitude) {
        var temp = view.TopLeftLatLong.Longitude;
        view.TopLeftLatLong.Longitude = view.BottomRightLatLong.Longitude;
        view.BottomRightLatLong.Longitude = temp;

        //Round bounds to a standard grid. Improves server side caching performance and reduces web service calls.
        var zoom = map.GetZoomLevel();
        var latrounding = (90/(Math.pow(2,(zoom-2))));
        var lonrounding = (180/(Math.pow(2,(zoom-1))));

        var lat1 = view.TopLeftLatLong.Latitude;
        var lat2 = view.BottomRightLatLong.Latitude;
        var lon1 = view.TopLeftLatLong.Longitude;
        var lon2 = view.BottomRightLatLong.Longitude;

        var TLat = (Math.floor(lat1 / latrounding)+1) * latrounding;
        var BLat = (Math.floor(lat2 / latrounding)) * latrounding;
        var LLon = (Math.floor(lon1 / lonrounding)) * lonrounding;
        var RLon = (Math.floor(lon2 / lonrounding)+1) * lonrounding;

        points.push(new VELatLong(TLat,LLon));
        points.push(new VELatLong(BLat,RLon));

The idea here is to handle Bird's eye mode, 3D rotations and 2D in this one function. I'm going to talk more about the standard grid. Feel free to ask about Bird's eye or 3D if you have questions.

Previously I simply passed the current bounds to the server, it got the data I needed and passed it back – all was good. The issue was scalability, as hundreds of requests are made these bounds were very unique even if the data they wanted to show was the same.

The solution? Create and oversize a standard grid bounds. What this does is makes many more requests identical. It also has a side benefit that slight movements of the map don't even a trigger a new data request.

From here you can implement server side caching for popular requests and/or set the web server to a http “get” and allow client side caching if appropriate (eg if your data doesn't change).

More to come.