LoginSignup
2
2

More than 1 year has passed since last update.

IfcOpenShellをコンパイルした件

Posted at

やりたかったこと

以前、IfcOpenShell pythonバインディングのことはじめで、condaでのIfcOpenShellのPythonバインディングを入れる解説をしましたが、何度やってもうまくいったりいかなかったりします。

最近はC++を触ることも多いので、この際、ソースからビルドしてみることにしました。環境はWindows 10、Visual Studio 2019 Communityです。これをやると、自動的にPythonバインディングも生成されます。

準備

まずは、ifcOpenShellでGithubのサイトで最新のコードをダウンロードしておきます。同サイトに要件なども書いてあります。Visual Studioの他にCMakeもインストールしてパスを通しておきましょう。作業を進めるには、Developer Command Promptが必要です。Visual Studioをインストールしたらついてくると思います。

image.png

ダウンロードして解凍したら、上記のコマンドプロンプトを使って、当該フォルダに移動します。その中にwinというフォルダがあるので、そこまで移動します。

コンパイル

詳細はwinフォルダのreadme.mdに書いてあるのですが、ここでは1つのやり方を示しておきます。ビルドに関して、IfcOpenShellは64ビットが推奨されるとのことです。理由はIFCは容易に2Gを超えるからとあります。また、何も指定しないとDebug用のビルドになりますが、今回はReleaseとしています。

最初のbuild-deps.cmd以外は、最初のパラメータがキャッシュ変数で保存されるはずなのですが、全て指定しないとうまくいきませんでした。

cd win
# 依存ファイルのダウンロード、ビルド
build-deps.cmd vs2019-x64 Release
# CMakeによりVisual Studioのソリューションファイルを作成
run-cmake.bat vs2019-x64 Release
# コマンドでVisual Studioのソリューションのビルド
build-ifcopenshell.bat vs2019-x64 Release
# フォルダにインストール
install-ifcopenshell.bat vs2019-x64 Release

うまくいくと、IfcOpenShellのフォルダに_installed-vs2019-x64が生成されており、bin/include/libがあることが分かります。必要に応じてDebugも作るとよいと思います。

サンプルプログラムの実行

インストールされたライブラリを使ってみます。今回はCMakeでコンパイルしてみようと思います。ただ、CMakeで生成しているにも関わらず、CMakeのConfigがありません。ドキュメントにも手動で参照してねと書いてあります。なんて面倒な、、、

CMakeする

今回は汎用的にCMakeでビルドしてみます。いくつか注意することがあって、上記のインストールプロセスで、CRTの設定が静的リンクをすることになっています。ここ を参考に切り替えを自動化するようにしておきます。対象するソースコードはmain.cppです。

CMakeLists.txt
project(main)
cmake_minimum_required(VERSION 3.14)

# Visual Studioでのコンパイル時は、CRTライブラリを静的リンクさせる
if(MSVC)
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG          ${CMAKE_CXX_FLAGS_DEBUG})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL     ${CMAKE_CXX_FLAGS_MINSIZEREL})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE        ${CMAKE_CXX_FLAGS_RELEASE})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
    string(REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /EHsc")
    set(CMAKE_CXX_FLAGS_DEBUG   "${CMAKE_CXX_FLAGS_DEBUG}   /DBUILD_TYPE=\\\"Debug\\\"")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /DBUILD_TYPE=\\\"Release\\\"")
endif(MSVC)


set(IFCOPENSHELL_ROOT "IfcOpenShellのインストールフォルダ")
find_package(BOOST REQUIRED)

add_executable(main main.cpp)

target_include_directories(main PRIVATE 
    ${IFCOPENSHELL_ROOT}\\include
    ${Boost_INCLUDE_DIRS}    
)
target_link_directories(main PRIVATE ${IFCOPENSHELL_ROOT}\\lib)

target_link_libraries(main PRIVATE IfcGeom IfcGeom_ifc2x3 IfcGeom_ifc4 IfcParse)

以下はサンプルプログラムを少し変えたものです。
対象のIFCファイルから、IfcBuildingElementを抜いてきて、IfcWindowに該当するものは面積を計算しています。デバッグコンソールが文字化けするので、対処するためのコードを入れています。

main.cpp
#include <iostream>
#include <string>  
#include <windows.h>

#define IfcSchema Ifc2x3

#include "ifcparse/IfcFile.h"
#include "ifcparse/Ifc2x3.h"

int main(int argc, char** argv) {

    std::string path = "";
    if (argc != 2) {
        path = "適当なifcファイルのパス";
    }
    else {
        path = argv[1];
    }

    // コマンドプロンプトのコードページを保存
    UINT prevCP = GetConsoleOutputCP();
    // コードページをUTF-8に変更
    SetConsoleOutputCP(CP_UTF8);


    // Redirect the output (both progress and log) to stdout
    Logger::SetOutput(&std::cout,&std::cout);

    // Parse the IFC file provided in argv[1]
    IfcParse::IfcFile file(path);
    if (!file.good()) {
        std::cout << "Unable to parse .ifc file" << std::endl;
        return 1;
    }


    IfcSchema::IfcBuildingElement::list::ptr elements = file.instances_by_type<IfcSchema::IfcBuildingElement>();

    std::cout << "Found " << elements->size() << " elements in " << path << ":" << std::endl;

    for (IfcSchema::IfcBuildingElement::list::it it = elements->begin(); it != elements->end(); ++it) {

        const IfcSchema::IfcBuildingElement* element = *it;
        IfcEntityInstanceData data = element->data();
        std::cout << element->data().toString() << std::endl;

        const IfcSchema::IfcWindow* window;
        if ((window = element->as<IfcSchema::IfcWindow>()) != 0) {
            if (window->hasOverallWidth() && window->hasOverallHeight()) {
                const double area = window->OverallWidth() * window->OverallHeight();
                std::cout << "The area of this window is " << area << std::endl;
            }
        }

    }
    // コードページを元に戻す(これをやらないとコマンドプロンプトを開き直すまでUTF-8のままになる)
    SetConsoleOutputCP(prevCP);
}

Visual Studioでコンパイル

準備ができたら、cmakeをしてください。うまくいけば、main.slnができていると思います。
なお、CMakeでの設定がうまくいっていれば、以下のように「ランタイムライブラリ」が`マルチスレッド(/MT)となっているはずです(Debugの場合は/MTd)。
image.png

以下が実行結果の例です。正しく対象のオブジェクトの属性が抽出できていますね。
image.png

2
2
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
2
2