/*
* Copyright 2010, 2011, 2012 mapsforge.org
*
* This program 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, either version 3 of the License, or (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mapsforge.core.model;
import java.io.Serializable;
/**
* A BoundingBox represents an immutable set of two latitude and two longitude coordinates.
*/
public class BoundingBox implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Creates a new BoundingBox from a comma-separated string of coordinates in the order minLat, minLon, maxLat,
* maxLon. All coordinate values must be in degrees.
*
* @param boundingBoxString
* the string that describes the BoundingBox.
* @return a new BoundingBox with the given coordinates.
* @throws IllegalArgumentException
* if the string cannot be parsed or describes an invalid BoundingBox.
*/
public static BoundingBox fromString(String boundingBoxString) {
double[] coordinates = CoordinatesUtil.parseCoordinateString(boundingBoxString, 4);
return new BoundingBox(coordinates[0], coordinates[1], coordinates[2], coordinates[3]);
}
/**
* The maximum latitude coordinate of this BoundingBox in degrees.
*/
public final double maxLatitude;
/**
* The maximum longitude coordinate of this BoundingBox in degrees.
*/
public final double maxLongitude;
/**
* The minimum latitude coordinate of this BoundingBox in degrees.
*/
public final double minLatitude;
/**
* The minimum longitude coordinate of this BoundingBox in degrees.
*/
public final double minLongitude;
/**
* @param minLatitude
* the minimum latitude coordinate in degrees.
* @param minLongitude
* the minimum longitude coordinate in degrees.
* @param maxLatitude
* the maximum latitude coordinate in degrees.
* @param maxLongitude
* the maximum longitude coordinate in degrees.
* @throws IllegalArgumentException
* if a coordinate is invalid.
*/
public BoundingBox(double minLatitude, double minLongitude, double maxLatitude, double maxLongitude) {
CoordinatesUtil.validateLatitude(minLatitude);
CoordinatesUtil.validateLongitude(minLongitude);
CoordinatesUtil.validateLatitude(maxLatitude);
CoordinatesUtil.validateLongitude(maxLongitude);
if (minLatitude > maxLatitude) {
throw new IllegalArgumentException("invalid latitude range: " + minLatitude + ' ' + maxLatitude);
} else if (minLongitude > maxLongitude) {
throw new IllegalArgumentException("invalid longitude range: " + minLongitude + ' ' + maxLongitude);
}
this.minLatitude = minLatitude;
this.minLongitude = minLongitude;
this.maxLatitude = maxLatitude;
this.maxLongitude = maxLongitude;
}
/**
* @param geoPoint
* the GeoPoint whose coordinates should be checked.
* @return true if this BoundingBox contains the given GeoPoint, false otherwise.
*/
public boolean contains(GeoPoint geoPoint) {
return this.minLatitude <= geoPoint.latitude && this.maxLatitude >= geoPoint.latitude
&& this.minLongitude <= geoPoint.longitude && this.maxLongitude >= geoPoint.longitude;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof BoundingBox)) {
return false;
}
BoundingBox other = (BoundingBox) obj;
if (Double.doubleToLongBits(this.maxLatitude) != Double.doubleToLongBits(other.maxLatitude)) {
return false;
} else if (Double.doubleToLongBits(this.maxLongitude) != Double.doubleToLongBits(other.maxLongitude)) {
return false;
} else if (Double.doubleToLongBits(this.minLatitude) != Double.doubleToLongBits(other.minLatitude)) {
return false;
} else if (Double.doubleToLongBits(this.minLongitude) != Double.doubleToLongBits(other.minLongitude)) {
return false;
}
return true;
}
/**
* @return a new GeoPoint at the horizontal and vertical center of this BoundingBox.
*/
public GeoPoint getCenterPoint() {
double latitudeOffset = (this.maxLatitude - this.minLatitude) / 2;
double longitudeOffset = (this.maxLongitude - this.minLongitude) / 2;
return new GeoPoint(this.minLatitude + latitudeOffset, this.minLongitude + longitudeOffset);
}
/**
* @return the latitude span of this BoundingBox in degrees.
*/
public double getLatitudeSpan() {
return this.maxLatitude - this.minLatitude;
}
/**
* @return the longitude span of this BoundingBox in degrees.
*/
public double getLongitudeSpan() {
return this.maxLongitude - this.minLongitude;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(this.maxLatitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(this.maxLongitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(this.minLatitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(this.minLongitude);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
/**
* @param boundingBox
* the BoundingBox which should be checked for intersection with this BoundingBox.
* @return true if this BoundingBox intersects with the given BoundingBox, false otherwise.
*/
public boolean intersects(BoundingBox boundingBox) {
if (this == boundingBox) {
return true;
}
return this.maxLatitude >= boundingBox.minLatitude && this.maxLongitude >= boundingBox.minLongitude
&& this.minLatitude <= boundingBox.maxLatitude && this.minLongitude <= boundingBox.maxLongitude;
}
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("minLatitude=");
stringBuilder.append(this.minLatitude);
stringBuilder.append(", minLongitude=");
stringBuilder.append(this.minLongitude);
stringBuilder.append(", maxLatitude=");
stringBuilder.append(this.maxLatitude);
stringBuilder.append(", maxLongitude=");
stringBuilder.append(this.maxLongitude);
return stringBuilder.toString();
}
}