CGAL的使用

1 C++類的知識

由於CGAL是用C++實現的,因此須要先了解一下C++編程。C++是面向對象的編程,這也是C++對C語言改進的最重要的部分。C++也被叫作是"帶類的 C"。簡單講一下類的構成,成員函數以及對象的定義和使用。html

1.1 C++類的構成

首先從C的結構體提及。C中的結構體我想你們已經熟悉了,不熟悉的朋友能夠先了解一下,這將對你認識「類」有很好的幫助。C中的結構體存在缺點:1.main 函數中的任意賦值語句均可以訪問結構體中的成員,但在實際應用中咱們想保護本身的私密數據不被訪問,所以C語言中的結構體的數據是不安全的;2.結構體中的數據和對該數據的操做是分離的,並非一個被封裝起來的總體,所以使程序難以重用,影響了軟件生產效率。因而C++中引入了類的概念。linux

C++中類的通常格式爲:c++

class Kid
   {
      private:
      int age;    //私有成員
      char *name;
      char *sex;
      public:      //公有成員
      void setKid(int age,char *name,char *sex);
      void showKid();
   };

C++中規定若是沒有對類的成員加私有private,保護protected,公有public,則默認爲私有的。而對於 C++的結構體來講,成員能夠是私有的,保護的或公有的,但默認爲公有的;還有要注意的是不能在類的聲明中給數據成員賦值。redis

通常狀況下,一個類的數據成員應該聲明爲私有的,成員函數聲明爲共有的。這樣,內部的數據隱藏在類中,在類的外部沒法訪問直接訪問,使數據獲得有效的保護。而公有的成員函數就成爲一種與類外部溝通的接口。算法

1.2 C++中的成員函數

1) 普通的成員函數。
要注意幾點:1.類名和函數名之間應加上做用域運算符::,用於聲明這個成員函數是屬於哪個類的,若是在函數名前沒有類名,或既無類名又無做用域運算符::,那麼這個函數不屬於任何類,不是成員函數,而是普通函數;2.在類的聲明中,成員函數原型的參數表中能夠不說明參數的名字,而只說明它的類型,但在類外定義時必須既要說明參數類型又要說明參數名;
2) 內聯成員函數,它又分顯式聲明和隱式聲明。shell

1.3 C++中的成員函數

類與對象的關係能夠用數據類型int和整形變量i之間的關係來類比。int類型和類類型表明一種抽象的概念,而整形變量和類的對象表明具體的東西。C++把類的變量稱爲類的對象,對象也被稱爲類的實例;類的對象能夠是: class Kid{...}kid1,kid2;也能夠是聲明瞭類後,使用時在定義對象: Kid kid1,kid2;(聲明一個類後,它並不接受和存儲具體的值,只做爲生成具體對象的一種樣板,只有定義了對象後,系統才爲對象分配存儲空間,以存放對象中的成員);編程

對對象中的成員的訪問能夠是:
1) 對象名.數據成員名/對象名.成員函數名(參數),好比api

kid1.setKid(10,"rookie_j","男");

2) 指針訪問對象中成員,好比:安全

class Kid{public: int age;}; 
Kid kid,*ptr; 
ptr=&kid;
cout << ptr->age //cout<<(*ptr).age;

3) 能夠經過引用來訪問對象中的成員bash

class Kid{public: int age;};
Kid kid;
Kid &ptr=kid;
cout << ptr.age   //cout<<kid.age;

由於接下來要講解的運用CGAL庫編寫凸包的程序,其程序運用以上的 C++的知識就能夠理解了,因此只講解以上的 C++ 的知識,具體想了解 C++的話,推薦(注意瞭解某種語言,不在於你看了多少書,而是去嘗試編寫)

1.《C++ Primer中文版》(第4版)
    【原書名】 C++ Primer (4th Edition)
    【原出版社】 Addison Wesley/Pearson
    【做者】 (美)Stanley B.Lippman,Josée LaJoie,Barbara E.Moo
    【譯者】 李師賢
    【叢書名】 圖靈計算機科學叢書
    【出版社】人民郵電出版社
