实习结束,能留下这么个小玩意也是不错的,功能比较完整的一个小模块,希望以后可以用到产品里。
此项目源码已上传GitHub:https://github.com/tangyeah/DataVisualization
一、实现环境:
NetBeansIDE 8.1
JDK 1.8
gephi-toolkit-0.9.1-all.jar
注:SDK使用NetBeans环境开发,对eclipse支持不好,尽量使用NetBeans来实现。
二、相关资源:
1.官方API:https://gephi.org/gephi-toolkit/0.9.1/apidocs/
2.Gephi官网:https://gephi.org/
3.GitHub:https://github.com/gephi/gephi
4.官方论坛:http://gephi.forumatic.com/
5.社区Manager邮箱:eduramiba@gmail.com
三、程序清单:
四、功能简述:
对外提供一个调用接口,实现对csv文件读取,将读取到的graph信息图形化显示;点击一个节点可高亮显示该节点以及所有与其相连的节点;可对点、边的可视化属性进行用户自定义。
五、主程序模块功能说明:
1.初始化一个project,并获取workspace
ProjectController pc = Lookup.getDefault().lookup(ProjectController.class);
pc.newProject();
Workspace workspace = pc.getCurrentWorkspace();
2.获取graphModel和需要用到的controller
GraphModel graphModel = Lookup.getDefault().lookup(GraphController.class).getGraphModel();
ImportController importController = Lookup.getDefault().lookup(ImportController.class);
FilterController filterController = Lookup.getDefault().lookup(FilterController.class);
3.输入文件,将输入的文件和之前获取的workspace关联
根据API中Importer实现的接口来看,可以支持csv,gdf,gexf,gml等文件格式,本说明仅实现对csv文件的读取,对csv文件格式具体要求是:每行两个字段,中间用空格隔开,第一个字段表示一条边的源顶点,第二个字段表示该边的目的顶点。
Container container;
try {
File file = new File("C:\\graph_data\\D2.csv");
container = importController.importFile(file);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
importController.process(container, new DefaultProcessor(), workspace);
4.根据输入文件生成有向图,并输出该图的点数和边数
DirectedGraph graph = graphModel.getDirectedGraph();
System.out.println("Nodes: " + graph.getNodeCount());
System.out.println("Edges: " + graph.getEdgeCount());
5.设置graph布局,目前API支持如下几种布局:
· org.gephi.layout.plugin.force
· org.gephi.layout.plugin.force.quadtree
· org.gephi.layout.plugin.force.yifanHu
· org.gephi.layout.plugin.forceAtlas
· org.gephi.layout.plugin.forceAtlas2
· org.gephi.layout.plugin.fruchterman
· org.gephi.layout.plugin.labelAdjust
· org.gephi.layout.plugin.noverlap
· org.gephi.layout.plugin.openord
· org.gephi.layout.plugin.random
· org.gephi.layout.plugin.rotate
· org.gephi.layout.plugin.scale
本说明中采用fruchterman布局,其特点是,如果导入的图中包含N个互相联通的子图,可以通过设置合理的参数,将各个子连通图互相分离开来,效果如下:
其他各种布局的效果可以使用gephi的exe客户端查看,根据需要替换本说明中的这段代码:
//Fruchterman布局设置,可将联通的子图分离开来
FruchtermanReingold myLayout = new FruchtermanReingold(null);
myLayout.setGraphModel(graphModel);
myLayout.setArea(10000.0f);
myLayout.setGravity(10.0);
myLayout.setSpeed(500.0);
myLayout.initAlgo();
for (int i = 0; i < 20000 && myLayout.canAlgo(); i++) {
myLayout.goAlgo();
}
myLayout.endAlgo();
6.设置Filter,可以根据需要滤除度过大或过小的点,同样的,也可以分别对入度和出度进行filter
//Filter设置,根据点的度来进行过滤
DegreeRangeFilter degreeFilter = new DegreeRangeFilter();
//InDegreeRangeFilter idf = new InDegreeRangeFilter();
//OutDegreeRangeFilter odf = new OutDegreeRangeFilter();
degreeFilter.init(graph);
degreeFilter.setRange(new Range(10, Integer.MAX_VALUE)); //滤出度大于等于10的点
Query query = filterController.createQuery(degreeFilter);
GraphView view = filterController.filter(query);
graphModel.setVisibleView(view);
7.设置graph的各种可视化属性,比如点颜色,边透明度,箭头大小等。代码以设置背景颜色为例:
PreviewController previewController = Lookup.getDefault().lookup(PreviewController.class);
PreviewModel previewModel = previewController.getModel();
previewModel.getProperties().putValue(PreviewProperty.BACKGROUND_COLOR, Color.WHITE);
所有可设置的属性如下:
https://gephi.org/gephi-toolkit/0.9.1/apidocs/org/gephi/preview/api/PreviewProperty.html
8.创建JFrame并显示graph
G2DTarget target = (G2DTarget) previewController.getRenderTarget(
RenderTarget.G2D_TARGET);
final PreviewSketch previewSketch = new PreviewSketch(target);
previewController.refreshPreview();
JFrame frame = new JFrame("DisplayWindow");
frame.setLayout(new BorderLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(previewSketch, BorderLayout.CENTER);
frame.setSize(1024, 768);
frame.addComponentListener(new ComponentAdapter(){
@Override
public void componentShown(ComponentEvent e){
previewSketch.resetZoom();
}
});
frame.setVisible(true);
六、对点击事件的监听
1.创建自定义Renderer类,实现Renderer和MouseResponsiveRenderer接口
(1)一定要声明:
@ServiceProvider(service = Renderer.class)
(2)复写函数needsPreviewMouseListener(PreviewMouseListener pl) {},使其返回true:
@Override
public boolean needsPreviewMouseListener(PreviewMouseListener pl) {
return true;
}
2.创建自定义MouseListener类,实现PreviewMouseListener接口
(1)声明:
@ServiceProvider(service = PreviewMouseListener.class)
(2)复写mouseClicked函数,自定义鼠标点击事件,详见源代码。
特别感谢Gephi社区经理eduramiba,在西班牙隔着6个小时的时差,20封往来电子邮件帮我解答了许多问题。