2025年10月15日水曜日

日本測地系2011のデータをOpenLayersの地図上に表示する

先日の記事(こちら)での作業において、座標参照系の変換でかなり苦労しました。結果として座標参照系の問題ではなかったのですが、日本測地系2011/平面直角座標系第9系(EPSG:6677)のデータをそのまま地図上に表示していれば、作業効率は高かったと感じました。

どのAIに聞いても、Oracle APEXのマップ・リージョンが使用しているMapLibre GL JSでEPSG:6677のデータを直接描画するのは困難とのことで、OpenLayersで表示することにしました。OpenLayersProj4jsを使用します。

以下が、作成したAPEXアプリケーションでの地図の表示です。東京都デジタルツイン実現プロジェクト区部点群データ等高線のデータがありますが、このデータをEPSG:6677のままデータベースに保存し、描画についてもEPSG:6677のままOpenLayersのレイヤーとして描画します。


実施した作業を簡単に紹介します。

等高線のロードにはGDALのogr2ogrを使用します。こちらの記事で作成したOracle Databaseのドライバを組み込んだGDALのコンテナを使用します。

podman run --rm -it -v $PWD:/home/oracle gdal

jgd2011 % podman run --rm -it -v $PWD:/home/oracle gdal

bash-5.1$ 


東京都デジタルツインのサイトからダウンロードした、等高線のDXFファイルをロードするスクリプトをload_dxf.shとして作成します。DXFの保存先となるデータベースの接続情報については、環境に合わせて変更します。
#!/bin/sh

PASS=ChangeMe

ogr2ogr -f OCI \
OCI:wksp_apexdev/${PASS}@host.containers.internal/freepdb1 \
$1 \
-oo ENCODING=CP932 \
-nln CONTOUR_LINES_6677 -lco GEOMETRY_NAME=GEOM -lco SRID=6677 -lco DIM=2 \
-a_srs EPSG:6677 \
-skipfailures
DXFのデータは表CONTOUR_LINES_6677の列GEOMに保存されます。SDO_GEOMETRY型になりますが、EPSG:6677として保存されます。

今回は東京駅付近の09LD1874.dxf、09LD1875.dxf、09LD1884.dxf、09LD1894.dxf、09LD1895.dxfの等高線をデータベースにロードしました。

sh load_dxf.sh 09LD1874.dxf

初回実行時に、表CONTOUR_LINES_6677の作成およびUSER_SDO_GEOM_METADATAへのメタデータの登録が行われます。ORA-13223が発生しますが、エラーはduplicate entryなので無視します。

bash-5.1$ sh load_dxf.sh 09LD1874.dxf

Warning 1: Layer creation options ignored since an existing layer is

         being appended to.

bash-5.1$ sh load_dxf.sh 09LD1874.dxf

ERROR 1: ORA-13223: duplicate entry for CONTOUR_LINES_6677.GEOM in SDO_GEOM_METADATA

ORA-06512: at "MDSYS.MD", line 1723

ORA-06512: at "MDSYS.MDERR", line 17

ORA-06512: at "MDSYS.SDO_GEOM_TRIG_INS1", line 91

ORA-04088: error during execution of trigger 'MDSYS.SDO_GEOM_TRIG_INS1'

Help: https://docs.oracle.com/error-help/db/ora-13223/

 in INSERT INTO USER_SDO_GEOM_METADATA VALUES ('CONTOUR_LINES_6677', 'GEOM', MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-6400.0000003,-5999.9999997,1e-07),MDSYS.SDO_DIM_ELEMENT('Y',-35400.0000003,-35099.9999997,1e-07)), 6677)

bash-5.1$ 


続けて他のメッシュもロードします。

sh load_dxf.sh 09LD1875.dxf
sh load_dxf.sh 09LD1884.dxf
sh load_dxf.sh 09LD1885.dxf
sh load_dxf.sh 09LD1894.dxf
sh load_dxf.sh 09LD1895.dxf


bash-5.1$ sh load_dxf.sh 09LD1875.dxf

Warning 1: Layer creation options ignored since an existing layer is

         being appended to.

bash-5.1$ sh load_dxf.sh 09LD1884.dxf

Warning 1: Layer creation options ignored since an existing layer is

         being appended to.

bash-5.1$ sh load_dxf.sh 09LD1885.dxf

Warning 1: Layer creation options ignored since an existing layer is

         being appended to.

bash-5.1$ sh load_dxf.sh 09LD1894.dxf

Warning 1: Layer creation options ignored since an existing layer is

         being appended to.

bash-5.1$ sh load_dxf.sh 09LD1895.dxf

Warning 1: Layer creation options ignored since an existing layer is

         being appended to.

bash-5.1$ 


データのロードは以上で完了です。

空のAPEXアプリケーションを作成します。名前日本測地系2011地図とします。


アプリケーションが作成されます。すべての機能をホーム・ページに実装します。


ページのデザインを行います。

主に表示範囲を表示するページ・アイテムとしてP1_STATUSを作成します。タイプ表示のみです。


等高線の線の太さを指定するページ・アイテムとしてP1_LINEWIDTHを作成します。タイプ数値フィールドです。

P1_STATUSの右隣に配置するため、レイアウト新規行の開始オフ列スパン2とします。

デフォルトタイプ静的を選び、静的値としてを設定します。


OpenLayersのマップを表示するリージョンを作成します。名前日本測地系2011地図とします。タイプ静的コンテンツで、ソースHTMLコードに以下を記述します。

<div id="map"></div>


以上でページのレイアウトは完成です。

指定した矩形に含まれる等高線のデータを、GeoJSONの配列として返すAjaxコールバックGET_FEATURE_COLLECTIONを作成します。

ソースPL/SQLコードとして以下を記述します。



OpenLayersのマップの描画などを行うコードは、静的アプリケーション・ファイルにJavaScriptを記述します。

静的アプリケーション・ファイルとしてapp.jsを作成し、以下を記述します。



ページ・プロパティにJavaScriptのライブラリをロードするように設定します。

JavaScriptファイルURLに以下を記述します。

https://cdn.jsdelivr.net/npm/proj4@2.19.10/dist/proj4.js
https://cdn.jsdelivr.net/npm/ol@10.6.1/dist/ol.js
#APP_FILES#app#MIN#.js


CSSのインラインに以下を記述します。表示するマップの大きさを規定します。

#map {
   width: 100%;
   height: 800px;
}


以上でAPEXアプリケーションは完成です。

アプリケーションを実行すると、記事の先頭のようにマップが表示されます。

APEXのアプリケーションであれば、EPSG:4632に変換すれば(SDO_CS.TRANSFORMで簡単に変換できます)標準のマップに描画できるため、あまり出番はないかもしれません。どうしても、オープンデータに含まれている座標値をそのまま使用したい、といったケースでは役に立つと思います。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/openlayers-epsg-6677.zip

若干、アプリケーションの作り方について説明すると、最初にClade Sonnet 4.5に静的なHTMLにOpenLayersでマップを表示し、レイヤーにEPSG:6677のデータを使うサンプルを作るようにお願いしました。出来上がったのがこちらです。JavaScriptのコードを静的アプリケーション・ファイルに移行し、それにデータベースとのデータのやり取りを追加しています。


Oracle APEXのアプリケーション作成の参考になれば幸いです。