Tuesday, January 15, 2013

D3GL Tutorials 03: Intro to data primitives with Points

Data primitives for D3GL are the visual equivalents to the raw data. So far, we have covered (1) creating a globe, (2) binding the globe to some data to set globe-specific properties, and then (3) binding primitives to data. But all this has been setting grounds for showcasing the data through the primitive it has been bound to by letting the data dictate specific properties of the primitives.

In D3GL globe, there are five data primitives:
Points, Shapes, Bars, Arcs,
. We will take
as an intro to primitives.

Customizing primitives for data

Just as each globe was an instance of a globe template which was tied to each data element, each point, shape, arc, etc. is an instance of a template. Just like with the globe template, you will either pass in fixed values that are shared across all instances or functions that will return customized values depending on the data element it takes as argument.

Let's take
as an example. First you would create a template that binds to data, as the following:
var points = globe.points()
  .data(function(k) {
    return datasets[k];
As we discussed in the previous tutorial, the argument
is bound on the globe level (i.e. per globe) and in this case is being used as the key to fetch a dataset, which is then bound to the primitive

We want to customize each point instance so that it represents each data element:
var points = globe.points()
  .data(function(k) {
    return datasets[k];
  .radius(function(d) {
    return scaleRadius(d['precipitation']);
  .color(function(d) {
    return scaleColor(d['precipitation']);
  .latitude(function(d) {
    return d['latitude'];
  .longitude(function(d) {
    return d['longitude'];
The parameter
used in the setter functions represents a data element in the dataset bound to
. In the above code snippet, the radius and color of each point is determined by the value of
. The scaling functions
take the precipitation value and spit out an appropriately scaled radius in units of degrees, and color in "#" format. D3.js provides a convenient
that is pretty useful for all types of scaling, including color gradients.


This demo marks the landings on Mars with
, using the color and size of each point to represent how recent the landing was: Landings on Mars


As discussed in the previous tutorial, a data primitive for D3GL Globe is another closure within the
has a rendering function, but unlike with the globe, this function is not invoked by the client. Instead, when
are added to the globe, the rendering function for
is pushed to the array of rendering functions that are called per frame by

In the rendering loop invoked with
a hidden canvas element that is programmatically created is passed in to the rendering functions for primitives, along with the datum the globe instance is bound to, and the WebGL environment:
// In rendering loop - called once per frame
for(var i = 0; i < primitiveRenderingFunctions.length; i++){
    webGLEnvironment, contextForHiddenCanvas, datumForGlobeInstance
Of course, it's JavaScript, not Objective-C, so the variable names are not actually this long.

In the rendering loop for
the datum pass in is used to fetch the dataset. Then for each element in the dataset, a circle is drawn using
on the context that is passed in:
function points(gl, context, datum) {
  var dataset = fnData(datum);
  for (var i = 0; i < dataset.length; i++) {
    var elem = dataset[i];
    // client-defined functions are used to fetch properties of each point
    var lat = fnLat(elem);
    var lon = fnLon(elem);
    // ... and so on
    drawCircle(context, plat, plon, pradius, color, strokeColor, lineWidth);
After all rendering functions in queue are called and the overlay texture on the hidden canvas is complete, the entire scene is rendered via
gl.renderer.render(gl.scene, gl.camera);

The other primitives roughly use the same format, but there are differences. So stay tuned!

← Prev

No comments:

Post a Comment