Вот код для получения верхних / правых / нижних / левых координат ограничительного прямоугольника.
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);
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;
}
Использование
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;
Swift
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)
}
}