Add modif senslabmap
authorAnthony Garcia <anthony.garcia@inria.fr>
Wed, 16 Oct 2013 10:31:32 +0000 (12:31 +0200)
committerAnthony Garcia <anthony.garcia@inria.fr>
Wed, 16 Oct 2013 10:31:32 +0000 (12:31 +0200)
plugins/senslabmap/senslabmap.py
plugins/senslabmap/static/css/senslabmap.css
plugins/senslabmap/static/js/senslabmap.js
plugins/senslabmap/static/js/viewer3D.js
plugins/senslabmap/templates/senslabmap.html

index 73c767d..7540edb 100644 (file)
@@ -5,9 +5,11 @@ class SensLabMap (Plugin):
     # set checkboxes if a final column with checkboxes is desired
     # pass columns as the initial set of columns
     #   if None then this is taken from the query's fields
-    def __init__ (self, query, **settings):
+    def __init__ (self, query, query_all, **settings):
         Plugin.__init__ (self, **settings)
-        self.query=query
+        self.query = query
+        self.query_all = query_all
+        self.query_all_uuid = query_all.query_uuid
 
     def template_file (self):
         return "senslabmap.html"
@@ -22,10 +24,10 @@ class SensLabMap (Plugin):
                            "js/spin.presets.js", "js/spin.min.js", "js/jquery.spin.js",
                            "js/three.js", "js/grenoble.js", "js/viewer3D.js",
                            ] ,
-            'css_files': [ "css/senslabmap.css" , 
+            'css_files': [ "css/senslabmap.css" ,
                            ],
             }
         return reqs
 
     # the list of things passed to the js plugin
-    def json_settings_list (self): return ['plugin_uuid','query_uuid']
+    def json_settings_list (self): return ['plugin_uuid', 'dom_id', 'query_uuid', 'query_all_uuid']
index cfd2d94..86f3638 100644 (file)
@@ -1,11 +1,40 @@
-.senslab-map {
-  width: 800px;
-  height: 500px;
-  height: 100%;
+.senslabmap {
+  margin: 10px;
+  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+  font-size: 13px;
+  line-height: 18px;
+  color: #333333;
+  background-color: #ffffff;
 }
 
 #div3d {
-    width: 100%; 
-    height: 500px; 
-    background-color: #202020;
+  height: 500px;
+  background-color: #202020;
+  z-index:-1
+}
+
+#selectionbox {
+  text-align: center;
+  padding:2px
+}
+
+#infobox {
+  text-align: center
+}
+
+#node_alive {
+  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAFRQAABUUBbA3bdwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAFHSURBVDiNtdSxSkJxFMfx7znVtZS2wFdIaLHBpcUl4UYPkRQNCU7hQ0RTYiAk9RDRhRpqaXHIJbBXEJwErXuj/2lJK60ovP3G/+F8/mf6iZkxnnIgib4ubIKsmpAFsm+jlhgtsLuUezw/8i0c35VxcOsquabGCcjyxE+fYg9O2DlbH9x+CRZvZJ4weSjCHiA/Y++qGcckBvuneXsCmB1ONEoemFD6JTQ6SISSREkHlEcXbl+mfIOLP2KfZdhoFPqB7F4vLj1HL/dAehoQ6Mx5Mysahc6PAQNIR6HzVdRyMWAAiFpOzYgNNCOngmXiAgXLqCHtuEBD2ipCMy5QhKaak9hAc9JUL6EB0InB63gJDbSe73UFitNqAsV6vtdVgEahHwhUp8CqjUI/ANDho/MGFTNqwGRBfh8zo+a8QWWE/1sffsw0jf0KmsOTrB0wIw8AAAAASUVORK5CYII=');
+  
+}
+
+#node_down {
+  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAFRQAABUUBbA3bdwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAEqSURBVDiNtdSxSkJxFMfx7zkGtQgKgU8gJLRcBZcmxxu9hNCU0BQ9RLSJTT1GdEenFrn87xIY+AQXhCu41OA9DdZNNMLy3288f87n/5uOmBkbqdf3KZfPMGsCAWYBACIJkCDimM8fmEze1ldlAwyCE8zuETna/GklZi+InJMkT9+Dnc4Bs9ktcAHIj9gKC9xRqVwxHL4C7BVPWXaDSG9LqCgE9MiyHLj8athshpg9/hJbo+UU5yKxVuuQxeIZqO0EQkqpdKzkeegBA6iR56ECbQ/YZ9qKmT/QrK1AwxsIDQXGHsGxIjLyxomMFPAHwkhRjYDUA5aiGilxPEWkuzMn0iWOpwqAcxFm/T9jZn2ciwC0GFar18CA5QXZmgIGH7vLov93D1ezw8V+B8jhfgJI7kYcAAAAAElFTkSuQmCC');
+}
+
+#node_selected {
+  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAFRQAABUUBbA3bdwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAE0SURBVDiNtdS/SoJxFMbx7zn0xyGhIfAGGhJaTHFpaTW6iISUSGqKLiLaxChq6CKid21pEcklsKEbEBqCGizhfRrMF9SiP+/bM57D+fzO8OOYJMZj9YdZUk8biBXwHCj30WlD2Ma4pTd/qd3F14nZcdBOWqu4nQNLEy+N5p5QW9ou3HwK2sV1ire5I7AdwL7BhhHomJmXfW2u9QCmolY/fQjUfghFC4HV6KdDYC/a0M5aJWRXv8TGaK2rUgiM09YCcAdkYoHQBZYdUykBDCCDqeTIiwlgg8iLjik50FR0RDYxUGQdo5MYaHQcWTMxUNZ0LEwOtLDpyAIGfyhuusgCVzX/iKkcmzOVVc0/OoAqhQCj/neMuiqFAMCj4vTzAagBTB7IryNQYzA7XPS/7uFIMcbFfgcJcoL5SKOsjQAAAABJRU5ErkJggg==');
+}
+
+#node_used {
+  background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAABHNCSVQICAgIfAhkiAAAAZJJREFUOI2t1D1LQlEcx/Hf+R/NTMKsawldqRZ7JDBIhyAIpwu9A6egpmrsbUQQ1FDQJL2B4E49LC0OuUQPToUKehFTosy6x9OQF8qiQu93Ohw4n7P9WDQaxQ+53Kx70Uv9MwEaDg85JsIAcG9epfL1u1SlblxU5eMRgFrzQ9YMOtAxt+CK7wedobGffrLKvKVvTmuJZROv55/vuaqq1rlzmE9tLXpWd33c7/8NAwAv71MmO+aXKsLwl6VxAsD8Ag7xqc2YO75GIPYXZkUgNuKcjpREwVuRhv5xB8DFurSYO77+X6i5mDu+7mJdmgUqWufKQauYVcNQyMN6tF4eGGgX7OWBAQ/r0UghNdIuZqWQGqGgY9Q2MOgYjdAgD43bBQ7y0DjlRPraLjAn0teUMW+TdoEZ8zZJxXrWNrBYzybpSZb1ksgX2sVKIl94kmWdABT1l72ldsGGUSQAqMln/bia2G4VO64mtmvyWQc+jUNFGqcPouALOidn/zsQJoQ8qx7u3IvLDTTWxvY9/AY2anmx3wGj5aLJgOrlPgAAAABJRU5ErkJggg==');
 }
