tpc27-2

TOPIC 27|3D都市モデルに別の地理空間情報を紐づけて利活用する[2/2]│PLATEAU DataLinkerの活用

PLATEAUには、「建物名」「高さ」「土地利用」「災害リスク」などのさまざまな地理空間情報が格納されています。一方、地方公共団体や企業が独自に公開している地理空間情報もあります。これらを紐づければ、検索や分析の幅が広がります。それを実現するのが「PLATEAU DataLinker」です。

Share

PLATEAUには、「建物名」「高さ」「土地利用」「災害リスク」などのさまざまな地理空間情報が格納されています。一方、地方公共団体や企業が独自に公開している地理空間情報もあります。これらを紐づければ、検索や分析の幅が広がります。それを実現するのが「PLATEAU DataLinker」です。

このトピックの内容は「PLATEAU DataLinkerを活用した3D都市モデルへの地理空間情報紐づけと活用法」(2024年度PLATEAU Hands-onアーカイブ動画)でも制作方法をハンズオン形式で紹介しています。

後半では、PLATEAU DataLinkerの活用方法を紹介します。

【目次】

27.4   CSV出力を利用してノーコードでアプリを作る

 27.4.1  作成するアプリの構成

 27.4.2  事前準備

 27.4.3  Glideを使った開発の実際

27.5   紐づけられたCityGMLをUnityで活用する

 27.5.1  作成するアプリの構成

 27.5.2  紐づけデータの作成

 27.5.3  Unityを使った開発の実際

27.6   まとめ

27.4 _ CSV出力を利用してノーコードでアプリを作る

PLATEAU DataLinkerを使って紐づけたデータは、さまざまな用途に活用できます。 

第一の活用例として、「授乳室がある建物のうち、高さが10m以上のもの」を地図上にピン表示するスマホアプリをノーコードで構築する例を示します。この実例は、浸水などの災害時でも使える授乳施設の検索を想定したものです。

【メモ】

高さ10m以上は、およそ、建物の3階建てに相当します。各公共団体(国土交通省も含め)は、水害時のハザードマップの浸水深の目安を「1階の床から1階の天井まで」「1階の天井から2階の天井近くまで」「2階の天井以上」の3区分で公表しています。3階以上が浸水する場所は河川付近等の限られた場所であるため、ここで例としている「10m以上」という条件は、浸水時でも利用可能な施設と予想できます。なお、PLATEAUの3D都市モデルには、「災害リスク(浸水)モデル」と「災害リスク(土砂災害)モデル」も含まれています。QGISなどのGISを使ってこうした情報と組み合わせれば、地域単位で条件を絞り込むこともできます(「TOPIC 21|QGISを用いた災害リスク情報の可視化と分析[2/2]|災害リスク情報を可視化する」を参照)。

図27-27 授乳室がある建物のうち、高さが10m以上のものをピン表示するスマホアプリ

27.4.1 _ 作成するアプリの構成

今回のアプリ開発には、「Glide(グライド)」を使用していきます。

Glideは、ノーコードの業務アプリ開発ツールです。データを操作するさまざまなコンポーネントが提供されており、各種データと連係し、そのデータを表示したり更新したりできます。リレーショナルデータベースだけでなく、「Googleスプレッドシート」「Excelワークシート」「CSVファイル」など、表形式のファイルをデータ連係できるのが大きな特徴です。

Glideには、地図を表示する「Mapコンポーネント」があり、経緯度情報を含むデータと連係すると、地図上にピン表示できます。図27-27に示した地図は、この機能で実現しています。

TOPIC 27|3D都市モデルに別の地理空間情報を紐づけて利活用する[1/2]│PLATEAU DataLinkerの紹介と実例】で作成した「おむつがえ・授乳施設一覧(町田市)」を「PLATEAUの該当地域の3D都市モデル」に紐づけ、それをCSV形式に変換したファイルをMapコンポーネントに紐づけます。

「おむつがえ・授乳施設一覧(町田市)」単体でも、授乳施設の場所をピンで表示できます。しかし建物の情報がないので、「高さが10m以上」という条件での絞り込みができません。そこでPLATEAUの3D都市モデルと紐づけることで、建物の高さでの絞り込みが可能になります。3D都市モデルにおいては、高さは「計測高さ(bldg:measuredHeight)」という属性に格納されており、PLATEAU DataLinkerではデフォルトで「建物の高さ uom=m」という列名で変換されます。

【メモ】

CSVに出力する際、属性値を含む列は、空白で区切って、その属性値が列名に追加されます。bldg:measuredHeight属性には、CityGML上で計測単位がメートルであることを示す「uom=m」という属性が付いているため、出力列名のデフォルトは、実際には、「建物の高さ uom=m」となります。

【メモ】

PLATEAUでは、建物の階数を「地上階数(bldg:storeysAboveGround)」という属性に格納している地域もあります。そうした地域では、高さ10m以上という条件の代わりに、この属性でフィルタリングするのも良いでしょう。

【メモ】

