見出し画像

緯度経度をピクセル座標に変換するSwift実装

地図タイルを描画してそこに自分の現在位置なり、位置情報と紐づいたデータなりをマッピングしようとすると、緯度経度からピクセル座標に変換する必要がある。

それをSwiftでどう実装するか、のメモ。

なお今回はあえてMapKitを使用しない制約の中での話なのだが、MapKit を使うと普通に MKMapView に緯度経度をビュー内の座標に変換するメソッドがあったりする。

func convert(
    _ coordinate: CLLocationCoordinate2D,
    toPointTo view: UIView?
) -> CGPoint

繰り返しになるが、今回はMapKitを使わず自前で地図タイルを描画する場合に、どうラスタータイルの画像内における位置と、位置情報(緯度経度)とを紐づけるかという話。


ズームレベル・緯度経度からピクセル座標へ変換する計算式

全然わからないのでググった。こちらの記事に数式が載っていた:

経度λとズームレベルzからピクセル座標xを計算
緯度φとズームレベルzからピクセル座標yを計算

本質的にはメルカトル図法の話ではあるが、ズームレベルの概念も絡んでやや複雑になっている。

なお元記事の元記事がこちらで、

さらにその元記事はGoogle Mapsのドキュメントのようだが、リンク先にアクセスすると404。そこにはこう書かれていたようだ:

わかりやすくするため、ピクセル座標の計算では、ズームレベル 0 の地図がベースタイルサイズの 1 つのタイルであると仮定します。次に、緯度と経度をこのベースタイルのピクセルの位置に変換する投影を使用して、ピクセル座標に相対的な世界座標を定義します。

(中略)

Google Maps の世界座標はメルカトル図法の原点(地図の北西の隅、経度 180 度、緯度約 85 度)から測定され、x の方向は東(右)に、y の方向は南(下)に増加します。Google Maps の基本メルカトル タイルは 256x256 ピクセルなので、使用できる世界座標の空間は {0-256}, {0-256} です(下記を参照)。

(中略)

ズーム レベル 19 では、地図上の x および y ピクセルはそれぞれ、0~256 * 219 の値を使用して参照されます。

グーグルマップ(Google Maps) の座標間変換式について(1) - 細橋龍一のブログ」より引用
「グーグルマップ(Google Maps) の座標間変換式について(1) - 細橋龍一のブログ」より引用

記事は難しそうな式の導出過程が記載されている。こういう先人の記事が本当にありがたい…

Swift での実装

ここから先は

1,290字
文章やサンプルコードは多少荒削りかもしれませんが、ブログや書籍にはまだ書いていないことを日々大量に載せています。たったの400円で、すぐに購読解除してもその月は過去記事もさかのぼって読めるので、少しでも気になる内容がある方にはオトクかと思います。

技術的なメモやサンプルコード、思いついたアイデア、考えたこと、お金の話等々、頭をよぎった諸々を気軽に垂れ流しています。

最後まで読んでいただきありがとうございます!もし参考になる部分があれば、スキを押していただけると励みになります。 Twitterもフォローしていただけたら嬉しいです。 https://twitter.com/shu223/