001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: * (C) 2002, Refractions Reserach Inc.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation;
010: * version 2.1 of the License.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: */
017: package org.geotools.graph.structure.opt;
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021:
022: import org.geotools.graph.structure.DirectedEdge;
023: import org.geotools.graph.structure.DirectedGraphable;
024: import org.geotools.graph.structure.DirectedNode;
025: import org.geotools.graph.structure.Edge;
026: import org.geotools.graph.structure.Graphable;
027: import org.geotools.graph.structure.Node;
028:
029: /**
030: * Optimized implementation of DirectedEdge.
031: *
032: * @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
033: *
034: * @see DirectedEdge
035: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/extension/graph/src/main/java/org/geotools/graph/structure/opt/OptDirectedEdge.java $
036: */
037: public class OptDirectedEdge extends OptGraphable implements
038: DirectedEdge {
039:
040: /** in node **/
041: private OptDirectedNode m_in;
042:
043: /** out node **/
044: private OptDirectedNode m_out;
045:
046: /**
047: * Constructs a new OptDirectedEdge.
048: *
049: * @param in Optimized in node.
050: * @param out Optimized out node.
051: */
052: public OptDirectedEdge(OptDirectedNode in, OptDirectedNode out) {
053: m_in = in;
054: m_out = out;
055: }
056:
057: /**
058: * @see DirectedEdge#getInNode()
059: */
060: public DirectedNode getInNode() {
061: return (m_in);
062: }
063:
064: /**
065: * @see DirectedEdge#getOutNode()
066: */
067: public DirectedNode getOutNode() {
068: return (m_out);
069: }
070:
071: /**
072: * @see Edge#getNodeA()
073: */
074: public Node getNodeA() {
075: return (m_in);
076: }
077:
078: /**
079: * @see Edge#getNodeB()
080: */
081: public Node getNodeB() {
082: return (m_out);
083: }
084:
085: /**
086: * @see Edge#getOtherNode(Node)
087: */
088: public Node getOtherNode(Node node) {
089: return (node == m_in ? m_out : node == m_out ? m_in : null);
090: }
091:
092: /**
093: * Unsupported Operation.
094: *
095: * @throws UnsupportedOperationException
096: */
097: public void reverse() {
098: throw new UnsupportedOperationException(getClass().getName()
099: + "#reverse()");
100: }
101:
102: /**
103: * @see Edge#compareNodes(Edge)
104: */
105: public int compareNodes(Edge other) {
106: if (m_in.equals(other.getNodeA())
107: && m_out.equals(other.getNodeB()))
108: return (Edge.EQUAL_NODE_ORIENTATION);
109:
110: if (m_in.equals(other.getNodeB())
111: && m_out.equals(other.getNodeA()))
112: return (Edge.OPPOSITE_NODE_ORIENTATION);
113:
114: return (Edge.UNEQUAL_NODE_ORIENTATION);
115: }
116:
117: /**
118: * @see Graphable#getRelated()
119: */
120: public Iterator getRelated() {
121: ArrayList related = new ArrayList(m_in.getDegree()
122: + m_out.getDegree() - 2);
123:
124: Edge[] edges = m_in.getInEdgeArray();
125: for (int i = 0; i < edges.length; i++) {
126: related.add(edges[i]);
127: }
128:
129: edges = m_in.getOutEdgeArray();
130: for (int i = 0; i < edges.length; i++) {
131: Edge e = edges[i];
132: if (!e.equals(this ) && !(e.getNodeA().equals(e.getNodeB())))
133: related.add(edges[i]);
134: }
135:
136: edges = m_out.getInEdgeArray();
137: for (int i = 0; i < edges.length; i++) {
138: Edge e = edges[i];
139:
140: switch (compareNodes(e)) {
141: case Edge.EQUAL_NODE_ORIENTATION:
142: case Edge.OPPOSITE_NODE_ORIENTATION:
143: continue; //already added
144:
145: case Edge.UNEQUAL_NODE_ORIENTATION:
146: related.add(e);
147: }
148: }
149:
150: edges = m_out.getOutEdgeArray();
151: for (int i = 0; i < edges.length; i++) {
152: Edge e = edges[i];
153:
154: switch (compareNodes(edges[i])) {
155: case Edge.EQUAL_NODE_ORIENTATION:
156: case Edge.OPPOSITE_NODE_ORIENTATION:
157: continue; //already added
158:
159: case Edge.UNEQUAL_NODE_ORIENTATION:
160: if (!e.getNodeA().equals(e.getNodeB()))
161: related.add(e);
162: }
163: }
164:
165: return (related.iterator());
166: }
167:
168: /**
169: * @see DirectedGraphable#getInRelated()
170: */
171: public Iterator getInRelated() {
172: return (new RelatedIterator(RelatedIterator.IN));
173: }
174:
175: /**
176: * @see DirectedGraphable#getOutRelated()
177: */
178: public Iterator getOutRelated() {
179: return (new RelatedIterator(RelatedIterator.OUT));
180: }
181:
182: /**
183: * Iterator used to iterate over adjacent edges.
184: *
185: * @author Justin Deoliveira, Refractions Research Inc, jdeolive@refractions.net
186: *
187: */
188: public class RelatedIterator implements Iterator {
189: /** in mode **/
190: public static final int IN = 0;
191:
192: /** out mode **/
193: public static final int OUT = 1;
194:
195: /** both mode **/
196: public static final int BOTH = 2;
197:
198: /** iteration mode **/
199: private int m_mode;
200:
201: /** iteration index **/
202: private int m_index;
203:
204: /** number of edges to iterate over **/
205: private int m_n;
206:
207: /**
208: * Constructs a new iterator.
209: *
210: * @param mode Iteration mode.
211: */
212: public RelatedIterator(int mode) {
213: m_mode = mode;
214: m_index = 0;
215:
216: switch (m_mode) {
217: case IN:
218: m_n = m_in.getInDegree();
219: break;
220:
221: case OUT:
222: m_n = m_out.getOutDegree();
223: break;
224:
225: default:
226: m_n = 0;
227: }
228: }
229:
230: /**
231: * Unsupported Operation.
232: *
233: * @throws UnsupportedOperationException
234: */
235: public void remove() {
236: throw new UnsupportedOperationException(getClass()
237: .getName()
238: + "#remove()");
239: }
240:
241: /**
242: * Determines if there are any more related edges to return.
243: *
244: * @see Iterator#hasNext()
245: */
246: public boolean hasNext() {
247: return (m_index < m_n);
248: }
249:
250: /**
251: * Returns the next related edge.
252: *
253: * @see Iterator#next()
254: */
255: public Object next() {
256: switch (m_mode) {
257: case IN:
258: return (m_in.getInEdgeArray()[m_index++]);
259: case OUT:
260: return (m_out.getOutEdgeArray()[m_index++]);
261: }
262:
263: return (null);
264: }
265: }
266: }
|