Tuesday, April 25, 2017

Data Paging Layers

We load a lot of data sources in WhirlyGlobe-Maply, usually over the network.  Images are relatively easy, but how do you deal with things like vector tiles?

Ye olde vector tile example

That would be the job of the Paging Layer.

Quadtree Structured Data Paging


It all starts with a quadtree, a simple enough data structure.  It's here that we decide what's visible and what needs to be loaded.

Quadtree courtesy wikipedia
The quadtree for a data source can be in any proj.4 supported coordinate system, but most people use Spherical Mercator which is... what they use.  No judgement.

In deciding what to load, we start at the top node (0: 0,0), projecting a box into the view and then recursing if the box is visible.  It's not all that expensive, because quadtree.  But does get a bit tricky when using the globe or multiple coordinate systems.



For image layers, the toolkit has its own complex logic for loading image tiles and frames and handling failure and so on.  We provide similar logic for vector tiles, but for anything else, the logic is you.

Quad Paging Layer


You've got a data source, sqlite file full of points, let's say.  You want to turn them into markers, but there's too many to load at once.



Here's where the QuadPagingLayer (Android) or MaplyQuadPagingLayer (iOS) comes in.  Set up one of these babies with the coordinate system and extents of your data source and it'll figure out what to load.

You have to create the visible objects and that's where the PagingInterface (Android) and MaplyPagingDelegate (iOS) come in.  The paging layer calls you back when it's time to load a tile's worth of data.

Mt. St. Helens LIDAR
We love our threading in WhirlyGlobe-Maply and it was ever so hard to implement.  So use it.  Try a dispatch queue on iOS or use a worker thread on Android.  But don't hold up the paging layer.  It has other things to do.

When you make a visible object (marker, label, etc) tell the paging layer what you created with the addData (iOS, Android) method and call tileDidLoad (Android, iOS) when you're finished.

That's enough information for the paging layer to do the rest, which includes...

Cleanup on Node (12: 129,1304)


One of the trickier bits here is deciding when to delete something.  Luckily, you don't have to.

You told the paging layer what you created and it'll delete it for you.  There's even a callback if you really, really want to know it did that.

Paging Layers are Awesome


There it is, one of the key pieces of WhirlyGlobe-Maply: the paging layer.  We use it all over the place and if we don't support your data type, you'll use it too.