国土地理院(GSI)のDigital Elevtation Modelは地理院Tileという概念を用いているため、この地理院Tile座標やTile内部の個々のDEM値の位置を世界座標系で表現するPixel座標を、他のGIS(Geographic Information System)で利用されることが多い緯度経度(Longitude, Latitude)に変換しないといけない場面に遭遇します。
The case like thatのために使用するFuctionなどをIntroduceしたいと思います。
1.Tile座標を緯度経度に変換するFunction
最初に、あるTile座標とZoomがgiveされたときに、そのTileのNorth-WestEdgeのLon,Lat(Longitude,Latitude)をReturnするFunction 'tile_to_lolat'です。
Google Geminiさんに聞くと、Latitudeの計算方法は以下の2種類あるようですが、どちらの式を使っても正しい緯度を計算できるそうです。
①lat = math.atan(math.sinh(math.pi * (1 - 2 * y / 2**z))) * 180 / math.pi
②mapy = (y / 2.0**z) * 2 * pi - pi, lat = 2 * atan(e ** (- mapy)) * 180 / pi - 90
Hyperbaric関数を解くのがめんどくさいので、ここはGoogleGeminiさんを信じることにします。
2.Tile内の標高値Meshの平均的なSizeをCalculateするFunction
Tile内には東西256×南北256個のElevationValueが格納されており、その1つ1つのElevationValueMeshの東西・南北の間隔(距離)とOneMeshの面積をCaluculateしてReturnするFunctionでございます。
引数zはZoomLevel。wn_x, wn_y, es_x, es_yは今回対象としている検討領域のWest-North EdgeおよびはEast-SouthののTile座標でございます。
lon_size, lat_sizeは緯度・経度の角度単位で、lon_pich, lat_pichは距離(m)単位の表示、areaはOneMeshの面積(m2)でございます。
3.緯度・経度とZoomLevelからPixel座標およびTile内部(局所)座標(Inner(Local) Tile Coordinate)をCalculateするFunction
緯度・経度(Lon, Lat)からあるZoomLevelにおけるPixel座標を、また、複数のTileを結合した結合TileModelの北西端を(0,0)とした内部(局所)Pixel座標(わたしは勝手にCol(Column:列), Row(行)と名付けました)
当初、1つのTileに対してTile北西端緯度・経度-Tile南東端緯度・経度を求めて、それを緯度差分÷256、経度差分÷256みたいな単純計算で行けるのかなぁと思って、Col, Rowといった内部(局所)座標を試行しましたが、そんな単純な方法では緯度経度から変換した位置が全く異なるということがわかり、緯度・経度とZoomから地球全体のPixel座標を求める変換式を探しました。
ChatGPTが公開される前だったのでWeb上を一生懸命探しました。ヒットしたのは「Trail Note」さまの以下のURLでございます。
https://www.trail-note.net/tech/coordinate/
緯度経度と地理院TileのPixel座標の関係を説明していただいている貴重な日本語のWebSiteでございます。本当にありがとうございます。このWebSiteを参考にして、Functionを以下のように定義いたします。
引数はz=ZoomLevel. lonlat=(Longitude, Latitude), edge = (wn_edge_lon, wn_edge_lat)[検討領域北西端の緯度、経度]でございます。
4.Tile内部(局所)座標(Inner(Local) Tile Coordinate)とZoomLevelから緯度経度(LonLat)をCalculateするFunction
前述の3.のReverseのTransformでございます。
引数はzoom=ZoomLevel. colrow=(column, Row)[対象領域北西端座標を[0, 0]としたときの任意の標高点の行列番号], nw_edge_lonlat = (wn_edge_lon, wn_edge_lat)[検討領域北西端の緯度、経度]でございます。
5.LonLan(緯度・経度)が既知の2点間のDistanceをCalcするFunction’lonlat_to_dist'
緯度・経度が既知の2点間の距離をCalcする関数です。2点の緯度経度(lon1, lat1), (lon2, lat2)を引数として与えて、2点間の距離distanceをReturnします。
かなりPastにCreateした関数なので中身を忘却してしまいました。中身についてGemini先生に聞いてみると以下の通りの回答をいただきました。
pyproj.Geod
を使用して、GRS80 楕円体に基づく地理座標計算オブジェクトを作成します。
grs80.inv()
メソッドを使用して、2点間の距離を計算します。このメソッドは、方位角、逆方位角、距離を返しますが、ここでは距離のみを使用します。このコードのポイントは'grs80 = pyproj.Geod(ellps='GRS80')'です。Gemini先生に解説していただきます。
grs80 = pyproj.Geod(ellps='GRS80')
というコードは、Python の pyproj
ライブラリを使用して、GRS80 楕円体に基づく地理座標計算オブジェクトを作成するものです。それぞれの部分について説明します。
pyproj ライブラリ
pyproj
は、Python で地理座標変換や測地線計算を行うためのライブラリです。- 地球の形状を考慮した高精度な計算が可能になります。
pyproj.Geod() クラス
pyproj.Geod()
は、測地線計算を行うためのクラスです。- 地球の楕円体モデルに基づいて、2点間の距離や方位角などを計算できます。
ellps='GRS80' 引数
ellps
は、楕円体(ellipsoid)モデルを指定する引数です。'GRS80'
は、GRS80(Geodetic Reference System 1980)楕円体モデルを指定しています。- GRS80 楕円体は、地球の形状を近似する回転楕円体であり、測地学における基準として広く使用されています。
- この引数を指定することで、GRS80 楕円体に基づいた計算が行われるようになります。
grs80 変数
grs80
は、作成されたpyproj.Geod
オブジェクトを格納する変数です。- このオブジェクトを使用して、距離計算や方位角計算などの測地線計算を行うことができます。
まとめ
このコードは、GRS80 楕円体モデルを使用して、地球上の2点間の距離や方位角などを計算するための準備を行っています。作成された grs80
オブジェクトを後続のコードで使用することで、高精度な地理座標計算が可能になります。
このgrs80オブジェクトを使用してaz, bkw_az, dist = grs80.inv(lon1, lat1, lon2, lat2)''というコードで以下の数値を計算しています。pyprojライブラリはおそるべしでございます。
az
: 1点目から2点目への方位角(Azimuth)。角度単位(度)。bkw_az
: 2点目から1点目への逆方位角(Back Azimuth)。角度単位(度)。
dist
: 2点間の距離(Distance)。メートル単位。GRS80楕円体についても聞いてみました。
GRS80楕円体(Geodetic Reference System 1980)は、地球の形状を近似する回転楕円体であり、測地学における基準として広く使用されています。以下に、GRS80楕円体に関する詳細な情報を提供します。
GRS80楕円体の特徴
- 形状の定義:
- 地球を回転楕円体としてモデル化し、その形状を数学的に定義しています。
- 長半径(赤道半径)と扁平率によって、楕円体の大きさと形状が決定されます。
- 主なパラメータ:
- 長半径 (a): 6,378,137 メートル
- 扁平率 (f): 1/298.257222101
- 測地学における役割:
- 地球上の位置を正確に測定し、地図を作成するための基準となります。
- GPSなどの衛星測位システムや、地理情報システム(GIS)においても、位置情報の基準として使用されます。
- WGS84との関係:
- GPSで使用されているWGS84(World Geodetic System 1984)楕円体は、GRS80楕円体と非常に近い値を持っています。
- 実用上、両者はほぼ同一のものとして扱われることが多いです。
GRS80楕円体の重要性
- 地球の形状を正確にモデル化することで、高精度な測量や位置測定が可能になります。
- 国際的な測地学の基準として、様々な分野で広く利用されています。
- GPSなどの衛星測位システムを支える重要な基盤となっています。
GRS80楕円体とWGS84楕円体の違い
GRS80楕円体とWGS84楕円体は非常に近い値を持っていますが、厳密にはわずかな違いがあります。
- WGS84は、GPSの運用に合わせて、より精密な測定に基づいて更新されています。
- そのため、最新の測量においては、WGS84の方がより正確な値を提供します。
しかし、一般的な用途においては、両者の違いは無視できるほど小さいため、どちらを使用しても実用上の問題はほとんどありません。
参考資料
- GRS80 - Wikipedia:
https://ja.wikipedia.org/wiki/GRS80 - 世界測地系 / エリアマーケティング・商圏分析・GIS用語集:
https://www.mapmarketing.co.jp/glossary/sekaisokutikei.html
5.Digital Elevation Modelの標高値を平均化するFunction 'tile_elev_sm1'
使用するかどうかは別にして、Tile内部の行列数を変えずに、与えられた引数'number'だけの上下左右の範囲の標高値を平均して、当該行列Pointの標高値を置き換える関数です。
地理院DEMは既に平均化されているように思えるので、このFunctionの要否については微妙化もしれませんが、ゆくゆくドローン測量した標高値など誤差を含む可能性があるModelを利用する際には有効かもしれません。
6.n×n個のタイルの標高値を平均化して、1個の標高値にまとめるコード
このコードについてはFunctionにすることを失念しており、MainCodeのままでお届けします。何かの時に使うことがあるかもしれないとCreatしたコードで、VariousなCalculateをするときに、DEMのDataが多すぎると処理時間が膨大になる可能性があると思って、n×n個のタイルの標高値を平均化したうえで、1個の標高値にまとめてしまおうというCodeです。
このコードを通すことで、例えば、256×256の標高値を持つTileを8×8の領域で読み込んだら、大変な量の標高値を持つModelになりますが、8×8個のタイルの標高値を平均化して1つにまとめることで256×256の標高値モデルに簡略化できるということになります。
(補足)前述5.、6.のCodeをWorkさせるためには、以下のようなInitial Inputが必要になります。
7.Confirmation(確認)
四国地方のMajor MountainsのLongitude、LatitudeをGoogleMapでGetし、そのLongitude、Latitudeを入力値として、DEM(GSITile)のElevationValueをObtainして、OfficialなElavation of the Top of MountainとCompereするCodeです。
さらに、ComareResultについては、Foliumを使ってGSIがPublishしているStandardMap上にMarkerをPlotして、DEM標高値とOfficialElevationをPopupでShowupしています。
まずは、数値のOutputです。
石鎚山天狗岳 経度・緯度: [133.11516, 33.76771] Tile内部座標(列・行番号): 1351 948 公式標高値: 1982 m, DEM標高値: 1956 m, 集水面積計算用標高値: 1956 m 剣山山頂 経度・緯度: [134.09408, 33.85358] Tile内部座標(列・行番号): 2776 797 公式標高値: 1955 m, DEM標高値: 1942 m, 集水面積計算用標高値: 1942 m 稲村山山頂 経度・緯度: [133.35912, 33.7471] Tile内部座標(列・行番号): 1706 984 公式標高値: 1506 m, DEM標高値: 1493 m, 集水面積計算用標高値: 1493 m 大滝山山頂 経度・緯度: [134.12712, 34.12331] Tile内部座標(列・行番号): 2824 323 公式標高値: 946 m, DEM標高値: 933 m, 集水面積計算用標高値: 933 m 伊予富士山頂 経度・緯度: [133.24812, 33.78806] Tile内部座標(列・行番号): 1544 912 公式標高値: 1756 m, DEM標高値: 1736 m, 集水面積計算用標高値: 1736 m 飯野山(讃岐富士)山頂 経度・緯度: [133.84571, 34.27428] Tile内部座標(列・行番号): 2414 57 公式標高値: 421.9 m, DEM標高値: 414 m, 集水面積計算用標高値: 414 m
全ての結果において、Offcial Elevation>DEM Elevationになっています。これはわたしの想像ですが、OfficialElevationは山頂の点の数値ですが、DEM標高値は山頂周辺の平均的な標高になっているのではないかなぁと思います。
FoliumによるPlotのResultです。最初は四国全域が表示され、指定したお山付近にマーカーが表示されていると思います。
コメント
コメントを投稿