スマホアプリに表示されている地図は、GlideのMapコンポーネント(その実体はMapBoxという地図サービス)によるものであり、PLATEAUの地図を表示しているわけではありません。この作例では、Mapコンポーネントで表示した(PLATEAUではない)地図上において、PLATEAU DataLinkerで出力した施設情報のCSVファイルに記載された施設の経緯度にピンを表示しているだけです。

図27-28 高さ10m以上の建物にある授乳施設を一覧表示する仕組み

27.4.2 _ 事前準備

このようなスマホアプリを作るにあたって、いくつか事前準備をします。

■ Glideのアカウント

Glideを利用するには、ユーザー登録が必要です。個人開発からエンタープライズまで幅広いライセンスが用意されていますが、個人開発であればフリー版を無償で利用できます。

下記のページに従って、Glideのアカウントを作成してください。執筆時点においては、トップページで[Start for free]をクリックすると、アカウントの作成を始められます。以下では、個人用の無償アカウントを作成した前提で進めます。

【Glide】

https://www.glideapps.com/

図27-29 Glideのトップページ
図27-30 アカウントを作成する

■ 授乳施設の情報が格納されたCSVデータ

図27-28に示した構成において、Mapコンポーネントと結びつけるCSVデータ――すなわち、建物の高さ情報を追加した「おむつがえ・授乳施設」のデータ――を用意します。

ここでは「PLATEAU DataLinkerを使った紐づけの実例」における作業と同様にして、授乳施設情報をPLATEAUの3D都市モデルに紐づけたものを用います。具体的には、同等の作業を町田市の全CityGMLファイルに対して作業して、CSVとしてダウンロードします。それらをExcelで開き、ひとつにまとめます。その後、Excelのフィルタ機能を使って施設名が空欄のものに絞り込み、それらを削除します。

ただし、Glideで地図を扱うMapコンポーネントでは、経緯度が「緯度,経度」の順のカンマ区切りのデータでなければならないという決まりがあります。そこでさらに、Excelの計算式を使って変更する(コラム「ChatGPTを使わない方法」や「Excelで置換して、スペース区切りからカンマ区切りにする」などを参照)もしくはChatGPTで変換したりするなどして、何かしらの方法でこの書式に変換します。

変換したデータの例をリスト27-1に示します。リスト27-1では「緯度経度」という列を設けました。以下ではこのデータを使っていきます。

【メモ】

PLATEAU DataLinkerを活用した3D都市モデルへの地理空間情報紐づけと活用法」(2024年度PLATEAU Hands-onアーカイブ動画)では、ChatGPTを使って経緯度の書式を変換する例を示しています。

GML ID,建物の高さ(m) uom=m,緯度経度,施設名,住所,電話番号 
bldg_a860e7d5-e18b-4fc0-a76f-96e950b60735,12.2,"35.60077922,139.3779912",スーパースポーツゼビオ多摩境店,東京都町田市小山ヶ丘3-5-1,042-798-6286
bldg_0f40c413-780c-4c86-a638-ce60f281b44f,,"35.59768992,139.4632931",花の木保育園,東京都町田市真光寺3-1-6,042-734-6113
bldg_8e257cd1-63de-4af1-b131-2fea3feeb780,31.1,"35.59192333,139.4386049",町田GIONスタジアム(町田市立陸上競技場),東京都町田市野津田町2035,042-735-4511
bldg_cabde403-807d-4f15-9bb8-fe22c81bb6df,9.4,"35.59872631,139.3816645",トイザらス・ベビーザらス 町田多摩境店,東京都町田市小山ヶ丘1-7-2,042-798-2138
bldg_201983f0-0e6d-49de-8499-636a5493168b,7.4,"35.58749856,139.4782692",ききょう保育園,東京都町田市鶴川1-16-7,042-735-2242
bldg_ec89eaf2-f4b1-4e87-a5d9-6ed68589a1b1,7.9,"35.58755839,139.4818157",みどりの森保育園,東京都町田市能ヶ谷4-7-19,042-708-8161
bldg_024f9261-2ec5-408f-a481-56b5045b93e5,7.2,"35.58796989,139.4654126",ぽっぽの森保育園(かのんカフェ),東京都町田市大蔵町410,042-860-1515
bldg_25880fe3-11bd-43a8-b868-7c5884f0f1f6,9.8,"35.58987883,139.4659195",子どもセンターつるっこ,東京都町田市大蔵町1913,042-708-0236
bldg_949081c9-b436-4149-bd2d-af7951c70704,15.5,"35.58888656,139.4673706",鶴川市民センター(鶴川保健センター併設),東京都町田市大蔵町1981-4,042-735-5704
bldg_4eaf83e6-91f6-44b8-b1d2-911b2c4d7edf,10,"35.58861389,139.467863",市立大蔵保育園(鶴川地域子育て相談センター),東京都町田市大蔵町1984,042-735-3600
bldg_febb8c37-5894-471f-875f-c5c0bad73dca,8,"35.58916633,139.4597705",西松屋チェーン町田大蔵店,東京都町田市大蔵557,042-735-6515
bldg_5af70412-9e05-42bc-a48b-5849bff58161,7.9,"35.589389,139.4606067",井の花保育園,東京都町田市大蔵町530-1,042-708-9541
bldg_b9dfe00c-4d9c-480f-8b81-abe7d493b68b,21.4,"35.58630764,139.4138148",市立室内プール,東京都町田市図師町199-1,042-792-7761
bldg_bd958cee-eb26-43cb-b449-11e884634cae,9.6,"35.59167761,139.3808414",トヨタ西東京カローラ町田小山店,東京都町田市小山町776-4,042-798-0033
bldg_f349e012-ac5a-4d0e-96c2-9a6ca63e5549,7.7,"35.59122853,139.3807892",かえで保育園,東京都町田市小山町775,042-798-0511

