2 normalize: function(node) {
5 if (node.component_name) { // wsn430-11.devlille.iot-lab.info
6 info = node.component_name.split(".");
7 } /*else if (node.hrn) { // iotlab.a8-11\.devgrenoble\.iot-lab\.info
8 var info = node.hrn.split("\\.");
9 info[0] = info[0].split(".")[1];
12 if (info && info[2] == "iot-lab" && info[3] == "info") {
13 node.arch = info[0].split("-")[0];
14 node.id = parseInt(info[0].split("-")[1]);
16 node.x = parseFloat(node.x);
17 node.y = parseFloat(node.y);
18 node.z = parseFloat(node.z);
19 node.selected = false;
20 node.normalized = true;
23 notify: function(node) {
24 console.log("[Notify] node " + node.id + " is " + node.selected);
26 createMaps: function($container, sites, nodes) {
28 var $menu = $("<ul id='sites-tabs' class='nav nav-tabs' data-tabs='sites-tabs'/>").appendTo($container);
29 var $maps = $("<div id='maps' class='tab-content' />").appendTo($container);
31 $.each(sites, function(i, site) {
32 var entry = $("<li><a href='#" + site + "' data-toggle='tab'>" + site + "</a></li>").appendTo($menu);
33 var $tab = $("<div class='tab-pane' id='" + site + "' />").appendTo($maps);
34 maps[site] = new Senslab.Map($tab);
35 maps[site].addNodes(nodes[site]);
38 $menu.find("li").eq(0).addClass("active");
39 $maps.find("div").eq(0).addClass("active");
42 $container.text("No nodes to display.");
47 Senslab.Map = function() {
51 "Suspected": 0xFF3030,
61 function Map($container, options) {
70 this.pointerDetectRay = new THREE.Raycaster();
71 this.pointerDetectRay.ray.direction.set(0, -1, 0);
72 this.projector = new THREE.Projector();
73 this.mouse2D = new THREE.Vector3(0, 0, 0);
75 this.renderer = new THREE.CanvasRenderer();
76 this.renderer.setSize(this.width, this.height);
78 this.camera = new THREE.PerspectiveCamera(75, this.width / this.height, 1, 10000);
80 this.scene = new THREE.Scene();
81 this.scene.add(this.camera);
83 this.updatePosition();
87 this.$nodeInputs = {};
89 $.each(archs, function(i, arch) {
90 self.$nodeInputs[arch] = $("<input type='text' placeholder='" + arch + "'>")
93 self.updateSelected(arch, expand($(this).val()));
98 var $canvas = $(this.renderer.domElement)
99 .mousemove(function(e) {
100 self.mouse2D.x = ((e.pageX - $canvas.offset().left) / $canvas.width()) * 2 - 1;
101 self.mouse2D.y = -((e.pageY - $canvas.offset().top) / $canvas.height()) * 2 + 1;
104 self.theta -= e.pageX - self.mouse2D.pageX;
105 self.phi += e.pageY - self.mouse2D.pageY;
111 self.mouse2D.pageX = e.pageX;
112 self.mouse2D.pageY = e.pageY;
114 self.updatePosition();
117 }).mousedown(function(e) {
121 self.pointerDetectRay = self.projector.pickingRay(self.mouse2D.clone(), self.camera);
122 var intersects = self.pointerDetectRay.intersectObjects(self.scene.children);
123 if (intersects.length > 0) {
124 var particle = intersects[0].object;
125 if (particle.data.boot_state != "Suspected") {
126 setSelected(particle, !particle.data.selected);
127 var $nodeInput = self.$nodeInputs[particle.data.arch];
128 $nodeInput.val(factorize(self.getNodesId(particle.data.arch)));
134 self.mouse2D.pageX = e.pageX;
135 self.mouse2D.pageY = e.pageY;
139 }).mouseup(function(e) {
146 }).mouseleave(function(e) {
148 }).mousewheel(function(e, delta) {
150 self.distance += delta * 5;
151 self.updatePosition();
155 $container.append($canvas);
158 Map.prototype.getNodesId = function(arch) {
159 var particles = this.scene.children;
161 for (var i = 0; i < particles.length; ++i) {
162 if (particles[i].data && particles[i].data.arch == arch && particles[i].data.selected) {
163 nodes.push(particles[i].id);
169 Map.prototype.addNodes = function(nodes) {
170 var center = getCenter(nodes);
172 nodes.sort(function(a, b) {
176 for(var i = 0; i < nodes.length; ++i) {
177 var material = new THREE.ParticleCanvasMaterial({program: circle});
178 var particle = new THREE.Particle(material);
179 particle.data = nodes[i];
180 particle.id = parseInt(nodes[i].id);
181 particle.position.x = (nodes[i].x - center.x) * 10;
182 particle.position.y = (nodes[i].y - center.y) * 10;
183 particle.position.z = (nodes[i].z - center.z) * 10;
184 particle.scale.x = particle.scale.y = 1;
186 this.scene.add(particle);
191 Map.prototype.updateSelected = function(arch, selectedNodes) {
192 var particles = this.scene.children;
193 for (var i = 0; i < particles.length; ++i) {
194 if (particles[i].data && particles[i].data.arch == arch && particles[i].data.boot_state != "Suspected") {
195 var particle = particles[i];
196 var selected = $.inArray(particle.id, selectedNodes) != -1;
197 if (particle.data.selected != selected) {
198 setSelected(particle, selected);
204 Map.prototype.updatePosition = function() {
205 this.camera.position.x = this.distance
206 * Math.sin(this.theta * Math.PI / 360)
207 * Math.cos(this.phi * Math.PI / 360);
208 this.camera.position.y = this.distance * Math.sin(this.phi * Math.PI / 360);
209 this.camera.position.z = this.distance
210 * Math.cos(this.theta * Math.PI / 360)
211 * Math.cos(this.phi * Math.PI / 360);
212 this.camera.lookAt(this.scene.position);
213 this.camera.updateMatrix();
216 Map.prototype.update = function() {
217 this.renderer.render(this.scene, this.camera);
220 function setSelected(particle, selected) {
221 particle.data.selected = selected;
223 Senslab.notify(particle.data);
226 function setColor(particle) {
227 var color = particle.data.selected ? colors["Selected"] : colors[particle.data.boot_state];
228 particle.material.color.setHex(color);
231 function getCenter(nodes) {
232 var xmin = 0, ymin = 0, zmin = 0;
233 var xmax = 0, ymax = 0, zmax = 0;
235 for (var i = 0; i < nodes.length; ++i) {
236 if (nodes[i].x > xmax) xmax = nodes[i].x;
237 if (nodes[i].x < xmin) xmin = nodes[i].x;
238 if (nodes[i].y > ymax) ymax = nodes[i].y;
239 if (nodes[i].y < ymin) ymin = nodes[i].y;
240 if (nodes[i].z > zmax) zmax = nodes[i].z;
241 if (nodes[i].z < zmin) zmin = nodes[i].z;
243 return {x: (xmax + xmin) / 2, y: (ymax + ymin) / 2, z: (zmax + zmin) / 2};
246 function factorize(nodes) {
249 var intervalStart = 0;
251 for (var i = 0; i < nodes.length; ++i) {
253 if (nodes[i] == prev + 1) {
256 factorized.push(intervalStart + "-" + prev);
261 if (nodes[i] == prev + 1) {
262 intervalStart = prev;
265 prev && factorized.push(prev);
270 factorized.push(intervalStart ? intervalStart + "-" + prev : prev);
271 return factorized.join(",");
274 function expand(input) {
275 var factorized = input.split(",");
277 for (var i = 0; i < factorized.length; ++i) {
278 var d = factorized[i].split("-");
280 for (var j = parseInt(d[0]); j < parseInt(d[1]) + 1; j++) {
284 expanded.push(parseInt(factorized[i]));
288 expanded.sort(function(a, b) {
292 for (var i = 1; i < expanded.length; i++) {
293 if (expanded[i] == expanded[i - 1]) {
294 expanded.splice(i--, 1);
300 function circle(context) {
302 context.arc(0, 0, 1, 0, Math.PI * 2, true);