# mesh_lib.py # # メッシュコード計算パッケージ (for Python) # # 2010-07-12 TAKENAKA, Akio. (Original ver in Perl) # 2016-11-06 TAKENAKA, Akio. (Port to Python) # # import mesh_lib で、このファイルて定義した4つの関数を # 読み込んでから使用する。 # # meshcode_to_latlong, メッシュコードから緯度・経度へ # latlong_to_meshcode, 緯度・経度からメッシュコードへ。 # dms_to_deg, 度・分・秒から度(小数点表示)へ。 # deg_to_dms, 度(小数点表示)から度・分・秒へ。 import re # 正規表現によるパターンマッチ ######################################## # メッシュコードを渡し、対応する緯度・経度を返す。 # メッシュコードは数値(整数)でも文字列型でも可。 # # 返値は数値データが2つ並んだタプル。 # # 特に指定しなければメッシュの中央の座標を返す。 # メッシュコードは一次、ニ次、三次いずれも可。 # # NW, NE, SW, SE を2つ目の引数として渡すと、それぞれ北西、北東、南西、南東の # コーナーの座標を返す。 # # 緯度・経度は度単位の小数。 # # usage # code_a = "55354251" # 三次メッシュコード # lat_lon = mesh_lib.meshcode_to_latlong(code_a); # 中央の緯度・経度 # print('latitude\t', lat_lon[0], '\tlongitude\t', lat_lon[1], # # code_a = "55354251" # 三次メッシュコード # lat_lon = mesh_lib.meshcode_to_latlong(code_a, 'NE') # 北東端 # print('latitude\t', lat_lon[0], '\tlongitude\t', lat_lon[1], def meshcode_to_latlong(code, loc = 'C'): if type(code) != int: # 整数型に(文字列が渡された場合に対応) try: code = int(code) except: # 形式チェック print("Error in mesh_lib.meshocode_to_latlong() Not a valid code handed.") raise code = str(code) # あらためて文字型に。 code12 = '' code34 = '' code5 = '' code6 = '' code7 = '' code8 = '' loc = loc.upper() if re.match("^C|(NE)|(NW)|(SE)|(SW)$", loc) == None: raise Exception ("Invalid option to meshcode_to_latlong()") match_1_result = re.match("\d{4}", code) if re.match("\d{4}", code): # 最初の4文字が数字 code12 = code[0:2] code34 = code[2:4] lat_width = 2.0 / 3.0 # grid cell の緯度方向の間隔 long_width = 1.0 # grid cell の経度方向の間隔 else: return (None) # メッシュコードとして無効 if re.match("\d{6}", code): # 少なくとも最初の6文字は数字 code5 = code[4:5] code6 = code[5:6] lat_width /= 8.0; long_width /= 8.0; if re.match("\d{8}", code): # 最初の8文字は数字 code7 = code[6:7] code8 = code[7:8] lat_width /= 10.0; long_width /= 10.0; # 以下、南西コーナーの座標を求める。 lat = float(code12) * 2 / 3 # 一次メッシュ long = float(code34) + 100 if (code5 != '') & (code6 != ''): # 二次メッシュ or 三次メッシュ lat += (float(code5) * 2 / 3) / 8 long += float(code6) / 8 if (code7 != '') & (code8 != ''): # 三次メッシュ lat += float(code7) * 2 / 3 / 8 / 10 long += float(code8) / 8 / 10 # ここまでで南東端の緯度・経度が得られた # 中央の座標なら、一区画の幅(経度幅)・高さ(緯度幅)の半分を足す。 if loc == 'C': lat += lat_width / 2 long += long_width / 2 # 北端の座標なら、一区画の高さ(緯度幅)を足す if re.search('N', loc): lat += lat_width # 東端の座標なら、一区画の幅(経度幅)を足す if re.search('E', loc): long += long_width return (lat, long) # タプルを返す。 ################## # 緯度・経度(度単位)を受けとり、これを含むメッシュのコードを返す # 緯度。経度の型は float でも文字列でも可。 # # 返値のメッシュコードは数値(整数)データ。 # # 3番めの引数として 1,2,3 を渡せば、一次メッシュ、二次メッシュ、 # 三次メッシュコードを計算する。指定がなければ三次メッシュ、 # # Usage: # code3 = meshlib.latlong_to_meshcode(35.3, 138.5) # 三次メッシュコード # code2 = meshlib.latlong_to_meshcode(35.3, 138.5, 2) # 二次メッシュコード # code1 = meshlib.latlong_to_meshcode(35.3, 138.5, 1) # 一次メッシュコード # def latlong_to_meshcode(lat, long, order = 3): if type(lat) != float: # 実数型でないなら変換 lat = float(lat) if type(long) != float: # 実数型でないなら変換 long = float(long) if (order < 1) | (order > 3): raise Exception ("Invalid parameter to latlong_to_meshcode()") # Latitude lat_in_min = lat * 60.0 code12 = int(lat_in_min / 40) # codeの1, 2文字目部分(数値) lat_rest_in_min = lat_in_min - code12 * 40 # 残差 code5 = int(lat_rest_in_min / 5 ) # code 5文字目 二次メッシュの1区画は緯度5分 lat_rest_in_min -= code5 * 5 # 残差 code7 = int(lat_rest_in_min / (5/10)) # code 7文字目 三次メッシュの1区画は緯度5分の 1/10 # Longitude code34 = int(long) - 100 # codeの3, 4文字目部分(数値) long_rest_in_deg = long - int(long) code6 = int(long_rest_in_deg * 8) long_rest_in_deg -= code6 / 8; code8 = int(long_rest_in_deg / (1/80) ) code = code12 * 100 + code34 if order >= 2: code = code * 100 + code5 * 10 + code6 if order == 3: code = code * 100 + code7 * 10 + code8 return int(code) ################## # 度、分、秒を受けとり、度の単位で小数点表示に変換して返す。 # # Usage: # deg = meshlib.dms_to_deg(35, 20, 15) def dms_to_deg (deg, min, sec): in_deg = deg + min / 60.0 + sec / 3600.0 return in_deg ################## # 度の単位の小数点表示を受けとり、 度、分、秒に変換して返す。 # 戻り値は数値データが3つ並んだタプル。 # # Usage: # dms = meshlib.deg_to_dms(35.3375) def deg_to_dms(in_deg): deg = int(in_deg) rest_in_deg = in_deg - deg min = int( rest_in_deg * 60 ) rest_in_min = rest_in_deg * 60 - min; sec = rest_in_min * 60; # もし繰り上がってしまっていたら、その分の調整、 if sec >= 60: # 秒が60を越えたら sec -= 60 min += 1 if min == 60: # 分が60 を越えたら min -= 60 deg += 1 return (deg, min, sec) # タプルを返す。