リスト27-1 今回用いるCSV形式ファイル(CsvData.csvファイル)

図27-31 町田市全域のCityGMLに対して結合したCSV出力。それらを結合して施設名が空欄のものを除外、さらに経緯度の列を「緯度,経度」の書式に変更したものを使う
コラム:Excelで置換して、スペース区切りからカンマ区切りにする

ChatGPTではなくExcelで連結するには、例えば「緯度 スペース 経度」のように、スペース区切りの列があるなら、それをSUBSTITUTE関数を使って「=SUBSTITUTE(C2, " ", ",")」などのように、スペースをカンマに置換します。

図27-32 すべての列を含むようにしてCSV出力。その後、経度緯度の列を「緯度,経度」の書式に変更したものを使う

27.4.3 _ Glideを使った開発の実際

準備が整ったら、Glideを操作して実際にスマホアプリを作っていきます。

■ CSVファイルを読み込んでアプリのひな形を作る

まずは、アプリのひな形を作ります。

【手順】Glideでスマホアプリを作る

[1]新規アプリを作成する

[New app]をクリックして、新規アプリを作成します。

【メモ】

Glideのアカウント作成直後にウィザードによってデモのアプリが自動で作られた場合は、デモのアプリを閉じて、新規に進めてください。

図27-33 新規アプリを作成する

[2]テンプレートを選択する

テンプレートの選択画面が表示されます。今回は、すでにあるデータファイルを基に作りたいので、[Import File]を選択し、[Continue]をクリックします。

図27-34 [Import File]のテンプレートを選択する

[3]CSVファイルを選択する

インポートするファイルを設定します。[Choose a file]を選択してリスト27-1のファイルを選択し、[Continue]をクリックします。

図27-35 CSVファイルを選択する

[4]アプリのひな形ができあがった

アプリのひな形ができあがりました。作られたアプリには[読み込んだファイル名(画面上ではCsvData)]と[Users]の2つのタブがあり、画面下でクリックすると切り替えられます。

[読み込んだファイル名]タブのほうには、読み込んだCSVファイルの情報が表示されています。そして[Users]タブには、開発者である自分のアイコンなどの情報が表示されています。

これらのタブは、左上の[NAVIGATION]に表示されているそれぞれの項目に相当します。内容を変更したいときは、[NAVIGATION]の部分で切り替えて編集します。

【メモ】

アプリのタイトルはCSVファイル名に基づいて決められるため、インポートしたファイル名によって異なります。

図27-36 CSVを一覧表示するアプリができあがった

■ 読み込んだデータの確認

画面上部の[Data]タブをクリックすると、読み込んだデータを確認できます。このあとの作業において、地図のコンポーネントにこの読み込んだデータの列を設定していくので、データの構造を確認しておきましょう。とくに「経緯度の列」とその書式を確認しておいてください。この例では「経度緯度」という列名とし、「緯度,経度」のように「緯度」と「経度」がカンマで区切った書式にしています。列名はあとで設定できるので任意ですが、書式は、このとおりでなければなりません。

図27-37 読み込んだデータを確認する

■ 地図表示する

次に、このアプリを修正して、地図を表示できるようにしていきます。

【手順】地図表示する

[1]一覧表示のコンポーネントを削除する

CSVを一覧表示しているコンポーネントの削除をします。一覧表示はCollectionコンポーネントが担当しており、画面左側の[COMPONENTS]の中にあります。これをマウスオーバーし、[×]をクリックして削除します。

図27-38 Collectionを削除する

[2]Mapコンポーネントを追加する

地図を表示するため、Mapコンポーネントを設置します。[COMPONENTS]の右の[+]をクリックすると利用可能なコンポーネント一覧が表示されるので、[Map]を検索して追加します。

配置すると、地図が表示されます。配置直後は中サイズ(Medium)なので、[Large]をクリックして、大きくします。

図27-39 Mapコントロールを追加する
図27-40 大きくしたところ

[3]地図データを設定する

Mapコントロールに対して、すでに読み込み済みの授乳施設情報CSVデータを設定します。
次の項目を設定します。

[DATA]

読み込むデータを設定する項目です。[Source]で授乳施設情報のCSVデータを選択します。

[ITEMS DATA]

Mapコントロール上でピン表示するデータを設定する項目です。Sourceで選択したデータの、どの列をどのように扱うのかを設定します。

[Address]には「緯度,経度が格納された列」を設定します。ここで指定した場所に地図上でピンが立ちます。[Address]を適切に設定すると、その範囲を含む地図範囲に拡大され、実際にピン留めされた位置がわかります。

