从MKTileOverlayPath获取MKMapRect

时间:2014-12-11 08:14:37

标签: ios mapkit

我搜索了很多答案&我无法想象这种方法不存在!! 我有一个MKTileOverlayPath(x,y& z),也能够得到这个矩形中心的lon / lat。 现在我需要得到每个矩形的跨度,这可能吗?

2 个答案:

答案 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,024z20倍。

这是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 = 12y = 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));
}