Get direction (compass) with two longitude/latitude points
Solution 1
O forgot to say I found the answer eventually. The application is to determine compass direction of a transit vehicle and its destination. Essentially, fancy math for acquiring curvature of Earth, finding an angle/compass reading, and then matching that angle with a generic compass value. You could of course just keep the compassReading and apply that as an amount of rotation for your image. Please note this is an averaged determination of the vehicle direction to the end point (bus station) meaning it can't know what the road is doing (so this probably best applies to airplanes or roller derby).
//example obj data containing lat and lng points
//stop location - the radii end point
endpoint.lat = 44.9631;
endpoint.lng = -93.2492;
//bus location from the southeast - the circle center
startpoint.lat = 44.95517;
startpoint.lng = -93.2427;
function vehicleBearing(endpoint, startpoint) {
endpoint.lat = x1;
endpoint.lng = y1;
startpoint.lat = x2;
startpoint.lng = y2;
var radians = getAtan2((y1 - y2), (x1 - x2));
function getAtan2(y, x) {
return Math.atan2(y, x);
};
var compassReading = radians * (180 / Math.PI);
var coordNames = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"];
var coordIndex = Math.round(compassReading / 45);
if (coordIndex < 0) {
coordIndex = coordIndex + 8
};
return coordNames[coordIndex]; // returns the coordinate value
}
ie: vehicleBearing(mybus, busstation) might return "NW" means its travelling northwesterly
Solution 2
I found some useful gps coordinates formula in math here. For this case, here my solution
private double getDirection(double lat1, double lng1, double lat2, double lng2) {
double PI = Math.PI;
double dTeta = Math.log(Math.tan((lat2/2)+(PI/4))/Math.tan((lat1/2)+(PI/4)));
double dLon = Math.abs(lng1-lng2);
double teta = Math.atan2(dLon,dTeta);
double direction = Math.round(Math.toDegrees(teta));
return direction; //direction in degree
}
eav
Updated on July 09, 2022Comments
-
eav almost 2 years
I'm working on a "compass" for a mobile-device. I have the following points:
point 1 (current location): Latitude = 47.2246, Longitude = 8.8257 point 2 (target location): Latitude = 50.9246, Longitude = 10.2257
Also I have the following information (from my android-phone):
The compass-direction in degree, which bears to the north. For example, when I direct my phone to north, I get 0°
How can I create a "compass-like" arrow which shows me the direction to the point?
Is there a mathematic-problem for this?
EDIT: Okay I found a solution, it looks like this:
/** * Params: lat1, long1 => Latitude and Longitude of current point * lat2, long2 => Latitude and Longitude of target point * * headX => x-Value of built-in phone-compass * * Returns the degree of a direction from current point to target point * */ function getDegrees(lat1, long1, lat2, long2, headX) { var dLat = toRad(lat2-lat1); var dLon = toRad(lon2-lon1); lat1 = toRad(lat1); lat2 = toRad(lat2); 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 = toDeg(Math.atan2(y, x)); // fix negative degrees if(brng<0) { brng=360-Math.abs(brng); } return brng - headX; }
-
StaWho over 12 yearsor you can go all fancy and account for the curvature of the Earth
-
ericjam over 11 yearsThat's a great description of an answer, try maybe providing a real example.
-
StaWho over 11 years@liquified - if you look the post, even before edit, it is not tagged with any language and the question asked is:
Is there a mathematic-problem for this?
. There is also no code supplied and apart frommath
tag there's also no other indication if OP would like to resolve it (amongst many) via, let's say real numbers trigonometry or complex numbers trigonometry. Given the ambiguous parameters of the question I think the answer is sufficient. -
user2071152 over 8 years@liquified, sorry am unable to understand why (compassReading / 45) is being done. Could you please let me know. Thanks.
-
ericjam over 8 years45 is 45 degree intervals of the compass, correlating to the 9 coordNames (human names) of the compass array (NSEW,etc). Dividing your compassReading by 45 gives you, in the range of 360 degrees, how close your reading is to one of those intervals (Math.round). 360 / 45 for example gives you 8 which is the 8th index in the array or "N". You could modify this if you wanted only NSEW by dividing by 90 instead
-
Mandeep Janjua almost 5 years@efwjames " correlating to the 9 coordNames " - 45*8=360. You have repeated "N" twice in your coordNames array. Please remove that.
-
allez l'OM over 2 yearsI vote for this answer, and give you my slightly shortened version (I like arrays, and more winds): const cardinals = ["N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N"]; const carDirect = (x0,y0, x1,y1) => Math.round( Math.atan2((x1-x0),(y1-y0)) * (8 / Math.PI) ); const cardIndex = (dir) => dir<0 ? dir+16 : dir; console.log(cardinals[cardIndex(carDirect( start_lng,start_lat, end_lng,end_lat))]); Thank you.