index 8075be9..1fe7810 100644 (file)
@@ -1,80 +1,51 @@
-/**
- * Description: SensLab display of 3D-geolocated data
- * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA
- * License: GPLv3
- */
-
-// xxx TODO -- this plugin has never been tested 
-// update_map looks suspiciously empty...
-// in addition it could use a bit of cleaning like what was done for the first plugins
-// especially wrt using 'instance' and 'data' in such a confusing way
-
-(function( $ ){
-
-    $.fn.SensLabMap = function( method ) {
-       /* Method calling logic */
-       if ( methods[method] ) {
-           return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
-       } else if ( typeof method === 'object' || ! method ) {
-           return methods.init.apply( this, arguments );
-       } else {
-           $.error( 'Method ' +  method + ' does not exist on $.SensLabMap' );
-       }    
-    };
-
-    var methods = {
-       init : function( options ) {
-           return this.each(function(){
-               var $this = $(this),
-               data = $this.data('SensLabMap'), SensLabMap = $('<div />', { text : $this.attr('title') });
-               // If the plugin hasn't been initialized yet
-               if ( ! data ) {
-                   /* Plugin initialization */
-                   //google.load('maps', '3', { other_params: 'sensor=false' });
-                   //google.setOnLoadCallback(initialize);
-                   init();
-                   /* End of plugin initialization */
-                   $(this).data('SensLabMap', {
-                       plugin_uuid: options.plugin_uuid,
-                       query_uuid: options.query_uuid,
-                       target : $this,
-                       SensLabMap : SensLabMap
-                   });
-                   /* Subscribe to query updates */
-                   $.subscribe('/results/' + options.query_uuid + '/changed', {instance: $this}, update_map);
-               }
-           });
-       },
-       destroy : function( ) {
-            return this.each(function(){
-               var $this = $(this), data = $this.data('SensLabMap');
-               $(window).unbind('SensLabMap');
-               data.SensLabMap.remove();
-               $this.removeData('SensLabMap');
-           });
-       },
-/*
-    reposition : function( ) { // ... },
-    show : function( ) { // ... },
-    hide : function( ) { // ... },
-*/
-       update : function( content ) { 
-            // should be made a private function
-            set3dsize()
-       },
-  };
-
-    /* Private methods */
-    function update_map(e, rows) {
-        var $plugindiv = e.data.instance;
-       $plugindiv.closest('.need-spin').spin(false);
-       
-        if(rows) {
-           /* TODO rendering */   
-        } else {
-           alert('error');
-        }
-       
+(function($){
+  var SensLabMap = Plugin.extend({
+    init: function(options, element) {
+      this._super(options, element);
+      
+      this.elmt().on('show', this, this.on_show);
+      
+      this.method = query.object;
+      
+      /* Setup query and record handlers */
+      this.listen_query(options.query_uuid);
+      this.listen_query(options.query_all_uuid, 'all');
+      
+      /* GUI setup and event binding */
+      this.initialize_map();
+    },
+    
+    initialize_map: function() {
+      this.nodes = [];
+      this.id = 0;
+      init();
+    },
+    
+    refresh: function() {
+      console.log("refresh");
+      myrender();
+    },
+    
+    on_show: function(e) {
+      e.data.refresh();
+    },
+    
+    on_all_new_record: function(n) {
+      // format is : [name, x, y, z, uid, state]
+      // state = "Busy", "Alive" or "Suspected"
+      if (n.x == null || n.y == null || n.z == null) {
+        console.log("Warning: no coord for " + n.hrn);
+        return;
+      }
+      this.id++;
+      node = [this.id, n.x, n.y, n.z, this.id, n.boot_state];
+      this.nodes.push(node);
+    },
+    
+    on_all_query_done: function() {
+      drawNodes(this.nodes);
+      parseNodebox();
     }
-
-})( jQuery );
+  });
+  $.plugin('SensLabMap', SensLabMap);
+})(jQuery);
index cf70e81..33ae659 100644 (file)
@@ -1,17 +1,8 @@
-\r
-// Various global variables\r
-var mouseX = 0, mouseY = 0,\r
-                       camera, scene, renderer, projector;\r
-var sTestEventType = 'mousedown';\r
-//var window3DWidth = window.innerWidth * 0.8;\r
-//var window3DHeight=window.innerHeight*0.75;\r
-var window3DWidth, window3DHeight;\r
-var offX, offY;\r
+// Various global variables\r
+var mouseX = 0, mouseY = 0, camera, scene, renderer, projector;\r
+\r
 // Camera parameters\r
-phi = -100, theta = 0, distance = 150;\r
-var rcount = 0;\r
-// Text display\r
-var info, nodelist, help;\r
+var phi = -100, theta = 0, distance = 130;\r
 \r
 // graphical nodes\r
 var objects = [];\r
@@ -21,322 +12,331 @@ var selectedNodes = [];
 \r
 var div3d, nodebox, infobox;\r
 \r
-function init() {\r
-    var particles, particle;\r
-\r
-    // jordan : modifier document.getElementById\r
-    div3d = jQuery('#div3d');\r
-    nodebox = jQuery('#nodebox');\r
-    infobox = jQuery('#infobox');\r
-    titlebox = jQuery('#titlebox');\r
-    // offset also\r
-    var offset = div3d.offset();\r
-    offY = offset.top;\r
-    offX = offset.left;\r
-\r
-    titlebox.innerHTML = 'Grenoble Site ' + nodes_gre.length + " nodes";\r
-    infobox.innerHTML = 'Node info : ';\r
-\r
-    nodebox.value = "";\r
-\r
-    camera = new THREE.PerspectiveCamera(75, window3DWidth / window3DHeight, 1, 10000);\r
-\r
-    scene = new THREE.Scene();\r
+function onResize() {\r
+  renderer.setSize(div3d.offsetWidth, div3d.offsetHeight);\r
+  camera.aspect = div3d.offsetWidth / div3d.offsetHeight;\r
+  camera.updateProjectionMatrix();\r
+  myrender();\r
+}\r
 \r
-    renderer = new THREE.CanvasRenderer();\r
+function getCenter(nodes) {\r
+  var xmin = 0, ymin = 0, zmin = 0;\r
+  var xmax = 0, ymax = 0, zmax = 0;\r
+  \r
+  for (var i = 0; i < nodes.length; i++) {\r
+    if (nodes[i][1] > xmax) xmax = nodes[i][1];\r
+    if (nodes[i][1] < xmin) xmin = nodes[i][1];\r
+    if (nodes[i][2] > ymax) ymax = nodes[i][2];\r
+    if (nodes[i][2] < ymin) ymin = nodes[i][2];\r
+    if (nodes[i][3] > zmax) zmax = nodes[i][3];\r
+    if (nodes[i][3] < zmin) zmin = nodes[i][3];\r
+  }\r
+  return {x: (xmax + xmin) / 2, y: (ymax + ymin) / 2, z: (zmax + zmin) / 2};\r
+}\r
 \r
-    // jordan XXX div3d.appendChild(renderer.domElement);\r
-    div3d.append(renderer.domElement);\r
+function debugaxis(axisLength) {\r
+  var v = function(x, y, z) {\r
+    return new THREE.Vertex(new THREE.Vector3(x, y, z));\r
+  }\r
+  \r
+  var createAxis = function (p1, p2, color) {\r
+    var lineGeometry = new THREE.Geometry();\r
+    var lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 });\r
+    lineGeometry.vertices.push(p1, p2);\r
+    var line = new THREE.Line(lineGeometry, lineMat);\r
+    scene.add(line);\r
+  }\r
+  \r
+  createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000);\r
+  createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00);\r
+  createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF);\r
+};\r
 \r