2.《C++ Primer Plus》(第四版)中文版
    【原書名】 C++ Primer Plus,Fourth Edition
    【原出版社】 Sams
    【做者】 (美)Stephen Prata
    【譯者】 孫建春 韋強
    【叢書名】 Primer Plus 系列
    【出版社】 人民郵電出版社

2 CGAL庫的應用

2.1 CGAL 中的 Kernel 和眼花繚亂的 typedef

看CGAL中演化繚亂的Kernel對我這個C++入門級的人來講是件痛苦的事。假若有時間,我會認真去看看模板類,類模板什麼的再去好好理解這些東西,可是我想大部分人在學習新的東西的時候是沒有興趣去看那麼的多參考書。因此摸着石頭過河時最好最有效的方法。如下說說這Kernel是個什麼東西,爲何要有那麼多的typedef

CGAL的開發人員力圖讓這個程序包有較強的擴展性,要有擴展性,同時又要有必定的規則層次。這個層次的底層是代數結構,其上談number type,再往上就是基本幾何對象(線,面,點,射線,線段)和定義在基本幾何對象上的基本算法,在往上就是各類複雜的幾何算法(包圍盒,搜索,網格化等),以下圖所示。
CGAL層次圖
<img src="htt://cgal_use.com/1.png" width="400" height="100">

所謂的Kernel就是Layer2的內容。CGAL將Layer2按照基本幾何對象的表達方式(用歐式座標表達仍是其次座標表達)進一步分紅CartesianHomogeneous兩種。簡單的說,咱們用Cartesian開始編程,之後的對象操做什麼的都是用x , y , z三個座標去表示點,線,面。

由於各個layer的東西在CGAL裏都是以類模板的形式定義。CGAL的一開始,會有一大堆typedef,其實就是給這些類模板起一個簡單而又好記的名字。看一例:

typedef CGAL:: Exact_predicates_exact_constructions_kernel K;
   typedef K::Ray_3 Ray;
   typedef K::Line_3 Line;
   typedef K::Point_3 Point;
   typedef K::Triangle_3 Triangle;
   typedef std::list<Triangle>::iterator Iterator;
   typedef CGAL::AABB_triangle_primitive<K,Iterator> Primitive;

CGAL給出了一些預約義的東西,也就是把上面那個不斷typedef的最初一部分給隱藏掉:

Exact_predicates_exact_constructions_kernel;
   Exact_predicates_exact_constructions_kernel_with_sqrt;
   Exact_predicates_inexact_constructions_kernel;

這些預約義的東西默認使用Cartesian,數據類型支持double,還包括能實現精確的幾何判斷(exact predicate ),原來的代碼能夠寫成:

typedef CGAL:: Cartesian<double> K;// 使用Cartesian座標描述幾何體,座標的數值時double型,之後用到 ray , line等幾何體的時候都按照Cartesian方式給出double型座標。
   typedef K::Ray_3 Ray;
   typedef K::Line_3 Line;
   typedef K::Point_3 Point;
   typedef K::Triangle_3 Triangle;
   typedef std::list<Triangle>::iterator Iterator;
   typedef CGAL::AABB_triangle_primitive<K,Iterator> Primitive;//這句話表示使用高級計算幾何算法AABB時,全部的幾何對象都是Cartesian表示的,座標的數值都是double。

2.2 CGAL中某種算法的運用流程

點擊http://doc.cgal.org/latest/Manual/packages.html| 66c998fe1f511ede5c7483b24fcc88ca4 |進入CGAL手冊,出現各類算法庫Arithmetic and AlgebraCombinatorial AlgorithmsGeometry KernelsPolygons、Arrangements等等。
假如咱們想找有關3d凸包的算法,則找到以下圖所示的算法,
3D凸包手冊

點擊reference manual,就會看到該算法庫中的ConceptsTraits ClassesConvex Hull FunctionsConvexity Checking Function,以下圖:
圖片描述

點擊convex_hull_3函數,就會看見該函數的使用規則和實例,以下圖
圖片描述

