package aimax.osm.data;
import java.util.Collection;
import aimax.osm.data.entities.MapNode;
/**
* Simple representation of a bounding box for geo coordinates.
*
* @author Ruediger Lunde
*/
public class BoundingBox {
private float latMin;
private float lonMin;
private float latMax;
private float lonMax;
public BoundingBox() {
latMin = Float.NaN;
lonMin = Float.NaN;
latMax = Float.NaN;
lonMax = Float.NaN;
}
public BoundingBox(float latMin, float lonMin, float latMax, float lonMax) {
this.latMin = latMin;
this.lonMin = lonMin;
this.latMax = latMax;
this.lonMax = lonMax;
}
public BoundingBox(Position center, int radiusKM) {
double phi = radiusKM / Position.EARTH_RADIUS;
float dLat = (float) Math.toDegrees(phi);
float dLon = (float) Math.toDegrees(phi
/ Math.cos(Math.toRadians(center.getLat())));
this.latMin = center.getLat() - dLat;
this.lonMin = center.getLon() - dLon;
this.latMax = center.getLat() + dLat;
this.lonMax = center.getLon() + dLon;
}
/** Adjusts the box so that the specified box is also included. */
public BoundingBox unifyWith(BoundingBox bb) {
latMin = Math.min(latMin, bb.latMin);
lonMin = Math.min(lonMin, bb.lonMin);
latMax = Math.max(latMax, bb.latMax);
lonMax = Math.max(lonMax, bb.lonMax);
return this;
}
/** Adjusts the box so that the result is the intersection of both boxes. */
public BoundingBox intersectWith(BoundingBox bb) {
latMin = Math.max(latMin, bb.latMin);
lonMin = Math.max(lonMin, bb.lonMin);
latMax = Math.min(latMax, bb.latMax);
lonMax = Math.min(lonMax, bb.lonMax);
return this;
}
public boolean intersectsWith(BoundingBox bb) {
if (latMin > bb.latMax || latMax < bb.latMin || lonMin > bb.lonMax
|| lonMax < bb.lonMin)
return false;
else
return true;
}
/**
* Makes sure, that all given nodes are within the box and extends the
* bounds if necessary.
*/
public void adjust(Collection<MapNode> nodes) {
for (MapNode node : nodes) {
if (Float.isNaN(latMin)) {
latMin = latMax = node.getLat();
lonMin = lonMax = node.getLon();
} else if (node.hasPosition()) {
if (node.getLat() < latMin)
latMin = node.getLat();
else if (node.getLat() > latMax)
latMax = node.getLat();
if (node.getLon() < lonMin)
lonMin = node.getLon();
else if (node.getLon() > lonMax)
lonMax = node.getLon();
}
}
}
/** Returns the distance between <code>latMax</code> and <code>latMin</code> in Kilometers. */
public float getNorthSouthDistKM() {
return (float) Position.getDistKM(latMax, lonMin, latMin, lonMin);
}
/**
* Returns the distance between <code>lonMin</code> and <code>lonMax</code> at
* latitude <code>(latMax-latMin)/2</code> in Kilometers.
*/
public float getWestEastDistKM() {
return (float) Position.getDistKM((latMin + latMax) / 2f, lonMin,
(latMin + latMax) / 2f, lonMax);
}
/**
* Checks whether the specified position is inside the box.
*/
public boolean isInside(double lat, double lon) {
return lat >= latMin && lat <= latMax && lon >= lonMin && lon <= lonMax;
}
public float getLatMin() {
return latMin;
}
public float getLonMin() {
return lonMin;
}
public float getLatMax() {
return latMax;
}
public float getLonMax() {
return lonMax;
}
public String toString() {
return "BB(" + latMin + ", " + lonMin + ", " + latMax + ", " + lonMax
+ ")";
}
}