必須なのはAddressだけですが、さらに追加の情報も設定しておきます。[Title]は見出しに相当します。ここでは[施設名]を選択しておきます。[Description]は詳細情報です。ここでは[電話番号]を選択しておきます。

図27-41 DATAとITEMS DATAを設定する

[4]動作を確認する

この段階で地図表示ができています。Mapコントロールをドラッグすれば、地図をスクロールできます。そしてピンをクリックすれば、TitleやDescriptionで設定した情報が表示されます。

【メモ】

繰り返しになりますが、ここで表示されている「地図」はMapコントロールが表示している地図であり、PLATEAUの地図ではありません。私たちが用意したデータは、地図上に「ピン」として表示されているにすぎません。

図27-42 ピンをクリックしたところ

■ 高さの条件を設定する

これで施設の場所をピン表示できました。次に、「高さが10m以上の建物にある授乳施設」のみに絞り込みます。絞り込みは、Mapコンポーネントの[Options]タブの[FILTER DATA]から設定できます。CityGML上では、建物の高さはbldg:measuredHeightという属性に格納されています。PLATEAU DataLinkerで変換したデータでは、「建物の高さ(m) uom=m」という列がそれに相当します。

【メモ】

「建物の高さ(m) uom=m」に変換されるのは、デフォルトの命名規則を用いている場合です。属性と列名との関係は、変換時に列ごとにテキストボックスで指定できます。

図27-43 高さは[建物の高さ(m) uom=m]の列に格納されていることを前提とする

【手順】高さが10m以上の授乳施設に絞り込む

[1]フィルタを追加する

[Options]タブの[FILTER DATA]の項目にある[Add Filter]をクリックしてフィルタを追加します。

図27-44 フィルタを追加する

[2]高さが10m以上という条件を設定する

フィルタの追加画面が表示されます。[建物の高さ(m) uom=m][≧][10]と設定します。設定すると同時に、画面上に表示されているピンもリアルタイムで条件を満たすものだけに絞り込まれます。

図27-45 フィルタ条件を設定する
コラム:作ったアプリを実際に公開する

以上で、Glideを使ったスマホアプリの作成は完了です。右上の[Publish]をクリックすると、これを公開して、実際にスマホで試せます。

Publishすると、URLが割り当てられます。表示されたQRコードをスマホで読み込んだり、URLを入力したりすることでアクセスできます。なお、スマホだけでなくPCでも利用できます。

デフォルトではプライベートな状態で公開されます。誰もが使えるようにするには[Privacy]タブで、[ACCESS]を[Public]に、[SIGN-IN]を[No sign-in]に、それぞれ設定します。

図27-46 Publishする
図27-47 URLが発行された
図27-48 Publishの設定変更

27.5 _ 紐づけられたCityGMLをUnityで活用する

第二の活用例として、Unityから扱う実例を示します。ここでは、車椅子使用者対応トイレのバリアフリー設備情報とPLATEAUの3D都市モデルを組み合わせ、「3階以下」に該当のトイレがある建物だけを色づけして表示する例を示します。

図27-49 3階以下に該当のトイレがある建物だけを色づけする

27.5.1 _ 作成するアプリの構成

このアプリでは、東京都オープンデータカタログサイトから入手できる「車椅子使用者対応トイレのバリアフリー情報(令和5年度更新版)」の「都立及び区市町村立施設等における車椅子使用者対応トイレのバリアフリー設備情報」というCSV形式データを使います。

このCSV形式ファイルには、車椅子使用者対応トイレが設置されている施設名やトイレ名、経緯度のほか、設置フロアという列があり、階数もわかります。このアプリでは、この設置フロアの情報を確認して3F以上かどうかを判定します。

【車椅子使用者対応トイレのバリアフリー情報(令和5年度更新版)】

https://catalog.data.metro.tokyo.lg.jp/dataset/t000054d0000000342

図27-50 車椅子使用者対応トイレのバリアフリー情報(令和5年度更新版)
図27-51 データをプレビューすると、[設置フロア]の列に階数が収録されていることがわかる

PLATEAU SDK for Unityを使うと、UnifyにPLATEAUの3D都市モデルを読み込めますが、このアプリ構築では、読み込む3D都市モデルに対してあらかじめPLATEAU DataLinkerを用いて、車椅子使用者対応トイレのバリアフリー情報(令和5年度更新版)のCSVファイルを紐づけ、その紐づけ後のデータをインポートします。するとUnityからは、もともとの3D都市モデルにはないCSVファイルに記載されたデータも参照できるようになります。

図27-52 属性を追加したPLATEAUの3D都市モデルをUnityでインポートする

27.5.2 _ 紐づけデータの作成

まずは、車椅子使用者対応トイレのバリアフリー設備情報を準備して、PLATEAUの3D都市モデルと紐づけます。

■車椅子使用者対応トイレのバリアフリー設備情報のダウンロード

東京都オープンデータカタログサイトから入手できる「車椅子使用者対応トイレのバリアフリー情報(令和5年度更新版)」の「都立及び区市町村立施設等における車椅子使用者対応トイレのバリアフリー設備情報」というCSV形式ファイルをダウンロードしておきます。

