我正在使用GoogleMaps软件开发工具包,目前我正在尝试将GMSVisibleRegion转换为CLRegion。
GMSVisibleRegion定义为:
typedef struct {
CLLocationCoordinate2D nearLeft;
CLLocationCoordinate2D nearRight;
CLLocationCoordinate2D farLeft;
CLLocationCoordinate2D farRight;
} GMSVisibleRegion;执行此操作的最快方法是什么?
不幸的是,很难理解开发人员命名“近”和“远”是什么意思。我认为这条评论也很有用:
/**
* Returns the region (four location coordinates) that is visible according to
* the projection.
*
* The visible region can be non-rectangular. The result is undefined if the
* projection includes points that do not map to anywhere on the map (e.g.,
* camera sees outer space).
*/
- (GMSVisibleRegion)visibleRegion;非常感谢!
编辑:好的,我的第一步是创建一个GMSVisibleRegion的MKCoordinateRegion。
我建议使用以下代码将GMSVisibleRegion转换为MKCoordinateRegion。任何反对意见。
+ (MKCoordinateRegion)regionForCenter:(CLLocationCoordinate2D)center andGMSVisibleRegion:(GMSVisibleRegion)visibleRegion
{
CLLocationDegrees latitudeDelta = visibleRegion.farLeft.latitude - visibleRegion.nearLeft.latitude;
CLLocationDegrees longitudeDelta = visibleRegion.farRight.longitude - visibleRegion.farLeft.longitude;
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
return MKCoordinateRegionMake(center, span);
}发布于 2013-03-05 08:25:09
我猜“near”是指屏幕底部的视图角落,而“far”是指屏幕顶部的角落。这是因为如果您倾斜了视图,则底部角距离摄影机最近,而顶部角距离摄影机最远。
将其转换为CLRegion的一种方法可能是使用相机的目标作为中心,然后计算从最大距离到四个角的半径。这可能不是该区域上最紧密的拟合圆,但由于圆无论如何都不能拟合视图的四边形,所以它可能足够接近。
下面是一个辅助函数,用于计算两个CLLocationCoordinate值之间以米为单位的距离:
double getDistanceMetresBetweenLocationCoordinates(
CLLocationCoordinate2D coord1,
CLLocationCoordinate2D coord2)
{
CLLocation* location1 =
[[CLLocation alloc]
initWithLatitude: coord1.latitude
longitude: coord1.longitude];
CLLocation* location2 =
[[CLLocation alloc]
initWithLatitude: coord2.latitude
longitude: coord2.longitude];
return [location1 distanceFromLocation: location2];
}然后,可以这样计算CLRegion:
GMSMapView* mapView = ...;
...
CLLocationCoordinate2D centre = mapView.camera.target;
GMSVisibleRegion* visibleRegion = mapView.projection.visibleRegion;
double nearLeftDistanceMetres =
getDistanceMetresBetweenLocationCoordinates(centre, visibleRegion.nearLeft);
double nearRightDistanceMetres =
getDistanceMetresBetweenLocationCoordinates(centre, visibleRegion.nearRight);
double farLeftDistanceMetres =
getDistanceMetresBetweenLocationCoordinates(centre, visibleRegion.farLeft);
double farRightDistanceMetres =
getDistanceMetresBetweenLocationCoordinates(centre, visibleRegion.farRight);
double radiusMetres =
MAX(nearLeftDistanceMetres,
MAX(nearRightDistanceMetres,
MAX(farLeftDistanceMetres, farRightDistanceMetres)));
CLRegion region = [[CLRegion alloc]
initCircularRegionWithCenter: centre radius: radius identifier: @"id"];更新:
关于您的MKCoordinateRegion更新,您的示例代码可能无法工作。如果地图旋转了90度,那么farLeft和nearLeft将具有相同的纬度,farRight和farLeft将具有相同的经度,因此您的纬度和经度差值将为零。
您需要遍历farLeft、farRight、nearLeft、nearRight中的所有四个,计算每一个的纬度和经度的最小和最大值,然后从中计算增量。
Google Maps SDK for iOS包含一个helper类,它已经为您完成了其中的一些工作-- GMSCoordinateBounds。它可以使用GMSVisibleRegion进行初始化
GMSMapView* mapView = ...;
....
GMSVisibleRegion visibleRegion = mapView.projection.visibleRegion;
GMSCoordinateBounds bounds =
[[GMSCoordinateBounds alloc] initWithRegion: visibleRegion];然后,GMSCoordinateBounds具有定义边界的northEast和southWest属性。因此,您可以按如下方式计算增量:
CLLocationDegrees latitudeDelta =
bounds.northEast.latitude - bounds.southWest.latitude;
CLLocationDegrees longitudeDelta =
bounds.northEast.longitude - bounds.southWest.longitude;您还可以从边界计算中心,从而计算MKCoordinateRegion
CLLocationCoordinate2D centre = CLLocationCoordinate2DMake(
(bounds.southWest.latitude + bounds.northEast.latitude) / 2,
(bounds.southWest.longitude + bounds.northEast.longitude) / 2);
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
return MKCoordinateRegionMake(centre, span);发布于 2013-05-16 20:40:59
纯粹主义者附录
如果你想要绝对严谨,你需要在国际日期变更线周围做一个修正。这在大多数应用程序中都是浪费精力的,但这个问题最近一直给我带来很大的痛苦,所以我想把它扔到社区帽子里去
基于Druce的更新(恐怕我不能发表评论)。
GMSMapView* mapView = ...;
....
GMSVisibleRegion visibleRegion = mapView.projection.visibleRegion;
GMSCoordinateBounds bounds =
[[GMSCoordinateBounds alloc] initWithRegion: visibleRegion];Latitude不需要对它做任何操作
CLLocationDegrees latitudeDelta =
bounds.northEast.latitude - bounds.southWest.latitude;根据协议,一个跨越国际日期变更线的地区可能在日本有southWest角(+140经度),在阿拉斯加有northEast角(-150经度)。加起来再除以2得出的是地球另一边的一个点。
northEast.longitude小于southWest.longitude的特殊情况需要处理
CLLocationCoordinate2D centre;
CLLocationDegrees longitudeDelta;
if(bounds.northEast.longitude >= bounds.southWest.longitude) {
//Standard case
centre = CLLocationCoordinate2DMake(
(bounds.southWest.latitude + bounds.northEast.latitude) / 2,
(bounds.southWest.longitude + bounds.northEast.longitude) / 2);
longitudeDelta = bounds.northEast.longitude - bounds.southWest.longitude;
} else {
//Region spans the international dateline
centre = CLLocationCoordinate2DMake(
(bounds.southWest.latitude + bounds.northEast.latitude) / 2,
(bounds.southWest.longitude + bounds.northEast.longitude + 360) / 2);
longitudeDelta = bounds.northEast.longitude + 360
- bounds.southWest.longitude;
}
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
return MKCoordinateRegionMake(centre, span);发布于 2014-05-22 21:31:08
对于任何基于目前提供的所有答案和更正来寻找样板代码的人,这里是作为GMSMapView上的一个类别实现的region:
//
// GMSMapViewExtensions.h
//
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import <GoogleMaps/GoogleMaps.h>
@interface GMSMapView (GMSMapViewExtensions)
@end和
//
// GMSMapViewExtensions.m
//
#import "GMSMapViewExtensions.h"
@implementation GMSMapView (GMSMapViewExtensions)
- (MKCoordinateRegion) region {
GMSVisibleRegion visibleRegion = self.projection.visibleRegion;
GMSCoordinateBounds * bounds = [[GMSCoordinateBounds alloc] initWithRegion: visibleRegion];
CLLocationDegrees latitudeDelta = bounds.northEast.latitude - bounds.southWest.latitude;
CLLocationCoordinate2D centre;
CLLocationDegrees longitudeDelta;
if (bounds.northEast.longitude >= bounds.southWest.longitude) {
// Standard case
centre = CLLocationCoordinate2DMake(
(bounds.southWest.latitude + bounds.northEast.latitude) / 2,
(bounds.southWest.longitude + bounds.northEast.longitude) / 2);
longitudeDelta = bounds.northEast.longitude - bounds.southWest.longitude;
} else {
// Region spans the international dateline
centre = CLLocationCoordinate2DMake(
(bounds.southWest.latitude + bounds.northEast.latitude) / 2,
(bounds.southWest.longitude + bounds.northEast.longitude + 360) / 2);
longitudeDelta = bounds.northEast.longitude + 360 - bounds.southWest.longitude;
}
MKCoordinateSpan span = MKCoordinateSpanMake(latitudeDelta, longitudeDelta);
return MKCoordinateRegionMake(centre, span);
}
- (MKMapRect)visibleMapRect {
MKCoordinateRegion region = [self region];
MKMapPoint a = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
region.center.latitude + region.span.latitudeDelta / 2,
region.center.longitude - region.span.longitudeDelta / 2));
MKMapPoint b = MKMapPointForCoordinate(CLLocationCoordinate2DMake(
region.center.latitude - region.span.latitudeDelta / 2,
region.center.longitude + region.span.longitudeDelta / 2));
return MKMapRectMake(MIN(a.x, b.x), MIN(a.y, b.y), ABS(a.x - b.x), ABS(a.y - b.y));
}
@end使用示例:
GMSMapView * mapView = .... // init code
MKCoordinateRegion mapRegion = mapView.region;https://stackoverflow.com/questions/15208181
复制相似问题