【超簡易版】 PLATEAUで土石流シミュレーションをビジュアル化


今更ですが、約1年前2021年7月のハッカソンで、私のチームが作成したものの中から、私が作成した部分について書きました。

https://asciistartup.connpass.com/event/212785/


## 作ったもの
土石流のシミュレーションを Unity でビジュアル化しました。

[![Image from Gyazo](https://i.gyazo.com/936d6a0f21f22b2872323bc1f94532cc.png)](https://gyazo.com/936d6a0f21f22b2872323bc1f94532cc)

https://twitter.com/tatsuya1970/status/1416708983117647874?s=20&t=ez_LRPbTI2tEws0rmq2yBw


<br><br>

## 土石流のシミュレーションデータ作成

まずは、土石流のシミュレーションデータを作成します。
iRIC Software で、土石流の分布や堆積高さを計算し、csv で保存。
（このやり方は割愛します）


こんなcsvデータができます。

Result-1.csv
[![Image from Gyazo](https://i.gyazo.com/012fbb7fc46fc9375fcd82bbf585b89a.jpg)](https://gyazo.com/012fbb7fc46fc9375fcd82bbf585b89a)

１つ１つ土砂の粒の位置情報で、40402行あります。

これが１つの瞬間の土砂の位置情報
このハッカソンのときは、時系列（何秒ごとか不明）で22個のcsvファイル（Result-1.csv　から Result-22.csv　）を作成した。

<br>

## Unity に再現

国土交通省の3D都市データ　PLATEAU　を使いました。

まず、PLATEAU のデータを FBXに変換して、Unity に持っていきます。
[![Image from Gyazo](https://i.gyazo.com/a02496ad035cf6cec569601188ff75fc.png)](https://gyazo.com/a02496ad035cf6cec569601188ff75fc)

方法はこちらを参考
[『PLATEAU』の都市3Dデータ形式CityGMLをFBXに変換してUnityで遊ぶ](http://tatsuya1970.com/?p=15666)
　
<br>

このUnity上の３D都市モデルに、iRICで作成した土石流シミュレーションをプロット　します。

<font color ="RED"> 2022.6.20 追加
まず、砂のオブジェクトをSphere で作り、プレハブ化します。
（プレハブにしなくてもいいかも）
[![Image from Gyazo](https://i.gyazo.com/cdb348088bfc8c320402179c6072ccf0.png)](https://gyazo.com/cdb348088bfc8c320402179c6072ccf0)

</font>

砂のオブジェクトを
iRIC のシミュレーションデータで算出した土砂の位置情報（平面直角座標）をUnityの座標に変換して、Unity 上にプロットしていきます。


以下の画像のように、どこでもいいので、適当にUnity上に基準点をもうけて、Unityの座標とそれに対応する平面直角座標を求めます。

[![Image from Gyazo](https://i.gyazo.com/9d4b9b21f363ba271369874fa8eb29e5.png)](https://gyazo.com/9d4b9b21f363ba271369874fa8eb29e5)

平面直角座標はこちらで計算しました。
https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2xyf.html

地図を目視して、だいたいな位置をもとに計算しましたので、計算結果は大雑把です。
ハッカソンだから許されると思いますが、正式な業務や研究にはこのやり方は多分よろしくないと思います。





ここまで求めたら、プログラミング

コードは以下（C#)

変数の説明：
unityX , unityY , unityZ  : 土砂をプロットするUnity の座標
unityX_origin　= 6715.52 : 　　　　　Unityの原点X座標
unityZ_origin　= 1709.992 : 　 Unityの原点Z座標
unityX_length = 19.84 　:unityの範囲のX軸の幅　（iRICの座標と対比し縮尺を求めるため）
unityZ_length = 19.862　:unityの範囲のZ軸の幅

gridX , gridY　:  iRIC Software で算出された座標
depth , hight :  iRIC Software で算出された深度、高さ

これから先は先ほど紹介した[平面直角座標のサイト](https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2xyf.html )で計算しました。

gridX_origin = -195173.3455  : unity の原点Zに対応するiRIC の座標
gridY_origin = 35302.4731    : unity の原点Yに対応するiRIC の座標

gridY_length = 1833.526　　 :Unity の範囲の幅に対する iRIC のY軸の幅
gridX_length = 2225.453  :　Unity の範囲の幅に対する iRIC のX軸の幅



``` sandDisplay.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;

public class sandDisplay : MonoBehaviour
{
    public GameObject sandObject;
    private GameObject obj;

    void Start()
    {
        StartCoroutine("Main");   
    }

    IEnumerator Main()
    { 
        float unityX;
        float unityX_length = 19.84f;
        float unityX_origin = 6715.52f;
        float gridX;
        float gridX_length = 2225.453f;
        float gridX_origin = -195173.3455f;

        float unityZ;
        float unityZ_length = 19.862f;
        float unityZ_origin = 1709.992f;
        float gridY;
        float gridY_length = 1833.526f;
        float gridY_origin = 35302.4731f;

        float depth;
        float hight;
        float unityY;

        for (int j = 1; j < 22; j++)
        {
            yield return new WaitForSeconds(0.5f);
            string file_name;
            TextAsset csvFile; // CSVファイル
            List<string[]> csvDatas = new List<string[]>(); // CSVの中身を入れるリスト;

            file_name = "Result_" + j; //csvのファイル名

            // Resoucesフォルダに保存したiRICのCSVを読み込む
            csvFile = Resources.Load(file_name) as TextAsset; 
            StringReader reader = new StringReader(csvFile.text);

            // , で分割しつつ一行ずつ読み込み、リストに追加していく
            int n = 0;

            while (reader.Peek() != -1) // reader.Peaekが-1になるまで
            {
                string line = reader.ReadLine(); // 一行ずつ読み込み
                csvDatas.Add(line.Split(',')); // , 区切りでリストに追加
                n = n + 1;
            }


            for (int i = 1; i < n; i++)

            {
                gridX = float.Parse(csvDatas[i][3]);　// iRICのY座標（csvファイル D列）
                gridY = float.Parse(csvDatas[i][2]);　// iRICのX座標（csvファイル C列）

                depth = float.Parse(csvDatas[i][4]);　// iRICのDepth（csvファイル E列）
                hight = float.Parse(csvDatas[i][5]);  // iRICのElevation（csvファイル F列）


                // ここでUnity の座標(unityX , unityY, unityZ)に変換している。
                // Unity のXZ軸　は iRIC では YX軸
                unityX = unityX_origin - (Mathf.Abs(gridY - gridY_origin) * (unityX_length / gridY_length));
                unityZ = unityZ_origin - (Mathf.Abs(gridX - gridX_origin) * (unityZ_length / gridX_length));
                
                unityY = hight / 100;
              
                if (depth > 0)
                {
                    //土砂をプロット
                    var _obj = (GameObject)Instantiate(sandObject, new Vector3(unityX, unityY +(depth/10) , unityZ), Quaternion.identity);

                   // 視認しやすく、1つおきに土砂の色を変えている
                    
                    if (i % 2 == 1) //奇数の場合
                    {
                        _obj.GetComponent<Renderer>().material.color = Color.red;
                    }
                    else
                    {
                        _obj.GetComponent<Renderer>().material.color = Color.blue;
                    }

                }

            }

        }
       
    }
}
```

<font color ="RED"> 2022.6.20 追加
このスクリプト sandDisplay.cs を空のオブジェクト（ここでは Sandcontroller ）　にアタッチする。
Sand Display の　Sand Object に　砂のプレハブ　（ここでは sand ）を指定する。

[![Image from Gyazo](https://i.gyazo.com/abe771577b8d0686a9022d0cb32d0fc9.png)](https://gyazo.com/abe771577b8d0686a9022d0cb32d0fc9)

</font>

以上です。

本当にこんなやり方でいいのか、プロの方からコメントいただければ幸いです。

<br>