Open34

IFCのデータ構造を可視化したい

ピン留めされたアイテム
kiyukakiyuka

操作感とか表示の見た目に関して、やりたいことメモ

  • 属性表示欄のサイズをマウスで変更できるように
  • 属性表示欄の見た目とか表示の仕方とか
    • 特に逆属性がわかるように
  • ノードの表示が多くなったときに表示をどうにかする
    • いい感じに自動で整列するとかできたらいいな
  • 重なっているノードを縦横で一定間隔で整列する
  • undo, redo
  • Shift押しながらのノード移動で水平垂直移動
  • 表示の保存
  • ノードの逆属性の順番がランダムなのをどうにかする(setで取得している関係でそうなっている)
  • ファイル読み込み処理をしていることがわかるように(ファイルが大きいと時間がかかる)
  • アプリ化したときのログ出力
  • ノードのグループ化(UEにもあるようなやつ)
  • ノード右クリックからメニューを開いて色々できるように?
    • プロパティセットをすべて表示とか?
    • 関係するノード展開?
kiyukakiyuka

前のスクラップでIFCのデータ構造がグラフ構造っぽいということがわかったので、それを可視化する試み。

ちなみに3Dモデルでの可視化という話ではなくて、データ構造そのものを可視化する。どちらかといえばBIMのModelingではなく、Informationの要素を可視化するイメージ。
直接それを使ってなにかする、というよりも「IFCのデータ構造特殊でよくわかんないからデータいじって解析するにしてもハードル高すぎない!?」という問題の手助けができたらいいなーというモチベ。

kiyukakiyuka

まず前提として、IFCファイルは結構特殊なファイル形式である。そのため、既存の可視化ライブラリを流用してもおそらくそのまま使うことはできず、拡張して独自実装する必要があると思われる。そのため、ある程度自由度のあるライブラリを使う必要がある。
データ構造的にあえて近いものを挙げるとER図かなーとも思うけれども、拡張することは必須になるだろうからあまり考えないことにする。

というわけで可視化するにあたってライブラリを調べた。ネットワークグラフ描画ライブラリ7個まとめの記事を参考に。
上記記事の7個のうち Cytoscape.js のサンプルにこれが近いかなーというものもあったけど、D3.js のほうが自由度高さそうなのと Plotly で若干馴染みがあるので ひとまず D3.js を使っていこうと思う。


結局、グラフライブラリは使用せずにVueを使用してHTML,CSS,SVGで書いている。
というのもChatGPTが強すぎて、ライブラリの学習コストを考えるとそっちのほうが楽そうっていうのが理由。

kiyukakiyuka

グラフ構造を表示するにしても、すべてを表示することはノード数が多すぎてできない。

IFC.jsのGitHubにある一番小さそうな TESTED_Simple_project_01.ifc で、ノード数は 14,119 ある。
つまり、まずは表示方法を検討する必要がある。どうしようか。

https://github.com/IFCjs/test-ifc-files

ちなみに IfcProduct の要素だけプロットしたら下記のようになる。これでノード数300くらい。
実際にはここに各ノードの情報を載せないといけないので、多くて50くらいが限界だと思う。

https://twitter.com/kiyuka_study/status/1622556352488026113?s=20&t=Q0cUg6_Ixo4DwsHqpaau3g

kiyukakiyuka

ノードのデザインを考えないと。デザインと言うか属性の値をそのままノードの表示させると場所を取りすぎる。属性の値は別途表示させる形のほうが良さそう。あと値のない属性の表示はいらないね。

kiyukakiyuka

シンプルにした。

ここから追加する

  • IDの場合のみエッジの接続点を配置するように
  • 逆属性は左に接続点を置く
  • 接続点を引っ張ると、ノードが追加されるように

まずは上2つの見た目部分をやる。

kiyukakiyuka

ノードの見た目を調整。接続点があれば別のIFCのEntityが紐づいている。左側に接続点があれば逆属性。接続点がなければ純粋な値が入っている属性。

次は接続点から別のノードを追加する。

kiyukakiyuka

