How to get angle between two POI?

后端 未结 3 421
傲寒
傲寒 2020-12-19 21:49

How do I calculate the angle in degrees between the coordinates of two POIs (points of interest) on an iPhone map application?

相关标签:
3条回答
  • 2020-12-19 22:38

    You are calculating the 'Bearing' from one point to another here. There's a whole bunch of formula for that, and lots of other geographic quantities like distance and cross-track error, on this web page:

    http://www.movable-type.co.uk/scripts/latlong.html

    the formulae are in several formats so you can easily convert to whatever language you need for your iPhone. There's also javascript calculators so you can test your code gets the same answers as theirs.

    0 讨论(0)
  • 2020-12-19 22:40

    I'm guessing you try to calculate the degrees between the coordinates of two points of interest (POI).

    Calculating the arc of a great circle:

    +(float) greatCircleFrom:(CLLocation*)first 
                          to:(CLLocation*)second {
    
        int radius = 6371; // 6371km is the radius of the earth
        float dLat = second.coordinate.latitude-first.coordinate.latitude;
        float dLon = second.coordinate.longitude-first.coordinate.longitude;
        float a = pow(sin(dLat/2),2) + cos(first.coordinate.latitude)*cos(second.coordinate.latitude) * pow(sin(dLon/2),2);
        float c = 2 * atan2(sqrt(a),sqrt(1-a));
        float d = radius * c;
    
        return d;
    }
    

    Another option is to pretend you are on cartesian coordinates (faster but not without error on long distances):

    +(float)angleFromCoordinate:(CLLocationCoordinate2D)first 
                   toCoordinate:(CLLocationCoordinate2D)second {
    
        float deltaLongitude = second.longitude - first.longitude;
        float deltaLatitude = second.latitude - first.latitude;
        float angle = (M_PI * .5f) - atan(deltaLatitude / deltaLongitude);
    
        if (deltaLongitude > 0)      return angle;
        else if (deltaLongitude < 0) return angle + M_PI;
        else if (deltaLatitude < 0)  return M_PI;
    
        return 0.0f;
    }
    

    If you want the result in degrees instead radians, you have to apply the following conversion:

    #define RADIANS_TO_DEGREES(radians) ((radians) * 180.0 / M_PI)
    
    0 讨论(0)
  • 2020-12-19 22:54

    If the other solutions dont work for you try this:

    - (int)getInitialBearingFrom:(CLLocation *)first
                            to:(CLLocation *)second
    {
        float lat1 = [self degreesToRad:first.coordinate.latitude];
        float lat2 = [self degreesToRad:second.coordinate.latitude];
        float lon1 = [self degreesToRad:first.coordinate.longitude];
        float lon2 = [self degreesToRad:second.coordinate.longitude];
        float dLon = lon2 - lon1;
        float y = sin (dLon) * cos (lat2);
        float x1 = cos (lat1) * sin (lat2);
        float x2 = sin (lat1) * cos (lat2) * cos (dLon);
        float x = x1 - x2;
        float bearingRadRaw = atan2f (y, x);
        float bearingDegRaw = bearingRadRaw * 180 / M_PI;
        int bearing = ((int) bearingDegRaw + 360) % 360; // +- 180 deg to 360 deg
    
        return bearing;
    }
    

    For final bearing, simply take the initial bearing from the end point to the start point and reverse it (using θ = (θ+180) % 360).

    You need these 2 helpers:

    -(float)radToDegrees:(float)radians
    {
        return radians * 180 / M_PI;
    }
    -(float)degreesToRad:(float)degrees
    {
        return degrees * M_PI /180;
    }
    
    0 讨论(0)
提交回复
热议问题