Web-Based Visualization

Web Technologies Suitable for (Interactive) Visualization and Related Opportunities




-- Ove Daae Lampe

Who am I?

Ove Daae Lampe

+Ove Lampe | ii.uib.no/vis | cmr.no/cmr_computing

Researcher at CMR Computing and PhD Student at UiB

Slides are available here: http://folk.uib.no/ola062/test_talk

Web Technologies

Supporting Visualization

Technologies

Prevalence (according to Google)

Java 12,000,000
Flash 10,900,000
Javascript 8,320,000

Results after a google search for Visualization +Java|Flash|Javascript (24.10.2011)

Support (vanilla):

Support (with some effort):

Flash

Adobe Flash (formerly Macromedia Flash) is a multimedia platform used to add animation and interactivity to web pages.

Java

Java is a programming language originally developed by James Gosling at Sun Microsystems and released in 1995. Java can be utilized online on webpages through applets.

HTML 5

HTML 5 is the fifth revision of the HTML standard created in 1990. Its core aims has been to improve the language with support for the lates multimedia.

HTML 5 -- II

Several new features increases the semantic value of documents: <section> , <article> and <header>.

The following added features adds possibilities in terms of multimedia, and visualization.

HTML 5 APIs

HTML5 has defined extended APIs such as:

HTML 5 Features

W3.org defines it's new features as following:

HTML 5 Features II

HTML5 Canvas:

2D and 3D

HTML5 Canvas 2D

The <canvas> is created using:

    <canvas id="tutorial" width="150" height="150" 
            style="border:solid black 1px;"></canvas>

which creates the following:

HTML5 Canvas 2D - II

Canvas exist in a 2D and in a 3D mode. We access the 2D context using:

  var canvas = document.getElementById("canvas");
  if (canvas.getContext) {
    var ctx = canvas.getContext("2d");
  }

This context, ctx, can be utilized for immediate mode 2D rendering, e.g.,:

  ctx.beginPath();  
  ctx.moveTo(30, 30);  
  ctx.lineTo(150, 150);
  ctx.bezierCurveTo(60, 70, 60, 70, 70, 150);
  ctx.lineTo(30, 30);

Canvas 2D Example

<html>
 <head>
  <script type="application/javascript">
    function draw() {
      var canvas = document.getElementById("canvas");
      if (canvas.getContext) {
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "rgb(200,0,0)";
        ctx.fillRect (10, 10, 55, 50);
        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 30, 55, 50);
    }}
  </script>
 </head>
 <body onload="draw();">
   <canvas id="canvas" width="150" height="150"></canvas>
 </body>
</html>

src: Mozilla

WebGL = Canvas 3D

WebGL

WebGL Hello World! - I

Html code using the Canvas tag:

  <body onload="webGLStart();">
    <canvas id="mycanvas" width="500" height="500"></canvas>
  </body>

And the webGLStart method:

      function webGLStart() {
        var canvas = document.getElementById("mycanvas");
        initGL(canvas);
        initShaders();
        initBuffers();
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
        drawScene();
    }

WebGL Hello World! - II

  var gl; // Define a 'global' GL-context variable
  function initGL(canvas) {
    try {
        gl = canvas.getContext("webgl");
    } catch (e){
      try {gl = canvas.getContext("experimental-webgl");}catch (e){}
    }
    if (gl){
        gl.viewportWidth  = canvas.width;
        gl.viewportHeight = canvas.height;    
    } else {
        alert("Could not initialise WebGL, sorry :-(");
    }
  }

WebGL Hello World! - III

Define a fragment shader:

<script id="shader-fs" type="x-shader/x-fragment">
    void main(void) {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
</script>

And a vertex shader:

<script id="shader-vs" type="x-shader/x-vertex">
  attribute vec3 vertex;
  uniform mat4 uMVMatrix;
  uniform mat4 uPMatrix;    
  void main(void) {
    gl_Position = uPMatrix * uMVMatrix * vec4(vertex, 1.0);
  }
</script>

WebGL Hello World! - IV

Create our vertex buffer (no immediate mode!)

var pos_buf;
function initBuffers() {
    pos_buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, pos_buf);
    var vertices = [
         0.0,  1.0,  0.0,
        -1.0, -1.0,  0.0,
         1.0, -1.0,  0.0
    ];
    gl.bufferData(gl.ARRAY_BUFFER, 
                  new Float32Array(vertices), 
                  gl.STATIC_DRAW);
    pos_buf.itemSize = 3;
    pos_buf.numItems = 3;
}

WebGL Hello World! - V

Render the scene

function drawScene() {
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // Create the perspective matrix pMatrix
    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 
                     0.1, 100.0, pMatrix); 
    mat4.identity(mvMatrix); // Reset our modelview matrix
    
    // Bind our vertex array (attrib array)
    gl.bindBuffer(gl.ARRAY_BUFFER, pos_buf);
    // Bind the vertex array to the shader attrib
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 
                           pos_buf.itemSize, gl.FLOAT, false, 0, 0);
    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLES, 0, pos_buf.numItems);
}

WebGL Hello World! - VI

src: Giles

WebGL - Wrapped

three.js

Create a WebGLRenderer

      var renderer = new THREE.WebGLRenderer({antialias: true});
      renderer.setSize(document.body.clientWidth, 
                       document.body.clientHeight);    
      document.body.appendChild(renderer.domElement);

And change its background color

      renderer.setClearColorHex(0xEEEEEE, 1.0);
      renderer.clear();

src

three.js - I

three.js - II

