package aimax.osm.routing;
import java.util.ArrayList;
import java.util.List;
import aima.core.agent.Action;
import aima.core.search.framework.SearchForActions;
import aima.core.search.framework.evalfunc.HeuristicFunction;
import aima.core.search.framework.problem.Problem;
import aima.core.search.framework.qsearch.GraphSearch;
import aima.core.search.informed.AStarSearch;
import aima.core.util.CancelableThread;
import aimax.osm.data.MapWayAttFilter;
import aimax.osm.data.MapWayFilter;
import aimax.osm.data.OsmMap;
import aimax.osm.data.Position;
import aimax.osm.data.entities.MapNode;
/**
* Implements a search engine for shortest path calculations. Modified versions
* can be implemented quite easily by overriding the various factory methods.
*
* @author Ruediger Lunde
*/
public class RouteCalculator {
/** Returns the names of all supported way selection options. */
public String[] getTaskSelectionOptions() {
return new String[] { "Distance", "Distance (Car)", "Distance (Bike)" };
}
/**
* Template method, responsible for shortest path generation between two map
* nodes. It searches for way nodes in the vicinity of the given nodes which
* comply with the specified way selection, searches for a suitable paths,
* and adds the paths as tracks to the provided <code>map</code>. Various
* factory methods can be used to override aspects of the default behavior
* in subclasses if needed.
*
* @param markers
* Nodes, not necessarily way nodes. The first node is used as
* start, last node as finish, all others as via nodes.
* @param map
* The information source.
* @param taskSelection
* Number, indicating which kinds of ways are relevant.
*/
public List<Position> calculateRoute(List<MapNode> markers, OsmMap map,
int taskSelection) {
List<Position> result = new ArrayList<Position>();
try {
MapWayFilter wayFilter = createMapWayFilter(map, taskSelection);
boolean ignoreOneways = (taskSelection == 0);
List<MapNode[]> pNodeList = subdivideProblem(markers, map, wayFilter);
MapNode prevNode = null;
for (int i = 0; i < pNodeList.size()
&& !CancelableThread.currIsCanceled(); i++) {
Problem problem = createProblem(pNodeList.get(i), map, wayFilter,
ignoreOneways, taskSelection);
HeuristicFunction hf = createHeuristicFunction(pNodeList.get(i),
taskSelection);
SearchForActions search = createSearch(hf, taskSelection);
List<Action> actions = search.findActions(problem);
if (actions.isEmpty())
break;
for (Object action : actions) {
if (action instanceof OsmMoveAction) {
OsmMoveAction a = (OsmMoveAction) action;
for (MapNode node : a.getNodes()) {
if (prevNode != node) {
result.add(new Position(node.getLat(), node
.getLon()));
prevNode = node;
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/** Factory method, responsible for way filter creation. */
protected MapWayFilter createMapWayFilter(OsmMap map, int taskSelection) {
if (taskSelection == 1)
return MapWayAttFilter.createCarWayFilter();
else if (taskSelection == 2)
return MapWayAttFilter.createBicycleWayFilter();
else
return MapWayAttFilter.createAnyWayFilter();
}
/**
* Factory method, responsible for subdividing the overall problem which is
* specified by a list of marker nodes. It returns arrays of way nodes.
* The arrays will be used to define problems to be solved one after
* another. This implementation returns pairs of from and to way nodes.
*/
protected List<MapNode[]> subdivideProblem(List<MapNode> markers,
OsmMap map, MapWayFilter wayFilter) {
List<MapNode[]> result = new ArrayList<MapNode[]>();
MapNode fromNode = map.getNearestWayNode(new Position(markers.get(0)),
wayFilter);
for (int i = 1; i < markers.size(); i++) {
MapNode toNode = map.getNearestWayNode(
new Position(markers.get(i)), wayFilter);
result.add(new MapNode[] { fromNode, toNode });
fromNode = toNode;
}
return result;
}
/** Factory method, responsible for problem creation. */
protected Problem createProblem(MapNode[] pNodes, OsmMap map,
MapWayFilter wayFilter, boolean ignoreOneways, int taskSelection) {
return new RouteFindingProblem(pNodes[0], pNodes[1], wayFilter,
ignoreOneways);
}
/** Factory method, responsible for heuristic function creation. */
protected HeuristicFunction createHeuristicFunction(MapNode[] pNodes,
int taskSelection) {
return new OsmSldHeuristicFunction(pNodes[1]);
}
/** Factory method, responsible for search creation. */
protected SearchForActions createSearch(HeuristicFunction hf, int taskSelection) {
return new AStarSearch(new GraphSearch(), hf);
}
}