В IOS (и большинстве картографических систем) изображения черепицы хранятся в структуре каталогов, где каждый уровень масштабирования является родительским каталогом с номером уровня масштабирования. В этом каталоге есть один или несколько каталогов, названных с номерами продольной черепицы плиток ниже - например, при уровне масштабирования 10 на 1024 плитки, а ваши каталоги могут быть 750, 751, 752 и 753, если это их изображения упал относительно. Под каждой координатой долготы (x-координата) находятся изображения (256 × 256 пикселей) для этой координаты y, каждая из которых обозначена для координаты x-плитки, опять же из 1024 при уровне масштабирования 10.
Чтобы найти, где вы находитесь в этих диапазонах используйте MKMapPointForCoordinate (CLLocationCoordinate2D), который даст вам точки карты lat (y) и lon (x) местоположения при полном уменьшении. Чтобы использовать номер долготы (у) плитки:
Int((pow(2.0, Double(z)) as Double) * point.y/268435456.0)
... где большое число является общим количеством точек на оси х при уровне масштабирования 0 (2^20 плитки * 256 пикселей/плитка). Таким образом, если point.x составляет 1/3 от большого числа, изображение равно 1/3 пути до 1024, а целое число, представляющее интервал в 256 пикселей (т. Е. Плитку), в которое попадает число, - это имя каталога.
Аналогично вычисляются точка и точка плитки широты (y), и это число является именем файла изображения. Так, при уровне масштабирования 10 изображения для плитки 752 из 1024 по оси х и 486 из 1024 по оси у будет в файле:
...Documents/Maps/yourDirectory/10/752/486.png
... при условии, что вы называете ваш общий каталог карты Карты и конкретный каталог для этого набора плиток 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)
, которая получает вас уровень масштабирования для плитки, которая подходит размер область, которая включает обе точки, но обратите внимание, что ни одна стандартная плитка такого размера (или любого размера, меньшего полной карты) может включать эти две точки в зависимости от того, где они лежат относительно сетки. Например, если они охватывают первый меридиан, первый шаг на 4 плитки на уровне масштабирования 1 будет их разделять, поэтому вам может понадобиться 2-4 плитки начального размера масштабирования, чтобы получить оба.В идеале напишите функцию, которая сообщит вам номер плитки (x и y), который включает CLLocationCoordinate2D, так как это очень удобно, когда вы выбираете, загружаете и собираете свои плитки.
В то время как вы можете уйти с геометрическим подходом, как вы показываете для вычисления значений продольной/оси Y, MKMapPointForCoordinate() незаменим для расчетов по широте/оси 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. Обратите внимание, что все это для карт Map Map Map и отображает их.
BTW, я добавил max при вычислении масштабирования, так как я не хотел уменьшать масштаб до уровня 10, так как я использую карты для поддержки навигации, и вы не можете позволить себе больше 6 или 7 уровней zoom (в 7 вам нужно более 5000 плиток!). Минус 1 состоит в том, чтобы получить небольшое пространство для дыхания и увеличить вероятность того, что я получу обе точки на 1 или 2 плитки. –
Спасибо за ваш ответ. Можете ли вы объяснить переменные или как получить эту переменную, которую вы используете, например, z, point, mapScale. Вы добавили код, чтобы получить уровень масштабирования, но я не уверен, что такое мой уровень масштабирования, spanForZoom - мой уровень масштабирования? – Hardik
bottomRight и topLeft находятся в углах области, для которой я хочу карту. Я получаю их, находя максимальные и минимальные широты и долготы среди мест в моих путевых точках и используя их для определения двух точек: bottomRight = (min, max) и topLeft = (max, min). Оттуда расчет startZoom должен сделать все остальное, чтобы получить зум. Значения .x и .y в этих вычислениях являются свойствами значений MKMapPoints, возвращаемых системой, соответствующей точкам x и y на графике. [см. следующий комментарий] –