ラベル Map の投稿を表示しています。 すべての投稿を表示
ラベル Map の投稿を表示しています。 すべての投稿を表示

2021年7月16日金曜日

マップのサンプル解説 (6) - 近隣の医療機関をレポートする

 こちらの記事の続きになります。

マップ上で検索の起点となる位置を指定し、その位置の周囲に立地している医療機関をレポートに一覧します。近隣の医療機関を検索するためにOracle SpatialのSDO_NNファンクションを使用します。


マップのサンプルではNearest Neighbor Searchのページに実装されています。

このファンクションを利用するためには、ジオメトリ列に索引が作成されている必要があります。そのため、最初に表C19_MEDICAL_FACILITIESの列GEOMETRYに空間索引を作成します。

SQLワークスペースオブジェクト・ブラウザを開き、作成メニューより索引を実行します。


表名C19_MEDICAL_FACILITIES索引のタイプ空間を選択し、へ進みます。


索引名はデフォルトで設定されるC19_MEDICAL_FACILITIES_SXをそのまま使います。索引列GEOMETRY (SDO_GEOMETRY)を選択し、表にはポイント・オブジェクトのみが含まれるONにします。列の登録をクリックします。

空間メタデータの設定画面が表示されます。座標系、ディメンションの設定はデフォルトのまま変更しません。空間メタデータの追加をクリックします。


実行をクリックすると、空間メタデータの追加を行います。索引の作成はこの後に実施します。


空間索引の作成画面に戻ります。へ進みます。


索引の作成を実行します。


以上で医療機関の位置を示す列GEOMETRYに空間索引が作成されました。

続いてページの作成に進みます。

こちらの記事で作成したレポート上で選択のページをコピーします。ページ番号10ページ名近隣の医療機関とします。


ページが作成されたら作業の開始です。

マップ・リージョンにマップ上でクリックされた位置のジオメトリを保持するページ・アイテムP10_CLICK_POSITIONを作成します。タイプ非表示設定保護された値OFFにします。


ページ・アイテムP10_CLICK_POSITIONが変更されたときに対話モード・レポートのリージョン医療機関とマップ自体をリフレッシュします。P10_CLICK_POSITION上で動的アクションの作成を行います。識別名前Refresh after Changeとします。ページ・アイテム上で動的アクションの作成を実行するとタイミングイベント変更選択タイプアイテムアイテムP10_CLICK_POSITIONとなります。ですので、確認だけして設定はそのままにします。


Trueアクションとして、識別アクションリフレッシュを指定します。影響を受ける要素選択タイプリージョンリージョンに対話モード・レポートのリージョン医療機関を指定します。P10_CLICK_POSITIONが変更されたとき、つまり、マップ上をクリックしたときにレポートが更新されます。


新規にアクションの作成を行うか、作成したアクションを重複させるかして、Trueアクションを作成し、マップ・リージョンもリフレッシュします。


対話モード・レポートのリージョン医療機関検索範囲候補数を指定するためのページ・アイテムを作成します。

リージョン医療機関ページ・アイテムの作成を実行します。識別名前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とします。レポートとマップのリージョンをリフレッシュするアクションを作成します。


マップ上の位置をクリックしたときに、クリックした位置のジオメトリをページ・アイテムP10_CLICK_POSITIONに保存する動的アクションを作成します。

マップ・リージョンで動的アクションの作成を行います。識別名前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_POSITIONP10_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_POSITIONP10_MAX_DISTANCEP10_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動画のような動作を確認してみましょう。

この記事をもって、マップ・リージョンのサンプルの解説記事は終了です。

索引がある最初の記事はこちらになります。

マップのサンプル解説 (5) - マップに表示されている医療機関をレポートする

 こちらの記事の続きです。

マップに表示されている医療機関をレポートに表示します。



マップのサンプルではCircle Searchのページに実装されています。こちらの記事で作成したレポート上で選択のページをコピーします。ページ番号ページ名マップ上の医療機関とします。


