ModularMovementModelViz.java 12.4 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
		
Julian Zobel's avatar
Julian Zobel committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
//		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()));
203
204
205
206
207
208
209
210
211
212
213
214
		
		
		
//		
//		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  );
//			}
//		}
		
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
242
	}

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

286
	}
287

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

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

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

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

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

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

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