图Graph的可视化
2020-01-28 本文已影响0人
kason_zhang

1 Jung2介绍
随着Graph图相关的应用,基于一种可视化工具进行数据分析是一种十分必要的工具,将极大便利的加快分析。随着大数据的发展,图神经网络,基于图的团伙发现算法,聚集算法等越来越多的应用到业务之中,仅仅从数据角度来看图的结果比较晦涩难懂,本文介绍一种java的可视化图Graph的工具-jung2,对于英文较好的同学,这里有一篇英文文档专门介绍Jung的使用方式,可以一读。http://www.grotto-networking.com/JUNG/JUNG2-Tutorial.pdf
2 步骤
- 初始化图
- 创建布局Layout
- 创建视图进行点边以及label等渲染
- 是否可拖拽
2.1 init图Grpah
addVertex 加入点
addEdge 加入边
Graph<BaseNode, BaseEdge> g2 = new SparseMultigraph<>();
for (BaseNode baseNode : nodes) {
g2.addVertex(baseNode);
}
for (BaseEdge baseEdge : edges) {
g2.addEdge(baseEdge, baseEdge.queryBaseNode(nodes, baseEdge.getSrcId()),
baseEdge.queryBaseNode(nodes, baseEdge.getDstId()), EdgeType.DIRECTED);
}
2.2 创建布局Layout
// Layout<V, E>, BasicVisualizationServer<V,E>
Layout<BaseNode, BaseEdge> layout = new CircleLayout(g2);
//layout.setSize(new Dimension(300,300));
layout.setSize(new Dimension(1000,900));
这边实际上是创建一个画布.
2.3 创建视图进行点边以及label等渲染
创建视图.
VisualizationViewer<BaseNode,BaseEdge> vv = new VisualizationViewer<>(layout);
vv.setPreferredSize(new Dimension(1500,1500));
创建点的颜色-用于区分不同点
// Setup up a new vertex to paint transformer...
Transformer<BaseNode,Paint> vertexPaint = new Transformer<BaseNode,Paint>() {
public Paint transform(BaseNode i) {
Map<String, Object> properties = i.getProperties();
Object isCenter = properties.get("is_center");
if (isCenter != null && Long.valueOf(isCenter.toString()) == 1) {
return Color.BLACK;
}
if (i.getNodeId().length() > 18) {
return Color.RED;
} else {
return Color.GREEN;
}
}
};
vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
设置线:虚线,线宽等
// Set up a new stroke Transformer for the edges
float dash[] = {10.0f};
final Stroke edgeStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 10f, dash, 0.0f);
Transformer<BaseEdge, Stroke> edgeStrokeTransformer =
new Transformer<BaseEdge, Stroke>() {
public Stroke transform(BaseEdge s) {
return edgeStroke;
}
};
vv.getRenderContext().setEdgeStrokeTransformer
(edgeStrokeTransformer);
设置点的显示: 即点上面显示的文字等
Transformer<BaseNode, String> baseNodeStringTransformer = new Transformer<BaseNode, String>() {
@Override
public String transform(BaseNode baseNode) {
return baseNode.getNodeId();
}
};
vv.getRenderContext().setVertexLabelTransformer(baseNodeStringTransformer);
设置边的显示
vv.getRenderContext().setEdgeLabelTransformer(new Transformer<BaseEdge, String>() {
@Override
public String transform(BaseEdge baseEdge) {
String s = "";
Map<String, Object> properties = baseEdge.getProperties();
Object amount = properties.get("amount");
long gmtOccur = (long)properties.get("gmtOccur");
String edgeType = turnName((String)properties.get("event_name"));
String format = f.format(gmtOccur);
return s + edgeType + " " + format + " " + amount;
}
});
设置是否可拖拽
DefaultModalGraphMouse<String, CreditEdge> gm = new DefaultModalGraphMouse<String, CreditEdge>();
gm.setMode(ModalGraphMouse.Mode.PICKING);
gm.addItemListener(gm.getModeListener());
vv.setGraphMouse(gm);
设置点边的响应事件-即按住点展示什么,按住边展示什么
PickedState<BaseNode> pickedVertexState = vv.getPickedVertexState();
ItemListener message = new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == SELECTED) {
System.out.println(e.getItem());
}
}
};
PickedState<BaseEdge> pickedEdgeState = vv.getPickedEdgeState();
pickedEdgeState.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
System.out.println(e.getItem());
}
});
pickedVertexState.addItemListener(message);
这里给出一个渲染的结果例子:

