Commit eff5d429 authored by Julian Zobel's avatar Julian Zobel 🦄
Browse files

Merge branch 'master' into 'cherry-pick-7698d9d7'

# Conflicts:
#   src/de/tud/kom/p2psim/impl/analyzer/metric/output/MetricOutputDAO.java
#   src/de/tud/kom/p2psim/impl/util/db/dao/DAO.java
parents 1c7f20ec 37020b44
......@@ -22,7 +22,7 @@ package de.tud.kom.p2psim.impl.topology.placement;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
/**
* Places components in the middle of the map
......
......@@ -30,7 +30,7 @@ import java.util.Vector;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
......
......@@ -30,8 +30,8 @@ import java.util.Vector;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.network.modular.common.GeoToolkit;
import de.tud.kom.p2psim.impl.topology.ExtendedPositionVector;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.ExtendedPositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
......
......@@ -27,8 +27,8 @@ import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tud.kom.p2psim.impl.network.modular.st.positioning.GNPPositioning.GNPPosition;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.TopologyFactory;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
/**
* Adapter to use the GNP-Positioning in the Topology-Components.
......
......@@ -26,7 +26,7 @@ import java.util.Vector;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
......@@ -69,9 +69,9 @@ public class GridPositionDistribution implements PlacementModel {
@Override
public PositionVector place(TopologyComponent comp) {
if (positions.isEmpty()) {
calcPositions2D();
calcPositions3D();
}
PositionVector pos = positions.get(placedComponents);
PositionVector pos = positions.get(placedComponents);
placedComponents = (placedComponents + 1) % numberOfComponents;
return pos;
}
......@@ -83,8 +83,8 @@ public class GridPositionDistribution implements PlacementModel {
public void setFakeNumberOfComponents(int fakeNumberOfComponents) {
this.fakeNumberOfComponents = fakeNumberOfComponents;
}
private void calcPositions2D() {
private void calcPositions3D() {
if (fakeNumberOfComponents != -1) {
numberOfComponents = fakeNumberOfComponents;
}
......@@ -104,7 +104,7 @@ public class GridPositionDistribution implements PlacementModel {
ycenter += random.nextDouble() * dist_y / 2
- dist_y / 4;
}
PositionVector vec = new PositionVector(xcenter, ycenter);
PositionVector vec = new PositionVector(xcenter, ycenter, 0);
positions.add(vec);
}
}
......
......@@ -23,8 +23,9 @@ package de.tud.kom.p2psim.impl.topology.placement;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;
import java.util.Random;
import org.apache.commons.io.IOUtils;
import org.json.JSONArray;
......@@ -33,18 +34,27 @@ import org.json.JSONObject;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.GPSCalculation;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
* Generates attraction points out of real data from OSM.
* Places a topology component based on JSON file attraction points
*
* @author Nils Richerzhagen
* @version 1.0, Feb 22, 2016
*
* FIX: Does only return the first element.
* Now components are placed on a randomly chosen attraction point.
*
* @author Julian Zobel
* @version 1.1, Nov 2018
*
*/
public class JSONPlacement implements PlacementModel {
private PositionVector worldDimensions;
private Random random = Randoms.getRandom(JSONPlacement.class);
private List<PositionVector> placements;
......@@ -60,7 +70,7 @@ public class JSONPlacement implements PlacementModel {
http://overpass-api.de/api/interpreter?data=%5Bout:json%5D;node%5Bamenity=bar%5D%2849%2E4813%2C8%2E5590%2C49%2E9088%2C8%2E7736%29%3Bout%3B
*/
public JSONPlacement() {
placements = new Vector<PositionVector>();
placements = new LinkedList<PositionVector>();
latLeft = GPSCalculation.getLatLower();
latRight = GPSCalculation.getLatUpper();
......@@ -119,7 +129,7 @@ public class JSONPlacement implements PlacementModel {
}
public void setPlacementJsonFile(String placementJsonFile) {
this.placementJsonFile = placementJsonFile;
this.placementJsonFile = placementJsonFile;
}
......@@ -128,12 +138,17 @@ public class JSONPlacement implements PlacementModel {
if(worldDimensions == null){
worldDimensions = comp.getTopology().getWorldDimensions();
}
getPlacements();
if(placements.isEmpty()) {
getPlacements();
}
}
@Override
public PositionVector place(TopologyComponent comp) {
return placements.remove(0);
int n = random.nextInt(placements.size());
return placements.get(n).clone();
}
}
......@@ -25,7 +25,7 @@ import java.util.Map;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
/**
* Unified interface for Position-Distributions based on PositionVectors. When
......
......@@ -24,9 +24,10 @@ import java.util.List;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.traci.TraciSimulationController;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml.XMLSimulationController;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.vehicular.api.SimulationSetupExtractor;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
......@@ -86,13 +87,13 @@ public class RSUPlacement implements PlacementModel {
*/
protected void initializeModel() {
if (this.sumoExe != null) {
_controller = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile);
_controller.init();
_controller = TraciSimulationController.createSimulationController(sumoExe, sumoConfigFile, 1);
_controller.init(Time.SECOND);
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_intersections = _controller.getAllIntersections(true);
} else {
_controller = new XMLSimulationController(null, sumoIntersections);
_controller.init();
_controller.init(Time.SECOND);
_controller.setObservedArea(offsetX, offsetY, offsetX + width, offsetY + height);
_intersections = _controller.getAllIntersections(true);
}
......@@ -108,7 +109,7 @@ public class RSUPlacement implements PlacementModel {
if (_currentIndex < _intersections.size()) {
Location intersection = _intersections.get(_currentIndex);
_currentIndex++;
return new PositionVector(intersection.getLongitude(), intersection.getLatitude());
return new PositionVector(intersection.getLongitudeOrX(), intersection.getLatitudeOrY());
} else {
return new PositionVector(Double.NaN, Double.NaN);
}
......
......@@ -22,7 +22,7 @@ package de.tud.kom.p2psim.impl.topology.placement;
import java.util.Random;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
/**
......@@ -38,7 +38,15 @@ public class RandomPositionDistribution extends PositionDistribution {
Random r = Randoms.getRandom(RandomPositionDistribution.class);
double[] vec = new double[getDimensions()];
for (int i = 0; i < getDimensions(); i++) {
vec[i] = r.nextInt((int) getWorldDimensions().getEntry(i));
int dim = (int) getWorldDimensions().getEntry(i);
if(dim == 0) {
vec[i] = 0;
}
else {
vec[i] = r.nextInt(dim);
}
}
PositionVector position = new PositionVector(vec);
return position;
......
/*
* Copyright (c) 2005-2010 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.placement;
import java.util.LinkedList;
import de.tud.kom.p2psim.api.topology.TopologyComponent;
import de.tud.kom.p2psim.api.topology.placement.PlacementModel;
import de.tud.kom.p2psim.impl.topology.component.BaseTopologyComponent;
import de.tud.kom.p2psim.impl.topology.component.UAVTopologyComponent;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
public class UAVBasePlacement implements PlacementModel {
public static LinkedList<UAVTopologyComponent> uavs = new LinkedList<>();
public static BaseTopologyComponent base;
private static double baseX, baseY;
private void addComponent(BaseTopologyComponent comp) {
if(base == null) {
base = comp;
}
else throw new UnsupportedOperationException("Received second base topology, only one supported!");
}
private void addComponent(UAVTopologyComponent comp) {
uavs.add(comp);
}
@Override
public PositionVector place(TopologyComponent comp) {
PositionVector pos = new PositionVector(baseX, baseY, 0);
return pos;
}
@Override
public void addComponent(TopologyComponent comp) {
if(comp instanceof BaseTopologyComponent) {
this.addComponent((BaseTopologyComponent)comp);
}
else if(comp instanceof UAVTopologyComponent) {
this.addComponent((UAVTopologyComponent)comp);
}
else {
throw new UnsupportedOperationException("UAVBasePlacement received wrong type of topology component!");
}
}
public void setBaseX(double X) {
this.baseX = X;
}
public void setBaseY(double Y) {
this.baseY = Y;
}
}
......@@ -21,7 +21,7 @@
/**
*
*/
package de.tud.kom.p2psim.impl.topology;
package de.tud.kom.p2psim.impl.topology.util;
/**
* @author Christian Gross
......
/*
* Copyright (c) 2005-2010 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.util;
import java.util.List;
import java.util.Set;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.linklayer.mac.MacAddress;
import de.tud.kom.p2psim.api.linklayer.mac.MacLayer;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.views.TopologyView;
import de.tud.kom.p2psim.impl.topology.component.DefaultTopologyComponent;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Oracle;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INode;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent.NetInterfaceName;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener;
import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSTypes;
import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityListener;
/**
* This is calculated based on global knowledge. It only registers as
* {@link LocationListener}, if a range is specified by the Provider.
*
* @author Bjoern Richerzhagen
* @version 1.0, May 13, 2015
*/
public class LocalGraphView implements LocationListener, ConnectivityListener {
/**
* Marker: has there been any movement since the graph view was last
* requested? If so: recalculate! Otherwise, we ignore this object to
* not perform calculations if no one is interested...
*/
private final double distance;
private final boolean isDistanceBased;
private final NetInterfaceName medium;
private final TopologyView topoView;
private final boolean onlyOnline;
private Graph currentView;
private boolean isInvalid = true;
private final PhyType phy;
public LocalGraphView(NetInterfaceName medium, boolean onlyOnline, Topology topology) {
this(medium, onlyOnline, -1, topology);
}
public LocalGraphView(NetInterfaceName medium, boolean onlyOnline,
double distance, Topology topology) {
this.medium = medium;
PhyType localPhy = null;
for (PhyType currPhy : PhyType.values()) {
if (currPhy.getNetInterfaceName() == medium
&& topology.getTopologyView(currPhy) != null) {
localPhy = currPhy;
break;
}
}
phy = localPhy;
assert localPhy != null;
this.topoView = topology.getTopologyView(localPhy);
this.distance = distance;
this.onlyOnline = onlyOnline;
this.isDistanceBased = (distance > 0);
assert !isDistanceBased || phy.isBroadcastMedium();
if (phy.isBroadcastMedium() || onlyOnline) {
for (Host host : Oracle.getAllHosts()) {
if (phy.isBroadcastMedium()) {
try {
DefaultTopologyComponent dcomp = host.getComponent(
DefaultTopologyComponent.class);
dcomp.requestLocationUpdates(null,
LocalGraphView.this);
} catch (ComponentNotAvailableException e) {
continue;
}
}
if (onlyOnline) {
if (host.getNetworkComponent()
.getByName(medium) != null) {
host.getNetworkComponent().getByName(medium)
.addConnectivityListener(
LocalGraphView.this);
}
}
}
}
}
private void recalculateLocalView() {
if (!isInvalid) {
/*
* Graphs are invalidated (i) based on movement, IFF a range was
* specified, (ii) based on online/offline events, IFF only
* online hosts are to be considered.
*/
return;
}
/*
* Calculate a complete global connectivity graph
*/
// Create new, empty graph
currentView = Graphs.createGraph();
// Add all (online?) nodes
for (MacLayer mac : topoView.getAllMacs()) {
if (!onlyOnline || mac.isOnline()) {
INode node = currentView.createNode(mac.getHost().getId());
node.setProperty(SiSTypes.PHY_LOCATION,
topoView.getPosition(mac.getMacAddress()).clone());
currentView.addElement(node);
}
}
if (isDistanceBased) {
// Build neighbors solely based on an assumed range
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Consider all nodes as potential neighbors
for (MacLayer neighborMac : topoView.getAllMacs()) {
// create, but do NOT add the node object
INode neighbor = currentView
.createNode(neighborMac.getHost().getId());
// only online nodes (already in graph)
if (!onlyOnline
|| currentView.containsNode(neighbor.getId())) {
// Distance?
if (topoView.getDistance(mac.getMacAddress(),
neighborMac.getMacAddress()) <= distance) {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
neighborMac.getHost().getId());
currentView.addElement(edge);
}
}
}
}
} else {
// Build neighborhoods based on underlay neighbors (1-hop)
for (MacLayer mac : topoView.getAllMacs()) {
// Fix Christoph Storm:
// Do not take offline nodes into account, unless told to do
// so...
if (onlyOnline && !currentView
.containsNode(mac.getHost().getId())) {
continue;
}
// Rely on underlay for neighbors
List<MacAddress> neighbors = topoView
.getNeighbors(mac.getMacAddress());
for (MacAddress neighborMac : neighbors) {
// create, but do NOT add the node object
INode neighbor = currentView.createNode(
topoView.getMac(neighborMac).getHost().getId());
// only online nodes (already in graph)
if (!onlyOnline
|| currentView.containsNode(neighbor.getId())) {
IEdge edge = currentView.createEdge(
mac.getHost().getId(),
topoView.getMac(neighborMac).getHost()
.getId());
currentView.addElement(edge);
edge.setProperty(SiSTypes.PHY_DISTANCE,
topoView.getDistance(mac.getMacAddress(),
neighborMac));
}
}
}
}
isInvalid = false;
}
public INode getOwnNode(SimHost ownHost) {
MacLayer mac = ownHost.getLinkLayer().getMac(phy);
if (!onlyOnline || mac.isOnline()) {
return currentView.createNode(ownHost.getId());
}
return null;
}
public Set<IEdge> getNeighbors(SimHost ownHost) {
recalculateLocalView();
INode ownNode = getOwnNode(ownHost);
return currentView.getOutgoingEdges(ownNode.getId());
}
/**
* This is the global view, therefore we do not distinguish between
* hosts.
*
* @return
*/
public Graph getLocalView() {
recalculateLocalView();
return currentView.clone();
}
@Override
public void onLocationChanged(Host host, Location location) {
this.isInvalid = true;
}
@Override
public void wentOnline(Host host, NetInterface netInterface) {
assert netInterface.getName() == medium;
this.isInvalid = true;
}
@Override
public void wentOffline(Host host, NetInterface netInterface) {
assert netInterface.getName() == medium;
this.isInvalid = true;
}
}
/*
* Copyright (c) 2005-2010 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.util;
import java.util.LinkedList;
import java.util.List;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationListener;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationRequest;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.LocationSensor;
/**
* Update 15.03.16 added support for multiple listeners (however, frequency
* etc. is immune after the first request is registered.)
*
* @author Bjoern Richerzhagen
* @version 1.0, Mar 15, 2016
*/
public class LocationRequestImpl implements LocationRequest, EventHandler {
private boolean immune = false;
private long interval = 1 * Simulator.MINUTE_UNIT;
private int priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
private Location lastLocation = null;
private List<LocationListener> listeners = new LinkedList<LocationListener>();
private int eventTypeSeq = 0;
private SimHost host;
private LocationSensor locationSensor;
public LocationRequestImpl(SimHost host, LocationSensor locationSensor) {
this.host = host;
this.locationSensor = locationSensor;
}
public void cancel(LocationListener listener) {
boolean removed = listeners.remove(listener);
if (listeners.isEmpty()) {
// upcoming event is no longer valid!
eventTypeSeq++;
}
assert removed;
}
public void immunizeAndStart(LocationListener listener) {
immune = true;
assert interval > 0;
if (listeners.isEmpty()) {
// Only start once!
lastLocation = null;
Event.scheduleImmediately(this, null, eventTypeSeq);
} else {
// Fire each new listener at least once
listener.onLocationChanged(host, locationSensor.getLastLocation());
}
listeners.add(listener);
}
@Override
public void setInterval(long interval) {
if (!immune) {
this.interval = interval;
}
}
@Override
public void setPriority(int priority) {
if (!immune) {
this.priority = priority;
}
}
@Override
public void eventOccurred(Object content, int type) {
if (eventTypeSeq != type) {
/*
* Discard invalid events caused when a client cancels updates
* but reactivates the request within the update frequency
* interval. In this case, the old events continue rescheduling
* themselves.
*/
return;
}
if (!listeners.isEmpty()) {
// Only reschedule, if at least one listener is ... listening
Location newLoc = locationSensor.getLastLocation();
listeners.forEach((LocationListener listener) -> listener
.onLocationChanged(host, newLoc));
lastLocation = newLoc;
Event.scheduleWithDelay(interval, this, null, eventTypeSeq);
}
}
}
......@@ -18,13 +18,14 @@
*
*/
package de.tud.kom.p2psim.impl.topology;
package de.tud.kom.p2psim.impl.topology.util;
import java.awt.Point;
import java.util.Arrays;
import com.vividsolutions.jts.geom.Coordinate;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
/**
......@@ -39,15 +40,26 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
*
* CHANGELOG
*
* - 14/08/08 Bjoern Richerzhagen: removed a number of unused, uncommented, and
* - 14.08.2008 Bjoern Richerzhagen: removed a number of unused, uncommented, and
* dubious methods from this class. Fixed the replace-bug (discovered by Nils)
* with little overhead. Implemented assertions with assertions - previous
* method introduces unwanted overhead outside of development settings. Removed
* the dubious equals-tolerance, which violates the hashCode contract. Seriously
* guys...
*
* @author Bjoern Richerzhagen
* @version 1.0, 04/25/2011
* - 05.09.2018 Julian Zobel: Added location support for third dimension (altitude)
* and removed a bug in the moveStep() function.
*
* - 10.09.2018 Julian Zobel: Adapted the replace function to work properly without
* assertions. Replace does now fully replace the position vector entries. PVs are now
* always at least 3D (with 0 altitude)
*
* - 14.03.2019 Louis Neumann: Added timestamp when creating a PositionVector and adjusted ageOfLocation()
*
* - 04.06.2019 Julian Zobel: Clone function also clones the timestamp from the cloned position.
*
* @author Bjoern Richerzhagen, Julian Zobel, Louis Neumann
* @version 1.2, 10.09.2018
*/
public class PositionVector implements Location {
......@@ -58,8 +70,13 @@ public class PositionVector implements Location {
* transforms can be performed in the getter-methods.
*/
private double[] values;
private double accuracy = -1;
/**
* Timestamp of creation
*/
private long created;
/**
* Create a new Position Vector
......@@ -68,23 +85,60 @@ public class PositionVector implements Location {
*/
public PositionVector(int dimensions) {
if (dimensions < 2) {
throw new AssertionError("Less than 2 Dimensions make no sense.");
throw new AssertionError("Vector cannot have less than 2 dimensions.");
}
// Position Vector is always at least 3D
if(dimensions == 2)
dimensions = 3;
this.dimensions = dimensions;
this.values = new double[dimensions];
this.created = Time.getCurrentTime();
}
/**
* Clone a PositionVector
* Constructors for position vectors, also usable for cloning.
*
* @param vec
*/
public PositionVector(PositionVector vec) {
this(vec.getDimensions());
for (int i = 0; i < vec.getDimensions(); i++) {
setEntry(i, vec.getEntry(i));
}
}
}
public PositionVector(double longitudeOrX, double latitudeOrY) {
this(3);
this.setLatitudeOrY(latitudeOrY);
this.setLongitudeOrX(longitudeOrX);
this.setAltitude(0);
}
public PositionVector(double longitudeOrX, double latitudeOrY, double altitude) {
this(3);
this.setLatitudeOrY(latitudeOrY);
this.setLongitudeOrX(longitudeOrX);
this.setAltitude(altitude);
}
public PositionVector(Location location) {
this.dimensions = 3;
this.values = new double[3];
if(location.hasAltitude()) {
this.setAltitude(location.getAltitude());
}
else {
this.setAltitude(0);
}
this.setLatitudeOrY(location.getLatitudeOrY());
this.setLongitudeOrX(location.getLongitudeOrX());
this.created = Time.getCurrentTime();
}
/**
* Convenience Constructor, initializes a Vector with values.length
......@@ -100,15 +154,35 @@ public class PositionVector implements Location {
}
@Override
public void setLatitude(double latitude)
throws UnsupportedOperationException {
this.setEntry(1, latitude);
public PositionVector clone() {
/*
* If you extend Position Vector, make sure to overwrite this method!
*/
PositionVector clone = new PositionVector(this); // use clone constructor
clone.created = this.created;
return clone;
}
/*
*
*
*/
@Override
public void setLongitude(double longitude)
throws UnsupportedOperationException {
this.setEntry(0, longitude);
public void setLatitudeOrY(double latitudeOrY)
{
this.setEntry(1, latitudeOrY);
}
@Override
public void setLongitudeOrX(double longitudeOrX)
{
this.setEntry(0, longitudeOrX);
}
@Override
public void setAltitude(double altitude) {
this.setEntry(2, altitude);
}
@Override
......@@ -323,25 +397,15 @@ public class PositionVector implements Location {
throw new AssertionError(
"Cast to Coordinate only possible with two or three dimensional PositionVector");
}
if (this.dimensions == 2)
return new Coordinate(getX(), getY());
else
return new Coordinate(getX(), getY(), getZ());
return new Coordinate(getX(), getY(), getZ());
}
@Override
public String toString() {
return "PositionVector " + Arrays.toString(values);
public String toString() {
return "PV("+getDimensions()+") " + Arrays.toString(values) + "";
}
@Override
public PositionVector clone() {
/*
* If you extend Position Vector, make sure to overwrite this method!
*/
return new PositionVector(this); // use clone constructor
}
@Override
public int hashCode() {
final int prime = 31;
......@@ -398,8 +462,11 @@ public class PositionVector implements Location {
* @param vector
*/
public void replace(PositionVector vector) {
assert dimensions == vector.getDimensions();
this.values = Arrays.copyOf(vector.values, dimensions);
this.dimensions = vector.getDimensions();
this.values = new double[dimensions];
for (int i = 0; i < this.dimensions; i++) {
setEntry(i, vector.getEntry(i));
}
}
/**
......@@ -420,8 +487,13 @@ public class PositionVector implements Location {
* @param speed
* @return
*/
@Deprecated
public PositionVector moveStep(PositionVector destination, double speed) {
if(speed == 0) {
return new PositionVector(this);
}
double distance = destination.distanceTo(this);
if (distance < speed) {
/*
......@@ -451,33 +523,39 @@ public class PositionVector implements Location {
@Override
public void set(Location l) {
assert (l instanceof PositionVector);
this.replace((PositionVector) l);
if (l instanceof PositionVector) {
this.replace((PositionVector) l);
}
else {
throw new AssertionError("Cannot replace PositionVector with Location");
}
}
@Override
public double getLatitude() {
/*
* TODO this is only a stub, as we do not work on long/lat in the
* simulator (yet?)
*/
public double getLatitudeOrY() {
return getY();
}
@Override
public double getLongitude() {
/*
* TODO this is only a stub, as we do not work on long/lat in the
* simulator (yet?)
*/
public double getLongitudeOrX() {
return getX();
}
@Override
public double getAltitude() {
return getZ();
}
@Override
public boolean hasAltitude() {
return dimensions > 2;
}
@Override
public long getAgeOfLocation() {
return 0; // always a fresh location
return Time.getCurrentTime() - created;
}
@Override
public double distanceTo(Location dest) {
if (dest instanceof PositionVector) {
......@@ -490,7 +568,8 @@ public class PositionVector implements Location {
* (pv.getEntry(i) - getEntry(i));
}
return Math.sqrt(dist);
} else {
}
else {
throw new AssertionError(
"Can not compute distance between Vectors of different length!");
}
......@@ -502,12 +581,14 @@ public class PositionVector implements Location {
@Override
public float bearingTo(Location dest) {
if (dest instanceof PositionVector) {
// This will be the angle between the difference vector (vec to dest) and the x-axis!
PositionVector t = (PositionVector) dest;
/*
* Calculates the angle using atan2 - this implies that the first
* two dimensions in your vector are the plane you are interested
* in.
*/
*/
return (float) Math.atan2(t.getEntry(1) - this.getEntry(1),
t.getEntry(0) - this.getEntry(0));
} else {
......@@ -515,4 +596,8 @@ public class PositionVector implements Location {
"Can only calculate an Angle on elements of type position vector");
}
}
}
......@@ -39,7 +39,7 @@ import de.tud.kom.p2psim.api.topology.movement.MovementSupported;
import de.tud.kom.p2psim.api.topology.views.DropProbabilityDeterminator;
import de.tud.kom.p2psim.api.topology.views.LatencyDeterminator;
import de.tud.kom.p2psim.api.topology.views.TopologyView;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Host;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
......
......@@ -33,7 +33,7 @@ import de.tud.kom.p2psim.api.linklayer.mac.MacLayer;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.api.topology.obstacles.ObstacleModel;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.FiveGTopologyView.CellLink;
import de.tud.kom.p2psim.impl.topology.views.fiveg.FiveGTopologyDatabase;
import de.tud.kom.p2psim.impl.topology.views.fiveg.FiveGTopologyDatabase.Entry;
......
......@@ -141,7 +141,7 @@ public class RangedTopologyView extends AbstractTopologyView<RangedLink> {
* @return max distance between hosts to still be able to communicate (ie.
* wireless range)
*/
protected double getRange() {
public double getRange() {
return range;
}
......
......@@ -29,18 +29,15 @@ import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
......@@ -157,8 +154,8 @@ public class VisualizationTopologyView extends JFrame
worldPanel.setPreferredSize(
new Dimension(VisualizationInjector.getWorldX(),
VisualizationInjector.getWorldY()));
this.setPreferredSize(new Dimension(800, 600));
this.setExtendedState(Frame.MAXIMIZED_BOTH);
this.setPreferredSize(new Dimension(VisualizationInjector.getWorldX() + 50, VisualizationInjector.getWorldY() + 100));
//this.setExtendedState(Frame.MAXIMIZED_BOTH);
Thread t = new Thread(this);
t.start();
......@@ -374,8 +371,8 @@ public class VisualizationTopologyView extends JFrame
@Override
public void onLocationChanged(Host host, Location location) {
this.position.setLocation(
VisualizationInjector.scaleValue(location.getLongitude()),
VisualizationInjector.scaleValue(location.getLatitude()));
VisualizationInjector.scaleValue(location.getLongitudeOrX()),
VisualizationInjector.scaleValue(location.getLatitudeOrY()));
}
}
......@@ -386,64 +383,26 @@ public class VisualizationTopologyView extends JFrame
* @author Bjoern Richerzhagen
* @version 1.0, 19.03.2012
*/
protected class WorldPanel extends JLayeredPane {
public class WorldPanel extends JLayeredPane {
protected ConcurrentHashMap<INodeID, VisNodeInformation> nodeInformation = new ConcurrentHashMap<INodeID, VisNodeInformation>();
protected final static int PADDING = 16;
public final static int PADDING = 16;
protected final static int NODE_PAD = 2;
public final static int NODE_PAD = 2;
private static final long serialVersionUID = -3023020559483652110L;
public WorldPanel() {
this.setLayout(null);
this.setDoubleBuffered(true);
this.addMouseListener(new MouseAdapter() {
/**
* Stores the mouse position, if the mouse button is pressed
*/
@Override
public void mousePressed(MouseEvent e) {
boolean turnedSomeoneOff = false;
for (VisNodeInformation node : nodeInformation.values()) {
// Make it easier to turn things off.
if (node.clicked && node.position
.distance(e.getPoint()) < PADDING + 2) {
node.clicked = !node.clicked;
VisualizationInjector
.notifyInteractionListenersOnClick(
node.hostId, node.clicked);
turnedSomeoneOff = true;
}
}
if (!turnedSomeoneOff) {
// Turn sth on (limit to one node)
for (VisNodeInformation node : nodeInformation.values()) {
if (node.disableClickListener) {
continue;
}
if (!node.clicked && node.position
.distance(e.getPoint()) < PADDING) {
node.clicked = !node.clicked;
VisualizationInjector
.notifyInteractionListenersOnClick(
node.hostId, node.clicked);
break;
}
}
}
}
});
}
public void addTopologyComponent(TopologyComponent comp) {
if (!nodeInformation.containsKey(comp.getHost().getId())) {
VisNodeInformation tVis = new VisNodeInformation(comp);
comp.requestLocationUpdates(null, tVis);
nodeInformation.put(comp.getHost().getId(), tVis);
nodeInformation.putIfAbsent(comp.getHost().getId(), tVis);
}
}
......@@ -455,32 +414,8 @@ public class VisualizationTopologyView extends JFrame
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
paintNodes(g2);
super.paintComponent(g);
}
private void paintNodes(Graphics2D g2) {
for (VisNodeInformation node : nodeInformation.values()) {
if (node.clicked) {
g2.setColor(Color.MAGENTA);
g2.fillOval((int) node.position.getX() - PADDING,
(int) node.position.getY() - PADDING,
PADDING * 2 + 1, PADDING * 2 + 1);
} else {
if (showNodes) {
// Draw nodes
g2.setColor(Color.DARK_GRAY);
g2.fillOval((int) node.position.getX() - NODE_PAD,
(int) node.position.getY() - NODE_PAD,
NODE_PAD * 2 + 1, NODE_PAD * 2 + 1);
}
}
}
}
}
public void notifyInteractionListenersOnClick(long hostid,
......@@ -573,7 +508,7 @@ public class VisualizationTopologyView extends JFrame
return plottingViews.get(name);
}
protected static void notifyInteractionListenersOnClick(long hostid,
public static void notifyInteractionListenersOnClick(long hostid,
boolean isActive) {
for (NodeVisInteractionListener listener : VisualizationInjector.interactionListeners) {
listener.onHostClick(hostid, isActive);
......
/*
* Copyright (c) 2005-2010 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.views.visualization.ui;
import java.util.HashMap;
import java.util.Map.Entry;
import org.jfree.data.xy.YIntervalSeries;
import de.tud.kom.p2psim.impl.analyzer.metric.MetricAnalyzer;
import de.tudarmstadt.maki.simonstrator.api.MessageWithDisasterType.MessageDisasterType;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricUnit;
import de.tudarmstadt.maki.simonstrator.api.common.metric.Metric.MetricValue;
public class DisasterMetricChartAdapter implements MetricPlotAdapter {
/** the overall metric */
private final Metric metric;
/** the average of all {@link MessageDisasterType} */
private MetricValue<Number> avg = null;
private YIntervalSeries avgSeries = null;
/** each type of {@link MessageDisasterType} */
private HashMap<MessageDisasterType, MetricValue<Number>> subMsgTypeValues;
private HashMap<YIntervalSeries, MetricValue<Number>> subMsgTypeSeries;
public DisasterMetricChartAdapter(Metric metric, PlottingView view,
int maxItems) {
this.metric = metric;
// fill subMsgTypeValues
if (metric.isOverallMetric()) {
MetricValue<?> mv = metric.getOverallMetric();
avg = (MetricValue<Number>) mv;
subMsgTypeValues = new HashMap<>();
for (MessageDisasterType type : MessageDisasterType.values()) {
Metric emergencyM = MetricAnalyzer
.getMetric(metric.getName() + type);
if (emergencyM != null && emergencyM.isOverallMetric())
subMsgTypeValues.put(type, emergencyM.getOverallMetric());
}
}
// fill series
if (avg != null) {
XYChart chart = view.createPlot(
metric.getName() + " -- " + metric.getDescription(),
"Average");
avgSeries = chart.getDataset().getSeries(0);
if (maxItems > 0)
avgSeries.setMaximumItemCount(maxItems);
subMsgTypeSeries = new HashMap<>();
for (Entry<MessageDisasterType, MetricValue<Number>> e : subMsgTypeValues
.entrySet()) {
YIntervalSeries tempSerie = new YIntervalSeries(e.getKey());
if (maxItems > 0)
tempSerie.setMaximumItemCount(maxItems);
chart.getDataset().addSeries(tempSerie);
subMsgTypeSeries.put(tempSerie, e.getValue());
}
}
}
@Override
public void refresh() {
double seconds = (double) Time.getCurrentTime() / (double) Time.SECOND;
if (avgSeries != null) {
double avgVal = scaledValue(avg);
if (avg.isValid())
avgSeries.add(seconds, avgVal, avgVal, avgVal);
}
for (Entry<YIntervalSeries, MetricValue<Number>> series : subMsgTypeSeries
.entrySet()) {
double tempVal = scaledValue(series.getValue());
if (series.getValue().isValid())
series.getKey().add(seconds, tempVal, tempVal, tempVal);
}
}
/**
* For {@link Time}.
*
* @param mv
* @return
*/
private double scaledValue(MetricValue<Number> mv) {
if (metric.getUnit() == MetricUnit.TIME) {
return mv.getValue().doubleValue() / Time.SECOND;
}
return mv.getValue().doubleValue();
}
}
......@@ -112,6 +112,9 @@ public class MetricChartAdapter implements MetricPlotAdapter {
+ metric.getDescription());
series = chart.getDataset().getSeries(0);
// add, otherwise re-range is not working
series.add(0, 0, 0, 0);
if (maxItems > 0) {
series.setMaximumItemCount(maxItems);
}
......@@ -159,8 +162,9 @@ public class MetricChartAdapter implements MetricPlotAdapter {
varDown = 0;
}
}
series.add(seconds, avgVal, Math.max(0, avgVal - varDown), avgVal
+ varUp);
if (avg.isValid())
series.add(seconds, avgVal, Math.max(0, avgVal - varDown), avgVal
+ varUp);
}
if (minSeries != null) {
double minV = scaledValue(min);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment