Get direction (compass) with two longitude/latitude points
Asked Answered
S

4

21

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;
}
Scharaga answered 14/12, 2011 at 10:17 Comment(7)
Do not post the solution about which even you are not clear.Floor
@Sameer what's your problem with the solution? If nobodoy else posts one, I can be the one. It's only for reference, if somebody else needs it. Getting a down-vote for that "reason". Can't understand.Scharaga
@Scharaga What does the toRad function you created look like?Denazify
@gohnjanotis: Not that much magic behind -> #136409Scharaga
@Scharaga If you want to post a solution to your own question, post it as an answer, not as an edit to the question. Answering your own question is perfectly normal and you can mark it as accepted to bring attention to it as the solution you went with the same as any other answer (it just won't earn any points from that). It's just much clearer to other users that come looking for solutions to similar problems if you do it this way.Scorekeeper
The function declaration has long1 and long2 but when used in the function they are lon1 and lon2.Istic
long2 !== lon2.Hallam
E
20

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

Este answered 30/3, 2014 at 4:0 Comment(4)
@liquified, sorry am unable to understand why (compassReading / 45) is being done. Could you please let me know. Thanks.Aubreyaubrie
45 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 insteadEste
@efwjames " correlating to the 9 coordNames " - 45*8=360. You have repeated "N" twice in your coordNames array. Please remove that.Marandamarasca
I 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.Abridgment
C
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

}
Chari answered 29/8, 2017 at 2:5 Comment(0)
M
0

I couldn't understand your solution well, calculating the slope worked for me. To modify on efwjames's and your answer. This should do -

import math
def getDegrees(lat1, lon1, lat2, lon2,head):
    dLat = math.radians(lat2-lat1)
    dLon = math.radians(lon2-lon1)
    bearing = math.degrees(math.atan2(dLon, dLat))
    return head-bearing
Margueritamarguerite answered 31/1, 2018 at 11:29 Comment(0)
O
-3

You'd need to calculate an Euclidean vector between your start point and end point, then calculate its angle (let's say relative to positive X) which would be the angle you want to rotate your arrow by.

Oven answered 14/12, 2011 at 10:29 Comment(3)
or you can go all fancy and account for the curvature of the EarthOven
That's a great description of an answer, try maybe providing a real example.Este
@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 from math 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.Oven

© 2022 - 2024 — McMap. All rights reserved.