【車椅子使用者対応トイレのバリアフリー情報(令和5年度更新版)】

https://catalog.data.metro.tokyo.lg.jp/dataset/t000054d0000000342

■データの加工

ダウンロードしたファイルをPLATEAU DataLinkerで紐づけられる形式に変更します。「PLATEAU DataLinkerを使った紐づけの実例」で解説したように、次の2つの修正が必要です。

① 文字コード

文字コードをUTF-8に変更します。

② 緯度と経度の結合

緯度の列と経度の列を結合して「緯度 経度」のように空白区切りのデータとします。

こうした整形をして、リスト27-2に示す構造のファイルに変換します。経度と緯度は、「緯度経度」という列として追加しました。

管理者種別番号,部局番号,施設種別番号,施設通し番号,施設内トイレ通し番号,施設名,都道府県,市区町村・番地,ビル建物名,トイレ名,設置フロア,経度,緯度,緯度経度,座標系,性別の分け,トイレへの誘導路として点字ブロックを敷設している,トイレの位置等を音声で案内している,戸の形式,車椅子が出入りできる(出入口の有効幅員80cm以上),車椅子が転回できる(直径150cm以上の円が内接できる),便座に背もたれがある,便座に手すりがある,オストメイト用設備がある,オストメイト用設備が温水対応している,大型ベッドを備えている,乳幼児用おむつ交換台等を備えている,乳幼児用椅子を備えている,非常用呼び出しボタンを設置している,利用できる時間は、通年変わらない,月曜日,火曜日,水曜日,木曜日,金曜日,土曜日,日曜日,祝日,その他,季節によって利用可能が異なる場合の期間,月曜日2,火曜日2,水曜日2,木曜日2,金曜日2,土曜日2,日曜日2,祝日2,その他2,季節によって利用可能が異なる場合の期間,月曜日3,火曜日3,水曜日3,木曜日3,金曜日3,土曜日3,日曜日3,祝日3,その他3,写真データ(トイレの入り口),写真データ(トイレ内),写真データ(トイレ内(別角度)),備考,データの作成年月 , データの変更年月, データの削除年月,,,,
13000,3,1,2,1,東京都人権プラザ,東京都,港区芝二丁目5番6号,芝256スクエアビル1・2階,多機能トイレ,1F,139.751659,35.652592,35.652592 139.751659,JGD2011,共用,×,○,C.手動引き戸,○,○,○,○,○,○,○,○,○,○,○,0930_1730,0930_1730,0930_1730,0930_1730,0930_1730,0930_1730,,0930_1730,日曜日・年末年始は休館となるため、利用できない,,,,,,,,,,,,,,,,,,,,,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_002_01_1.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_002_01_2.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_002_01_3.jpg,※ 音声案内は今年度設置予定,201901,202211,,,,,
13000,3,1,1,1,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,201901,,202401,,,,
13000,3,7,16,1,大浦野営場,東京都,東京都新島村式根島,,大浦野営場 便所,1F,139.209249,34.330566,34.330566 139.209249,JGD2011,共用,×,×,C.手動引き戸,○,○,×,×,×,×,×,○,×,×,○,0000_2359,0000_2359,0000_2359,0000_2359,0000_2359,0000_2359,0000_2359,0000_2359,,,,,,,,,,,,,,,,,,,,,,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_07_016_01_1.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_07_016_01_2.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_07_016_01_3.jpg,,201901,202211,,,,,
13000,3,1,3,1,東京都大島支庁舎,東京都,大島町元町字オンダシ222番地1,東京都大島支庁舎,身障者用便所,1F,139.357449,34.757454,34.757454 139.357449,JGD2011,共用,×,×,C.手動引き戸,○,×,×,○,×,×,×,×,×,○,○,0830_1715,0830_1715,0830_1715,0830_1715,0830_1715,,,,,,,,,,,,,,,,,,,,,,,,,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_003_01_1.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_003_01_2.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_003_01_3.jpg,,201901,202401,,,,,
13000,3,1,3,2,東京都大島支庁舎,東京都,大島町元町字オンダシ222番地1,東京都大島支庁舎,身障者用便所,2F,139.357449,34.757454,34.757454 139.357449,JGD2011,共用,,,,,,,,,,,,,,○,0830_1715,0830_1715,0830_1715,0830_1715,0830_1715,,,,,,,,,,,,,,,,,,,,,,,,,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_003_02_1.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_003_02_2.jpg,http://www.opendata.metro.tokyo.jp/fukushihoken/wc-photos/13000_03_01_003_02_3.jpg,,,202401,,,,,
…略…

リスト27-2 整形したCSVデータ(文字コードはUTF-8)

■ 3D都市モデルのダウンロード

このCSVデータをPLATEAUの3D都市モデルと紐づけます。結びつける地域はデータがある範囲ならどこでもよいですが、今回は浜松町駅周辺(3次メッシュコード「53393680」)を例として扱います。

この地域は東京都の3D都市モデルに含まれます。まずは、G空間情報センターからダウンロードします。

