2011-11-09 13 views
5

EDIT: Creo que mi problema es que este código funciona para niveles enteros de zoom, pero me gustaría que funcione para niveles de zoom flotante.Coincidir con el zoom/límites de un mapa MapKit con el zoom/límites de un mapa RouteMe

Tengo una aplicación iOS en la que el usuario puede alternar entre un mapa basado en RouteMe y un mapa basado en MapKit.

Cuando cambian de fuente, me gustaría poder mostrar exactamente la misma área en una que en la otra. Sin embargo, no puedo encontrar la manera de hacer que coincidan porque RouteMe y MapKit usan diferentes estructuras de datos para describir los límites del mapa.

Aquí hay un código que lo acerca un poco, pero no es exacto. Este código viene de: http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/

No estoy seguro de si este código debe ser reparado, o posiblemente estoy pasando por alto una solución mucho más fácil. El código se ejecuta comenzando por el último método que figura:

#define MERCATOR_OFFSET 268435456 
#define MERCATOR_RADIUS 85445659.44705395 

#pragma mark - 
#pragma mark Map conversion methods 

- (double)longitudeToPixelSpaceX:(double)longitude { 
    return round(MERCATOR_OFFSET + MERCATOR_RADIUS * longitude * M_PI/180.0); 
} 

- (double)latitudeToPixelSpaceY:(double)latitude { 
    return round(MERCATOR_OFFSET - MERCATOR_RADIUS * logf((1 + sinf(latitude * M_PI/180.0))/(1 - sinf(latitude * M_PI/180.0)))/2.0); 
} 

- (double)pixelSpaceXToLongitude:(double)pixelX { 
    return ((round(pixelX) - MERCATOR_OFFSET)/MERCATOR_RADIUS) * 180.0/M_PI; 
} 

- (double)pixelSpaceYToLatitude:(double)pixelY { 
    return (M_PI/2.0 - 2.0 * atan(exp((round(pixelY) - MERCATOR_OFFSET)/MERCATOR_RADIUS))) * 180.0/M_PI; 
} 


- (MKCoordinateSpan)coordinateSpanWithMapView:(MKMapView *)mapView 
          centerCoordinate:(CLLocationCoordinate2D)centerCoordinate 
           andZoomLevel:(NSInteger)zoomLevel { 
    // convert center coordiate to pixel space 
    double centerPixelX = [self longitudeToPixelSpaceX:centerCoordinate.longitude]; 
    double centerPixelY = [self latitudeToPixelSpaceY:centerCoordinate.latitude]; 

    // determine the scale value from the zoom level 
    NSInteger zoomExponent = 20 - zoomLevel; 
    double zoomScale = pow(2, zoomExponent); 

    // scale the map’s size in pixel space 
    CGSize mapSizeInPixels = mapView.bounds.size; 
    double scaledMapWidth = mapSizeInPixels.width * zoomScale; 
    double scaledMapHeight = mapSizeInPixels.height * zoomScale; 

    // figure out the position of the top-left pixel 
    double topLeftPixelX = centerPixelX - (scaledMapWidth/2); 
    double topLeftPixelY = centerPixelY - (scaledMapHeight/2); 

    // find delta between left and right longitudes 
    CLLocationDegrees minLng = [self pixelSpaceXToLongitude:topLeftPixelX]; 
    CLLocationDegrees maxLng = [self pixelSpaceXToLongitude:topLeftPixelX + scaledMapWidth]; 
    CLLocationDegrees longitudeDelta = maxLng - minLng; 

    // find delta between top and bottom latitudes 
    CLLocationDegrees minLat = [self pixelSpaceYToLatitude:topLeftPixelY]; 
    CLLocationDegrees maxLat = [self pixelSpaceYToLatitude:topLeftPixelY + scaledMapHeight]; 
    CLLocationDegrees latitudeDelta = -1 * (maxLat - minLat); 

    // create and return the lat/lng span 
    MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta); 
    return span; 
} 


- (void)setCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate 
        zoomLevel:(NSUInteger)zoomLevel 
        animated:(BOOL)animated { 

    // use the zoom level to compute the region 
    MKCoordinateSpan span = [self coordinateSpanWithMapView:self  
           centerCoordinate:centerCoordinate 
            andZoomLevel:zoomLevel]; 
    MKCoordinateRegion region = MKCoordinateRegionMake(centerCoordinate, span); 

    // set the region like normal 
    [self setRegion:region animated:animated]; 
} 
+0

Una cosa que he notado sobre MKMapView es que si configura la región y luego la vuelve a leer inmediatamente, obtendrá valores diferentes. En nuestra aplicación, establezco el valor que desencadena una devolución de llamada de delegado y luego leo el nuevo valor y lo uso para determinar dónde colocar nuestras superposiciones. No estoy seguro si esto ayuda. :-( – EricS

Respuesta

4

Por desgracia, esta es una limitación de la Google Maps API, que sólo acepta valores enteros hora de establecer el nivel de zoom del mapa: Código MapKit de Apple está llamando a los subyacentes API de Google Maps Al configure el área mostrada de MKMapView, y el resultado, sin importar qué método de MapKit use para establecer el área, es un mapa que se alejó al nivel de zoom entero más cercano.

El código de Troy Brant le da un círculo completo y pone una capa encima de las API de MapKit que le permite establecer el nivel de zoom directamente ... pero finalmente no tiene control preciso sobre el área mostrada por un MKMapView, a menos el nivel del mapa deseado es un número entero.

Varias variaciones de esta pregunta han aparecido en Stack Overflow (p. Ej., MKMapView setRegion "snaps" to predefined zoom levels? y MKMapView show incorrectly saved region), pero hasta ahora nadie ha encontrado una forma programática de hacer un mapa con un nivel de zoom no entero, y sospecho Tomaría la cooperación entre Google y Apple para lograrlo.

+0

Buen resumen del problema y la falta de solución. Supongo que tendré que pensar en algo más, ya que actualmente no es posible. Gracias, Scott. –