/* * 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.traverse.GraphTraversal; import org.geotools.graph.traverse.GraphWalker; import org.geotools.graph.traverse.basic.BasicGraphTraversal; import org.geotools.graph.traverse.standard.DijkstraIterator; import org.geotools.graph.traverse.standard.DijkstraIterator.EdgeWeighter; import org.geotools.graph.traverse.standard.DijkstraIterator.NodeWeighter; /** * Calculates node paths in a graph using Dijkstra's Shortest Path Algorithm. * Dijsktras algorithm calculates a shortest path from a specefied node (the * source node of the underlying dijkstra iteration) to every other node in the * graph. * * @see DijsktraIterator * @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net * * @source $URL$ */ public class DijkstraShortestPathFinder implements GraphWalker { /** Graphs to calculate paths for **/ private Graph m_graph; /** Graph traversal used for the dijkstra iteration **/ private GraphTraversal m_traversal; /** Underling Dijkstra iterator **/ private DijkstraIterator m_iterator; /** * Constructs a new path finder. * * @param graph The graph to calculate paths for. * @param iterator The dijsktra iterator to used to calculate shortest paths. */ public DijkstraShortestPathFinder(Graph graph, DijkstraIterator iterator) { m_graph = graph; m_iterator = iterator; m_traversal = new BasicGraphTraversal(graph, this, iterator); } /** * Constructs a new path finder. * * @param graph Graph to calculate paths for. * @param source Node to calculate paths from. * @param weighter Associates weights with edges in the graph. */ public DijkstraShortestPathFinder( Graph graph, Graphable source, EdgeWeighter weighter ) { this(graph,source,weighter,null); } /** * Constructs a new path finder. * * @param graph Graph to calculate paths for. * @param source Node to calculate paths from. * @param weighter Associates weights with edges in the graph. * @param nweighter Associates weights with nodes in the graph. */ public DijkstraShortestPathFinder( Graph graph, Graphable source, EdgeWeighter weighter, NodeWeighter nweighter ) { m_graph = graph; m_iterator = new DijkstraIterator(weighter,nweighter); m_iterator.setSource(source); m_traversal = new BasicGraphTraversal(graph, this, m_iterator); } /** * Performs the graph traversal and calculates the shortest path from * the source node to every other node in the graph. */ public void calculate() { m_traversal.init(); m_traversal.traverse(); } /** * Returns a path <B>from</B> g <B>to</B> the source. If the desired path is * the opposite (from the source to g) can be used. * * @param g The start node of the path to be calculated. * * @see Path#riterator() * * @return A path from g to the source. */ public Path getPath(Graphable g) { Path p = new Path(); p.add(g); Graphable parent = g; while((parent = m_iterator.getParent(parent)) != null) p.add(parent); if (!p.getLast().equals(m_iterator.getSource())) return(null); return(p); } /** * Returns the cost associated with a node calculated during the graph * traversal. * * @param g The node whose cost is desired. * * @return The cost associated with the node. */ public double getCost(Graphable g) { return(m_iterator.getCost(g)); } public DijkstraIterator getIterator() { return(m_iterator); } public GraphTraversal getTraversal() { return(m_traversal); } /** * Does nothing except signal the traversal to continue. * * @see GraphWalker#visit(Graphable, GraphTraversal) */ public int visit(Graphable element, GraphTraversal traversal) { return(GraphTraversal.CONTINUE); } /** * Does nothing. * * @see GraphWalker#finish() */ public void finish() {} }