比较用于绘制网络拓扑的开源 java 图形绘制框架(JUNG 和 Prefuse)

发布于 2024-10-11 19:32:55 字数 1266 浏览 3 评论 0原文

对于具有以下要求的网络图,可以使用哪些开源 Java 图形绘制框架?该图的节点数将少于 1000 个。

1) 有平行边
2) 单个图中的有向边和无向边
3)图像表示的节点
4)用户与节点和边的交互
5) 动态添加/删除节点和边
6)节点和边上的多重标记,用户可以关闭/打开不同级别的标记。 (就像分层绘图以及关闭/打开图层)
7)不同的布局算法来显示星形、环形、网状拓扑

我评估了 JUNG 和 Prefuse。这是我为我的每个要求找到的。

1) Prefuse 无法显示平行边,而 JUNG 支持。可以操纵 prefuse 代码来显示平行边缘吗?由于这涉及基本数据级别的更改,我相信这比通常的自定义渲染更改更困难。

2)我在 prefuse 和 JUNG 中都没有找到任何对组合图(有向边和无向边)的引用。还有人知道吗?

3) 对于 Prefuse 和 JUNG 来说,这似乎很容易。

4) 同样,prefuse 和 JUNG 都提供了对用户交互的支持。

5)prefuse和JUNG都支持。重绘图表时每个框架的表现如何?我在另一篇文章中看到 prefuse 对于动态更新表现不佳(Prefuse Toolkit:动态添加节点和边

6)这来了直到修改图表并重新绘制它。所以问题就变成了5)

7) JUNG和prefuse都有多种布局算法。但是当我尝试在 JUNG 和 Prefuse 中使用 FruchtermanReingoldLayout 显示相同的数据集时,我得到了不同的显示。有什么想法吗?不知何故,Prefuse 中的布局算法似乎比 JUNG 中显示更好的布局(我认为渲染也更好),尽管 Prefuse 中的大多数布局算法都基于 JUNG 实现。 Prefuse 布局如 ForceDirectedLayout/FruchtermanReingoldLayout 和 CircleLayout 直接映射到星形、圆形、网状拓扑。

除了这些要求之外,prefuse 对表达式和查询语言有很好的支持,但看起来不像 JUNG 那样积极开发。哪一个的可视化效果更好?关于哪一种适合以及如何克服缺点有什么建议吗?

还有其他我可以使用的框架吗?

which of the open source Java graph drawing frameworks to use for a network diagram with the following requirements? The graph will have less than 1000 nodes.

1) has parallel edges
2) directed and undirected edges within a single graph
3) nodes represented by images
4) user interaction with nodes and edges
5) dynamically adding/deleting nodes and edges
6) multiple labelling on nodes and edges , different levels of labelling can be turned off/on by users. (like drawing in layers and turning off / on a layer)
7) different layout algorithms to display star, ring, mesh topologies

I evaluated JUNG and Prefuse. This is what I found for each of my requirements.

1) Prefuse cannot display parallel edges while JUNG supports it. Can prefuse code be manipulated to display parallel edges ? Since this involves basic data level changes I believe this would be more difficult that the usual customized rendering changes.

2) I didnt find any reference to combined graph (both directed and undirected edges) in both prefuse and JUNG. Does anyone know otherwise?

3) This seems easy with both Prefuse and JUNG

4) Again both prefuse and JUNG provides support for user interaction.

5) Both prefuse and JUNG supports it. How does each framework perform while redrawing the graph ? I saw in another post that prefuse does not perform well for dynamic updates (Prefuse Toolkit: dynamically adding nodes and edges)

6) This comes down to modifying the graph and redrawing it. So the question becomes the same as 5)

7) Both JUNG and prefuse has multiple layout algorithms. But When I tried to display the same dataset using FruchtermanReingoldLayout in both JUNG and Prefuse I get different displays. Any ideas why ? Somehow the layout algorithms in Prefuse seem to display a better layout than in JUNG (rendering is also better I think) though most of the layout algorithms in Prefuse are based on JUNG implementation.
Prefuse layouts such as ForceDirectedLayout/FruchtermanReingoldLayout and CircleLayout directly maps to star,circle, mesh topologies.

Outside of these requirements, prefuse has good support for expressions and query language but looks like it is not actively developed unlike JUNG. which one has better visualization? Any suggestions on which one will be suitable and how to overcome the shortcomings ?

Any other frameworks out there which I can use ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

聽兲甴掵 2024-10-18 19:32:55

我是 JUNG 的创建者和维护者之一,所以在下面的回复中请记住这一点。

不过,首先我应该说 Prefuse 的作者是朋友的朋友(是的,我们见过),他做得很好。我对 Prefuse 没有经验,但我见过用它创建的一些漂亮的可视化效果。

