/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.search.spatial.impl;
/**
* Bounding box for search area on Earth
*
* @author Nicolas Helleringer <nicolas.helleringer@novacodex.net>
* @author Mathieu Perez <mathieu.perez@novacodex.net>
*/
public final class Rectangle {
private final Point lowerLeft;
private final Point upperRight;
public Rectangle(Point lowerLeft, Point upperRight) {
this.lowerLeft = lowerLeft;
this.upperRight = upperRight;
}
/**
* Compute appropriate bounding box on Earth with pole and prime meridian crossing checks
*
* @param center of the search area
* @param radius of the search area
* @return a bounding box for the area
* @see <a href="http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates">Bouding box on Earth calculation</a>
*/
public static Rectangle fromBoundingCircle(Point center, double radius) {
// http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates
double minimumLatitude, maximumLatitude;
double minimumLongitude, maximumLongitude;
if ( radius > center.getDistanceTo( GeometricConstants.NORTH_POLE ) ) {
maximumLatitude = GeometricConstants.LATITUDE_DEGREE_MAX;
}
else {
maximumLatitude = center.computeDestination( radius, GeometricConstants.HEADING_NORTH ).getLatitude();
}
if ( radius > center.getDistanceTo( GeometricConstants.SOUTH_POLE ) ) {
minimumLatitude = GeometricConstants.LATITUDE_DEGREE_MIN;
}
else {
minimumLatitude = center.computeDestination( radius, GeometricConstants.HEADING_SOUTH ).getLatitude();
}
if ( ( radius > 2 * Math.PI * GeometricConstants.EARTH_MEAN_RADIUS_KM * Math.cos(
Math.toRadians(
minimumLatitude
)
) ) || ( radius > 2 * Math.PI * GeometricConstants.EARTH_MEAN_RADIUS_KM * Math.cos(
Math.toRadians(
maximumLatitude
)
) ) ) {
maximumLongitude = GeometricConstants.LONGITUDE_DEGREE_MAX;
minimumLongitude = GeometricConstants.LONGITUDE_DEGREE_MIN;
}
else {
Point referencePoint = Point.fromDegrees(
Math.max(
Math.abs( minimumLatitude ),
Math.abs( maximumLatitude )
), center.getLongitude()
);
maximumLongitude = referencePoint.computeDestination( radius, GeometricConstants.HEADING_EAST )
.getLongitude();
minimumLongitude = referencePoint.computeDestination( radius, GeometricConstants.HEADING_WEST )
.getLongitude();
}
return new Rectangle(
Point.fromDegreesInclusive( minimumLatitude, minimumLongitude ),
Point.fromDegreesInclusive( maximumLatitude, maximumLongitude )
);
}
public Point getLowerLeft() {
return lowerLeft;
}
public Point getUpperRight() {
return upperRight;
}
}