/* * 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.traverse.standard; import java.util.Iterator; import org.geotools.graph.structure.Graph; import org.geotools.graph.structure.Graphable; import org.geotools.graph.traverse.GraphTraversal; import org.geotools.graph.traverse.basic.SourceGraphIterator; import org.geotools.graph.util.FIFOQueue; import org.geotools.graph.util.Queue; /** * Iterates over the nodes of a graph in a <B>Breadth First Search</B> pattern * starting from a specified node. The following illustrates the iteration * order. <BR> * <BR> * <IMG src="doc-files/bfs.gif"/><BR> * <BR> * The iteration operates by maintaning a node queue of <B>active</B> nodes. * An <B>active</B> node is a node that will returned at a later stage of the i * teration. The node queue for a Breadth First iteration is implemented as a * <B>First In First Out</B> queue. * A node is placed in the the node queue if it has not been visited, and * it is adjacent to a a node that has been visited. The node queue intially * contains only the source node of the traversal. * * @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net * * * @source $URL$ */ public class BreadthFirstIterator extends SourceGraphIterator { /** Contains all nodes to be returned **/ private Queue m_active; /** * Sets the source of the traversal and places it in the node queue. The first * call to this method will result in the internal node queue being built. * Subsequent calls to the method clear the node queue and reset the iteration. * * @see SourceGraphIterator#setSource(Graphable) */ public void setSource(Graphable source) { super.setSource(source); //set source of traversal, creating queue if necessary if (m_active == null) m_active = buildQueue(getGraph()); else if (m_active.isEmpty()) m_active.clear(); m_active.enq(getSource()); } /** * Does nothing. * * @see org.geotools.graph.traverse.GraphIterator#init(Graph) */ public void init(Graph graph, GraphTraversal traversal) { //do nothing } /** * Returns the next node from the node queue that has not yet been visited. It * is possible for the node queue to contain duplicate entries. To prevent * the iteration returning the same node multiple times, the visited flag is * checked on nodes coming out of the queue. If the flag is set, the node * is ignored, not returned, and the next node in the queue is returned. This * is however tranparent to the caller. * * @see org.geotools.graph.traverse.GraphIterator#next() */ public Graphable next(GraphTraversal traversal) { while(!m_active.isEmpty()) { Graphable next = (Graphable)m_active.deq(); if (!traversal.isVisited(next)) return(next); } return(null); } /** * Looks for nodes adjacent to the current node to place into the node queue. * An adjacent node is only placed into the node queue if its visited flag * is unset. * * @see org.geotools.graph.traverse.GraphIterator#cont(Graphable) */ public void cont(Graphable current, GraphTraversal traversal) { for (Iterator itr = current.getRelated(); itr.hasNext();) { Graphable related = (Graphable)itr.next(); if (!traversal.isVisited(related)) { m_active.enq(related); } } } /** * Kills the current branch by not looking for any adjacent nodes to place * into the node queue. * * @see org.geotools.graph.traverse.GraphIterator#killBranch(Graphable) */ public void killBranch(Graphable current, GraphTraversal traversal) { //do not look for any adjacent nodes to place into the active queue } /** * Builds the node queue for the iteration. * * @param graph The graph being iterated over. * * @return A First In First Out queue. */ protected Queue buildQueue(Graph graph) { return(new FIFOQueue(graph.getNodes().size())); } /** * Returns the node queue. * * @return The node queue. */ protected Queue getQueue() { return(m_active); } }