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

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

282
	}
283

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

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

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

350
351
352
353
354
355
356
357
358
359
360
361
	@Override
	public String getDisplayName() {
		return "Mobility Model";
	}

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

	@Override
	public JMenu getCustomMenu() {
362
		return menu;
363
364
365
366
367
368
	}

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