3D bar chart on the globe using three.js

When people need to present per-country data such as GDP, they usually resort to color-coded maps or simple bar charts. In 3D, you could combine these two and end up with something like this:

globe bar chartThis is very obvious idea, yet I had no time to try it until last November. It worked, and I went on with my life, leaving the code to collect the dust. Then I saw Kaspersky cyberthreat map this March, which used extruded country shapes to support zooming. This reminded me this gold I was sitting on, and now I was finally able to fork out some time to undust it and push to github.

Overview

Basically, you take 2D country shapes and tessellate it on the sphere surface, then extrude towards the sphere center. You end up with cone-shaped meshes that you can then scale to build this kind of geo- bar chart. The catch is that corresponding three.js scene weighs much more than its 2D source data (ObjectExporter blows 100 KB of GeoJSON up to many MBs). Much of this extra weight comes in the form of useless digits in vertex data, but even with that removed there is extra dimension, data duplication and so on. To work around this issue you have to build 3D geometry from tessellated 2D data on the fly – this puts 3D data size at ~150% of 2D. Still sucks, if compared to TopoJSON, but tolerable. Corresponding code looks like

for (var name in data) {
    geometry = new Map3DGeometry (data[name], innerRadius);
    globe.add (data[name].mesh = new THREE.Mesh (geometry, material));
}

Map3DGeometry class and the tool to create the data are now at github.

Tessellation

Following documents the problems you would encounter if you did it yourself, so you may probably skip it. My first idea was to use ear clipping or similar method on country borders. In fact, three.js has such a method built in itself. This is how the result would look like:

map2globe_try_1

You can see it does not look that nice with large countries. To fix this shit you need to generate lots of vertices uniformly distributed on the sphere and include them in tessellation. This requires constrained Delaunay library such as poly2tri.

My first attempt using poly2tri looked like this:

map2globe_try_2

A little bit nicer, but check out those vertical edges. Why does “Delaunay” tessellation prefer clearly longer vertical edges to shorter horizontal ones? The answer is: bad choice of coordinates. So this time I had to re-do the tesselation in Mercator coordinates, and the result now was like this:

map2globe_try_3

Still not perfect, but much better. The only serious problem now was with long border lines such as between Canada and USA:

map2globe_try_4

I had to split these into several edges to make it more arc-like in 3D, and at the same time wiggle the vertices around to keep poly2tri happy, as it does not handle collinear edges at all.

Well, that’s it. If you’re reading this, you can imagine how many hours I have just saved you, so be nice and say “thanks” :)

2 Responses to “3D bar chart on the globe using three.js”


  1. 1 thiagoponte April 20, 2014 at 18:49

    I normally don’t deal with data to graphics, but i ever need it, i’ll follow your advices.


  1. 1 Prog.Hu Trackback on June 5, 2014 at 15:20

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




Old stuff

April 2014
M T W T F S S
« Mar   May »
 123456
78910111213
14151617181920
21222324252627
282930  

Oh, btw…


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: