A Day In The Life

とあるプログラマの備忘録

Python を使って緯度経度から地域メッシュコードを算出する

緯度経度(latitude, longitude)から日本の地域メッシュコードを算出する Python3.7 のプログラムを作成しました。

プログラム

緯度経度から1-3次メッシュコード(基準地域メッシュコード)を算出します。精度を出すためにミリ秒で計算しています。

import math

# 計算の単位(ミリ秒)
MILLISECOND = 3600000

class FirstGrid(object):
    def __init__(self, lat, lon):
        '''
        1次メッシュコード計算
        '''
        self.lat = lat
        self.lon = lon
        # メッシュの高さ
        self.height_ms = MILLISECOND * (40 / 60)
        # メッシュの幅
        self.width_ms = MILLISECOND
        # メッシュコードの上位桁
        self.upper = int(math.floor(lat * 15 / 10))
        # メッシュコードの下位桁
        self.lower = int(math.floor(lon - 100))
        # 南端(緯度)
        self.south_ms = self.upper * MILLISECOND / 1.5
        # 西端(経度)
        self.west_ms = (self.lower + 100) * MILLISECOND

    def code(self):
        ''' メッシュコード '''
        return f'{self.upper}{self.lower}'

    def origin(self):
        ''' メッシュの南西端(緯度経度) '''
        return self.south_ms / MILLISECOND, self.west_ms / MILLISECOND

class Grid(FirstGrid):
    def __init__(self, parent, divide):
        '''
        2,3次メッシュコード計算
        :param parent 親メッシュ
        :param divide 分割単位
        '''
        self.lat = parent.lat
        self.lon = parent.lon
        lat_ms = parent.lat * MILLISECOND
        lon_ms = parent.lon * MILLISECOND
        # 親メッシュの高さと幅から当該メッシュの高さと幅を算出する
        self.height_ms = parent.height_ms / divide
        self.width_ms = parent.width_ms / divide
        h = self.height_ms
        w = self.width_ms
        # 上位桁
        self.upper = int(math.floor((lat_ms - parent.south_ms) / h))
        # 下位桁
        self.lower = int(math.floor((lon_ms - parent.west_ms) / w))
        # 南端
        self.south_ms = self.upper * h + parent.south_ms
        # 西端
        self.west_ms = self.lower * w + parent.west_ms

    def code(self):
        return f'{self.upper}{self.lower}'

    def origin(self):
        return self.south_ms / MILLISECOND, self.west_ms / MILLISECOND

class LatLon2Code(object):
    def __init__(self, lat, lon):
        f = FirstGrid(lat, lon)
        # 2次メッシュは1次メッシュを8分割する
        s = Grid(f, 8)
        self._first = f
        self._second = s
        # 3次メッシュは2次メッシュを10分割する
        self._third = Grid(s, 10)

    def first(self):
        return self._first.code()

    def second(self):
        return f'{self._first.code()}{self._second.code()}'

    def third(self):
        return f'{self._first.code()}{self._second.code()}{self._third.code()}'

地域メッシュは英語だと Grid Square と表現するらしいのでクラス名は Grid にしています。1次メッシュの計算が特殊で2次3次は同じ計算をするので、1次と2次3次でクラスを分けました。

使い方

LatLon2Code クラスのコンストラクタに緯度経度を渡してコードを取得します。

def test_latlon2code():
    # 渋谷
    ll2c = LatLon2Code(35.6640352, 139.6982122)
    assert(ll2c.first() == '5339')
    assert(ll2c.second() == '533935')
    assert(ll2c.third() == '53393595')

参考記事