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.

Implementation

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.


Saturday, July 21, 2012

Is WhirlyGlobe dead?

That's the question I always ask when a project's blog has gone dark.  Github and google code are populated with the dried out husks of open source dreams past.  WhirlyGlobe isn't one of them.  Or at least not yet.  I've just been busy.

If you check out the WhirlyGlobe 2.0 repository on github, you'll see a steady stream of updates.  2.0 isn't quite ready to ship, but it's getting close.  My list of things to do is below two digits at this point.  One of them deserves a bit more discussion.

WhirlyGlobe Component

The single biggest problem I have with WhirlyGlobe is that it's, apparently, a complete bitch and a half to understand.  I mean, hey, it's just a combination of Objective C/C++, OpenGL ES, a bunch of dependent open source libraries, and multi-threading.  Like that's hard?  What?

Okay, that's kind of hard.  Now I'm doing something about it.

For the high end user, your iPad melting kind of app that swaps gigabytes of data in and out on the fly... you're stuck.  Suck it up.  But for the low end, I'm making a nice self contained component.

On the compile side, it's one single package that contains all the weird stuff I pull in.  No more compiling Eigen or downloading Boost and Shape and Clipper.  It's all in the library.  The mistakes you can make compiling it are few and easy to fix.

On the development side, the component is... well it's just the one component.  You create a WhirlyGlobeViewController, add its view your view hierarchy and off you go.  It will manage the threading, selection, interaction, and tear down.  All stuff that confused the hell out of people.

Oh, and no more direct C++ exposure.  It's all Objective-C from the outside.

The Future

It's starting simple, of course, with a standard interaction model (think WhirlyGlobeTester) and just the basic markers, vectors, and labels.  For imagery I'll support the old texture groups and the new quad tree data sets (both local and network) so that'll be a bit more exciting.  Then we'll just see where it goes.

Supporting a more general purpose vector data set is going to be tricky.  I'll have to see what's possible and, frankly, who comes in with paying work.  On the plus side, most people are interested in a whole lot of images and just a few vectors.  The Component will work well for that.

Friday, June 8, 2012

WWDC 2012

I'll be there.  I was up early enough to grab a ticket.

If you're there and want to talk maps, 3D, and the real time display there of, drop me a line.

Monday, May 14, 2012

Economist - World in Figures

This one was in development for a long, long time.  I was only involved with the globe portion a few months ago and then more recently to clear up a few details.  So here's what it looks like.

That's a picture taken from space.  The world is actually pastel.
It's ambitious as hell.  I recommend checking it out.  Basically, it's about traversing a data set, the kind of thing Economist subscribers would be interested in.  You've got all sorts of stats about countries, ways to graph and compare and so on.  The globe is just used for selection.

The Globe

Obviously, it's WhirlyGlobe or I wouldn't be mentioning it.  For all the complexity of the rest of the app, the globe is pretty simple.  There's one big image for the countries and their borders, chopped up into the usual chunks.  There's a layer of text on top of that for the country labels.  Lastly, all the selection is handled by an invisible lookup into a typical vector data set.

That last bit is a little different from my old approach.  Since we're not displaying the vector data, it isn't present in memory for selection.  However, you can do selection using the bounding boxes I build on top of the shape files.  That's what makes it reasonably zippy and keeps memory usage low.

Nowadays I almost always do that.  Once the vector data is converted into a raw Drawable form it's not convenient for selection.  Since selection can be (relatively) slow I just hunt around in the appropriately indexed vector data.  I'm doing that in the layer thread so a little delay is fine.

Data Visualization on the iPad

What they were trying to do here was interesting.  I've discussed similar things with other prospective clients.  People can get very excited about comparative statistics mapped on to a globe.  Most people don't have the money to spend or a really firm idea of what the product should be.  These folks obviously did and I think the app was a natural fit for their brand.

I wasn't closely involved with the project (sub-sub-contractor) so I don't know where they're going to take it.  Good use of WhirlyGlobe, though.  Very appropriate.

Friday, May 11, 2012

WhirlyGlobe 2.0 on github

It's not released yet, but I've made it public.  Don't make me regret it.

WhirlyGlobe 2.0 has a lot of neat stuff in it, but it's still very much in development.  I do have clients already using it and the damn thing is open source so it might as well be public.

For now, please use WhirlyGlobe 1.2 unless:

  • You've talked to me and you have some demonstrated need
  • You're paying me money to implement features for you in 2.0.
  • You're willing to use it silently and not bug me.

I'd say 2.0 is now past that tipping point where it's more a "thing" than an "idea" so it might as well be out there.  But again, not for general use.

Mapping Engines

I hint at this in the README and you can see it clearly in the code so I might as well just come out and say it.  I'm branching out from the 3D globe.  Turns out much of what I built is usable as a 2D (ish) map display engine.  Almost as if I planned it that way!

It'll be a 2D(ish) map display toolkit based on a 3D rendering engine.  I'm going for fast and sexy, a small niche for sure, but a much bigger one than WhirlyGlobe.

And no, please don't try to use what's in the WhirlyGlobe 2.0 tree for this.  It's not ready.

Releases

First comes WhirlyGlobe 2.0.  Expect that in early summer when some of the new features settle down.  I'm hoping to slip a couple of big changes in there first, but we'll see.