以下是荣格对这些问题的回答。其中几个((1)、(2)、(4) 在 PluggableRendererDemo 中进行了演示:

  1. 支持(您需要正确的数据模型,出于性能原因,并非所有模型都支持平行边缘)
  2. 支持(同样) ,您需要正确的数据模型)
  3. 支持(请参阅ImageShaperDemo
  4. 支持(大多数演示)
  5. 支持(请参阅GraphEditorDemo
  6. 不直接支持,尽管您当然可以动态更改标签并使用HTML 来渲染复杂的标签。JUNG
  7. 的布局算法更适合一般网络(树等有一些例外),但是,许多人已经这样做了,

希望这会有所帮助。

I'm one of the creators and maintainers of JUNG, so bear that in mind for the responses below.

First, though, I should say that the author of Prefuse is a friend of a friend (and yes, we've met) and he's done a great job. I am not experienced with Prefuse, but I've seen some beautiful visualizations created with it.

Here are the answers to those questions for JUNG. Several of them ((1), (2), (4)are demonstrated in PluggableRendererDemo:

  1. Supported (you'll need the right data model, not all support parallel edges for performance reasons)
  2. Supported (again, you need the right data model)
  3. Supported (see ImageShaperDemo)
  4. Supported (most demos)
  5. Supported (see GraphEditorDemo)
  6. Not directly supported, although you can certainly change labels dynamically and use HTML to render complex labels.
  7. JUNG's layout algorithms are more for general networks (with a few exceptions for trees, etc.). You can certainly construct your own layout algorithms, however, and many have done so.

Hope this helps.

一绘本一梦想 2024-10-18 19:32:55

几年前(2007 年?)我使用 prefuse 来可视化通话数据记录。我考虑了 prefuse、jung、jgraph 和其他一些,并选择了 prefuse。起初,我有点难以理解 prefuse,但一旦我熟悉了它,它就非常容易(扩展)并且使用起来很有趣。我想 JUNG 也可以这样说,但我从未尝试过。

1) 在 prefuse 中,很容易添加您自己的自定义渲染器来绘制平行边缘 - 您可以继承默认 EdgeRenderer 并重写 render() 方法。不需要“基本数据级别更改”。如果您想将其视为 MVC 内容,那么这一切都在视图部分中。

2)这根本不是一个问题。有不止一种方法可以做到这一点: 1)您可以有两个渲染器 - 一个用于绘制有向边缘,一个用于绘制无向边缘,它们会很好地工作,并对边缘进行适当的分组。 2)放置一个标志(在 prefuse 中的支持表元组中添加一个布尔列)来指示边缘是否有向,并根据该标志在 EdgeRender 中相应地跳过箭头绘制部分。

3) 这非常简单

4) 同上

5) 最后一个 prefuse 版本是“prefuse beta 版本 2007.10.21”。我之前使用过一个,它在动态添加或删除节点时可能存在竞争条件 - 我猜它缺少一些同步关键字。我通过确保在添加或删除节点时停止所有动画和操作(颜色、大小、布局)来解决这个问题 - 也不要忘记更新你的 lucene 索引(如果你确实使用其内置的 lucene 搜索引擎) )。最新的应该可以解决这个比赛问题,但我从未有机会尝试。

6)既然你提到了“多重标签”,我认为这不是“修改图形并重新绘制它”的问题 - 这只是自定义标签/边缘渲染器以仅绘制相关标签的问题,所以这并不是一个大问题。而且我认为这与5根本没有关系。

7) 我并不惊讶 prefuse 和 JUNG 对 FruchtermanReingoldLayout 的渲染不同 - 有几个因素可能会影响其中一个因素,即每个实现开始计算的起始节点,所以我不会太担心这个问题。在 prefuse 中尝试不同的内置图形布局算法非常容易,因此您可以继续检查哪一个最接近您想要的算法。查看星形布局的 RadialLayout 和 BalloonTreeLayout。 ForceDirectedLayout 需要相当多的迭代才能使节点的放置“稳定”。请注意,不必显示这些迭代,因此您可以在后台运行它并呈现最终结果。

我没有使用过JUNG,所以我不能对它发表太多评论。

根据我使用 prefuse 的经验,我强烈推荐它,因为它经过深思熟虑的设计和组件之间的责任分离。杰弗里·希尔(Jeffrey Heer)(前言作者)确实做得很好。

使用 prefuse 时需要注意的事项(这是我在使用 prefuse 时清晰记得的两个“痛点”):

1)存在一个错误,即缩小时,节点标签不会适当缩小,从而导致溢出节点的边界框,当节点移动时,这将留下字体绘制伪影,因为渲染器仅清除并重新绘制节点边界框​​内的内容。 IIRC 这是由 AWT 字体度量本身的错误引起的。解决方法是在标签和节点边界框​​之间留出足够的边距。