接続点をドラッグしてノードを追加できるように。画像はOwnerHistoryからエッジを引っ張った図。
エッジ表示できてないけど。
あと一つの属性から複数のノードがぶら下がっているのにはまだ対応してない。

次はエッジを表示する。

kiyukakiyuka

なんとかエッジを繋いだ。エッジがノードの上に来てるのどうにかしたいけど。若干エッジの位置がずれるのもどうにかしたい。

やることメモ

  • ゴリ押しした部分があるので、そのうち修正する
  • 複数ノードぶら下がっている場合に対応する
  • エッジの表示をノードの下に来るようにする
  • ...

いろいろあるなー...ひとまず次はエッジをノードの下に表示する。

kiyukakiyuka

単にノードが透明なせいだったので、エッジをノードの下に表示するのはすぐできた。

複数ノードぶら下がっている場合に対応したいけど、どういう仕様にするか...全部展開する?選択した一つを展開する?
選択する場合、追加する前に選択画面を表示して -> 選択して -> ノード追加 という手順を踏む必要がある(選択する表示の追加が必要)し、ひとまず全部展開しますか。

kiyukakiyuka

複数ノードを展開できるように。画像はノードをきれいに並べ直したあと。
展開直後は全部のノードが重なって表示される。

ノードが多くなってくると表示がごちゃっとするのをどうにかしないと。

  • ホイールコロコロで表示の拡大縮小
  • ノードを消す処理
  • 表示全体の移動

このあたりかな。まずは拡大縮小しますか。

kiyukakiyuka

ノードを選択して削除できるようにした。もうちょっと選択を目立つデザインにしてもいいかもだけどひとまず。

エッジの表示をどうにかしたい。現状まっすぐ引いているだけなので、接続点の逆側に行くとどこと繋がっているのかわかりにくい。それにノードの横幅が大きいと位置がおかしい。

イメージ的にはRete.js。接続点から少し横に出てから接続しに行く感じ。
(ちなみに最初このライブラリを使って実装しようかと思ったけど、書き方に癖があって習得に時間がかかりそうだったから見送っている)

https://retejs.org/examples/basic/vue

その前にバグとか直すか。

  • 属性が単純な値か他のノードに繋がっているかの判定を、データが数値化か文字かで判定してしまっているので、座標などの数値データでエラーになる
  • すでに表示されているエッジでも、ノード追加処理をすると同じエッジが複数描画されてしまう
  • ノードを画面外に移動できてしまう(拡大縮小移動処理で対応できるので問題ないといえば問題ない)
kiyukakiyuka

表示を調整。ノードを半透明にしてエッジが裏にあっても見えるように。Rete.jsを参考にしました。
あと、ノードの幅は固定にしてはみ出した文字は省略する感じに。

というかChatGPT便利すぎて困る。切り詰め方法。
https://chat.openai.com/share/da610b4e-7221-4892-bc2f-7329449d5906

次は数値データに対応します。

kiyukakiyuka

座標とかの数値データのもエラーにならないようには修正完了。
そう思って色々触ってたらまたバグ見つけた。
#374からノード追加するとおかしなことに。直します。

kiyukakiyuka

エッジについては直したけど、新たなバグと言うかを。IfcIntegerって何?
数値データなんだけどIFCのエンティティ要素っぽくって???なんでそうなってるの?

ifcopenshellで取得するとid=0で取得される。

item = model.by_id(446)
item.NominalValue.get_info()
# {'id': 0, 'type': 'IfcInteger', 'wrappedValue': 2}

IFCファイル上だと直接エンティティ指定しているみたいな感じ。

#446= IFCPROPERTYSINGLEVALUE('NumberOfStoreys',$,IFCINTEGER(2),$);

https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcInteger.htm

kiyukakiyuka

ひとまずID:0のデータはそのまま値として扱うことに。

次は属性の値を表示させたい。ただ、ノード上に表示させると画像みたいにちょっと無理がある。
だから属性を表示させる欄を画面右端とかに追加して、そこに表示させる感じかな。

kiyukakiyuka

右に表示欄作って表示させた。ひとまず最低限の機能はできたと思うんだよね。表示の仕方とか操作感とか改善点は色々あるけど。

