/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.graph.path; import org.geotools.graph.structure.Graph; import org.geotools.graph.structure.Graphable; import org.geotools.graph.structure.Node; import org.geotools.graph.traverse.GraphTraversal; import org.geotools.graph.traverse.GraphWalker; import org.geotools.graph.traverse.basic.BasicGraphTraversal; import org.geotools.graph.traverse.standard.AStarIterator; import org.geotools.graph.traverse.standard.AStarIterator.AStarFunctions; /** * Calculates the shortest path between two nodes using the A Star algorithm * (for details see http://en.wikipedia.org/wiki/A_star) * @see AStarIterator * @author Germán E. Trouillet, Francisco G. Malbrán. Universidad Nacional de Córdoba (UNC) * * * @source $URL$ */ public class AStarShortestPathFinder implements GraphWalker { /** Graphs to calculate paths for **/ private Graph m_graph; /** Graph traversal used for the A Star iteration **/ private GraphTraversal m_traversal; /** Underling A Star iterator **/ private AStarIterator m_iterator; /** */ private Node m_target; /** * Constructs a new path finder * * @param graph Graph where we will perform the search. * @param source Node to calculate path from. * @param target Node to calculate path to. * @param weighter Associates weights with edges in the graph. */ public AStarShortestPathFinder ( Graph graph, Node source, Node target, AStarFunctions afuncs ) { m_graph = graph; m_target = target; m_iterator = new AStarIterator(source, afuncs); m_traversal = new BasicGraphTraversal(graph,this,m_iterator); } /** * Performs the graph traversal and calculates the shortest path from * the source node to destiny node in the graph. */ public void calculate() { m_traversal.init(); m_traversal.traverse(); } /** * * @see GraphWalker#visit(Graphable, GraphTraversal) */ public int visit(Graphable element, GraphTraversal traversal) { if (element.equals(m_target)) { return(GraphTraversal.STOP); } else { return(GraphTraversal.CONTINUE); } } /** * Returns a path <B>from</B> the target <B>to</B> the source. If the desired path is * the opposite (from the source to the target), the <i>reverse</i> or the <i>riterator</i> * methods from the <b>Path<b> class can be used. * * @see Path#riterator() * @see Path#reverse() * * @return A path from the target to the source. * @throws WrongPathException */ public Path getPath() throws WrongPathException { Path path = new Path(); path.add(m_target); Node parent = m_iterator.getParent(m_target); while ( parent != null ) { path.add(parent); parent = m_iterator.getParent(parent); } if (!path.getLast().equals(m_iterator.getSource())) { throw new WrongPathException("getPath: The path obtained doesn't begin correctly"); } return(path); } /** * Does nothing. * * @see GraphWalker#finish() */ public void finish() {} } class WrongPathException extends Exception{ String message; public WrongPathException(String msj){ message = msj; } public String getMessage(){ return message; } }