package aimax.osm.routing; import java.util.ArrayList; import java.util.List; import aima.core.agent.Action; import aima.core.search.framework.GraphSearch; import aima.core.search.framework.HeuristicFunction; import aima.core.search.framework.Problem; import aima.core.search.framework.Search; import aima.core.search.informed.AStarSearch; import aima.core.util.CancelableThread; import aimax.osm.data.OsmMap; import aimax.osm.data.MapWayAttFilter; import aimax.osm.data.MapWayFilter; import aimax.osm.data.Position; import aimax.osm.data.entities.MapNode; /** * Implements a search engine for shortest path calculations. * * @author Ruediger Lunde */ public class RouteCalculator { /** Returns the names of all supported way selection options. */ public String[] getWaySelectionOptions() { 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>. The * three factory methods can be used to override aspects of the default * behavior in subclasses if needed. * * @param locs * 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 waySelection * Number, indicating which kinds of ways are relevant. */ public List<Position> calculateRoute(List<MapNode> locs, OsmMap map, int waySelection) { List<Position> result = new ArrayList<Position>(); try { MapWayFilter wayFilter = createMapWayFilter(map, waySelection); boolean ignoreOneways = (waySelection == 0); MapNode fromNode = map.getNearestWayNode(new Position(locs .get(0)), wayFilter); result.add(new Position(fromNode.getLat(), fromNode.getLon())); for (int i = 1; i < locs.size() && !CancelableThread.currIsCanceled(); i++) { MapNode toNode = map.getNearestWayNode(new Position(locs .get(i)), wayFilter); HeuristicFunction hf = createHeuristicFunction(toNode, waySelection); Problem problem = createProblem(fromNode, toNode, map, wayFilter, ignoreOneways, waySelection); Search search = new AStarSearch(new GraphSearch(), hf); List<Action> actions = search.search(problem); if (actions.isEmpty()) break; for (Object action : actions) { if (action instanceof OsmMoveAction) { OsmMoveAction a = (OsmMoveAction) action; for (MapNode node : a.getNodes()) if (!node.equals(a.getFrom())) result.add(new Position(node.getLat(), node .getLon())); } } fromNode = toNode; } } catch (Exception e) { e.printStackTrace(); } return result; } /** Factory method, responsible for way filter creation. */ protected MapWayFilter createMapWayFilter(OsmMap map, int waySelection) { if (waySelection == 1) return MapWayAttFilter.createCarWayFilter(); else if (waySelection == 2) return MapWayAttFilter.createBicycleWayFilter(); else return MapWayAttFilter.createAnyWayFilter(); } /** Factory method, responsible for heuristic function creation. */ protected HeuristicFunction createHeuristicFunction(MapNode toRNode, int waySelection) { return new OsmSldHeuristicFunction(toRNode); } /** Factory method, responsible for problem creation. */ protected Problem createProblem(MapNode fromNode, MapNode toNode, OsmMap map, MapWayFilter wayFilter, boolean ignoreOneways, int waySelection) { return new RouteFindingProblem(fromNode, toNode, wayFilter, ignoreOneways); } }