こちらの記事の続きになります。
マップ上で検索の起点となる位置を指定し、その位置の周囲に立地している医療機関をレポートに一覧します。近隣の医療機関を検索するためにOracle SpatialのSDO_NNファンクションを使用します。
マップのサンプルではNearest Neighbor Searchのページに実装されています。
このファンクションを利用するためには、ジオメトリ列に索引が作成されている必要があります。そのため、最初に表C19_MEDICAL_FACILITIESの列GEOMETRYに空間索引を作成します。
SQLワークスペースのオブジェクト・ブラウザを開き、作成メニューより索引を実行します。
空間メタデータの設定画面が表示されます。座標系、ディメンションの設定はデフォルトのまま変更しません。空間メタデータの追加をクリックします。
索引の作成を実行します。
以上で医療機関の位置を示す列GEOMETRYに空間索引が作成されました。
続いてページの作成に進みます。
こちらの記事で作成したレポート上で選択のページをコピーします。ページ番号は10、ページ名は近隣の医療機関とします。
ページが作成されたら作業の開始です。
マップ・リージョンにマップ上でクリックされた位置のジオメトリを保持するページ・アイテムP10_CLICK_POSITIONを作成します。タイプは非表示、設定の保護された値はOFFにします。
ページ・アイテムP10_CLICK_POSITIONが変更されたときに対話モード・レポートのリージョン医療機関とマップ自体をリフレッシュします。P10_CLICK_POSITION上で動的アクションの作成を行います。識別の名前はRefresh after Changeとします。ページ・アイテム上で動的アクションの作成を実行するとタイミングはイベントが変更、選択タイプがアイテム、アイテムがP10_CLICK_POSITIONとなります。ですので、確認だけして設定はそのままにします。
Trueアクションとして、識別のアクションにリフレッシュを指定します。影響を受ける要素の選択タイプをリージョン、リージョンに対話モード・レポートのリージョン医療機関を指定します。P10_CLICK_POSITIONが変更されたとき、つまり、マップ上をクリックしたときにレポートが更新されます。
対話モード・レポートのリージョン医療機関に検索範囲と候補数を指定するためのページ・アイテムを作成します。
リージョン医療機関でページ・アイテムの作成を実行します。識別の名前はP10_MAX_DISTANCE、タイプは数値フィールドを選択します。ラベルは検索範囲(km)とします。
ページ・アイテムの値が変更されたときにレポートとマップをリフレッシュする動的アクションRefresh after Change2を作成します。P10_CLICK_POSITIONに作成した動的アクションRefresh after Changeと同じ手順になります。
続いてページ・アイテムP10_NEIGHBOR_COUNTを作成します。タイプは数値フィールド、レベルは候補数とします。動的アクションもP10_CLICK_POSITION、P10_MAX_DISTANCEと同様に作成します。動的アクションの作成を行い、名前をRefresh and Change3とします。レポートとマップのリージョンをリフレッシュするアクションを作成します。
マップ・リージョンで動的アクションの作成を行います。識別の名前はClick on Mapとします。タイミングのイベントはマップがクリックされました [マップ]、選択タイプはリージョン、リージョンとして..マップを選択します。
Trueアクションの識別のアクションは値の設定とします。設定のタイプの設定にはJavaScript Expressionを選択し、JavaScript式として以下を記述します。
JSON.stringify({"type":"Point", "coordinates": [this.data.lng, this.data.lat]})
影響を受ける要素の選択タイプをアイテムとし、アイテムに位置を保存するページ・アイテムであるP10_CLICK_POSITIONを選択します。実行オプションの初期化時に実行はOFFにします。
マップ上にクリックした位置を表示するレイヤーを作成します。マップ・リージョンのレイヤー上でレイヤーの作成を実行します。識別の名前を検索起点とします。レイヤー・タイプはポイントです。ソースの位置はローカル・データベース、タイプはSQL問合せとし、以下をSQL問合せとして記述します。
select
0 as id
, mdsys.sdo_util.from_geojson( :P10_CLICK_POSITION ) as geometry
from sys.dual
where :P10_CLICK_POSITION is not null
送信するページ・アイテムとしてP10_CLICK_POSITIONを指定します。
列のマッピングのジオメトリ列のデータ型にSDO_GEOMETRYを選択し、ジオメトリ列にはGEOMETRYを選択します。主キー列はIDです。ポイント・オブジェクトのスタイルはSVG、形状にPin Circleを選びますが、形状の選択画面では円のピンとなっています。シェイプ・スケールに2を指定します。外観の塗りつぶしの色として青色#007aff、ストロークの色は#ffffffを指定します。ストロークの幅は1を指定します。
続いて、検索範囲を表示するレイヤーを作成します。さきほどと同様にレイヤーの作成を行い、識別の名前を検索範囲、レイヤー・タイプをポリゴンとします。SQL問合せとして以下を記述します。
select
0 as id,
mdsys.sdo_util.circle_polygon(
point => mdsys.sdo_util.from_geojson( :P10_CLICK_POSITION ),
radius => :P10_MAX_DISTANCE * 1000,
arc_tolerance => 1 ) as geometry
from sys.dual
where :P10_MAX_DISTANCE is not null and :P10_CLICK_POSITION is not null
送信するページ・アイテムとして、P10_CLICK_POSITIONとP10_MAX_DISTANCEを指定します。列のマッピングは上記のSELECT文で返される列より指定します。ジオメトリ列のデータ型はSDO_GEOMETRY、ジオメトリ列はGEOMETRY、主キー列はIDです。外観の塗りつぶしの色を#d8aa12、塗りつぶしの不透明度を.2とします。
対話モード・レポート医療機関のソースのSQL問合せに、近隣の医療機関に検索結果を限定するWHERE句を追加します。また、検索の起点から医療機関の距離を返す列DISTANCEも追加します。近隣の検索にはOracle SpatialのSDO_NNファンクションを活用しています。距離の算出にはSDO_NN_DISTANCEファンクションを使用しています。
select f.facility_id, f.zip_code, f.facility_name, f.facility_addr, f.geometry
, m.ans_type ans_type_m, e.ans_type ans_type_e, h.ans_type ans_type_h
, sdo_nn_distance(1) distance
from c19_medical_facilities f
left outer join (
select ans_type, facility_type, facility_id
from c19_medical_facility_statuses
where facility_type = 'M') m
on f.facility_id = m.facility_id
left outer join (
select ans_type, facility_type, facility_id
from c19_medical_facility_statuses
where facility_type = 'E') e
on f.facility_id = e.facility_id
left outer join (
select ans_type, facility_type, facility_id
from c19_medical_facility_statuses
where facility_type = 'H') h
on f.facility_id = h.facility_id
where
(
:P10_CLICK_POSITION is not null
and
sdo_nn(
geometry
, mdsys.sdo_util.from_geojson ( :P10_CLICK_POSITION )
, case
when :P10_MAX_DISTANCE is not null then
'distance=' || :P10_MAX_DISTANCE || ' '
end
|| 'unit=km'
, 1
) = 'TRUE'
)
and
(
:P10_NEIGHBOR_COUNT is null
or
rownum <= :P10_NEIGHBOR_COUNT
)
送信するページ・アイテムとして、P10_CLICK_POSITION、P10_MAX_DISTANCE、P10_NEIGHBOR_COUNTを指定します。
追加された列DISTANCEの表示を調整します。リージョン医療機関の列を開き、DISTANCEを選択します。ヘッダーは距離に変更します。外観の書式マスクは999G999G999G999G990D00を指定し、小数点2桁までを表示対象とします。
マップ・リージョンも対話モード・レポートと同じ変更を行います。ソースのSQL問合せ、および、送信するページ・アイテムは対話モード・レポートと同じ値にします。
最後にコピー元のページに実装されていた機能が動作するように、若干のコードの修正を行います。
ページ・プロパティのJavaScriptのファンクションおよびグローバル変数の宣言の記載を以下に変更します。ページ・アイテム名がP7_FACILITY_IDのままだったので、P10_FACILITY_IDに変更しています。それ以外でP7_FACILITY_IDとなっている部分は、ページのコピーが作成される際にP10_FACILITY_IDに変更されています。
function showFeature( pId ) {
apex.item( "P10_FACILITY_ID").setValue( pId );
apex.event.trigger( $("#medical-facilities-region"), "refresh_and_center" );
}
以上で完了です。ページを実行して記事の最初にあるGIF動画のような動作を確認してみましょう。
この記事をもって、マップ・リージョンのサンプルの解説記事は終了です。
索引がある最初の記事はこちらになります。
完