ページが作成されたら作業の開始です。

マップ・リージョンにページ・アイテムP9_BBOXを作成します。このページ・アイテムは、マップ・リージョンに表示されている領域のジオメトリを保存します。タイプ非表示設定保護された値OFFにします。


マップ・リージョンのAttributesを開き、詳細境界ボックス・アイテムとしてP9_BBOXを指定します。この設定により、マップに表示されている領域がP9_BBOXに保存されます。


マップの表示倍率が低いと多数の医療機関がマップ上に表示されます。それらすべての医療機関をレポートに一覧する代わりに、マップの倍率を上げるよう警告を表示します。

最初にレイアウトを調整するためのリージョンを作成します。リージョンの作成を実行し、Content Bodyの直下に配置します。識別タイトルレポートとします。タイプ静的コンテンツ外観テンプレートとしてBlank with Attributes (No Grid)を選択します。


対話モード・レポートのリージョン医療機関レイアウト親リージョンレポートに変更します。


警告を表示するリージョンを作成します。リージョンの作成を実行し、識別タイトルレポートなしとします。ソーステキストとして以下を記述します。
詳細のレポートを表示するには、マップの表示領域が広すぎます。
レポートを表示するにはマップを拡大してください。
レイアウト親リージョンレポートとし、外観テンプレートAlertを選択します。


これで、レポートの準備はできました。

マップの表示領域が変わったときに(ズームイン、ズームアウトされたとき)動的アクションを起動し、医療機関のレポートをリフレッシュします。

マップ・リージョンで動的アクションの作成を実行します。

識別名前Refresh Reportとします。タイミングイベントマップが変更されました [マップ]です。選択タイプリージョンリージョン..マップを選びます。クライアント側の条件として、タイプJavaScript式を選び、JavaScript式に以下を記述します。

$v("P9_BBOX") !== ""
&&
apex.region("medical-facilities-region").call("getMapCenterAndZoomLevel").zoom >= 12

P9_BBOXに値が設定されていて、かつ、マップの倍率が12を超えているときに、マップに表示されている医療機関をレポートに一覧します。


最初のTrueアクションとして、識別アクションリフレッシュ影響を受ける要素選択タイプリージョンリージョン..医療機関を指定します。このアクションによって医療機関のレポートが更新されます。


警告のリージョンを非表示にします。TRUEアクションの作成を実行し、識別アクション非表示とします。影響を受ける要素選択タイプリージョンリージョン..レポートなしとします。


動的アクションのクライアント側の条件に一致しない場合、警告のリージョンを表示させます。作成したTrueアクションコンテキスト・メニューを開き反対のアクションの作成を実行します。


TRUEアクションの作成を実行し、医療機関のレポート表示します。識別アクション表示影響を受ける要素選択タイプリージョンとし、リージョン..医療機関を選びます。


このアクションについても、反対のアクションの作成を実行します。


P9_BBOXとして保存されるジオメトリが検索結果に反映されるよう、レポートおよびマップのソースであるSQL問合せを更新します。

対話モード・レポートの医療機関ソースSQL問合せは以下になります。P9_BBOXとして設定されている領域に接しているか含まれる位置に存在する医療機関に限定されるよう、WHERE句でSDO_ANYINTERACTファンクションが使用されています。

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
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
:P9_BBOX is not null
and
sdo_anyinteract(
geometry,
mdsys.sdo_util.from_geojson( :P9_BBOX )
) = 'TRUE'

送信するページ・アイテムP9_BBOXを指定します。


マップのソースのSQL問合せには以前の作業でWHERE句が付けられています。今回の用途では不要なので削除します。以下のSQLになります。

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
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

送信するページ・アイテムに設定されているP9_FACILITY_IDは不要なので削除します。


以上で完了です。ページを実行して記事の最初にあるGIF動画のような動作を確認してみましょう。

索引がある最初の記事はこちらになります。

マップのサンプル解説 (4) - 円形ツールを使う