-    window.addEventListener('resize', set3dsize, false);\r
-    scene.add(camera);\r
-    set3dsize();\r
+function drawNodes(nodes) {\r
+  var geometry = new THREE.Geometry();\r
+  var center = getCenter(nodes);\r
+  \r
+  onResize();\r
+  for (var i = 0; i < nodes.length; i++) {\r
+    var material = new THREE.ParticleCanvasMaterial({\r
+      color: 0xffffff,\r
+      program: function (context) {\r
+        context.beginPath();\r
+        context.arc(0, 0, 1, 0, Math.PI * 2, true);\r
+        context.closePath();\r
+        context.fill();\r
+      }\r
+    });\r
+    var particle = new THREE.Particle(material);\r
+    particle.name = nodes[i][0];\r
+    particle.position.x = nodes[i][1] - center.x;\r
+    particle.position.y = nodes[i][2] - center.y;\r
+    particle.position.z = nodes[i][3] - center.z;\r
+    particle.uid = nodes[i][4];\r
+    particle.state = nodes[i][5];\r
+    particle.position.multiplyScalar(10);\r
+    particle.scale.x = particle.scale.y = 1;\r
+    scene.add(particle);\r
+    \r
+    var vertex = new THREE.Vertex(particle.position);\r
+    geometry.vertices.push(vertex);\r
+    objects.push(particle)\r
     \r
-\r
-    var PI2 = Math.PI * 2;\r
-    var geometry = new THREE.Geometry();\r
-\r
-    // let's find the center of the nodes\r
-    xmin = ymin = zmin = 0;\r
-    xmax = ymax = zmax = 0;\r
-\r
-    for (var i = 0; i < nodes_gre.length; i++) {\r
-        if (nodes_gre[i][1] > xmax) xmax = nodes_gre[i][1];\r
-        if (nodes_gre[i][1] < xmin) xmin = nodes_gre[i][1];\r
-        if (nodes_gre[i][2] > ymax) ymax = nodes_gre[i][2];\r
-        if (nodes_gre[i][2] < ymin) ymin = nodes_gre[i][2];\r
-        if (nodes_gre[i][3] > zmax) zmax = nodes_gre[i][3];\r
-        if (nodes_gre[i][3] < zmin) zmin = nodes_gre[i][3];\r
-    }\r
-\r
-    xcenter = (xmax + xmin) / 2;\r
-    ycenter = (ymax + ymin) / 2;\r
-    zcenter = (zmax + zmin) / 2;\r
-\r
-    // display nodes as TREE particles\r
-    for (var i = 0; i < nodes_gre.length; i++) {\r
-        material = new THREE.ParticleCanvasMaterial({\r
-            color: 0xffffff,\r
-            program: function (context) {\r
-                context.beginPath();\r
-                context.arc(0, 0, 1, 0, PI2, true);\r
-                context.closePath();\r
-                context.fill();\r
-            }\r
-        });\r
-        particle = new THREE.Particle(material);\r
-        particle.name = nodes_gre[i][0];\r
-        particle.position.x = nodes_gre[i][1] - xcenter;\r
-        particle.position.y = nodes_gre[i][2] - ycenter;\r
-        particle.position.z = nodes_gre[i][3] - zcenter;\r
-        particle.position.multiplyScalar(10);\r
-        particle.scale.x = particle.scale.y = 1;\r
-        scene.add(particle);\r
-        v = new THREE.Vertex(particle.position);\r
-        geometry.vertices.push(v);\r
-        objects.push(particle)\r
-    }\r
-\r
     debugaxis(10);\r
-    // a projector is needed to find which node is under the mouse\r
-    projector = new THREE.Projector();\r
-\r
-    nodebox.onkeyup = parseNodebox;\r
-    // set mouse event handlers // TODO jordan\r
-    document.onmousedown = OnMouseDown;\r
-    document.onmouseup = OnMouseUp;\r
-    document.onmousemove = displayNodeInfo;\r
-    if (window.addEventListener)\r
-    /** DOMMouseScroll is for mozilla. */\r
-        window.addEventListener('DOMMouseScroll', wheel, false);\r
-    /** IE/Opera. */\r
-    window.onmousewheel = document.onmousewheel = wheel;\r
     myrender();\r
+  }\r
 }\r
 \r
