如何计算地理点周围的矩形?

the*_*ory 1 geolocation latitude-longitude cllocation

每当位置发生变化时,CLLocationManager都会向我的委托发送新的CLLocation.该位置的坐标表示为CLLocationCoordinate2D对象,该对象仅包含纬度和经度.我想取这个位置,确定南纬1000米,西经1000度,北纬1000米,东经1000米的纬度和经度.这样我最终得到位于该位置西南方向的一个坐标和该位置的一个东北方向.

我不知道如何做到这一点,今晚我的GoogleFoo看起来很糟糕.我发现的哪些信息提供了难以理解的数学.有人帮助brotha黑客吗?如果有的话,我可以使用iOS API,但是只对doublelat和long的值进行操作的等式会更好.它不必在厘米内准确,但在米内会很好.理想情况下,它看起来像这样:

NSArray *rect = CalculateRectangleFromLocation(
    clLocationCoordinate2D,
    1000.0
);
Run Code Online (Sandbox Code Playgroud)

然后*rect将有四个值:西南角的纬度和长度以及东北角的纬度和长度.

小智 5

这是获取边界矩形的顶部/右侧/底部/左侧坐标的代码.

LatLon.h

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

extern double radians(double degrees);
extern double degrees(double radians);

extern CLLocationCoordinate2D LatLonDestPoint(CLLocationCoordinate2D origin, double brearing, CLLocationDistance distance);
Run Code Online (Sandbox Code Playgroud)

LatLon.m

const CLLocationDegrees kLatLonEarthRadius = 6371.0;

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

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

CLLocationCoordinate2D LatLonDestPoint(CLLocationCoordinate2D origin, double bearing, CLLocationDistance distance) {
    double brng = radians(bearing);
    double lat1 = radians(origin.latitude);
    double lon1 = radians(origin.longitude);

    CLLocationDegrees lat2 = asin(sin(lat1) * cos(distance / kLatLonEarthRadius) + 
                                  cos(lat1) * sin(distance / kLatLonEarthRadius) * cos(brng));
    CLLocationDegrees lon2 = lon1 + atan2(sin(brng) * sinf(distance / kLatLonEarthRadius) * cos(lat1),
                                                      cosf(distance / kLatLonEarthRadius) - sin(lat1) * sin(lat2));
    lon2 = fmod(lon2 + M_PI, 2.0 * M_PI) - M_PI;

    CLLocationCoordinate2D coordinate;
    if (! (isnan(lat2) || isnan(lon2))) {
        coordinate.latitude = degrees(lat2);
        coordinate.longitude = degrees(lon2);
    }

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

用法

CLLocationCoordinate2D location = ...;
double distance = ...;

CLLocationCoordinate2D right = LatLonDestPoint(location, 90.0, distance);
CLLocationDegrees rectRight = right.longitude;

CLLocationCoordinate2D top = LatLonDestPoint(location, 0.0, distance);
CLLocationDegrees rectTop = top.latitude;

CLLocationCoordinate2D left = LatLonDestPoint(location, 270.0, distance);
CLLocationDegrees rectLeft = left.longitude;

CLLocationCoordinate2D bottom = LatLonDestPoint(location, 180.0, distance);
CLLocationDegrees rectBottom = bottom.latitude;
Run Code Online (Sandbox Code Playgroud)

迅速

extension CLLocationCoordinate2D {
    fileprivate func radians(degrees: Double) -> Double { return degrees * .pi / 180.0 }
    fileprivate func degrees(radians: Double) -> Double { return radians * 180.0 / .pi }

    func coordinate(bearing: Double, distanceInMeter distance: CLLocationDistance) -> CLLocationCoordinate2D {
        let kLatLonEarthRadius: CLLocationDegrees = 6371.0
        let brng: Double = radians(degrees: bearing)
        let lat1: Double = radians(degrees: self.latitude)
        let lon1: Double = radians(degrees: self.longitude)

        let lat2: CLLocationDegrees = asin(
            sin(lat1) * cos(distance / kLatLonEarthRadius) +
            cos(lat1) * sin(distance / kLatLonEarthRadius) * cos(brng)
        )

        var lon2: CLLocationDegrees = lon1 + atan2(
            sin(brng) * sin(distance / kLatLonEarthRadius) * cos(lat1),
            cos(distance / kLatLonEarthRadius) - sin(lat1) * sin(lat2)
        )
        lon2 = fmod(lon2 + .pi, 2.0 * .pi) - .pi

        var coordinate = CLLocationCoordinate2D()
        if !lat2.isNaN && !lon2.isNaN {
            coordinate.latitude = degrees(radians: lat2)
            coordinate.longitude = degrees(radians: lon2)
        }
        return coordinate
    }

    func rect(distanceInMeter meter: CLLocationDistance) -> (north: Double, west: Double, south: Double, east: Double) {
        let north = coordinate(bearing: 0, distanceInMeter: meter).latitude
        let south = coordinate(bearing: 180, distanceInMeter: meter).latitude
        let east = coordinate(bearing: 90, distanceInMeter: meter).longitude
        let west = coordinate(bearing: 270, distanceInMeter: meter).longitude

        return (north: north, west: west, south: south, east: east)
    }
}
Run Code Online (Sandbox Code Playgroud)