我搜索了很多答案&我无法想象这种方法不存在!! 我有一个MKTileOverlayPath(x,y& z),也能够得到这个矩形中心的lon / lat。 现在我需要得到每个矩形的跨度,这可能吗?
答案 0 :(得分:9)
是的,虽然只有MapKit并不完全明显。
Tiles&叠加路径在网格系统中定义,其中(方形)地图一侧的点数等于2^z * 256
,因为默认屏幕平铺大小为256px
平方。 z0
是一个256px
正方形图块,z1
是四个图块,总面积为512px
正方形等。此系统中的图块坐标是线性的(正方形中的所有正方形)地图)。
MKMapPoint
源自z20
,因此MKMapSizeWorld
一侧是268,435,456
个地图点。如果你做数学,2^20 * 256 = 268,435,456
。地图点也是线性的(方形图中的像素/点)。
纬度和经度当然不是线性的,因为这是一个投影表示,这就是为什么你有像MKMetersPerMapPointAtLatitude()
这样的函数。
如果您有以下MKTileOverlayPath
:
z = 10
x = 12
y = 8
您知道世界磅值是2^10 * 256 = 262,144
,而世界是2^10 = 1,024
平铺的一面。
图块的左边缘为256 * 12 = 3,072
个点,顶边为256 * 8 = 2,048
个点。这些与z10
相关,比268,435,456 / 262,144 = 1,024
小z20
倍。
这是MKMapPoint
的{{1}}。
右下角类似{ x: (3,072 * 1,024 = 3,145,728), y: (2,048 * 1,024 = 2,097,152) }
(将瓷砖的大小{ x: 3,407,872, y: 2,359,296 }
添加到每个)。
您可以在每个256 * 1,024 = 262,144
上使用MKCoordinateForMapPoint()
来获取CLLocationCoordinate2D
,并减去差异以获得MKCoordinateSpan
。
{ latitude: 84.8024737243345, longitude: -175.78125 }
{ latitude: 84.7705283207591, longitude: -175.4296875 }
{ latitudeDelta: 0.0319454035754205, longitudeDelta: 0.3515625 }
是的,这些点非常靠近地图左上角的阿拉斯加地区,但这是合乎逻辑的,因为x = 12
和y = 8
来自左上角的1,024
个瓷砖。
@interface GridTileOverlay : MKTileOverlay
@end
@implementation GridTileOverlay
-(void)loadTileAtPath:(MKTileOverlayPath)path result:(void (^)(NSData *, NSError *))result {
NSLog(@"Loading tile x/y/z: %ld/%ld/%ld",(long)path.x,(long)path.y,(long)path.z);
int worldPointSize = pow(2,(int)path.z)*256; // 2^10 * 256 = 262,144
int tilesOnASide = pow(2,(int)path.z); // 2^10 = 1,024
long leftEdge = path.x *256; // 256 * 12 = 3,072 points
long topEdge = path.y *256; // 256 * 8 = 2,048
int w = self.boundingMapRect.size.width; // 2^20 * 256 = 268,435,456
int zScale = w / worldPointSize; // 268,435,456 / 262,144 = 1,024
int tileSize = 256 * zScale; // 256 * 1,024 = 262,144
long x0 = leftEdge*zScale; // 3,072 * 1,024 = 3,145,728
long y0 = topEdge*zScale; // 2,048 * 1,024 = 3,145,728
long x1 = x0 + tileSize;
long y1 = y0 + tileSize;
MKMapPoint ul = MKMapPointMake(x0, y0); // upper left
MKMapPoint lr = MKMapPointMake(x1, y1); // lower right
MKMapRect mapRect = MKMapRectMake (fmin(ul.x, lr.x),
fmin(ul.y, lr.y),
fabs(ul.x - lr.x),
fabs(ul.y - lr.y));
}
@end
答案 1 :(得分:2)
主题的变体
+ (MKMapRect)mapRectForTilePath:(MKTileOverlayPath)path
{
CGFloat xScale = (double)path.x / [self worldTileWidthForZoomLevel:path.z];
CGFloat yScale = (double)path.y / [self worldTileWidthForZoomLevel:path.z];
MKMapRect world = MKMapRectWorld;
return MKMapRectMake(world.size.width * xScale,
world.size.height * yScale,
world.size.width / [self worldTileWidthForZoomLevel:path.z],
world.size.height / [self worldTileWidthForZoomLevel:path.z]);
}
/*
Determine the number of tiles wide *or tall* the world is, at the given zoomLevel.
(In the Spherical Mercator projection, the poles are cut off so that the resulting 2D map is "square".)
*/
+ (NSUInteger)worldTileWidthForZoomLevel:(NSUInteger)zoomLevel
{
return (NSUInteger)(pow(2,zoomLevel));
}