001: /*
002: * <copyright>
003: *
004: * Copyright 2003-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.logistics.plugin.seanet;
027:
028: import java.util.Iterator;
029: import java.util.Vector;
030:
031: /** A sea route network. It uses a standard network of nodes and
032: links provided by NodeData.class. The Panama and Suez canals can
033: be opened and closed.
034:
035: <p> The network should be used as a stateful calculator of
036: distances and routes:
037:
038: <ul>
039:
040: <li> Use setFrom(lat, lon) to set a from location and compute
041: distances from it and the network nodes.
042:
043: <li> Use setTo(lat, lon) to set a to location.
044:
045: <li> Use distance() to compute the distance in nautical miles
046: between from and to.
047:
048: <li> Use route() to return an iterator of Location's of the route
049: from to to from. The locations along the route are only valid
050: while the from point has not change.
051:
052: </ul>
053:
054: **/
055: public class Network {
056:
057: int now = 0;
058:
059: public Network() {
060: this ((new NodeData()).getNodes());
061: }
062:
063: public Network(Vector nodes) {
064: this .nodes = nodes;
065: this .fringe1 = new Vector(nodes.size());
066: this .fringe2 = new Vector(nodes.size());
067: }
068:
069: Link getLink(int i, int j) {
070: return ((Link) ((Node) nodes.elementAt(i)).links.elementAt(j));
071: }
072:
073: public void setPanamaCanal(boolean isOpen) {
074: getLink(0, 0).setIsOpen(isOpen);
075: getLink(1, 0).setIsOpen(isOpen);
076: }
077:
078: public boolean getPanamaCanal() {
079: return getLink(0, 0).isOpen();
080: }
081:
082: public void setSuezCanal(boolean isOpen) {
083: getLink(2, 0).setIsOpen(isOpen);
084: getLink(3, 0).setIsOpen(isOpen);
085: }
086:
087: public boolean getSuezCanal() {
088: return getLink(2, 0).isOpen();
089: }
090:
091: Vector nodes;
092:
093: public Iterator getNodes() {
094: return nodes.iterator();
095: }
096:
097: Vector fringe1, fringe2;
098:
099: double fromLat, fromLon;
100: Node from;
101:
102: public void setFrom(double lat, double lon) {
103: this .fromLat = lat;
104: this .fromLon = lon;
105: this .setFrom(this .closestNode(lat, lon));
106: }
107:
108: double toLat, toLon;
109: Node to;
110:
111: public void setTo(Node to) {
112: this .to = to;
113: }
114:
115: public void setTo(double lat, double lon) {
116: this .toLat = lat;
117: this .toLon = lon;
118: this .setTo(this .closestNode(lat, lon));
119: }
120:
121: public double distance(double fromLat, double fromLon,
122: double toLat, double toLon) {
123: this .setFrom(fromLat, fromLon);
124: return this .distance(toLat, toLon);
125: }
126:
127: public double distance(double toLat, double toLon) {
128: this .setTo(toLat, toLon);
129: return distance();
130: }
131:
132: public double distance() {
133: return this .to.distance(this .toLat, this .toLon) + to.getCost()
134: + this .from.distance(this .fromLat, this .fromLon);
135: }
136:
137: /**
138: Search the entire net so distance and routes to the from point can
139: be computed easily.
140: **/
141: public void setFrom(Node from) {
142: this .now = this .now + 1;
143: this .from = from;
144: for (Iterator i = getNodes(); i.hasNext();)
145: ((Node) i.next()).setCost(Node.HUGE);
146: from.setCost(0);
147:
148: fringe1.setSize(0);
149: fringe1.add(from);
150: fringe2.setSize(0);
151:
152: propagate(fringe1, fringe2);
153: fringe1.setSize(0);
154: fringe2.setSize(0);
155: }
156:
157: void propagate(Vector fringe1, Vector fringe2) {
158: fringe2.setSize(0);
159: for (Iterator i1 = fringe1.iterator(); i1.hasNext();)
160: ((Node) i1.next()).propagateToLinks(fringe2);
161: if (fringe2.size() > 0)
162: propagate(fringe2, fringe1);
163: }
164:
165: /**
166: * Find the closest Node in the network to this location.
167: */
168: public Node closestNode(double latitude, double longitude) {
169: GreatCircle gc = new GreatCircle(latitude, longitude);
170: Node minNode = null;
171: double minDistance = Node.HUGE;
172: Iterator i = this .getNodes();
173: while (i.hasNext()) {
174: Node n = ((Node) i.next());
175: gc.setPoint2(n.getLatitude(), n.getLongitude());
176: double d = gc.distanceNM();
177: if (d < minDistance) {
178: minNode = n;
179: minDistance = d;
180: }
181: }
182: return minNode;
183: }
184:
185: public Iterator route() {
186: return new SequenceIterator(new SingletonIterator(
187: new LocationImpl(toLat, toLon)), new SequenceIterator(
188: new RouteIterator(this .to), new SingletonIterator(
189: new LocationImpl(fromLat, fromLon))));
190: }
191:
192: public Iterator routeNoSource() {
193: return new SequenceIterator(new RouteIterator(this .to),
194: new SingletonIterator(
195: new LocationImpl(fromLat, fromLon)));
196: }
197:
198: public Iterator routeNoSourceOrDestination() {
199: return new RouteIterator(this .to);
200: }
201:
202: public Iterator routeNoDestination() {
203: return new SequenceIterator(new SingletonIterator(
204: new LocationImpl(toLat, toLon)), new RouteIterator(
205: this .to));
206: }
207:
208: public class RouteIterator implements Iterator {
209: int now;
210: Node here;
211:
212: public RouteIterator(Node here) {
213: this .here = here;
214: this .now = Network.this .now;
215: }
216:
217: void check() {
218: if (this .now != Network.this .now)
219: throw new java.util.ConcurrentModificationException(
220: "Underlying network has changed.");
221: }
222:
223: public boolean hasNext() {
224: check();
225: return this .here != null;
226: }
227:
228: public Object next() {
229: check();
230: Object result = this .here;
231: if (this .here == Network.this .from) {
232: this .here = null;
233: } else {
234: this .here = this .here.getBack();
235: }
236: return result;
237: }
238:
239: public void remove() {
240: throw new UnsupportedOperationException();
241: }
242: }
243: }
|