D3.gráfico dirigido de fuerza js, reduce los cruces de bordes haciendo que los bordes se repelan entre sí


Así que ya tengo una página que dibuja un gráfico dirigido por la fuerza, como el que se muestra aquí.

Y eso funciona bien. Estoy usando el JS de aquí, con algunos ajustes para extender los nodos ligeramente mejor.

Estas son más o menos las únicas diferencias:

d3.json("force.json", function(json) {
  var force = d3.layout.force()
      .gravity(0.1)
      .charge(-2000)
      .linkDistance(1)
      .linkStrength(0.1)
      .nodes(json.nodes)
      .links(json.links)
      .size([w, h])
      .start();

Donde la reducción de la fuerza del enlace parece hacer que los enlaces se parezcan más a los resortes, por lo que se vuelve similar a la técnica Fruchterman & Reingold que se usa a menudo. Esto funciona razonablemente bien, pero solo para gráficos bastante pequeños. Con gráficos más grandes, el número de cruces simplemente aumenta, como cabría esperar, pero la solución en la que aterriza normalmente está lejos de ser óptima. No estoy buscando un método para obtener la solución óptima, sé que es muy difícil. Me gustaría que tuviera alguna adición cruda que trate de forzar las líneas separadas, así como los nodos.

¿Hay alguna manera de agregar una repulsión entre los enlaces, así como entre los nodos? No estoy familiarizado con el la forma en que funciona la fuerza D3, y parece que no puedo encontrar nada que diga que esto es posible...

Author: VividD, 2012-08-17

4 answers

Desafortunadamente, la respuesta a su pregunta no existe.

No hay un mecanismo incorporado en D3 que repele los bordes o minimice los cruces de bordes. Uno pensaría que no sería tan difícil implementar una carga en un borde, pero aquí estamos.

Además, no parece haber ningún mecanismo en ningún lugar que reduzca los cruces de bordes en general. He mirado a través de docenas de bibliotecas de visualización y algoritmos de diseño, y ninguno de ellos se ocupan de reducir cruces de bordes en un gráfico genérico no dirigido.

Hay una serie de algoritmos que funcionan bien para gráficos planos, o gráficos de 2 niveles, u otras simplificaciones. dagre funciona bien en teoría para gráficos de 2 niveles, aunque la absoluta falta de documentación hace que sea casi imposible trabajar con ellos.

Parte de la razón para esto es que el trazado de gráficos es difícil. En particular, minimizar los cruces de bordes es NP-difícil, por lo que sospecho que la mayoría de los diseñadores de diseño golpeó que problema, golpear la cabeza contra el teclado un par de veces, y renunciar.

Si a alguien se le ocurre una buena biblioteca para esto, por favor publíquela para el resto de nosotros:)

 10
Author: GreySage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-30 23:08:57

Algo que podría ser más fácil que tratar de repeler con fuerza los bordes es mover los nodos hasta que la cantidad de líneas de cruce en el sistema sea menor.

Http://en.wikipedia.org/wiki/Simulated_annealing

Comience con los nodos con la menor cantidad de conexiones y desplácese hacia abajo.

Si intentas usar los bordes como nodos sospecho que vas a tener los mismos problemas de bloqueo espacial. La solución está en averiguar dónde hay edge intersecciones y si se pueden resolver. Usted puede encontrar que la resolución de muchos de los cruces de borde no es posible

Un enfoque más lateral de la visualización es animarla de manera que solo muestre un subconjunto de nodos y conexiones a la vez. O para hacer que los bordes sean transparentes hasta que el usuario coloque el foco del mouse sobre un nodo, que apunta a que los bordes asociados se vuelvan más visibles.

 5
Author: VoronoiPotato,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-29 19:43:54

Seguí el ejemplo del Editor de Fuerza y vi que establecer charge y linkDistance valores resuelve el problema.

  ...
  .charge(-200)
  .linkDistance(50)
  ...

Captura de pantalla:

introduzca la descripción de la imagen aquí

 1
Author: Ionică Bizău,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-08 07:16:15

He "solucionado" el problema con esto:

nodes[0].x = width / 2;
nodes[0].y = 100;
nodes[0].fixed = true;
force.on("tick", function(e) {

    var kx = .4 * e.alpha, ky = 1.4 * e.alpha;
    links.forEach(function(d, i) {
      d.target.x += (d.source.x - d.target.x) * kx;
      d.target.y += (d.source.y + 80 - d.target.y) * ky;
    });
    [...]
 }

Http://mbostock.github.io/d3/talk/20110921/parent-foci.html

No es exactamente lo que queríamos, pero mejor que antes. Importend es, que se define un"raíz" -Nodo y lo arregló.

nodes[0].fixed = true;

Parece más como un árbol, pero por lo que es más claro.

 -1
Author: Baum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-13 09:00:32