ModularMovementModelViz.java 14 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Copyright (c) 2005-2015 KOM – Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package de.tud.kom.p2psim.impl.topology.movement.modularosm;

23
import java.awt.BasicStroke;
24
import java.awt.Color;
25
import java.awt.Composite;
26
27
28
29
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
30
import java.awt.geom.Point2D;
31
import java.util.LinkedHashMap;
32
import java.util.LinkedList;
33
import java.util.Map;
34
import javax.swing.JCheckBoxMenuItem;
35
import javax.swing.JComponent;
36
import javax.swing.JMenu;
37
38
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
39
40
41
42

import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.GHPoint3D;

43
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
44
import de.tud.kom.p2psim.impl.topology.movement.local.AbstractLocalMovementStrategy;
45
import de.tud.kom.p2psim.impl.topology.movement.local.RealWorldStreetsMovement;
46
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionProvider;
47
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
48
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView;
49
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
50
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.VisualizationComponent;
51
52
53
54
55
import de.tud.kom.p2psim.impl.topology.views.visualization.world.NodeVisInteractionListener;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Oracle;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
56
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
57
58
59
60
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.Route.RouteSegment;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.route.RouteSensor;
61
62

/**
63
64
 * Visualization Component of the Attraction Points in the Modular Movement
 * Model.
65
66
 * 
 * 
67
 * @author Martin Hellwig, Bjoern Richerzhagen
68
69
 * @version 1.0, 02.07.2015
 */
70
public class ModularMovementModelViz extends JComponent
71
		implements VisualizationComponent, NodeVisInteractionListener {
72

Clemens Krug's avatar
Clemens Krug committed
73
	protected ModularMovementModel movementModel;
74

75
76
	protected boolean showAttractionPoints = true;

Julian Zobel's avatar
Julian Zobel committed
77
	protected boolean showNodePositions = false;
78

Julian Zobel's avatar
Julian Zobel committed
79
	protected boolean showTrajectories = false;
80
81
	
	protected boolean setupCalculatesTrajectories = false;
82

83
84
	private JMenu menu;

85
86
	private Map<Long, TrajectoryVis> trajectoryVisualizations = new LinkedHashMap<>();

87
	private final static int NODE_SIZE = 2;
88

89
	private final static int ATTR_SIZE = 5;
90
91

	private static Color COLOR_ATTR_POINT = Color.decode("#4A7B9D");
92

93
	public ModularMovementModelViz() {
Clemens Krug's avatar
Clemens Krug committed
94
95
96
        init();
	}

97
	protected void init() {
Clemens Krug's avatar
Clemens Krug committed
98
99
        setBounds(0, 0, VisualizationInjector.getWorldX(),
                VisualizationInjector.getWorldY());
100
		VisualizationInjector.addInteractionListener(this);
Clemens Krug's avatar
Clemens Krug committed
101
102
103
104
105
106
        setOpaque(true);
        setVisible(true);

        menu = new JMenu("Mobility Model");
        menu.add(createCheckboxAp());
        menu.add(createCheckboxNodePositions());
107
		menu.add(createCheckboxTrajectories());
Clemens Krug's avatar
Clemens Krug committed
108
109
    }

110
	public ModularMovementModelViz(ModularMovementModel model) {
Clemens Krug's avatar
Clemens Krug committed
111
		init();
112
		this.movementModel = model;
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
	}

	private JCheckBoxMenuItem createCheckboxAp() {
		final JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(
				"show attraction points", showAttractionPoints);
		checkBox.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				showAttractionPoints = checkBox.isSelected();
				VisualizationInjector.invalidate();
			}
		});
		return checkBox;
	}

	private JCheckBoxMenuItem createCheckboxNodePositions() {
		final JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(
				"show node positions", showNodePositions);
		checkBox.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				showNodePositions = checkBox.isSelected();
				VisualizationInjector.invalidate();
			}
		});
		return checkBox;
139
140
	}

