トップ地図アプリMap4 > 陸地の描画

陸地の描画

前ページ
海岸線のレンダリング[2021.12.13]
OSM海岸線データ

はじめに

陸地も OSMデータで描画する。しかし、広域森林や水域などとは描画方法が少し異なる。

OSMの海岸線Wayデータを繋ぎ合わせると、巨大なポリゴンとなる。 小さな島程度であれば、森林や湖と同じように描画できる。しかし、大陸は余りにも巨大であり、 日本地図に限っても、本州、北海道、九州などは巨大なポリゴンであるから、 森林や湖などと同じように、描画するのは無理である。

低ズームの場合は分割は要らないが、高ズームでは、 強大なポリゴンをプログラムで無数の小さいポリゴンに分割して、この小さくしたポリゴンを描画する。

陸地ポリゴンデータのダウンロード

サイト[1]からland-polygons-split-4326.zipおよびsimplified-land-polygons-complete-3857.zipをダウンロードした。

座標系は 4326系にするが、低ズーム用はこれが提供されていないため 3857系とした。いずれ、PostgreSQL/PostGIS で 4326系で CSV出力する。

QGISに読込む

低ズーム用ファイルを QGIS に読込み、異常がないことを確かめた。QGISで CSVファイルにエクスポートできるはずだが、 今回は、見送った。

PostgreSQL/PostGISに読込み、CSVファイルに出力する

データベース osm を作り、create extension postgis を実行して置く。

shp2pgsql -I -s 3857 d:/downloads/simplified-land-polygons-complete-3857/simplified_land_polygons.shp land_polygons > imp.sql
psql -h localhost -p 5432 -d osm -U postgres -f imp.sql

データベース osm に テーブル land_polygons が作られる。

COPY (select gid, ST_AsText(ST_Transform(geom,4326)) AS way from land_polygons) 
TO 'c:/map/simplified_land_polygons.tsv' WITH CSV DELIMITER E'\t';

高ズーム用は以下のようにする。

shp2pgsql -I -s 4326 d:/downloads/land-polygons-split-4326/land_polygons.shp land_polygons_split > imp2.sql
psql -h localhost -p 5432 -d osm -U postgres -f imp2.sql
COPY (select gid, ST_AsText(ST_Transform(geom,4326)) AS way from land_polygons_split) 
TO 'c:/map/land_polygons_split.tsv' WITH CSV DELIMITER E'\t';

2024.4.19に tsvファイルを再出力した。

TSVファイルをOSMバイナリレコードファイルに変換する

GISにおけるMultipolygonは一般に複数の outer polygon があり、それぞれの outer polygon が複数の inner polygon を持つものを言う。上で得られた TSVファイルは Multipolygon 形式であるが、以前は、inner polygon を持たない outer polygon が一つ だけのシンプルな Polygon であった。

しかし、2024年2月1日にダウンロードしたデータには inner polygon が含まれているようである。

標準OSM地図のレンダリングは osm2pgsql で PostgreSQL/PostGISデータベースに OSMデータを取り込むが、この場合の マルチポリゴンは outer polygon は一つである。複数の outer polygon がある場合、複数のレコードとする。 Map4 もこれに従っている。multipolygon の場合、先頭が outer polygon で、その後ろに複数の inner polygon が続く。 それぞれのノード数は先頭にまとめて置かれる。

陸地ポリゴンは実態に合わせて polygon データとする。{key,val} は {'natural','land'} とする。 数年前に作ったプログラムを参考にして、変換プログラムを作る。

TSVファイルの各行は次のようなものである。座標値は経度、緯度の順である。

173	MULTIPOLYGON(((17.6338182 59.0056128,17.6332013 59.0057863,17.6326863 59.0059161,17.632712 59.0061304)))

先頭の ID は当面、無視する。必要に応じて、osm_id と同じ扱いとする。

head(2), [num_nds(4)],  {lon,lat}*, tags_length(2), {key,val}*  ... polygon 
head(2), {num_nds(4)}*, {lon,lat}*, tags_length(2), {key,val}*  ... multipolygon
head:  第0,1bit(0x03) 0: point、   1: line、    2: polygon、 3: multipolygon
num_nodes:  multipolygonの場合、最終要素(最終inner polygonノード数)の最上位ビットは 1 とする。

outer polygon は一つであるが、inner polygon は一つ以上である。

inner が二つの場合 MULTIPOLYGON(((outer),(inner 1),(inner 2))) となり、outer と inner、inner 同士は "),(" で区切られる。

今回のデータには低ズーム用で1つ(inner 1)、高ズーム用で3つのマルチポリゴン(inner 3, 1, 2)があることが分かった。

低ズームでのマルチポリゴンはカスピ海のようだ。高ズームではカスピ海は分割により、inner polygon ではなくなっていた。 しかし、別の地域にいくつかの multipolygon がある。

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -land high
215342: 4
449441: 2
744401: 3

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -land low
63912: 2
LandPolygon.java

メッシュ分割

ポリゴンが大きいため、一般のOSMバイナリレコードよりも小さいzoom値で分割する。 取りあえず、低ズーム用は zoom 0(分割なし)、高ズーム用は zoom 6 で分割する。

プログラムは OSMバイナリレコードファイル用と共通である。

java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -devide lands low 0 0
java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -devide lands high 6 6

高ズームの極座標の精度は小数点以下7桁とした。中低ズームではそれだけの精度は不要なので、 中ズームは小数点以下6桁、中ズームは小数点以下5桁とした。

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -devide lands low 0 0
レコード数=63930, 最大レコード長=878586, 平均レコード長=249.8, 平均タグ長=4.0B, 最大タグ長=4B
実行時間: 0.10分

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -devide lands high 6 6
レコード数=750423, 最大レコード長=665086, 平均レコード長=1322.2, 平均タグ長=4.0B, 最大タグ長=4B
実行時間: 2.63分

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -bbox lands low 0
BBox max 8921KB c:\map\data1\lands-low0\0\0.dat
実行時間: 0.01分

c:\map>java -Dfile.encoding=UTF-8 -Xmx5g -classpath ./class OSMUtil -bbox lands high 6
BBox max 11699KB c:\map\data1\lands-high6\35\18.dat
実行時間: 0.49分

リファレンス

[1] Data Derived from OpenStreetMap for Download
[2] [C# GIS]SharpMapでシェープファイルの情報を読み取ってみる
[3] QGIS を使ってシェープファイル(Shapefile)を CSV に変換する方法
[4] Daylight Coastlines