diff --git a/view/js/charts.js b/view/js/charts.js index 8c4f7a6..969400b 100644 --- a/view/js/charts.js +++ b/view/js/charts.js @@ -1,5 +1,10 @@ /* [1] Gestion du sociogramme =========================================================*/ + + + + + /* (0) On recupere les elements importants */ var SOCIOGRAM = { container: document.getElementById('sociogram'), @@ -8,9 +13,17 @@ var SOCIOGRAM = { request: { path: 'charts/network_data' }, response: null, nodes: null, - edges: null + edges: null, + rad: 500, + nodeDistance: 100, + arrange: null }; + + + + + /* (0.5) Surcharge graph */ // On recupere les voisins d'un noeud sigma.classes.graph.addMethod('nodeNeighbors', function(nodeId){ @@ -39,6 +52,17 @@ sigma.classes.graph.addMethod('nodeNeighbors', function(nodeId){ return neighbors; }); +// On recupere les voisins directs d'un noeud +sigma.classes.graph.addMethod('nodeDirectNeighbors', function(nodeId){ + // On retourne les voisins directs + return this.allNeighborsIndex[nodeId]; +}); + + + + + + /* (0.8) Initialisation de SIGMA */ SOCIOGRAM.sigma = new sigma({renderer: { container: SOCIOGRAM.container, 'type': 'canvas' }}); @@ -47,6 +71,11 @@ SOCIOGRAM.sigma = new sigma({renderer: { container: SOCIOGRAM.container, 'type': + + + + + /* (1) On recupere les informations via l'API */ api.send(SOCIOGRAM.request, function(response){ // Si erreur, on quitte @@ -56,6 +85,11 @@ api.send(SOCIOGRAM.request, function(response){ SOCIOGRAM.response = response; + + + + + /* (2) Parametrage de SIGMA */ SOCIOGRAM.sigma.settings({ defaultNodeColor: '#348ed8', @@ -64,32 +98,36 @@ api.send(SOCIOGRAM.request, function(response){ defaultHoverLabelBGColor: "#002147", defaultLabelHoverColor: "#fff", labelThreshold: 10, - defaultEdgeType: "curve" + defaultEdgeType: "line" }); + + + + + /* (3) On recupere la liste des noeuds */ SOCIOGRAM.nodes = []; - // On calcule l'angle min - var ang = 2*Math.PI / SOCIOGRAM.response.data.alter.length; - - // Parametres d'affichage - var ray = 500; - // Pour chaque alter for( var i = 0 ; i < SOCIOGRAM.response.data.alter.length ; i++ ){ SOCIOGRAM.nodes.push({ 'id': 'n-'+SOCIOGRAM.response.data.alter[i][0], 'label': SOCIOGRAM.response.data.alter[i][1], - 'x': ray+ ray*Math.cos(ang*i), - 'y': ray+ ray*Math.sin(ang*i), + 'x': 0, + 'y': 0, 'size': SOCIOGRAM.response.data.alter[i][2] }); } + + + + + /* (4) On recupere la liste des liens */ SOCIOGRAM.edges = []; @@ -103,15 +141,120 @@ api.send(SOCIOGRAM.request, function(response){ + + + + + /* (5) On ajoute nos noeuds */ for( var i = 0 ; i < SOCIOGRAM.nodes.length ; i++) SOCIOGRAM.sigma.graph.addNode(SOCIOGRAM.nodes[i]); + + + + + /* (6) On ajoute nos liens */ for( var i = 0 ; i < SOCIOGRAM.edges.length ; i++) SOCIOGRAM.sigma.graph.addEdge(SOCIOGRAM.edges[i]); + + + + + /* (7) Gestion des interactions */ + /* RETOURNE LA DISTANCE AVEC LE NOEUD LE PLUS PRES + * + * @x Abscisse du point + * @y Ordonnees du point + * + * @return distance Retourne la distance du noeud le plus proche + * + */ + SOCIOGRAM.nodeAt = function(x, y){ + var nodes = SOCIOGRAM.sigma.graph.nodes(); + var minDistance = null; + + for( nodeId in nodes ){ + var distance = Math.sqrt( Math.pow(x-nodes[nodeId].x, 2) + Math.pow(y-nodes[nodeId].y, 2) ); + if( minDistance == null || distance < minDistance ) + minDistance = distance; + } + + return minDistance; + }; + + + + /* POSITIONNE LES VOISINS AUTOUR DU NOEUD COURANT + * + * @nodeId Id du noeud courant + * @pos Contient {x, y} position initiale, sinon la position actuelle du noeud + * + */ + SOCIOGRAM.arrange = function(nodeId, pos, alone){ + var node = SOCIOGRAM.sigma.graph.nodes(nodeId); + + // Si le noeud est deja place, on ne fais rien + if( node.x != 0 || node.y != 0 ) return; + + var pos = (pos==null) ? {x: node.x, y: node.y} : pos; // On recupere la position + + // Tant que le noeud est trop proche d'un autre, on l'eloigne + // UNIQUEMENT si alone n'est pas NULL + if( alone ){ + while( SOCIOGRAM.nodeAt(pos.x, pos.y) < 2*SOCIOGRAM.nodeDistance ){ + pos = { + x: pos.x + 2*SOCIOGRAM.nodeDistance*Math.cos(Math.random()*2*Math.PI), + y: pos.y + 2*SOCIOGRAM.nodeDistance*Math.sin(Math.random()*2*Math.PI) + }; + } + } + + // On recupere les voisins directs + var neighborsId = SOCIOGRAM.sigma.graph.nodeDirectNeighbors(nodeId); + var neighbors = {}; + var neighborsCount = 0; + for( neighborId in neighborsId ){ + neighbors[neighborId] = SOCIOGRAM.sigma.graph.nodes(neighborId); + neighborsCount++; + } + + + // On positionne le noeud + node.x = pos.x; + node.y = pos.y; + + var angles = []; + + // On positionne chaque voisin si c'est pas deja fait + for( neighborId in neighbors ){ + var current = SOCIOGRAM.sigma.graph.nodes(neighborId); + // Si n'est pas deja positionne + if( current.x == 0 && current.y == 0 ){ + // On cherche un angle tant qu'il est pas trop pres d'un deja pris + var angle, alreadyUsed = false; + do{ + angle = Math.random()*2*Math.PI; + for( var i = 0 ; i < angles.length ; i++ ) + if( Math.abs(angle-angles[i]) > Math.PI/10 ){ + alreadyUsed = true; + break; + } + + }while( alreadyUsed ); + + current.x = pos.x + SOCIOGRAM.nodeDistance*Math.cos(angle); + current.y = pos.y + SOCIOGRAM.nodeDistance*Math.sin(angle); + SOCIOGRAM.arrange(current.id); + } + } + + SOCIOGRAM.sigma.refresh(); + }; + // On affiche que les voisins d'un noeud SOCIOGRAM.sigma.bind('clickNode', function(e){ var nodeId = e.data.node.id; @@ -129,13 +272,23 @@ api.send(SOCIOGRAM.request, function(response){ // On affiche tous les noeuds quand on clique dans le vide SOCIOGRAM.sigma.bind('clickStage', function(e){ - SOCIOGRAM.sigma.graph.nodes().forEach(function(n) { n.color = n.originalColor; }); + SOCIOGRAM.sigma.graph.nodes().forEach(function(n){ n.color = n.originalColor; }); SOCIOGRAM.sigma.refresh(); }); + + + + + /* (8) On affiche le graphique */ SOCIOGRAM.sigma.camera.ratio = 1.2; + + // On repartit les noeuds + SOCIOGRAM.sigma.refresh(); + SOCIOGRAM.sigma.graph.nodes().forEach(function(n){ SOCIOGRAM.arrange(n.id, null, true); }); + SOCIOGRAM.sigma.refresh(); });