141
	private JCheckBoxMenuItem createCheckboxTrajectories() {
142
		setupCalculatesTrajectories = AbstractLocalMovementStrategy.isCalculatingRouteSegments();
143
144
145
146
147
148
		final JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem(
				"show node trajectories", showTrajectories);
		checkBox.addChangeListener(new ChangeListener() {
			@Override
			public void stateChanged(ChangeEvent e) {
				showTrajectories = checkBox.isSelected();
149
150
151
152
				if (!setupCalculatesTrajectories) {
					AbstractLocalMovementStrategy
							.setCalculationOfRouteSegments(showTrajectories);
				}
153
154
155
				VisualizationInjector.invalidate();
			}
		});
156
157
158
159
		if (!setupCalculatesTrajectories) {
			AbstractLocalMovementStrategy
					.setCalculationOfRouteSegments(showTrajectories);
		}
160
161
162
		return checkBox;
	}

163
164
	public static LinkedList<PointList> paths = new LinkedList<PointList>();
	
165
166
167
168
169
170
171
	@Override
	public void paint(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);

172
		if (showAttractionPoints) {
Clemens Krug's avatar
Clemens Krug committed
173
			drawAttractionPoints(g2);
174
		}
175

176
		if (showNodePositions) {
Clemens Krug's avatar
Clemens Krug committed
177
178
179
180
            for (SimLocationActuator comp : movementModel
                    .getAllLocationActuators()) {
                drawNodePosition(g2, comp);
            }
181
		}
182
183
184
185
186
187

		if (showTrajectories) {
			for (TrajectoryVis tVis : trajectoryVisualizations.values()) {
				tVis.drawTrajectory(g2);
			}
		}
188
		
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
		//<Variable name="GRAPHHOPPER_BLOCKED_AREAS" value="51.813680,8.783510,51.806795,8.804239;51.821036,8.771151,51.814987, 8.779090;" /> 
		
		if(this.movementModel.getLocalMovementStrategy() instanceof RealWorldStreetsMovement) {
			RealWorldStreetsMovement mov = (RealWorldStreetsMovement) this.movementModel.getLocalMovementStrategy();
			
			if(mov.getBlockedAreas() != null && !mov.getBlockedAreas().isEmpty()) {
				g2.setColor(new Color(1f, 0f, 0f, 0.5f));
				
				String[] split = mov.getBlockedAreas().split(";");
				
				for (String s : split) {
					String[] vals = s.split(",");
									
					PositionVector p1 = GPSCalculation.transformGPSWindowToOwnWorld(Double.parseDouble(vals[0]), Double.parseDouble(vals[1]));
					PositionVector p2 = GPSCalculation.transformGPSWindowToOwnWorld(Double.parseDouble(vals[2]), Double.parseDouble(vals[3]));
					
					g2.fillRect(VisualizationInjector.scaleValue(p1.getX()), VisualizationInjector.scaleValue(p1.getY()), 
							VisualizationInjector.scaleValue(p2.getX()) - VisualizationInjector.scaleValue(p1.getX()), 
							VisualizationInjector.scaleValue(p2.getY())- VisualizationInjector.scaleValue(p1.getY()));
					
				}
			}
			
		}
		
