LoginSignup
25
26

More than 5 years have passed since last update.

地図表示の経度幅と横ピクセル幅から、ズームを逆算する方法

Last updated at Posted at 2014-04-16

昨日会社で、同僚に経緯度と表示範囲から、地図ズーム逆算する方法聞かれたんですよ。
で、偉そうに、メルカトル図法だから緯度が影響するからとかなんとか言ったんですけどね、なんかいざ計算してみると、緯度関係なく計算できそうなんですよ。

で、よくよく考えると、等角図法なんで緯度に関係なく経度間の幅は一定になるはずで、それとピクセル間の比でズーム決まるはずですから、どう考えても緯度関係なさそうなんですよね。
今までよくよく考えてなかったから気づきませんでしたけど。

いやあ、これだけ地図に詳しくなったつもりでも、いろいろ気づかされるもんですね…。

というわけで、ちょっと算出法をまとめてみたら、チョー簡単な式になりました。

まず、ズームレベルzと、そのズームレベルでの球面メルカトル座標(単位m)とピクセルの比(meter per pixel:正式用語ではありませんが、mppとでも略します)の定義を見てみましょう。
JavaScriptベースだとこの辺に以前まとめましたが、数式ベースだと、

M_{max}:球面メルカトル座標最大値 (赤道での地球半周のm)\\
R:地球半径\\
\\
とおくと、M_{max}=\pi R \\
また、ズームレベルzでの世界全体地図の1辺ピクセル数は、\\
256 \times 2^z なので、mppは、\\
mpp = \frac{2\pi R}{256 \times 2^z} = \frac{\pi R}{128 \times 2^z}

また、地図表示エリアの東端経度Lx1、ピクセルx座標Px1、西端経度Lx2、ピクセルx座標Px2とおくと、表示領域から求まるmppは、

東端メルカトルx座標 M_{x1} = \frac{L_{x1} \pi R}{180}\\
西端メルカトルx座標 M_{x2} = \frac{L_{x2} \pi R}{180}\\
\\
mpp = \frac{M_{x1}-M_{x2}}{P_{x1}-P_{x2}}\\
=\frac{\frac{\pi R (L_{x1}-L_{x2})}{180}}{P_{x1}-P_{x2}}\\
経度差を\Delta L = L_{x1}-L_{x2}、\\
ピクセル差を\Delta P = P_{x1}-P_{x2}とおくと、\\
mpp = \frac{\pi R \Delta L}{180 \times \Delta P}

この両者が一致するzを求めるので、

\frac{\pi R}{128 \times 2^z} = \frac{\pi R \Delta L}{180 \times \Delta P}\\
2^z = \frac{180 \times \Delta P}{128 \times \Delta L} = \frac{45 \times \Delta P}{32 \times \Delta L}\\
z = log_2(\frac{45 \times \Delta P}{32 \times \Delta L}) \\
= log_2(1.40625\frac{\Delta P}{\Delta L}) \\
= \frac{log_e(1.40625\frac{\Delta P}{\Delta L})}{log_e 2} (対数法則詳しくない人のために)

という感じの計算結果になると思います。

つまり、JavaScriptで書くなら、

経度差とX座標ピクセル差から、ズームレベルを求める
    var zoom = Math.Log( 1.40625 * (px1 - px2) / (lon1 - lon2) ) / Math.LN2;

という感じでしょうか。

小数になるので、適宜ceil/floor/roundしてください。
また、Retinaだのxxhdpiだのみたいな高解像度環境では、実ピクセル数ではなく、dpやpointのような値を使うのが吉です。

25
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
26