インストールテストCGALとread_ply()

14011 ワード

の原因となる
CGALでmeshの操作をしたいのですが、私の上流出力はPLYファイルで保存されているsurface meshで、CGALのフォーマットに変換したいです.Googleの発見により、比較的新しいCGALバージョンにはread_ply()関数があり、現在のシステムに付属しているCGALバージョンはサポートされていないため、新しいCGALをインストールする必要がある.How hard can it be?! しかし、事実上、これはほぼ午後の時間を費やした.
ローカルシステム
Ubuntu 18.04 cmake 3.16 Qt 5.9.5
clone repo
CGALのGithub cloneからローカルへ.現在のCGALバージョンは5.0.2で、git checkout releases/GAL-5.0.2で対応するtagに切り替わります.
ローカルプロジェクトと結合
CGAL GithubのページにINSTALL.mdファイルがあります.内には、ローカルプロジェクトにCGALを追加する方法があります.基本原理はCGAL自体がheader onlyのlibraryなので、cmakeに私たちのclone CGALの位置を見つけるだけでいいです.INSTALL.mdでは、cgal_create_cmake_scriptスクリプトを使用してCMakeLists.txtを生成する方法について説明し、cmakeを実行する際にCGALの特定の位置を指定する必要があることを示しています.cgal_create_cmake_scriptで生成されたCMakeLists.txtの最後に、create_single_source_cgal_programというcmake関数が使用され、この関数はソースファイルが1つしかないtargetしか作成できないようです.簡単なGoogleの後、実際にはcreate_single_source_cgal_programで複数のソースファイルを指定することもできますが、target名は最初に指定したソースファイルに基づいて構成されます.こちらを参考にしてください.create_single_source_cgal_programで生成されたCMakeLists.txtをテンプレートとして、新しいCMakeLists.txtファイルを以下のように記述する.
cmake_minimum_required(VERSION 3.16)
project( TestCGAL5 )

set(CMAKE_CXX_STANDARD 14)

set(CGAL_DIR /path/to/cgal)
find_package(CGAL REQUIRED QUIET OPTIONAL_COMPONENTS Core )

add_executable(TestCGAL5 main.cpp)

target_link_libraries(TestCGAL5 ${CGAL_LIBRARIES})

このとき、CMakeを呼び出すときにCGALの位置を指定する必要はありません.
Qtサポートを追加
テストのためのプログラム(付録)は、CGALが提供するdraw()関数を使用してmeshを描画する必要があります.CMakeLists.txtに変更がない場合、コンパイルに問題はありませんが、実行時には「Impossible to draw,CGAL_USE_BASIC_VIEWER is not defined.」というエラーが表示されます.
そこで最初のcppファイルに以下のコードを追加しました(ここを参照)
#define CGAL_USE_BASIC_VIEWER

コンパイルエラー、エラー内容はQtに関連しています.
ここでは本当にCGALにツッコミを入れ始めますが、ドキュメントは本当にQtを正しくサポートする方法を書いていません.
ドキュメントから見つけられる手がかりは限られており、ここではCGALが使用するQt componentについて説明します.CMakeについては、Qtがおすすめの方法がありますので、こちらを参考にしてください.これらの要件を満たすために、Qt自体に加えて、一部のシステムライブラリもインストールする必要があるようです(こことここを参照).
sudo apt-get install qt5-default
sudo apt-get install libqt5svg5-dev qtscript5-dev

しかし、本当にQtが推奨するようにすると、正常にコンパイルできず、autouicに関するエラーに遭遇し、エラーメッセージGoogleによると、有効なソリューションが得られません(例えば、このソリューションは使いにくい).そこでCGALにルーチンコードがあるのかと思いました.本当にありますね.
CGALのINSTALL.mdでは、インスタンスコードのコンパイル方法について説明しています.コンパイルプロセスを例示するために使用されるTriangulation_2/examples/Triangulation_2フォルダには、CGAL::Draw()という名前のdraw_triangulation_2.cppを呼び出す必要があるルーチンがある.Triangulation_2/examples/Triangulation_2に保存されたcppファイルをすべてコンパイルするために使用されるCMakeLists.txtの内容は、次のとおりです.
# Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application.


cmake_minimum_required(VERSION 3.1...3.15)
project( Triangulation_2_Examples )


if(NOT POLICY CMP0070 AND POLICY CMP0053)
  # Only set CMP0053 to OLD with CMake<3.10, otherwise there is a warning.
  cmake_policy(SET CMP0053 OLD)
endif()

if(POLICY CMP0071)
  cmake_policy(SET CMP0071 NEW)
endif()

find_package(CGAL COMPONENTS Qt5)

if(CGAL_Qt5_FOUND)
  add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()

if ( CGAL_FOUND )

  # create a target per cppfile
  file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
  foreach(cppfile ${cppfiles})
    create_single_source_cgal_program( "${cppfile}" )
  endforeach()

  if(CGAL_Qt5_FOUND)
    target_link_libraries(draw_triangulation_2 PUBLIC CGAL::CGAL_Qt5)
  else()
    message(STATUS "NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled.")
  endif()

else()
  
    message(STATUS "This program requires the CGAL library, and will not be compiled.")
  
endif()

まず、CGALの例CMakeLists.txtでは、Qt 5が推奨するようにQtへの依存を追加していない点が重要である.あと3つ注意すべき点は(1)find_packageの場合はQt componentを指定する必要があります.(2)add_の使用definitions();(3)増加対CGAL::CGAL_Qt 5のリンク.以上の観察から,我々の最初のCMakeLists.txtを以下のように修正した.
cmake_minimum_required(VERSION 3.16)
project( TestCGAL5 )

set(CMAKE_CXX_STANDARD 14)

set(CGAL_DIR /path/to/cgal)
find_package(CGAL REQUIRED COMPONENTS Qt5 OPTIONAL_COMPONENTS Core )

if(CGAL_Qt5_FOUND)
    add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()

add_executable(TestCGAL5 main.cpp)

target_link_libraries(TestCGAL5 ${CGAL_LIBRARIES} CGAL::CGAL_Qt5)

コンパイルに成功しました.
付録:試験手順
簡単なテストプログラムで、PLYファイルをsurface meshとして読み込んで、画面にこのmeshを描きます.ソースコードはCGAL Surface Mesh公式ドキュメントを参照してください.
#include 
#include 
#include 
#include 

#include 
#include 
#include 

typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3                Point;
typedef CGAL::Surface_mesh<Point>      Mesh;

int main( int argc, char **argv ) {
    std::cout << "Hello, TestCGAL5! " << std::endl;

    if ( argc <= 1 ) {
        throw std::runtime_error("Must use arguments. ");
    }

    std::ifstream ifs { argv[1] };
    if ( !ifs ) {
        std::stringstream ss;
        ss << "Open " << argv[1] << " failed. ";
        throw std::runtime_error(ss.str());
    }

    Mesh surfaceMesh;

    if ( !CGAL::read_ply( ifs, surfaceMesh ) ) {
        throw std::runtime_error("Failed to real the file. ");
    }

    ifs.close();

    CGAL::draw(surfaceMesh);

    return 0;
}