package com.schneeloch.bostonbusmap_library.math;
/**
* All non-specific math stuff used to calculate angles and distances should go in here
* @author schneg
*
*/
public class Geometry {
/**
* Used in calculating the distance between coordinates
*/
private static final double radiusOfEarthInKilo = 6371.2;
private static final double kilometersPerMile = 1.609344;
private static final double radiusOfEarthInMiles = radiusOfEarthInKilo / kilometersPerMile;
public static final double degreesToRadians = java.lang.Math.PI / 180.0;
public static final double radiansToDegrees = 180.0 / java.lang.Math.PI;
private static final double InvPITimes180 = (1.0 / Math.PI) * 180;
public static final double milesToMeters = 1609.34;
/**
* For testing only
*
* @param lat1
* @param lon1
* @param lat2
* @param lon2
* @return
*/
public static float computeCompareDistanceFloat(float lat1, float lon1, float lat2, float lon2)
{
//great circle distance
//double dist = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1));
float dist = (float)(((1.0f - Math.cos(lat1 - lat2)) * 0.5f) + Math.cos(lat1) * Math.cos(lat2) *
((1.0f - Math.cos(lon1 - lon2)) * 0.5f));
return dist * (float)radiusOfEarthInMiles;
}
/**
* Returns a compare distance, or a distance which is distorted for efficiency sake but comparisons are always correct
*
* @param lat1 latitude in radians
* @param lat2 longitude in radians
* @param lat2 latitude in radians
* @param lon2 longitude in radians
* @return distance in miles
*/
public static float computeCompareDistance(double lat1, double lon1, double lat2, double lon2)
{
//great circle distance
double dist = ((1.0 - Math.cos(lat1 - lat2)) * 0.5) + (Math.cos(lat1) * Math.cos(lat2) *
((1.0 - Math.cos(lon1 - lon2)) * 0.5));
return (float) (dist * radiusOfEarthInMiles);
}
public static int getDegreesFromSlope(double y, double x)
{
double thetaInRadians = Math.atan2(y, x);
int degrees = mathRadiansToDegrees(thetaInRadians);
return degrees;
}
/**
* Convert from radians starting east and going counterclockwise, to a degree direction starting north and going clockwise
*
* @param thetaAsRadians direction in radians, where east is 0 and going counterclockwise
* @return a descriptive String showing the direction (for example: E (90 deg))
*/
public static int mathRadiansToDegrees(double thetaAsRadians)
{
//NOTE: degrees will be 0 == north, going clockwise
int degrees = (int)(thetaAsRadians * InvPITimes180);
if (degrees < 0)
{
degrees += 360;
}
//convert to usual compass orientation
degrees = -degrees + 90;
if (degrees < 0)
{
degrees += 360;
}
return degrees;
}
/**
* From http://stackoverflow.com/questions/120283/working-with-latitude-longitude-values-in-java
* All params are in radians
* @param lat1
* @param lng1
* @param lat2
* @param lng2
* @return
*/
public static double computeDistanceInMiles(double lat1, double lng1,
double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = lat2-lat1;
double dLng = lng2-lng1;
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist;
}
}