/* * 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 . * */ package de.tud.kom.p2psim.impl.topology.movement.local; import java.util.ArrayList; import java.util.List; import java.util.WeakHashMap; import de.tud.kom.p2psim.api.topology.movement.MovementSupported; import de.tud.kom.p2psim.impl.topology.PositionVector; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Path; import de.tud.kom.p2psim.impl.topology.waypoints.graph.Waypoint; import de.tud.kom.p2psim.impl.topology.waypoints.graph.WeakWaypoint; import de.tud.kom.p2psim.impl.util.Either; import de.tud.kom.p2psim.impl.util.Left; import de.tud.kom.p2psim.impl.util.Right; /** * This movement strategy uses the getShortestPath method implemented by the * waypoint model and moves along path given by this method. * * @author Fabio Zöllner * @version 1.0, 10.04.2012 */ public class ShortestPathWaypointMovement extends AbstractLocalMovementStrategy { // Contains the shortest path and the currently used path protected final WeakHashMap currentPath = new WeakHashMap(); protected final WeakHashMap> dstPaths = new WeakHashMap>(); // Used to check if the destination was altered by the waypoint movement // model protected WeakHashMap currentDestination = new WeakHashMap(); /** * Calculates the next position of the given movement supported component by * using the shortest path to the waypoint closest to the destination. */ @Override public Either nextPosition(MovementSupported comp, PositionVector destination) { if (currentDestination.get(comp) == null || !currentDestination.get(comp).equals(destination)) { currentDestination.put(comp, destination); calculateNextMovementPath(comp, destination); // If the list of the shortest path is empty the destination is the // same // as the current position. Thus tell the abstract waypoint model // that we // reached the destination. if (dstPaths.get(comp).size() == 0) { return new Right(true); } } int currentPathIdx = currentPath.get(comp); Waypoint currentWaypoint = dstPaths.get(comp).get(currentPathIdx); double speed = getMovementSpeed(comp); PositionVector newPosition = comp.getRealPosition().moveStep( currentWaypoint.getPosition(), speed); if (destinationWaypointReached(currentWaypoint, newPosition, speed)) { // We reached the next waypoint on the path to the destination // move to the next waypoint currentPath.put(comp, ++currentPathIdx); // The destination waypoint has been reached, tell the abstract // waypoint model if (dstPaths.get(comp).size() <= currentPathIdx) { currentPath.put(comp, --currentPathIdx); return new Right(true); } } return new Left(newPosition); } /** * Finds the closest waypoints to the current position of the movement * supported component as well as the final destination and searches for a * path between the two waypoints using the underlying network of * WeakWaypoints. * * @param comp * @param finalDestination */ protected void calculateNextMovementPath(MovementSupported comp, PositionVector finalDestination) { // Required for shortest path calculation Waypoint closestWaypointToCurrentPosition = waypointModel .getClosestWaypoint(comp.getRealPosition(), WeakWaypoint.class); Waypoint closestWaypointToDestination = waypointModel .getClosestWaypoint(finalDestination, WeakWaypoint.class); List shortestPath = waypointModel.getShortestPath( closestWaypointToCurrentPosition, closestWaypointToDestination); List waypointList = buildWaypointList( closestWaypointToCurrentPosition, shortestPath); dstPaths.put(comp, waypointList); currentPath.put(comp, Integer.valueOf(0)); } /** * Build a list of waypoints that starts a the given starting waypoint based * on the given list of paths. * * @param start * @param shortestPath * @return */ protected List buildWaypointList(Waypoint start, List shortestPath) { List waypointList = new ArrayList(); Waypoint lastWaypoint = start; waypointList.add(start); for (Path p : shortestPath) { lastWaypoint = p.getOtherEnd(lastWaypoint); waypointList.add(lastWaypoint); } return waypointList; } /** * Checks if the current destination waypoint has been reached by testing * the distance between the current position an the current destination * waypoint for distance < speedLimit * 2. * * FIXME BR: why *2? * * @param currentWaypoint * @param newPosition * @return */ protected boolean destinationWaypointReached(Waypoint currentWaypoint, PositionVector newPosition, double speed) { double distance = newPosition.distanceTo(currentWaypoint.getPosition()); return (distance < speed * 2); } }