概要
Apple MapKitのMKTileOverlayを使ってタイル座標のズームレベルを取得します
背景
地理情報システム(GIS)を作成するときタイル座標およびタイル画像は欠かせない概念かと思います。タイル座標は z/x/y
の形式で表現されます。
しかしながら、Apple MapKitにはズームレベルという概念がなく、よくregionを操作・計算してズームレベルを計算します。
しかし調査をしたところ、MKTileOverlayというタイル画像を読み込むためのクラスを用いることで簡単にズームレベルを取得できることがわかりました!
このことについての解説記事が自分が調査した範囲では見つけることができなかったので、この記事を作成した次第です。同じケースでお悩みの方の参考になれば嬉しいです🙏
サンプルコード
import UIKit
import MapKit
class ViewController: UIViewController {
// 国土地理院のTileOverlayを作成する
lazy var mapTile = MKTileOverlay(urlTemplate: "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png")
// タイル座標のカスタムTileOverlayを作成する
lazy var gridTile = GridOverlay()
lazy var mapView: MKMapView = {
let mapView = MKMapView()
mapView.delegate = self
// 地理院のタイルを追加
mapView.addOverlay(mapTile)
// カスタムタイルを追加
mapView.addOverlay(gridTile)
return mapView
}()
override func viewDidLoad() {
super.viewDidLoad()
mapView.frame = view.bounds
view.addSubview(mapView)
// Mapの初期化
let coordinate = CLLocationCoordinate2D(latitude: 35.681236, longitude: 139.767125)
let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
let region = MKCoordinateRegion(center: coordinate, span: span)
mapView.setRegion(region, animated: false)
}
}
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
// TileOverlayの描画
return MKTileOverlayRenderer(overlay: overlay)
}
}
class GridOverlay: MKTileOverlay {
override func loadTile(at path:MKTileOverlayPath, result:@escaping (Data?, Error?) -> Void) {
UIGraphicsBeginImageContext(CGSize(width: 256,height: 256))
guard let context = UIGraphicsGetCurrentContext() else {
return
}
// 格子を描画する
context.setStrokeColor(UIColor.black.cgColor)
context.stroke(CGRect(x: 0, y: 0, width: 256,height: 256))
// タイル座標(z/x/y)をテキストを描画する
UIGraphicsPushContext(context)
let font = UIFont.systemFont(ofSize: 20)
let text = "\(path.z) / \(path.x) / \(path.y)"
let string = NSAttributedString(string: text, attributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: UIColor.red])
string.draw(at: CGPoint(x: 0, y: 118))
UIGraphicsPopContext()
let tileImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
result(tileImage?.pngData(), nil)
}
}
キャプチャ画像
準備中
国土地理院の座標確認ページとぜひ比較してみてください!
参考