やりたいこと
表題の通りですが、IfcOpenShellというのはIFCを解析できるオープンソースライブラリで、もともとC++で書かれているけれど、Pythonバインディングも出ています。IfcOpenShellのツール群の中には、IfcConvertというものがあって、IFCのジオメトリ抽出が可能になっている。OBJ、IGES、DAE、STLなど様々なフォーマット変換が可能であり、GUIDや名前で特定の形状のみ抽出することもできます。一般的にはこれで十分なのですが、IFCの属性情報と形状を使って、色々なことをしようとすると、どうしても直接ジオメトリやトポロジといった3Dデータをいじりたくなります(ふつうはならないけどね)。
その場合は、OpenCASCADEと呼ばれるライブラリ(CADカーネル)を使うのが一般的で、実際ライブラリにも含まれています。このライブラリは、FreeCADなどに用いられる老舗のオープンソースライブラリで、パラメトリックな3Dモデラー機能を提供してくれるようです。
ちなみにIFCの解析ライブラリというのは、オープンソースだとIFC++やxBIM Toolkit、有料だとIFC Engineやapstex IFC Framework(一部は無料)などがあります。
IfcOpenShellによるIFCの分析とpythonOCCによる描画
準備
ライブラリの関係もあって、Python3.5の環境を用意します。私の場合はインストールしてあるAnacondaで、condaを使って必要ライブラリをインストールしました。対応しているPythonは3.5までのようだったので、環境としてはそれを使い、対応したバージョンのOpenCASCADEのPython-bindingであるpythonocc
をインストールします。ネットワーク環境の要因なのか、結構失敗するのでソースコードからビルドしたほうが良いかもしれません。
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==0.17.3
あと、適当なIFCファイルを準備します。ifcOpenHouseなどでよいでしょう。
※Python3.6にも対応になったようです(2020/2/15)
IFCからの形状取得
IFCのジオメトリは、複雑なIfcRepresentationItem
に分解されています。具体的にはSurface Model(Tessellatiobなど), SolidModel(CGS,B-reps,sweepなど)などの形状表現やスタイル、テクスチャ表現などです。IfcOpenShellはこの複雑さを隠し、すべての統一された境界表現(B-reps)に変換します。加えて、レンダリングのためのMESH生成も行ってくれます。
ちなみに、実際のBIMでの形状モデリングは「カーネル」と呼ばれるものに依存しているようで、例えばASICやParadsolidといったものです。カットアウトや開口のような複雑な表現も容易にモデリングできます。
MESHの取得
以下が一番単純なサンプルになります。
import ifcopenshell
from ifcopenshell import geom
def read_geom(ifc_path):
ifc_file = ifcopenshell.open(ifc_path)
settings = geom.settings()
for ifc_entity in ifc_file.by_type("IfcWall"):
shape = geom.create_shape(settings, ifc_entity)
# メッシュの取得
ios_vertices = shape.geometry.verts
ios_edges = shape.geometry.edges
ios_faces = shape.geometry.faces
# 普通にPrintしてみる
print(ios_vertices)
print(ios_edges)
print(ios_faces)
geom.setting()
というのは変換のためのオプションで、デフォルトでは頂点(Vetices)、稜線(Edge)、面(Face)のメッシュを生成します。geom.create_shape(settings, ifc_entry)
で、ifc_entryで示されたIFC要素の形状を取得することができます。頂点は、x,y,zからなるトリプレットであり、稜線はそれらを結ぶもの、そして面は3つの頂点と稜線から構成されます。
B-repsを直接扱う。
上記では直接レンダリング可能なメッシュ表現を取得しましたが、境界表現であるB-reps(Boundary representation )を直接取得することもできます。geom.setting()
に以下のパラメータを指定します。以下ではついでにファイルに保存を試みています。
settings = geom.settings()
settings.set(settings.USE_BREP_DATA, True)
occ_shape = shape.geometry.brep_data
# IfcOpenShell generate an Open Cascade BREP
with open("IfcOpenShellSamples/brep_data", "w") as file:
file.write(occ_shape)
出力したフォーマットは、Open Cascade BREP Formatというものらしいです。
pythonOCCを使って描画するのは以下のようにします。色が変な気がしますが、まずはこんなもんかな。
import ifcopenshell
from ifcopenshell import geom
# Specify to return pythonOCC shapes from ifcopenshell.geom.create_shape()
settings = geom.settings()
settings.set(settings.USE_PYTHON_OPENCASCADE, True)
# Initialize a graphical display window
occ_display = geom.utils.initialize_display()
ifc_file = ifcopenshell.open("ifcOpenHouse.ifc")
products = ifc_file.by_type("IfcProduct")
for product in products:
if product.is_a("IfcOpeningElement"): continue
if product.Representation:
shape = geom.create_shape(settings, product).geometry
display_shape = geom.utils.display_shape(shape)
if product.is_a("IfcPlate"):
# Plates are the transparent parts of the window assembly
# in the IfcOpenHouse model
geom.utils.set_shape_transparency(display_shape, 0.8)
# すぐ消えるので、ここでループさせる
ifcopenshell.geom.utils.main_loop()