2010-01-17 6 views
28

Чтобы настроить запрос на внешний сервер, я хочу получить границы текущего вида карты в приложении iPhone, которое я создаю. UIView должен реагировать на ограничения, но, похоже, MKMapView этого не делает. После настройки области и масштабирования на карте я пытаюсь получить границы. Я застрял на первом шаге, чтобы попытаться получить CGPoints, представляющие углы карты SE и NW. После этого я собирался использовать:Получение границ MKMapView

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

код компилируется без предупреждений, однако как таковые и северо-запад оба нуль. Глядя на self.mapView.bounds.origin.x, переменная равна 0. Попытка NSLog непосредственно self.mapView.bounds.size.width дает мне «Программный полученный сигнал:« EXC_BAD_ACCESS ».» который, как представляется, поступает из NSLog.

Кто-нибудь знает подходящий способ получить юго-восточный угол и северо-западный угол (в координатах карты) из видимой области MKMapView?

EDIT: Кажется, что когда вы что-то задали, ответ приходит к вам сразу после. Я использовал% @ вместо @f для печати каждой переменной в NSLog, которая там бросала ошибки. Я также обнаружил свойство annotationVisibleRect для MKMapview. Кажется, что annotationVisibleRect основан на координатах родительского представления.

ответ

72

Хорошо я официально ответил на мой собственный вопрос, но так как я не нашел его где-нибудь, прежде чем я отправлю ответ здесь:

//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]; 
36

Другим вариантом является использование свойства 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); 
+1

Кроме того, вместо вычисления координаты х и у себя, вы можете использовать 'удобные функции MKMapRectGetMaxX (mRect)' (и подобные). – neilkimmett

+3

Стоит отметить, что visibleMapRect верен своему имени и возвращает только видимую часть карты. В нашем приложении у нас есть слайдер UIView, который появляется над MapView при выборе элемента. Когда это выходит, visibleMapRect возвращает только ту часть карты, которая все еще видна. В нашем случае нам нужны были все границы, поэтому решение @deadroxy работало лучше для нас. – joneswah

+0

@joneswah рад, что это решение по-прежнему классическое:] спасибо! – deadroxy

1

Я был в состоянии получить эту работу с запросом Анализировать 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]; 
9

Swift далеко ... (на основе @ 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) 
    } 
} 
+0

Как я могу использовать это в контроллере? –

+0

@QadirHussain, как только вы добавите это в свой проект, вы можете вызвать 'self.myMapView.edgePoints()', который вернет вам кортеж с параметрами 'ne' и' sw' (как я определил в 'typealias') –

+0

' var edgePoints = mapView.edgePoints() '' print (edgePoints.ne.latitude) '' print (edgePoints.ne.longitude) '' print (edgePoints.sw.longitude) '' print (edgePoints.sw.latitude) ' – webjunkie

0

Этот код работает с поворотом карты, как 90/180 градусов. set mapView.pitchEnabled = NO; за меньшие ошибки.

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]; 
1

Это 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.longitude, 
     min.latitude, 
     max.longitude, 
     max.latitude 
    ] 
    } 
} 

В 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) 

Обратите внимание, что long предшествует lat в кортеже (long,lat)

1

этот сайт решить эту проблему. 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]]; 
} 
Смежные вопросы