//		g2.setColor(Color.black);			
//		g2.setColor(new Color(1f, 0f, 0f, 0.5f));
//		PositionVector p1 = GPSCalculation.transformGPSWindowToOwnWorld(51.813680, 8.783510);
//		PositionVector p2 = GPSCalculation.transformGPSWindowToOwnWorld(51.806795, 8.804239);
//					
//		g2.fillRect(VisualizationInjector.scaleValue(p1.getX()), VisualizationInjector.scaleValue(p1.getY()), 
Julian Zobel's avatar
Julian Zobel committed
220
221
222
//				VisualizationInjector.scaleValue(p2.getX()) - VisualizationInjector.scaleValue(p1.getX()), 
//				VisualizationInjector.scaleValue(p2.getY())- VisualizationInjector.scaleValue(p1.getY()));
//		
223
//		p1 = GPSCalculation.transformGPSWindowToOwnWorld(51.821036, 8.771151);
Julian Zobel's avatar
Julian Zobel committed
224
//		p2 = GPSCalculation.transformGPSWindowToOwnWorld(51.814987, 8.779090);
225
226
//
//		g2.fillRect(VisualizationInjector.scaleValue(p1.getX()), VisualizationInjector.scaleValue(p1.getY()), 
Julian Zobel's avatar
Julian Zobel committed
227
228
//				VisualizationInjector.scaleValue(p2.getX() - p1.getX()), 
//				VisualizationInjector.scaleValue(p2.getY() - p1.getY()));
229
//		
230
231
232
233
234
235
236
237
238
//				
//		p1 = GPSCalculation.transformGPSWindowToOwnWorld(51.792919, 8.785700);
//		p2 = GPSCalculation.transformGPSWindowToOwnWorld(51.789575, 8.799222);
//				
//		g2.fillRect(VisualizationInjector.scaleValue(p1.getX()), VisualizationInjector.scaleValue(p1.getY()), 
//				VisualizationInjector.scaleValue(p2.getX()) - VisualizationInjector.scaleValue(p1.getX()), 
//				VisualizationInjector.scaleValue(p2.getY())- VisualizationInjector.scaleValue(p1.getY()));
		
		//		
239
240
241
242
243
244
245
246
//		for (PointList pointList : paths) {
//			for (GHPoint3D temp : pointList) {
//				PositionVector p = RealWorldStreetsMovement.transformGPSWindowToOwnWorld(temp.getLat(), temp.getLon());
//				
//				g2.fillOval(VisualizationInjector.scaleValue(p.getX()) - 2, VisualizationInjector.scaleValue(p.getY()) - 2, 4,4  );
//			}
//		}
		
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
	}

	@Override
	public void onHostClick(long hostID, boolean isActive) {
		if (isActive) {
			Host h = Oracle.getHostByID(INodeID.get(hostID));
			try {
				RouteSensor routeSensor = h.getComponent(RouteSensor.class);
				trajectoryVisualizations.put(hostID,
						new TrajectoryVis(routeSensor));
			} catch (ComponentNotAvailableException e) {
				// ignore.
			}

		} else {
			trajectoryVisualizations.remove(hostID);
		}
	}

	/**
	 * Visualizes the movement trajectory of a given node.
	 * 
	 * @author Bjoern Richerzhagen
	 * @version 1.0, Aug 10, 2017
	 */
	private class TrajectoryVis {

		private final RouteSensor routeSensor;
275
		
276
277
278
279
280
281
		public TrajectoryVis(RouteSensor routeSensor) {
			this.routeSensor = routeSensor;
		}

		public void drawTrajectory(Graphics2D g2) {
			Route rt = routeSensor.getRoute();
Björn Richerzhagen's avatar
Björn Richerzhagen committed
282
283
284
			if (!rt.hasSegmentInformation()) {
				return;
			}
285
			boolean alt = false;
286
287
			for (RouteSegment segment : rt.getSegmentsAhead()) {
				Location lastLoc = null;
288
289
290
291
292
				g2.setColor(Color.MAGENTA);
				if (alt) {
					g2.setColor(Color.ORANGE);
				}
				alt = !alt;
293
294
295
				for (Location loc : segment.getSegmentLocations()) {
					if (lastLoc == null) {
						lastLoc = loc;
296
297
						g2.drawString(segment.getSegmentId(),
								VisualizationInjector
298
										.scaleValue(lastLoc.getLongitudeOrX()),
299
								VisualizationInjector
300
										.scaleValue(lastLoc.getLatitudeOrY()));
301
302
						continue;
					}
303
					g2.setStroke(new BasicStroke(3.0f));
304
305
					g2.drawLine(
							VisualizationInjector
306
									.scaleValue(lastLoc.getLongitudeOrX()),
307
							VisualizationInjector
308
									.scaleValue(lastLoc.getLatitudeOrY()),
309
							VisualizationInjector
310
									.scaleValue(loc.getLongitudeOrX()),
311
							VisualizationInjector
312
									.scaleValue(loc.getLatitudeOrY()));
313
314
315
316
317
					lastLoc = loc;
				}
			}
		}

318
	}
