1

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

我不知道该怎么做,而且我的 GoogleFoo 今晚似乎很差。我发现的信息提供了难以理解的数学。有人帮助一个brotha黑客吗?如果有 iOS API,我可以使用 iOS API,但是仅对doublelat 和 long 值进行运算的方程式会更好。它不必精确到厘米,尽管在米内会很好。理想情况下,它看起来像这样:

NSArray *rect = CalculateRectangleFromLocation(
    clLocationCoordinate2D,
    1000.0
);

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

4

2 回答 2

5

这是获取边界矩形的上/右/下/左坐标的代码。

纬度

#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);

纬度

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;
}

用法

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;

迅速

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)
    }
}
于 2011-04-15T14:24:01.710 回答
0

我通常通过使用 PROJ4 库将纬度和经度转换为对我所在地区有用的以米为单位的投影来做到这一点(如果您没有更多信息,UTM 工作得很好,我在北加州,所以我所在地区的测量员都工作在 EPSG:2226 中),以米为单位添加适当的偏移量,然后使用 PROJ4 转换回来。

稍后编辑:下面 Jayant 给出的答案很好,具体取决于您的仪表矩形需要有多准确。地球不是球体,甚至不是扁球体,因此将距离与经纬度相加的投影可能很重要。即使使用 PROJ4,这些仪表也处于海平面。地理比你想象的要难。

于 2011-04-15T05:14:06.343 回答