ModularMovementModelViz.java 12.2 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.util.PositionVector;
47
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView;
48
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
49
import de.tud.kom.p2psim.impl.topology.views.visualization.ui.VisualizationComponent;
50
51
52
53
54
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;
55
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.IAttractionPoint;
56
57
58
59
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;
60
61

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

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

74
75
	protected boolean showAttractionPoints = true;

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

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

82
83
	private JMenu menu;

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

86
	private final static int NODE_SIZE = 2;
87

88
	private final static int ATTR_SIZE = 5;
89
90

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

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

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

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

109
	public ModularMovementModelViz(ModularMovementModel model) {
Clemens Krug's avatar
Clemens Krug committed
110
		init();
111
		this.movementModel = model;
112
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
	}

	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;
138
139
	}

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

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

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

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

		if (showTrajectories) {
			for (TrajectoryVis tVis : trajectoryVisualizations.values()) {
				tVis.drawTrajectory(g2);
			}
		}
187
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
		
		g2.setColor(Color.black);				
		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.getX()), 
				VisualizationInjector.scaleValue(p2.getX()) - VisualizationInjector.scaleValue(p1.getX()), 
				VisualizationInjector.scaleValue(p2.getY())- VisualizationInjector.scaleValue(p1.getY()));
		
		p1 = GPSCalculation.transformGPSWindowToOwnWorld(51.821036,8.771151);
		p2 = GPSCalculation.transformGPSWindowToOwnWorld(51.814987, 8.779090);
		
		g2.fillRect(VisualizationInjector.scaleValue(p1.getX()), VisualizationInjector.scaleValue(p1.getX()), 
				VisualizationInjector.scaleValue(p2.getX() - p1.getX()), 
				VisualizationInjector.scaleValue(p2.getY() - p1.getY()));
		
		
		
//		
//		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  );
//			}
//		}
		
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
	}

	@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;
242
		
243
244
245
246
247
248
		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
249
250
251
			if (!rt.hasSegmentInformation()) {
				return;
			}
252
			boolean alt = false;
253
254
			for (RouteSegment segment : rt.getSegmentsAhead()) {
				Location lastLoc = null;
255
256
257
258
259
				g2.setColor(Color.MAGENTA);
				if (alt) {
					g2.setColor(Color.ORANGE);
				}
				alt = !alt;
260
261
262
				for (Location loc : segment.getSegmentLocations()) {
					if (lastLoc == null) {
						lastLoc = loc;
263
264
						g2.drawString(segment.getSegmentId(),
								VisualizationInjector
265
										.scaleValue(lastLoc.getLongitudeOrX()),
266
								VisualizationInjector
267
										.scaleValue(lastLoc.getLatitudeOrY()));
268
269
						continue;
					}
270
					g2.setStroke(new BasicStroke(3.0f));
271
272
					g2.drawLine(
							VisualizationInjector
273
									.scaleValue(lastLoc.getLongitudeOrX()),
274
							VisualizationInjector
275
									.scaleValue(lastLoc.getLatitudeOrY()),
276
							VisualizationInjector
277
									.scaleValue(loc.getLongitudeOrX()),
278
							VisualizationInjector
279
									.scaleValue(loc.getLatitudeOrY()));
280
281
282
283
284
					lastLoc = loc;
				}
			}
		}

285
	}
286

Clemens Krug's avatar
Clemens Krug committed
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
    /**
     * 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)
    {
304
305
		Composite gc = g2.getComposite();
		
306
        for (IAttractionPoint aPoint : movementModel.getAttractionPoints()) {
Clemens Krug's avatar
Clemens Krug committed
307
308
309
310
311
            Point point = ((PositionVector) aPoint).asPoint();
            // draw border
            g2.setColor(Color.BLACK);
            g2.setFont(VisualizationTopologyView.FONT_MEDIUM);
            g2.drawString(aPoint.getName(),
312
                    VisualizationInjector.scaleValue(point.x) - g2.getFontMetrics().stringWidth(aPoint.getName()) / 2,
313
                    VisualizationInjector.scaleValue(point.y - aPoint.getRadius() - 5) - ATTR_SIZE);
314
315
316
317
318
319
320
//            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);
321
            g2.setColor(COLOR_ATTR_POINT);
322
            int radius = VisualizationInjector.scaleValue(aPoint.getRadius()) + ATTR_SIZE;
323
324
325
            g2.drawOval(VisualizationInjector.scaleValue(point.x) - radius,
                    VisualizationInjector.scaleValue(point.y) - radius,
                    radius * 2 + 1, radius * 2 + 1);
326
327
            
            g2.setComposite(gc);
Clemens Krug's avatar
Clemens Krug committed
328
329
330
331
332
333
334
335
336
337
338
339
340
        }
    }

    /**
     * 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
341
     
Clemens Krug's avatar
Clemens Krug committed
342
        g2.setColor(Color.GRAY);
343
        g2.fillOval(VisualizationInjector.scaleValue(pt.getX()) - NODE_SIZE,
Julian Zobel's avatar
Julian Zobel committed
344
345
                VisualizationInjector.scaleValue(pt.getY()) - NODE_SIZE, 
                NODE_SIZE * 2, NODE_SIZE * 2);
Clemens Krug's avatar
Clemens Krug committed
346
347
348
349
350
351
352
	}

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

353
354
355
356
357
358
359
360
361
362
363
364
	@Override
	public String getDisplayName() {
		return "Mobility Model";
	}

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

	@Override
	public JMenu getCustomMenu() {
365
		return menu;
366
367
368
369
370
371
	}

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