Closed19

.ifc を .ifcx (ifcx_alpha) に変換する

kiyukakiyuka

ifcx の alpha 版 が 2025年4月に公開されたので遊ぼう!ということでデータを作ります。
https://github.com/buildingSMART/IFC5-development

追記:このコミットの alpha 版で実施
https://github.com/buildingSMART/IFC5-development/tree/0a351ab2efe7deabbdd131c338a08d5b5c38179c

kiyukakiyuka

公式には一つしかサンプルがないけど、データ構造としては header, schemas, data で構成されている。
スキーマも必須なのかなと思って削除してビューアーで表示してみたらエラーだったので必須っぽい。

        "header": {
            "version": "ifcx_alpha",
            "author": "authorname",
            "timestamp": "time string"
        },
        "schemas": {
            ... schemas
        },
        "data": [
            ... data
        ]
kiyukakiyuka

スキーマは、 データの attributes の値の定義をしているっぽい。

この例だと bsi::name は 文字列ですよって定義。

  "schemas": {
    "bsi::name": {
      "value": {
        "dataType": "String"
      }
    },

  "data": [
    {
      "identifier":"8134f9ec-2e87-4b70-a538-9b6dc7ba94b1",
      "inherits": {
        "windowType": "f40ec978-42e6-414a-a044-b6df23dfafef"
      },
      "attributes": {
        "bsi::name": "Instance of Window_001"
      }
    },
kiyukakiyuka

ifcx のファイル内のスキーマではなくて、先に ifcx 自体のスキーマを見ましょうね。
ということでこれです。ifc-alpha.tsp

ifcx のファイル自体は header, schemas, data で構成されている。
メインの dataIfcxNode のリスト。

model IfcxFile {
    header: IfcxHeader;
    schemas: Record<IfcxSchema>;
    data: IfcxNode[]
}

IfcxNode は以下。id とノードの子(children, inherits) と 属性がある。
children, inherits の違いはひとまず気にしないでおく。

model IfcxNode {
    identifier: path;
    children?: Record<string | null>;
    inherits?: Record<string | null>;
    attributes?: Record<unknown>;
}
kiyukakiyuka

children は tree の表示的な子要素な感じ。

kiyukakiyuka

形状情報は、三角形メッシュがそのまま入っているので作るのは簡単そう。

kiyukakiyuka

tree 構造は children に入れるだけだからこれも簡単にできる。

IFCファイルから作るのであればこれだけ。

model = ifcopenshell.open(path)
project = model.by_type("IfcProject")[0]

root_node = {"identifier": str(uuid.uuid4()), "children": {}}
nodes = [root_node]
project_node = {"identifier": str(uuid.uuid4()), "children": {}}
nodes.append(project_node)
root_node["children"][project.Name or project.GlobalId] = project_node["identifier"]

def add_children_node(nodes, element, node):
    children = ifcopenshell.util.element.get_decomposition(element, is_recursive=False)
    for child in children:
        child_node = {"identifier": str(uuid.uuid4()), "children": {}}
        nodes.append(child_node)
        node["children"][child.Name or child.GlobalId] = child_node["identifier"]
        add_children_node(nodes, child, child_node)

add_children_node(nodes, project, project_node)
kiyukakiyuka

usd::usdgeom::mesh 追加して形状情報追加して公式ビューアーで表示しようとしたらエラーになった。

render.mjs:459 Uncaught TypeError: Cannot read properties of undefined (reading 'usd::usdshade::materialbindingapi::material::binding')

usd::usdshade::materialbindingapi::material::binding は必須なのか。適当にデフォルト色を入れてくれればいいんだけど、そんな機能はないっぽい。

kiyukakiyuka

色情報はこれ。id に / 入っているのは気持ち悪いので参考にしないようにします(?)。
というより色情報だけ特殊処理しないといけなくなるから修正されると思う。

    {
      "identifier":"359c715f-5961-4c20-be08-9bb25ea75c24/Shader",
      "attributes": {
        "bsi::name": "WallMaterial shader",
        "usd::materials::info::id": "UsdPreviewSurface",
        "usd::materials::inputs::diffuseColor": [
          0.8,
          0.7,
          0.6
        ],
        "usd::materials::inputs::opacity": 1,
        "usd::materials::outputs::surface": null
      }
    },
kiyukakiyuka

色の指定は、データ構造的にはこうなんだけどさ。これ、窓みたいに、ガラスと木枠の2種類で構成されてるときって、色指定個別にできなくない?Bodyの方に色情報つけないと。

kiyukakiyuka

ひとまず気にせず色設定をしよう。

オブジェクトの属性に usd::usdshade::materialbindingapi がついてて、

    {
      "identifier":"f079bafd-8733-48d8-85df-1c1656a17c1f",
      "attributes": {
        "usd::usdshade::materialbindingapi": {
          "material::binding": {
            "ref": "f83b2e90-81df-4cae-ad63-52a51009e561"
          }
        },
      }
    },

usd::usdshade::materialbindingapiusd::usdshade::material ? が紐づいていて、


    {
      "identifier":"f83b2e90-81df-4cae-ad63-52a51009e561",
      "children": {
        "Shader": "b3325921-8f14-4847-9473-cfc6e333683a"
      },
      "attributes": {
        "bsi::name": "SpaceMaterial",
        "usd::usdshade::material": {
          "outputs::surface.connect": {
            "ref": "./Shader.usd::materials::outputs::surface"
          }
        }
      }
    },

その下に色情報が紐づいている形。

    {
      "identifier":"f83b2e90-81df-4cae-ad63-52a51009e561/Shader",
      "attributes": {
        "bsi::name": "SpaceMaterial shader",
        "usd::materials::info::id": "UsdPreviewSurface",
        "usd::materials::inputs::diffuseColor": [
          0.6,
          0.7,
          0.8
        ],
        "usd::materials::inputs::opacity": 0.3,
        "usd::materials::outputs::surface": null
      }
    },
kiyukakiyuka

いけた。opening 除いてないから窓が埋まってるけど。

kiyukakiyuka

さて複数色を対応できるようにしますか。
複数色使ってるものは直接形状を指定するのではなくて、もう一つ階層を作って、色ごとにオブジェクトを分ける想定なんだと思う。

kiyukakiyuka

属性情報とか入れようかと思ったけど、大量にスキーマ定義しないといけないから、やめておきましょうか。まだ alpha版が出たばっかで公式が変わる可能性も高いし。

そんなわけでこのスクラップはCloseですの。

このスクラップは4ヶ月前にクローズされました