Сопоставьте масштаб / границы карты MapKit с масштабом / границами карты RouteMe - PullRequest
5 голосов
/ 09 ноября 2011

РЕДАКТИРОВАТЬ: я считаю, что моя проблема заключается в том, что этот код работает для целочисленных уровней масштабирования, но я бы хотел, чтобы он работал для уровней с плавающей точкой. У меня есть приложение для 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];
}

1 Ответ

4 голосов
/ 20 ноября 2011

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

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

Несколько вариантовпо этому вопросу появились переполнения стека (например, MKMapView setRegion «привязывает» к предопределенным уровням масштабирования? и MKMapView показывают неправильно сохраненную область ), но пока никто не придумалпрограммный способ сделать карту с нецелым уровнем масштабирования, иЯ подозреваю, что для того, чтобы это произошло, понадобится сотрудничество между Google и Apple.

...