/*
* 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.geotools.graph.structure.GraphVisitor;
import org.geotools.graph.structure.Graphable;
import org.geotools.graph.structure.Node;
import org.geotools.graph.util.IndexedStack;
public class ExhaustivePathFinder {
public final static int CONTINUE_PATH = 0;
public final static int END_PATH_AND_CONTINUE = 1;
public final static int END_PATH_AND_STOP = 2;
public final static int KILL_PATH = 3;
private int m_maxitr;
private int m_maxplen;
public ExhaustivePathFinder() {
this(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
public ExhaustivePathFinder(int maxitr, int maxplen) {
m_maxitr = maxitr;
m_maxplen = maxplen;
}
public Path getPath(Node from, Node to) {
final Node dst = to;
GraphVisitor visitor = new GraphVisitor() {
public int visit(Graphable component) {
if (component.equals(dst)) return(END_PATH_AND_STOP);
return(CONTINUE_PATH);
}
};
List paths = getPaths(from, visitor);
if (paths.isEmpty()) return(null);
return((Path)paths.get(0));
}
public List getPaths(Node from, Node to) {
final Node dst = to;
GraphVisitor visitor = new GraphVisitor() {
public int visit(Graphable component) {
if (component.equals(dst)) return(END_PATH_AND_CONTINUE);
return(CONTINUE_PATH);
}
};
return(getPaths(from, visitor));
}
public List getPaths(Node from, GraphVisitor visitor) {
ArrayList paths = new ArrayList();
//create a map to maintain iterator state
HashMap node2related = new HashMap();
//create the stack and place start node on
IndexedStack stack = new IndexedStack();
stack.push(from);
int iterations = 0;
O: while(!stack.isEmpty() && (iterations++ < m_maxitr)) {
//peek the stack
Node top = (Node)stack.peek();
switch(visitor.visit(top)) {
case END_PATH_AND_CONTINUE:
paths.add(new Path(stack));
stack.pop();
continue;
case END_PATH_AND_STOP:
paths.add(new Path(stack));
break O;
case KILL_PATH:
stack.pop();
continue;
case CONTINUE_PATH:
}
Iterator related = null;
if ((related = (Iterator)node2related.get(top)) == null) {
related = top.getRelated();
node2related.put(top,related);
}
while(stack.size() < m_maxplen && related.hasNext()) {
Node adj = (Node)related.next();
if (stack.contains(adj)) continue;
//push adjacent onto stack, and reset iterator
stack.push(adj);
node2related.put(adj, adj.getRelated());
continue O;
}
//all adjacent have been processed or are in stack
stack.pop();
}
return(paths);
}
}