2021年5月18日火曜日

21.1のマップ・リージョンを使用する

 Oracle APEX 21.1よりマップ・リージョンが新設されました。アプリケーションを作成して、使い方を確認してみようと思います。最終的には以下のアプリケーションを作成します。

以前にOracle Spatialの機能をOracle APEXから利用する手順について書いた記事を元にしています。

Oracle Spatialの機能をOracle APEXで使用する

元記事に従ってアプリケーションを作成したのち、マップ・リージョンを追加します。または、元記事の手順を飛ばして、以下のアプリケーションをインポートしてから始めることもできます。

https://github.com/ujnak/apexapps/blob/master/exports/drone-permits-app.sql

Drone Permits Appが作成済みでGeocoderを呼び出す機能も追加済み、というのが前提条件です。

ページ番号6Drone Flight Request - Detailsを開き、新規にリージョンの作成を行います。識別タイトルドローン飛行空域とし、タイプマップを選択します。


最初にドローンの飛行が禁止されている、すべての空域を表示するレイヤーを設定します。新規となっているレイヤーを選択し、識別名前禁止空域レイヤー・タイプポリゴンを選択します。

ソース表名URBAN_AREA_UKを選択します。ドローンの飛行が禁止されている空域は列GEOMに定義されているので、列のマッピングジオメトリ列のデータ型としてSDO_GEOMETRYを選択し、ジオメトリ列GEOMを指定します。


ページを実行して結果を確認してみます。英国の禁止空域のみが列GEOMに登録されているため、地図が英国にフィットして表示されています。青く表示されている領域がドローンの飛行禁止空域です。


次に飛行許可を申請した座標をレイヤーとして表示します。左ペインのマップ・リージョンのレイヤーの上でコンテキスト・メニューを表示させ、レイヤーの作成を実行します。


識別名前リクエストとし、レイヤー・タイプポイントを選択します。ソースタイプSQL問合せとし、SQL問合せに以下のSELECT文を記述します。

select n002, n003
from apex_collections where collection_name = 'GEOCODER_RESULTS'
and n002 is not null and n003 is not null

列のマッピングジオメトリ列のデータ型として、経度/緯度を選択し、経度列N002緯度列N003を指定します。外観塗りつぶしの色は赤(#ff0000)を指定します。


APEXコレクションGEOMETRY_RESULTSへ経度、緯度の情報を投入する処理は、ボタンOBTAIN_FLY_ZONE_INFOをクリックしたときに行われます。

OBTAIN_FLY_ZONE_INFOの動的アクションからジオコーダーが呼び出され、リクエストした住所から座標が得たのちにマップ・リージョンをリフレッシュするよう、動的アクションに処理を追加します。

最初にページのロード時にAPEXコレクションGEOCODER_RESULTSを初期化します。ページがロードされる時点でコレクションを初期化することにより、前回のジオコーダーの呼び出しで取得した座標がマップに表示されることを防ぎます。実行するPL/SQLコードは以下です。

apex_collection.create_or_truncate_collection('GEOCODER_RESULTS');

レンダリング前プロセスの作成を行います。名前コレクションの初期化とし、タイプとしてコードを実行を選択します。ソース位置ローカル・データベース言語PL/SQLPL/SQLコードに上記のAPEX_COLLECTIONの呼び出しを記述します。


座標を取得したのち、マップ・リージョンをリフレッシュさせます。

左ペインに動的アクション・ビューを表示させ、動的アクションであるジオコード取得成功にTrueアクションを作成します。作成したアクションの識別アクションリフレッシュを選択します。影響を受ける要素は、選択タイプリージョンリージョンドローン飛行空域です。


ページを実行し、今までの実装を確認します。飛行リクエストの一覧から任意のリクエストを選択します。Obtain Fly Zone Infoのボタンをクリックすると、マップに位置が表示されます。


ドローンの飛行禁止空域にリクエストが含まれている場合、その空域を表示させます。そのためのレイヤーを新たに追加します。表示する空域の選択に、以下のSQL問合せを使います。Oracle Spatialが提供するSDO_ANYINTERACTファンクションを使用しています。

select GEOM
from URBAN_AREA_UK ar,
(
select n002, n003 from apex_collections
where collection_name = 'GEOCODER_RESULTS'
and n002 is not null and n003 is not null
) pt
where sdo_anyinteract(
geom,
mdsys.sdo_geometry(2001, 4326,
mdsys.sdo_point_type(pt.n002, pt.n003, null),
null, null
)
) = 'TRUE'

新規にレイヤーを追加し、識別名前該当する禁止空域とします。レイヤー・タイプポリゴンを選択します。ソースSQL問合せに上記のSELECT文を記述し、列のマッピングとしてジオメトリ列データ型SDO_GEOMETRYジオメトリ列としてGEOMを指定します。


レイヤーの重ね合わせ表示の際に、該当する禁止空域の上にリクエストが表示されるよう、レイヤーの順序を、禁止空域該当する禁止空域リクエストの順番に入れ替えます。


以上で完成です。アプケーションを動作させると、一番最初のGIF動画の動作を確認することができます。

今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/drone-permits-app-with-spatial.sql

ジオコーダーは、elocation.oracle.comにたいしてRESTの呼び出しを行なっています。ネットワークACLの設定でOracle Databaseからのリクエストの発行が失敗したときに、以下のコードで接続を許可しました。

begin

  dbms_network_acl_admin.create_acl(acl => 'geocoder.xml',

                                    description => 'eLocation',

                                    principal => 'APEX_210100',

                                    is_grant  => true,

                                    privilege => 'connect');

  dbms_network_acl_admin.assign_acl(acl => 'geocoder.xml',

                                    host => 'elocation.oracle.com');

end;

/

commit;


以上になります。

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