我已经在 JUNG2 上工作了一段时间,试图将一组对象的非常复杂的层次结构可视化。不幸的是,这种层次结构并不像一棵树,因为:
- 一些节点将有多个父节点。此外,这些父母可能在树的不同分支上。
- 一些节点可能有重复(这是必须允许的,我不能忽略它们)
截至目前,我正在使用SparseGraph
; 将所有节点放入图中,绘制有向的子/超级关系,并在节点之间复制为无向边。然后按照MinimumSpanningTreeDemo源代码,我创建一个MinimumSpanningTreeForest2
对象,并将其发送Forest
到TreeLayout
. 长话短说,我得到了布局,但是它们大约有 15000 像素宽!由于我不以交互方式使用这些图表,而是将其用作静态图像,因此在报告中使用这根本不可行。
我意识到如果有太多并排的节点,节点标签会占用相当多的空间,所以我想我可以旋转标签并让它们垂直。这惨遭失败,我设法使用扩展的自定义类来旋转标签DefaultVertexLabelRenderer
,但是当我将旋转设置为时,Math.PI/2
我根本看不到标签!所以这是我的问题:
- 是否可以强制布局更苗条?我想制作类似树状图的东西,据称可以使用 JUNG2。这真的可能吗?在那种情况下怎么办?
- 我是否认为应该可以垂直渲染节点标签?我试图改变课堂上的锚点,
VertexLabelAsShapeRenderer
但仍然没有快乐。说到事情;Renderer
sRendererContext
和实际渲染的对象之间的联系真的很模糊。有很多类,我很难弄清楚哪些是实际用于渲染的。例如BasicVertexLabelRenderer
,默认情况下似乎根本不使用它。因此,标签的整个定位只是神秘的......
我知道 JUNG 开发人员已经在库中投入了数小时的辛勤工作,我不想听起来苦涩或不感激,但我真的认为本教程与弄清楚演示如何编写以及渲染如何工作之间存在很长的差距。
任何状况之下; 这是我创建图表的代码的一部分:
public void visualizeGraph(File saveFolder){
MinimumSpanningForest2<PHGNode, PHGEdge> prim = new MinimumSpanningForest2<PHGNode, PHGEdge>(
g, new DelegateForest<PHGNode, PHGEdge>(), DelegateTree.<PHGNode, PHGEdge>getFactory(),
new ConstantTransformer(1.0));
Forest<PHGNode, PHGEdge> tree = prim.getForest();
Layout<PHGNode, PHGEdge> layout = new TreeLayout<PHGNode, PHGEdge>(tree);
// custom visualization viewer that allows writing to disk
final WritingVisualizationViewer<PHGNode, PHGEdge> vv = new WritingVisualizationViewer<PHGNode, PHGEdge>(layout,layout.getSize());
// this class extends VertexLabelAsShapeRenderer and supplies means of fiddling with label coordinates
VerticalVertexLabelAsShapeRenderer<PHGNode,PHGEdge> vlasr =
new VerticalVertexLabelAsShapeRenderer<PHGNode,PHGEdge>(vv.getRenderContext());
vv.getRenderContext().setVertexLabelTransformer(
new ChainedTransformer<PHGNode,String>(new Transformer[]{
new ToStringLabeller<PHGEdge>(),new Transformer<String,String>() {
public String transform(String input) { return input; }}}));
// Change the background of node labels so that they appear transparent
Transformer<PHGNode,Paint> vertexPaint = new Transformer<PHGNode,Paint>() {
public Paint transform(PHGNode n) { return vv.getBackground(); }
};
// extends DefaultVertexLabelRendeder to provide rotation of labels
VerticalVertexLabelRenderer vvlr = new VerticalVertexLabelRenderer();
vv.getRenderContext().setVertexLabelRenderer(vvlr);
vv.getRenderContext().setVertexFontTransformer(new VertexFontTransformer<PathwayHierarchyGraph.PHGNode>());
vv.getRenderContext().setVertexShapeTransformer(vlasr);
vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.BentLine<PHGNode, PHGEdge>());
vv.getRenderer().getVertexLabelRenderer().setPosition(Position.CNTR);
//printGraphStats(tree);
vv.writeToDisk(saveFolder,"hierarchyTree.png");
}