【3D都市モデル(Project PLATEAU)東京都23区】

https://www.geospatial.jp/ckan/dataset/plateau-tokyo23ku

図27-53 今回扱う浜松町駅周辺の範囲(画面はjSTAT MAPで確認したところ)
図27-54 G空間情報センターから東京都の3D都市モデルをダウンロードする

■ データの紐づけ

さて、このように「車椅子使用者対応トイレのバリアフリー情報のCSVファイル(緯度経度の列を修正し、UTF-8として保存したもの)」と「PLATEAUの3D都市モデルのCityGMLファイル(G空間情報からダウンロードしたもの)」が準備できたら、PLATEAU DataLinkerを使って紐づけます。

左側(①PLATEAU)でCityGMLファイル(53393680_bldg_6697_2_op.gml)、右側(②紐づけたいデータ)でCSVファイルを選択します。[紐づける属性]では[建物の座標(経度緯度)]とCSV上の緯度経度の列を選択します。

「③『紐づけたいデータ』から追加したい属性を選択し、属性名を記入してください」では、すべての項目にチェックを付けてGMLファイルを生成します。

図27-55 PLATEAU DataLinkerで紐づけする

紐づけたファイルをPLATEAUの3D都市モデルが置かれていた場所に、元のファイルと同名で上書きします。これで、もともとの3D都市モデルにCSVファイルのデータが追加された状態になります。

図27-56 変換後のファイルで上書きした

27.5.3 _ Unityを使った開発の実際

準備が整ったところで、Unityを使って、実際にアプリを作っていきます。

■ PLATEAU SDKで紐づけ後のCityGMLファイルを読み込む
PLATEAU DataLinkerで追加したデータは、元のCityGMLファイルに属性を追加しただけなので、PLATEAU SDKを使って、そのまま読み込めます。「PLATEAU SDKでの活用」と同じ手順で、紐づけ後のCityGMLファイルを読み込みます。

【メモ】

本チュートリアルでは、Unityを日本語化したものを使っています。日本語していない場合もメニュー名が異なるだけで、操作方法は同じです。

【手順】紐づけ後のCityGMLファイルを読み込む

[1]プロジェクトを新規作成する

Unityを起動して、プロジェクトを新規作成します。ここでは、[3D]テンプレートを使って作成します。

図27-57 プロジェクトを新規作成する

[2]PLATEAU SDKをインストールする

PLATEAU SDKのリリースページから、PLATEAU SDKのtgz形式ファイルをダウンロードします。

Unityの[ウィンドウ]から[パッケージマネージャ]をクリックして、パッケージマネージャを開きます。左上の[+]をクリックし、[.tgzファイルからパッケージを加える]を選択して、ダウンロードしたPLATEAUのtgz形式ファイルを追加します。

【メモ】

PLATEAU SDKインストールの詳細については、PLATEAU SDK for Unityのドキュメントを参照してください。

図27-58 ダウンロードしたPLATEAU SDKのtgzファイルを追加する

[3]PLATEAU SDKを起動する

PLATEAU SDKを追加すると、Unity Editorに[PLATEAU]メニューが追加されるので、[PLATEAU]―[PLATEAU SDK]をクリックして起動します。

[4]3D都市モデルをインポートする

PLATEAU SDKで、該当のCityGMLを選択します。[インポート元]で[ローカル]を選択し、PLATEAUの3D都市モデルをダウンロードしたフォルダを選択します(このフォルダ以下のbldgフォルダは、図27-56に示したように、あらかじめ紐づけ後のデータで上書きしておきます)。

[①基準座標系の選択]では、[09:東京(本州)、福島、栃木、茨城、埼玉、千葉、群馬、神奈川]を選択し、[選択範囲]を選択します。

図27-59 3D都市モデルが置かれたフォルダを選択する

そして読み込みたい範囲を選択します。ここでは、紐づけたデータ(先ほど上書きしたファイル)に相当するメッシュコード「53393680」を選択し、[決定]をクリックします。

【メモ】

[メッシュコード検索]をクリックするとメッシュコードを入力でき、該当の地域が拡大表示されます。

図27-60 メッシュコード「53393680」の領域を選択する

するとPLATEAU SDKのウィンドウに戻るので、どのデータをどのようにインポートするのかを決めます。ここでは次のように設定して、建築物のLOD1のみを属性情報付きでインポートします。

【一括設定】

[属性情報を含める]にチェック。他の項目は任意。

【建築物】

[インポートする]にチェック。LOD描画設定を「1」にする。

【橋梁、道路、災害リスク、都市計画決定情報、土地利用】

[インポートする]のチェックを外す。

図27-61 建築物のみをLOD1でインポートする

[5]モデルがインポートされた

3D都市モデルがインポートされ、建物が表示されました。

図27-62 建物が表示された

■ 3F以下に車椅子使用者対応トイレがある建物を色づけする

見かけは、普通に3D都市モデルをインポートした場合と同じですが、読み込んだデータには、PLATEAU DataLinkerで紐づけした属性が含まれています。

