如何从数据库中绘制地图上的图块?

时间:2016-11-10 22:31:44

标签: ios swift3 mapkit mkoverlay

我正在使用Swift 3.0开发基于GIS的iOS应用程序。我想在Map上绘制切片,切片图像存储在SQLite数据库中。

我的问题是如何从数据库中检索平铺图像并在地图上绘制图像,因为数据库包含列缩放(值将为12,13等),tile_row(值将为4122,3413等) ,tile_column(值将是4122,3413等)和数据,但我得到数千的缩放级别值,我在iOS应用程序中获得纬度和经度值,所以我需要转换这些值以匹配数据库中的值。我找到了一种将缩放级别转换为1到18比例的方法,但我不知道能否使用纬度和经度匹配tile_row和tile_column值。

另外请验证我的代码将缩放级别转换为1到18(类似于谷歌地图缩放级别)是正确的:

uint*_t

感谢。

1 个答案:

答案 0 :(得分:2)

在IOS(和大多数地图系统)中,图块图像存储在目录结构中,其中每个缩放级别是以缩放级别编号命名的父目录。在该目录下,有一个或多个目录以下面的图块的纵向图块编号命名 - 例如,在缩放级别10处有1024个图块,如果这样,则目录可以是750,751,752和753。他们的图像相对下降的地方。在每个经度(x坐标)目录下,该y坐标的图像(256 X 256像素),每个以x平铺坐标命名,在缩放级别10再次为1024.

要查找您在这些范围内的位置,请使用MKMapPointForCoordinate(CLLocationCoordinate2D),它将在完全缩小时为您提供某个位置的lat(y)和lon(x)地图点。要获得经度(y)磁贴数量,请使用:

Int((pow(2.0, Double(z)) as Double) * point.y / 268435456.0) 

...其中大数字是缩放级别0(x ^ 2个图块* 256像素/图块)的x轴上的总点数。这样,如果point.x是大数字的1/3,则图像是通过1024的方式的1/3,并且表示该数字落入的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是沿x或y轴的缩放级别20地图中的像素总数。请注意,所有这些都适用于Apples MapKit地图和显示它们的功能。