Получение границ MKMapView
Чтобы настроить запрос на внешний сервер, я хочу получить границы текущего вида карты в приложении iPhone, которое я создаю. UIView должен реагировать на ограничения, но, похоже, MKMapView этого не делает. После настройки области и масштабирования на карте я пытаюсь получить границы. Я застрял на первом шаге, чтобы попытаться получить CGPoints, представляющие углы карты SE и NW. После этого я собирался использовать:
- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view
Чтобы преобразовать точки в координаты карты. Но я даже не могу зайти так далеко...
//Recenter and zoom map in on search location
MKCoordinateRegion region = {{0.0f, 0.0f}, {0.0f, 0.0f}};
region.center = mySearchLocation.searchLocation.coordinate;
region.span.longitudeDelta = 0.01f;
region.span.latitudeDelta = 0.01f;
[self.mapView setRegion:region animated:YES];
//After the new search location has been added to the map, and the map zoomed, we need to update the search bounds
//First we need to calculate the corners of the map
CGPoint se = CGPointMake(self.mapView.bounds.origin.x, mapView.bounds.origin.y);
CGPoint nw = CGPointMake((self.mapView.bounds.origin.x + mapView.bounds.size.width), (mapView.bounds.origin.y + mapView.bounds.size.height));
NSLog(@"points are: se %@, nw %@", se, nw);
Код компилируется без предупреждений, однако se и nw равны нулю. Глядя на self.mapView.bounds.origin.x, переменная равна 0. Попытка NSLog непосредственно self.mapView.bounds.size.width дает мне "Программный полученный сигнал:" EXC_BAD_ACCESS "." который, как представляется, поступает из NSLog.
Кто-нибудь знает правильный способ получить юго-восточный угол и северо-западный угол (в координатах карты) из видимой области MKMapView?
РЕДАКТ: Кажется, что когда вы что-то задали, ответ приходит сразу после вас. Я использовал% @вместо @f для печати каждой переменной в NSLog, которая там бросала ошибки. Я также обнаружил свойство annotationVisibleRect для MKMapview. Кажется, что annotationVisibleRect основан на координатах родительского представления.
Ответы
Ответ 1
Хорошо, я официально ответил на свой вопрос, но так как я не нашел его нигде, прежде чем я отправлю ответ здесь:
//To calculate the search bounds...
//First we need to calculate the corners of the map so we get the points
CGPoint nePoint = CGPointMake(self.mapView.bounds.origin.x + mapView.bounds.size.width, mapView.bounds.origin.y);
CGPoint swPoint = CGPointMake((self.mapView.bounds.origin.x), (mapView.bounds.origin.y + mapView.bounds.size.height));
//Then transform those point into lat,lng values
CLLocationCoordinate2D neCoord;
neCoord = [mapView convertPoint:nePoint toCoordinateFromView:mapView];
CLLocationCoordinate2D swCoord;
swCoord = [mapView convertPoint:swPoint toCoordinateFromView:mapView];
Ответ 2
Другой вариант - использовать свойство visibleMapRect в экземпляре MKMapView и использовать MKCoordinateForMapPoint() для преобразования в lat/lon.
MKMapRect mRect = self.mapView.visibleMapRect;
MKMapPoint neMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), mRect.origin.y);
MKMapPoint swMapPoint = MKMapPointMake(mRect.origin.x, MKMapRectGetMaxY(mRect));
CLLocationCoordinate2D neCoord = MKCoordinateForMapPoint(neMapPoint);
CLLocationCoordinate2D swCoord = MKCoordinateForMapPoint(swMapPoint);
Ответ 3
Сдвиг... (на основе ответа @deadroxy...)
typealias Edges = (ne: CLLocationCoordinate2D, sw: CLLocationCoordinate2D)
extension MKMapView {
func edgePoints() -> Edges {
let nePoint = CGPoint(x: self.bounds.maxX, y: self.bounds.origin.y)
let swPoint = CGPoint(x: self.bounds.minX, y: self.bounds.maxY)
let neCoord = self.convertPoint(nePoint, toCoordinateFromView: self)
let swCoord = self.convertPoint(swPoint, toCoordinateFromView: self)
return (ne: neCoord, sw: swCoord)
}
}
Ответ 4
Этот http://wiki.openstreetmap.org/wiki/Bounding_Box является документом для ограничительной рамки
bbox = left,bottom,right,top
bbox = min Longitude , min Latitude , max Longitude , max Latitude
![enter image description here]()
Вы можете иметь структуру BoundingBox
которая представляет это
struct BoundingBox {
let min: CLLocationCoordinate2D
let max: CLLocationCoordinate2D
init(rect: MKMapRect) {
let bottomLeft = MKMapPointMake(rect.origin.x, MKMapRectGetMaxY(rect))
let topRight = MKMapPointMake(MKMapRectGetMaxX(rect), rect.origin.y)
min = MKCoordinateForMapPoint(bottomLeft)
max = MKCoordinateForMapPoint(topRight)
}
var points: [CLLocationDegrees] {
return [
min.latitude,
min.longitude,
max.latitude
max.longitude,
]
}
}
visibleMapRect
такой же, как region.span
let mapView = MKMapView(frame: CGRect(x: 0, y: 0, width: 320, height: 640))
XCTAssertEqual(mapView.userLocation.coordinate.latitude, 0)
XCTAssertEqual(mapView.userLocation.coordinate.longitude, 0)
let boundingBox = BoundingBox(rect: mapView.visibleMapRect)
XCTAssertEqual(boundingBox.max.longitude-boundingBox.min.longitude, mapView.region.span.longitudeDelta)
XCTAssertEqual(boundingBox.max.latitude-boundingBox.min.latitude, mapView.region.span.latitudeDelta)
Ответ 5
Мне удалось заставить это работать с запросом Parse GeoBox:
//Calculate the corners of the map to get the points
CGPoint nePoint = CGPointMake(self.mapView.bounds.origin.x + self.mapView.bounds.size.width, self.mapView.bounds.origin.y);
CGPoint swPoint = CGPointMake((self.mapView.bounds.origin.x),(self.mapView.bounds.origin.y+ self.mapView.bounds.size.height));
//Transform points into lat/long values
CLLocationCoordinate2D NECoordinate = [self.mapView convertPoint:nePoint toCoordinateFromView:self.mapView];
CLLocationCoordinate2D SWCoordinate = [self.mapView convertPoint:swPoint toCoordinateFromView:self.mapView];
//Convert to Parse GeoPoints
PFGeoPoint *Southwest = [PFGeoPoint geoPointWithLatitude:SWCoordinate.latitude longitude:SWCoordinate.longitude];
PFGeoPoint *Northeast = [PFGeoPoint geoPointWithLatitude:NECoordinate.latitude longitude:NECoordinate.longitude];
Ответ 6
этот сайт решает проблему.
http://www.softwarepassion.com/how-to-get-geographic-coordinates-of-the-visible-mkmapview-area-in-ios/
MKMapRect mRect = self.mapView.visibleMapRect;
-(CLLocationCoordinate2D)getNECoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:MKMapRectGetMaxX(mRect) y:mRect.origin.y];
}
-(CLLocationCoordinate2D)getNWCoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:MKMapRectGetMinX(mRect) y:mRect.origin.y];
}
-(CLLocationCoordinate2D)getSECoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:MKMapRectGetMaxX(mRect) y:MKMapRectGetMaxY(mRect)];
}
-(CLLocationCoordinate2D)getSWCoordinate:(MKMapRect)mRect{
return [self getCoordinateFromMapRectanglePoint:mRect.origin.x y:MKMapRectGetMaxY(mRect)];
}
-(CLLocationCoordinate2D)getCoordinateFromMapRectanglePoint:(double)x y:(double)y{
MKMapPoint swMapPoint = MKMapPointMake(x, y);
return MKCoordinateForMapPoint(swMapPoint);
}
-(NSArray *)getBoundingBox:(MKMapRect)mRect{
CLLocationCoordinate2D bottomLeft = [self getSWCoordinate:mRect];
CLLocationCoordinate2D topRight = [self getNECoordinate:mRect];
return @[[NSNumber numberWithDouble:bottomLeft.latitude ],
[NSNumber numberWithDouble:bottomLeft.longitude],
[NSNumber numberWithDouble:topRight.latitude],
[NSNumber numberWithDouble:topRight.longitude]];
}
Ответ 7
Это расширение решает эту проблему и поддерживает синтаксис centerCoordinate
в Swift 5
extension MKMapView {
var northWestCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.minX, y: visibleMapRect.minY).coordinate
}
var northEastCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.maxX, y: visibleMapRect.minY).coordinate
}
var southEastCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.maxX, y: visibleMapRect.maxY).coordinate
}
var southWestCoordinate: CLLocationCoordinate2D {
return MKMapPoint(x: visibleMapRect.minX, y: visibleMapRect.maxY).coordinate
}
}
Ответ 8
Этот код работает с поворотом карты, как 90/180 градусов.
set mapView.pitchEnabled = НЕТ; для меньших ошибок.
CLLocationDirection heading = mapView.camera.heading;
float mapWidth = mapView.frame.size.width;
float mapHeight = mapView.frame.size.height;
float neX = mapWidth;
float neY = 0.0;
float swX = 0.0;
float swY = mapHeight;
if (heading >= 0 && heading <= 90) {
//println("Q1")
float ratio = heading / 90;
neX = (1-ratio) * mapWidth;
swX = (mapWidth*ratio);
} else if (heading >= 90 && heading <= 180) {
//println("Q2")
float ratio = (heading - 90) / 90;
neX = 0;
neY = (mapHeight*ratio);
swY = (1-ratio) * mapHeight;
swX = mapWidth;
} else if (heading >= 180 && heading <= 270) {
//println("Q3")
float ratio = (heading - 180) / 90;
neX = mapWidth*ratio;
neY = mapHeight;
swX = (1-ratio) * mapWidth;
swY = 0;
} else if (heading >= 270 && heading <= 360) {
//println("Q4");
float ratio = (heading - 270) / 90;
neX = mapWidth;
neY = (1-ratio) * mapHeight;
swY = ratio * mapHeight;
}
CGPoint swPoint = CGPointMake(swX, swY);
CGPoint nePoint = CGPointMake(neX, neY);
CLLocationCoordinate2D swCoord = [mapView convertPoint:swPoint toCoordinateFromView:mapView];
CLLocationCoordinate2D neCoord = [mapView convertPoint:nePoint toCoordinateFromView:mapView];
Ответ 9
У меня были некоторые проблемы с некоторыми другими ответами для карт, которые были повернуты на 2 пальца. Этот код работал для меня:
MKMapRect rect = self.mapView.visibleMapRect;
CLLocationCoordinate2D northeast = MKCoordinateForMapPoint(MKMapPointMake(MKMapRectGetMaxX(rect),rect.origin.y));
CLLocationCoordinate2D southwest = MKCoordinateForMapPoint(MKMapPointMake(rect.origin.x ,MKMapRectGetMaxY(rect)));
Мой ответ получен из ответа and 保 状, и соответствующий веб-сайт введите ссылку здесь. Она также упрощена на 3 линии для юго-западных и северо-восточных углов.
Ответ 10
Обновленный @onmyway133 отличный ответ для моих целей, мне были нужны координаты всех четырех углов:
struct BoundingBox {
let topRight: CLLocationCoordinate2D
let topLeft: CLLocationCoordinate2D
let bottomRight: CLLocationCoordinate2D
let bottomLeft: CLLocationCoordinate2D
init(rect: MKMapRect) {
topRight = MKMapPoint(x: rect.maxX, y: rect.origin.y).coordinate
topLeft = MKMapPoint(x: rect.origin.x, y: rect.origin.y).coordinate
bottomRight = MKMapPoint(x: rect.maxX, y: rect.maxY).coordinate
bottomLeft = MKMapPoint(x: rect.origin.x, y: rect.maxY).coordinate
}
var items: [String: CLLocationCoordinate2D] {
return [
"topRight": topRight,
"topLeft": topLeft,
"bottomRight": bottomRight,
"bottomLeft": bottomLeft,
]
}
var points: [CLLocationDegrees] {
return [
topRight.latitude,
topRight.longitude,
topLeft.latitude,
topLeft.longitude,
bottomRight.latitude,
bottomRight.longitude,
bottomLeft.latitude,
bottomLeft.longitude,
]
}
}
И пример того, как я использовал эти данные:
let boundingBox = BoundingBox(rect: mapView.visibleMapRect)
var annotations = Array<MKPointAnnotation>()
for point in boundingBox.items {
let newPoint = MKPointAnnotation()
newPoint.coordinate = point.value
annotations.append(newPoint)
}
mapView.addAnnotations(annotations)