4
3

More than 3 years have passed since last update.

IFCOpenshellとTrimeshを使ってIFCのデータを可視化した話と設定の落とし穴

Last updated at Posted at 2021-05-09

これなんの話?

BIMの標準データ交換フォーマットであるIFCのデータを可視化しようとした。
しかし、PythonのJupyter上で可視化しようとしたところ、IFCのデータを処理するためのライブラリ・IfcOpenShellに落とし穴があってドツボにはまったけど何とか解決したよっていうお話。

IFCのデータをPythonで可視化する

まずやらないといけないこと

IFCのデータのメッシュ化

IFCのデータは曲線やらなにやらのデータが入っていて、座標系は部屋や階ごとの相対座標系になっていたりする。
こいつを座標系展開して、形状をメッシュ化するのは大変。
ただ、IFCのデータを読み込んで、3Dメッシュ化する機能を持つライブラリは世の中に既に存在している。
それがIfcOpenshellである。他にもIFCEngineなんてものもあるが、こちらは研究目的なら無償だけどビジネスやらなにやらで使うならお金がかかる。

とりあえず、今回はpythonでコードを書くので使うのならばpythonのバインディングがあるIfcOpenshellでしょうと。

必要なもののインストール

ifcopenshellをインストールするにはcondaが必要だけど、Anaconda入れればOK
Anacondaでのcondaの使い方とか知らないっていう人は別途自分で調べてください()

pythonのバージョンは3.8でcondaの仮想環境は構築しました。
そのうえで、とりあえず以下のコマンドを実行すれば必要なものは入る…はず

conda install -c conda-forge -c oce -c dlr-sc -c ifcopenshell ifcopenshell

conda install -c conda-forge -c dlr-sc -c pythonocc -c oce pythonocc-core

pip install trimesh

いざコード作成

jupyterを起動してコードを書きました。
サンプルはIfcOpenHouseを使いました。
内容は以下の通り

import ifcopenshell
from ifcopenshell import geom
import trimesh

ifc_file = ifcopenshell.open("IfcOpenHouse_IFC2x3.ifc")
settings = geom.settings()

scene = trimesh.Scene()

for ifc_entity in ifc_file.by_type("IfcProduct"):
    if ifc_entity.Representation:
        shape = geom.create_shape(settings, ifc_entity)
        ios_vertices = shape.geometry.verts
        ios_faces = shape.geometry.faces

        vertices = [[ios_vertices[i], ios_vertices[i+1], ios_vertices[i+2]] for i in range(0, len(ios_vertices), 3)]
        faces = [[ios_faces[i], ios_faces[i+1], ios_faces[i+2]] for i in range(0, len(ios_faces), 3)]

        mesh = trimesh.Trimesh(vertices=vertices, faces=faces)

        scene.add_geometry(mesh)

scene.show()

これで可視化出来る…はずだった

ところが出てきたのはこんなやつだった

キャプチャ.PNG

まあ、こうなってしまうのはIfcOpenshellの方のコードが色々とおかしいんでしょう…ってことで、色々調べてみた結果、どうやら座標系の設定の方に問題があることが分かった。

と、いうわけでその設定を行うようにしたコードだと以下の通りになる。


import ifcopenshell
from ifcopenshell import geom
import trimesh

# 3Dオブジェクトのシーングラフを作成
scene = trimesh.Scene()

def read_geom(ifc_path):
    # ファイル読み込み
    ifc_file = ifcopenshell.open(ifc_path)
    settings = geom.settings()
    # ワールド座標系を設定する(この設定がないとさっきみたいに変な三角形メッシュが出力される)
    settings.set(settings.USE_WORLD_COORDS, True)

    # IfcProductのサブクラスを全部取得する
    for ifc_entity in ifc_file.by_type("IfcProduct"):
        if ifc_entity.is_a("IfcOpeningElement"): continue
        if ifc_entity.Representation:
            # 設定に基づいてメッシュデータを作成
            shape = geom.create_shape(settings, ifc_entity)
            ios_vertices = shape.geometry.verts
            ios_faces = shape.geometry.faces

            # 出力した頂点リストと頂点インデックスのリストを整形
            # どちらも要素3の配列が並んでる2次元配列に
            vertices = [[ios_vertices[i], ios_vertices[i+1], ios_vertices[i+2]] for i in range(0, len(ios_vertices), 3)]
            faces = [[ios_faces[i], ios_faces[i+1], ios_faces[i+2]] for i in range(0, len(ios_faces), 3)]

            # trimeshを使って頂点インデックスと頂点リストからメッシュを生成
            mesh = trimesh.Trimesh(vertices=vertices, faces=faces)

            # メッシュをシーングラフに追加
            scene.add_geometry(mesh)

read_geom("IfcOpenHouse_IFC2x3.ifc")

# シーングラフを可視化
scene.show()

これをjupyter上で実行して得られた画像がこちら

キャプチャ.PNG

参考にしたところ

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3