WGS84Position.java
/*
* Copyright (C) 2021-2023 Dipl.-Inform. Kai Hofmann. All rights reserved!
*/
package de.powerstat.validation.values;
import java.util.Objects;
import de.powerstat.validation.interfaces.IValueObject;
/**
* World geodetic system 1984 position.
*
* Possibly DSGVO relevant.
*
* TODO precision
* TODO output formats
* TODO Get address for position if possible
*/
public final class WGS84Position implements Comparable<WGS84Position>, IValueObject
{
/* *
* Cache for singletons.
*/
// private static final Map<NTuple3<Double, Double, Double>, WGS84Position> CACHE = new WeakHashMap<>();
/**
* Epsilon for double compare.
*/
private static final double EPSILON = 0.000001D;
/**
* Position separator.
*/
private static final String SEPARATOR = " ";
/**
* Positions latitude specifies the north–south position of a point on the Earth's surface.
*
* Ranges from 0° at the Equator to 90° (North or South) at the poles.
*/
private final double latitude;
/**
* Positions longitude specifies the east–west position of a point on the Earth's surface.
*
* The prime meridian, which passes near the Royal Observatory, Greenwich, England, is defined as 0° longitude by convention. Positive longitudes are east of the prime meridian, and negative ones are west.
*/
private final double longitude;
/**
* Positions altitude - height above sea level.
*/
private final double altitude;
/**
* Constructor.
*
* @param latitude Positions latitude specifies the north–south position of a point on the Earth's surface. Ranges from 0° at the Equator to 90° (North or South) at the poles.
* @param longitude Positions longitude specifies the east–west position of a point on the Earth's surface. The prime meridian, which passes near the Royal Observatory, Greenwich, England, is defined as 0° longitude by convention. Positive longitudes are east of the prime meridian, and negative ones are west.
* @param altitude Positions altitude - height above sea level.
*/
private WGS84Position(final double latitude, final double longitude, final double altitude)
{
super();
if ((latitude < -90.0) || (latitude > 90.0))
{
throw new IndexOutOfBoundsException("Latitude out of range"); //$NON-NLS-1$
}
if ((longitude < -180.0) || (longitude > 180.0))
{
throw new IndexOutOfBoundsException("Longitude out of range"); //$NON-NLS-1$
}
this.latitude = latitude;
this.longitude = longitude;
this.altitude = altitude;
}
/**
* WGS84Position factory.
*
* @param latitude Positions latitude specifies the north–south position of a point on the Earth's surface. Ranges from 0° at the Equator to 90° (North or South) at the poles.
* @param longitude Positions longitude specifies the east–west position of a point on the Earth's surface. The prime meridian, which passes near the Royal Observatory, Greenwich, England, is defined as 0° longitude by convention. Positive longitudes are east of the prime meridian, and negative ones are west.
* @param altitude Positions altitude - height above sea level.
* @return WGS84Position object
*/
public static WGS84Position of(final double latitude, final double longitude, final double altitude)
{
/*
final NTuple3<Double, Double, Double> tuple = NTuple3.of(latitude, longitude, altitude);
synchronized (WGS84Position.class)
{
WGS84Position obj = WGS84Position.CACHE.get(tuple);
if (obj != null)
{
return obj;
}
obj = new WGS84Position(latitude, longitude, altitude);
WGS84Position.CACHE.put(tuple, obj);
return obj;
}
*/
return new WGS84Position(latitude, longitude, altitude);
}
/**
* WGS84Position factory.
*
* @param value latitude longitude altitude separated by one space
* @return WGS84Position object
*/
public static WGS84Position of(final String value)
{
final String[] values = value.split(SEPARATOR);
if (values.length != 3)
{
throw new IllegalArgumentException("value not of expected format");
}
final double latitude = Double.parseDouble(values[0]);
final double longitude = Double.parseDouble(values[1]);
final double altitude = Double.parseDouble(values[2]);
return of(latitude, longitude, altitude);
}
/**
* Get latitude.
*
* @return Latitude
*/
public double getLatitude()
{
return this.latitude;
}
/**
* Get longitude.
*
* @return Longitude
*/
public double getLongitude()
{
return this.longitude;
}
/**
* Get altitude.
*
* @return Altitude
*/
public double getAltitude()
{
return this.altitude;
}
/**
* Returns the value of this WGS84Position as a String.
*
* @return The value represented by this object after conversion to type String.
*/
@Override
public String stringValue()
{
return this.latitude + SEPARATOR + this.longitude + SEPARATOR + this.altitude;
}
/**
* Calculate hash code.
*
* @return Hash
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
int result = Double.hashCode(this.latitude);
result = (31 * result) + Double.hashCode(this.longitude);
return (31 * result) + Double.hashCode(this.altitude);
}
/**
* Is equal with another object.
*
* @param obj Object
* @return true when equal, false otherwise
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof WGS84Position))
{
return false;
}
final WGS84Position other = (WGS84Position)obj;
return (Math.abs(this.latitude - other.latitude) < WGS84Position.EPSILON) && (Math.abs(this.longitude - other.longitude) < WGS84Position.EPSILON) && (Math.abs(this.altitude - other.altitude) < WGS84Position.EPSILON);
}
/**
* Returns the string representation of this WGS84Position.
*
* The exact details of this representation are unspecified and subject to change, but the following may be regarded as typical:
*
* "WGS84Position[latitude=0.0, longitude=0.0, altitude=0.0]"
*
* @return String representation of this WGS84Position
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
final var builder = new StringBuilder(47);
builder.append("WGS84Position[latitude=").append(this.latitude).append(", longitude=").append(this.longitude).append(", altitude=").append(this.altitude).append(']'); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
return builder.toString();
}
/**
* Compare with another object.
*
* @param obj Object to compare with
* @return 0: equal; 1: greater; -1: smaller
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
@Override
public int compareTo(final WGS84Position obj)
{
Objects.requireNonNull(obj, "obj"); //$NON-NLS-1$
int result = Double.compare(this.latitude, obj.latitude);
if (result == 0)
{
result = Double.compare(this.longitude, obj.longitude);
if (result == 0)
{
result = Double.compare(this.altitude, obj.altitude);
}
}
return result;
}
}