2011-01-12 14 views
28

¿cuál de los frameworks de dibujo de gráficos Java de código abierto que se utilizarán para un diagrama de red con los siguientes requisitos? El gráfico tendrá menos de 1000 nodos.comparando marcos de dibujo de gráfico de Java de fuente abierta (JUNG y Prefuse) para dibujar la topología de red

1) tiene bordes paralelos
2) dirigido y bordes no dirigidos dentro de un único gráfico
3) nodos representados por imágenes
4) la interacción del usuario con nodos y los bordes
5) añadir dinámicamente/eliminación de nodos y bordes
6) etiquetado múltiple en nodos y bordes, los diferentes niveles de etiquetado pueden ser activados/desactivados por los usuarios. (como dibujar en capas y apagar/encender una capa)
7) diferentes algoritmos de diseño para mostrar topologías en estrella, anillo, malla

He evaluado JUNG y Prefuse. Esto es lo que encontré para cada uno de mis requisitos.

1) El prefusible no puede mostrar bordes paralelos mientras JUNG lo admite. ¿Se puede manipular el código de prefijado para mostrar bordes paralelos? Dado que esto implica cambios básicos en el nivel de datos, creo que esto sería más difícil que los cambios de representación personalizados habituales.

2) No encontré ninguna referencia al gráfico combinado (ambos bordes dirigidos y no dirigidos) tanto en el prefijo como en JUNG. ¿Alguien sabe de otra manera?

3) Esto parece fácil tanto con Prefuse y JUNG

4) Una vez más, tanto prefuse y JUNG proporciona soporte para la interacción del usuario.

5) Tanto el prefijo como JUNG lo admiten. ¿Cómo funciona cada marco mientras se vuelve a dibujar el gráfico? Vi en otra publicación que el prefuse no funciona bien para las actualizaciones dinámicas (Prefuse Toolkit: dynamically adding nodes and edges)

6) Esto se reduce a modificar el gráfico y volver a dibujarlo. Entonces la pregunta es la misma que 5)

7) Tanto JUNG como prefuse tienen múltiples algoritmos de diseño. Pero cuando traté de mostrar el mismo conjunto de datos usando FruchtermanReingoldLayout en JUNG y Prefuse, obtengo diferentes pantallas. ¿Alguna idea de por qué? De alguna manera, los algoritmos de diseño en Prefuse parecen mostrar una mejor disposición que en JUNG (la representación también es mejor, creo), aunque la mayoría de los algoritmos de diseño en Prefuse se basan en la implementación de JUNG. Los diseños de prefusiones como ForceDirectedLayout/FruchtermanReingoldLayout y CircleLayout se asignan directamente a topologías de estrella, círculo, malla.

Fuera de estos requisitos, el prefuse tiene un buen soporte para expresiones y lenguaje de consulta pero parece que no se desarrolla activamente a diferencia de JUNG. ¿cuál tiene mejor visualización? ¿Alguna sugerencia sobre cuál será adecuada y cómo superar las deficiencias?

¿Hay algún otro framework que pueda usar?

+7

+1 para este . Me gusta el hecho de que hayas trabajado intensamente evaluando dos posibilidades y presentado tus hallazgos. Aquí hay mucho valor para otros más allá de su pregunta. Esta podría ser la mejor "primera pregunta" para un nuevo usuario que he visto en dos años aquí. Daría más si pudiera. – duffymo

Respuesta

3

Hace unos años (2007?) Utilizo el prefijo para visualizar registros de datos de llamadas. Consideré prefuse, jung, jgraph y algunos otros y elegí el prefuse. Al principio es un poco difícil de entender, pero una vez que me familiaricé con él, es realmente fácil de extender y divertido de usar. Creo que lo mismo se puede decir de JUNG pero nunca lo intenté.

1) En prefuse es muy fácil agregar su propio renderizador personalizado para dibujar bordes paralelos: puede subclasificar el EdgeRenderer predeterminado y anular el método de renderizado(). No es necesario realizar "cambios básicos en el nivel de datos". Todo esto está en la parte de la vista si quieres verlo como algo de MVC.

2) Esto no es realmente un problema en absoluto. Hay más de una forma de hacerlo: 1) Puede tener dos procesadores, uno para dibujar los bordes dirigidos y otro para dibujar los bordes no dirigidos, que funcionarán bien y agruparán los bordes de manera apropiada. 2) Ponga una bandera (agregue una columna booleana en la tupla de la tabla de respaldo en el habla de prefusión) para indicar si se dirige el borde y saltee la porción de dibujo de la flecha correspondiente en EdgeRender de acuerdo con esa bandera.

3) Esto es muy fácil

4) ditto

5) La última versión prefuse es "prefuse versión beta 10/21/2007". Utilicé el anterior, que tiene una posible condición de carrera cuando se agregan o eliminan nodos dinámicamente, creo que faltaron algunas palabras clave sincronizadas. Lo resolví asegurándome de detener todas las animaciones y acciones (color, tamaño, diseño) al agregar o eliminar nodos. Tampoco olvides actualizar tus índices lucene también (si usas su motor de búsqueda lucene incorporado)) El último se supone que resuelve este problema racial, pero nunca tuve la oportunidad de probarlo.

6) Como mencionaste "etiquetado múltiple", creo que esto no se trata de "modificar el gráfico y volver a dibujarlo"; solo es cuestión de personalizar los marcadores de etiqueta/borde para dibujar solo las etiquetas relevantes para que no sea realmente un gran problema. Además, no creo que esto esté relacionado con 5 en absoluto.