每一個算法庫中都會帶有示例程序,點擊左側列表中example->convex_hull_3/quickhull_3.cpp,就會看到以下示例程序:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/algorithm.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/convex_hull_3.h>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel  K;
typedef CGAL::Polyhedron_3<K>                     Polyhedron_3;
typedef K::Segment_3                              Segment_3;
// define point creator
typedef K::Point_3                                Point_3;
typedef CGAL::Creator_uniform_3<double, Point_3>  PointCreator;
//a functor computing the plane containing a triangular facet
struct Plane_from_facet {
  Polyhedron_3::Plane_3 operator()(Polyhedron_3::Facet& f) {
      Polyhedron_3::Halfedge_handle h = f.halfedge();
      return Polyhedron_3::Plane_3( h->vertex()->point(),
                                    h->next()->vertex()->point(),
                                    h->opposite()->vertex()->point());
  }
};
int main()
{
  CGAL::Random_points_in_sphere_3<Point_3, PointCreator> gen(100.0);
  // generate 250 points randomly on a sphere of radius 100.0
  // and copy them to a vector
  std::vector<Point_3> points;
  CGAL::cpp11::copy_n( gen, 250, std::back_inserter(points) );
  // define polyhedron to hold convex hull
  Polyhedron_3 poly;
  
  // compute convex hull of non-collinear points
  CGAL::convex_hull_3(points.begin(), points.end(), poly);
  std::cout << "The convex hull contains " << poly.size_of_vertices() << " vertices" << std::endl;
  
  // assign a plane equation to each polyhedron facet using functor Plane_from_facet
  std::transform( poly.facets_begin(), poly.facets_end(), poly.planes_begin(),Plane_from_facet());
  return 0;
}

三、CGAL程序的編譯

3.1 Cmake

對於用CGAL所編寫的程序(由於基於C++)可利用Cmake來進行編譯安裝。CMake是一個跨平臺的安裝(編譯)工具,能夠用簡單的語句來描述全部平臺的安裝(編譯過程)。他可以輸出各類各樣的makefile或者project文件,能測試編譯器所支持的C++特性,相似UNIX下的automake。只是 CMake 的組態檔取名爲 CmakeLists.txt。Cmake 並不直接建構出最終的軟件,而是產生標準的建構檔(如 Unix 的 Makefile 或 Windows Visual C++ 的 projects/workspaces),而後再依通常的建構方式使用。這使得熟悉某個集成開發環境(IDE)的開發者能夠用標準的方式建構他的軟件,這種可使用各平臺的原生建構系統的能力是 CMake 和 SCons 等其餘相似系統的區別之處。
建議去了解一下CMake方面的知識。
linux-gentoo下cmake的安裝

$ sudo emerge -avt cmake

3.2 CGAL示例程序編譯

1) 建立一個工程目錄quickhull3,並將上面的示例程序quickhull_3.cpp放入該目錄中

$ mkdir quickhull3
$ ls
quickhull_3.cpp

2) 編寫CMakeLists.txt文件,鑑於許多朋友不會編寫CMakeLists.txt文件,所以這裏給出一個可自動生成CMakeLists.txt文件的shell腳本文件create_cmakelists.sh,該腳本僅運用於基於CGAL算法庫編寫的項目,將此腳本放在工程主目錄中,其內容以下:

#!/bin/bash

# Copyright (c) 1999,2000,2002-2007,2009,2011,2012
# Utrecht University (The Netherlands),
# ETH Zurich (Switzerland),
# INRIA Sophia-Antipolis (France),
# Max-Planck-Institute for Informatics Saarbruecken (Germany), 
# and Tel-Aviv University (Israel).  All rights reserved.
#
# This file is part of CGAL (www.cgal.org); you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 3 of the License,
# or (at your option) any later version.
#
# Licensees holding a valid commercial license may use this file in
# accordance with the commercial license agreement provided with the software.
#
# This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
# WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# $URL: svn+ssh://fcacciola@scm.gforge.inria.fr/svn/cgal/trunk/Scripts/scripts/cgal_create_makefile $
# $Id: cgal_create_makefile 36976 2007-03-09 22:53:24Z reichel $
#
# Author(s)     : various

