org.hibernate.search.spatial.impl.Point Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-search-engine Show documentation
Show all versions of hibernate-search-engine Show documentation
Core of the Object/Lucene mapper, query engine and index management
/*
* Hibernate Search, full-text search for your domain model
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or .
*/
package org.hibernate.search.spatial.impl;
import org.hibernate.search.spatial.Coordinates;
/**
* Normalized latitude,longitude holder (in [-90;90],[-180,180]) with distance and destination computations methods
*
* @author Nicolas Helleringer
* @author Mathieu Perez
*/
public final class Point implements Coordinates {
private final double latitude;
private final double longitude;
/**
* @param latitude in degrees
* @param longitude in degrees
* @return a point with coordinates given in degrees
*/
public static Point fromDegrees(double latitude, double longitude) {
return new Point( normalizeLatitude( latitude ), normalizeLongitude( longitude ) );
}
/**
* @param center the coordinates for the Point to be created
* @return a Point from given Coordinates. Same instance when given a Point.
*/
public static Point fromCoordinates(Coordinates center) {
if ( center instanceof Point ) {
return (Point) center;
}
else {
return Point.fromDegrees( center.getLatitude(), center.getLongitude() );
}
}
/**
* @param latitude in degrees
* @param longitude in degrees
* @return a point with coordinates given in degrees
*/
public static Point fromDegreesInclusive(double latitude, double longitude) {
return new Point( normalizeLatitude( latitude ), normalizeLongitudeInclusive( longitude ) );
}
/**
* @param longitude in degrees
* @return longitude normalized in ]-180;+180]
*/
public static double normalizeLongitude(double longitude) {
if ( longitude == ( -GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 ) ) {
return GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 ;
}
else {
return normalizeLongitudeInclusive( longitude );
}
}
/**
* @param longitude in degrees
* @return longitude normalized in [-180;+180]
*/
public static double normalizeLongitudeInclusive(double longitude) {
if ( (longitude < -( GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 ) ) || (longitude > ( GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 ) ) ) {
double _longitude;
// shift 180 and normalize full circle turn
_longitude = ( ( longitude + ( GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 ) ) % GeometricConstants.WHOLE_CIRCLE_DEGREE_RANGE );
// as Java % is not a math modulus we may have negative numbers so the unshift is sign dependant
if ( _longitude < 0 ) {
_longitude = _longitude + ( GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 );
}
else {
_longitude = _longitude - ( GeometricConstants.LONGITUDE_DEGREE_RANGE / 2 );
}
return _longitude;
}
else {
return longitude;
}
}
/**
* @param latitude in degrees
* @return latitude normalized in [-90;+90]
*/
public static double normalizeLatitude(double latitude) {
if ( latitude > GeometricConstants.LATITUDE_DEGREE_MAX || latitude < GeometricConstants.LATITUDE_DEGREE_MIN ) {
// shift 90, normalize full circle turn and 'symmetry' on the lat axis with abs
double _latitude = Math.abs( ( latitude + ( GeometricConstants.LATITUDE_DEGREE_RANGE / 2 ) ) % ( GeometricConstants.WHOLE_CIRCLE_DEGREE_RANGE ) );
// Push 2nd and 3rd quadran in 1st and 4th by 'symmetry'
if ( _latitude > GeometricConstants.LATITUDE_DEGREE_RANGE ) {
_latitude = GeometricConstants.WHOLE_CIRCLE_DEGREE_RANGE - _latitude;
}
// unshift
_latitude = _latitude - ( GeometricConstants.LATITUDE_DEGREE_RANGE / 2 );
return _latitude;
}
else {
return latitude;
}
}
/**
* @param latitude in radians
* @param longitude in radians
* @return a point with coordinates given in radians
*/
public static Point fromRadians(double latitude, double longitude) {
return fromDegrees( latitude * GeometricConstants.TO_DEGREES_RATIO, longitude * GeometricConstants.TO_DEGREES_RATIO);
}
/**
* @param latitude in degrees
* @param longitude in degrees
*/
private Point(double latitude, double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
/**
* Calculate end of travel point
*
* @param distance to travel
* @param heading of travel in decimal degree
* @return arrival point
* @see Compute destination
*/
public Point computeDestination(double distance, double heading) {
double headingRadian = heading * GeometricConstants.TO_RADIANS_RATIO;
double destinationLatitudeRadian = Math.asin(
Math.sin( getLatitudeRad() ) * Math.cos( distance / GeometricConstants.EARTH_MEAN_RADIUS_KM ) + Math.cos(
getLatitudeRad()
) * Math.sin( distance / GeometricConstants.EARTH_MEAN_RADIUS_KM ) * Math.cos(
headingRadian
)
);
double destinationLongitudeRadian = getLongitudeRad() + Math.atan2(
Math.sin( headingRadian ) * Math.sin(
distance / GeometricConstants.EARTH_MEAN_RADIUS_KM
) * Math.cos( getLatitudeRad() ),
Math.cos( distance / GeometricConstants.EARTH_MEAN_RADIUS_KM ) - Math.sin( getLatitudeRad() ) * Math.sin(
destinationLatitudeRadian
)
);
return fromRadians( destinationLatitudeRadian, destinationLongitudeRadian );
}
/**
* Compute distance between two points
*
* @param other a {@link org.hibernate.search.spatial.impl.Point} object.
* @see Distance haversine formula
*/
public double getDistanceTo(Point other) {
return getDistanceTo( other.getLatitude(), other.getLongitude() );
}
/**
* Compute distance point and other location given by its latitude and longitude in decimal degrees
*
* @param latitude in decimal degrees
* @param longitude in decimal degrees
* @see Distance haversine formula
*/
public double getDistanceTo(final double latitude,final double longitude) {
double destinationLatitudeRadians = normalizeLatitude( latitude ) * GeometricConstants.TO_RADIANS_RATIO;
double destinationLongitudeRadians = normalizeLongitude( longitude ) * GeometricConstants.TO_RADIANS_RATIO;
final double dLat = ( destinationLatitudeRadians - getLatitudeRad() ) / 2.0d;
final double dLon = ( destinationLongitudeRadians - getLongitudeRad() ) / 2.0d;
final double a = Math.pow( Math.sin( dLat ), 2 ) + Math.pow( Math.sin( dLon ), 2) * Math.cos( getLatitudeRad()) * Math.cos( destinationLatitudeRadians );
final double c = 2.0d * Math.atan2( Math.sqrt( a ), Math.sqrt( 1.0d - a ) );
return c * GeometricConstants.EARTH_MEAN_RADIUS_KM;
}
@Override
public Double getLatitude() {
return latitude;
}
@Override
public Double getLongitude() {
return longitude;
}
public double getLatitudeRad() {
return latitude * GeometricConstants.TO_RADIANS_RATIO;
}
public double getLongitudeRad() {
return longitude * GeometricConstants.TO_RADIANS_RATIO;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append( "Point" );
sb.append( "{latitude=" ).append( latitude );
sb.append( ", longitude=" ).append( longitude );
sb.append( '}' );
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy