2011-11-09 5 views
5

EDIT: Я считаю, что моя проблема заключается в том, что этот код работает для целых уровней масштабирования, но я бы хотел, чтобы он работал для уровней масштабирования с плавающей точкой.Сопоставьте масштаб карты MapKit с масштабированием карты RouteMe

У меня есть приложение iOS, в котором пользователь может переключаться между картой на основе RouteMe и картой MapKit.

Когда они переключают источники, я хотел бы иметь возможность показывать ту же самую область в одном, что и в другом. Однако я не могу понять, как их сопоставить, потому что RouteMe и MapKit используют разные структуры данных для описания границ карт.

Вот несколько кодов, которые заставляют его быть близкими, но это не точно. Этот код исходит от: http://troybrant.net/blog/2010/01/set-the-zoom-level-of-an-mkmapview/

Я не уверен, должен ли этот код исправляться, или, возможно, я упускаю из виду гораздо более легкое решение. Код выполняется, начиная с последним методом, перечисленный:

#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

Одна вещь, которую я заметил о MKMapView, заключается в том, что если вы установите область и затем сразу ее прочитаете, вы получите разные значения. В нашем приложении я устанавливаю значение, которое запускает обратный вызов делегата, а затем я читаю новое значение и использую его, чтобы определить, где разместить наши оверлеи. Не уверен, что это поможет. :-( – EricS

ответ

4

К сожалению, это ограничение Google Maps API, который принимает только целые значения при определении уровня масштабирования карты: MapKit код компании Apple называют основной API Карт Google, когда вы установите отображаемую область MKMapView, и результат - независимо от того, какой метод MapKit вы используете для установки области, - это карта, которая уменьшена до ближайшего целочисленного уровня масштабирования.

Код Трой Бранта принимает вас на полный круг и помещает слой над API-интерфейсом MapKit, который позволяет вам установить уровень масштабирования напрямую ... но в конечном итоге у вас нет точного контроля над областью, отображаемой MKMapView, если только зум уровень вашей желаемой карты является целым числом.

Несколько вариантов этого вопроса появились в переполнении стека (например, MKMapView setRegion "snaps" to predefined zoom levels? и MKMapView show incorrectly saved region), но до сих пор никто не придумал программный способ сделать карту с нецелым уровнем масштабирования, и я подозреваю, что это «давайте сотрудничать между Google и Apple, чтобы это произошло».

+0

Хорошее изложение проблемы и отсутствие решения. Думаю, мне придется кое-что выяснить, так как в настоящее время это невозможно. Спасибо Скотту. –

Смежные вопросы