# This script creates a CGAL cmake script with entries for .C and .cpp
# files in the current directory - some options can be given or specified in a file


#LEDA
#GMP
#GMPXX
#MPFR
#MPFI
#RS
#TAUCS
#BLAS
#LAPACK
#OPENNL
#QGLViewer (or implied by Qt4?)
#ESBTL
#NTL

#Core (implies GMP+GMPXX)
#Qt3 (implies QT3)
#Qt4 (implies QT4)
#ImageIO

#not (yet) supported
#F2C (comes with BLAS/LAPACK - something like that)
#IPE (ask Laurent)
#MKL (ask Andreas)

create_cmake_script_with_options()
{
  qt3='n'
  qt4='n'

  # parse options file
  if [ -e "$OPTIONS_FILE" ]; then

    OLDIFS="$IFS"
    IFS=$'\n'
    for LINE in `cat $OPTIONS_FILE`; do 

      # CGAL components
      if [ -z "$CGAL_COMPONENTS_GIVEN" ]; then # read file only if not given!
        next_cgal_component=`echo $LINE | grep -v "#" | grep CGAL_COMPONENT`
        if [ ! -z "$next_cgal_component" ]; then
          next_cgal_component=${next_cgal_component/CGAL_COMPONENT /}
          if [ -z "$CGAL_COMPONENTS" ]; then 
            CGAL_COMPONENTS=$next_cgal_component
          else
            CGAL_COMPONENTS=$CGAL_COMPONENTS":"$next_cgal_component
          fi
        fi
      fi

      # Boost components
      if [ -z "$BOOST_COMPONENTS_GIVEN" ]; then # read file only if not given!
        next_boost_component=`echo $LINE | grep -v "#" | grep BOOST_COMPONENT`
        if [ ! -z "$next_boost_component" ]; then
          next_boost_component=${next_boost_component/BOOST_COMPONENT /}
          if [ -z "$BOOST_COMPONENTS" ]; then 
            BOOST_COMPONENTS=$next_boost_component
          else
            BOOST_COMPONENTS=$BOOST_COMPONENTS":"$next_boost_component
          fi
        fi
      fi

    done
    IFS="$OLDIFS"
  fi


  # print makefile header
  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'
# Created by the script cgal_create_cmake_script_with_options
# This is the CMake script for compiling a set of CGAL applications.

EOF
  #---------------------------------------------------------------------------
  if [ "$SINGLE_SOURCE" = "n" ]; then
    echo "project( ${PROJECT} )"
  else 
    echo "project( ${SOURCE} )"
  fi

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'


cmake_minimum_required(VERSION 2.6.2)
if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER 2.6)
  if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}" VERSION_GREATER 2.8.3)
    cmake_policy(VERSION 2.8.4)
  else()
    cmake_policy(VERSION 2.6)
  endif()
endif()

set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
 
if ( COMMAND cmake_policy )

  cmake_policy( SET CMP0003 NEW )  

endif()

# CGAL and its components
EOF
if [ -n "$ENABLE_CTEST" ]; then
  echo "enable_testing()"