7) No me sorprende que el prefijo y la representación de JUNG de FruchtermanReingoldLayout sean diferentes: hay algunos factores que pueden afectar a este nodo de inicio donde cada implementación inicia el cálculo, así que no me preocuparía demasiado sobre este tema. Es bastante fácil probar los diferentes algoritmos de diseño de gráficos incorporados en el prefijo para que pueda seguir adelante y verificar cuál está más cerca de lo que le gustaría tener. Consulte RadialLayout y BalloonTreeLayout para ver el diseño de estrella. ForceDirectedLayout necesita bastantes iteraciones para que la ubicación de los nodos sea "estable". Tenga en cuenta que estas iteraciones no es necesario que se muestren para que pueda ejecutarlo en segundo plano y mostrar el resultado final.

No he usado JUNG, así que no puedo comentar mucho al respecto.

De acuerdo con mi experiencia con el prefuse Lo recomiendo altamente debido al diseño bien pensado (en mi humilde opinión) y la separación de la responsabilidad entre los componentes. Jeffrey Heer (autor anterior) realmente hizo un buen trabajo allí.

Cosas a tener en cuenta si se utiliza prefuse (estos son los dos "dolor-pulgares" que recuerdo vívidamente cuando se trabaja con prefuse):

1) Hay un error en el que cuando el zoom se aleja, las etiquetas de nodo no se alejan correctamente de manera que desborde el cuadro delimitador del nodo, lo que dejará artefactos de dibujo fuente cuando el nodo se mueva porque el representador solo borra y vuelve a dibujar cosas dentro del cuadro delimitador del nodo. IIRC esto se debe a un error en la métrica de fuente AWT. La solución consiste en dejar un amplio margen entre la etiqueta y el cuadro delimitador del nodo.

2) Al extender los diseños incorporados, puede encontrar uno o dos "problemas de alcance" donde un miembro de la superclase a la que le gustaría tener acceso recibe el atributo privado en lugar de protegido para que la solución es modificar la biblioteca en sí o crear una nueva clase sin heredar (¡eso puede ser un poco doloroso!). Supongo que puedes decir lo mismo para algunas otras bibliotecas de Java. No todos tienen el beneficio de la retrospectiva, ¿no? :)

Desde que hizo esta pregunta hace aproximadamente un mes (en el momento de escribir esto) me gustaría saber cuál fue su decisión y cómo resultó para usted si siguió adelante con la implementación.

2

Sé que has especificado jung y prefijos pero ... He tenido una buena experiencia tanto con TomSawyer como con yFiles. La lista de requisitos que ha propuesto es muy básica para estos dos y admiten mucho más.

Ran.

5

Soy uno de los creadores y mantenedores de JUNG, así que tenlo en cuenta para las respuestas a continuación.

En primer lugar, debo decir que el autor de Prefuse es amigo de un amigo (y sí, nos hemos conocido) y que ha hecho un gran trabajo. No tengo experiencia con Prefuse, pero he visto algunas visualizaciones hermosas creadas con él.

Aquí están las respuestas a esas preguntas para JUNG. Varios de ellos ((1), (2), (4) se demuestran en PluggableRendererDemo:

  1. compatibles (que necesita el modelo de datos correcto, no todos apoyar bordes paralelos por razones de rendimiento)
  2. compatibles (una vez más, se necesita el modelo de datos de la derecha)
  3. soportados (ver ImageShaperDemo)
  4. Compatible (la mayoría de las versiones parciales de programa)
  5. soportados (ver GraphEditorDemo)
  6. No compatible directamente, aunque se puede certa cambiar las etiquetas dinámicamente y usar HTML para renderizar etiquetas complejas.
  7. Los algoritmos de diseño de JUNG son más para redes generales (con algunas excepciones para árboles, etc.). Sin embargo, puedes construir tus propios algoritmos de diseño, y muchos lo han hecho.

Espero que esto ayude.

0

Me gusta la respuesta de @ holygeek. Aquí está mi aplicación a la solución de 2 (ambos dirigidos y no dirigidos bordes), por Prefuse:

public class MyRenderFactory implements RendererFactory 
{ 
    private NodeRenderer nodeRenderer = new NodeRenderer(); 
    private EdgeRenderer defaultEdgeRenderer = new EdgeRenderer(); 
    private EdgeRenderer undirectedEdgeRenderer = new EdgeRenderer(EdgeRenderer.EdgeType.LINE, EdgeRenderer.EdgeArrowType.NONE); 

    public static String directedness = "myEdgeDirectedness"; 

    public enum EdgeDirected 
    { 
     directed, undirected; 

     public static EdgeDirected fromIsDirected(boolean isDirected) 
     { 
      if (isDirected) 
      { 
       return directed; 
      } 
      return undirected; 
     } 
    } 

    @Override 
    public Renderer getRenderer(VisualItem<?> visualItem) 
    { 
     if (visualItem instanceof EdgeItem) 
     { 
      if (visualItem.get(directedness).equals(PrefuseGraphConverter.EdgeDirected.undirected)) 
      { 
       return undirectedEdgeRenderer; 
      } 
      return defaultEdgeRenderer; 
     } 
     return nodeRenderer; 
    } 
} 

... en otros lugares, donde se crea el gráfico ...

MyRenderFactory.EdgeDirected directedness = 
     MyRenderFactory.EdgeDirected.fromIsDirected(myEdge.isDirected()); 
prefuseEdge.set(MyRenderFactory.directedness, directedness); 
Cuestiones relacionadas