この属性を利用して、「3F以下に車椅子使用者対応トイレがある建物」を色づけします。紐づけ対象のCSVからわかるように、トイレが設置されている階数は[設置フロア]列に格納されています(前掲の図27-51を参照)。そこでこの値を参照して、「3F以下のとき」に青色にします。

いくつかのやり方がありますが、ここではPLATEAU SDKで読み込んだ3D都市モデルのオブジェクトの親となるオブジェクトに対して、配下のオブジェクトの属性を調べ、設置フロアが3F以下のときに青色のマテリアルを設定するスクリプトを実行するように構成します。

具体的な手順は、以下のとおりです。

【手順】読み込んだ3D都市モデルにおいて、設置フロアに3F以下の属性が設定されている建物を青色にする

[1]スクリプトをコピーする

該当の処理をするスクリプトをあらかじめ用意し、プロジェクトのAssetsフォルダに配置しておきます。ここでは、リスト27-3に示すFilter.csを使います。Filter.csの処理の詳細については、後述します。

using UnityEngine; 
using System.Reflection;
using System.Text;
using System.Linq;
using PLATEAU.CityInfo;

public class Filter : MonoBehaviour
{
// インスペクターで親オブジェクトを指定するための変数
public GameObject parentObject;

void Start()
{
if (parentObject != null)
{
// 親オブジェクトのすべての子オブジェクトを取得
foreach (Transform child in parentObject.transform)
{
var targetObject = child.gameObject;
// PLATEAUCityObjectGroupコンポーネントを取得
var cityObjGroup = targetObject.GetComponent<PLATEAUCityObjectGroup>();
if (cityObjGroup != null)
{
Debug.Log("Component: PLATEAUCityObjectGroup");

PrintAttributesToCanvas(cityObjGroup, targetObject);
}
else
{
Debug.Log("PLATEAUCityObjectGroup component not found.");
}
}
}
else
{
Debug.Log("No parent object assigned.");
}
}

private void PrintAttributesToCanvas(PLATEAUCityObjectGroup cityObjGroup, GameObject targetObject)
{
// インポートされた各ゲームオブジェクトには PLATEAUCityObjectGroup コンポーネントがアタッチされている
var firstPrimaryObj = cityObjGroup.PrimaryCityObjects.FirstOrDefault();
if (firstPrimaryObj != null)
{
// 設置フロアを取得
var attributesMap = firstPrimaryObj.AttributesMap;
// 設置フロアは、PLATEAUの属性情報の中では "設置フロア" というキーで格納されている
if (attributesMap.TryGetValue("設置フロア", out var attribute))
{
// 値はattribute.StringValueで取得できる
var stringValue = attribute.StringValue;
// 文字列の各文字をループで確認
foreach (char c in stringValue)
{
// 文字が数字かどうかを確認
if (char.IsDigit(c))
{
// 文字を整数に変換
if (int.TryParse(c.ToString(), out int digit))
{
// 数字が3以下かどうかを確認
if (digit <= 3)
{
// ゲームオブジェクトのRendererコンポーネントを取得
var renderer = targetObject.GetComponent<Renderer>();
if (renderer != null)
{
var materials = renderer.materials;
// 各マテリアルを青色に変更
for (int i = 0; i < materials.Length; i++)
{
// マテリアルのインスタンスを作成
materials[i] = new Material(materials[i]);
materials[i].color = Color.blue;
}
renderer.materials = materials;
}
}
}
else
{
// 変換に失敗した場合の警告ログ
Debug.LogWarning($"'{c}'は整数に変換できない");
}
}
}
}
}
}
}

リスト27-3 Filter.cs

図27-63 あらかじめスクリプトを作って登録しておく

[2]空のゲームオブジェクトを作る

このスクリプトを実行するための仕組みを作ります。いくつかのやり方がありますが、ここでは空のゲームオブジェクトを作り、そこにアタッチします。

[ヒエラルキー]ウィンドウで右クリックし、[空のオブジェクトを作成]を選択して、空のゲームオブジェクトを作ります。

図27-64 空のゲームオブジェクトを作る

[3]スクリプトのアタッチと処理対象プロパティの設定

GameObjectという名前のゲームオブジェクトができあがります。これをクリックして選択した状態にして、[インスペクター]に先ほどのFilter.csをドラッグ&ドロップして登録します。こうすることで、このGameObjectが読み込まれたときに、Filter.csファイルのStartメソッドが実行されるようになります。

詳細は次項で説明しますが、Filter.csでは操作対象の親オブジェクトを指定する「parentObject」というプロパティで定義しています。この定義がインスペクター上に表示されるので、設定します。

[ヒエラルキー]ウィンドウを確認すると、読み込んだ3D都市モデルのツリーに「LOD0」と「LOD1」があるのがわかります。これらは3D都市モデルの親要素であり、読み込んだ地物のデータはこの配下にすべて存在します。今回はこのLOD1をドラッグ&ドロップして、このツリーをFilter.csに記述したコードで処理するようにします。

// インスペクターで親オブジェクトを指定するための変数
public GameObject parentObject;
図27-65 スクリプトをアタッチして必要なプロパティを設定する

