2010-01-17 15 views
28

Para configurar una consulta a un servidor externo, quiero obtener los límites de la vista de mapa actual en una aplicación de iPhone que estoy construyendo. UIView debe responder a los límites, pero parece que MKMapView no lo hace. Después de establecer una región y hacer zoom en el mapa, intento obtener los límites. Estoy atascado en el primer paso, que es tratar de obtener los CGPoints que representan las esquinas SE y NW del mapa. Después de eso iba a usar:Obtener los límites de un MKMapView

- (CLLocationCoordinate2D)convertPoint:(CGPoint)point toCoordinateFromView:(UIView *)view 

Para transformar los puntos en coordenadas del mapa. Pero no puedo ni siquiera llegar tan lejos ...

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

El código se compila sin advertencias sin embargo se y nw son ambos nulos. Al mirar a self.mapView.bounds.origin.x, la variable es 0. Intentar con NSLog directamente self.mapView.bounds.size.width me da una "Señal de programa recibida:" EXC_BAD_ACCESS "." que parece provenir de NSLog.

¿Alguien sabe la manera correcta de obtener la esquina sureste y la esquina noroeste (en las coordenadas del mapa) desde el área visible de un MKMapView?

EDIT: Parece que cada vez que preguntas algo aquí la respuesta viene a ti justo después. Estaba usando% @ en lugar de @f para imprimir cada variable en NSLog que estaba arrojando errores allí. También descubrí la propiedad annotationVisibleRect de MKMapview. Sin embargo, parece que el annotationVisibleRect se basa en las coordenadas de vista principal.

Respuesta

72

Está bien que respondió oficialmente a mi propia pregunta, pero ya que no he encontrado en cualquier lugar antes de que voy a publicar la respuesta aquí:

//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

Otra opción es utilizar la propiedad visibleMapRect en su instancia MKMapView y el uso MKCoordinateForMapPoint() para convertir a 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

Además, en lugar de calcular la coordenadas X e Y sí mismo que puede utilizar las funciones de confort 'MKMapRectGetMaxX (mRect)' (y similares). – neilkimmett

+3

Vale la pena señalar que visibleMapRect es fiel a su nombre y solo devuelve la parte visible del mapa. En nuestra aplicación, tenemos una UIView deslizable que viene sobre MapView cuando se selecciona un elemento. Cuando esto sale, visibleMapRect solo devuelve la parte del mapa que todavía está visible. En nuestra instancia, necesitábamos todos los límites, por lo que la solución @deadroxy funcionó mejor para nosotros. – joneswah

+0

@joneswah me alegro de que esta solución todavía sea un clásico:] ¡gracias! – deadroxy

1

pude conseguir que esto funcione con la consulta Analizar 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 distancia ... (basado en la respuesta de @ 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

¿cómo puedo usar esto en mi controlador de vista? –

+0

@QadirHussain una vez que agregue esto a su proyecto puede llamar 'self.myMapView.edgePoints()' que le devolverá la tupla con los parámetros 'ne' y' sw' (como definí en 'typealias') –

+0

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

0

Este código funciona con un mapa que gira como 90/180 grados. establecer mapView.pitchEnabled = NO; por menos errores.

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

Este http://wiki.openstreetmap.org/wiki/Bounding_Box es un documento para la caja

bbox = left,bottom,right,top 
bbox = min Longitude , min Latitude , max Longitude , max Latitude 

enter image description here

saltando Usted puede tener una estructura BoundingBox que representa este

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

El visibleMapRect es la misma que 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) 

Tenga en cuenta que viene antes longlat en la tupla (long,lat)

1

este sitio web resolver el problema. 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]]; 
} 
Cuestiones relacionadas