public static IGeoPoint computeOffsetOrigin ( IGeoPoint to , double distance , double heading ) { heading = toRadians ( heading ) ; distance /= EARTH_RADIUS ; // http://lists.maptools.org/pipermail/proj/2008-October/003939.html double n1 = cos ( distance ) ; double n2 = sin ( distance ) * cos ( heading ) ; double n3 = sin ( distance ) * sin ( heading ) ; double n4 = sin ( toRadians ( to . getLatitude ( ) ) ) ; // There are two solutions for b. b = n2 * n4 +/- sqrt(), one solution results // in the latitude outside the [-90, 90] range. We first try one solution and // back off to the other if we are outside that range. double n12 = n1 * n1 ; double discriminant = n2 * n2 * n12 + n12 * n12 - n12 * n4 * n4 ; if ( discriminant < 0 ) { // No real solution which would make sense in IGeoPoint-space. return null ; } double b = n2 * n4 + sqrt ( discriminant ) ; b /= n1 * n1 + n2 * n2 ; double a = ( n4 - n2 * b ) / n1 ; double fromLatRadians = atan2 ( a , b ) ; if ( fromLatRadians < - PI / 2 || fromLatRadians > PI / 2 ) { b = n2 * n4 - sqrt ( discriminant ) ; b /= n1 * n1 + n2 * n2 ; fromLatRadians = atan2 ( a , b ) ; } if ( fromLatRadians < - PI / 2 || fromLatRadians > PI / 2 ) { // No solution which would make sense in IGeoPoint-space. return null ; } double fromLngRadians = toRadians ( to . getLongitude ( ) ) - atan2 ( n3 , n1 * cos ( fromLatRadians ) - n2 * sin ( fromLatRadians ) ) ; return new GeoPoint ( toDegrees ( fromLatRadians ) , toDegrees ( fromLngRadians ) ) ; }
Returns the location of origin when provided with a IGeoPoint destination meters travelled and original heading . Headings are expressed in degrees clockwise from North . This function returns null when no solution is available .