Then comes the rebranding and the release of the mapping toolkit.  WhirlyGlobe will remain, but under the umbrella of the new library with a new release number and so forth.  Yeah, that's a little confusing.  Expect that late summer.

Thursday, May 10, 2012

Xweather - Extreme Weather

This one's been in development for a while and I'm really happy to see it published.

Xweather displays recent extreme weather events and lets users see where they were, what they were, and read details about that.  Check out the screen shot I just totally stole off their app store page.


It's pretty.  Buy it you cheap bastards.


Development

"Where did they get that handsome globe?" you probably wouldn't bother asking.  Well, it's WhirlyGlobe obviously.  Duh.

For the most part this is just a stock WhirlyGlobe 1.2 globe.  eLoomn, the developers, paid me to add markers and that crazy animated marker functionality.  Looks pretty good actually, but that's all in 1.2 now.  I quite like how the markers turned out.

On a scale from "corporate sales office location display" to "iPad melting dynamic map application", this one would fall somewhere in the middle.  Pretty easy on my end, good use of WhirlyGlobe, not super complex.  They could take it in the iPad melting direction if they wanted to, but I like how they dialed in their ambitions for this first version.


The Future!

As usual I don't make a dime off this sucker, because that's not how I roll.  They have some cool ideas for the next version and, as always, I charge by the hour so I'd love to see this one take off.  Plus it's just pretty nice and they were really easy to work with.

I could see some WhirlyGlobe 2.0 insanity fitting nicely into this app.  [I suspect 2.0 based apps will pretty much all page the multi-res images]. But for now, it does what it does and it does it well.  Very cool.

Thursday, April 12, 2012

MapBox Tiles Paging

The whole point of supporting MapBox Tiles is to load them selectively in to memory as needed.  That is, to page them.  And now we can.  The video explains it best.



That's the Blue Marble January data set and it contains levels 0 through 8.  Level 0 covers almost the entire globe except for the poles.  Children subdivide by 4 each time, so you can do the math.  Or not, but I'm feeling lazy.

New Data Layer

I've added a new data layer to the WhirlyGlobe library, WhirlyGlobeMBTileLayer.  It acts like a regular SphericalEarthLayer with a few differences.

  • It takes a WhirlyGlobeMBTiles object on startup.  It'll check the metadata and then page textures from that data set.
  • maxTiles controls how many individual tiles are loaded in at once.
  • minTileArea controls how deep its willing to page for a zoom level.  This is screen resolution dependent, which is good.
  • viewUpdatePeriod tells the system how often to update based on view changes.
Kick it off and it'll go do its thing within the layer thread.  It serializes tile updates to avoid overwhelming the rendering system and generally tries to keep a low profile.

QuadTree Based Tile Paging

A tile data set organized in a quad tree is great, but if the data is in a different coordinate system from the display, things get interesting.  Here, we're projecting that quad tree, in Spherical Mercator, on to a sphere.  Stuff gets warped.

There's two ways of dealing with that:  You either don't, or you do.  I chose the latter.  It's easier to just show.



WhirlyGlobe Toolkit Changes

In addition to the new data layer and MapBox Tiles objects, I added support for view based updates.

WhirlyGlobeView updates can be overwhelming; there are modes where the matrix is continuously changing, so you might be called at each and every frame.  That's problematic if you're doing any sort of serious calculation for your updates.  To help out, I broke the view update into two pieces.

  • A watcher delegate to capture every view update
  • A layer view watcher that filters the updates based on frequency.
A data layer plugs into this is by registering with the layer view watcher for a maximum update frequency.  The layer is then called no more often than that frequency.  And yes, I take care of the dangling update condition.

This will likely change a bit in WhirlyGlobe 2.0.  Consult me if you want to use this mechanism directly.


How's It Working?

It's working pretty well.  You could slip this in to a few existing WhirlyGlobe apps without much trouble.  There are a few caveats, though.
  • This only works with static local databases.  Paging over the network will come eventually, but it'll be more work.
  • At present the layer really, really wants a full database between the levels you specify.  No missing tiles.
  • Edges aren't correct between neighboring tiles of differing resolutions.  If you pay attention, you can see lines.  It's a classic problem, I know how to fix it.  Just takes time.
  • There's at least one quad tree bug out there.  You might not notice it, but I do.
  • Tiles should really fade in and out rather than pop.
  • Textures need to be downloaded in the background to avoid overwhelming the rendering engine.
Most of these you and your users may never notice.  If you need the paging functionality, grab a copy of the trunk, after I've checked in, and give it a try.  If you notice the problems, let's talk.

Future Work

I'll be doing some minor cleanup and documentation over the next day and then checking this all in.  That will be the last big thing I do for WhirlyGlobe 1.3.  At some later date, hopefully after someone's used it, I'll bundle it all up as the WhirlyGlobe 1.3 distribution in its own framework.

I've got clients (that is, paying customers) who want more complicated things.  Those I'm doing in WhirlyGlobe 2.0.  Some of that is paging related, much of it isn't.  It should all be neat and, yes, I'll be releasing it open source.

If you've got an app coming up in the next few months, use the trunk and/or WhirlyGlobe 1.3 and let me know what you're up to.

Addendum

It's all checked in to the trunk.  Enjoy.