/**
* RESTRICTED RIGHTS LEGEND
*
* BBNT Solutions LLC
* A Verizon Company
* 10 Moulton Street
* Cambridge, MA 02138
* (617) 873-3000
*
* Copyright BBNT Solutions LLC 2001, 2002 All Rights Reserved
*
*/
package com.bbn.openmap.geo;
import java.util.Iterator;
/**
* Iterate along a sequence of Ribbons. A Ribbon is a three Geo set, with a
* RIGHT, CENTER and LEFT Geo in the Ribbon. The location of the LEFT and RIGHT
* Geo are perpendicular to the great circle path that the CENTER Geo resides
* on.
*/
public class RibbonIterator implements Iterator<Ribbon>, Iterable<Ribbon> {
protected Geo v1;
protected Geo v2;
protected double radius;
protected Geo gc;
protected Rotation rotator;
protected Geo point;
protected double distance;
/**
* Return an iterator that returns Ribbons along the great circle between v1
* and v2. The Ribbon points are radius radians apart, and each Ribbon is
* 2*radius apart.
*/
public RibbonIterator(Geo v1, Geo v2, double radius) {
this(v1, v2, radius, 2.0 * radius);
}
/**
* Return an iterator that returns Ribbons along the great circle between v1
* and v2. The Ribbon points are radius radians apart, and each Ribbon is
* rotationIntervalDist apart.
*
* @param v1 from this Geo
* @param v2 to this Geo
* @param radius distance away from great circle lines between geos, in
* radians.
* @param rotationIntervalDist interval distance between ribbons, in
* radians. You want this to be smaller than the distance between the
* geos, obviously.
*/
public RibbonIterator(Geo v1, Geo v2, double radius, double rotationIntervalDist) {
this.v1 = v1;
this.v2 = v2;
if (v1 == null || v2 == null || v1.equals(v2)) {
// hasNext should fail
this.point = v2;
} else {
this.distance = v1.distance(v2);
this.radius = radius;
this.gc = v1.crossNormalize(v2);
this.rotator = new Rotation(gc, rotationIntervalDist);
this.point = v1;
}
}
/**
* Call after hasNext() returns true.
*
* @return next Ribbon containing points at offset from v1 and v2.
*/
public Ribbon next() {
if (!hasNext()) {
return Ribbon.getEmpty();
}
if (point != v2 && v1.distance(point) < distance) {
Ribbon result = new Ribbon(point, gc, radius);
point = rotator.rotate(point);
return result;
} else {
point = v2;
return new Ribbon(point, gc, radius);
}
}
/**
* Are there more Ribbons in the iterator?
*
* @return true if there are, then call next().
*/
public boolean hasNext() {
return point != v2;
}
public void remove() {
}
public Iterator<Ribbon> iterator() {
return this;
}
}