Friday, July 27, 2012

Network image tile paging

As soon as I had quad tree paging working for local image data sets, like MapBox Tiles, the next question was "What about over the network?"

It's actually a little harder than it seems.  If we're paging data locally and the read is fast enough, we can just fetch one tile at a time.  That's not going to work over the network.  Latency might be fairly severe and loading could be unacceptably slow.

The Demo

But enough of the problems, obviously we can solve them.  So let's see how it works.

The answer is, it works pretty well.  The whole quad display layer infrastructure and assorted data structures and sources is panning out nicely.


Here is where things get complicated and then, happily, simpler again.  Let's start with the complicated part.

The data layer that controls all of this is the WhirlyGlobeQuadDisplayLayer.  I discuss it in an earlier blog post, but I'll give it a quick review.  You tell the layer how big the data set you're paging is and provide a whole bunch of delegate methods to fill in the details.  As the user pans and zooms around, the layer is constantly evaluating tiles to load and reevaluating tiles to unload.  But it doesn't actually load anything, that's up to the delegates.

To make one of these things work, you need to provide a couple different delegates to implement the example in the video.  It goes like so.

  • Create a WhirlyGlobeNetworkTileQuadSource, giving it the base URL and image extension.  It'll fetch tiles in the usual base/level/col/row.ext form.  You can also give it a cache directory to check first.
  • Create a WhirlyGlobeQuadTileLoader and give it the data source.  This is the bit that manages the geometry underneath the images.
  • Create a WhirlyGlobeQuadDisplayLayer and add it to the layer thread.  Give this the tile loader and data source and off it goes.
That means setting up image set paging over the network involves three different objects created and initialized in the right order.  That can get complicated.

Implementation: WhirlyGlobe Component

So to make it a bit easier, I've added this functionality to the WhirlyGlobe Component.  All you have to do there is make a call to addQuadEarthLayerWithRemoteSource with the following.
  • The base URL for the image data set.
  • Extension for the image type (e.g. png)
  • An optional cache directory.
  • The min and max zoom levels.  Zero is standard for the min and max can go as deep as the data set provides.
You can tear that thing down just as easily without thinking about threads or ordering or what have you.

Onward to the Future

The WhirlyGlobe 2.0 release is close.  I only have a couple of serious bugs to fix and then a bit of documentation to do.  But first, I'm going to release WhirlyGlobeComponent.

I provide a stripped down, simplified view of WhirlyGlobe with the Component.  It's built on top of the toolkit, of course, but it's entirely an Objective C interface that exposes little of the complexity.  I'd say it has about 60% of the functionality at this point, but 90% of what most people want.  For example, no vectors in the first version, just labels, markers, and base image layers.

The WhirlyGlobe Component's launch is imminent, likely in the next week or two.  I've tested it on client projects and I like how it's working.