import re from pyproj import Proj class Decoder: def __init__(self): # https://www.gsi.go.jp/LAW/heimencho.html orgdefs = ''' 平面直角座標系 系番号 座標系原点の経緯度 適用区域 経度(東経) 緯度(北緯) I 129度30分0秒0000 33度0分0秒0000 長崎県 鹿児島県のうち北方北緯32度南方北緯27度西方東経128度18分東方東経130度を境界線とする区域内(奄美群島は東経130度13分までを含む。)にあるすべての島、小島、環礁及び岩礁 II 131度 0分0秒0000 33度0分0秒0000 福岡県 佐賀県 熊本県 大分県 宮崎県 鹿児島県(I系に規定する区域を除く。) III 132度10分0秒0000 36度0分0秒0000 山口県 島根県 広島県 IV 133度30分0秒0000 33度0分0秒0000 香川県 愛媛県 徳島県 高知県 V 134度20分0秒0000 36度0分0秒0000 兵庫県 鳥取県 岡山県 VI 136度 0分0秒0000 36度0分0秒0000 京都府 大阪府 福井県 滋賀県 三重県 奈良県 和歌山県 VII 137度10分0秒0000 36度0分0秒0000 石川県 富山県 岐阜県 愛知県 VIII 138度30分0秒0000 36度0分0秒0000 新潟県 長野県 山梨県 静岡県 IX 139度50分0秒0000 36度0分0秒0000 東京都(XIV系、XVIII系及びXIX系に規定する区域を除く。) 福島県 栃木県 茨城県 埼玉県 千葉県 群馬県 神奈川県 X 140度50分0秒0000 40度0分0秒0000 青森県 秋田県 山形県 岩手県 宮城県 XI 140度15分0秒0000 44度0分0秒0000 小樽市 函館市 伊達市 北斗市 北海道後志総合振興局の所管区域 北海道胆振総合振興局の所管区域のうち豊浦町、壮瞥町及び洞爺湖町 北海道渡島総合振興局の所管区域 北海道檜山振興局の所管区域 XII 142度15分0秒0000 44度0分0秒0000 北海道(XI系及びXIII系に規定する区域を除く。) XIII 144度15分0秒0000 44度0分0秒0000 北見市 帯広市 釧路市 網走市 根室市 北海道オホーツク総合振興局の所管区域のうち美幌町、津別町、斜里町、清里町、小清水町、訓子府町、置戸町、佐呂間町及び大空町 北海道十勝総合振興局の所管区域 北海道釧路総合振興局の所管区域 北海道根室振興局の所管区域 XIV 142度 0分0秒0000 26度0分0秒0000 東京都のうち北緯28度から南であり、かつ東経140度30分から東であり東経143度から西である区域 XV 127度30分0秒0000 26度0分0秒0000 沖縄県のうち東経126度から東であり、かつ東経130度から西である区域 XVI 124度 0分0秒0000 26度0分0秒0000 沖縄県のうち東経126度から西である区域 XVII 131度 0分0秒0000 26度0分0秒0000 沖縄県のうち東経130度から東である区域 XVIII 136度 0分0秒0000 20度0分0秒0000 東京都のうち北緯28度から南であり、かつ東経140度30分から西である区域 XIX 154度 0分0秒0000 26度0分0秒0000 東京都のうち北緯28度から南であり、かつ東経143度から東である区域 '''.strip() def dms2deg(dms): v = [float(_) for _ in re.split('[度分秒]', dms)] v = sum(p/q for p,q in zip(v, (1, 60, 60**2, 60**3))) return v # orgdefs = [line.split('\t', 3)[1:3] for line in orgdefs.split('\n')[3:]] orgdefs = [[dms2deg(_) for _ in line.split('\t', 3)[1:3]] for line in orgdefs.split('\n')[3:]] #print(orgdefs) # TODO convert to UTM # https://www.gsi.go.jp/chubu/minichishiki10.html # ... is this right? p ={ _: Proj(f'+proj=utm +zone={_} +ellps=WGS84 +datum=WGS84 +units=m +no_defs ') for _ in range(51,57)} zones = [str(int(((x+180)/6+1))) + 'N' for (x,y) in orgdefs] orgdefs = [p[int(((x+180)/6+1))](x,y) for (x,y) in orgdefs] self.orgdefs = {('%02d' % k):{'xy':v, 'zone':z} for k,v,z in zip(range(1,20), orgdefs, zones)} def level50k(self, v): return [(ord(p)-ord(o))*d for p,o,d in zip(v, 'KE', (30,40))], (30,40) def level5k(self, v): return [int(p)*d for p,d in zip(v, (3,4))], (3,4) def level2p5k(self, v): return {'1':(0,0), '2':(1.5,0), '3':(0,2),'4':(1.5,2)}[v], (1.5, 2) def level1k(self, v): return [p*q for p,q in zip([int(v[0]), ord(v[1]) - ord('A')], (.6, .8))], (.6,.8) def levelp5k(self, v): return [int(p)*d for p,d in zip(v, (.3,.4))], (.3, .4) def __call__(self, v, offset=True): """returns coords of ur and lr corner""" # split string ser, lv50k, lv = v[:2], v[2:4], v[4:] # get 平面直角座標系 origin and utm zone org, zon = self.orgdefs[ser].values() # decode first two levels lv50k, sz = self.level50k(lv50k) # decode last level if len(lv) == 0: lv5k, lv,sz = (0,0), (0,0), sz level = 50000 else: lv5k, lv = lv[:2], lv[2:] lv5k, sz = self.level5k(lv5k) if len(lv) == 0: lv, sz = (0, 0), sz level = 5000 elif len(lv) == 1: # 2.5k lv,sz = self.level2p5k(lv) level = 2500 else: if lv[-1] in 'ABCDE': # 1k lv,sz = self.level1k(lv) level = 1000 else: # .5k lv, sz = self.levelp5k(lv) level = 500 # sum offsets ofs = [(lv50k[_] + lv5k[_] + lv[_]) for _ in (0,1)] # For offset and size, convert units from meters to km ofs = [ _ * 1000 for _ in ofs] sz = [ _ * 1000 for _ in sz] # so far, first dim is sourtherly, second dim is easterly # change this to first dim being easterly, seond dim northerly ul = [ofs[1], -ofs[0]] lr = [ofs[1] + sz[1], -ofs[0] - sz[0]] if offset: return (ser, ul,lr, level) else: ul = [o+_ for o,_ in zip(org, ul) ] lr = [o+_ for o,_ in zip(org, lr) ] return (zon, ul,lr, level) decoder = Decoder() def tester1(): ex = ['09LD35', '09LD352', '09LD354E', '09LD3599'] # print(decoder.orgdefs) print('distance from 平面直角座標系 origin: "座標系id", upper-left, lower-right') for x in ex: print(x, decoder(x, offset=True)) print('distance from UTM origin') for x in ex: print(x, decoder(x, offset=False)) def tester2(): ex = ''' 09AA 09AA00 09AA001 09AA000A 09AA0000 09TH 09TH99 09TH991 09TH994 09TH994E 09TH9999 09KE 09KE00 09KE001 09KE000A 09KE0000 09LD3599 09LD352 09CG543 09CG3776 '''.strip() for line in ex.split('\n'): cod = line.strip() if not len(cod): continue print(cod, decoder(cod)) if __name__ == '__main__': #tester1() #tester2() import sys cod = sys.argv[1] res = decoder(cod) print(cod, res)