//$("#univbris_welcome").hide(); //jQuery("#univbris_flowspace_selection").show(); /* d3 data */ var nIslands=[], //replace pad = 5, width = parseInt($("#topologyContainer").css("width")), /* Obtain width from container */ height = 400; //Islands area generation var p = width/height ny = Math.sqrt(nIslands/p), nx = Math.ceil(p*ny), ny = Math.ceil(ny), foci = []; if (nx*ny > nIslands){ if (nx > ny && (nx-1)*ny >= nIslands) nx--; else if( nx <= ny && nx*(ny-1) >= nIslands) ny--; } var aw = Math.floor((width-(nx+1)*pad)/nx), ah = Math.floor((height-(ny+1)*pad)/ny); for (i=0; i1) { p = [randomXToY(set.x0, set.x1), randomXToY(set.y0, set.y1) ]; d = getDistance(p); } } catch(err) { p = []; } return p; }; var epoints= []; for (i=0;i0){ $("#link_zoom_out img").css("background-color", "#666"); cur_zoom = cur_zoom - zoom; zoom_out_active = true; } else{ $("#target, svg, g").css("cursor", "move"); } } else if(zoom_out_active == true){ cur_zoom = cur_zoom + zoom; $("#link_zoom_out img").css("background-color", ""); $("#target, svg, g").css("cursor", "move"); zoom_out_active = false; } else{ cur_zoom = cur_zoom - zoom; zoom_out_active = false; $("#link_zoom_in img").css("background-color", ""); if((cur_zoom - zoom) > 0){ $("#link_zoom_out img").css("background-color", "#666"); zoom_out_active = true; } else{ $("#target, svg, g").css("cursor", "move"); } } }; function zoomReset(){ cur_zoom = 0.99; posx = 0; posy = 0; return redraw(); }; function click(){ if (zoom_in_active == true || zoom_out_active == true){ var mouseClick = d3.mouse(this); _x = -mouseClick[0]/2; _y = -mouseClick[1]/2; if(zoom_out_active == true){ _x = -_x/2; _y = -_y/2; } posx += _x; posy += _y; zoom_in_active = false; zoom_out_active = false; return redraw(); } }; function redraw() { // trans=[(Math.round(width/cur_zoom) - width)/2, (Math.round(height/cur_zoom) - height)/2]; trans = [posx, posy]; svg.transition() .duration(500) .attr('x', function(d){ return d.x; }) .attr('y', function(d){ return d.y; }) .attr("transform", "translate(" + trans +")" + "scale(" + cur_zoom + ")"); $("#link_zoom_in img").css("background-color",""); $("#link_zoom_out img").css("background-color",""); $("#target, svg, g").css("cursor", "move"); }; //Global position of the canvas var posx = 0; var posy = 0; /* Translation - bound to drag behavior */ dragMap = function(d) { //No drag while zoom option active if(zoom_in_active == false && zoom_out_active == false){ posx += d3.event.dx; posy += d3.event.dy; svg.attr('x', function(d) { return d.x; }) .attr('y', function(d) { return d.y; }) .attr("transform", "translate(" + posx + "," + posy + ") scale (" + cur_zoom + ")"); } }; /* Instantiation General parameters*/ var padding = 6, color = d3.scale.category10().domain(d3.range(nIslands)), radius = d3.scale.sqrt().range([0, 12]); var svg = d3.select("#target") .on("click", click) .append("svg") .attr("pointer-events", "all") .attr("width", width) .attr("height", height) .datum({x: 0, y: 0}) .call(d3.behavior.drag().on("drag", dragMap)) .append("svg:g").on("zoom", redraw) .attr("cursor", "move") // DATA VARIABLES var nodes = data.nodes; // Set color for each node nodes.forEach(function(d) { if (d.available != "False") { d.color = color(d.group%nIslands); } else { d.color = "#CCC"; } }); var links = data.links; // Modified version (Carolina) var force = d3.layout.force() .gravity(1/(2*nIslands)) .distance(200/nIslands) .friction(0.6) .size([width, height]) .nodes(nodes) .links(links) .start(); var EMPTY_ISLAND = "Island with no resources"; //XXX:Very ugly, needs improvement var islandsLocs = [] for (i = 0; i< nIslands; i++){ islandsLocs[i] = EMPTY_ISLAND; } nodeInitialPos = [] for (i = 0; i< nodes.length; i++){ nodeInitialPos[i] = [nodes[i].x, nodes[i].y]; if (islandsLocs[nodes[i].group] == EMPTY_ISLAND){ islandsLocs[nodes[i].group] = nodes[i].location; } } var dataislands = [] for (i = 0; i< nIslands; i++){ dataislands[i] = {rx: (aw/2 + ah/2)/2, ry: ah/2, cx:(foci[i].x0+foci[i].x1)/2, cy:(foci[i].y0+foci[i].y1)/2, group: i, location: islandsLocs[i]}; } var islands = svg.selectAll(".island") .data(dataislands) .enter().append("g") .attr("class", "island") var iellipses = islands.append("ellipse") .attr("rx", function(d) { return d.rx; }) .attr("ry", function(d) { return d.ry; }) .attr("cx",function(d) { return d.cx; }) .attr("cy", function(d) { return d.cy; }) .style("fill", function(d) { return color(d.group%nIslands); }) .style("stroke", function(d) { return color(d.group%nIslands);}) .style("opacity", 0.3) .style("stroke-opacity", 0.7) var ilabels = islands.append("text") .attr("text-anchor", "middle") .attr("y", function(d){ return d.cy + d.ry*0.9}) .attr("x", function(d){ return d.cx}) .attr("font-color", function(d) { return d3.rgb(color(d.group%nIslands)).darker(5); }) .style("opacity",1) .style("cursor", "default") .text(function(d) { return d.location }); //First ellipse animation on startup animate(); var link = svg.selectAll(".link") .data(links) .enter().append("line") .attr("class", "link"); link.on("click", function(d) { d3.select(this).style("stroke", function(d){return getLinkStyle(d, "click");})}); var node = svg.selectAll(".node") .data(nodes) .enter().append("g") .attr("class", "node") .call(force.drag) .call(d3.behavior.drag() .on("dragstart", function(d, i, e) { d.fixed = false; force.stop(); }) .on("drag", function(d, i) { d.px += d3.event.dx; d.py += d3.event.dy; d.x += d3.event.dx; d.y += d3.event.dy; d3.select(this).selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "drag");}) tick(); }) .on("dragend", function(d, i) { // d.fixed = true; // of course set the node to fixed so the force does not include the node in its auto positioning stuff //with the force.stop() it won't autopositioning, allowing to regroup the nodes d3.select(this).selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "dragstop");}) tick(); force.stop(); }) ); node.append("circle") .attr("r", function(d) { return d.radius; }) .style("stroke", function(d){return getNodeCircleStyle(d, "stroke");}) .style("fill", function(d){return getNodeCircleStyle(d, "fill");}); node.append("image") .attr("xlink:href", function (d) { return d.image; }) .attr("x", -8) .attr("y", -8) .attr("width", 16) .attr("height", 16) .attr("opacity", function(d) { return d.available=="False"?0.8:1; }) node.append("text") .attr("dx", 12) .attr("dy", ".35em") .text(function(d) { return d.name }); node.on("mouseover", function (d, i){ //tooltip.show(get_node_info_formated(d)); // Ugly hack to decode HTML tooltip.show($('
').html(d.description).text()); $("#selected_node_info").html("Selected " + d.type + ": " + d.nodeName + " at " + d.location); $("#selected_node_info").css("background-color", d.color ); $("#selected_node_info").css("text-shadow", "-3px 2px 4px #eee"); $("#selected_node_info").show(); } ) .on("mouseout", function() { $("#selected_node_info").css("background-color", "#ebf5ff"); //$("#selected_node_info").hide() tooltip.hide(); }) .on("click", function(d) { /* Only available AMs can be selected */ if (d.available != "False") { //checkTopologyLoops(d); d3.select(this).selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "click");}); } }) //Number of nodes in each Island var qNodes = []; for(i=0; i= 10) { fact = Math.floor(node_groups[o.group]/10); } else { fact = o.group+1; } // Carolina: when there are few nodes, avoid them to stay too far away from the center // AND when there are so many nodes avoid them to stay too near each others if(qNodes[o.group] < 5){ fact = fact * 2; } else { fact = fact/2; } try { o.y += k * fact * qNodes[o.group] * ((dataislands[o.group].cy) - o.y); o.x += k * fact * qNodes[o.group] * ((dataislands[o.group].cx) - o.x); } catch (err) { } }); node.each(collide(.5)); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")";}) .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); }); function redrawNodes(){ node.selectAll("circle").style("stroke", function(d){return getNodeCircleStyle(d, "stroke");}); link.style("stroke", function(d) {return getLinkStyle(d, "stroke");}); link.style("stroke-width", function(d) {return getLinkStyle(d, "stroke-width");}); } function tick() { link.attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.each(collide(.5)); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .attr("cx", d.x) .attr("cy", d.y); }; function animate(){ iellipses.attr("rx", function(d) { return d.rx; }) .style("display","block") .attr("ry", function(d) { return d.ry; }) .attr("cx",function(d) { return d.cx; }) .attr("cy", function(d) { return d.cy; }) .style("fill", function(d) { return color(d.group%nIslands); }) .style("stroke", function(d) { return color(d.group%nIslands);}) .style("opacity", 0.3) .style("stroke-opacity", 0.7) ilabels.attr("text-anchor", "middle") .attr("y", function(d){ return d.cy + d.ry*0.9}) .attr("x", function(d){ return d.cx}) .attr("font-color", function(d) { return d3.rgb(color(d.group%nIslands)).darker(5); }) .style("opacity",1) .text(function(d) { return d.location }); iellipses.transition() .style("stroke-width",3) .style("stroke", function(d) { return d3.rgb(color(d.group%nIslands)).brighter(10);}) .duration(1500) iellipses.transition() .delay(1500) .style("opacity",0) .duration(3000) ilabels.transition() .delay(1500) .style("opacity",0) .duration(3000); } function regroup(){ force.resume(); animate(); } function collide(alpha) { var quadtree = d3.geom.quadtree(nodes); return function(d) { var r = d.radius + radius.domain()[1] + padding, nx1 = d.x - r, nx2 = d.x + r, ny1 = d.y - r, ny2 = d.y + r; quadtree.visit(function(quad, x1, y1, x2, y2) { if (quad.point && (quad.point !== d)) { var x = d.x - quad.point.x, y = d.y - quad.point.y, l = Math.sqrt(x * x + y * y), r = d.radius + quad.point.radius + (d.color !== quad.point.color) * padding; if (l < r) { l = (l - r) / l * alpha; d.x -= x *= l; d.y -= y *= l; quad.point.x += x; quad.point.y += y; } } return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; }); }; }; $("#link_zoom_in").click(function(){ $("#target, svg, g").css("cursor", "url({%url img_media 'zoomin.png' %}),auto"); }); $("#link_zoom_out").click(function(){ $("#target, svg, g").css("cursor", "url({%url img_media 'zoomout.png' %}),auto" ); });