-function set3dsize() {\r
-    // jordan\r
-    var offset = div3d.offset();\r
-    offY = offset.top;\r
-    offX = offset.left;\r
-    window3DWidth = div3d.width();\r
-    window3DHeight = div3d.height();\r
-    renderer.setSize(window3DWidth, window3DHeight);\r
-\r
-    camera.aspect = window3DWidth / window3DHeight;\r
-    camera.updateProjectionMatrix();\r
-\r
-    myrender();\r
+function init(nodes) {\r
+  div3d = document.getElementById('div3d');\r
+  nodebox = document.getElementById('nodebox');\r
+  infobox = document.getElementById('infobox');\r
+  \r
+  infobox.innerHTML = 'Node info : ';\r
+  nodebox.value = "";\r
+  \r
+  camera = new THREE.PerspectiveCamera(75, div3d.offsetWidth / div3d.offsetHeight, 1, 10000);\r
+  scene = new THREE.Scene();\r
+  renderer = new THREE.CanvasRenderer();\r
+  projector = new THREE.Projector();\r
+  \r
+  div3d.appendChild(renderer.domElement);\r
+  \r
+  window.addEventListener('resize', onResize, false);\r
+  scene.add(camera);\r
+  \r
+  nodebox.onkeyup = parseNodebox;\r
+  \r
+  div3d.onmousedown = OnMouseDown;\r
+  div3d.onmouseup = OnMouseUp;\r
+  div3d.onmousemove = displayNodeInfo;\r
+  if (div3d.addEventListener) {\r
+    div3d.addEventListener('DOMMouseScroll', wheel, false); // mozilla\r
+  }\r
+  div3d.onmousewheel = wheel; // IE & Opera\r
 }\r
 \r
 function sortfunction(a, b) {\r
-    return (a - b) //causes an array to be sorted numerically and ascending\r
+  return (a - b) //causes an array to be sorted numerically and ascending\r
 }\r
 \r
 // factorize the expanded list in selectedNode to produce dash intervals\r
 // 1,2,3,5,9  -> 1-3,5,9\r
 function factorize() {\r
-    var fact = [];\r
-    var previous = 0;\r
-    var intervalStart = 0;\r
-    selectedNodes.sort(sortfunction);\r
-    for (j = 0; j < selectedNodes.length; j++) {\r
-        if (intervalStart) {\r
-            // we are in an interval\r
-            if (selectedNodes[j] == previous + 1) {\r
-                // interval grows\r
-                previous += 1;\r
-            } else {\r
-                // end of interval\r
-                fact.push(intervalStart + "-" + previous);\r
-                intervalStart = 0;\r
-                previous = selectedNodes[j];\r
-            }\r
-        } else {\r
-            // we are not in an interval\r
-            if (selectedNodes[j] == previous + 1) {\r
-                // let's begin an interval\r
-                intervalStart = previous;\r
-                previous += 1;\r
-            } else {\r
-                if (previous) fact.push(previous);\r
-                previous = selectedNodes[j];\r
-            }\r
-        }\r
-    } // for end \r
-    // at the end of the loop, two cases\r
-    // we were still in an interval, then add it to the result\r
-    // we were not in an interval, then add the last selectednode (previous)\r
+  var fact = [];\r
+  var previous = 0;\r
+  var intervalStart = 0;\r
+  selectedNodes.sort(sortfunction);\r
+  for (j = 0; j < selectedNodes.length; j++) {\r
     if (intervalStart) {\r
+      // we are in an interval\r
+      if (selectedNodes[j] == previous + 1) {\r
+        // interval grows\r
+        previous += 1;\r
+      } else {\r
+        // end of interval\r
         fact.push(intervalStart + "-" + previous);\r
+        intervalStart = 0;\r
+        previous = selectedNodes[j];\r
+      }\r
     } else {\r
-        if (previous) fact.push(previous);\r
+      // we are not in an interval\r
+      if (selectedNodes[j] == previous + 1) {\r
+        // let's begin an interval\r
+        intervalStart = previous;\r
+        previous += 1;\r
+      } else {\r
+        if (previous) {\r
+          fact.push(previous);\r
+        }\r
+        previous = selectedNodes[j];\r
+      }\r
     }\r
-    return fact;\r
+  } // for end\r
+  // at the end of the loop, two cases\r
+  // we were still in an interval, then add it to the result\r
+  // we were not in an interval, then add the last selectednode (previous)\r
+  if (intervalStart) {\r
+    fact.push(intervalStart + "-" + previous);\r
+  } else if (previous) {\r
+    fact.push(previous);\r
+  }\r
+  return fact;\r
 }\r
 \r
 // expand a list of nodes containing dash intervals\r
 // 1-3,5,9 -> 1,2,3,5,9\r
-function expand(factExp) {\r
-    exp = [];\r
-    for (i = 0; i < factExp.length; i++) {\r
-        dashExpression = factExp[i].split("-");\r
-        if (dashExpression.length == 2) {\r
-            for (j = parseInt(dashExpression[0]); j < (parseInt(dashExpression[1]) + 1); j++)\r
-                exp.push(j);\r
-        } else exp.push(parseInt(factExp[i]));\r
+function expand(input) {\r
+  var factorized = input.split(",");\r
+  var expanded = [];\r
+  for (var i = 0; i < factorized.length; i++) {\r
+    var d = factorized[i].split("-");\r
+    if (d.length == 2) {\r
+      for (var j = parseInt(d[0]); j < parseInt(d[1]) + 1; j++) {\r
+        expanded.push(j);\r
+      }\r
+    } else {\r
+      expanded.push(parseInt(factorized[i]));\r
+    }\r
+  }\r
+  expanded.sort(sortfunction);\r
+  for (var i = 1; i < expanded.length; i++) {\r
+    if (expanded[i] == expanded[i - 1]) {\r
+      expanded.splice(i--, 1);\r
     }\r
-    exp.sort(sortfunction);\r
-    for (var i = 1; i < exp.length; i++) { if (exp[i] == exp[i - 1]) { exp.splice(i--, 1); } }\r
-    return exp;\r
+  }\r
+  return expanded;\r
 }\r
 \r
 function parseNodebox() {\r
-    input = nodebox.value;\r
-    selectedNodes = expand(input.split(","));\r
-    myrender();\r
+  selectedNodes = expand(nodebox.value);\r
+  myrender();\r
 }\r
 \r
-function debugaxis(axisLength) {\r
-    //Shorten the vertex function\r
-    function v(x, y, z) {\r
-        return new THREE.Vertex(new THREE.Vector3(x, y, z));\r
-    }\r
-\r
-    //Create axis (point1, point2, colour)\r
-    function createAxis(p1, p2, color) {\r
-        var line, lineGeometry = new THREE.Geometry(),\r
-                    lineMat = new THREE.LineBasicMaterial({ color: color, lineWidth: 2 });\r
-        lineGeometry.vertices.push(p1, p2);\r
-        line = new THREE.Line(lineGeometry, lineMat);\r
-        scene.add(line);\r
-    }\r
-\r
-    createAxis(v(0, 0, 0), v(axisLength, 0, 0), 0xFF0000);\r
-    createAxis(v(0, 0, 0), v(0, axisLength, 0), 0x00FF00);\r
-    createAxis(v(0, 0, 0), v(0, 0, axisLength), 0x0000FF);\r
-};\r
-\r
 // set the camera position according two angles theta and phi and the distance\r
 // and display the scene\r
 function myrender() {\r
-    //infobox.innerHTML = " Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z\r
-    //                + " - " + theta + "," + phi + ","+ distance;\r
-    //infobox.innerHTML = selectedNodes;\r
-    camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360);\r
-    camera.position.y = distance * Math.sin(this.phi * Math.PI / 360);\r
-    camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);\r
-    camera.lookAt(scene.position);\r
-    camera.updateMatrix();\r
-\r
-    for (i = 0; i < objects.length; i++)\r
-        if (selectedNodes.indexOf(objects[i].name) != -1) objects[i].material.color.setHex(0xff0000);\r
-        else objects[i].material.color.setHex(0xffffff);\r
-    renderer.render(scene, camera);\r
+  camera.position.x = distance * Math.sin(theta * Math.PI / 360) * Math.cos(phi * Math.PI / 360);\r
+  camera.position.y = distance * Math.sin(this.phi * Math.PI / 360);\r
+  camera.position.z = distance * Math.cos(this.theta * Math.PI / 360) * Math.cos(this.phi * Math.PI / 360);\r
+  camera.lookAt(scene.position);\r
+  camera.updateMatrix();\r
+  \r
+  for (i = 0; i < objects.length; i++) {\r
+    if (selectedNodes.indexOf(objects[i].name) != -1) {\r
+      objects[i].material.color.setHex(0x0099CC);\r
+    } else {\r
+      if (objects[i].state == "Busy") {\r
+        objects[i].material.color.setHex(0x9943BE);\r
+      } else if (objects[i].state == "Alive") {\r
+        objects[i].material.color.setHex(0x7FFF00);\r
+      } else {\r
+        objects[i].material.color.setHex(0xFF3030);\r
+      }\r
+    }\r
+  }\r
+  renderer.render(scene, camera);\r
 }\r
 \r
-// rigthbutton is used for rotations \r
+// rigthbutton is used for rotations\r
 function onDocumentMouseMoveRot(event) {\r
-    NewmouseX = event.clientX;\r
-    NewmouseY = event.clientY;\r
-    DeltaX = NewmouseX - mouseX;\r
-    DeltaY = NewmouseY - mouseY;\r
-\r
-    mouseX = NewmouseX;\r
-    mouseY = NewmouseY;\r
-\r
-    theta -= DeltaX;\r
-    phi += DeltaY;\r
-    if (phi > 180) phi = 180;\r
-    if (phi < -180) phi = -180;\r
-    myrender();\r
+  var NewmouseX = event.clientX;\r
+  var NewmouseY = event.clientY;\r
+  var DeltaX = NewmouseX - mouseX;\r
+  var DeltaY = NewmouseY - mouseY;\r
+  \r
+  mouseX = NewmouseX;\r
+  mouseY = NewmouseY;\r
+  \r
+  theta -= DeltaX;\r
+  phi += DeltaY;\r
+  if (phi > 180) phi = 180;\r
+  if (phi < -180) phi = -180;\r
+  myrender();\r
 }\r
 // mousewheel is used for zoom\r
 function Zoom(delta) {\r
-    distance += delta * 5;\r
-    myrender();\r
+  distance += delta * 5;\r
+  myrender();\r
 }\r
 \r
 // return the graphical node under the mouse\r
 function findNodeUnderMouse(event) {\r
-    var vector = new THREE.Vector3(((event.clientX - offX) / window3DWidth) * 2 - 1, -((event.clientY - offY) / window3DHeight) * 2 + 1, 0.5);\r
-    projector.unprojectVector(vector, camera);\r
-    var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());\r
-    var intersects = ray.intersectObjects(objects);\r
-    if (intersects.length > 0) {\r
-        return intersects[0];\r
-    } else return null;\r
+  var x, y, z;\r
+  \r
+  event.preventDefault();\r
+  \r
+  x = ((event.clientX - div3d.offsetLeft) / div3d.offsetWidth) * 2 - 1;\r
+  y = -((event.clientY - div3d.offsetTop) / div3d.offsetHeight) * 2 + 1;\r
+  z = 0.5;\r
+  \r
+  var vector = new THREE.Vector3(x, y, z);\r
+  projector.unprojectVector(vector, camera);\r
+  \r
+  var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize());\r
+  var intersects = ray.intersectObjects(objects);\r
+  \r
+  if (intersects.length > 0) {\r
+    return intersects[0];\r
+  } else {\r
+    return null;\r
+  }\r
 }\r
 \r
 // display some info of the node under the mouse\r
 function displayNodeInfo(e) {\r
-    obj = findNodeUnderMouse(e);\r
-    if (obj) infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + nodes_gre[obj.object.id][4];\r
-    //    else infobox.innerHTML = e.clientX + "," + e.clientY + " - " + offX + "," + offY;\r
+  obj = findNodeUnderMouse(e);\r
+  if (obj) {\r
+    infobox.innerHTML = 'Node info : number ' + obj.object.name + " with id " + obj.object.uid;\r
+  }\r
 }\r
 \r
 // select/unselect nodes\r
 function toggleNode(obj) {\r
-    nodeId = obj.object.name;\r
-    i = selectedNodes.indexOf(nodeId);\r
-    if (i == -1) selectedNodes.push(nodeId);\r
-    else selectedNodes.splice(i, 1);\r
-    nodebox.value = factorize().join(",");\r
-    myrender();\r
+  var nodeId = obj.object.name;\r
+  var index = selectedNodes.indexOf(nodeId);\r
+  \r
+  if (index == -1) {\r
+    selectedNodes.push(nodeId);\r
+  } else {\r
+    selectedNodes.splice(index, 1);\r
+  }\r
+  nodebox.value = factorize().join(",");\r
+  myrender();\r
 }\r
 \r
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
 // Mouse handling functions\r
 //\r
 function OnMouseDown(e) {\r
-    var clickType = 'LEFT';\r
-    if (e.type != sTestEventType) return true\r
+  var clickType = 'LEFT';\r
+  if (e.type != 'mousedown') return true\r
     if (e.which) {\r
-        if (e.which == 3) clickType = 'RIGHT';\r
-        if (e.which == 2) clickType = 'MIDDLE';\r
-        //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z;\r
+      if (e.which == 3) clickType = 'RIGHT';\r
+      if (e.which == 2) clickType = 'MIDDLE';\r
+      //infobox.innerHTML = clickType + " - Cam Pos = " + camera.position.x + "," + camera.position.y + "," + camera.position.z;\r
     }\r
     mouseX = e.clientX;\r
-    mouseY = e.clientY;\r
-    if (clickType == 'RIGHT') {\r
-        document.onmousemove = onDocumentMouseMoveRot;\r
-    }\r
-    if (clickType == 'LEFT') {\r
-        obj = findNodeUnderMouse(e);\r
-        if (obj != null) toggleNode(obj);\r
-    }\r
+  mouseY = e.clientY;\r
+  if (clickType == 'RIGHT') {\r
+    document.onmousemove = onDocumentMouseMoveRot;\r
+  }\r
+  if (clickType == 'LEFT') {\r
+    obj = findNodeUnderMouse(e);\r
+    if (obj != null) toggleNode(obj);\r
+  }\r
 }\r
 \r
 function OnMouseUp(e) {\r
-    document.onmousemove = displayNodeInfo;\r
+  document.onmousemove = displayNodeInfo;\r
 }\r
 \r
 // This function was taken here : http://www.adomas.org/javascript-mouse-wheel/\r
 // Event handler for mouse wheel event.\r
 \r
 function wheel(event) {\r
-    var delta = 0;\r
-    if (!event) /* For IE. */\r
-        event = window.event;\r
-    if (event.wheelDelta) { /* IE/Opera. */\r
-        delta = event.wheelDelta / 120;\r
-    } else if (event.detail) { /** Mozilla case. */\r
-        /** In Mozilla, sign of delta is different than in IE.\r
-        * Also, delta is multiple of 3.\r
-        */\r
-        delta = -event.detail / 3;\r
-    }\r
-    /** If delta is nonzero, handle it.\r
-    * Basically, delta is now positive if wheel was scrolled up,\r
-    * and negative, if wheel was scrolled down.\r
-    */\r
-    if (delta)\r
-        Zoom(delta);\r
-    /** Prevent default actions caused by mouse wheel.\r
-    * That might be ugly, but we handle scrolls somehow\r
-    * anyway, so don't bother here..\r
-    */\r
-    if (event.preventDefault)\r
-        event.preventDefault();\r
-    event.returnValue = false;\r
-}          \r
+  var delta = 0;\r
+  if (!event) /* For IE. */\r
+    event = window.event;\r
+  if (event.wheelDelta) { /* IE/Opera. */\r
+    delta = event.wheelDelta / 120;\r
+  } else if (event.detail) { /** Mozilla case. */\r
+    /** In Mozilla, sign of delta is different than in IE.\r
+     * Also, delta is multiple of 3.\r
+     */\r
+    delta = -event.detail / 3;\r
+  }\r
+  /** If delta is nonzero, handle it.\r
+   * Basically, delta is now positive if wheel was scrolled up,\r
+   * and negative, if wheel was scrolled down.\r
+   */\r
+  if (delta)\r
+    Zoom(delta);\r
+  /** Prevent default actions caused by mouse wheel.\r
+   * That might be ugly, but we handle scrolls somehow\r
+   * anyway, so don't bother here..\r
+   */\r
+  if (event.preventDefault)\r
+    event.preventDefault();\r
+  event.returnValue = false;\r
+}\r
index c1c6599..c00ea64 100644 (file)
@@ -1 +1,18 @@
-<div class='senslab-map'><div id='div3d'></div></div>
+<div class="senslabmap">
+  <div class="row" id="maps">
+    <div class="span8 offset2">
+      <div id="selectionbox">
+        Selected Nodes <input type="text" placeholder="1-10,24,25" id="nodebox" />
+        <button class="btn" id="btnSave" value="Save">Save</button>
+      </div>
+      <div id="div3d" oncontextmenu="return false;"></div>
+      <div id="infobox"></div>
+      <div style="text-align:right">
+        <div id="node_alive"></div> Alive -
+        <div id="node_down"></div> Down -
+        <div id="node_selected"></div> Selected -
+        <div id="node_used"></div> Busy
+      </div>
+    </div>
+  </div>
+</div>
\ No newline at end of file