Commit 0c80da45 authored by Björn Richerzhagen's avatar Björn Richerzhagen
Browse files

Removed deprecated `Position`-Interface

parent db566de9
/* /*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package de.tud.kom.p2psim.impl.topology.waypoints.strong; package de.tud.kom.p2psim.impl.topology.waypoints.strong;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Vector; import java.util.Vector;
import javax.swing.JComponent; import javax.swing.JComponent;
import org.apache.commons.math.random.JDKRandomGenerator; import org.apache.commons.math.random.JDKRandomGenerator;
import org.apache.commons.math.random.RandomGenerator; import org.apache.commons.math.random.RandomGenerator;
import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.GeometryFactory;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.obstacles.Obstacle; import de.tud.kom.p2psim.api.topology.obstacles.Obstacle;
import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel; import de.tud.kom.p2psim.api.topology.waypoints.WaypointModel;
import de.tud.kom.p2psim.api.util.geo.maps.Node; import de.tud.kom.p2psim.api.util.geo.maps.Node;
import de.tud.kom.p2psim.api.util.geo.maps.Way; import de.tud.kom.p2psim.api.util.geo.maps.Way;
import de.tud.kom.p2psim.impl.simengine.Simulator; import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector;
import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector.DisplayString; import de.tud.kom.p2psim.impl.topology.views.VisualizationTopologyView.VisualizationInjector.DisplayString;
import de.tud.kom.p2psim.impl.topology.waypoints.StrongWaypointSupport; import de.tud.kom.p2psim.impl.topology.waypoints.StrongWaypointSupport;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.StrongWaypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.StrongWaypoint;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tud.kom.p2psim.impl.util.geo.maps.osm.OSMMap; import de.tud.kom.p2psim.impl.util.geo.maps.osm.OSMMap;
import de.tud.kom.p2psim.impl.util.geo.maps.osm.OSMNode; import de.tud.kom.p2psim.impl.util.geo.maps.osm.OSMNode;
import de.tud.kom.p2psim.impl.util.geo.maps.osm.OSMObstacle; import de.tud.kom.p2psim.impl.util.geo.maps.osm.OSMObstacle;
import de.tudarmstadt.maki.simonstrator.api.Monitor; import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level; import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
public class OSMHotspotStrategy extends StrongWaypointStrategy { public class OSMHotspotStrategy extends StrongWaypointStrategy {
protected ArrayList<HotspotDeplacmentInfo> hotspotMoveLerpPositions = new ArrayList<HotspotDeplacmentInfo>(); protected ArrayList<HotspotDeplacmentInfo> hotspotMoveLerpPositions = new ArrayList<HotspotDeplacmentInfo>();
private static String AMENITIES_FILENAME = "data/maps/valid_amenities.ordering"; private static String AMENITIES_FILENAME = "data/maps/valid_amenities.ordering";
private RandomGenerator rnd; private RandomGenerator rnd;
protected int placementRetries = 1000; protected int placementRetries = 1000;
// The number of strong waypoints that shall be added to the map // The number of strong waypoints that shall be added to the map
protected int noOfWaypoints = 1000; protected int noOfWaypoints = 1000;
// Holds the actually existing amenities in the map (given that they are // Holds the actually existing amenities in the map (given that they are
// valid) // valid)
ArrayList<String> existingAmenities; ArrayList<String> existingAmenities;
private WaypointModel model = null; private WaypointModel model = null;
/** /**
* A list of the most used amenities in open street map sorted by the * A list of the most used amenities in open street map sorted by the
* likelihood of being hotspots where many people meet. * likelihood of being hotspots where many people meet.
*/ */
private static ArrayList<String> validAmenities = new ArrayList<String>(); private static ArrayList<String> validAmenities = new ArrayList<String>();
public OSMHotspotStrategy() { public OSMHotspotStrategy() {
// The fresh random generator based on the configured seed // The fresh random generator based on the configured seed
// ensures that the amount of waypoints and their positioning is // ensures that the amount of waypoints and their positioning is
// reproducible // reproducible
rnd = new JDKRandomGenerator(); rnd = new JDKRandomGenerator();
rnd.setSeed(Simulator.getSeed()); rnd.setSeed(Simulator.getSeed());
validAmenities = readAmenitiesFromFile(); validAmenities = readAmenitiesFromFile();
} }
/** /**
* Reads the valid amenities from the file AMENETIES_FILENAME and returns * Reads the valid amenities from the file AMENETIES_FILENAME and returns
* them as a list of strings. * them as a list of strings.
* *
* @return * @return
*/ */
private ArrayList<String> readAmenitiesFromFile() { private ArrayList<String> readAmenitiesFromFile() {
File ordering = new File(AMENITIES_FILENAME); File ordering = new File(AMENITIES_FILENAME);
if (!ordering.exists()) if (!ordering.exists())
throw new ConfigurationException( throw new ConfigurationException(
"Unable to read the amenities file (" + AMENITIES_FILENAME "Unable to read the amenities file (" + AMENITIES_FILENAME
+ ")"); + ")");
ArrayList<String> amenities = new ArrayList<String>(); ArrayList<String> amenities = new ArrayList<String>();
BufferedReader reader = null; BufferedReader reader = null;
try { try {
reader = new BufferedReader(new FileReader(ordering)); reader = new BufferedReader(new FileReader(ordering));
String line = reader.readLine(); String line = reader.readLine();
while (line != null) { while (line != null) {
if (!line.equals("")) { if (!line.equals("")) {
amenities.add(line); amenities.add(line);
} }
line = reader.readLine(); line = reader.readLine();
} }
reader.close(); reader.close();
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new ConfigurationException( throw new ConfigurationException(
"Unable to read the amenities file (" + AMENITIES_FILENAME "Unable to read the amenities file (" + AMENITIES_FILENAME
+ ")", e); + ")", e);
} catch (IOException e) { } catch (IOException e) {
throw new ConfigurationException( throw new ConfigurationException(
"Unable to read the amenities file (" + AMENITIES_FILENAME "Unable to read the amenities file (" + AMENITIES_FILENAME
+ ")", e); + ")", e);
} finally { } finally {
try { try {
reader.close(); reader.close();
} catch (Exception e) { } catch (Exception e) {
// ... // ...
} }
} }
return amenities; return amenities;
} }
@Override @Override
public void generateStrongWaypoints(WaypointModel wpModel) { public void generateStrongWaypoints(WaypointModel wpModel) {
this.model = wpModel; this.model = wpModel;
if (!(wpModel instanceof StrongWaypointSupport)) if (!(wpModel instanceof StrongWaypointSupport))
throw new ConfigurationException( throw new ConfigurationException(
"OSMHotspotStrategy requires a waypoint model with strong waypoint support to work correctly."); "OSMHotspotStrategy requires a waypoint model with strong waypoint support to work correctly.");
if (!(model.getMap() instanceof OSMMap)) if (!(model.getMap() instanceof OSMMap))
throw new ConfigurationException( throw new ConfigurationException(
"OSMHotspotStrategy requires a OSMMap to work correctly."); "OSMHotspotStrategy requires a OSMMap to work correctly.");
OSMMap map = (OSMMap) model.getMap(); OSMMap map = (OSMMap) model.getMap();
StrongWaypointSupport sws = (StrongWaypointSupport) wpModel; StrongWaypointSupport sws = (StrongWaypointSupport) wpModel;
noOfWaypoints = sws.getNoOfWaypoints(); noOfWaypoints = sws.getNoOfWaypoints();
// Find hotspots based on the validAmenities list // Find hotspots based on the validAmenities list
final List<Hotspot> hotspots = findHotspots(map); final List<Hotspot> hotspots = findHotspots(map);
// Filter the existing valid amenities // Filter the existing valid amenities
existingAmenities = existingAmenity(hotspots); existingAmenities = existingAmenity(hotspots);
// Assign radii based on the priority of the amenities // Assign radii based on the priority of the amenities
assignRadii(hotspots, map); assignRadii(hotspots, map);
// Move the hotspots if they are inside of an obstacle // Move the hotspots if they are inside of an obstacle
if (obstacleModel != null) { if (obstacleModel != null) {
moveWaypointsBasedOnObstacles(hotspots); moveWaypointsBasedOnObstacles(hotspots);
} }
// Add the number of specified way points distributed by the radius size // Add the number of specified way points distributed by the radius size
addStrongWaypoints(hotspots); addStrongWaypoints(hotspots);
// Inject the JComponent for displaying the hotspots // Inject the JComponent for displaying the hotspots
VisualizationInjector.injectComponent("Hotspots", 0, new ShowHotspots( VisualizationInjector.injectComponent("Hotspots", 0, new ShowHotspots(
hotspots, model), false); hotspots, model), false);
VisualizationInjector.addDisplayString(new DisplayString() { VisualizationInjector.addDisplayString(new DisplayString() {
@Override @Override
public String getDisplayString() { public String getDisplayString() {
int distinctAmenities = 0; int distinctAmenities = 0;
if (existingAmenities != null) if (existingAmenities != null)
distinctAmenities = existingAmenities.size(); distinctAmenities = existingAmenities.size();
return "OSM[Waypoints (strong/weak): " return "OSM[Waypoints (strong/weak): "
+ model.getNumberOfWaypoints(StrongWaypoint.class) + model.getNumberOfWaypoints(StrongWaypoint.class)
+ "/" + model.getNumberOfWaypoints(WeakWaypoint.class) + "/" + model.getNumberOfWaypoints(WeakWaypoint.class)
+ ", Hotspots: " + hotspots.size() + ", Hotspots: " + hotspots.size()
+ ", Distinct amenities: " + distinctAmenities + ", Distinct amenities: " + distinctAmenities
+ ", Highest amenity: " + hotspots.get(0).amenity + "]"; + ", Highest amenity: " + hotspots.get(0).amenity + "]";
} }
}); });
} }
/** /**
* Uses the information provided by the obstacle model to move the hotspots * Uses the information provided by the obstacle model to move the hotspots
* outside of the obstacles should the be completely covered. * outside of the obstacles should the be completely covered.
*/ */
private void moveWaypointsBasedOnObstacles(List<Hotspot> hotspots) { private void moveWaypointsBasedOnObstacles(List<Hotspot> hotspots) {
for (Hotspot hotspot : hotspots) { for (Hotspot hotspot : hotspots) {
createHotspotGeometry(hotspot); createHotspotGeometry(hotspot);
Obstacle obstacle = isHotspotInsideObstacle(hotspot); Obstacle obstacle = isHotspotInsideObstacle(hotspot);
if (obstacle == null) if (obstacle == null)
continue; continue;
hotspot.wasHidden = true; hotspot.wasHidden = true;
Tuple<PositionVector, PositionVector> closestEdges = findClosestEdgest( Tuple<PositionVector, PositionVector> closestEdges = findClosestEdgest(
hotspot, obstacle); hotspot, obstacle);
double t = rnd.nextDouble(); double t = rnd.nextDouble();
PositionVector a = closestEdges.getA(); PositionVector a = closestEdges.getA();
PositionVector b = closestEdges.getB(); PositionVector b = closestEdges.getB();
PositionVector newPosition = a.clone(); PositionVector newPosition = a.clone();
PositionVector p = b.minus(newPosition); PositionVector p = b.minus(newPosition);
p.multiplyScalar(t); p.multiplyScalar(t);
newPosition.add(p); newPosition.add(p);
PositionVector direction = a.clone(); PositionVector direction = a.clone();
p = b.minus(direction); p = b.minus(direction);
p.multiplyScalar(0.5); p.multiplyScalar(0.5);
direction.add(p); direction.add(p);
direction = direction.minus(hotspot.position); direction = direction.minus(hotspot.position);
direction.normalize(); direction.normalize();
direction.multiplyScalar(hotspot.radius / 2); direction.multiplyScalar(hotspot.radius / 2);
newPosition.add(direction); newPosition.add(direction);
HotspotDeplacmentInfo lerpPos = new HotspotDeplacmentInfo( HotspotDeplacmentInfo lerpPos = new HotspotDeplacmentInfo(
closestEdges.getA(), closestEdges.getB(), newPosition, closestEdges.getA(), closestEdges.getB(), newPosition,
hotspot.position); hotspot.position);
hotspotMoveLerpPositions.add(lerpPos); hotspotMoveLerpPositions.add(lerpPos);
hotspot.position = newPosition; hotspot.position = newPosition;
} }
} }
private Tuple<PositionVector, PositionVector> findClosestEdgest( private Tuple<PositionVector, PositionVector> findClosestEdgest(
Hotspot hotspot, Obstacle obstacle) { Hotspot hotspot, Obstacle obstacle) {
Geometry geometry = obstacle.getGeometry(); Geometry geometry = obstacle.getGeometry();
Coordinate[] coordinates = geometry.getCoordinates(); Coordinate[] coordinates = geometry.getCoordinates();
PositionVector[] positionCache = new PositionVector[coordinates.length]; PositionVector[] positionCache = new PositionVector[coordinates.length];
double closestDistance = -1; double closestDistance = -1;
int closestIdx = -1; int closestIdx = -1;
for (int i = 0; i < coordinates.length; i++) { for (int i = 0; i < coordinates.length; i++) {
positionCache[i] = new PositionVector(coordinates[i].x, positionCache[i] = new PositionVector(coordinates[i].x,
coordinates[i].y); coordinates[i].y);
double d = positionCache[i].getDistance(hotspot.position); double d = positionCache[i].distanceTo(hotspot.position);
if (closestDistance > d || closestDistance == -1) { if (closestDistance > d || closestDistance == -1) {
closestDistance = d; closestDistance = d;
closestIdx = i; closestIdx = i;
} }
} }
PositionVector before = positionCache[closestIdx - 1 == -1 ? coordinates.length - 1 PositionVector before = positionCache[closestIdx - 1 == -1 ? coordinates.length - 1
: closestIdx - 1]; : closestIdx - 1];
PositionVector after = positionCache[closestIdx + 1 == coordinates.length ? 0 PositionVector after = positionCache[closestIdx + 1 == coordinates.length ? 0
: closestIdx + 1]; : closestIdx + 1];
if (before.getDistance(hotspot.position) < after if (before.distanceTo(hotspot.position) < after
.getDistance(hotspot.position)) { .distanceTo(hotspot.position)) {
return new Tuple<PositionVector, PositionVector>( return new Tuple<PositionVector, PositionVector>(
positionCache[closestIdx].clone(), before); positionCache[closestIdx].clone(), before);
} else { } else {
return new Tuple<PositionVector, PositionVector>( return new Tuple<PositionVector, PositionVector>(
positionCache[closestIdx].clone(), after); positionCache[closestIdx].clone(), after);
} }
} }
private Obstacle isHotspotInsideObstacle(Hotspot hotspot) { private Obstacle isHotspotInsideObstacle(Hotspot hotspot) {
for (Obstacle obstacle : obstacleModel.getObstacles()) { for (Obstacle obstacle : obstacleModel.getObstacles()) {
if (obstacle.contains(hotspot.geometry)) { if (obstacle.contains(hotspot.geometry)) {
return obstacle; return obstacle;
} }
} }
return null; return null;
} }
/** /**
* Uses the validAmenities list to find hotspots in the map and returns a * Uses the validAmenities list to find hotspots in the map and returns a
* list newly created Hotspots. * list newly created Hotspots.
* *
* @param map * @param map
* @return * @return
*/ */
private List<Hotspot> findHotspots(OSMMap map) { private List<Hotspot> findHotspots(OSMMap map) {
List<Hotspot> hotspots = new ArrayList<Hotspot>(); List<Hotspot> hotspots = new ArrayList<Hotspot>();
Collection<OSMNode> nodes = map.getNodes(); Collection<OSMNode> nodes = map.getNodes();
Collection<Way> ways = map.getWays(); Collection<Way> ways = map.getWays();
List<Obstacle> obstacles = map.getObstacles(); List<Obstacle> obstacles = map.getObstacles();
// Node and Way are currently the only retained // Node and Way are currently the only retained
// information and also the most used // information and also the most used
// TODO: Add a MovementStrategy that doesn't use waypoints but avoids // TODO: Add a MovementStrategy that doesn't use waypoints but avoids
// obstacles // obstacles
// TODO: Add a MovementStrategy that uses the waypoints but doesn't move // TODO: Add a MovementStrategy that uses the waypoints but doesn't move
// in a straight line // in a straight line
// TODO: Add an option to assign StrongWaypoints based on the density of // TODO: Add an option to assign StrongWaypoints based on the density of
// WeakWaypoints or convert some WeakWaypoints to StrongWaypoints // WeakWaypoints or convert some WeakWaypoints to StrongWaypoints
for (Obstacle o : obstacles) { for (Obstacle o : obstacles) {
OSMObstacle obstacle = (OSMObstacle) o; OSMObstacle obstacle = (OSMObstacle) o;
if (obstacle.containsAttribute("amenity")) { if (obstacle.containsAttribute("amenity")) {
if (getAmenityIndex(obstacle.getAttribute("amenity"), if (getAmenityIndex(obstacle.getAttribute("amenity"),
validAmenities) < 0) validAmenities) < 0)
continue; continue;
Hotspot hotspot = new Hotspot(); Hotspot hotspot = new Hotspot();
hotspot.position = obstacle.getVertices().get(0); hotspot.position = obstacle.getVertices().get(0);
hotspot.amenity = obstacle.getAttribute("amenity"); hotspot.amenity = obstacle.getAttribute("amenity");
hotspot.type = obstacle.getAttribute("name"); hotspot.type = obstacle.getAttribute("name");
hotspots.add(hotspot); hotspots.add(hotspot);
} }
} }
/* /*
* for (Node n : nodes) { OSMNode node = (OSMNode)n; if * for (Node n : nodes) { OSMNode node = (OSMNode)n; if
* (node.containsAttribute("amenity")) { if * (node.containsAttribute("amenity")) { if
* (getAmenityIndex(node.getAttribute("amenity"), validAmenities) < 0) * (getAmenityIndex(node.getAttribute("amenity"), validAmenities) < 0)
* continue; * continue;
* *
* Hotspot hotspot = new Hotspot(); hotspot.position = * Hotspot hotspot = new Hotspot(); hotspot.position =
* node.getWorldPosition(); hotspot.amenity = * node.getWorldPosition(); hotspot.amenity =
* node.getAttribute("amenity"); hotspot.type = "node"; * node.getAttribute("amenity"); hotspot.type = "node";
* *
* hotspots.add(hotspot); } } * hotspots.add(hotspot); } }
* *
* for (Way w : ways) { OSMWay way = (OSMWay)w; if * for (Way w : ways) { OSMWay way = (OSMWay)w; if
* (way.containsAttribute("amenity")) { if * (way.containsAttribute("amenity")) { if
* (getAmenityIndex(way.getAttribute("amenity"), validAmenities) < 0) * (getAmenityIndex(way.getAttribute("amenity"), validAmenities) < 0)
* continue; * continue;
* *
* PositionVector center = getCenter(way.getNodes()); * PositionVector center = getCenter(way.getNodes());
* *
* Hotspot hotspot = new Hotspot(); hotspot.position = center; * Hotspot hotspot = new Hotspot(); hotspot.position = center;
* hotspot.amenity = way.getAttribute("amenity"); hotspot.type = "way"; * hotspot.amenity = way.getAttribute("amenity"); hotspot.type = "way";
* *
* hotspots.add(hotspot); } } * hotspots.add(hotspot); } }
*/ */
Collections.sort(hotspots, new HotspotComparator(validAmenities)); Collections.sort(hotspots, new HotspotComparator(validAmenities));
return hotspots; return hotspots;
} }
/** /**
* Filters the existing amenities based on the validAmenities list * Filters the existing amenities based on the validAmenities list
* *
* @param hotspots * @param hotspots
* Hotspots with amenities * Hotspots with amenities
* @return List of existing valid amenities * @return List of existing valid amenities
*/ */
public ArrayList<String> existingAmenity(List<Hotspot> hotspots) { public ArrayList<String> existingAmenity(List<Hotspot> hotspots) {
ArrayList<String> list = new ArrayList<String>(); ArrayList<String> list = new ArrayList<String>();
for (String vh : validAmenities) { for (String vh : validAmenities) {
for (Hotspot h : hotspots) { for (Hotspot h : hotspots) {
if (h.amenity.equals(vh)) { if (h.amenity.equals(vh)) {
list.add(vh); list.add(vh);
break; break;
} }
} }
} }
return list; return list;
} }
/** /**
* Returns the center of a list of nodes * Returns the center of a list of nodes
* *
* @param points * @param points
* @return * @return
*/ */
private PositionVector getCenter(Vector<Node> points) { private PositionVector getCenter(Vector<Node> points) {
PositionVector centroid = new PositionVector(0, 0); PositionVector centroid = new PositionVector(0, 0);
for (Node n : points) { for (Node n : points) {
centroid.add(n.getWorldPosition()); centroid.add(n.getWorldPosition());
} }
centroid.multiplyScalar(1 / (double) points.size()); centroid.multiplyScalar(1 / (double) points.size());
return centroid; return centroid;
} }
/** /**
* Calculates the maximum radius size based on the map size and assigns the * Calculates the maximum radius size based on the map size and assigns the
* radii based on the hotspots amenities priority. * radii based on the hotspots amenities priority.
* *
* The hotspot with the highest priority e.g. the first hotspot in the list * The hotspot with the highest priority e.g. the first hotspot in the list
* receives the maximum radius. * receives the maximum radius.
* *
* Note: This method also creates the Geometry object for the hotspot * Note: This method also creates the Geometry object for the hotspot
* *
* @param hotspots * @param hotspots
* Hotspots whos radius shall be calculated * Hotspots whos radius shall be calculated
* @param map * @param map
* The current map * The current map
*/ */
private void assignRadii(List<Hotspot> hotspots, OSMMap map) { private void assignRadii(List<Hotspot> hotspots, OSMMap map) {
PositionVector dimensions = map.getDimensions(); PositionVector dimensions = map.getDimensions();
double llsqrt = Math.sqrt(dimensions.getX() + dimensions.getY()); double llsqrt = Math.sqrt(dimensions.getX() + dimensions.getY());
double defaultRadius = 0.630 * llsqrt; // 0.887 double defaultRadius = 0.630 * llsqrt; // 0.887
int idx; int idx;
for (Hotspot h : hotspots) { for (Hotspot h : hotspots) {
idx = getAmenityIndex(h.amenity, existingAmenities); idx = getAmenityIndex(h.amenity, existingAmenities);
h.radius = (defaultRadius / (idx + 1)); h.radius = (defaultRadius / (idx + 1));
h.geometry = createHotspotGeometry(h); h.geometry = createHotspotGeometry(h);
} }
} }
private Geometry createHotspotGeometry(Hotspot h) { private Geometry createHotspotGeometry(Hotspot h) {
int points = 20; int points = 20;
double slice = 2 * Math.PI / points; double slice = 2 * Math.PI / points;
ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>(); ArrayList<Coordinate> coordinates = new ArrayList<Coordinate>();
for (int i = 0; i < points; i++) { for (int i = 0; i < points; i++) {
double angle = slice * i; double angle = slice * i;
int newX = (int) (h.position.getX() + h.radius * Math.cos(angle)); int newX = (int) (h.position.getX() + h.radius * Math.cos(angle));
int newY = (int) (h.position.getY() + h.radius * Math.sin(angle)); int newY = (int) (h.position.getY() + h.radius * Math.sin(angle));
coordinates.add(new Coordinate(newX, newY)); coordinates.add(new Coordinate(newX, newY));
} }
coordinates.add(coordinates.get(0)); coordinates.add(coordinates.get(0));
Coordinate[] coordinateArray = new Coordinate[coordinates.size()]; Coordinate[] coordinateArray = new Coordinate[coordinates.size()];
GeometryFactory gf = new GeometryFactory(); GeometryFactory gf = new GeometryFactory();
return gf.createLinearRing(coordinates.toArray(coordinateArray)); return gf.createLinearRing(coordinates.toArray(coordinateArray));
} }
/** /**
* Adds strong way points to the graph that are used for the navigation of * Adds strong way points to the graph that are used for the navigation of
* AbstractWaypointMovementModel implementations. * AbstractWaypointMovementModel implementations.
* *
* FIXME: Find a way to place all waypoints (currently only used x retries) * FIXME: Find a way to place all waypoints (currently only used x retries)
* FIXME: Remove hotspots that are fully contained in an obstacle!! * FIXME: Remove hotspots that are fully contained in an obstacle!!
* *
* @param hotspots * @param hotspots
* Hotspots to whom the new way points shall be added * Hotspots to whom the new way points shall be added
*/ */
private void addStrongWaypoints(List<Hotspot> hotspots) { private void addStrongWaypoints(List<Hotspot> hotspots) {
double radiiSum = 0.0; double radiiSum = 0.0;
for (Hotspot h : hotspots) { for (Hotspot h : hotspots) {
radiiSum += h.radius; radiiSum += h.radius;
} }
double wps = noOfWaypoints / radiiSum; double wps = noOfWaypoints / radiiSum;
int wpCount = 0; int wpCount = 0;
addHotspots: { addHotspots: {
for (Hotspot h : hotspots) { for (Hotspot h : hotspots) {
int nrWps = (int) (Math.round(wps * h.radius)); int nrWps = (int) (Math.round(wps * h.radius));
int retries = 0; int retries = 0;
for (int i = 0; i < nrWps; i++) { for (int i = 0; i < nrWps; i++) {
PositionVector loc = selectRandomLocation(h); PositionVector loc = selectRandomLocation(h);
if (obstacleModel != null) { if (obstacleModel != null) {
if (!obstacleModel.contains(loc)) { if (!obstacleModel.contains(loc)) {
model.addWaypoint(new StrongWaypoint<Object>(loc)); model.addWaypoint(new StrongWaypoint<Object>(loc));
if (++wpCount >= noOfWaypoints) if (++wpCount >= noOfWaypoints)
break addHotspots; break addHotspots;
} else { } else {
if (!(retries++ >= placementRetries)) if (!(retries++ >= placementRetries))
i--; i--;
} }
} else { } else {
model.addWaypoint(new StrongWaypoint<Object>(loc)); model.addWaypoint(new StrongWaypoint<Object>(loc));
if (++wpCount >= noOfWaypoints) if (++wpCount >= noOfWaypoints)
break addHotspots; break addHotspots;
} }
} }
} }
} }
Monitor.log(OSMHotspotStrategy.class, Level.INFO, "Added " + wpCount Monitor.log(OSMHotspotStrategy.class, Level.INFO, "Added " + wpCount
+ " strong waypoints."); + " strong waypoints.");
} }
/** /**
* Selects a random location inside the hotspots radius * Selects a random location inside the hotspots radius
* *
* @param hotspot * @param hotspot
* @return * @return
*/ */
private PositionVector selectRandomLocation(Hotspot hotspot) { private PositionVector selectRandomLocation(Hotspot hotspot) {
double theta = rnd.nextDouble() * Math.PI * 2; double theta = rnd.nextDouble() * Math.PI * 2;
double length = Math.sqrt(rnd.nextDouble()); double length = Math.sqrt(rnd.nextDouble());
double x = Math.cos(theta) * hotspot.radius * length; double x = Math.cos(theta) * hotspot.radius * length;
double y = Math.sin(theta) * hotspot.radius * length; double y = Math.sin(theta) * hotspot.radius * length;
return new PositionVector(hotspot.position.getX() + x, return new PositionVector(hotspot.position.getX() + x,
hotspot.position.getY() + y); hotspot.position.getY() + y);
} }
/** /**
* Returns the position of the given amenity in the validHotspots list. * Returns the position of the given amenity in the validHotspots list.
* *
* @param amenity * @param amenity
* @param validHotspots * @param validHotspots
* @return * @return
*/ */
private static int getAmenityIndex(String amenity, private static int getAmenityIndex(String amenity,
ArrayList<String> validHotspots) { ArrayList<String> validHotspots) {
if (validHotspots == null) if (validHotspots == null)
return 0; return 0;
for (int i = 0; i < validHotspots.size(); i++) { for (int i = 0; i < validHotspots.size(); i++) {
if (validHotspots.get(i).equals(amenity)) { if (validHotspots.get(i).equals(amenity)) {
return i; return i;
} }
} }
return -1; return -1;
} }
/** /**
* Bean for hotspots * Bean for hotspots
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 08.04.2012 * @version 1.0, 08.04.2012
*/ */
private static class Hotspot { private static class Hotspot {
public Hotspot() { public Hotspot() {
// //
} }
public double weight; public double weight;
public String amenity; public String amenity;
public PositionVector position; public PositionVector position;
public String type; public String type;
public double radius; public double radius;
public Geometry geometry; public Geometry geometry;
public boolean wasHidden = false; public boolean wasHidden = false;
} }
/** /**
* Compares hotspots based on their amenity and prioritizes ways over nodes. * Compares hotspots based on their amenity and prioritizes ways over nodes.
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 08.04.2012 * @version 1.0, 08.04.2012
*/ */
private static class HotspotComparator implements Comparator<Hotspot> { private static class HotspotComparator implements Comparator<Hotspot> {
private ArrayList<String> validHotspots; private ArrayList<String> validHotspots;
public HotspotComparator(ArrayList<String> validHotspots) { public HotspotComparator(ArrayList<String> validHotspots) {
this.validHotspots = validHotspots; this.validHotspots = validHotspots;
} }
@SuppressWarnings("synthetic-access") @SuppressWarnings("synthetic-access")
@Override @Override
public int compare(Hotspot h1, Hotspot h2) { public int compare(Hotspot h1, Hotspot h2) {
int idx1 = getAmenityIndex(h1.amenity, validHotspots); int idx1 = getAmenityIndex(h1.amenity, validHotspots);
int idx2 = getAmenityIndex(h2.amenity, validHotspots); int idx2 = getAmenityIndex(h2.amenity, validHotspots);
int diff = idx1 - idx2; int diff = idx1 - idx2;
if (diff != 0) { if (diff != 0) {
return diff; return diff;
} else { } else {
if ("way".equals(h1) && "node".equals(h2)) if ("way".equals(h1) && "node".equals(h2))
return 1; return 1;
if ("node".equals(h1) && "way".equals(h2)) if ("node".equals(h1) && "way".equals(h2))
return -1; return -1;
return 0; return 0;
} }
} }
} }
private class HotspotDeplacmentInfo { private class HotspotDeplacmentInfo {
public PositionVector edge1; public PositionVector edge1;
public PositionVector edge2; public PositionVector edge2;
public PositionVector newPosition; public PositionVector newPosition;
public PositionVector oldPosition; public PositionVector oldPosition;
public HotspotDeplacmentInfo(PositionVector edge1, public HotspotDeplacmentInfo(PositionVector edge1,
PositionVector edge2, PositionVector newPosition, PositionVector edge2, PositionVector newPosition,
PositionVector oldPosition) { PositionVector oldPosition) {
this.edge1 = edge1; this.edge1 = edge1;
this.edge2 = edge2; this.edge2 = edge2;
this.newPosition = newPosition; this.newPosition = newPosition;
this.oldPosition = oldPosition; this.oldPosition = oldPosition;
} }
} }
/** /**
* Draws the hotspots on the map and displays some extra information * Draws the hotspots on the map and displays some extra information
* *
* @author Fabio Zöllner * @author Fabio Zöllner
* @version 1.0, 08.04.2012 * @version 1.0, 08.04.2012
*/ */
private class ShowHotspots extends JComponent { private class ShowHotspots extends JComponent {
private List<Hotspot> hotspots; private List<Hotspot> hotspots;
private WaypointModel model; private WaypointModel model;
public ShowHotspots(List<Hotspot> hotspots, WaypointModel model) { public ShowHotspots(List<Hotspot> hotspots, WaypointModel model) {
super(); super();
this.hotspots = hotspots; this.hotspots = hotspots;
this.model = model; this.model = model;
PositionVector dimension = model.getMap().getDimensions(); PositionVector dimension = model.getMap().getDimensions();
setBounds(0, 0, (int) dimension.getX(), (int) dimension.getY()); setBounds(0, 0, (int) dimension.getX(), (int) dimension.getY());
setOpaque(false); setOpaque(false);
setVisible(true); setVisible(true);
} }
@Override @Override
protected void paintComponent(Graphics g) { protected void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g; Graphics2D g2 = (Graphics2D) g;
g2.setFont(new Font("SansSerif", Font.PLAIN, 9)); g2.setFont(new Font("SansSerif", Font.PLAIN, 9));
int i = 0; int i = 0;
for (Hotspot h : hotspots) { for (Hotspot h : hotspots) {
if (!h.wasHidden) { if (!h.wasHidden) {
g2.setColor(new Color(255, 255, 0, 100)); g2.setColor(new Color(255, 255, 0, 100));
} else { } else {
g2.setColor(new Color(0, 0, 255, 100)); g2.setColor(new Color(0, 0, 255, 100));
} }
g2.fillOval((int) (h.position.getX() - h.radius), g2.fillOval((int) (h.position.getX() - h.radius),
(int) (h.position.getY() - h.radius), (int) (h.position.getY() - h.radius),
(int) h.radius * 2, (int) h.radius * 2); (int) h.radius * 2, (int) h.radius * 2);
g2.setColor(Color.BLACK); g2.setColor(Color.BLACK);
if (h.type != null) { if (h.type != null) {
g2.drawString( g2.drawString(
h.type, h.type,
(int) (h.position.getX() - h.amenity.length() * 1.5), (int) (h.position.getX() - h.amenity.length() * 1.5),
(int) h.position.getY()); (int) h.position.getY());
} }
} }
drawLerp(g2); drawLerp(g2);
} }
protected void drawLerp(Graphics2D g2) { protected void drawLerp(Graphics2D g2) {
for (HotspotDeplacmentInfo l : hotspotMoveLerpPositions) { for (HotspotDeplacmentInfo l : hotspotMoveLerpPositions) {
g2.setColor(new Color(0, 0, 0, 255)); g2.setColor(new Color(0, 0, 0, 255));
g2.drawLine((int) l.edge1.getX(), (int) l.edge1.getY(), g2.drawLine((int) l.edge1.getX(), (int) l.edge1.getY(),
(int) l.edge2.getX(), (int) l.edge2.getY()); (int) l.edge2.getX(), (int) l.edge2.getY());
g2.fillOval((int) l.edge1.getX() - 2, (int) l.edge1.getY() - 2, g2.fillOval((int) l.edge1.getX() - 2, (int) l.edge1.getY() - 2,
4, 4); 4, 4);
g2.fillOval((int) l.edge2.getX() - 2, (int) l.edge2.getY() - 2, g2.fillOval((int) l.edge2.getX() - 2, (int) l.edge2.getY() - 2,
4, 4); 4, 4);
g2.setColor(new Color(238, 232, 170, 100)); g2.setColor(new Color(238, 232, 170, 100));
g2.fillOval((int) l.newPosition.getX() - 2, g2.fillOval((int) l.newPosition.getX() - 2,
(int) l.newPosition.getY() - 2, 4, 4); (int) l.newPosition.getY() - 2, 4, 4);
g2.setColor(new Color(238, 232, 170, 100)); g2.setColor(new Color(238, 232, 170, 100));
g2.drawLine((int) l.oldPosition.getX(), g2.drawLine((int) l.oldPosition.getX(),
(int) l.oldPosition.getY(), (int) l.newPosition.getX(), (int) l.oldPosition.getY(), (int) l.newPosition.getX(),
(int) l.newPosition.getY()); (int) l.newPosition.getY());
} }
} }
} }
} }
/* /*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package de.tud.kom.p2psim.impl.util.geo.maps; package de.tud.kom.p2psim.impl.util.geo.maps;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.PriorityQueue; import java.util.PriorityQueue;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
import org.jgrapht.alg.ConnectivityInspector; import org.jgrapht.alg.ConnectivityInspector;
import org.jgrapht.alg.DijkstraShortestPath; import org.jgrapht.alg.DijkstraShortestPath;
import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import de.tud.kom.p2psim.api.scenario.ConfigurationException; import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.obstacles.Obstacle; import de.tud.kom.p2psim.api.topology.obstacles.Obstacle;
import de.tud.kom.p2psim.api.util.geo.maps.Map; import de.tud.kom.p2psim.api.util.geo.maps.Map;
import de.tud.kom.p2psim.api.util.geo.maps.Way; import de.tud.kom.p2psim.api.util.geo.maps.Way;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.obstacles.PolygonObstacle; import de.tud.kom.p2psim.impl.topology.obstacles.PolygonObstacle;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.DefaultWeightedEdgeRetrievableGraph; import de.tud.kom.p2psim.impl.topology.waypoints.graph.DefaultWeightedEdgeRetrievableGraph;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Path; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Path;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.PathEdgeFactory; import de.tud.kom.p2psim.impl.topology.waypoints.graph.PathEdgeFactory;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint;
import de.tud.kom.p2psim.impl.util.Tuple; import de.tud.kom.p2psim.impl.util.Tuple;
import de.tud.kom.p2psim.impl.util.geo.maps.MapChangeListener.MapEvent; import de.tud.kom.p2psim.impl.util.geo.maps.MapChangeListener.MapEvent;
public abstract class AbstractMap implements Map { public abstract class AbstractMap implements Map {
private List<Obstacle> obstacles = Lists.newLinkedList(); private List<Obstacle> obstacles = Lists.newLinkedList();
private List<Path> paths = Lists.newLinkedList(); private List<Path> paths = Lists.newLinkedList();
protected DefaultWeightedEdgeRetrievableGraph<Waypoint, Path> graph = new DefaultWeightedEdgeRetrievableGraph<Waypoint, Path>( protected DefaultWeightedEdgeRetrievableGraph<Waypoint, Path> graph = new DefaultWeightedEdgeRetrievableGraph<Waypoint, Path>(
new PathEdgeFactory()); new PathEdgeFactory());
private Multimap<Class, Waypoint> typeWaypointMap = ArrayListMultimap.create(); private Multimap<Class, Waypoint> typeWaypointMap = ArrayListMultimap.create();
protected PositionVector minPosition = new PositionVector(2); protected PositionVector minPosition = new PositionVector(2);
protected PositionVector maxPosition = new PositionVector(2); protected PositionVector maxPosition = new PositionVector(2);
protected List<Way> ways = Lists.newLinkedList(); protected List<Way> ways = Lists.newLinkedList();
protected boolean[] swapped = new boolean[2]; protected boolean[] swapped = new boolean[2];
protected String filename = null; protected String filename = null;
private boolean isLoaded = false; private boolean isLoaded = false;
private String name = ""; private String name = "";
private List<MapChangeListener> mapListeners = Lists.newLinkedList(); private List<MapChangeListener> mapListeners = Lists.newLinkedList();
// TEMP // TEMP
protected PositionVector ppm; protected PositionVector ppm;
public void loadMap() { public void loadMap() {
if (filename == null) { if (filename == null) {
throw new ConfigurationException( throw new ConfigurationException(
"Unable to load map. Missing a filename, please make sure the configuration contains a file attribute."); "Unable to load map. Missing a filename, please make sure the configuration contains a file attribute.");
} }
doLoadMap(); doLoadMap();
buildGraph(); buildGraph();
//forcefullyConnectGraphs(); //forcefullyConnectGraphs();
removeNotConnectedGraphs(); removeNotConnectedGraphs();
isLoaded = true; isLoaded = true;
} }
protected abstract void doLoadMap(); protected abstract void doLoadMap();
protected String getFilename() { protected String getFilename() {
return filename; return filename;
} }
public void setFile(String filename) { public void setFile(String filename) {
this.filename = filename; this.filename = filename;
} }
protected void buildGraph() { protected void buildGraph() {
graph = new DefaultWeightedEdgeRetrievableGraph<Waypoint, Path>( graph = new DefaultWeightedEdgeRetrievableGraph<Waypoint, Path>(
new PathEdgeFactory()); new PathEdgeFactory());
for (Path path : paths) { for (Path path : paths) {
graph.addVertex(path.getSource()); graph.addVertex(path.getSource());
graph.addVertex(path.getTarget()); graph.addVertex(path.getTarget());
typeWaypointMap.put(path.getSource().getClass(), path.getSource()); typeWaypointMap.put(path.getSource().getClass(), path.getSource());
typeWaypointMap.put(path.getTarget().getClass(), path.getTarget()); typeWaypointMap.put(path.getTarget().getClass(), path.getTarget());
graph.addEdge(path.getSource(), path.getTarget(), path); graph.addEdge(path.getSource(), path.getTarget(), path);
} }
} }
public void addObstacle(Obstacle obstacle) { public void addObstacle(Obstacle obstacle) {
obstacles.add(obstacle); obstacles.add(obstacle);
raiseMapChanged(new MapChangeListener.ObstacleEvent(obstacle)); raiseMapChanged(new MapChangeListener.ObstacleEvent(obstacle));
} }
public void addPath(Path path) { public void addPath(Path path) {
paths.add(path); paths.add(path);
raiseMapChanged(new MapChangeListener.PathEvent(path)); raiseMapChanged(new MapChangeListener.PathEvent(path));
} }
public List<Path> getPaths() { public List<Path> getPaths() {
return paths; return paths;
} }
public void clearPaths() { public void clearPaths() {
paths.clear(); paths.clear();
} }
/** /**
* Scales the world based on the given vector: coordinate * (world / * Scales the world based on the given vector: coordinate * (world /
* dimensions) * dimensions)
* *
* @param world * @param world
*/ */
public void mapToWorld(PositionVector world) { public void mapToWorld(PositionVector world) {
PositionVector pixelPerMeter = world.clone(); PositionVector pixelPerMeter = world.clone();
pixelPerMeter.divide(getDimensions()); pixelPerMeter.divide(getDimensions());
this.ppm = pixelPerMeter; this.ppm = pixelPerMeter;
mapWaypoints(pixelPerMeter); mapWaypoints(pixelPerMeter);
mapObstacles(pixelPerMeter); mapObstacles(pixelPerMeter);
raiseMapChanged(new MapChangeListener.MapToWorldEvent(world)); raiseMapChanged(new MapChangeListener.MapToWorldEvent(world));
} }
private void mapObstacles(PositionVector pixelPerMeter) { private void mapObstacles(PositionVector pixelPerMeter) {
for (Obstacle o : obstacles) { for (Obstacle o : obstacles) {
PolygonObstacle p = (PolygonObstacle) o; PolygonObstacle p = (PolygonObstacle) o;
List<PositionVector> vertices = p.getVertices(); List<PositionVector> vertices = p.getVertices();
List<PositionVector> newVertices = Lists.newArrayList(); List<PositionVector> newVertices = Lists.newArrayList();
for (PositionVector v : vertices) { for (PositionVector v : vertices) {
newVertices.add(toPixelCoords(v, pixelPerMeter)); newVertices.add(toPixelCoords(v, pixelPerMeter));
} }
p.rebuildPolygon(newVertices); p.rebuildPolygon(newVertices);
} }
} }
private void mapWaypoints(PositionVector pixelPerMeter) { private void mapWaypoints(PositionVector pixelPerMeter) {
for (Waypoint w : graph.vertexSet()) { for (Waypoint w : graph.vertexSet()) {
w.setPosition(toPixelCoords(w.getPosition(), pixelPerMeter)); w.setPosition(toPixelCoords(w.getPosition(), pixelPerMeter));
} }
} }
protected PositionVector toPixelCoords(PositionVector position, PositionVector pixelPerMeter) { protected PositionVector toPixelCoords(PositionVector position, PositionVector pixelPerMeter) {
PositionVector clonedPosition = position.clone(); PositionVector clonedPosition = position.clone();
PositionVector relativePosition = clonedPosition.minus(getMinPosition()); PositionVector relativePosition = clonedPosition.minus(getMinPosition());
relativePosition.multiply(pixelPerMeter); relativePosition.multiply(pixelPerMeter);
return relativePosition; return relativePosition;
} }
public List<Obstacle> getObstacles() { public List<Obstacle> getObstacles() {
return obstacles; return obstacles;
} }
public PositionVector pos(double x, double y) { public PositionVector pos(double x, double y) {
return new PositionVector(x, y); return new PositionVector(x, y);
} }
protected void createPath(Waypoint wp1, Waypoint wp2) { protected void createPath(Waypoint wp1, Waypoint wp2) {
Path path = new Path(wp1, wp2); Path path = new Path(wp1, wp2);
addPath(path); addPath(path);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public DefaultWeightedEdgeRetrievableGraph getGraph() { public DefaultWeightedEdgeRetrievableGraph getGraph() {
return graph; return graph;
} }
@Override @Override
public PositionVector getMinPosition() { public PositionVector getMinPosition() {
return cut(minPosition); return cut(minPosition);
} }
@Override @Override
public PositionVector getMaxPosition() { public PositionVector getMaxPosition() {
return cut(maxPosition); return cut(maxPosition);
} }
public void setMinPosition(PositionVector minPosition) { public void setMinPosition(PositionVector minPosition) {
this.minPosition = minPosition; this.minPosition = minPosition;
} }
public void setMaxPosition(PositionVector maxPosition) { public void setMaxPosition(PositionVector maxPosition) {
this.maxPosition = maxPosition; this.maxPosition = maxPosition;
} }
public PositionVector getDimensions() { public PositionVector getDimensions() {
return getMaxPosition().minus(getMinPosition()); return getMaxPosition().minus(getMinPosition());
} }
public List<Way> getWays() { public List<Way> getWays() {
return ways; return ways;
} }
public void swapWorld(Axis axis, double max) { public void swapWorld(Axis axis, double max) {
for (Waypoint w : graph.vertexSet()) { for (Waypoint w : graph.vertexSet()) {
w.getPosition().setEntry(axis.ordinal(), w.getPosition().setEntry(axis.ordinal(),
max - w.getPosition().getEntry(axis.ordinal())); max - w.getPosition().getEntry(axis.ordinal()));
} }
for (Obstacle o : obstacles) { for (Obstacle o : obstacles) {
PolygonObstacle p = (PolygonObstacle) o; PolygonObstacle p = (PolygonObstacle) o;
List<PositionVector> vertices = p.getVertices(); List<PositionVector> vertices = p.getVertices();
for (PositionVector v : vertices) { for (PositionVector v : vertices) {
v.setEntry(axis.ordinal(), max - v.getEntry(axis.ordinal())); v.setEntry(axis.ordinal(), max - v.getEntry(axis.ordinal()));
} }
p.rebuildPolygon(vertices); p.rebuildPolygon(vertices);
} }
swapped[axis.ordinal()] = !swapped[axis.ordinal()]; swapped[axis.ordinal()] = !swapped[axis.ordinal()];
raiseMapChanged(new MapChangeListener.SwapMapEvent(axis, max)); raiseMapChanged(new MapChangeListener.SwapMapEvent(axis, max));
} }
public enum Axis { public enum Axis {
X_AXIS, Y_AXIS X_AXIS, Y_AXIS
} }
public boolean isSwapped(Axis axis) { public boolean isSwapped(Axis axis) {
return swapped[axis.ordinal()]; return swapped[axis.ordinal()];
} }
public List<Path> getShortestPath(Waypoint start, Waypoint end) { public List<Path> getShortestPath(Waypoint start, Waypoint end) {
DijkstraShortestPath<Waypoint, Path> dijkstrashortestpath = new DijkstraShortestPath<Waypoint, Path>( DijkstraShortestPath<Waypoint, Path> dijkstrashortestpath = new DijkstraShortestPath<Waypoint, Path>(
graph, start, end); graph, start, end);
return dijkstrashortestpath.getPathEdgeList(); return dijkstrashortestpath.getPathEdgeList();
} }
public void addWaypoint(Waypoint wp) { public void addWaypoint(Waypoint wp) {
graph.addVertex(wp); graph.addVertex(wp);
typeWaypointMap.put(wp.getClass(), wp); typeWaypointMap.put(wp.getClass(), wp);
} }
public Collection<Waypoint> getWaypoints(Class type) { public Collection<Waypoint> getWaypoints(Class type) {
return typeWaypointMap.get(type); return typeWaypointMap.get(type);
} }
public boolean isLoaded() { public boolean isLoaded() {
return this.isLoaded; return this.isLoaded;
} }
@Override @Override
public String getName() { public String getName() {
return name; return name;
} }
@Override @Override
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
public void addMapChangeListener(MapChangeListener listener) { public void addMapChangeListener(MapChangeListener listener) {
mapListeners .add(listener); mapListeners .add(listener);
} }
public void removeMapChangeListener(MapChangeListener listener) { public void removeMapChangeListener(MapChangeListener listener) {
mapListeners.remove(listener); mapListeners.remove(listener);
} }
private void raiseMapChanged(MapEvent event) { private void raiseMapChanged(MapEvent event) {
for (MapChangeListener l : mapListeners) { for (MapChangeListener l : mapListeners) {
l.mapChanged(event); l.mapChanged(event);
} }
} }
/** /**
* Calculates all connected sets in the graph and removes * Calculates all connected sets in the graph and removes
* all waypoints that aren't part of the largest connected set. * all waypoints that aren't part of the largest connected set.
*/ */
private void removeNotConnectedGraphs() { private void removeNotConnectedGraphs() {
Queue<List<Waypoint>> queue = getConnectedComponents(); Queue<List<Waypoint>> queue = getConnectedComponents();
if (queue.size() <= 1) if (queue.size() <= 1)
return; return;
// Remove the connected set with the highest number of // Remove the connected set with the highest number of
// waypoints so it won't be touched // waypoints so it won't be touched
queue.poll(); queue.poll();
List<Waypoint> waypoints = queue.poll(); List<Waypoint> waypoints = queue.poll();
while (waypoints != null) { while (waypoints != null) {
//removeWaypoints(waypoints, WeakWaypoint.class); //removeWaypoints(waypoints, WeakWaypoint.class);
for (Waypoint w : waypoints) { for (Waypoint w : waypoints) {
Set<Path> edges = Sets.newHashSet(graph.edgesOf(w)); Set<Path> edges = Sets.newHashSet(graph.edgesOf(w));
for (Path p : edges) { for (Path p : edges) {
graph.removeEdge(p); graph.removeEdge(p);
} }
graph.removeVertex(w); graph.removeVertex(w);
} }
waypoints = queue.poll(); waypoints = queue.poll();
} }
} }
private void forcefullyConnectGraphs() { private void forcefullyConnectGraphs() {
Set<Waypoint> waypoints = graph.vertexSet(); Set<Waypoint> waypoints = graph.vertexSet();
Queue<List<Waypoint>> queue = getConnectedComponents(); Queue<List<Waypoint>> queue = getConnectedComponents();
if (queue.size() <= 1) if (queue.size() <= 1)
return; return;
queue.poll(); queue.poll();
List<Waypoint> connectedSet = queue.poll(); List<Waypoint> connectedSet = queue.poll();
while (connectedSet != null) { while (connectedSet != null) {
ArrayList<Tuple<Waypoint, Waypoint>> shortestDistances = new ArrayList<Tuple<Waypoint, Waypoint>>(); ArrayList<Tuple<Waypoint, Waypoint>> shortestDistances = new ArrayList<Tuple<Waypoint, Waypoint>>();
for (Waypoint w : connectedSet) { for (Waypoint w : connectedSet) {
Waypoint sd = findClosestWaypoint(w, waypoints); Waypoint sd = findClosestWaypoint(w, waypoints);
shortestDistances.add(new Tuple<Waypoint, Waypoint>(w, sd)); shortestDistances.add(new Tuple<Waypoint, Waypoint>(w, sd));
} }
Tuple<Waypoint, Waypoint> shortestDistancePair = findClosestTuple(shortestDistances); Tuple<Waypoint, Waypoint> shortestDistancePair = findClosestTuple(shortestDistances);
try { try {
createPath(shortestDistancePair.getA(), shortestDistancePair.getB()); createPath(shortestDistancePair.getA(), shortestDistancePair.getB());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
//removeWaypoint(shortestDistancePair.getA()); //removeWaypoint(shortestDistancePair.getA());
Set<Path> edges = graph.outgoingEdgesOf(shortestDistancePair.getA()); Set<Path> edges = graph.outgoingEdgesOf(shortestDistancePair.getA());
for (Path p : edges) { for (Path p : edges) {
graph.removeEdge(p); graph.removeEdge(p);
} }
graph.removeVertex(shortestDistancePair.getA()); graph.removeVertex(shortestDistancePair.getA());
} }
connectedSet = queue.poll(); connectedSet = queue.poll();
} }
} }
/** /**
* Searches for the waypoint in the set that is the closest * Searches for the waypoint in the set that is the closest
* to the target waypoint. * to the target waypoint.
* *
* @param target * @param target
* @param waypoints * @param waypoints
* @return * @return
*/ */
private Waypoint findClosestWaypoint(Waypoint target, Collection<Waypoint> waypoints) { private Waypoint findClosestWaypoint(Waypoint target, Collection<Waypoint> waypoints) {
double d = -1; double d = -1;
Waypoint wp = null; Waypoint wp = null;
for (Waypoint w : waypoints) { for (Waypoint w : waypoints) {
double ld = target.getPosition().getDistance(w.getPosition()); double ld = target.getPosition().distanceTo(w.getPosition());
if (ld < d || d == -1) { if (ld < d || d == -1) {
d = ld; d = ld;
wp = w; wp = w;
} }
} }
return wp; return wp;
} }
/** /**
* Searches for the tuple whos two waypoints are the closest to each other. * Searches for the tuple whos two waypoints are the closest to each other.
* *
* @param shortestDistances * @param shortestDistances
* @return * @return
*/ */
private Tuple<Waypoint, Waypoint> findClosestTuple(ArrayList<Tuple<Waypoint, Waypoint>> shortestDistances) { private Tuple<Waypoint, Waypoint> findClosestTuple(ArrayList<Tuple<Waypoint, Waypoint>> shortestDistances) {
Tuple<Waypoint, Waypoint> shortestDistance = null; Tuple<Waypoint, Waypoint> shortestDistance = null;
double d = -1; double d = -1;
for (Tuple<Waypoint, Waypoint> wpT : shortestDistances) { for (Tuple<Waypoint, Waypoint> wpT : shortestDistances) {
double ld = wpT.getA().getPosition().getDistance(wpT.getB().getPosition()); double ld = wpT.getA().getPosition()
.distanceTo(wpT.getB().getPosition());
if (ld < d || d == -1) {
d = ld; if (ld < d || d == -1) {
shortestDistance = wpT; d = ld;
} shortestDistance = wpT;
} }
}
return shortestDistance;
} return shortestDistance;
}
private Queue<List<Waypoint>> getConnectedComponents() {
ConnectivityInspector ci = new ConnectivityInspector<Waypoint, Path>(getGraph()); private Queue<List<Waypoint>> getConnectedComponents() {
ConnectivityInspector ci = new ConnectivityInspector<Waypoint, Path>(getGraph());
@SuppressWarnings("unchecked")
List<Set<Waypoint>> connectedSets = ci.connectedSets(); @SuppressWarnings("unchecked")
List<Set<Waypoint>> connectedSets = ci.connectedSets();
PriorityQueue<List<Waypoint>> queue = new PriorityQueue<List<Waypoint>>(1, new Comparator<List<Waypoint>>() {
@Override PriorityQueue<List<Waypoint>> queue = new PriorityQueue<List<Waypoint>>(1, new Comparator<List<Waypoint>>() {
public int compare(List<Waypoint> o1, List<Waypoint> o2) { @Override
return o2.size() - o1.size(); public int compare(List<Waypoint> o1, List<Waypoint> o2) {
} return o2.size() - o1.size();
}); }
});
for (Set<Waypoint> waypointSet : connectedSets) {
queue.add(new ArrayList<Waypoint>(waypointSet)); for (Set<Waypoint> waypointSet : connectedSets) {
} queue.add(new ArrayList<Waypoint>(waypointSet));
}
return queue;
} return queue;
}
private PositionVector cut(PositionVector v1) {
int x = (int) v1.getX(); private PositionVector cut(PositionVector v1) {
int y = (int) v1.getY(); int x = (int) v1.getX();
int y = (int) v1.getY();
PositionVector v2 = new PositionVector(x, y);
PositionVector v2 = new PositionVector(x, y);
return v2;
} return v2;
} }
}
...@@ -4,7 +4,6 @@ import java.util.Map; ...@@ -4,7 +4,6 @@ import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import de.tud.kom.p2psim.api.common.Position;
import de.tud.kom.p2psim.impl.network.modular.common.GeoToolkit; import de.tud.kom.p2psim.impl.network.modular.common.GeoToolkit;
import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.common.Transmitable; import de.tudarmstadt.maki.simonstrator.api.common.Transmitable;
...@@ -17,7 +16,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; ...@@ -17,7 +16,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
* *
* @author Andreas Hemel * @author Andreas Hemel
*/ */
public class GeoSpherePosition implements Transmitable, Position { public class GeoSpherePosition implements Transmitable, Location {
/** Latitude in radians */ /** Latitude in radians */
private final double latitude; private final double latitude;
...@@ -131,7 +130,7 @@ public class GeoSpherePosition implements Transmitable, Position { ...@@ -131,7 +130,7 @@ public class GeoSpherePosition implements Transmitable, Position {
* @return The distance in meters. * @return The distance in meters.
*/ */
@Override @Override
public double getDistance(Position destination) { public double distanceTo(Location destination) {
GeoSpherePosition dest = (GeoSpherePosition) destination; GeoSpherePosition dest = (GeoSpherePosition) destination;
if (enableDistanceCache) { if (enableDistanceCache) {
Double cached = checkDistanceCache(this, dest); Double cached = checkDistanceCache(this, dest);
...@@ -163,8 +162,8 @@ public class GeoSpherePosition implements Transmitable, Position { ...@@ -163,8 +162,8 @@ public class GeoSpherePosition implements Transmitable, Position {
} }
@Override @Override
public double getAngle(Position target) { public float bearingTo(Location target) {
return -getBearing(target) + 180; return (float) (-getBearing(target) + 180);
} }
/** Calculate the initial bearing to target on a great circle in degrees. /** Calculate the initial bearing to target on a great circle in degrees.
...@@ -177,7 +176,7 @@ public class GeoSpherePosition implements Transmitable, Position { ...@@ -177,7 +176,7 @@ public class GeoSpherePosition implements Transmitable, Position {
* *
* @return The initial bearing in degrees. * @return The initial bearing in degrees.
*/ */
public double getBearing(Position target) { public double getBearing(Location target) {
return Math.toDegrees(getBearingRad(target)); return Math.toDegrees(getBearingRad(target));
} }
...@@ -188,7 +187,7 @@ public class GeoSpherePosition implements Transmitable, Position { ...@@ -188,7 +187,7 @@ public class GeoSpherePosition implements Transmitable, Position {
* *
* @return The initial bearing in radians. * @return The initial bearing in radians.
*/ */
public double getBearingRad(Position destination) { public double getBearingRad(Location destination) {
GeoSpherePosition dest = (GeoSpherePosition) destination; GeoSpherePosition dest = (GeoSpherePosition) destination;
if (enableBearingCache) { if (enableBearingCache) {
Double cached = checkBearingCache(this, dest); Double cached = checkBearingCache(this, dest);
...@@ -228,11 +227,6 @@ public class GeoSpherePosition implements Transmitable, Position { ...@@ -228,11 +227,6 @@ public class GeoSpherePosition implements Transmitable, Position {
return getDestinationRad(Math.toRadians(bearing), distance); return getDestinationRad(Math.toRadians(bearing), distance);
} }
@Override
public GeoSpherePosition getTarget(double distance, double angle) {
return getDestinationRad(angle, distance);
}
/** Calculate the destination position given a bearing and a distance. /** Calculate the destination position given a bearing and a distance.
* *
* The formulae used here assume a spherical Earth, so this calculation has * The formulae used here assume a spherical Earth, so this calculation has
...@@ -448,14 +442,4 @@ public class GeoSpherePosition implements Transmitable, Position { ...@@ -448,14 +442,4 @@ public class GeoSpherePosition implements Transmitable, Position {
public long getAgeOfLocation() { public long getAgeOfLocation() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public double distanceTo(Location dest) {
return getDistance((Position) dest);
}
@Override
public float bearingTo(Location dest) {
return (float) getBearing((Position) dest);
}
} }
/* /*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
* *
* This file is part of PeerfactSim.KOM. * This file is part of PeerfactSim.KOM.
* *
* PeerfactSim.KOM is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* any later version. * any later version.
* *
* PeerfactSim.KOM is distributed in the hope that it will be useful, * PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>. * along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
package de.tud.kom.p2psim.impl.util.structures; package de.tud.kom.p2psim.impl.util.structures;
import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint;
public class WaypointKdTree extends KdTree<Waypoint> { public class WaypointKdTree extends KdTree<Waypoint> {
public WaypointKdTree(int dimensions) { public WaypointKdTree(int dimensions) {
super(dimensions, null); super(dimensions, null);
} }
@Override @Override
protected double pointDist(double[] p1, double[] p2) { protected double pointDist(double[] p1, double[] p2) {
return new PositionVector(p1).getDistance(new PositionVector(p2)); return new PositionVector(p1).distanceTo(new PositionVector(p2));
} }
@Override @Override
protected double pointRegionDist(double[] point, double[] min, double[] max) { protected double pointRegionDist(double[] point, double[] min, double[] max) {
// FIXME: Implement (if required) // FIXME: Implement (if required)
return 0; return 0;
} }
} }
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