代码之家  ›  专栏  ›  技术社区  ›  Nick

计算轴承w/Haversine函数的分类

  •  25
  • Nick  · 技术社区  · 15 年前

    我试图为CLLocation编写一个类别,以便将方向角返回到另一个CLLocation。

    我相信我是做错了公式(微积分不是我的强项)。返回的轴承总是关闭的。

    我一直在考虑这个问题,并尝试应用被接受为正确答案的更改以及它引用的网页:

    Calculating bearing between two CLLocationCoordinate2Ds

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

    谢谢

    这是我的分类-

    #import <Foundation/Foundation.h>
    #import <CoreLocation/CoreLocation.h>
    
    
    @interface CLLocation (Bearing)
    
    -(double) bearingToLocation:(CLLocation *) destinationLocation;
    -(NSString *) compassOrdinalToLocation:(CLLocation *) nwEndPoint;
    
    @end
    

    ---------中心位置+方位m

    #import "CLLocation+Bearing.h"
    
    double DegreesToRadians(double degrees) {return degrees * M_PI / 180;};
    double RadiansToDegrees(double radians) {return radians * 180/M_PI;};
    
    
    @implementation CLLocation (Bearing)
    
    -(double) bearingToLocation:(CLLocation *) destinationLocation {
    
     double lat1 = DegreesToRadians(self.coordinate.latitude);
     double lon1 = DegreesToRadians(self.coordinate.longitude);
    
     double lat2 = DegreesToRadians(destinationLocation.coordinate.latitude);
     double lon2 = DegreesToRadians(destinationLocation.coordinate.longitude);
    
     double dLon = lon2 - lon1;
    
     double y = sin(dLon) * cos(lat2);
     double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
     double radiansBearing = atan2(y, x);
    
     return RadiansToDegrees(radiansBearing);
    }
    
    6 回复  |  直到 9 年前
        1
  •  25
  •   Claus Broch    15 年前

    你的密码在我看来很好。微积分没有问题。您没有指定离结果有多远,但可以尝试将弧度/度数转换器调整为:

    double DegreesToRadians(double degrees) {return degrees * M_PI / 180.0;};
    double RadiansToDegrees(double radians) {return radians * 180.0/M_PI;};
    

    如果你是负方位,加上 2*M_PI 最终的结果是弧度轴承(或360度,如果你这样做后,转换成度)。atan2返回范围内的结果 -M_PI M_PI (-180到180度),所以您可能需要使用如下代码将其转换为罗盘方位

    if(radiansBearing < 0.0)
        radiansBearing += 2*M_PI;
    
        2
  •  6
  •   TofuBeer    9 年前

    这是一个在斯威夫特的类别开始移植:

    import Foundation
    import CoreLocation
    public extension CLLocation{
    
        func DegreesToRadians(_ degrees: Double ) -> Double {
            return degrees * M_PI / 180
        }
    
        func RadiansToDegrees(_ radians: Double) -> Double {
            return radians * 180 / M_PI
        }
    
    
        func bearingToLocationRadian(_ destinationLocation:CLLocation) -> Double {
    
            let lat1 = DegreesToRadians(self.coordinate.latitude)
            let lon1 = DegreesToRadians(self.coordinate.longitude)
    
            let lat2 = DegreesToRadians(destinationLocation.coordinate.latitude);
            let lon2 = DegreesToRadians(destinationLocation.coordinate.longitude);
    
            let dLon = lon2 - lon1
    
            let y = sin(dLon) * cos(lat2);
            let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
            let radiansBearing = atan2(y, x)
    
            return radiansBearing
        }
    
        func bearingToLocationDegrees(destinationLocation:CLLocation) -> Double{
            return   RadiansToDegrees(bearingToLocationRadian(destinationLocation))
        }
    }
    
        3
  •  4
  •   Jeef    11 年前

    public func bearingBetweenTwoPoints(#lat1 : Double, #lon1 : Double, #lat2 : Double, #lon2: Double) -> Double {
    
    func DegreesToRadians (value:Double) -> Double {
        return value * M_PI / 180.0
    }
    
    func RadiansToDegrees (value:Double) -> Double {
        return value * 180.0 / M_PI
    }
    
    let y = sin(lon2-lon1) * cos(lat2)
    let x = (cos(lat1) * sin(lat2)) - (sin(lat1) * cos(lat2) * cos(lat2-lon1))
    
    let degrees = RadiansToDegrees(atan2(y,x))
    
    let ret = (degrees + 360) % 360
    
    return ret;
    
    }
    
        4
  •  3
  •   abdullahselek    8 年前

    这是另一个 CLLocation公司 分机可用于 斯威夫特3

    public extension CLLocation {
    
        func degreesToRadians(degrees: Double) -> Double {
            return degrees * .pi / 180.0
        }
    
        func radiansToDegrees(radians: Double) -> Double {
            return radians * 180.0 / .pi
        }
    
        func getBearingBetweenTwoPoints(point1: CLLocation, point2: CLLocation) -> Double {
            let lat1 = degreesToRadians(degrees: point1.coordinate.latitude)
            let lon1 = degreesToRadians(degrees: point1.coordinate.longitude)
    
            let lat2 = degreesToRadians(degrees: point2.coordinate.latitude)
            let lon2 = degreesToRadians(degrees: point2.coordinate.longitude)
    
            let dLon = lon2 - lon1
    
            let y = sin(dLon) * cos(lat2)
            let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
            let radiansBearing = atan2(y, x)
    
            return radiansToDegrees(radians: radiansBearing)
        }
    
    }
    
        5
  •  2
  •   David Seek    9 年前

    工作速度3和4

    extension CLLocation {
    
    
        func getRadiansFrom(degrees: Double ) -> Double {
    
            return degrees * .pi / 180
    
        }
    
        func getDegreesFrom(radians: Double) -> Double {
    
            return radians * 180 / .pi
    
        }
    
    
        func bearingRadianTo(location: CLLocation) -> Double {
    
            let lat1 = self.getRadiansFrom(degrees: self.coordinate.latitude)
            let lon1 = self.getRadiansFrom(degrees: self.coordinate.longitude)
    
            let lat2 = self.getRadiansFrom(degrees: location.coordinate.latitude)
            let lon2 = self.getRadiansFrom(degrees: location.coordinate.longitude)
    
            let dLon = lon2 - lon1
    
            let y = sin(dLon) * cos(lat2)
            let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
    
            var radiansBearing = atan2(y, x)
    
            if radiansBearing < 0.0 {
    
                radiansBearing += 2 * .pi
    
            }
    
    
            return radiansBearing
        }
    
        func bearingDegreesTo(location: CLLocation) -> Double {
    
            return self.getDegreesFrom(radians: self.bearingRadianTo(location: location))
    
        }
    
    
    }
    

    用法:

    let degrees = location1.bearingDegreesTo(location: location2)
    
        6
  •  1
  •   Romain    10 年前

    为什么我要用余弦定律:

    • 快速运行(因为没有sqrt函数)
    • 足够精确除非你做一些天文学
    • 非常适合后台任务
    
    func calculateDistance(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D) -> Double {
    
        let π = M_PI
        let degToRad: Double = π/180
        let earthRadius: Double = 6372797.560856
    
        // Law of Cosines formula
        // d = r . arc cos (sin 𝜑A sin 𝜑B + cos 𝜑A cos 𝜑B cos(𝜆B - 𝜆A) )
    
        let 𝜑A = from.latitude * degToRad
        let 𝜑B = to.latitude * degToRad
        let 𝜆A = from.longitude * degToRad
        let 𝜆B = to.longitude * degToRad
    
        let angularDistance = acos(sin(𝜑A) * sin(𝜑B) + cos(𝜑A) * cos(𝜑B) * cos(𝜆B - 𝜆A) )
        let distance = earthRadius * angularDistance
    
        return distance
    
    }
    
    推荐文章