以上で完了です。[▶]ボタンをクリックして実行すると、車椅子使用者対応トイレが3F以下に存在する建物だけが、青色で表示されます。

図27-66 実行して確認したところ
コラム:インスペクターで属性を確認する

PLATEAU SDKで読み込んだ地物には、PLATEAU City Object Groupというスクリプトがアタッチされています。Unity上で建物をクリックすると、インスペクターで、その建物に関する情報を確認できますが、このとき[PLATEAU City Object Group]の表示で、属性を確認できます。

実行して確認した「青い建物」のいずれかをクリックすると、図27-67に示すように、PLATEAU DataLinkerで紐づけた「設置フロア」が「3F」などの値に設定されていることがわかります。

図27-67 インスペクターで属性を確認したところ

■ プログラムの動作

前述したリスト27-3のFilter.csでは、次のように処理をすることで、条件に合致する建物を青色にしています。

① すべての子オブジェクトに対するループ

Unityではスクリプトの処理はStartメソッドから始まります。Startメソッドでは、次のようにparentObjectプロパティ(これは図27-65で設定したもの)の子オブジェクトに対してループすることで、その配下のすべてのオブジェクトを処理するようにしています。

void Start()
{
if (parentObject != null)
{
// 親オブジェクトのすべての子オブジェクトを取得
foreach (Transform child in parentObject.transform)
{
var targetObject = child.gameObject;

② 属性値の取得と判定

PLATEAU SDKでインポートしたオブジェクトには、PLATEAUCityObjectGroupコンポーネントがアタッチされており、このコンポーネントを経由して、属性値を参照できます。以下では、属性値を取得し、PrintAttributesToCanvasメソッドに渡しています。

// PLATEAUCityObjectGroupコンポーネントを取得
var cityObjGroup = targetObject.GetComponent<PLATEAUCityObjectGroup>();
if (cityObjGroup != null)
{
    Debug.Log("Component: PLATEAUCityObjectGroup");
    
    PrintAttributesToCanvas(cityObjGroup, targetObject);
}
else
{
    Debug.Log("PLATEAUCityObjectGroup component not found.");
}

③ 属性値を比較して色づけする

属性値を比較して色づけする処理は、PrintAttributesToCanvasメソッドで実装しています。次のようにすると、オブジェクトの属性値を取得できます。

【メモ】

PrimaryCityObjectsは配列です。ここではFirstOrDefaultで先頭のオブジェクトに関するデータを取得しています。配列であるのは、複数のPLATEAU 地物が結合されて1つのゲームオブジェクトとして構成されていることがあるためです。

private void PrintAttributesToCanvas(PLATEAUCityObjectGroup cityObjGroup, GameObject targetObject)
{
var firstPrimaryObj = cityObjGroup.PrimaryCityObjects.FirstOrDefault();

設置フロアは、次のようにして取得できます。設置フロアは「3F」「4F」などの文字列であるため、数値に変換します。

if (firstPrimaryObj != null)
{
// 設置フロアを取得
var attributesMap = firstPrimaryObj.AttributesMap;
// 設置フロアは、PLATEAUの属性情報の中では "設置フロア" というキーで格納されている
if (attributesMap.TryGetValue("設置フロア", out var attribute))
{
// 値はattribute.StringValueで取得できる
var stringValue = attribute.StringValue;
// 文字列の各文字をループで確認
foreach (char c in stringValue)
{
// 文字が数字かどうかを確認
if (char.IsDigit(c))
{
// 文字を整数に変換
if (int.TryParse(c.ToString(), out int digit))
{

数値であるならば、3階以下かどうかを判定し、オブジェクトを色づけします。色づけするには、Materialオブジェクトを作って設定します。

// 数字が3以下かどうかを確認
if (digit <=3)
{
    // ゲームオブジェクトのRendererコンポーネントを取得
    var renderer = targetObject.GetComponent<Renderer>();
    if (renderer != null)
    {
        var materials = renderer.materials;
       // 各マテリアルを青色に変更
       for (int i = 0; i < materials.Length; i++)
       {
            // マテリアルのインスタンスを作成
            materials[i] = new Material(materials[i]);
            materials[i].color = Color.blue;
        }
        renderer.materials = materials;
    }
}

27.6 _ まとめ

このトピックでは、PLATEAUの3D都市モデルに属性を追加できるPLATUEAU DataLinkerの使い方を解説しました。Unityで扱う例から見たように、属性を追加したPLATEAUの3D都市モデルも追加前とまったく同じように利用できます。地方公共団体や企業などがさまざまな地理空間情報を提供しているので、こうしたデータを追加すれば、PLATEAUの活用範囲はさらに広がります。

またPLATEAU DataLinkerには、CSV出力機能があるため、PLATEAUが持つ属性をExcelなどの表計算アプリや2Dの地図ツールなどでも活用できます。このトピックでは、建物に関する「高さ」を利用しましたが、ほかにも「用途」「地域」「災害リスク」などの属性もあります(どのような属性が提供されているのかは都市によって異なります)。こうした属性と既存の地理空間情報を組み合わせることでも、また新たな活用法が生まれます。

【文】

米田将(HollowByte)

大澤文孝