用于计算带有半阴茎function的轴承的CL位置类别
我试图写一个CLLocation的类别,以将方位返回到另一个CLLocation。
我相信我正在做一些错误的公式(结石不是我的强项)。 返回的轴承总是closures。
我一直在看这个问题,并尝试应用接受的更改作为正确的答案和它引用的网页:
计算两个CLLocationCoordinate2D之间的方位
http://www.movable-type.co.uk/scripts/latlong.html
感谢任何指针。 我已经尝试纳入来自其他问题的反馈,但我仍然没有得到什么。
谢谢
这是我的类别 –
—– CLLocation + Bearing.h
#import <Foundation/Foundation.h> #import <CoreLocation/CoreLocation.h> @interface CLLocation (Bearing) -(double) bearingToLocation:(CLLocation *) destinationLocation; -(NSString *) compassOrdinalToLocation:(CLLocation *) nwEndPoint; @end
——— CLLocation + Bearing.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); }
你的代码对我来说似乎很好。 结石没有错。 你不指定你的结果有多远,但你可以尝试调整你的弧度/度数转换器:
double DegreesToRadians(double degrees) {return degrees * M_PI / 180.0;}; double RadiansToDegrees(double radians) {return radians * 180.0/M_PI;};
如果您获得的是负方位,请将2*M_PI
添加到2*M_PI
的最终结果中(如果在转换为度数后执行,则为360)。 atan2返回范围-M_PI
到M_PI
(-180到180度)的结果,所以你可能想把它转换成指南针方位,使用类似下面的代码
if(radiansBearing < 0.0) radiansBearing += 2*M_PI;
这是在开始的类别Swift中的移植:
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)) } }
这是另一个实现
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; }
我在斯威夫特使用余弦定律。 它运行速度比Haversine快,其结果非常相似。 1米的巨大距离的变化。
为什么我使用余弦定律:
- 运行速度快(因为没有sqrtfunction)
- 精确到足够的,除非你做一些天文学
- 完美的后台任务
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 }
工作迅速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)
这是另外一个可以在Swift 3和Swift 4中使用的CLLocation扩展
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) } }