RhinoInsideを用いてCPythonから属性ユーザテキストに書き込む(UnityWebアプリ編)
BIMの重要な要素に属性情報があります。仕様や数量などの情報をモデルデータに埋め込み、生産設計や施工管理等に活用することができます。
2021年最後の投稿として、 本記事では Unityで作成したWebアプリからRhinoモデルの属性情報の変更を行う方法を述べます。UnityからHTTP通信でサーバーにデータを送り、サーバー側でRhinoInsideを用いてCPythonから属性情報を書き込みます。WebAPIのフレームワークにCPythonモジュールのFlaskを使います。
まず、CPythonはあらかじめインストールされていることを想定します。パッケージ管理ソフトのPIPで以下のモジュールをインストールします。
・RhinoInside ※Rhinoバージョン7
・Flask-Cors ※WebGL版を開発するのに必要
それと、今回はUnityを使うのでUnityとWebGL用のフォントをインストールします。
・Unity ※UnityHubをインストール後、Unity(バージョンは最新)インストール
・Noto Sans Japanese ※UnityでWebGLを開発する際、日本語の表示に使う
デモ動画1
まず、パネルオブジェクトを選択して属性情報を表示するデモ動画です。
上記の動画のように地面をクリックするとその場所に移動して、ドラッグで視点の回転を行い、パネルオブジェクトをクリックすると赤くなって、画面右側のUIに属性情報が表示されます。
右側の黒い画面はサーバー側のCPythonプログラムの処理の様子です。 同じPC内での処理なのでIPアドレスが同じですが、Wi-fi経由のローカルネットワークを介して、属性情報の受け渡しを行っているのがわかります。
ローカルネットワークにアクセスできるなら、スマートフォンやiPadからも開くことができます。
Unityでアプリを作成する
ブラウザから動くWebアプリを作成します。以下のスクリーンショット画像のようにUnityで作成しました。Rhinoから出力した.3dsモデルを表示して、床部分をクリックすることでクリックする箇所へ移動したり、オブジェクトをクリックするとマテリアルに色がつくようにしました。
Unityで指定したオブジェクトの属性情報を受け取って表示
UnityはHTTP通信を行うことができます。クライアント側ではUnityで作成したWebアプリから属性情報の送受信を行います。Unityで受け取った属性情報を右側GUIのテキストボックスに表示されるようにしました。
一方のサーバー側では、WebAPIフレームワークのFlaskで属性情報の送受信を行い、CPythonのRhinoInsideモジュールでRhinoモデルの属性情報の読み書きを行います。
属性情報の受け渡しができると、画面右のUIに属性情報が表示されます。
下はUnity C#コードの一部で、HTTP通信を行っている処理です。
using UnityEngine.Networking;
...
IEnumerator GetAttribute(GameObject obj_selected)
{
//パネルオブジェクトの名前をセット
WWWForm form = new WWWForm();
form.AddField("name_panel", obj_selected.name, Encoding.UTF8);
UnityWebRequest webRequest = UnityWebRequest.Post(URL_Flask + "get_atrb", form);
webRequest.downloadHandler = new DownloadHandlerBuffer();
//URLに接続して待機
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.Success)//リクエスト成功
{
//通信成功。属性情報がセットされたはず
string str_json = webRequest.downloadHandler.text;
var lines_kvp = JsonConvert.DeserializeObject<Dictionary<string, object>>(str_json);
foreach (var kvp in lines_kvp)
{
string key = kvp.Key;
object value = kvp.Value;
Debug.Log(key + " : " + value);
...
}
}
}
Unityで属性情報の値を変更して、サーバー側からRhinoモデルに書き込む
UIのテキストボックスに属性情報を変更する内容を入力してボタンを押すと、変更内容がサーバー側に送られて、CPythonのRhinoInsideで処理を行います。
以下、属性情報を受け取って.3dmに書き込む処理です。
# -*- coding: UTF-8 -*-
import os, sys
import rhinoinside
rhinoinside.load()
import System
import Rhino
#Flaskの初期化
from flask import Flask, request, render_template, jsonify
from flask_cors import CORS
app = Flask(__name__)
app.config["JSON_AS_ASCII"] = False #for UTF-8 support
CORS(app) #CORS(クロス・オリジン・リソース・共有)の解決
dir_home = os.path.dirname(__file__)
path_3dm = os.path.join(dir_home, "panelize.3dm")
...
#属性情報を受け取って.3dmの更新
@app.route('/update_atrb', methods=['POST'])
def UpdateAtrb():
dict_atrb = {}
print("update attributes:")
for key in request.form.keys():
value = request.form[key]
dict_atrb[key] = value
print(" {} : {}".format(key, value))
#属性情報をセット
set_atrb(dict_atrb)
return "Updated!!!"
#.3dmファイルを開いて属性情報を更新
def set_atrb(dict_atrb):
if not "002_PANEL_NAME" in dict_atrb.keys():
return
name_panel = dict_atrb["002_PANEL_NAME"]
f3dm = Rhino.FileIO.File3dm.Read(path_3dm)
if f3dm is None:
return dict_atrb
for obj in f3dm.Objects:
if obj.Name != name_panel:
continue
atrb = obj.Attributes
for key in dict_atrb.keys():
#番号除外
if not key[:3].isdecimal() or int(key[:3]) in [1,2,3]:
continue
#属性情報をセット
value = dict_atrb[key]
atrb.SetUserString(key, value)
#ひとつ読めたら閉じる
break
#変更を保存
f3dm.Write(path_3dm, version=6)
f3dm.Dispose()
Rhinoを開いてから変わっているかを確認します。下のスクリーンショット画像から属性情報が変わっている様子がわかります。
デモ動画2
最後に属性情報を書き込んで.3dmファイルを開いて確認するデモ動画を見てみましょう。
以上になります。このアプリの良いところはRhinoをインストールしていないデバイスからでもモデルを確認したり、属性情報の読み書きができるところです。実用となると、メンバーのログインや属性情報の書き換える権限の問題も出てきて面倒なのですが、この技術は様々なことに応用できそうです。
それでは最後に今年もお世話になりました。2022年もSyntegrateをよろしくお願いします。