/**
* Módulo red, utilizado crear y gestionar la red que es generada del resultado del analísis de comunidad ecológica.
*
* @namespace net_module
*/
var net_module = (function(verbose, url_zacatuche, map_module_net) {
var _url_zacatuche = url_zacatuche;
var _map_module_net = map_module_net;
var _VERBOSE = verbose;
var _toastr = toastr;
var iTrans;
var _language_module_net;
var _linkedByIndex = {};
var _color = d3.scale.category10();
var _highlight_color = "#B4FC00"; //"red"; //"#48D7D5";
var _highlight_linked_color = "#04C4FE"; //"red"; //"#48D7D5";
var _map_conected = d3.map([]);
var _legend_groups = [];
/**
* Método setter del módulo de internacionalización.
*
* @function setLanguageModule
* @public
* @memberof! net_module
*
* @param {object} languageModule - Módulo de internacionalización
*/
function setLanguageModule(languageModule) {
_language_module_net = languageModule;
_iTrans = _language_module_net.getI18();
}
/**
* Método setter de las las leyendas de los grupos de variables.
*
* @function setLegendGroup
* @public
* @memberof! net_module
*
* @param {array} legend_groups - Array con las leyendas de los grupos de variables seleccioandos en el analísis de comunidad ecológica.
*/
function setLegendGroup(legend_groups) {
_legend_groups = legend_groups;
}
/**
* Éste método inicializa variables y componentes que son necesarios para la creación de la red y asigna a una variable global una instancia del módulo de lenguaje.
*
* @function _netConfigure
* @private
* @memberof! net_module
*
* @param {object} languageModule - Módulo de internacionalización
* @param {type} s_filters - Array con los grupos de variables source utlizados en el analísis de comunidad ecológica.
* @param {type} t_filters - Array con los grupos de variables target utlizados en el analísis de comunidad ecológica.
*/
function _netConfigure(language_module, s_filters, t_filters) {
_VERBOSE ? console.log("_netConfigure") : _VERBOSE;
_toastr.options = {
"debug": false,
"onclick": null,
"fadeIn": 300,
"fadeOut": 1000,
"timeOut": 2000,
"extendedTimeOut": 2000,
"positionClass": "toast-bottom-center",
"preventDuplicates": true,
"progressBar": true
};
$("#send_email").click(function(e) {
// _VERBOSE ? console.log($("#email_address")) : _VERBOSE;
_VERBOSE ? console.log($("#email_address")[0].validity["valid"]) : _VERBOSE;
if ($("#email_address")[0].validity["valid"]) {
email = $("#email_address").val();
milliseconds = new Date().getTime();
// d3.json(_url_trabajo + "t=" + milliseconds)
d3.json(_url_zacatuche + "t=" + milliseconds)
.header("Content-Type", "application/json")
.post(
JSON.stringify({
qtype: "getEdges",
download: true,
mail: email,
s_tfilters: s_filters,
t_tfilters: t_filters,
ep_th: 0.0
}),
function(error, d) {
$('#modalMail').modal('hide');
if (error) {
_VERBOSE ? console.log(error) : _VERBOSE;
toastr.error("Error al enviar el archivo");
throw error;
}
// _VERBOSE ? console.log(d) : _VERBOSE;
_toastr.success("Archivo enviado por correo electrónico");
});
}
else {
alert("Correo invalido")
}
});
_language_module_net = language_module;
_iTrans = _language_module_net.getI18();
}
/**
* Éste método genera una instancia de la red.
*
* @function createNet
* @public
* @memberof! net_module
*
* @param {json} json - Json que contiene los nodos y los enlaces resultado del análisis de communidad ecológica
* @param {object} display_obj - Referencia al controlador de comunidad ecológica
*/
function createNet(json, display_obj) {
_VERBOSE ? console.log("createNet") : _VERBOSE;
console.log(json);
// si se desa agregar mas de una red añadir aqui
var graph_array = [
EpsilonGraph(json, display_obj).group(display_obj.group_eps_spname)
];
var graph_component = d3.selectAll(".graph")
.data(graph_array)
.each(function(graph) {
// _VERBOSE ? console.log(display_obj.renderAll) : _VERBOSE;
graph.on("brushend", display_obj.renderAll);
});
return graph_component;
}
/**
* Clase que genera instancias de tipo red así como interacción con el módulo de histograma y el modulo de tabla a través del controlador de comunidad ecológica.
*
* @function EpsilonGraph
* @public
* @memberof! net_module
*
* @param {json} json - Json que contiene los nodos y los enlaces resultado del análisis de communidad ecológica
* @param {object} display_obj - Referencia al controlador de comunidad ecológica
*/
function EpsilonGraph(json, display_obj) {
_VERBOSE ? console.log("EpsilonGraph") : _VERBOSE;
_VERBOSE ? console.log(display_obj) : _VERBOSE;
$("#graph").empty();
$("#graph_controls").empty();
// var focus_node = null, highlight_node = null;
// var highlight_trans = 0.1;
var margin = {top: 5, right: 20, bottom: 30, left: 20};
// var width = $("#hist").width() - margin.left - margin.right;
// var height = $("#hist").height() - margin.top - margin.bottom;
var max_eps = d3.max(json.links, function(d) {
return d.value;
});
var min_eps = d3.min(json.links, function(d) {
return d.value;
});
var link_color = d3.scale.quantize().domain([-max_eps, max_eps]).range(colorbrewer.RdGy[11]);
var shiftKey, ctrlKey;
// var tip;
// var svg_g;
if (!EpsilonGraph.id) {
EpsilonGraph.id = 0;
}
var id = EpsilonGraph.id++,
brusher = d3.svg.brush(),
// xScale = d3.scale.linear().domain([0,width]).range([0,width]),
// yScale = d3.scale.linear().domain([0,height]).range([0, height]),
dimension, group, round;
var width = $("#graph").width(),
height = $("#graph").height(); //height = graphHeight;
var nodeGraph = json;
var xScale = d3.scale.linear().domain([0, width]).range([0, width]);
var yScale = d3.scale.linear().domain([0, height]).range([0, height]);
var force = d3.layout.force()
.size(100, 100)
.charge(-100) // default: -30, carga del nodo, negativos es repulsion, positivos atraccion, 0 desactiva algoritmo
.linkStrength(0.1)
// .gravity(0.05) // default: 0.1, concentra lso puntos en el centro al aumentar su valor, 0 elimina la gravedad hacia le centro del layout
.linkDistance(width / 5)
// .chargeDistance(500) // asigna el maximo valor de carga
// .linkStrength(function(d){
// return rango_eps(d.value);
// }) // establece la rigidez de los enlaces, rango: [0 - 1]
// .friction(0.5)
.size([width, height]);
/*********************** adding the node toolptip to the graph container */
// Define the div for the tooltip
var div_tip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
/*********************** main container */
var svg_g = d3.select("#graph")
.attr("tabindex", 1)
// .attr("class", "brush_container")
.on("keydown.brush", keydown)
.on("keyup.brush", keyup)
// .each(function() { this.focus(); })
.append("svg")
.attr("id", "svg_container")
.attr("class", "svg_container")
.attr("width", "100%")
.attr("height", "100%")
// .on("click",function(){
// console.log("click svg");
// d3.selectAll("g.node").selectAll("circle").attr("stroke","white");
// d3.selectAll("g.node").selectAll("circle").attr("stroke-width",1);
// })
// TODO: Verificar el ajsute en a,tura del mensaje de selección
svg_g.append("text")
.append('svg:tspan')
.attr("id", "info_text_net")
.attr("y", $("#graph").height() - margin.bottom - 30)
.attr("x", 360)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text(_iTrans.prop('lb_info_net'))
.append('svg:tspan')
.attr("id", "info_text_slider")
.attr("y", $("#graph").height() - margin.bottom - 10)
.attr("x", 160)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text(_iTrans.prop('lb_info_slider'));
d3.select("#graph")
.append("div")
.attr("id", "slider_charge")
.attr("class", "slider_charge")
$(function() {
$("#slider_charge").slider({
min: -200,
max: 5,
step: 1,
value: -100,
change: function(event, ui) {
_VERBOSE ? console.log(ui.value) : _VERBOSE;
force
.charge(ui.value)
.start();
}
});
});
$("#slider_charge .ui-slider-handle").text("ATR").width(30).height(20);
// var legend_div = d3.select("#graph")
// .append("div")
// .attr("id", "legend_div")
// .attr("class", "legend_div")
// var legend_svg = legend_div.append("svg")
// .attr("id", "legend_svg")
// .attr("class", "legend_svg");
// // .attr("width", "100%")
// // .attr("height", "100%");
var legend = svg_g.selectAll(".legend")
.data(_legend_groups)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + 10 + ")";
});
legend.append("rect")
.attr("x", function(d, i) {
return (width - 50) - (i * 120);
})
.attr("y", 3)
.attr("width", 20)
.attr("height", 20)
.style("fill", function(d, i) {
return _color(d.idgrp);
})
.style("opacity", 0.7);
legend.append("text")
.attr("x", function(d, i) {
return (width - 56) - (i * 120);
})
.attr("y", 15)
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) {
if (d.side == 0) {
return "Src: " + d.label;
}
else {
return "Trg: " + d.label;
}
});
/*********************** zoomer */
var zoomer = d3.behavior.zoom().
// scaleExtent([0.5, 2]).
x(xScale).
y(yScale).
on("zoomstart", zoomstart).
on("zoom", redraw);
/* funciones zoomer */
// var redraw_done = false;
function zoomstart() {
_VERBOSE ? console.log("zoomstart") : _VERBOSE;
// if(!redraw_done){
d3.selectAll("g.node").selectAll("circle").attr("stroke", "white");
d3.selectAll("g.node").selectAll("circle").attr("stroke-width", 1);
// redraw_done = false;
// }
node.each(function(d) {
d.selected = false;
d.previouslySelected = false;
});
node.classed("selected", false);
}
function redraw() {
_VERBOSE ? console.log("redraw") : _VERBOSE;
// redraw_done = true;
vis.attr("transform",
"translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}
var svg_graph = svg_g.append('svg:g')
.attr("class", "zoomer_svg")
.call(zoomer);
// .call(brusher)
/*********************** brusher */
var spids_node_selected = [];
brusher
.x(xScale)
.y(yScale);
/******************* contenedor secundario para sleccion de red */
var brush = svg_graph.append("g")
.datum(function() {
// _VERBOSE ? console.log("datum") : _VERBOSE;
return {selected: false, previouslySelected: false};
})
.attr("class", "brush");
brush.call(brusher)
.on("mousedown.brush", null)
.on("touchstart.brush", null)
.on("touchmove.brush", null)
.on("touchend.brush", null);
brush.select('.background').style('cursor', 'auto');
/******************* contenedor secundario para nodos y enlaces */
var vis = svg_graph.append("svg:g");
vis.attr("id", "vis")
.attr('fill', 'red')
.attr('stroke', 'black')
.attr('stroke-width', 1)
.attr('opacity', 1)
.attr('id', 'vis');
/******************* contenedor de enlaces */
var link_group = vis.append("g")
.attr("class", "link")
.selectAll("line");
/*** los enlaces se generan dinamicamente en la selección */
/******************* contenedor de nodos */
var node_group = vis.append("g")
.attr("class", "node")
.selectAll("circle");
/*** funcionamiento de nodos */
var node = node_group.data(json.nodes)
.enter().append("circle")
.attr("class", "node_item")
.attr("r", function(d) {
return 5 + Math.pow(d.occ / Math.PI, 0.5);
})
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.style("fill", function(d) {
return _color(d.group);
})
.on('mouseover', function(d) {
d3.select(this).attr("r", function(d) {
return 10 + Math.pow(d.occ / Math.PI, 0.5);
});
div_tip.transition()
.duration(200)
.style("opacity", .9);
div_tip.html(
"<strong>" + _iTrans.prop('lb_variable_name') + ":</strong> <span >" + d.label + "</span><br/><br/>" +
"<strong>" + _iTrans.prop('lb_occ') + ":</strong> <span >" + d.occ + "</span>"
)
.style("left", (d3.event.pageX + 20) + "px")
.style("top", (d3.event.pageY - 38) + "px");
})
.on('mouseout', function(d) {
d3.select(this).attr("r", function(d) {
return 5 + Math.pow(d.occ / Math.PI, 0.5);
});
div_tip.transition()
.duration(500)
.style("opacity", 0);
})
.on("dblclick", function(d) {
d3.event.stopPropagation();
d.fixed = !d.fixed;
})
.on("click", function(d) {
_VERBOSE ? console.log("click") : _VERBOSE;
if (d3.event.defaultPrevented)
return;
// _VERBOSE ? console.log("Manda petición especie") : _VERBOSE;
species_selected = {"id": d.spid, "label": d.label}
_showSpecieOcc([d], json.nodes);
if (!shiftKey) {
node.classed("selected", function(p) {
return p.selected = p.previouslySelected = false;
})
}
d3.select(this).classed("selected", d.selected = !d.previouslySelected);
})
.call(d3.behavior.drag()
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended));
// asigna una posicion inicial en diagonal a los nodos, para que sea contante el numero de pasos para reacomodar la red
// var n = json.nodes.length;
// json.nodes.forEach(function(d, i) {
// d.x = d.y = width / n * i;
// });
/**********************************************/
function dragstarted(d) {
_VERBOSE ? console.log("dragstarted") : _VERBOSE;
d3.event.sourceEvent.stopPropagation();
if (!d.selected && !shiftKey) {
// if this node isn't selected, then we have to unselect every other node
node.classed("selected", function(p) {
return p.selected = p.previouslySelected = false;
});
}
d3.select(this).classed("selected", function(p) {
d.previouslySelected = d.selected;
return d.selected = true;
});
node.filter(function(d) {
return d.selected;
})
.each(function(d) {
d.fixed |= 2;
})
// a[0] |= b -> a[0] = a[0] | b
}
function dragged(d) {
// _VERBOSE ? console.log("dragged") : _VERBOSE;
node.filter(function(d) {
return d.selected;
})
.each(function(d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
d.px += d3.event.dx;
d.py += d3.event.dy;
})
force.resume();
}
function dragended(d) {
_VERBOSE ? console.log("dragended") : _VERBOSE;
//d3.select(self).classed("dragging", false);
node.filter(function(d) {
return d.selected;
})
.each(function(d) {
d.fixed = true;
})
// ~2 == -(2 + 1) == -3
}
function keydown() {
shiftKey = d3.event.shiftKey || d3.event.metaKey;
ctrlKey = d3.event.ctrlKey;
_VERBOSE ? console.log('keydown') : _VERBOSE;
if (d3.event.keyCode == 67) { //the 'c' key
_center_view();
}
if (shiftKey) {
_VERBOSE ? console.log('shiftKey') : _VERBOSE;
svg_graph.call(zoomer)
.on("mousedown.zoom", null)
.on("touchstart.zoom", null)
.on("touchmove.zoom", null)
.on("touchend.zoom", null);
//svg_graph.on('zoom', null);
vis.selectAll('g.gnode')
.on('mousedown.drag', null);
brush.select('.background').style('cursor', 'crosshair')
brush.call(brusher);
}
}
function keyup() {
_VERBOSE ? console.log("keyup") : _VERBOSE;
shiftKey = d3.event.shiftKey || d3.event.metaKey;
ctrlKey = d3.event.ctrlKey;
brush.call(brusher)
.on("mousedown.brush", null)
.on("touchstart.brush", null)
.on("touchmove.brush", null)
.on("touchend.brush", null);
brush.select('.background').style('cursor', 'auto')
svg_graph.call(zoomer);
// _VERBOSE ? console.log("keyup2") : _VERBOSE;
}
/***************** controles */
// Generación fuera de panel
d3.select("#graph_controls")
.append("div")
.attr("id", "play-stop-button-holder")
.attr("class", "div_btn stop_forces")
.append("button")
.attr("class", "btn btn-primary glyphicon glyphicon-stop")
.attr("id", "pararRed")
.attr("type", "button")
.attr("title", _iTrans.prop('lb_detener_net'))
.on("click", _stop_nodes);
d3.select("#graph_controls")
.append("div")
.attr("id", "center_view_holder")
.attr("class", "div_btn center")
.append("button")
.attr("class", "btn btn-primary glyphicon glyphicon-record")
.attr("id", "center_view_btn")
.attr("type", "button")
.attr("title", _iTrans.prop('lb_centrar_net'))
.on("click", _center_view);
d3.select("#graph_controls")
.append("div")
.attr("id", "div_search_holder")
.attr("class", "div_btn search_input")
.append("input")
.attr("class", "form-control")
.attr("id", "input_text_search")
.attr("type", "text")
.attr("placeholder", _iTrans.prop('lb_buscar_sp'))
.on("input", _search_node);
d3.select("#graph_controls")
.append("div")
.attr("id", "div_export_holder")
.attr("class", "div_btn export_btn")
.append("button")
.attr("class", "btn btn-primary glyphicon glyphicon-download-alt")
.attr("id", "export_btn")
.attr("type", "button")
.attr("title", _iTrans.prop('lb_exportar_net'))
.on("click", _export_graph);
// ******* extración de código para que la red no sea regenerada, solo filtrada
// evento llamado por render ****
function graph(div) {
_VERBOSE ? console.log("graph") : _VERBOSE;
div.each(function() {
_VERBOSE ? console.log("graph div.each") : _VERBOSE;
/*********************** init variables, and force object */
console.log(display_obj.dim_node_state.top(Infinity));
var epsilonBySource = display_obj.nestByR.entries(display_obj.dim_node_state.top(Infinity));
var json_temp = []
var indexVisibleNodes = []
var nodes_related = d3.map([]);
console.log(epsilonBySource);
_linkedByIndex = {};
epsilonBySource.forEach(function(bean, i) {
bean.values.forEach(function(val) {
if (Math.abs(val.value) > display_obj.ep_th) {
// _VERBOSE ? console.log(val) : _VERBOSE;
json_temp.push({"source": val.source, "target": val.target, "value": val.value});
nodes_related.set(val.source, parseInt(val.source));
nodes_related.set(val.target, parseInt(val.target));
_linkedByIndex[val.source + "," + val.target] = true;
}
// else{
// nodes_related.set(parseInt(val.source), false);
// nodes_related.set(parseInt(val.target), false);
// }
});
});
_VERBOSE ? console.log(nodes_related.keys()) : _VERBOSE;
for (var val in nodes_related.values()) {
indexVisibleNodes.push(val);
}
_VERBOSE ? console.log(indexVisibleNodes) : _VERBOSE;
_VERBOSE ? console.log(epsilonBySource) : _VERBOSE;
// _VERBOSE ? console.log("json_temp: " +json_temp.length) : _VERBOSE;
// _VERBOSE ? console.log(d3.selectAll("g.node").selectAll("circle")) : _VERBOSE;
d3.selectAll("g.node").selectAll("circle")
.each(function(d) {
d3.select(this).style("visibility", function(d) {
if (nodes_related.has((d.index).toString())) {
d.visible = true;
return "visible";
}
else {
d.visible = false;
return "hidden";
}
});
}
);
$("line.link").remove();
link = link_group.data(json_temp)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", 5)
.style("stroke", function(d) {
return link_color(d.value);
})
.style("opacity", 1);
// _VERBOSE ? console.log(force) : _VERBOSE;
force
.nodes(json.nodes)
.links(json_temp)
.start();
force.on("tick", function() {
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.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.attr('cx', function(d) {
return d.x;
}).attr('cy', function(d) {
return d.y;
});
});
for (var i = 0; i < json.nodes.length; ++i)
force.tick();
force.resume();
brusher
.on("brushstart", function(d) {
_VERBOSE ? console.log("brushstart") : _VERBOSE;
node.each(function(d) {
d.previouslySelected = shiftKey && d.selected;
});
})
.on("brush", function(e) {
_VERBOSE ? console.log("brush") : _VERBOSE;
indexNodes = [];
var extent = d3.event.target.extent();
index_selected_visible = [];
node.classed("selected", function(d) {
inside = extent[0][0] <= d.x && d.x < extent[1][0] && extent[0][1] <= d.y && d.y < extent[1][1]
indexNodes.push(d.previouslySelected ^ inside)
return d.selected = d.previouslySelected ^ inside;
});
// _VERBOSE ? console.log(indexNodes) : _VERBOSE;
// _VERBOSE ? console.log(indexNodes.length) : _VERBOSE;
// _VERBOSE ? console.log(nodes_related.keys()) : _VERBOSE;
// _VERBOSE ? console.log(nodes_related.keys().length) : _VERBOSE;
indexNodes.forEach(function(d, i) {
if (nodes_related.has(i.toString())) {
if (nodes_related.get(i.toString()) && d == 1) {
// _VERBOSE ? console.log(i) : _VERBOSE;
// _VERBOSE ? console.log(d) : _VERBOSE;
index_selected_visible.push(i);
}
}
});
// _VERBOSE ? console.log(nodes_selected) : _VERBOSE;
// _VERBOSE ? console.log(index_selected_visible) : _VERBOSE;
spids_node_selected = [];
$.each(index_selected_visible, function(index, value) {
// spids_node_selected.push(json.nodes[value].spid);
spids_node_selected.push(json.nodes[value]);
});
})
.on("brushend", function(e) {
_VERBOSE ? console.log("brushend...") : _VERBOSE;
// _VERBOSE ? console.log(spids_node_selected) : _VERBOSE;
// if(spids_node_selected.length > 0)
_showSpecieOcc(spids_node_selected, json.nodes);
d3.event.target.clear();
d3.select(this).call(d3.event.target);
});
// asigna el foco al zoomer
brush.call(brusher)
.on("mousedown.brush", null)
.on("touchstart.brush", null)
.on("touchmove.brush", null)
.on("touchend.brush", null);
brush.select('.background').style('cursor', 'auto')
svg_graph.call(zoomer);
// center_view();
// force.stop();
// _stop_nodes();
});
}
// Activa el algoritmo de fuerzas entre los nodos que componen la red.
function _start_nodes() {
d3.selectAll("g.node").selectAll("circle")
.each(
function(d) {
d.fixed = false;
}
);
force.start();
d3.select("#iniciarRed")
.remove();
d3.select("#play-stop-button-holder")
.append("button")
.attr("class", "btn btn-primary glyphicon glyphicon-stop")
.attr("id", "pararRed")
.attr("type", "button")
.attr("title", "Detener red")
.on("click", _stop_nodes);
}
// Detiene el algoritmo de fuerzas entre los nodos que componen la red.
function _stop_nodes() {
force.stop();
d3.selectAll("g.node").selectAll("circle")
.each(
function(d) {
d.fixed = true;
}
);
d3.select("#pararRed")
.remove();
d3.select("#play-stop-button-holder")
.append("button")
.attr("class", "btn btn-primary glyphicon glyphicon-play")
.attr("id", "iniciarRed")
.attr("type", "button")
.attr("title", "Reiniciar red")
.on("click", _start_nodes);
}
// Resalta los nodos que coinciden con el nombre de la cadena introducida.
function _search_node(d) {
_clean_highlight();
search_str = $("#input_text_search").val();
if (search_str.length <= 2) {
d3.selectAll("g.node").selectAll("circle")
.each(function(item) {
d3.select(this).attr("stroke", "white");
d3.select(this).attr("class", "no_path");
d3.select(this).style("stroke-dasharray", "none");
d3.select(this).attr("r", function(d) {
return 5 + Math.pow(d.occ / Math.PI, 0.5);
});
d3.select(this).style("stroke-width", 1);
});
return;
}
// _map_conected = d3.map([]);
// var nodes_selected = [];
d3.selectAll("g.node").selectAll("circle")
.each(function(item) {
if (item.label.toLowerCase().startsWith(search_str.toLowerCase())) {
// _VERBOSE ? console.log(item.label + " " + item.index) : _VERBOSE;
// _VERBOSE ? console.log(highlight_color) : _VERBOSE;
// nodes_selected.push(item);
d3.select(this).attr("class", "path");
d3.select(this).attr("stroke", function() {
return _highlight_color;
});
d3.select(this).style("stroke-width", 4);
// d3.select(this).style("outline", 4);
d3.select(this).style("stroke-dasharray", ("200"));
d3.select(this).style("stroke-linecap", "round");
d3.select(this).attr("r", function(d) {
return 10 + Math.pow(d.occ / Math.PI, 0.5);
});
}
else {
d3.select(this).attr("stroke", "white");
d3.select(this).attr("class", "nopath");
// d3.select(this).style("stroke-dasharray", "none");
d3.select(this).attr("r", function(d) {
return 5 + Math.pow(d.occ / Math.PI, 0.5);
});
d3.select(this).style("stroke-width", 1);
}
});
// $.each(nodes_selected, function(index, value_a){
// set_highlight(value_a);
// });
}
// Despliega el control para descargar la red.
function _export_graph() {
_VERBOSE ? console.log("export_graph") : _VERBOSE;
$('#modalMail').modal('show');
}
// TODO: enlazar con la red que se genra de forma dinámica....
function _center_view() {
_VERBOSE ? console.log("_center_view") : _VERBOSE;
if (nodeGraph === null)
return;
var nodes = nodeGraph.nodes;
//no molecules, nothing to do
if (nodes.length === 0)
return;
// Get the bounding box
min_x = d3.min(nodes.map(function(d) {
return d.x;
}));
min_y = d3.min(nodes.map(function(d) {
return d.y;
}));
max_x = d3.max(nodes.map(function(d) {
return d.x;
}));
max_y = d3.max(nodes.map(function(d) {
return d.y;
}));
// The width and the height of the graph
mol_width = max_x - min_x;
mol_height = max_y - min_y;
// how much larger the drawing area is than the width and the height
width_ratio = width / mol_width;
height_ratio = height / mol_height;
// we need to fit it in both directions, so we scale according to
// the direction in which we need to shrink the most
min_ratio = Math.min(width_ratio, height_ratio) * 0.8;
// the new dimensions of the molecule
new_mol_width = mol_width * min_ratio;
new_mol_height = mol_height * min_ratio;
// translate so that it's in the center of the window
x_trans = -(min_x) * min_ratio + (width - new_mol_width) / 2;
y_trans = -(min_y) * min_ratio + (height - new_mol_height) / 2;
// do the actual moving
vis.attr("transform",
"translate(" + [x_trans, y_trans] + ")" + " scale(" + min_ratio + ")");
// tell the zoomer what we did so that next we zoom, it uses the
// transformation we entered here
zoomer.translate([x_trans, y_trans]);
zoomer.scale(min_ratio);
}
;
graph.dimension = function(_) {
// _VERBOSE ? console.log("graph.dimension") : _VERBOSE;
// _VERBOSE ? console.log(_) : _VERBOSE;
if (!arguments.length)
return dimension;
dimension = _;
return graph;
};
graph.group = function(_) {
// _VERBOSE ? console.log("graph.group") : _VERBOSE;
// _VERBOSE ? console.log(_) : _VERBOSE;
if (!arguments.length)
return group;
group = _;
return graph;
};
return d3.rebind(graph, brusher, "on");
}
/**
* Éste método verifica si dos nodos se encuentran conectados a través del cálculo épsilon.
*
* @function _isConnected
* @private
* @memberof! net_module
*
* @param {object} a - Nodo source
* @param {object} b - Nodo target
*/
function _isConnected(a, b) {
return _linkedByIndex[a.index + "," + b.index] || _linkedByIndex[b.index + "," + a.index] || a.index == b.index;
}
/**
* Éste método verifica si nu nodo tiene vecinos a través del cálculo épsilon.
*
* @function hasConnections
* @private
* @memberof! net_module
*
* @param {object} a - Nodo source
*/
function hasConnections(a) {
for (var property in _linkedByIndex) {
s = property.split(",");
if ((s[0] == a.index || s[1] == a.index) && _linkedByIndex[property])
return true;
}
return false;
}
/**
* Éste método borra los componentes visuales e iniciliza parámetros para generar un nuevo análisis de comunidad ecológica.
*
* @function _clean_search
* @private
* @memberof! net_module
*
*/
function _clean_search() {
console.log("_clean_search");
$("#input_text_search").val("");
d3.selectAll("g.node").selectAll("circle")
.each(function(item) {
d3.select(this).attr("stroke", "white");
d3.select(this).attr("class", "no_path");
d3.select(this).style("stroke-dasharray", "none");
d3.select(this).attr("r", function(d) {
return 5 + Math.pow(d.occ / Math.PI, 0.5);
});
d3.select(this).style("stroke-width", 1);
});
}
/**
* Éste método limpia los nodos que fueron resaltados al verificar los vecinos de un nodo.
*
* @function _clean_highlight
* @private
* @memberof! net_module
*
*/
function _clean_highlight() {
console.log("_clean_highlight");
_map_conected = d3.map([]);
d3.selectAll("g.node").selectAll("circle").attr("stroke", "white");
d3.selectAll("g.node").selectAll("circle").style("stroke-width", 1);
}
/**
* Éste método resalta los nodos vecinos de un nodo source.
*
* @function _set_highlight
* @private
* @memberof! net_module
*
* @param {object} d - nodo source
*/
function _set_highlight(d) {
console.log("_set_highlight");
d3.selectAll("g.node").selectAll("circle").attr("stroke", function(o) {
if ((_isConnected(d, o) && d.spid != o.spid) || _map_conected.has(o.spid)) {
_map_conected.set(o.spid, true);
return _highlight_linked_color;
}
else {
return "white";
}
});
d3.selectAll("g.node").selectAll("circle").style("stroke-width", function(o) {
if ((_isConnected(d, o) && d.spid != o.spid) || _map_conected.has(o.spid)) {
console.log("4");
_map_conected.set(o.spid, true);
return 4;
}
else {
return 1;
}
});
// link.style("stroke", function(o) {
// return o.source.index == d.index || o.target.index == d.index ? highlight_color : ((isNumber(o.score) && o.score>=0)?color(o.score):default_link_color);
}
/**
* Éste método muestra las ocurrencias por celda del conjunto seleccionado en el mapa resultado del análisis de comunidad.
*
* @function _showSpecieOcc
* @private
* @memberof! net_module
*
* @param {array} nodes_selected - Array con los nodos selecionados
* @param {array} nodes - Array con los nodos que componen la red total
*/
function _showSpecieOcc(nodes_selected, nodes) {
_VERBOSE ? console.log("_showSpecieOcc") : _VERBOSE;
var spids = [];
$.each(nodes_selected, function(index, value) {
spids.push(value.spid);
});
_map_conected = d3.map([]);
_clean_search();
$.each(nodes_selected, function(index, value_a) {
_set_highlight(value_a);
});
var sdata = {
'qtype': 'getCountGridid',
"spids": spids
};
$.ajax({
// url : _url_trabajo,
url: _url_zacatuche + "/niche/especie",
type: 'post',
data: sdata,
// dataType : "json",
success: function(resp) {
// json = JSON.parse(json_file);
json = resp.data;
_VERBOSE ? console.log(json) : _VERBOSE;
arg_gridid = [];
arg_count = [];
$.each(json, function(index, item) {
arg_gridid.push(item.gridid);
arg_count.push(parseInt(item.cont));
});
var max_eps = d3.max(arg_count);
var min_eps = d3.min(arg_count);
_VERBOSE ? console.log(max_eps) : _VERBOSE;
_VERBOSE ? console.log(min_eps) : _VERBOSE;
var link_color;
if (max_eps == min_eps) {
link_color = d3.scale.quantize().domain([0, max_eps]).range(colorbrewer.YlOrRd[9]);
}
else {
link_color = d3.scale.quantize().domain([min_eps, max_eps]).range(colorbrewer.YlOrRd[9]);
}
_VERBOSE ? console.log(link_color(min_eps)) : _VERBOSE;
_VERBOSE ? console.log(link_color(max_eps)) : _VERBOSE;
_map_module_net.colorizeFeaturesNet(arg_gridid, arg_count, link_color);
},
error: function(jqXHR, textStatus, errorThrown) {
_VERBOSE ? console.log("error configureStyleMap: " + textStatus) : _VERBOSE;
// deleteStyle();
}
});
}
/**
* Éste método realiza el llamado a la función que inicializa variables y componentes que son necesarios para la creación de la red.
*
* @function startNet
* @public
* @memberof! net_module
*
* @param {object} languageModule - Módulo de internacionalización
* @param {type} s_filters - Array con los grupos de variables source utlizados en el analísis de comunidad ecológica.
* @param {type} t_filters - Array con los grupos de variables target utlizados en el analísis de comunidad ecológica.
*/
function startNet(language_module, s_filters, t_filters) {
_VERBOSE ? console.log("startNet") : _VERBOSE;
_netConfigure(language_module, s_filters, t_filters);
}
return{
startNet: startNet,
createNet: createNet,
setLanguageModule: setLanguageModule,
setLegendGroup: setLegendGroup
}
});