可参考代码:
package graph;
import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.picking.PickedState;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import entity.BaseEdge;
import entity.BaseNode;
import entity.CreditEdge;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Map;
import java.util.Set;
import static java.awt.event.ItemEvent.SELECTED;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
public class BuildGraphOpenSource {
public static final Logger LOGGER = LoggerFactory.getLogger(BuildGraphOpenSource.class);
public static final FastDateFormat f = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
public void buildGraph(Map<String, Object> nodesAndSource) {
try {
Set<BaseNode> nodes = (Set<BaseNode>)nodesAndSource.get("nodes");
Set<BaseEdge> edges = (Set<BaseEdge>)nodesAndSource.get("edges");
Graph<BaseNode, BaseEdge> g2 = new SparseMultigraph<>();
for (BaseNode baseNode : nodes) {
g2.addVertex(baseNode);
}
for (BaseEdge baseEdge : edges) {
g2.addEdge(baseEdge, baseEdge.queryBaseNode(nodes, baseEdge.getSrcId()),
baseEdge.queryBaseNode(nodes, baseEdge.getDstId()), EdgeType.DIRECTED);
}
displayView(g2);
} catch (Exception e) {
LOGGER.error("build graph failed");
}
}
private void displayView(Graph<BaseNode, BaseEdge> g2) {
// Layout<V, E>, BasicVisualizationServer<V,E>
Layout<BaseNode, BaseEdge> layout = new CircleLayout(g2);
//layout.setSize(new Dimension(300,300));
layout.setSize(new Dimension(1000,900));
VisualizationViewer<BaseNode,BaseEdge> vv = new VisualizationViewer<>(layout);
vv.setPreferredSize(new Dimension(1500,1500));
// Setup up a new vertex to paint transformer...
Transformer<BaseNode,Paint> vertexPaint = new Transformer<BaseNode,Paint>() {
public Paint transform(BaseNode i) {
Map<String, Object> properties = i.getProperties();
Object isCenter = properties.get("is_center");
if (isCenter != null && Long.valueOf(isCenter.toString()) == 1) {
return Color.BLACK;
}
if (i.getNodeId().length() > 18) {
return Color.RED;
} else {
return Color.GREEN;
}
}
};
// Set up a new stroke Transformer for the edges
float dash[] = {10.0f};
final Stroke edgeStroke = new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_MITER, 10f, dash, 0.0f);
//vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
Transformer<BaseNode, String> baseNodeStringTransformer = new Transformer<BaseNode, String>() {
@Override
public String transform(BaseNode baseNode) {
return baseNode.getNodeId();
}
};
Transformer<BaseEdge, Stroke> edgeStrokeTransformer =
new Transformer<BaseEdge, Stroke>() {
public Stroke transform(BaseEdge s) {
return edgeStroke;
}
};
vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
vv.getRenderContext().setEdgeStrokeTransformer
(edgeStrokeTransformer);
//vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
vv.getRenderContext().setVertexLabelTransformer(baseNodeStringTransformer);
vv.getRenderContext().setEdgeLabelTransformer(new Transformer<BaseEdge, String>() {
@Override
public String transform(BaseEdge baseEdge) {
String s = "";
Map<String, Object> properties = baseEdge.getProperties();
Object amount = properties.get("amount");
long gmtOccur = (long)properties.get("gmtOccur");
String edgeType = turnName((String)properties.get("event_name"));
String format = f.format(gmtOccur);
return s + edgeType + " " + format + " " + amount;
}
});
vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);
DefaultModalGraphMouse<String, CreditEdge> gm = new DefaultModalGraphMouse<String, CreditEdge>();
gm.setMode(ModalGraphMouse.Mode.PICKING);
gm.addItemListener(gm.getModeListener());
vv.setGraphMouse(gm);
JFrame frame = new JFrame("图关系展示");
PickedState<BaseNode> pickedVertexState = vv.getPickedVertexState();
ItemListener message = new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == SELECTED) {
System.out.println(e.getItem());
}
}
};
PickedState<BaseEdge> pickedEdgeState = vv.getPickedEdgeState();
pickedEdgeState.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
System.out.println(e.getItem());
}
});
pickedVertexState.addItemListener(message);
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.getContentPane().add(vv);
frame.pack();
frame.setVisible(true);
}
private String turnName(String eventName) {
if ("APPLY".equalsIgnoreCase(eventName)) {
return "放款";
} else if ("TRANSFER".equalsIgnoreCase(eventName)) {
return "转账";
} else if ("TRADE".equalsIgnoreCase(eventName)) {
return "交易";
}
return "UNKNOWN";
}
}