Create a Camera

      // new THREE.Camera( FOV, viewAspectRatio, zNear, zFar );
      var camera = new THREE.Camera( 45, width/height, 1, 10000 );
      camera.position.z = 300;

Make a Scene with a Cube

      var scene = new THREE.Scene();
      var cube = new THREE.Mesh(new THREE.CubeGeometry(50,50,50),
                     new THREE.MeshBasicMaterial({color: 0x000000}));
      scene.addChild(cube);

And render the Scene as seen by the Camera

      renderer.render(scene, camera);

three.js - III

three.js - IV

Adding light, shadows, and animation

// enable shadows on the renderer
renderer.shadowMapEnabled = true;
// enable shadows for a light
light.castShadow = true;
// enable shadows for an object
litCube.castShadow = true;
litCube.receiveShadow = true;
// Adding the animation
litCube.position.x = Math.cos(t/600)*85;
litCube.position.y = 60-Math.sin(t/900)*25;
litCube.position.z = Math.sin(t/600)*85;
litCube.rotation.x = t/500;
litCube.rotation.y = t/800;

three.js - V

src: Ilmari Heikkinen

three.js code - Bar graph

      var grid = /* 2D Array */
      var barGraph = new THREE.Object3D();
      scene.addChild(barGraph);

      var max = /* Grid max value */
      var mat = new THREE.MeshLambertMaterial({color: 0xFFAA55});
      for (var j=0; j<grid.length; j++) {
        for (var i=0; i<grid[j].length; i++) {
          var barHeight = grid[j][i]/max * 80;
          var geo = new THREE.CubeGeometry(8, barHeight, 8);
          var mesh = new THREE.Mesh(geo, mat);
          mesh.position.x = (i-grid[j].length/2) * 16;
          mesh.position.y = barHeight/2;
          mesh.position.z = -(j-grid.length/2) * 16;
          mesh.castShadow = mesh.receiveShadow = true;
          barGraph.addChild(mesh);
        }
      }

three.js - Bar graph

src: Ilmari Heikkinen

three.js code - Scatter plot

var scatterPlot = new THREE.Object3D();
var mat = new THREE.ParticleBasicMaterial(
  {vertexColors: true, size: 1.5});

var pointCount = 10000;
var pointGeo = new THREE.Geometry();
for (var i=0; i<pointCount; i++) {
  var x = Math.random() * 100 - 50;
  var y = x*0.8+Math.random() * 20 - 10;
  var z = x*0.7+Math.random() * 30 - 15;
  pointGeo.vertices.push(new THREE.Vertex(new THREE.Vector3(x,y,z)));
  pointGeo.colors.push(new THREE.Color().setHSV(
    (x+50)/100, (z+50)/100, (y+50)/100));
}
var points = new THREE.ParticleSystem(pointGeo, mat);
scatterPlot.addChild(points);
scene.fog = new THREE.FogExp2(0xFFFFFF, 0.0035);

three.js - Scatter plot

src: Ilmari Heikkinen

three.js - GUI controls

Using DAT.GUI:

      var gui = new DAT.GUI();
      gui.add(cube.scale, 'x').min(0.1).max(10).step(0.1);
      gui.add(cube.scale, 'y', 0.1, 10, 0.1);
      gui.add(cube.scale, 'z', 0.1, 10, 0.1);

Done!

code.google.com/p/dat-gui

Scalable cube

src: Ilmari Heikkinen

Custom Libraries

Specialized Data

Custom Libraries

ChemDoodle

The ChemDoodle components greatly simplifies visualizing protein, and other molecular structures.

<script>
	// setup component
	var cdcanvas = new ChemDoodle.TransformCanvas3D(
                                    'cnv_name', 400, 400);
	// set the representation to 'Ball and Stick'
	cdcanvas.specs.set3DRepresentation('Ball and Stick');
	// set the background color to black
	cdcanvas.specs.backgroundColor = 'white';
	// load data
	var molFile = '3036\n  CHEMDO83D\n\n 28 29  0 ....  END\n';
	// set the coordinate multiplier to 1 to stay in Angstroms
	var molecule = ChemDoodle.readMOL(molFile, 1);
	cdcanvas.loadMolecule(molecule);
</script>

ChemDoodle - II

src: ChemDoodle

ChemDoodle - III

src: ChemDoodle

WebGL - KDE

Author: Ove Daae Lampe

A library to quickly draw kernel density estimates from datasets stored in google spreadsheets

<script type="text/javascript" src="KDE.js"></script>
<body>
<div id="viscontainer" style="width:800px;height:600px;"></div>
<script type="text/javascript">
    // Creating a new KDE requires only the id of the container
    my_kde = new KDE( '#viscontainer' );
    // Load data from a google spreadsheet key. Data must be public.
    var key='0Ah8aKdOzkIVEdGlDZjc3VW1nenFrMnlfeVZfc0hLN0E';
    my_kde.setGoogleData( key );
</script>
</body>

WebGL - KDE example

src: lampe

D3.js

D3.js is a selection mechanism enabling the transformation of svg or dom objects to data visualizations. D3 focuses on efficient transofmations, or scene changes. D3.js shares the primary author with ProtoVis, Mike Bostock and as such has several similarities.

D3.js does not use the canvas class or WebGL, but utilizes inline SVG

D3.js Force-Directed Graph

src: d3.js

D3.js Chloropeth Map

src: d3.js

D3.js Population Pyramid

src: d3.js

WebGL - Globe

WebGL - Geoid Viewer

WebGL - PointStream

WebGL - Pixel Processing

src:cake23

Summary

and Conclusions

Summary

Thank You

Any Questions?