package com.nutiteq.components;
import henson.midp.Float11;
/**
* Point object for moving WGS84 coordinates between library and implementing
* application
*/
public class WgsPoint {
public static final int FORMAT_LAT_LON = 1;
private final double lon;
private final double lat;
// "average" radius of the earth
private static final double EARTH_RADIUS = 6367454D;
public WgsPoint(final double lon, final double lat) {
this.lon = lon;
this.lat = lat;
}
/**
* Get coordinate latitude
*
* @return latitude
*/
public double getLat() {
return lat;
}
/**
* Get coordinate longitude
*
* @return longitude
*/
public double getLon() {
return lon;
}
public Point toInternalWgs() {
return new Point((int) (lon * 1000000D), (int) (lat * 1000000D));
}
public String toString() {
return new StringBuffer().append(lon).append("E ").append(lat).append("N").toString();
}
/**
* Check if two WgsPoint objects refer to the same coordinates.
*
* @param obj
* the other object
* @return true if the coordinates are the same, false otherwise
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null || !(obj instanceof WgsPoint)) {
return false;
}
final WgsPoint p = (WgsPoint) obj;
return lat == p.getLat() && lon == p.getLon();
}
public int hashCode() {
throw new RuntimeException("hashCode() not implemented!");
}
/**
* Compute distance in meters between two points.
*
* @param p1
* first point
* @param p2
* second point
* @return distance in meters
*/
public static double distanceInMeters(final WgsPoint p1, final WgsPoint p2) {
final double p1latr = Math.toRadians(p1.lat);
final double p2latr = Math.toRadians(p2.lat);
final double dlat = (p2latr - p1latr) / 2;
final double dlon = Math.toRadians(p2.lon - p1.lon) / 2;
final double s1 = Math.sin(dlat);
final double s2 = Math.sin(dlon);
final double h = s1 * s1 + Math.cos(p1latr) * Math.cos(p2latr) * s2 * s2;
final double dist = 2 * EARTH_RADIUS * Float11.asin(Math.sqrt(h));
return dist;
}
/**
* True course at p1 using great circle distance.
* @param p1 first point
* @param p2 second point
* @return course in degrees as a number between 0 and 360
*/
public static double initialTrueCourse(final WgsPoint p1, final WgsPoint p2) {
final double dlon = Math.toRadians(p2.lon-p1.lon);
final double p1latr = Math.toRadians(p1.lat);
final double p2latr = Math.toRadians(p2.lat);
// check for poles
final double c1 = Math.cos(p1latr);
if (c1 < 0.00001) {
return (p1latr > 0) ? 180 : 0;
}
final double c2 = Math.cos(p2latr);
final double at1 = Math.sin(dlon)*c2;
final double at2 = c1*Math.sin(p2latr)-Math.sin(p1latr)*c2*Math.cos(dlon);
final double at = Float11.atan2(at1, at2);
final double atd = Math.toDegrees(at);
if (atd < 0) {
return atd + 360;
} else if (atd >= 360) {
return atd - 360;
} else {
return atd;
}
}
/**
* True course at p2 using great circle distance.
* final_true_course(p1,p2) = initial_true_course(p2,p1)-180.
* @param p1 first point
* @param p2 second point
* @return course in degrees as a number between 0 and 360
*/
public static double finalTrueCourse(final WgsPoint p1, final WgsPoint p2) {
final double crs = initialTrueCourse(p2, p1) + 180;
if (crs >= 360) {
return crs - 360;
} else {
return crs;
}
}
public static WgsPoint parsePoint(final int format, final String string, final String separator) {
final double one = Double.parseDouble(string.substring(0, string.indexOf(separator)).trim());
final double two = Double.parseDouble(string.substring(string.indexOf(separator) + 1).trim());
return format == FORMAT_LAT_LON ? new WgsPoint(two, one) : new WgsPoint(one, two);
}
}