将CLLocation移动x米

Oli*_*ver 24 iphone cocoa-touch latitude-longitude core-location

我有一个CLLocation定义,我想将这个点移动到东边x米和南边y米.我怎么能实现这一目标?

Pet*_* O. 28

转换到Swift,取自这个答案:

func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D {
    let distRadians = distanceMeters / (6372797.6) // earth radius in meters

    let lat1 = origin.latitude * M_PI / 180
    let lon1 = origin.longitude * M_PI / 180

    let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(bearing))
    let lon2 = lon1 + atan2(sin(bearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2))

    return CLLocationCoordinate2D(latitude: lat2 * 180 / M_PI, longitude: lon2 * 180 / M_PI)
}
Run Code Online (Sandbox Code Playgroud)

Morgan Chen写道:

此方法中的所有数学运算都以弧度完成.在方法开始时,为此也将lon1和lat1转换为弧度.轴承也是弧度.请记住,此方法考虑了地球的曲率,对于小距离,您实际上并不需要这样做.

  • 如果对任何人都不清楚,那么轴承指的是你想要前进的方向,以度为单位,所以对于north:bearing = 0,对于east:bearing = 90,对于西南:轴承= 225,等等... (10认同)

Kor*_*and 17

改进彼得斯答案的快速解决方案.只有校正是在计算时轴承应该是弧度.

 func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D {
    let distRadians = distanceMeters / (6372797.6)

    var rbearing = bearing * M_PI / 180.0

    let lat1 = origin.latitude * M_PI / 180
    let lon1 = origin.longitude * M_PI / 180

    let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(rbearing))
    let lon2 = lon1 + atan2(sin(rbearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2))

    return CLLocationCoordinate2D(latitude: lat2 * 180 / M_PI, longitude: lon2 * 180 / M_PI)
}
Run Code Online (Sandbox Code Playgroud)


小智 16

伟大的帖子,这里是喜欢复制/粘贴的人的Obj-C包装:

- (CLLocationCoordinate2D) locationWithBearing:(float)bearing distance:(float)distanceMeters fromLocation:(CLLocationCoordinate2D)origin {
    CLLocationCoordinate2D target;
    const double distRadians = distanceMeters / (6372797.6); // earth radius in meters

    float lat1 = origin.latitude * M_PI / 180;
    float lon1 = origin.longitude * M_PI / 180;

    float lat2 = asin( sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(bearing));
    float lon2 = lon1 + atan2( sin(bearing) * sin(distRadians) * cos(lat1),
                     cos(distRadians) - sin(lat1) * sin(lat2) );

    target.latitude = lat2 * 180 / M_PI;
    target.longitude = lon2 * 180 / M_PI; // no need to normalize a heading in degrees to be within -179.999999° to 180.00000°

    return target;
}
Run Code Online (Sandbox Code Playgroud)


pro*_*rmr 6

有一个C函数接近你要求的但它需要一个方位和距离.它位于github上的UtilitiesGeo类中.您可以将CLLocation中的纬度和经度传递给它,然后从返回的结果lat2和lon2创建一个新的CLLocation:

/*-------------------------------------------------------------------------
* Given a starting lat/lon point on earth, distance (in meters)
* and bearing, calculates destination coordinates lat2/lon2.
*
* all params in degrees
*-------------------------------------------------------------------------*/
void destCoordsInDegrees(double lat1, double lon1,
                         double distanceMeters, double bearing,
                         double* lat2, double* lon2);
Run Code Online (Sandbox Code Playgroud)

如果您不能使用它,请查看从此处此处派生的算法,也许您可以修改它,或者这些站点可能更接近您的需求.


Den*_*uev 6

奇怪的是,没有人想到使用 MapKit 中的 MKCooperativeRegion 来自动计算。

import MapKit

extension CLLocation {
    func movedBy(latitudinalMeters: CLLocationDistance, longitudinalMeters: CLLocationDistance) -> CLLocation {
        let region = MKCoordinateRegion(center: coordinate, latitudinalMeters: abs(latitudinalMeters), longitudinalMeters: abs(longitudinalMeters))

        let latitudeDelta = region.span.latitudeDelta
        let longitudeDelta = region.span.longitudeDelta

        let latitudialSign = CLLocationDistance(latitudinalMeters.sign == .minus ? -1 : 1)
        let longitudialSign = CLLocationDistance(longitudinalMeters.sign == .minus ? -1 : 1)

        let newLatitude = coordinate.latitude + latitudialSign * latitudeDelta
        let newLongitude = coordinate.longitude + longitudialSign * longitudeDelta

        let newCoordinate = CLLocationCoordinate2D(latitude: newLatitude, longitude: newLongitude)

        let newLocation = CLLocation(coordinate: newCoordinate, altitude: altitude, horizontalAccuracy: horizontalAccuracy, verticalAccuracy: verticalAccuracy, course: course, speed: speed, timestamp: Date())

        return newLocation
    }
}
Run Code Online (Sandbox Code Playgroud)