在 IOS(和大多数地图系统)中,平铺图像存储在目录结构中,其中每个缩放级别都是以缩放级别编号命名的父目录。在该目录下,有一个或多个目录以下面瓦片的纵向瓦片编号命名 - 例如,在缩放级别 10 下,有 1024 个瓦片,您的目录可能是 750、751、752 和 753,如果那是他们的图像相对下降。在每个经度(x 坐标)目录下是该 y 坐标的图像(256 X 256 像素),每个都以 x 平铺坐标命名,在缩放级别为 10 时也是 1024 个。
要查找您在这些范围内的位置,请使用 MKMapPointForCoordinate(CLLocationCoordinate2D),它会在完全缩小时为您提供某个位置的纬度 (y) 和经度 (x) 地图点。要获取经度 (y) 瓷砖编号,请使用:
Int((pow(2.0, Double(z)) as Double) * point.y / 268435456.0)
...其中大数字是缩放级别 0 时 x 轴上的总点数(2^20 块 * 256 像素/块)。这样,如果 point.x 是大数的 1/3,则图像是 1/3 到 1024 的瓦片,表示该数字落入的 256 像素间隔(即瓦片)的整数就是名称目录。
纬度 (y) 地图点和图块编号的计算方法类似,该编号是图像文件的名称。因此,在缩放级别 10 时,沿 x 轴的 1024 个图块中的 752 个和沿 y 轴的 1024 个中的 486 个图块的图像将位于文件中:
...Documents/Maps/yourDirectory/10/752/486.png
...如果您将整个地图目录命名为 Maps 以及这组图块的特定目录为 yourDirectory。当您使用覆盖时,您将使用此目录信息以及其余设置来实例化 MKTileOverlay 对象。请注意,偏移量是从左下角开始的,除非您指定它们是相反的,因为它们正在考虑 x 和 y 轴(提醒您使用 CoreGraphics 作为 UIImage 吗?)。
最后,在给定要为其捕获快照的区域的两个角点的情况下,我计算缩放级别的方法如下:
let position1 = MKMapPointForCoordinate(bottomRight)
let position2 = MKMapPointForCoordinate(topLeft)
let xPosition1 = position1.x / Setting.shared.mapScale
let xPosition2 = position2.x / Setting.shared.mapScale
let yPosition1 = position1.y / Setting.shared.mapScale
let yPosition2 = position2.y / Setting.shared.mapScale
let relativeSpanX = xPosition1 - xPosition2 // X distance between points relative to size of full map
let relativeSpanY = yPosition1 - yPosition2 // Y distance between points relative to size of full map
let spanForZoom = max(relativeSpanX, relativeSpanY)
startingZoom = max(10, Int(log2(1.0 / spanForZoom)) - 1)
这将为您提供适合包含两个点的区域大小的图块的缩放级别,但请注意,该大小的任何标准图块(或小于完整地图的任何大小)都可能包含这两个点,具体取决于在它们相对于网格的位置上。例如,如果它们跨越本初子午线,则在缩放级别 1 的第一步到 4 个图块将它们分开,因此您可能需要 2 - 4 个起始缩放大小的图块来获得两者。理想情况下,编写一个函数来告诉您包含 CLLocationCoordinate2D 的图块编号(x 和 y),因为这在您选择、下载和收集图块时非常方便。
虽然您可以使用几何方法来计算纵向/y 轴值,但 MKMapPointForCoordinate() 对于纬度/y 轴计算是必不可少的,因为当您向北移动时,墨卡托地图是非线性的或南,该功能会为您处理。
这应该可以帮助您入门,但这是一个挑剔的过程 - 需要关注的一件事是布局始终从左下角开始;收集和标记图块时很容易混淆。
我使用以下函数计算给定缩放级别下点所在的图块的 x 和 y 坐标:
func getTileCoordinates(location: CLLocationCoordinate2D, z: Int) -> (x: Int, y: Int)
{
let point = MKMapPointForCoordinate(location)
let locationX = Int((pow(2.0, Double(z)) as Double) * point.x / 268435456.0)
let locationY = Int((pow(2.0, Double(z)) as Double) * point.y / 268435456.0)
return (locationX, locationY)
}
...再次,其中 268435456.0 是缩放级别 20 地图中沿 x 或 y 轴的像素总数。请注意,所有这些都是针对 Apple MapKit 地图和显示它们的功能。