319

Clemens Krug's avatar
Clemens Krug committed
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    /**
     * Provides access super.paintComponent() for extending classes.
     * @param g the Graphics object for painting.
     */
    protected void paintSuper(Graphics g)
    {
        super.paintComponent(g);
    }

    /**
     * Draws the attraction points. This method has been extracted from paint()
     * to make it possible for extending class to override only this bit while leaving everything
     * else untouched.
     * @param g2 the Graphics2D object for painting.
     */
	protected void drawAttractionPoints(Graphics2D g2)
    {
337
338
		Composite gc = g2.getComposite();
		
339
        for (IAttractionPoint aPoint : movementModel.getAttractionPoints()) {
Clemens Krug's avatar
Clemens Krug committed
340
341
342
343
344
            Point point = ((PositionVector) aPoint).asPoint();
            // draw border
            g2.setColor(Color.BLACK);
            g2.setFont(VisualizationTopologyView.FONT_MEDIUM);
            g2.drawString(aPoint.getName(),
345
                    VisualizationInjector.scaleValue(point.x) - g2.getFontMetrics().stringWidth(aPoint.getName()) / 2,
346
                    VisualizationInjector.scaleValue(point.y - aPoint.getRadius() - 5) - ATTR_SIZE);
347
348
349
350
351
352
353
//            g2.setColor(COLOR_ATTR_POINT);
//            float alpha = 0.25f + (float) (aPoint.getWeight() / 2);
//            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
//            g2.fillOval(
//                    VisualizationInjector.scaleValue(point.x) - ATTR_PAD,
//                    VisualizationInjector.scaleValue(point.y) - ATTR_PAD,
//                    ATTR_PAD * 2 + 1, ATTR_PAD * 2 + 1);
354
            g2.setColor(COLOR_ATTR_POINT);
355
            int radius = VisualizationInjector.scaleValue(aPoint.getRadius()) + ATTR_SIZE;
356
357
358
            g2.drawOval(VisualizationInjector.scaleValue(point.x) - radius,
                    VisualizationInjector.scaleValue(point.y) - radius,
                    radius * 2 + 1, radius * 2 + 1);
359
360
            
            g2.setComposite(gc);
Clemens Krug's avatar
Clemens Krug committed
361
362
363
364
365
366
367
368
369
370
371
372
373
        }
    }

    /**
     * Draws the position of the node. This method has been extracted from paint()
     * to make it possible for extending class to override only this bit while leaving everything
     * else untouched. Instead of painting all of the nodes, only a specific one gets painted. This allows
     * extending class to fall back to this implementation if one specific node could not be drawn for whatever reason.
     * @param g2 the Graphics2D object for painting.
     */
	protected void drawNodePosition(Graphics2D g2, SimLocationActuator comp)
	{
        Point2D pt = comp.getRealPosition().asPoint();
Julian Zobel's avatar
Julian Zobel committed
374
     
Clemens Krug's avatar
Clemens Krug committed
375
        g2.setColor(Color.GRAY);
376
        g2.fillOval(VisualizationInjector.scaleValue(pt.getX()) - NODE_SIZE,
Julian Zobel's avatar
Julian Zobel committed
377
378
                VisualizationInjector.scaleValue(pt.getY()) - NODE_SIZE, 
                NODE_SIZE * 2, NODE_SIZE * 2);
Clemens Krug's avatar
Clemens Krug committed
379
380
381
382
383
384
385
	}

	protected void setMovementModel(ModularMovementModel model)
    {
        movementModel = model;
    }

386
387
388
389
390
391
392
393
394
395
396
397
	@Override
	public String getDisplayName() {
		return "Mobility Model";
	}

	@Override
	public JComponent getComponent() {
		return this;
	}

	@Override
	public JMenu getCustomMenu() {
398
		return menu;
399
400
401
402
403
404
	}

	@Override
	public boolean isHidden() {
		return false;
	}
405
}