Files
Party-Parrots-At-Sea/src/main/java/seng302/server/simulator/GeoUtility.java
T
Haoming Yin 705a0a2eaf Added document and unit tests for GeoUtility class.
- three methods in GeoUtility have been tested and passed.

#story[828]
2017-04-28 14:34:24 +12:00

83 lines
3.1 KiB
Java

package seng302.server.simulator;
import seng302.server.simulator.mark.Position;
public class GeoUtility {
private static double EARTH_RADIUS = 6378.137;
/**
* Calculates the euclidean distance between two markers on the canvas using xy coordinates
*
* @param p1 first geographical position
* @param p2 second geographical position
* @return the distance in meter between two points in meters
*/
public static Double getDistance(Position p1, Position p2) {
double dLat = Math.toRadians(p2.getLat() - p1.getLat());
double dLon = Math.toRadians(p2.getLng() - p1.getLng());
double a = Math.pow(Math.sin(dLat / 2), 2.0)
+ Math.cos(Math.toRadians(p1.getLat())) * Math.cos(Math.toRadians(p2.getLat()))
* Math.pow(Math.sin(dLon / 2), 2.0);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = EARTH_RADIUS * c;
return d * 1000; // distance from km to meter
}
/**
* Calculates the angle between to angular co-ordinates on a sphere.
*
* @param p1 the first geographical position, start point
* @param p2 the second geographical position, end point
* @return the initial bearing in degree from p1 to p2, value range (0 ~ 360 deg.).
* vertical up is 0 deg. horizontal right is 90 deg.
*
* NOTE:
* The final bearing will differ from the initial bearing by varying degrees
* according to distance and latitude (if you were to go from say 35°N,45°E
* (≈ Baghdad) to 35°N,135°E (≈ Osaka), you would start on a heading of 60°
* and end up on a heading of 120°
*/
public static Double getBearing(Position p1, Position p2) {
double dLon = Math.toRadians(p2.getLng() - p1.getLng());
double y = Math.sin(dLon) * Math.cos(Math.toRadians(p2.getLat()));
double x = Math.cos(Math.toRadians(p1.getLat())) * Math.sin(Math.toRadians(p2.getLat()))
- Math.sin(Math.toRadians(p1.getLat())) * Math.cos(Math.toRadians(p2.getLat())) * Math.cos(dLon);
double bearing = Math.toDegrees(Math.atan2(y, x));
return (bearing + 360.0) % 360.0;
}
/**
* Given an existing point in lat/lng, distance in (in meter) and bearing
* (in degrees), calculates the new lat/lng.
*
* @param origin the original position within lat / lng
* @param bearing the bearing in degree, from original position to the new position
* @param distance the distance in meter, from original position to the new position
* @return the new position
*/
public static Position getGeoCoordinate(Position origin, Double bearing, Double distance) {
double b = Math.toRadians(bearing); // bearing to radians
double d = distance / 1000.0; // distance to km
double originLat = Math.toRadians(origin.getLat());
double originLng = Math.toRadians(origin.getLng());
double endLat = Math.asin(Math.sin(originLat) * Math.cos(d / EARTH_RADIUS)
+ Math.cos(originLat) * Math.sin(d / EARTH_RADIUS) * Math.cos(b));
double endLng = originLng
+ Math.atan2(Math.sin(b) * Math.sin(d / EARTH_RADIUS) * Math.cos(originLat),
Math.cos(d / EARTH_RADIUS) - Math.sin(originLat) * Math.sin(endLat));
return new Position(Math.toDegrees(endLat), Math.toDegrees(endLng));
}
}