こちらの記事の続きです。

マップ上で円形ツールを使って選択した医療機関をレポートに表示します。


マップのサンプルではCircle Searchのページに実装されています。ひとつ前の記事で作成したレポート上で選択のページをコピーします。ページ番号、ページ名はマップ上で選択とします。

ページが作成されたら作業の開始です。

対話モード・レポートにページ・アイテムP8_CIRCLE_GEOJSONを作成します。タイプ非表示設定保護された値OFFにします。マップ上で円形ツールを使って指定した領域をGeoJSONの形式で保持するために使用します。


円形ツールで指定した領域をP8_CIRCLE_GEOJSONに保存する動的アクションを作成します。

マップ・リージョンで動的アクションの作成を実行します。識別名前Circle Finishedタイミングイベントマップが変更されました[マップ]選択タイプリージョンリージョン..マップを選択します。

クライアント側の条件として、タイプJavaScript式を選び、JavaScript式として以下を記述します。

this.data && this.data.changeType === "circle-drawn"

詳細イベント有効範囲動的にします。


最初のTrueアクションとして、値の設定を作成します。設定タイプの設定JavaScript Expressionを選択します。JavaScript式として以下を記載します。

( this.data.circle ? JSON.stringify( this.data.circle.data.geometry ) : "" )

影響を受ける要素選択タイプアイテムアイテムとしてP8_CIRCLE_GEOJSONを指定します。これで this.data.circle.data.geometry として取得される円形ツールで指定した領域が、GeoJSON形式でページ・アイテムP8_CIRCLE_GEOJSONに設定されます。


ページ・アイテムP8_CIRCLE_GEOJSONに領域の情報が設定されたので、対話モード・レポートのリージョンとマップ・リージョンをリフレッシュして、検索結果に反映させるアクションを作成します。

TRUEアクションの作成を実行し、識別アクションリフレッシュとします。影響を受ける要素選択タイプリージョンリージョンとして対話モード・レポートのリージョンである医療機関を指定します。


同様の手順で、マップ・リージョンをリフレッシュするアクションを作成します。


最後にTRUEアクションとしてJavaScriptコードの実行を作成します。円形ツールで選択した領域をクリアします。設定コードには以下を記述します。

apex.region( "medical-facilities-region" ).call ( "clearCircle" );


円形ツールによって指定された領域に含まれる医療機関のみが検索されるよう、対話モード・レポートとマップ・リージョンのSQL問合せを更新します。Oracle SpatialのSDO_ANYINTERACTファンクションを使用します。

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
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
:P8_CIRCLE_GEOJSON is null
or
sdo_anyinteract(
geometry,
mdsys.sdo_util.from_geojson( :P8_CIRCLE_GEOJSON)
) = 'TRUE'

対話モード・レポートのSQL問合せを更新します。送信するページ・アイテムP8_CIRCLE_GEOJSONを追加します。


マップ・リージョンのSQL問合せも更新します。送信するページ・アイテムP8_CIRCLE_GEOJSONを追加します。


円形ツールで指定した領域をマップ上に表示するために、新規にレイヤーを作成します。

レイヤーの作成を実行し、識別名前検索範囲とします。レイヤー・タイプポリゴンです。ソースSQL問合せに以下のSELECT文を記述します。

select 0 as id,
mdsys.sdo_util.from_geojson( to_clob( :P8_CIRCLE_GEOJSON )) as geometry
from sys.dual
where :P8_CIRCLE_GEOJSON is not null

送信するページ・アイテムP8_CIRCLE_GEOJSONを指定します。


列のマッピングジオメトリ列のデータ型SDO_GEOMETRYを選択し、ジオメトリ列GEOMETRYとします。主キー列IDを選択します。外観塗りつぶしの色にベージュ#d8aa12を指定し、塗りつぶしの不透明度は .2 とします。


以上で完了です。ページを実行して記事の最初にあるGIF動画のような動作を確認してみましょう。

索引がある最初の記事はこちらになります。