現状だとIfcProjectからしかデータを辿れないから、特定のエンティティについてって言うことができない状態。
次は指定したのエンティティのノードを表示できるようにする。

kiyukakiyuka

一応、検索して追加自体はできたけど...

  • 指定のIFCエンティティに対して、データが複数ある場合どうするのか
  • ノードの追加位置が現状左上固定

複数あるのもID込みで一覧に表示させるか...
ノードの追加位置も右クリックでメニュー表示させてとかやりたいけど...

kiyukakiyuka

IDはサブ階層にして表示した。
元の一覧でID全部を表示しようとすると処理速度的に不可能だったので。IFCファイル数十万行とか普通にあるから当たり前だった。

右クリックで検索窓を左側に表示して、右クリックした場所にノードを追加する形に。

ここからどうしようか。3Dモデルも表示して、モデルをクリックしたらそこに関係あるノード表示したり、逆にノード選択すると3Dモデルのどの部分なのかをモデル上でハイライトしたり、とかやろうと思えば色々あるけど。
ひとまずは上でメモった操作上の改善点とかをちまちま修正しますか。

kiyukakiyuka

ノード追加中のエッジを表示するように(スクショだだとマウス表示されないからわかりにくいけど)。

エッジ接続位置とずれるのはどうしようかな...ノード追加時にどの属性から追加されたかを判断して位置を調整すればいいんだけど...

kiyukakiyuka

ノード追加時のノード位置をエッジ接続点に合わせるようにした。
前の「マウスを離した位置にノードの左上がくる」のとどっちがいいのかはわかんないけど、修正後のほうが自然かな?

(スクショだだとマウス表示されなくてわからないので画像なし)

kiyukakiyuka

複数ノードが追加されるときに少しずらして追加するように。
接続点基準でずらしてるからなんか変だけど。まあよし。

kiyukakiyuka

Shiftドラッグで範囲選択できるように。

選択処理の仕様を変えるか。現状だとノードを次々クリックすると複数選択されるから、最後にクリックしたものだけ選択されるようにする。そしてShift押しながらクリックで複数選択されるようにする。多分一般的にはこっちだと思う。

kiyukakiyuka

選択処理色々修正

  • 複数選択の仕様変更
  • ノード移動時に選択されたノードすべてが移動するように変更

(キャプチャだとわからないので画像はなし...)

kiyukakiyuka

ノードの整列処理追加。いい感じのアイコンが見つからなかったのでFigmaで自作した。
整列処理作るよりアイコン作るのが大変だったよ...

kiyukakiyuka

使ってて思うのが、この壁のエンティティってどこ壁だ?となってBIMvisoinとかで確認しに行ってるから、やっぱりモデルの表示はほしい。
そんなわけでモデルの表示を実装します。

モデルの表示についてはIfcOpenShellではなくてweb-ifcを使う。なぜなら処理速度が圧倒的に速いので。
そして表示はBabylon.jsでやります。なぜなら趣味だからです。
いや、IFC.js(Three.js)でやろうにも、結局エンティティとモデルの紐づけとかやるには、内部処理を解析しないといけないから、だったら最初から自分で位置から書けばいいかなって。それなら慣れてるBabylon.jsのほうがいいかなって。つまり趣味です。

kiyukakiyuka

Babylon.jsで表示はできるんだけど重い。メモリバカ食いしてる。
インスタンスとかも使わずにそのまま表示しているせいだとは思うけど...WebGLに詳しいわけじゃないんだよね...

とりあえず軽いモデルで試してるからいいけど、どうにかしないとな。
IFC.jsでどうやってるのか調べるか。

kiyukakiyuka

ThatOpen/engine_components になってからIFC.jsほとんど触れてないんだけど、調べても記事まったく出てこないな?
別に公式ドキュメントを見ればいいんだけど、半分くらいThree.jsの内容なんだよね...あとなんかなんとなくとっつきにくくなってる。英語しか情報がないからかもだけど。

https://github.com/ThatOpen/engine_components

ちゃんとこっちも調べますか。