1
2
3
4
5
6
7
8
9 package edu.uci.ics.jung.samples;
10
11 import java.awt.BorderLayout;
12 import java.awt.Color;
13 import java.awt.Container;
14 import java.awt.Dimension;
15 import java.awt.Graphics;
16 import java.awt.Graphics2D;
17 import java.awt.event.ActionEvent;
18 import java.awt.event.ActionListener;
19 import java.awt.geom.AffineTransform;
20 import java.awt.geom.Point2D;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.swing.ImageIcon;
27 import javax.swing.JApplet;
28 import javax.swing.JButton;
29 import javax.swing.JFrame;
30 import javax.swing.JPanel;
31
32 import org.apache.commons.collections15.Transformer;
33 import org.apache.commons.collections15.functors.ChainedTransformer;
34
35 import edu.uci.ics.jung.algorithms.layout.Layout;
36 import edu.uci.ics.jung.algorithms.layout.StaticLayout;
37 import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
38 import edu.uci.ics.jung.graph.Graph;
39 import edu.uci.ics.jung.graph.util.EdgeType;
40 import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
41 import edu.uci.ics.jung.visualization.Layer;
42 import edu.uci.ics.jung.visualization.VisualizationViewer;
43 import edu.uci.ics.jung.visualization.control.AbstractModalGraphMouse;
44 import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
45 import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
46 import edu.uci.ics.jung.visualization.control.ScalingControl;
47 import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
48 import edu.uci.ics.jung.visualization.renderers.GradientVertexRenderer;
49 import edu.uci.ics.jung.visualization.renderers.Renderer;
50 import edu.uci.ics.jung.visualization.renderers.BasicVertexLabelRenderer.InsidePositioner;
51
52
53
54
55
56
57
58
59 @SuppressWarnings("serial")
60 public class WorldMapGraphDemo extends JApplet {
61
62
63
64
65 Graph<String, Number> graph;
66
67
68
69
70 VisualizationViewer<String, Number> vv;
71
72 Map<String,String[]> map = new HashMap<String,String[]>();
73 List<String> cityList;
74
75
76
77
78
79
80
81
82 public WorldMapGraphDemo() {
83 setLayout(new BorderLayout());
84
85 map.put("TYO", new String[] {"35 40 N", "139 45 E"});
86 map.put("PEK", new String[] {"39 55 N", "116 26 E"});
87 map.put("MOW", new String[] {"55 45 N", "37 42 E"});
88 map.put("JRS", new String[] {"31 47 N", "35 13 E"});
89 map.put("CAI", new String[] {"30 03 N", "31 15 E"});
90 map.put("CPT", new String[] {"33 55 S", "18 22 E"});
91 map.put("PAR", new String[] {"48 52 N", "2 20 E"});
92 map.put("LHR", new String[] {"51 30 N", "0 10 W"});
93 map.put("HNL", new String[] {"21 18 N", "157 51 W"});
94 map.put("NYC", new String[] {"40 77 N", "73 98 W"});
95 map.put("SFO", new String[] {"37 62 N", "122 38 W"});
96 map.put("AKL", new String[] {"36 55 S", "174 47 E"});
97 map.put("BNE", new String[] {"27 28 S", "153 02 E"});
98 map.put("HKG", new String[] {"22 15 N", "114 10 E"});
99 map.put("KTM", new String[] {"27 42 N", "85 19 E"});
100 map.put("IST", new String[] {"41 01 N", "28 58 E"});
101 map.put("STO", new String[] {"59 20 N", "18 03 E"});
102 map.put("RIO", new String[] {"22 54 S", "43 14 W"});
103 map.put("LIM", new String[] {"12 03 S", "77 03 W"});
104 map.put("YTO", new String[] {"43 39 N", "79 23 W"});
105
106 cityList = new ArrayList<String>(map.keySet());
107
108
109 graph = new DirectedSparseMultigraph<String, Number>();
110 createVertices();
111 createEdges();
112
113 ImageIcon mapIcon = null;
114 String imageLocation = "/images/political_world_map.jpg";
115 try {
116 mapIcon =
117 new ImageIcon(getClass().getResource(imageLocation));
118 } catch(Exception ex) {
119 System.err.println("Can't load \""+imageLocation+"\"");
120 }
121 final ImageIcon icon = mapIcon;
122
123 Dimension layoutSize = new Dimension(2000,1000);
124
125 Layout<String,Number> layout = new StaticLayout<String,Number>(graph,
126 new ChainedTransformer(new Transformer[]{
127 new CityTransformer(map),
128 new LatLonPixelTransformer(new Dimension(2000,1000))
129 }));
130
131 layout.setSize(layoutSize);
132 vv = new VisualizationViewer<String,Number>(layout,
133 new Dimension(800,400));
134
135 if(icon != null) {
136 vv.addPreRenderPaintable(new VisualizationViewer.Paintable(){
137 public void paint(Graphics g) {
138 Graphics2D g2d = (Graphics2D)g;
139 AffineTransform oldXform = g2d.getTransform();
140 AffineTransform lat =
141 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).getTransform();
142 AffineTransform vat =
143 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).getTransform();
144 AffineTransform at = new AffineTransform();
145 at.concatenate(g2d.getTransform());
146 at.concatenate(vat);
147 at.concatenate(lat);
148 g2d.setTransform(at);
149 g.drawImage(icon.getImage(), 0, 0,
150 icon.getIconWidth(),icon.getIconHeight(),vv);
151 g2d.setTransform(oldXform);
152 }
153 public boolean useTransform() { return false; }
154 });
155 }
156
157 vv.getRenderer().setVertexRenderer(
158 new GradientVertexRenderer<String,Number>(
159 Color.white, Color.red,
160 Color.white, Color.blue,
161 vv.getPickedVertexState(),
162 false));
163
164
165 vv.setVertexToolTipTransformer(new ToStringLabeller());
166 vv.setEdgeToolTipTransformer(new Transformer<Number,String>() {
167 public String transform(Number edge) {
168 return "E"+graph.getEndpoints(edge).toString();
169 }});
170
171 vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
172 vv.getRenderer().getVertexLabelRenderer().setPositioner(new InsidePositioner());
173 vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO);
174
175 final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
176 add(panel);
177 final AbstractModalGraphMouse graphMouse = new DefaultModalGraphMouse();
178 vv.setGraphMouse(graphMouse);
179
180 vv.addKeyListener(graphMouse.getModeKeyListener());
181 vv.setToolTipText("<html><center>Type 'p' for Pick mode<p>Type 't' for Transform mode");
182
183 final ScalingControl scaler = new CrossoverScalingControl();
184
185
186
187
188 JButton plus = new JButton("+");
189 plus.addActionListener(new ActionListener() {
190 public void actionPerformed(ActionEvent e) {
191 scaler.scale(vv, 1.1f, vv.getCenter());
192 }
193 });
194 JButton minus = new JButton("-");
195 minus.addActionListener(new ActionListener() {
196 public void actionPerformed(ActionEvent e) {
197 scaler.scale(vv, 1/1.1f, vv.getCenter());
198 }
199 });
200
201 JButton reset = new JButton("reset");
202 reset.addActionListener(new ActionListener() {
203
204 public void actionPerformed(ActionEvent e) {
205 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
206 vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW).setToIdentity();
207 }});
208
209 JPanel controls = new JPanel();
210 controls.add(plus);
211 controls.add(minus);
212 controls.add(reset);
213 add(controls, BorderLayout.SOUTH);
214 }
215
216
217
218
219
220
221 private void createVertices() {
222 for (String city : map.keySet()) {
223 graph.addVertex(city);
224 }
225 }
226
227
228
229
230
231 void createEdges() {
232
233 for(int i=0; i<map.keySet().size()*1.3; i++) {
234 graph.addEdge(new Double(Math.random()), randomCity(), randomCity(), EdgeType.DIRECTED);
235 }
236 }
237
238 private String randomCity() {
239 int m = cityList.size();
240 return cityList.get((int)(Math.random()*m));
241 }
242
243 static class CityTransformer implements Transformer<String,String[]> {
244
245 Map<String,String[]> map;
246 public CityTransformer(Map<String,String[]> map) {
247 this.map = map;
248 }
249
250
251
252
253 public String[] transform(String city) {
254 return map.get(city);
255 }
256 }
257
258 static class LatLonPixelTransformer implements Transformer<String[],Point2D> {
259 Dimension d;
260 int startOffset;
261
262 public LatLonPixelTransformer(Dimension d) {
263 this.d = d;
264 }
265
266
267
268 public Point2D transform(String[] latlon) {
269 double latitude = 0;
270 double longitude = 0;
271 String[] lat = latlon[0].split(" ");
272 String[] lon = latlon[1].split(" ");
273 latitude = Integer.parseInt(lat[0]) + Integer.parseInt(lat[1])/60f;
274 latitude *= d.height/180f;
275 longitude = Integer.parseInt(lon[0]) + Integer.parseInt(lon[1])/60f;
276 longitude *= d.width/360f;
277 if(lat[2].equals("N")) {
278 latitude = d.height / 2 - latitude;
279
280 } else {
281 latitude = d.height / 2 + latitude;
282 }
283
284 if(lon[2].equals("W")) {
285 longitude = d.width / 2 - longitude;
286
287 } else {
288 longitude = d.width / 2 + longitude;
289 }
290
291 return new Point2D.Double(longitude,latitude);
292 }
293
294 }
295
296
297
298
299 public static void main(String[] args) {
300
301 final JFrame frame = new JFrame();
302 Container content = frame.getContentPane();
303 content.add(new WorldMapGraphDemo());
304 frame.pack();
305 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
306 frame.setVisible(true);
307 }
308 }