fi
  #---------------------------------------------------------------------------
  # echo "CGAL_COMPONENTS: $CGAL_COMPONENTS"
  # echo "CGAL_PRECONFIGURED_LIBS: $CGAL_PRECONFIGURED_LIBS"
  if [ ! -z "$CGAL_COMPONENTS" ]; then
    # ensure capitalization

    # CGAL: Core, Qt3, Qt4, PDB, ImageIO
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[c|C][o|O][r|R][e|E]/Core}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[q|Q][t|T]3/Qt3}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[q|Q][t|T]4/Qt4}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[i|I][m|M][a|A][g|G][e|E][i|I][o|O]/ImageIO}
  
    # external libs

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[g|G][m|M][p|P]/GMP}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[g|G][m|M][p|P][x|X][x|X]/GMPXX}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[m|M][p|P][f|F][r|R]/MPFR}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[l|L][e|E][d|D][a|A]/LEDA}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[m|M][p|P][f|F][i|I]/MPFI}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[r|R][s|S]/RS}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[o|O][p|P][e|E][n|N][n|N][l|L]/OpenNL}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[t|T][a|A][u|U][c|C][s|S]/TAUCS}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[b|B][l|L][a|A][s|S]/BLAS}
    CGAL_COMPONENTS=${CGAL_COMPONENTS//[l|L][a|A][p|P][a|A][c|C][k|K]/LAPACK}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[q|Q][g|G][l|L][v|V][i|I][e|E][w|W][e|E][r|R]/QGLViewer}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[z|Z][l|L][i|I][b|B]/zlib}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[e|E][s|S][b|B][t|T][l|L]/ESBTL}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[n|N][t|T][l|L]/NTL}

    CGAL_COMPONENTS=${CGAL_COMPONENTS//[o|O][p|P][e|E][n|N][g|G][l|L]/OpenGL}


#F2C?
#IPE?
#MKL?

    OLDIFS="$IFS"
    IFS=':'
    for cgal_component in $CGAL_COMPONENTS; do
      COMPONENT=`echo $cgal_component | tr '[:upper:]' '[:lower:]'`

      # for qtmoc
      if [ "$COMPONENT" = "qt3" ]; then
        qt3='y'
      fi
      if [ "$COMPONENT" = "qt4" ]; then
        qt4='y'
      fi

    done
    IFS=$OLDIFS

  fi

  if [ "$CGAL_PRECONFIGURED_LIBS" = "y" ]; then
    CGAL_COMPONENTS=${CGAL_COMPONENTS}" ALL_PRECONFIGURED_LIBS"
  fi

  echo "find_package( CGAL QUIET COMPONENTS ${CGAL_COMPONENTS//:/ } )"

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

if ( NOT CGAL_FOUND )

  message(STATUS "This project requires the CGAL library, and will not be compiled.")
  return()  

endif()

# include helper file
include( ${CGAL_USE_FILE} )

EOF
  #---------------------------------------------------------------------------

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

# Boost and its components
EOF
  #---------------------------------------------------------------------------

  if [ ! -z "$BOOST_COMPONENTS" ]; then

    echo "find_package( Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS//:/ } )"

  else

    echo "find_package( Boost REQUIRED )"

  fi # additional Boost components

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

if ( NOT Boost_FOUND )

  message(STATUS "This project requires the Boost library, and will not be compiled.")

  return()  

endif()
EOF
  #---------------------------------------------------------------------------


  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

# include for local directory
EOF
  #---------------------------------------------------------------------------

  if [ -d include ] ; then
    echo 'include_directories( BEFORE include )'
  fi        

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'

# include for local package
EOF
  #---------------------------------------------------------------------------

  # includes for local package
  if [ -d ../../include ] ; then
    echo 'include_directories( BEFORE ../../include )'
  fi
  if [ -d ../include ] ; then
    echo 'include_directories( BEFORE ../include )'
  fi

  if [ ! -z "$PACKAGES" ]; then
    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'

# include of additional packages
EOF
    #-------------------------------------------------------------------------
  fi

  # Qt3 or Qt4
  if [ "$qt3" = "y" ]; then

    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'

# Qt3
# FindQt3-patched.cmake is FindQt3.cmake patched by CGAL developers, so
# that it can be used together with FindQt4: all its variables are prefixed
# by "QT3_" instead of "QT_".
find_package(Qt3-patched QUIET )

if ( NOT QT3_FOUND )

  message(STATUS "This project requires the Qt3 library, and will not be compiled.")
  return()  

endif()

if ( CGAL_Qt3_FOUND )
  
  include( Qt3Macros-patched )

endif()
EOF
    #-------------------------------------------------------------------------
  fi # qt3

  if [ "$qt4" = "y" ]; then

    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'

# Qt4
set( QT_USE_QTXML     true )
set( QT_USE_QTMAIN    true )
set( QT_USE_QTSCRIPT  true )
set( QT_USE_QTOPENGL  true )

find_package(Qt4)  

if ( NOT QT_FOUND )

  message(STATUS "This project requires the Qt4 library, and will not be compiled.")
  return()  

endif()
EOF
    #-------------------------------------------------------------------------

  fi #qt4

  if [ ! -z "$BOOST_COMPONENTS" ]; then
    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'

# Boost linking
EOF
    #-------------------------------------------------------------------------

    OLDIFS="$IFS"
    IFS=':'
    for boost_component in $BOOST_COMPONENTS; do
      BOOST_COMPONENT=`echo $boost_component | tr '[:lower:]' '[:upper:]'`
      echo "add_definitions( \"-DCGAL_USE_BOOST_${BOOST_COMPONENT}\" )"
      echo "list(APPEND CGAL_3RD_PARTY_LIBRARIES \${Boost_${BOOST_COMPONENT}_LIBRARY} )"
    done
    IFS=$OLDIFS

  fi # additional Boost components


  # All Files or Single Source

  if [ "$SINGLE_SOURCE" = "n" ]; then #=======================================

    ###############
    # ALL SOURCES #
    ###############

    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'


# Creating entries for all .cpp/.C files with "main" routine
# ##########################################################

EOF
    #-------------------------------------------------------------------------


    if [ "$qt4" = "y" ]; then

      echo "include( CGAL_CreateSingleSourceCGALProgramQt4 )"

    else
 
      echo "include( CGAL_CreateSingleSourceCGALProgram )"

    fi
    # add a new line
    echo

    # Qt3
    if [ "$qt3" = "y" ]; then
      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'
if ( CGAL_Qt3_FOUND AND QT3_FOUND )

EOF
      #-----------------------------------------------------------------------

      for file in `ls *.C *.cpp 2> /dev/null | sort` ; do
        # Create an executable for each cpp that  contains a function "main()"
        BASE=`basename $file .C`
        BASE=`basename $BASE .cpp`
        egrep '\bmain[ \t]*\(' $file >/dev/null 2>&1
        if [ $? -eq 0 ]; then
          echo "qt3_automoc( ${file} )"
        fi
      done

      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'

  # Make sure the compiler can find generated .moc files
  include_directories( BEFORE ${CMAKE_CURRENT_BINARY_DIR} )
  
  include_directories( ${QT3_INCLUDE_DIR} )

  list(APPEND CGAL_3RD_PARTY_LIBRARIES ${QT3_LIBRARIES} )

endif()

EOF
      #-----------------------------------------------------------------------

    fi # qt3

    # Qt4
    if [ "$qt4" = "y" ]; then
      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'

if ( CGAL_Qt4_FOUND AND QT_FOUND )

  include( ${QT_USE_FILE} )
  include_directories( ${QT_INCLUDE_DIR} )  

endif()

EOF
      #-----------------------------------------------------------------------
    fi # qt4

    for file in `ls *.C *.cpp 2> /dev/null | sort`; do
      # Create an executable for each cpp that  contains a function "main()"
      BASE=`basename $file .C`
      BASE=`basename $BASE .cpp`
      egrep '\bmain[ \t]*\(' $file >/dev/null 2>&1
      if [ $? -eq 0 ]; then
        if [ "$qt4" = "y" ]; then
          echo "create_single_source_cgal_program_qt4( \"$file\" )"
        else
          echo "create_single_source_cgal_program( \"$file\" )"
        fi
        if [ -n "$ENABLE_CTEST" ]; then 
          if [ -f "$BASE.cin" ] ; then
            CIN=" < $BASE.cin"
          else
            CIN=
          fi
          cat <<EOF
add_test( "$BASE" \${CMAKE_CTEST_COMMAND}
  --build-and-test "\${CMAKE_CURRENT_SOURCE_DIR}"
                   "\${CMAKE_CURRENT_BINARY_DIR}"
  --build-generator "\${CMAKE_GENERATOR}"
  --build-makeprogram "\${CMAKE_MAKE_PROGRAM}"
  --build-target $BASE
  --build-no-clean
  --build-run-dir "\${CMAKE_CURRENT_SOURCE_DIR}"
  --test-command sh -c "\${CMAKE_CURRENT_BINARY_DIR}/$BASE$CIN" )
EOF
        fi
      fi
      #add a new line
      echo 
    done
    
  else #======================================================================

    #################
    # SINGLE_SOURCE #
    #################

    target_name=$SOURCE

    echo
    echo
    echo "# Creating entries for target: $target_name"
    #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
    cat << 'EOF'
# ############################
EOF
    #-------------------------------------------------------------------------

    for file in `ls *.C *.cpp 2> /dev/null | sort`; do
      all="$all $file"
    done

    # Qt3
    if [ "$qt3" = "y" ]; then
      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'

if ( CGAL_Qt3_FOUND AND QT3_FOUND )

EOF
      #-----------------------------------------------------------------------

      echo "qt3_automoc( ${all} )"

      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'

  # Make sure the compiler can find generated .moc files
  include_directories( BEFORE ${CMAKE_CURRENT_BINARY_DIR} )
 
  include_directories( ${QT3_INCLUDE_DIR} )

endif()
EOF
      #-----------------------------------------------------------------------
    fi # qt3

    # Qt4
    if [ "$qt4" = "y" ]; then
      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'

if ( CGAL_Qt4_FOUND AND QT_FOUND )

  include( ${QT_USE_FILE} )
  include_directories( ${QT_INCLUDE_DIR} )  

EOF
      #-----------------------------------------------------------------------

      echo "  # UI files (Qt Designer files)"
      for file in `ls *.ui 2> /dev/null | sort`; do
        echo "  qt4_wrap_ui( DT_UI_FILES $file )"
      done
      echo
      echo "  # qrc files (resources files, that contain icons, at least)"
      for file in `ls *.qrc 2> /dev/null | sort`; do
        echo "  qt4_add_resources ( DT_RESOURCE_FILES ./$file )"
      done
      echo
      MOC_FILES=""
      echo "  # use the Qt MOC preprocessor on classes that derives from QObject"
      for file in `ls include/*.h 2> /dev/null | sort`; do
        BASE=`basename $file .h`
        egrep 'Q_OBJECT' $file >/dev/null 2>&1
        if [ $? -eq 0 ]; then
          echo "  qt4_generate_moc( include/${BASE}.h ${BASE}.moc )"
          MOC_FILES="${BASE}.moc $MOC_FILES"
        fi
      done
      for file in `ls *.h 2> /dev/null | sort`; do
        BASE=`basename $file .h`
        egrep 'Q_OBJECT' $file >/dev/null 2>&1
        if [ $? -eq 0 ]; then
          echo "  qt4_generate_moc( ${BASE}.h ${BASE}.moc )"
          MOC_FILES="${BASE}.moc $MOC_FILES"
        fi
      done
      for file in `ls *.cpp 2> /dev/null | sort`; do
        BASE=`basename $file .cpp`
        egrep 'Q_OBJECT' $file >/dev/null 2>&1
        if [ $? -eq 0 ]; then
          echo "  qt4_generate_moc( ${BASE}.cpp ${BASE}.moc )"
          MOC_FILES="${BASE}.moc $MOC_FILES"
        fi
      done

      #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
      cat << 'EOF'

endif()
EOF
      #-----------------------------------------------------------------------

      all="${all} ${MOC_FILES} \${DT_UI_FILES} \${DT_RESOURCE_FILES}"

    fi # qt4

    # no 'cat' here, as variable substitution required
    echo
    echo "add_executable( ${target_name} ${all} )"
    echo
    echo "add_to_cached_list( CGAL_EXECUTABLE_TARGETS ${target_name} )"
    echo
    echo "# Link the executable to CGAL and third-party libraries"
    LIBS=""
    if [ "$qt3" = "y" ]; then
      LIBS="\${QT3_LIBRARIES}"
    fi
    if [ "$qt4" = "y" ]; then
      LIBS="\${QT_LIBRARIES}" 
    fi
    LIBS=$LIBS" \${CGAL_LIBRARIES} \${CGAL_3RD_PARTY_LIBRARIES}"
    echo "target_link_libraries(${target_name}  $LIBS )"

  fi # single source or all files #===========================================

  #vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
  cat << 'EOF'
EOF
  #---------------------------------------------------------------------------

echo

}

usage()
{
  echo "Usage: `basename $0` [-s source] [-c cgal-component1:cgal-component2:...] [-b boost-component1:boost-component2:...] [-p] [-o options_file='`pwd`/cgal_cmake_options:$HOME/.cgal_cmake_options_rc'] [-v] [-h]" >&2
  echo >&2
  echo "  -s source If this parameter is given the script will create one single executable for 'source' with all source files; otherwise it creates one executable for each main'ed source." >&2
  echo "  cgal_componentX - must be a valid cgal component, examples are 'Core','ImageIO','Qt3','Qt4' ('benchmark', 'symbolic')." >&2
  echo "  boost_componentX - must be a valid boost component, like 'filesystem', 'program_options'." >&2
  echo "  -p use all of CGAL's preconfigured libraries" >&2
  echo "  -o options_file - file with PACKAGE, DIRECTORY, CGAL_COMPONENT, and BOOST_COMPONENT directives" >&2
  echo "  -v the version" >&2
  echo "  -h this info screen" >&2
  echo  >&2
}


SINGLE_SOURCE='n'
SOURCE=""

CGAL_COMPONENTS_GIVEN=""
CGAL_COMPONENTS=""

CGAL_PRECONFIGURED_LIBS='n'

BOOST_COMPONENTS_GIVEN=""
BOOST_COMPONENTS=""

OPTIONS_FILE=`pwd`"/cgal_cmake_options"

if [ ! -e "$OPTIONS_FILE" ]; then
  OPTIONS_FILE="${HOME}/.cgal_cmake_options_rc"
fi

# parse command line arguments
while getopts s:c:b:o:phvt OPT; do
  case "$OPT" in
    s)  SINGLE_SOURCE='y'
        SOURCE=$OPTARG
        if [ "${SOURCE:(-4)}" = ".cpp" ]; then
           echo "Error: Source must not end with '.cpp'!" >&2
           echo
           usage
           exit 2
        fi
        if [ "${SOURCE:(-2)}" = ".C" ]; then
           echo "Error: Source must not end with '.C'!" >&2
           echo
           usage
           exit 2
        fi

        ;;

    c)  CGAL_COMPONENTS_GIVEN='y'
        CGAL_COMPONENTS=$OPTARG
        ;;
    b)  BOOST_COMPONENTS_GIVEN='y'
        BOOST_COMPONENTS=$OPTARG
        ;;

    o)  OPTIONS_FILE=$OPTARG
        if [ ! -e "$OPTIONS_FILE" ]; then
          echo "Options-file '$OPTIONS_FILE' does not exist." >&2
          exit 1
        fi
        ;;
    p)  CGAL_PRECONFIGURED_LIBS='y'
        ;;
    t)  ENABLE_CTEST='y'
        ;;
    h)  usage
        exit 0
        ;;
    v)  echo "`basename $0` version 0.1"
        exit 0
        ;;
    \?) # getopts issues an error message
        usage
        exit 1
        ;;
  esac
done

shift `expr $OPTIND - 1`

#echo "FILE: $OPTIONS_FILE"
#echo "BOOST_COMPONENTS: $BOOST_COMPONENTS"
echo "CGAL_COMPONENTS: $CGAL_COMPONENTS"
#echo "SINGLE_SOURCE: $SINGLE_SOURCE"
#echo "SOURCE: $SOURCE"

OUTPUTFILE=CMakeLists.txt
PROJECT=`basename $PWD`

if [ -f ${OUTPUTFILE} ] ; then
  echo "moving $OUTPUTFILE to ${OUTPUTFILE}.bak ..."
  echo
  mv -f $OUTPUTFILE ${OUTPUTFILE}.bak
fi

create_cmake_script_with_options | tee $OUTPUTFILE

echo
echo "created $OUTPUTFILE in $PWD ..."
$ ./create_cmakelists.sh 
$ ls 
CMakeLists.txt quickhull_3.cpp

3) 爲了保持代碼目錄的整潔,建議採用外部編譯,即新建一個build目錄,在該目錄下配置編譯,其過程以下:

$ mkdir build && cd build
$ cmake ..
$ make 
$ ./quickhull_3.cpp
The convex hull contains 89 vertices
相關文章
相關標籤/搜索