2)扩展内置布局时,您可能会遇到一两个“范围问题”,其中您想要访问的超类的成员被赋予私有属性而不是受保护,因此解决方案是修改库本身或创建一个新类而不继承(这可能有点痛苦!)。我想你也可以对其他一些 java 库说同样的话。不是每个人都能得到事后诸葛亮的好处不是吗? :)

自从您大约一个月前(在我撰写本文时)提出这个问题以来,我想知道您的决定是什么,以及如果您继续实施,结果如何。

A few years back (2007?) I use prefuse to visualize call data records. I considered prefuse, jung, jgraph and a few others and chose prefuse. At first it's a bit hard to wrap my head around prefuse but once I got familiar with it it's really easy (to extend) and fun to use. I guess the same can be said for JUNG but I never tried it.

1) In prefuse it's very easy to add your own custom renderer for drawing parallel edges - you can subclass the default EdgeRenderer and override the render() method. There's no "basic data level changes" needed. This is all in the view part if you'd like to think of it as an MVC stuff.

2) This is not really an issue at all. There are more than one way to do this: 1) You can have two renderers - one for drawing the directed edges and one for drawing the undirected edges and they'll work just fine, and group the edges appropriately. 2) Put a flag (add a boolean column in the backing table tuple in prefuse speak) to indicate whether the edge is directed and skip the arrow drawing portion accordingly in the EdgeRender according to that flag.

3) This is super easy

4) ditto

5) The last prefuse release is "prefuse beta release 2007.10.21". I used the one before that, which have a possible race condition when adding or deleting nodes dynamically - it was missing a few synchronized keywords I guess. I solved that by making sure to stop all the animation and actions (color, size, layout) when adding or removing nodes - also don't forget to update your lucene indexes as well (if you do use its built-in lucene search engine). The latest one is supposed to solve this race issue but I never had the chance to try it out.

6) Since you mentioned "multiple labelling" I think this not a matter of "modifying the graph and redrawing it" - it's just a matter of customizing your label/edge renderers to draw only the relevant labels so this is not really a big issue. Also I don't think this is related to 5 at all.

7) I'm not surprised that prefuse and JUNG's rendering of the FruchtermanReingoldLayout are different - there are a few factors that might affect this one of them the starting node where each implementation start the calculation so I wouldn't worry much about this issue. It's quite easy to try out the different builtin graph layout algorithms in prefuse so you can go ahead and check out which one is closest to what you'd like to have. Check out the RadialLayout and BalloonTreeLayout for the star layout. ForceDirectedLayout needs quite a few iterations for the placement of nodes to be "stable". Note that these iterations is not necessary to be shown so you can run it in the background and render the final result.

I haven't use JUNG so I can't comment much on it.

Based on my experience with prefuse I highly recommend it due to the very well (IMHO) thought-out design and separation of resposibility between the components. Jeffrey Heer (prefuse author) really did a good job there.

Things to watch out for if you use prefuse (these are the two "sore-thumbs" that I vividly remember when working with prefuse):

1) There's a bug where when zooming out, the node labels are not zoomed out appropriately such that it overflows the bounding box of the node which will leave font drawing artifacts when the node moves because the renderer only clears and redraws stuff within the node's bounding box. IIRC this is caused by a bug in AWT font metric itself. The workaround is to leave ample margin between the label and the node bounding box.

2) When extending the built-in layouts, you might encounter one or two "scoping issue" where a member of the superclass that you'd like to have access to is given the private attribute instead of protected so the solution is to either modify the library itself or create a new class without inheriting (that can be a bit painful!). I guess you can say the same for some other java libraries. Not everyone have the benefit of hindsight no? :)

Since you asked this question about a month ago (at the time of me writing this) I'd like to know what your decision was and how it turned out for you if you went ahead with the implementation.

绾颜 2024-10-18 19:32:55

我知道你指定了 jung 和 prefuse,但是......
我对 TomSawyer 和 yFiles 都有很好的体验。您提出的要求列表对于这两个来说非常基本 - 并且它们支持更多。

然。

I know you specified jung and prefuse but...
I've had good experience with both TomSawyer and yFiles. The requirements list you proposed is very basic to these two - and they support much more.

Ran.

完美的未来在梦里 2024-10-18 19:32:55

我建议也评估 JGraph

I'd suggest evaluating JGraph too.

め可乐爱微笑 2024-10-18 19:32:55

我喜欢@holygeek的回答。这是我对 Prefuse 2(有向边和无向边)的解决方案的实现:

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;
    }
}

...其他地方,创建图形的地方...

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

I like @holygeek's answer. Here is my implementation to the solution for 2 (both directed and undirected edges), for 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;
    }
}

...elsewhere, where the graph is created...

MyRenderFactory.EdgeDirected directedness =
        MyRenderFactory.EdgeDirected.fromIsDirected(myEdge.isDirected());
prefuseEdge.set(MyRenderFactory.directedness, directedness);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文