/*
* 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.structure.opt;
import java.util.ArrayList;
import java.util.Iterator;
import org.geotools.graph.structure.DirectedEdge;
import org.geotools.graph.structure.DirectedGraphable;
import org.geotools.graph.structure.DirectedNode;
import org.geotools.graph.structure.Edge;
import org.geotools.graph.structure.Graphable;
import org.geotools.graph.structure.Node;
/**
* Optimized implementation of DirectedEdge.
*
* @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
*
* @see DirectedEdge
* @source $URL$
*/
public class OptDirectedEdge extends OptGraphable implements DirectedEdge {
/** in node **/
private OptDirectedNode m_in;
/** out node **/
private OptDirectedNode m_out;
/**
* Constructs a new OptDirectedEdge.
*
* @param in Optimized in node.
* @param out Optimized out node.
*/
public OptDirectedEdge(OptDirectedNode in, OptDirectedNode out) {
m_in = in;
m_out = out;
}
/**
* @see DirectedEdge#getInNode()
*/
public DirectedNode getInNode() {
return(m_in);
}
/**
* @see DirectedEdge#getOutNode()
*/
public DirectedNode getOutNode() {
return(m_out);
}
/**
* @see Edge#getNodeA()
*/
public Node getNodeA() {
return(m_in);
}
/**
* @see Edge#getNodeB()
*/
public Node getNodeB() {
return(m_out);
}
/**
* @see Edge#getOtherNode(Node)
*/
public Node getOtherNode(Node node) {
return(node == m_in ? m_out : node == m_out ? m_in : null);
}
/**
* Unsupported Operation.
*
* @throws UnsupportedOperationException
*/
public void reverse() {
throw new UnsupportedOperationException(
getClass().getName() + "#reverse()"
);
}
/**
* @see Edge#compareNodes(Edge)
*/
public int compareNodes(Edge other) {
if (m_in.equals(other.getNodeA()) && m_out.equals(other.getNodeB()))
return(Edge.EQUAL_NODE_ORIENTATION);
if (m_in.equals(other.getNodeB()) && m_out.equals(other.getNodeA()))
return(Edge.OPPOSITE_NODE_ORIENTATION);
return(Edge.UNEQUAL_NODE_ORIENTATION);
}
/**
* @see Graphable#getRelated()
*/
public Iterator getRelated() {
ArrayList related = new ArrayList(
m_in.getDegree() + m_out.getDegree() - 2
);
Edge[] edges = m_in.getInEdgeArray();
for (int i = 0; i < edges.length; i++) {
related.add(edges[i]);
}
edges = m_in.getOutEdgeArray();
for (int i = 0; i < edges.length; i++) {
Edge e = edges[i];
if (!e.equals(this) && !(e.getNodeA().equals(e.getNodeB())))
related.add(edges[i]);
}
edges = m_out.getInEdgeArray();
for (int i = 0; i < edges.length; i++) {
Edge e = edges[i];
switch(compareNodes(e)) {
case Edge.EQUAL_NODE_ORIENTATION:
case Edge.OPPOSITE_NODE_ORIENTATION:
continue; //already added
case Edge.UNEQUAL_NODE_ORIENTATION:
related.add(e);
}
}
edges = m_out.getOutEdgeArray();
for (int i = 0; i < edges.length; i++) {
Edge e = edges[i];
switch(compareNodes(edges[i])) {
case Edge.EQUAL_NODE_ORIENTATION:
case Edge.OPPOSITE_NODE_ORIENTATION:
continue; //already added
case Edge.UNEQUAL_NODE_ORIENTATION:
if (!e.getNodeA().equals(e.getNodeB())) related.add(e);
}
}
return(related.iterator());
}
/**
* @see DirectedGraphable#getInRelated()
*/
public Iterator getInRelated() {
return(new RelatedIterator(RelatedIterator.IN));
}
/**
* @see DirectedGraphable#getOutRelated()
*/
public Iterator getOutRelated() {
return(new RelatedIterator(RelatedIterator.OUT));
}
/**
* Iterator used to iterate over adjacent edges.
*
* @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
*
*/
public class RelatedIterator implements Iterator {
/** in mode **/
public static final int IN = 0;
/** out mode **/
public static final int OUT = 1;
/** both mode **/
public static final int BOTH = 2;
/** iteration mode **/
private int m_mode;
/** iteration index **/
private int m_index;
/** number of edges to iterate over **/
private int m_n;
/**
* Constructs a new iterator.
*
* @param mode Iteration mode.
*/
public RelatedIterator(int mode) {
m_mode = mode;
m_index = 0;
switch(m_mode) {
case IN:
m_n = m_in.getInDegree();
break;
case OUT:
m_n = m_out.getOutDegree();
break;
default:
m_n = 0;
}
}
/**
* Unsupported Operation.
*
* @throws UnsupportedOperationException
*/
public void remove() {
throw new UnsupportedOperationException(
getClass().getName() + "#remove()"
);
}
/**
* Determines if there are any more related edges to return.
*
* @see Iterator#hasNext()
*/
public boolean hasNext() {
return(m_index < m_n);
}
/**
* Returns the next related edge.
*
* @see Iterator#next()
*/
public Object next() {
switch(m_mode) {
case IN: return(m_in.getInEdgeArray()[m_index++]);
case OUT: return(m_out.getOutEdgeArray()[m_index++]);
}
return(null);
}
}
}