Longitude, Latitude, Altitude to 3D-Cartesian Coordinate Systems - gps

I'm wondering about the transformation from Lat,Lon,Alt Values to 3D-Systems like ECEF (Earth-Centered).
This can be implemented as follows (https://gist.github.com/1536054):
/*
* WGS84 ellipsoid constants Radius
*/
private static final double a = 6378137;
/*
* eccentricity
*/
private static final double e = 8.1819190842622e-2;
private static final double asq = Math.pow(a, 2);
private static final double esq = Math.pow(e, 2);
void convert(latitude,longitude,altitude){
double lat = Math.toRadians(latitude);
double lon = Math.toRadians(longitude);
double alt = altitude;
double N = a / Math.sqrt(1 - esq * Math.pow(Math.sin(lat), 2));
x = (N + alt) * Math.cos(lat) * Math.cos(lon);
y = (N + alt) * Math.cos(lat) * Math.sin(lon);
z = ((1 - esq) * N + alt) * Math.sin(lat);
}
What in my opinion seems very strange is the fact, that a little change of the altitude, affects x,y and z, where I would expect, that it just affect one axis. For example, if I have two GPS-Points, which have same lat/lon values but different altitude values, I'll get 3 different x,y,z coordinates.
Can someone explain the "idea" behind this? This looks very curious to me... Is there any other 3D-System, in which only one of the values is changing, when I lower/higher my altitude value?
Thanks a lot!

If you look at this picture: ECEF Coordinate System
then you see why.
ECEF is a cube arround the earth, centered in earth center.
if altitude raises you move out.
Lat/lon is an "angular" coordinate system where lat,lon are angles,
ECEF is a cartesian coordinate system!
Probaly you thougt ECEF is like LatLon with center earth has altitude 0, but this is not the case.

Related

"Get 100 meters out from" Haversin Formula

I'm interested in working with coordinates, and I was wondering, how is it possible to get the distance between two points (coordinates) in meters. After a long search I found the Haversine Formula, and the Objective-C implementation of it here.
It's the following (I modified it a little bit for myself):
- (CGFloat)directMetersFromCoordinate:(CLLocation *)from toCoordinate:(CLLocation *)to {
static const double DEG_TO_RAD = 0.017453292519943295769236907684886;
static const double EARTH_RADIUS_IN_METERS = 6372797.560856;
double latitudeArc = (from.coordinate.latitude - to.coordinate.latitude) * DEG_TO_RAD;
double longitudeArc = (from.coordinate.longitude - to.coordinate.longitude) * DEG_TO_RAD;
double latitudeH = sin(latitudeArc * 0.5);
latitudeH *= latitudeH;
double lontitudeH = sin(longitudeArc * 0.5);
lontitudeH *= lontitudeH;
double tmp = cos(from.coordinate.latitude*DEG_TO_RAD) * cos(to.coordinate.latitude*DEG_TO_RAD);
return EARTH_RADIUS_IN_METERS * 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH)); }
My question is:
How is it possible to get 100 meters distance (for latitude and for longitude) for the current location?
This formula is too complicated for me, I don't understand it, so I can't "code it back" to get the result what I want.
I need only the actual location (Paris, Tokyo, London, New York, whatever), and a (float) number for latitude and a (float) number for longitude, which (float) number represents 100 meters distance from the actual location.
If you open this page, here you can "calculate out" the 100 meters distance between two points ("actual" and the one 100 meters away).
For example:
Point1: 47.0, 19.0
Point2: 47.0, 19.0013190
---That's 0.1000 km (100 m) distance.
Point1: 47.0, 19.0
Point2: 47.0008995, 19.0
---is also 0.1000 km (100 m) distance.
Here you can see, that at that coordinate (latitude 47.0 and longitude 19.0) 100 meters distance is 0.0008995 (latitude) and 0.0013190 (longitude).
And I want to get these data with the help of the Haversine Formula, just don't know, how.
Could you help me to figure it out?
Thanks!
UPDATE:
Thank you for the answers, right now I don't have time to try them out, but as I understood, I didn't explain exactly what I want.
Maybe this is a better example, how I want to use these "100 meters":
So, right now I'm at the coordinate "lat x" and "lon y". There is another point (let's say a hotel) at another given coordinate, "lat a" and "lon b".
My question is: how can I calculate out, if this hotel is (less than) 100 meters from me? So it doesn't matter, if it's only 5 meters or 99 meters, both of them are less (or equal) than 100 meters far from me.
With the code what I provided, I can calculate this out, that's what that formula is for.
But let's say, I have a million of other coordinates (hotel locations) that I want to work with. And I need only a list of them, what are (less than) 100 meters away from me. So yes, that's a circle around me with a radius of 100 meters, and I need the results within that.
It would take much more time and resource to take all the coordinates of these "million" hotels and calculate the distance one by one, that's why I thought it would be much easier to calculate out, how much 100 meters are in latitude and longitude (changes the value as we are on different locations, that' why I can't use simply the ones what I calculated out in the example above).
So if I would know how much 100 meters are in latitude and longitude for example at London's coordinate (if I'm there), I could simply get the list of the hotels what are (less than) 100 meters far from me, by a simple dividing:
if
((hotelLocation.coordinate.latitude <= (myLocation.coordinate.latitude + "100metersInLatitude")) || (hotelLocation.coordinate.latitude >= (myLocation.coordinate.latitude - "100metersInLatitude")))
&&
((hotelLocation.coordinate.longitude <= (myLocation.coordinate.longitude + "100metersInLongitude")) || (hotelLocation.coordinate.longitude >= (myLocation.coordinate.longitude - "100metersInLongitude")))
{
NSLog(#"Be Happy :-) !");
}
I just need these "100metersInLatitude" and "100metersInLongitude", calculated always from "myLocation".
Whoa, I hope, somebody will understand what I just wrote down, because it's not easy for me, neither... :-)))
Assuming you have a point with latitude and longitude, and you want to find another point that is a distance d on a bearing b, when the distance is small (you said "100 meters" which is very small on the surface of the earth) then you can do a simple approximation - treating the earth's surface locally as "flat". Here is a simple C program that implements this (using the numbers you had above). I updated it to include the "accurate" formulation as well - it's just a few more calculations, but it is accurate at all distances (and not just the short ones). The equation I used came from the link you referenced - subheading "Destination point given distance and bearing from start point"
updated - I moved the accurate calculation into a separate function, and added a loop to compute the new point for all integer bearings from 0 to 359, printing out every 30th. This give you the "circle" I talked about in my initial comment.
#include <stdio.h>
#include <math.h>
double radians(double x) {
return acos(0.0) * x / 90.0;
}
void calcNewPosition(double lat, double lon, double bearing, double d, double *newLat, double *newLon) {
double lat1, lon1, br, pi;
double Re = 6371000;
// convert everything to radians first:
lat1 = radians(lat);
lon1 = radians(lon);
br = radians(bearing);
pi = 2 * acos(0.0);
double lat2, lon2;
lat2 = asin( sin(lat1) * cos(d/Re) +
cos( lat1 ) * sin( d / Re ) * cos(br ) );
lon2 = lon1 + atan2(sin(br) * sin( d / Re ) * cos( lat1 ), \
cos( d / Re ) - sin(lat1 ) * sin( lat2 ) );
*newLat = 180. * lat2 / pi;
*newLon = 180. * lon2 / pi;
}
int main(void) {
double lon = 47., lat=19.;
double newLongitude, newLatitude;
double dx, dy, dLong, dLat;
double Re = 6371000, d = 100, bearing = 0.0;
double pi;
double lat1, lon1, br;
// convert everything to radians first:
lat1 = radians(lat);
lon1 = radians(lon);
br = radians(bearing);
pi = 2 * acos(0.0);
// approximate calculation - using equirectangular approximation
// and noting that distance between meridians (lines of longitude)
// get closer at higher latitudes, with cos(latitude).
dx = d * sin(br); // distance in E-W direction
dy = d * cos(br); // distance in N-S direction
dLat = 360 * dy / (2.0 * pi * Re); // convert N-S to degrees latitude
dLong = 360 * dx / (2.0 * pi * Re * cos(lat1)); // convert E-W to degrees longitude
newLatitude = lat + dLat;
newLongitude = lon + dLong;
printf("simple forumula: the new position is %.8lf lon, %.8lf lat\n", newLongitude, newLatitude);
// more accurate formula: based on http://www.movable-type.co.uk/scripts/latlong.html
double lat2, lon2;
calcNewPosition(lat, lon, bearing, d, &lat2, &lon2);
printf("more accurate: the new position is %.8lf lon, %.8lf lat\n", lon2, lat2);
// now loop over all bearings and compute the "circle of points":
int iBearing;
double lonArray[360], latArray[360];
for(iBearing = 0; iBearing < 360; iBearing++) {
calcNewPosition(lat, lon, (double)iBearing, d, &latArray[iBearing], &lonArray[iBearing]);
if (iBearing % 30 == 0) printf("bearing %03d: new lat = %.8lf, new lon = %.8lf\n", iBearing, latArray[iBearing], lonArray[iBearing]);
}
return 0;
}
The output of this is
simple forumula: the new position is 47.00000000 lon, 19.00089932 lat
more accurate: the new position is 47.00000000 lon, 19.00089932 lat
bearing 000: new lat = 19.00089932, new lon = 47.00000000
bearing 030: new lat = 19.00077883, new lon = 47.00047557
bearing 060: new lat = 19.00044966, new lon = 47.00082371
bearing 090: new lat = 19.00000000, new lon = 47.00095114
bearing 120: new lat = 18.99955034, new lon = 47.00082371
bearing 150: new lat = 18.99922116, new lon = 47.00047557
bearing 180: new lat = 18.99910068, new lon = 47.00000000
bearing 210: new lat = 18.99922116, new lon = 46.99952443
bearing 240: new lat = 18.99955034, new lon = 46.99917629
bearing 270: new lat = 19.00000000, new lon = 46.99904886
bearing 300: new lat = 19.00044966, new lon = 46.99917629
bearing 330: new lat = 19.00077883, new lon = 46.99952443
As you can see, it is accurate to within a fraction of a meter (your code gave 19.0008995 - it is actually possible that your result was "wrong" in the last digit as these two methods agree to 8 significant digits even though they use different equations).
The question isn't really answerable if the OP wants a location a distance (100 meters) from the current location without a desired bearing being provided, there being an infinite number of points in a circle around the point.
So, this answer may or may not be what the OP wants, it is a way with CLLocation to calculate the distance between two points.
Create two CLLocation point and use the method Have you looked at theCLLocationmethod- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location`.
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:)latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:)latitude2 longitude:longitude2];
double distance = [location1 distanceFromLocation:location2];
The radius of the earth at equator = 6,371 km. The equator is divided into 360 degrees of longitude, so each degree at the equator represents approximately 111.32 km. Moving away from the equator towards a pole this distance decreases to zero at the pole.To calculate the distance at different latitudes multiply it by the cosine of the latitude
3 decimal places,0.001 degrees aproximates to
111.32 meters at equator
96.41meters at 30 degrees N/S
78.71 meters at 45 degrees N/S
55.66 meters at 60 degrees N/S
28.82 meters at 75 degrees N/S
For for small distances (100 meters) Pythagoras’ theorem can be used on an equirectangular projection to calculate distance. This is less complicated than Haversine or Spherical Law of Cosines.
var R = 6371; // km
lat/lng in radians
In pseudo code as I don't know Objective-C
var x = (lng2-lng1) * cos((lat1+lat2)/2);
var y = (lat2-lat1);
var d = sqrt(x*x + y*y) * R;

Minimum distance between a point and a line in latitude, longitude

I have a line with two points in latitude and longitude
A: 3.222895, 101.719751
B: 3.227511, 101.724318
and 1 point
C: 3.224972, 101.722932
How can I calculate minimum distance between point C and a line consists of point A and B?
It will be convenient if you can provide the calculation and objective-c code too. The distance is around 89 meters (using ruler in Google Earth).
Thanks to mimi and this great article http://www.movable-type.co.uk/scripts/latlong.html but they don't give the whole picture. Here is a detail one. All this points are collected using Google Earth using Placemark to mark the locations. Make sure lat/long are set to decimal degrees in Preferences.
lat A = 3.222895
lon A = 101.719751
lat B = 3.222895
lon B = 101.719751
lat C = 3.224972
lon C = 101.722932
Earth radius, R = 6371
1. First you have to find the bearing from A to C and A to B.
Bearing formula
bearingAC = atan2( sin(Δλ)*cos(φ₂), cos(φ₁)*sin(φ₂) − sin(φ₁)*cos(φ₂)*cos(Δλ) )
bearingAB = atan2( sin(Δλ)*cos(φ₂), cos(φ₁)*sin(φ₂) − sin(φ₁)*cos(φ₂)*cos(Δλ) )
φ is latitude, λ is longitude, R is earth radius
2. Find A to C distance using spherical law of cosines
distanceAC = acos( sin(φ₁)*sin(φ₂) + cos(φ₁)*cos(φ₂)*cos(Δλ) )*R
3. Find cross-track distance
distance = asin(sin(distanceAC/ R) * sin(bearingAC − bearing AB)) * R
Objective-C code
double lat1 = 3.227511;
double lon1 = 101.724318;
double lat2 = 3.222895;
double lon2 = 101.719751;
double lat3 = 3.224972;
double lon3 = 101.722932;
double y = sin(lon3 - lon1) * cos(lat3);
double x = cos(lat1) * sin(lat3) - sin(lat1) * cos(lat3) * cos(lat3 - lat1);
double bearing1 = radiansToDegrees(atan2(y, x));
bearing1 = 360 - ((bearing1 + 360) % 360);
double y2 = sin(lon2 - lon1) * cos(lat2);
double x2 = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(lat2 - lat1);
double bearing2 = radiansToDegrees(atan2(y2, x2));
bearing2 = 360 - ((bearing2 + 360) % 360);
double lat1Rads = degreesToRadians(lat1);
double lat3Rads = degreesToRadians(lat3);
double dLon = degreesToRadians(lon3 - lon1);
double distanceAC = acos(sin(lat1Rads) * sin(lat3Rads)+cos(lat1Rads)*cos(lat3Rads)*cos(dLon)) * 6371;
double min_distance = fabs(asin(sin(distanceAC/6371)*sin(degreesToRadians(bearing1)-degreesToRadians(bearing2))) * 6371);
NSLog(#"bearing 1: %g", bearing1);
NSLog(#"bearing 2: %g", bearing2);
NSLog(#"distance AC: %g", distanceAC);
NSLog(#"min distance: %g", min_distance);
Actually there's a library for this. You can find it here https://github.com/100grams/CoreLocationUtils
Calculate bearing for each: C to A , and C to B:
var y = Math.sin(dLon) * Math.cos(lat2);
var x = Math.cos(lat1)*Math.sin(lat2) -
Math.sin(lat1)*Math.cos(lat2)*Math.cos(dLon);
var brng = Math.atan2(y, x).toDeg();
dLon= lon2-lon1;
Calculate cross-track distance:
var dXt = Math.asin(Math.sin(distance_CB/R)*Math.sin(bearing_CA-bearing_CB)) * R;
R is the radius of earth, dXt is the minimum distance you wanted to calculate.
Code to carry out this calculation is posted at here.
This implements an accurate solution in terms of ellipsoidal geodesics.
For the basic geodesic calculations, you can use
GeographicLib or the port of these algorithms to C which are included in version 4.9.0 of PROJ.4. This C interface is documented here.
Here's the result of compiling and running intercept.cpp:
$ echo 3.222895 101.719751 3.227511 101.724318 3.224972 101.722932 | ./intercept
Initial guess 3.225203 101.7220345
Increment 0.0003349040566247297 0.0003313413822354505
Increment -4.440892098500626e-16 0
Increment 0 0
...
Final result 3.225537904056624 101.7223658413822
Azimuth to A1 -135.1593040635131
Azimuth to A2 44.84069593652217
Azimuth to B1 134.8406959363608
Distance to line is 88.743m:
$ echo 3.224972 101.722932 3.225537904056624 101.7223658413822 | GeodSolve -i
-45.15927221 -45.15930407 88.743
See post here:
https://stackoverflow.com/a/33343505/4083623
For distance up to a few thousands meters I would simplify the issue from sphere to plane.
Then, the issue is pretty simply as a easy triangle calculation can be used:
We have points A and B and look for a distance X to line AB. Then:
Location a;
Location b;
Location x;
double ax = a.distanceTo(x);
double alfa = (Math.abs(a.bearingTo(b) - a.bearingTo(x))) / 180
* Math.PI;
double distance = Math.sin(alfa) * ax;
If you know how to calculate the distance of two points, get the distances between each two points, you get AB, AC, and BC. You want to know the closest distance between point C and line AB.
First get the value of P
P=(AB+BC+AC)/2
Using P, you need to get S
S=SQRT((P(P-AC)(P-AB)(P-AC))
SQRT means square root. Then you get what you want by
2*S/AB

Move camera target position along with the mouse

I am rewriting my application using the modern OpenGL (3.3+) in Jogl.
I am using all the conventional matrices, that is objectToWorld, WorldToCamera and CameraToClip (or model, view and projection)
I created a class for handling all the mouse movements as McKesson does in its "Learning modern 3d graphic programming" with a method to offset the camera target position:
private void offsetTargetPosition(MouseEvent mouseEvent){
Mat4 currMat = calcMatrix();
Quat orientation = currMat.toQuaternion();
Quat invOrientation = orientation.conjugate();
Vec2 current = new Vec2(mouseEvent.getX(), mouseEvent.getY());
Vec2 diff = current.minus(startDragMouseLoc);
Vec3 worldOffset = invOrientation.mult(new Vec3(-diff.x*10, diff.y*10, 0.0f));
currView.setTargetPos(currView.getTargetPos().plus(worldOffset));
startDragMouseLoc = current;
}
calcMatrix() returns the camera matrix, the rest should be clear.
What I want is moving my object along with the mouse, right now mouse movement and object translation don't correspond, that is they are not linear, because I am dealing with different spaces I guess..
I learnt that if I want to apply a transformation T in space O, but related in space C, I should do the following with p as vertex:
C * (C * T * C^-1) * O * p
Should I do something similar?
I solved with a damn simple proportion...
float x = (float) (10000 * 2 * EC_Main.viewer.getAspect() * diff.x / EC_Main.viewer.getWidth());
float y = (float) (10000 * 2 * diff.y / EC_Main.viewer.getHeight());
Vec3 worldOffset = invOrientation.mult(new Vec3(-x, y, 0.0f));
Taking into account my projection matrix
Mat4 orthographicMatrix = Jglm.orthographic(-10000.0f * (float) EC_Main.viewer.getAspect(), 10000.0f * (float) EC_Main.viewer.getAspect(),
-10000.0f, 10000.0f, -10000.0f, 10000.0f);

Calculate distance in (x, y) between two GPS-Points

I'm looking for a smooth way to calculate the distance between two GPS Points, so I get the result like: "You have to go x meters up and y meters to the left - so I can work with a 2d-coordinate system, where I have my position as (0,0) and the other positions is showing the distance in (x, y) in meters from my position.
My idea was to calculate the distance between the points using the haversine formula. (This returns my hypotenuse)
In addition to that, I'm calculating the bearing between this two points. This is my alpha.
With this two values, I wanted to use basic trigonometry functions to resolve my problem.
So I tried to calculate:catheti_1 = sin(alpha) * hypotenuse, catheti_2 = cos(alpha) * hypotenuse.
Maybe I'm doing something wrong, but my results are useless at the moment.
So my question is: How can I calculate the distance in x and y direction between two GPS points?
I'm calculating alpha in the following procedure:
public static double bearingTo(GPSBean point1, GPSBean point2) {
double lat1 = Math.toRadians(point1.latitude);
double lat2 = Math.toRadians(point2.latitude);
double lon1 = Math.toRadians(point1.longitude);
double lon2 = Math.toRadians(point2.longitude);
double deltaLong = lon2 - lon1;
double y = Math.sin(deltaLong) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(deltaLong);
double bearing = Math.atan2(y, x);
return (Math.toDegrees(bearing) + 360) % 360;
}
I just implemented your code, using approximate coordinates of NYC and Boston as reference points, and implementing the Haversine formula as found at http://www.movable-type.co.uk/scripts/latlong.html (which you didn't show):
long1 = -71.02; lat1 = 42.33;
long2 = -73.94; lat2 = 40.66;
lat1 *=pi/180;
lat2 *=pi/180;
long1*=pi/180;
long2*=pi/180;
dlong = (long2 - long1);
dlat = (lat2 - lat1);
// Haversine formula:
R = 6371;
a = sin(dlat/2)*sin(dlat/2) + cos(lat1)*cos(lat2)*sin(dlong/2)*sin(dlong/2)
c = 2 * atan2( sqrt(a), sqrt(1-a) );
d = R * c;
When I run this code, I get d = 306, which agrees with the answer from the above site.
For the bearing I get 52 deg - again, close to what the site gave.
Without seeing the rest of your code it's hard to know why your answer is different.
Note: when the two points are close together, you could make all kinds of approximations, but this code should still work - the formula has good numerical stability because it's using the sin of the difference between longitudes, latitudes (rather than the difference of the sin).
Addendum:
Using your code for x, y (in your question), I get sensible values for the distance - agreeing with the "proper" answer to within 120 m (which isn't bad since one is a straight line approximation and the other follows the curvature of the earth). So I think your code is basically OK now you fixed the typo.
Use Haversine formula to Calculate distance (in km) between two points specified by latitude/longitude (in numeric degrees)
from: Haversine formula - R. W. Sinnott, "Virtues of the Haversine"
Sky and Telescope, vol 68, no 2, 1984
http://www.census.gov/cgi-bin/geo/gisfaq?Q5.1
Example usage from form:
result.value = LatLon.distHaversine(lat1.value.parseDeg(), long1.value.parseDeg(), * lat2.value.parseDeg(), long2.value.parseDeg());
Javascript :
LatLon.distHaversine = function(lat1, lon1, lat2, lon2) {
var R = 6371; // earth's mean radius in km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad();
lat1 = lat1.toRad(), lat2 = lat2.toRad();
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon/2) * Math.sin(dLon/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
If anybody is interested to have a simpler formula that anyone can understand. Here is mine, it works for Sweden, but you can adapt it to work anywhere by making a more general formula for calculation of longfactor.
Hope you can understand even if it is written in an odd language.
<gpsDist lat1,long1,lat2,long2> all parameters in 1/100000 degree.
Example: <getDist 5950928,1327120,5958505,1302241> => 16303
Same at https://gps-coordinates.org/distance-between-coordinates.php => 16.35 KM.
<var $latFactor,1.112>
<function getDist,
-<var $longFactor,<calc 0.638 - ($1/100000-55)*0.0171,3>>
-<var $latDist,<calc ($3-$1)*$latFactor>>
-<var $longDist,<calc ($4-$2)*$longFactor>>
-<sqrt $latDist*$latDist + $longDist*$longDist>
->
/Bertil Friman

calculate latitude and longitude along a circumference of a known circle with known distance

I dont need help with a programming language, I need help from someone to calculate the gps coordinates of points of a specific distance, namely 22 feet apart, on the circumference of a circle. I know the beginning gps coordinates and the radius. I am pretty sure the haversine, or the speherical law of cosines has the answer, but its been a long time since I have used any trig formulas and I cant figure it out. I am using decimal degrees and am programing in this vb.net. If someone could dumb this down for me it would be a great help.
As I understand you have:
Coordinate of the center of
circumference.
Distance between
two point on the circumference of a
circle.
Radius of circumference.
In my opinion this is not enough for calculating other point's coordinates. You should have as minimum yet one point coordinate, because we only can guess where points are placed on the circumference.
Here's the basic algorithm:
Calculate the angular measure whose arc length is 22 feet, with the given radius
numPoints = Math.PI * 2 / angularMeasure
for i in range(numPoints):
calculate proportion around the circle we are, in terms of degrees or radians
calculate the location of the endpoint of a great circle or rhumb arc from the center point moving in the specific azimuth direction (from the proportion around the circle) the given radius
This last point is the hardest part. Here's code from the WorldWind SDK (available: http://worldwind.arc.nasa.gov/java/) (Note- you'll have to calculate the radius in terms of angles, which you can do pretty easily given the radius / circumference of the earth)
/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
/**
* Computes the location on a rhumb line with the given starting location, rhumb azimuth, and arc distance along the
* line.
*
* #param p LatLon of the starting location
* #param rhumbAzimuth rhumb azimuth angle (clockwise from North)
* #param pathLength arc distance to travel
*
* #return LatLon location on the rhumb line.
*/
public static LatLon rhumbEndPosition(LatLon p, Angle rhumbAzimuth, Angle pathLength)
{
if (p == null)
{
String message = Logging.getMessage("nullValue.LatLonIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (rhumbAzimuth == null || pathLength == null)
{
String message = Logging.getMessage("nullValue.AngleIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double lat1 = p.getLatitude().radians;
double lon1 = p.getLongitude().radians;
double azimuth = rhumbAzimuth.radians;
double distance = pathLength.radians;
if (distance == 0)
return p;
// Taken from http://www.movable-type.co.uk/scripts/latlong.html
double lat2 = lat1 + distance * Math.cos(azimuth);
double dPhi = Math.log(Math.tan(lat2 / 2.0 + Math.PI / 4.0) / Math.tan(lat1 / 2.0 + Math.PI / 4.0));
double q = (lat2 - lat1) / dPhi;
if (Double.isNaN(dPhi) || Double.isNaN(q) || Double.isInfinite(q))
{
q = Math.cos(lat1);
}
double dLon = distance * Math.sin(azimuth) / q;
// Handle latitude passing over either pole.
if (Math.abs(lat2) > Math.PI / 2.0)
{
lat2 = lat2 > 0 ? Math.PI - lat2 : -Math.PI - lat2;
}
double lon2 = (lon1 + dLon + Math.PI) % (2 * Math.PI) - Math.PI;
if (Double.isNaN(lat2) || Double.isNaN(lon2))
return p;
return new LatLon(
Angle.fromRadians(lat2).normalizedLatitude(),
Angle.fromRadians(lon2).normalizedLongitude());
}
You are looking for the equation of what is called a "small circle". Look at this book for the equation of the small circle and the arc length equation for that small circle. However, because your distances are so small, you could consider your area flat and use simpler geometry. Using UTM coordinates would make the calculations much simpler than using lat/long.
The Haversine formula relates to great circles, not small circles...