diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..3b83ce65bc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# Dependency and build folders created by the build scripts
+/deps*/
+/build*/
+/install*/
+/win/BuildDepsCache*.txt
+# IfcExpressParser residue
+/src/ifcexpressparser/__pycache__
+/src/ifcexpressparser/express_parser.py
+# Python test residue
+/test/__pycache__
diff --git a/README.md b/README.md
index b64227f291..059869ee62 100644
--- a/README.md
+++ b/README.md
@@ -1,52 +1,63 @@
IfcOpenShell
============
-open source (LGPL) software library for working with the IFC file format
+IfcOpenShell is an open source ([LGPL]) software library for working with the Industry Foundation Classes ([IFC])
+file format. Currently supported IFC releases are [IFC2x3 TC1] and [IFC4].
-[http://ifcopenshell.org](http://ifcopenshell.org)
-[http://academy.ifcopenshell.org](http://academy.ifcopenshell.org)
+For more information, see
+* [http://ifcopenshell.org](http://ifcopenshell.org)
+* [http://academy.ifcopenshell.org](http://academy.ifcopenshell.org)
+Prerequisites
+-------------
+* Git
+* CMake (2.6 or newer)
+* Windows: Visual Studio 2008 or newer with C++ toolset, MinGW not supported currently
+* *nix: GCC 4.7 or newer, or Clang (any version should work, but not tested)
Dependencies
-============
+-------------
* [Boost](http://www.boost.org/)
-* Open Cascade *optional*, but required for building IfcGeom)
- [Official](http://www.opencascade.org/getocc/download/loadocc/) or [community edition](https://github.com/tpaviot/oce)
+* Open Cascade - *optional*, but required for building IfcGeom
+ ([official](http://www.opencascade.org/getocc/download/loadocc/) or [community edition](https://github.com/tpaviot/oce))
For converting IFC representation items into BRep solids and tesselated meshes
-* [ICU](http://site.icu-project.org/) *optional*
+* [ICU](http://site.icu-project.org/) - *optional*
For handling code pages and Unicode in the parser
-* [OpenCOLLADA](https://github.com/khronosGroup/OpenCOLLADA/) *optional*
+* [OpenCOLLADA](https://github.com/khronosGroup/OpenCOLLADA/) - *optional*
For IfcConvert to be able to write tessellated Collada (.dae) files
-* [SWIG](http://www.swig.org/), [Python](https://www.python.org/) libraries *optional*
+* [SWIG](http://www.swig.org/) and [Python](https://www.python.org/) - *optional*
For building the IfcOpenShell Python interface and the Blender add-on
-* 3ds max SDK *optional*
- For building the 3ds max plug-in
+* [3ds Max SDK](http://www.autodesk.com/products/3ds-max/free-trial) - *optional*
+ For building the 3ds Max plug-in.
+ All recent versions of 3ds Max (2014 and newer) are 64-bit only, so a 64-bit installation is assumed.
+Building IfcOpenShell
+---------------------
+### Compiling on Windows
+The preferred way to fetch and build this project's dependencies is to use the build scripts
+in win/ folder. **See [win/readme.md] for more information**. Instructions in a nutshell
+(**assuming Visual Studio 2015 x64 environment variables set**):
-Compiling on Windows
-====================
-Users are advised to use the Visual Studio .sln file in the win/ folder.
-For Windows users a prebuilt Open CASCADE version is available from the
-http://opencascade.org website. Download and install this version and
-provide the paths to the Open CASCADE header and library files to MS
-Visual Studio C++.
+ > git clone https://github.com/IfcOpenShell/IfcOpenShell.git
+ > cd IfcOpenShell\win
+ > build-deps.cmd
+ > run-cmake.bat
-For building the Autodesk 3ds Max plugin, the 3ds Max SDK needs to be
-installed as well as 3ds Max itself. Please provide the include and
-library paths to Visual Studio.
+You can now open and build the solution file in Visual Studio:
-For building the IfcPython wrapper, SWIG needs to be installed. Please
-download the latest swigwin version from http://www.swig.org/download.html.
-After extracting the .zip file, please add the extracted folder to the PATH
-environment variable. Python needs to be installed, please provide the
-include and library paths to Visual Studio.
+ > ..\build-vs2015-x64\IfcOpenShell.sln
+As the scripts default to using the `RelWithDebInfo` configuration, and a freshly created solution by CMake defaults
+to `Debug`, make sure to switch the used build configuration. Build the `INSTALL` project (right-click -> Project
+Only) to deploy the headers and binaries into a single location if wanted/needed.
-Compiling on *nix
-=================
-Users are advised to build IfcOpenShell using the cmake file provided in
-the cmake/ folder. There might be an Open CASCADE package in your operating
-system's software repository. If not, you will need to compile Open
-CASCADE yourself. See http://opencascade.org.
+Alternatively, one can use the utility batch files to build and install the project easily from the command-line:
+
+ > build-ifcopenshell.cmd
+ > install-ifcopenshell.cmd
+
+### Compiling on *nix
+There might be an Open CASCADE package in your operating system's software repository. If not, you will need to compile
+Open CASCADE yourself. See http://opencascade.org.
For building the IfcPython wrapper, SWIG and Python development are
required.
@@ -75,7 +86,10 @@ To build IfcOpenShell please take the following steps:
$ cmake ../
$ make
-If all worked out correctly you can now use IfcOpenShell. For example:
+If all worked out correctly you can now use IfcOpenShell. See the examples below.
+
+Usage examples
+--------------
**Invoking IfcConvert from the command line**
@@ -84,8 +98,6 @@ If all worked out correctly you can now use IfcOpenShell. For example:
$ ./IfcConvert Munkerud_hus6_BE.ifc
$ less Munkerud_hus6_BE.obj
-Or:
-
**Using the IfcOpenShell Python interface**
$ wget -O duplex.zip http://projects.buildingsmartalliance.org/files/?artifact_id=4278
@@ -146,3 +158,9 @@ Or:
>>>
>>> # Writing IFC-SPF files to disk:
>>> f.write("out.ifc")
+
+[LGPL]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/COPYING "LGPL"
+[IFC]: http://www.buildingsmart-tech.org/specifications/ifc-overview "IFC"
+[IFC2x3 TC1]: http://www.buildingsmart-tech.org/specifications/ifc-releases/ifc2x3-tc1-release "IFC2x3 TC1"
+[IFC4]: http://www.buildingsmart-tech.org/specifications/ifc-releases/ifc4-release "IFC4"
+[win/readme.md]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/win/readme.md "win/readme.md"
\ No newline at end of file
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 7431c8d566..6ddb3c1645 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -1,17 +1,91 @@
-cmake_minimum_required (VERSION 2.6)
+################################################################################
+# #
+# This file is part of IfcOpenShell. #
+# #
+# IfcOpenShell is free software: you can redistribute it and/or modify #
+# it under the terms of the Lesser GNU General Public License as published by #
+# the Free Software Foundation, either version 3.0 of the License, or #
+# (at your option) any later version. #
+# #
+# IfcOpenShell is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# Lesser GNU General Public License for more details. #
+# #
+# You should have received a copy of the Lesser GNU General Public License #
+# along with this program. If not, see . #
+# #
+################################################################################
+
+cmake_minimum_required (VERSION 2.8.5)
+
project (IfcOpenShell)
-FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options)
+OPTION(UNICODE_SUPPORT "Build IfcOpenShell with Unicode support (requires ICU)." ON)
+OPTION(COLLADA_SUPPORT "Build IfcConvert with COLLADA support (requires OpenCOLLADA)." ON)
+OPTION(ENABLE_BUILD_OPTIMIZATIONS "Enable certain compiler and linker optimizations on RelWithDebInfo and Release builds." OFF)
+OPTION(IFCCONVERT_DOUBLE_PRECISION "IfcConvert: Use double precision floating-point numbers." ON)
+OPTION(USE_IFC4 "Use IFC 4 instead of IFC 2x3 (full rebuild recommended when switching this)" OFF)
+OPTION(BUILD_IFCPYTHON "Build IfcPython." ON)
+OPTION(BUILD_EXAMPLES "Build example applications." ON)
+OPTION(USE_VLD "Use Visual Leak Detector for debugging memory leaks, MSVC-only." OFF)
+OPTION(BUILD_IFCMAX "Build IfcMax, a 3ds Max plug-in, Windows-only." OFF)
+# TODO QtViewer is deprecated ATM as it uses the 0.4 API
+# OPTION(BUILD_QTVIEWER "Build IfcOpenShell Qt GUI Viewer (requires Qt 4 framework)." OFF)
+
+
+# Create cache entries if absent for environment variables
+MACRO(UNIFY_ENVVARS_AND_CACHE VAR)
+ IF ((NOT DEFINED ${VAR}) AND (NOT "$ENV{${VAR}}" STREQUAL ""))
+ SET(${VAR} "$ENV{${VAR}}" CACHE STRING "${VAR}" FORCE)
+ ENDIF()
+ENDMACRO()
+
+UNIFY_ENVVARS_AND_CACHE(OCC_INCLUDE_DIR)
+UNIFY_ENVVARS_AND_CACHE(OCC_LIBRARY_DIR)
+UNIFY_ENVVARS_AND_CACHE(ICU_INCLUDE_DIR)
+UNIFY_ENVVARS_AND_CACHE(ICU_LIBRARY_DIR)
+UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_INCLUDE_DIR)
+UNIFY_ENVVARS_AND_CACHE(OPENCOLLADA_LIBRARY_DIR)
+UNIFY_ENVVARS_AND_CACHE(PCRE_LIBRARY_DIR)
+UNIFY_ENVVARS_AND_CACHE(PYTHON_EXECUTABLE)
+IF(WIN32)
+ UNIFY_ENVVARS_AND_CACHE(THREEDS_MAX_SDK_HOME)
+ENDIF()
+
+# Find Boost
+IF(MSVC)
+ SET(Boost_USE_STATIC_LIBS ON)
+ SET(Boost_USE_STATIC_RUNTIME ON)
+ SET(Boost_USE_MULTITHREADED ON)
+ENDIF()
+FIND_PACKAGE(Boost REQUIRED COMPONENTS system program_options regex thread date_time)
MESSAGE(STATUS "Boost include files found in ${Boost_INCLUDE_DIRS}")
MESSAGE(STATUS "Boost libraries found in ${Boost_LIBRARY_DIRS}")
-# Find Open CASCADE header files
-IF("$ENV{OCC_INCLUDE_DIR}" STREQUAL "")
- SET(OCC_INCLUDE_DIR "/usr/include/opencascade/" CACHE FILEPATH "Open CASCADE header files")
+# Usage:
+# SET(SOME_LIRARIES foo bar)
+# ADD_DEBUG_VARIANTS(SOME_LIRARIES "${SOME_LIRARIES}" "d")
+# "foo bar" -> "optimized foo debug food optimized bar debug bard"
+FUNCTION(ADD_DEBUG_VARIANTS NAME LIBRARIES POSTFIX)
+ SET(LIBRARIES_STR "${LIBRARIES}")
+ SET(LIBRARIES "")
+ FOREACH(lib ${LIBRARIES_STR})
+ SET(LIBRARIES "${LIBRARIES} optimized ${lib}")
+ SET(LIBRARIES "${LIBRARIES} debug ${lib}${POSTFIX}")
+ ENDFOREACH()
+ STRING(STRIP ${LIBRARIES} LIBRARIES) # leading and trailing whitespace cause confusion
+ SEPARATE_ARGUMENTS(LIBRARIES) # "optimized debug " needs to be a list instead of a string
+ SET(${NAME} ${LIBRARIES} PARENT_SCOPE)
+ENDFUNCTION()
+
+# Find Open CASCADE
+IF("${OCC_INCLUDE_DIR}" STREQUAL "")
+ SET(OCC_INCLUDE_DIR "/usr/include/oce/" CACHE FILEPATH "Open CASCADE header files")
MESSAGE(STATUS "Looking for opencascade include files in: ${OCC_INCLUDE_DIR}")
MESSAGE(STATUS "Use OCC_INCLUDE_DIR to specify another directory")
ELSE()
- SET(OCC_INCLUDE_DIR $ENV{OCC_INCLUDE_DIR} CACHE FILEPATH "Open CASCADE header files")
+ SET(OCC_INCLUDE_DIR ${OCC_INCLUDE_DIR} CACHE FILEPATH "Open CASCADE header files")
MESSAGE(STATUS "Looking for opencascade include files in: ${OCC_INCLUDE_DIR}")
ENDIF()
@@ -22,220 +96,351 @@ ELSE()
MESSAGE(FATAL_ERROR "Unable to find header files, aborting")
ENDIF()
-# Find Open CASCADE library files
-IF("$ENV{OCC_LIBRARY_DIR}" STREQUAL "")
+SET(OPENCASCADE_LIBRARIES
+ TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO
+ TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset
+)
+
+IF(MSVC)
+ ADD_DEBUG_VARIANTS(OPENCASCADE_LIBRARIES "${OPENCASCADE_LIBRARIES}" "d")
+ENDIF()
+
+IF("${OCC_LIBRARY_DIR}" STREQUAL "")
SET(OCC_LIBRARY_DIR "/usr/lib/" CACHE FILEPATH "Open CASCADE library files")
MESSAGE(STATUS "Looking for opencascade library files in: ${OCC_LIBRARY_DIR}")
MESSAGE(STATUS "Use OCC_LIBRARY_DIR to specify another directory")
ELSE()
- SET(OCC_LIBRARY_DIR $ENV{OCC_LIBRARY_DIR} CACHE FILEPATH "Open CASCADE library files")
+ SET(OCC_LIBRARY_DIR ${OCC_LIBRARY_DIR} CACHE FILEPATH "Open CASCADE library files")
MESSAGE(STATUS "Looking for opencascade library files in: ${OCC_LIBRARY_DIR}")
ENDIF()
-FIND_LIBRARY(libTKernel "TKernel" ${OCC_LIBRARY_DIR} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64)
+FIND_LIBRARY(libTKernel NAMES TKernel TKerneld PATHS ${OCC_LIBRARY_DIR} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64)
IF(libTKernel)
MESSAGE(STATUS "Library files found")
ELSE()
MESSAGE(FATAL_ERROR "Unable to find library files, aborting")
ENDIF()
-IF("$ENV{ICU_INCLUDE_DIR}" STREQUAL "")
- MESSAGE(STATUS "No ICU include directory specified")
-ElSE()
- SET(ICU_INCLUDE_DIR CACHE FILEPATH "ICU header files")
+IF(UNICODE_SUPPORT)
+ # Find ICU
+ IF("${ICU_INCLUDE_DIR}" STREQUAL "")
+ MESSAGE(STATUS "No ICU include directory specified")
+ ElSE()
+ SET(ICU_INCLUDE_DIR "${ICU_INCLUDE_DIR}" CACHE FILEPATH "ICU header files")
+ ENDIF()
+
+ IF("${ICU_LIBRARY_DIR}" STREQUAL "")
+ MESSAGE(STATUS "No ICU library directory specified")
+ ElSE()
+ SET(ICU_LIBRARY_DIR "${ICU_LIBRARY_DIR}" CACHE FILEPATH "ICU library files")
+ ENDIF()
+
+ FIND_LIBRARY(icu NAMES icuuc icuucd PATHS /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 ${ICU_LIBRARY_DIR})
+
+ IF(icu)
+ ADD_DEFINITIONS(-DHAVE_ICU)
+ MESSAGE(STATUS "ICU libraries found")
+ # NOTE icudata appears to be icudt on Windows/MSVC and icudata on others
+ # dl is included to resolve dlopen and friends symbols
+ IF(MSVC)
+ SET(ICU_LIBRARIES icuuc icudt)
+ ADD_DEBUG_VARIANTS(ICU_LIBRARIES "${ICU_LIBRARIES}" "d")
+ ADD_DEFINITIONS(-DU_STATIC_IMPLEMENTATION) # required for static ICU
+ ELSE()
+ SET(ICU_LIBRARIES icuuc icudata dl)
+ ENDIF()
+ ELSE()
+ MESSAGE(FATAL_ERROR "UNICODE_SUPPORT enabled, but unable to find ICU. Disable UNICODE_SUPPORT or fix ICU paths to proceed.")
+ ENDIF()
ENDIF()
-IF("$ENV{ICU_LIBRARY_DIR}" STREQUAL "")
- MESSAGE(STATUS "No ICU library directory specified")
-ElSE()
- SET(ICU_LIBRARY_DIR CACHE FILEPATH "ICU library files")
+IF(COLLADA_SUPPORT)
+ # Find OpenCOLLADA
+ IF("${OPENCOLLADA_INCLUDE_DIR}" STREQUAL "")
+ MESSAGE(STATUS "No OpenCOLLADA include directory specified")
+ SET(OPENCOLLADA_INCLUDE_DIR "/usr/include/opencollada" CACHE FILEPATH "OpenCOLLADA header files")
+ ElSE()
+ SET(OPENCOLLADA_INCLUDE_DIR "${OPENCOLLADA_INCLUDE_DIR}" CACHE FILEPATH "OpenCOLLADA header files")
+ ENDIF()
+
+ IF("${OPENCOLLADA_LIBRARY_DIR}" STREQUAL "")
+ MESSAGE(STATUS "No OpenCOLLADA library directory specified")
+ SET(OPENCOLLADA_LIBRARY_DIR "/usr/lib/opencollada" CACHE FILEPATH "OpenCOLLADA library files")
+ ElSE()
+ SET(OPENCOLLADA_LIBRARY_DIR "${OPENCOLLADA_LIBRARY_DIR}" CACHE FILEPATH "OpenCOLLADA library files")
+ ENDIF()
+
+ SET(OPENCOLLADA_INCLUDE_DIRS "${OPENCOLLADA_INCLUDE_DIR}/COLLADABaseUtils" "${OPENCOLLADA_INCLUDE_DIR}/COLLADAStreamWriter")
+
+ FIND_FILE(COLLADASWStreamWriter_h "COLLADASWStreamWriter.h" ${OPENCOLLADA_INCLUDE_DIRS})
+ IF(COLLADASWStreamWriter_h)
+ MESSAGE(STATUS "OpenCOLLADA header files found")
+ ADD_DEFINITIONS(-DWITH_OPENCOLLADA)
+ SET(OPENCOLLADA_LIBRARIES
+ GeneratedSaxParser MathMLSolver OpenCOLLADABaseUtils OpenCOLLADAFramework OpenCOLLADASaxFrameworkLoader
+ OpenCOLLADAStreamWriter UTF buffer ftoa pcre
+ )
+ IF(NOT "${PCRE_LIBRARY_DIR}" STREQUAL "")
+ SET(OPENCOLLADA_LIBRARY_DIR ${OPENCOLLADA_LIBRARY_DIR} ${PCRE_LIBRARY_DIR})
+ ENDIF()
+ IF(MSVC)
+ ADD_DEBUG_VARIANTS(OPENCOLLADA_LIBRARIES "${OPENCOLLADA_LIBRARIES}" "d")
+ ENDIF()
+ ELSE()
+ MESSAGE(FATAL_ERROR "COLLADA_SUPPORT enabled, but unable to find OpenCOLLADA. Disable COLLADA_SUPPORT or fix OpenCOLLADA paths to proceed.")
+ ENDIF()
ENDIF()
-FIND_LIBRARY(icu "icuuc" /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 ${ICU_LIBRARY_DIR})
+ # TODO Are these needed on other platforms still or can these be removed for good?
+IF (NOT WIN32)
+ INCLUDE(CheckIncludeFileCXX)
-IF(icu)
- MESSAGE(STATUS "ICU libraries found")
- ADD_DEFINITIONS(-DHAVE_ICU)
- SET(ICU_LIBRARIES icuuc icudata)
-ELSE()
- MESSAGE(STATUS "Unable to find ICU library files, continuing")
+ MACRO(CHECK_ADD_OCE_OCC_DEF INCLUDE)
+ STRING(REPLACE . _ STR ${INCLUDE})
+ STRING(TOUPPER ${STR} STR)
+ CHECK_INCLUDE_FILE_CXX("${INCLUDE}" FOUND_${STR})
+ IF(FOUND_${STR})
+ ADD_DEFINITIONS(-DOCE_HAVE_${STR})
+ ADD_DEFINITIONS(-DHAVE_${STR})
+ ENDIF(FOUND_${STR})
+ ENDMACRO()
+
+ CHECK_ADD_OCE_OCC_DEF(limits)
+ CHECK_ADD_OCE_OCC_DEF(climits)
+ CHECK_ADD_OCE_OCC_DEF(limits.h)
+ CHECK_ADD_OCE_OCC_DEF(fstream)
+ CHECK_ADD_OCE_OCC_DEF(fstream.h)
+ CHECK_ADD_OCE_OCC_DEF(iomanip)
+ CHECK_ADD_OCE_OCC_DEF(iomanip.h)
+ CHECK_ADD_OCE_OCC_DEF(iostream)
+ CHECK_ADD_OCE_OCC_DEF(iostream.h)
ENDIF()
-IF("$ENV{OPENCOLLADA_INCLUDE_DIR}" STREQUAL "")
- MESSAGE(STATUS "No OpenCOLLADA include directory specified")
- SET(OPENCOLLADA_INCLUDE_DIR "/usr/local/include/opencollada" CACHE FILEPATH "OpenCOLLADA header files")
-ElSE()
- SET(OPENCOLLADA_INCLUDE_DIR "$ENV{OPENCOLLADA_INCLUDE_DIR}" CACHE FILEPATH "OpenCOLLADA header files")
-ENDIF()
-
-IF("$ENV{OPENCOLLADA_LIBRARY_DIR}" STREQUAL "")
- MESSAGE(STATUS "No OpenCOLLADA library directory specified")
- SET(OPENCOLLADA_LIBRARY_DIR "/usr/local/lib/opencollada" CACHE FILEPATH "OpenCOLLADA library files")
-ElSE()
- SET(OPENCOLLADA_LIBRARY_DIR "$ENV{OPENCOLLADA_LIBRARY_DIR}" CACHE FILEPATH "OpenCOLLADA library files")
-ENDIF()
-
-SET(OPENCOLLADA_INCLUDE_DIRS "${OPENCOLLADA_INCLUDE_DIR}/COLLADABaseUtils" "${OPENCOLLADA_INCLUDE_DIR}/COLLADAStreamWriter")
-
-FIND_FILE(COLLADASWStreamWriter_h "COLLADASWStreamWriter.h" ${OPENCOLLADA_INCLUDE_DIRS})
-IF(COLLADASWStreamWriter_h)
- MESSAGE(STATUS "OpenCOLLADA header files found")
- ADD_DEFINITIONS(-DWITH_OPENCOLLADA)
- SET(OPENCOLLADA_LIBRARIES
- GeneratedSaxParser MathMLSolver OpenCOLLADABaseUtils
- OpenCOLLADAFramework OpenCOLLADASaxFrameworkLoader
- OpenCOLLADAStreamWriter UTF buffer ftoa pcre
- )
-ELSE()
- MESSAGE(STATUS "OpenCOLLADA header files not found, continuing without COLLADA support")
-ENDIF()
-
-INCLUDE(CheckIncludeFileCXX)
-
-MACRO(CHECK_ADD_OCE_OCC_DEF INCLUDE)
- STRING(REPLACE . _ STR ${INCLUDE})
- STRING(TOUPPER ${STR} STR)
- CHECK_INCLUDE_FILE_CXX("${INCLUDE}" FOUND_${STR})
- IF(FOUND_${STR})
- ADD_DEFINITIONS(-DOCE_HAVE_${STR})
- ADD_DEFINITIONS(-DHAVE_${STR})
- ENDIF(FOUND_${STR})
-ENDMACRO(CHECK_ADD_OCE_OCC_DEF)
-
-CHECK_ADD_OCE_OCC_DEF(limits)
-CHECK_ADD_OCE_OCC_DEF(climits)
-CHECK_ADD_OCE_OCC_DEF(limits.h)
-CHECK_ADD_OCE_OCC_DEF(fstream)
-CHECK_ADD_OCE_OCC_DEF(fstream.h)
-CHECK_ADD_OCE_OCC_DEF(iomanip)
-CHECK_ADD_OCE_OCC_DEF(iomanip.h)
-CHECK_ADD_OCE_OCC_DEF(iostream)
-CHECK_ADD_OCE_OCC_DEF(iostream.h)
-
IF(NOT CMAKE_BUILD_TYPE)
- SET(CMAKE_BUILD_TYPE "Release")
-ENDIF(NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE "Release")
+ENDIF()
+
+# NOTE: RelWithDebInfo and Release use O2 (= /Ox /Gl /Gy/ = Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy) by default,
+# with the exception with RelWithDebInfo has /Ob1 instead. /Ob2 has been observed to improve the performance
+# of IfcConvert significantly.
+# TODO Setting of /GL and /LTCG don't seem to apply for static libraries (IfcGeom, IfcParse)
+if(ENABLE_BUILD_OPTIMIZATIONS)
+ if(MSVC)
+ # C++
+ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ob2 /GL")
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
+ # Linker
+ # /OPT:REF enables also /OPT:ICF and disables INCREMENTAL
+ set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
+ # /OPT:NOICF is recommended when /DEBUG is used (http://msdn.microsoft.com/en-us/library/xe4t6fc1.aspx)
+ set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF")
+ set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG /OPT:REF")
+ set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG /OPT:NOICF")
+ else()
+ #TODO GCC (& Clang?) optimizations
+ message(STATUS "ENABLE_BUILD_OPTIMIZATIONS not implemented for GCC/non-MSVC compilers.)")
+ endif()
+endif()
IF(MSVC)
- ADD_DEFINITIONS(-D_UNICODE)
-ElSE(MSVC)
- ADD_DEFINITIONS(-fPIC -Wno-non-virtual-dtor)
-ENDIF(MSVC)
+ # Enable solution folders (free VS versions prior to 2012 don't support solution folders)
+ if (MSVC_VERSION GREATER 1600)
+ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+ endif()
-INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS} /usr/inc /usr/local/inc /usr/local/include/oce ${ICU_INCLUDE_DIR} ${Boost_INCLUDE_DIRS})
-
-ADD_LIBRARY(IfcParse STATIC
- ../src/ifcparse/Ifc2x3-latebound.cpp
- ../src/ifcparse/Ifc2x3.cpp
- ../src/ifcparse/Ifc4-latebound.cpp
- ../src/ifcparse/Ifc4.cpp
- ../src/ifcparse/IfcCharacterDecoder.cpp
- ../src/ifcparse/IfcGlobalId.cpp
- ../src/ifcparse/IfcHierarchyHelper.cpp
- ../src/ifcparse/IfcLateBoundEntity.cpp
- ../src/ifcparse/IfcParse.cpp
- ../src/ifcparse/IfcSIPrefix.cpp
- ../src/ifcparse/IfcSpfHeader.cpp
- ../src/ifcparse/IfcUtil.cpp
- ../src/ifcparse/IfcWrite.cpp
-)
-
-ADD_LIBRARY(IfcGeom STATIC
- ../src/ifcgeom/IfcGeomCurves.cpp
- ../src/ifcgeom/IfcGeomFaces.cpp
- ../src/ifcgeom/IfcGeomFunctions.cpp
- ../src/ifcgeom/IfcGeomHelpers.cpp
- ../src/ifcgeom/IfcGeomMaterial.cpp
- ../src/ifcgeom/IfcGeomRenderStyles.cpp
- ../src/ifcgeom/IfcGeomRepresentation.cpp
- ../src/ifcgeom/IfcGeomShapes.cpp
- ../src/ifcgeom/IfcGeomWires.cpp
- ../src/ifcgeom/IfcRegister.cpp
-)
-
-IF(icu)
- TARGET_LINK_LIBRARIES(IfcParse icuuc)
+ IF(USE_VLD)
+ ADD_DEFINITIONS(-DUSE_VLD)
+ ENDIF()
+ # Enforce Unicode for CRT and Win32 API calls
+ ADD_DEFINITIONS(-D_UNICODE -DUNICODE)
+ # Disable warnings about unsafe C functions; we could use the safe C99 & C11 versions if we have no need for supporting old compilers.
+ ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS)
+ ADD_DEFINITIONS(-bigobj) # required for building the big ifcXXX.objs, https://msdn.microsoft.com/en-us/library/ms173499.aspx
+ # Bump up the warning level from the default 3 to 4.
+ ADD_DEFINITIONS(-W4)
+ IF(MSVC_VERSION GREATER 1800) # > 2013
+ # Disable overeager and false positives causing C4458 ("declaration of 'indentifier' hides class member"), at least for now.
+ ADD_DEFINITIONS(-wd4458)
+ ENDIF()
+ # Link against the static VC runtime
+ FOREACH(flag CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL
+ CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+ CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO)
+ IF(${flag} MATCHES "/MD")
+ STRING(REGEX REPLACE "/MD" "/MT" ${flag} "${${flag}}")
+ ENDIF()
+ IF(${flag} MATCHES "/MDd")
+ STRING(REGEX REPLACE "/MDd" "/MTd" ${flag} "${${flag}}")
+ ENDIF()
+ ENDFOREACH()
+ElSE()
+ ADD_DEFINITIONS(-fPIC -Wno-non-virtual-dtor)
ENDIF()
+INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} ${OCC_INCLUDE_DIR} ${OPENCOLLADA_INCLUDE_DIRS}
+ ${ICU_INCLUDE_DIR} ${Boost_INCLUDE_DIRS}
+)
+if(NOT WIN32)
+ INCLUDE_DIRECTORIES(${INCLUDE_DIRECTORIES} /usr/inc /usr/local/inc /usr/local/include/oce)
+endif()
+
+function(files_for_ifc_version IFC_VERSION RESULT_NAME)
+ set(IFC_PARSE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcparse)
+ set(${RESULT_NAME}
+ ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}.h
+ ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}enum.h
+ ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}-latebound.h
+ ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}.cpp
+ ${IFC_PARSE_DIR}/Ifc${IFC_VERSION}-latebound.cpp
+ PARENT_SCOPE
+ )
+endfunction()
+
+if(COMPILE_SCHEMA)
+ find_package(PythonInterp)
+
+ IF(NOT PYTHONINTERP_FOUND)
+ MESSAGE(FATAL_ERROR "A Python interpreter is necessary when COMPILE_SCHEMA is enabled. Disable COMPILE_SCHEMA or fix Python paths to proceed.")
+ ENDIF()
+
+ set(IFC_RELEASE_NOT_USED "2x3" "4")
+
+ # Install pyparsing if necessary
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip freeze OUTPUT_VARIABLE PYTHON_PACKAGE_LIST)
+ if ("${PYTHON_PACKAGE_LIST}" STREQUAL "")
+ execute_process(COMMAND pip freeze OUTPUT_VARIABLE PYTHON_PACKAGE_LIST)
+ if ("${PYTHON_PACKAGE_LIST}" STREQUAL "")
+ message(WARNING "Failed to find pip. Pip is required to automatically install pyparsing")
+ endif()
+ endif()
+ string(FIND "${PYTHON_PACKAGE_LIST}" pyparsing PYPARSING_FOUND)
+ if ("${PYPARSING_FOUND}" STREQUAL "-1")
+ message(STATUS "Installing pyparsing")
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip "install" --user pyparsing RESULT_VARIABLE SUCCESS)
+ if (NOT "${SUCCESS}" STREQUAL "0")
+ execute_process(COMMAND pip "install" --user pyparsing RESULT_VARIABLE SUCCESS)
+ if (NOT "${SUCCESS}" STREQUAL "0")
+ message(WARNING "Failed to automatically install pyparsing. Please install manually")
+ endif()
+ endif()
+ else()
+ message(STATUS "Python interpreter with pyparsing found")
+ endif()
+
+ # Bootstrap the parser
+ message(STATUS "Compiling schema, this will take a while...")
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} bootstrap.py express.bnf
+ WORKING_DIRECTORY ../src/ifcexpressparser
+ OUTPUT_FILE express_parser.py
+ RESULT_VARIABLE SUCCESS)
+
+ if (NOT "${SUCCESS}" STREQUAL "0")
+ MESSAGE(FATAL_ERROR "Failed to bootstrap parser. Make sure pyparsing is installed")
+ endif()
+
+ # Generate code
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} ../ifcexpressparser/express_parser.py ../../${COMPILE_SCHEMA}
+ WORKING_DIRECTORY ../src/ifcparse
+ OUTPUT_VARIABLE COMPILED_SCHEMA_NAME)
+
+ # Prevent the schema that had just been compiled from being excluded
+ if("${COMPILED_SCHEMA_NAME}" STREQUAL "IFC2X3")
+ list(REMOVE_ITEM IFC_RELEASE_NOT_USED "2x3")
+ add_definitions(-DUSE_IFC2x3)
+ elseif("${COMPILED_SCHEMA_NAME}" STREQUAL "IFC4")
+ list(REMOVE_ITEM IFC_RELEASE_NOT_USED "4")
+ add_definitions(-DUSE_IFC4)
+ endif()
+else()
+ if(USE_IFC4)
+ add_definitions(-DUSE_IFC4)
+ set(IFC_RELEASE_NOT_USED "2x3")
+ else()
+ add_definitions(-DUSE_IFC2x3) # TODO Make all caps? i.e. USE_IFC2X3
+ set(IFC_RELEASE_NOT_USED "4")
+ endif()
+endif()
+
+# IfcParse
+file(GLOB IFCPARSE_H_FILES ../src/ifcparse/*.h)
+file(GLOB IFCPARSE_CPP_FILES ../src/ifcparse/*.cpp)
+
+foreach(IFC_RELEASE ${IFC_RELEASE_NOT_USED})
+ files_for_ifc_version(${IFC_RELEASE} SOURCE_FILES_NOT_USED)
+ foreach(SOURCE_FILE ${SOURCE_FILES_NOT_USED})
+ list(REMOVE_ITEM IFCPARSE_CPP_FILES ${SOURCE_FILE})
+ list(REMOVE_ITEM IFCPARSE_H_FILES ${SOURCE_FILE})
+ endforeach()
+endforeach()
+
+set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
+
+ADD_LIBRARY(IfcParse STATIC ${IFCPARSE_FILES})
+
+IF(UNICODE_SUPPORT)
+ TARGET_LINK_LIBRARIES(IfcParse ${ICU_LIBRARIES} ${Boost_LIBRARIES})
+ENDIF()
+
+# IfcGeom
+file(GLOB IFCGEOM_H_FILES ../src/ifcgeom/*.h)
+file(GLOB IFCGEOM_CPP_FILES ../src/ifcgeom/*.cpp)
+
+set(IFCGEOM_FILES ${IFCGEOM_CPP_FILES} ${IFCGEOM_H_FILES})
+ADD_LIBRARY(IfcGeom STATIC ${IFCGEOM_FILES})
+
TARGET_LINK_LIBRARIES(IfcGeom IfcParse)
-LINK_DIRECTORIES (${LINK_DIRECTORIES} ${IfcOpenShell_BINARY_DIR} ${OCC_LIBRARY_DIR} ${OPENCOLLADA_LIBRARY_DIR} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 ${ICU_LIBRARY_DIR} ${Boost_LIBRARY_DIRS})
-
-ADD_EXECUTABLE(IfcConvert
- ../src/ifcconvert/ColladaSerializer.cpp
- ../src/ifcconvert/IfcConvert.cpp
- ../src/ifcconvert/OpenCascadeBasedSerializer.cpp
- ../src/ifcconvert/WavefrontObjSerializer.cpp
- ../src/ifcconvert/XmlSerializer.cpp
- ../src/ifcconvert/SvgSerializer.cpp
- ../src/ifcconvert/util.cpp
+LINK_DIRECTORIES(${LINK_DIRECTORIES} ${IfcOpenShell_BINARY_DIR} ${OCC_LIBRARY_DIR} ${OPENCOLLADA_LIBRARY_DIR}
+ ${ICU_LIBRARY_DIR} ${Boost_LIBRARY_DIRS}
)
+if(NOT WIN32)
+ LINK_DIRECTORIES(${LINK_DIRECTORIES} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64)
+endif()
-TARGET_LINK_LIBRARIES (IfcConvert IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${ICU_LIBRARIES})
+# IfcConvert
+if (IFCCONVERT_DOUBLE_PRECISION)
+ add_definitions(-DIFCCONVERT_DOUBLE_PRECISION)
+endif()
+file(GLOB IFCCONVERT_CPP_FILES ../src/ifcconvert/*.cpp)
+file(GLOB IFCCONVERT_H_FILES ../src/ifcconvert/*.h)
+set(IFCCONVERT_FILES ${IFCCONVERT_CPP_FILES} ${IFCCONVERT_H_FILES})
+ADD_EXECUTABLE(IfcConvert ${IFCCONVERT_FILES})
-ADD_EXECUTABLE(IfcGeomServer
- ../src/ifcgeomserver/IfcGeomServer.cpp
-)
+# Make sure cross-referenced symbols between static OCC libraries get
+# resolved. Also add thread and rt libraries.
+get_filename_component(libTKernelExt ${libTKernel} EXT)
+if("${libTKernelExt}" STREQUAL ".a")
+ find_package(Threads)
+ if (NOT APPLE)
+ set(LIB_RT "rt")
+ endif()
+ set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${LIB_RT} dl)
+endif()
-TARGET_LINK_LIBRARIES (IfcGeomServer IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset ${ICU_LIBRARIES})
+TARGET_LINK_LIBRARIES(IfcConvert IfcParse IfcGeom ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${ICU_LIBRARIES})
-# Build python wrapper using separate CMakeLists.txt
-ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
+# IfcGeomServer
+file(GLOB CPP_FILES ../src/ifcgeomserver/*.cpp)
+file(GLOB H_FILES ../src/ifcgeomserver/*.h)
+set(SOURCE_FILES ${CPP_FILES} ${H_FILES})
+ADD_EXECUTABLE(IfcGeomServer ${SOURCE_FILES})
-# Build IfcParseExamples using separate CMakeLists.txt
-ADD_SUBDIRECTORY(../src/examples examples)
+TARGET_LINK_LIBRARIES(IfcGeomServer IfcParse IfcGeom ${OPENCASCADE_LIBRARIES} ${Boost_LIBRARIES} ${ICU_LIBRARIES})
-# ADD_SUBDIRECTORY(../src/qtviewer qtviewer)
+IF(BUILD_IFCPYTHON)
+ ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
+ENDIF()
+
+IF(BUILD_EXAMPLES)
+ ADD_SUBDIRECTORY(../src/examples examples)
+ENDIF()
+
+IF(BUILD_IFCMAX)
+ ADD_SUBDIRECTORY(../src/ifcmax ifcmax)
+ENDIF()
# CMake installation targets
-SET(include_files_geom
- ../src/ifcgeom/IfcGeom.h
- ../src/ifcgeom/IfcGeomElement.h
- ../src/ifcgeom/IfcGeomIterator.h
- ../src/ifcgeom/IfcGeomIteratorSettings.h
- ../src/ifcgeom/IfcGeomMaterial.h
- ../src/ifcgeom/IfcGeomRenderStyles.h
- ../src/ifcgeom/IfcGeomRepresentation.h
- ../src/ifcgeom/IfcGeomShapeType.h
- ../src/ifcgeom/IfcRegister.h
- ../src/ifcgeom/IfcRegisterConvertCurve.h
- ../src/ifcgeom/IfcRegisterConvertFace.h
- ../src/ifcgeom/IfcRegisterConvertShape.h
- ../src/ifcgeom/IfcRegisterConvertShapes.h
- ../src/ifcgeom/IfcRegisterConvertWire.h
- ../src/ifcgeom/IfcRegisterCreateCache.h
- ../src/ifcgeom/IfcRegisterDef.h
- ../src/ifcgeom/IfcRegisterGeomHeader.h
- ../src/ifcgeom/IfcRegisterPurgeCache.h
- ../src/ifcgeom/IfcRegisterShapeType.h
- ../src/ifcgeom/IfcRegisterUndef.h
- ../src/ifcgeom/IfcRepresentationShapeItem.h
-)
-
-SET(include_files_parse
- ../src/ifcparse/Ifc2x3-latebound.h
- ../src/ifcparse/Ifc2x3.h
- ../src/ifcparse/Ifc2x3enum.h
- ../src/ifcparse/Ifc4-latebound.h
- ../src/ifcparse/Ifc4.h
- ../src/ifcparse/Ifc4enum.h
- ../src/ifcparse/IfcCharacterDecoder.h
- ../src/ifcparse/IfcEntityDescriptor.h
- ../src/ifcparse/IfcException.h
- ../src/ifcparse/IfcFile.h
- ../src/ifcparse/IfcGlobalId.h
- ../src/ifcparse/IfcHierarchyHelper.h
- ../src/ifcparse/IfcLateBoundEntity.h
- ../src/ifcparse/IfcParse.h
- ../src/ifcparse/IfcSIPrefix.h
- ../src/ifcparse/IfcSpfHeader.h
- ../src/ifcparse/IfcSpfStream.h
- ../src/ifcparse/IfcUtil.h
- ../src/ifcparse/IfcWritableEntity.h
- ../src/ifcparse/IfcWrite.h
- ../src/ifcparse/SharedPointer.h
-)
-INSTALL(FILES ${include_files_geom} DESTINATION include/ifcgeom)
-INSTALL(FILES ${include_files_parse} DESTINATION include/ifcparse)
-INSTALL(TARGETS IfcConvert DESTINATION bin)
+INSTALL(FILES ${IFCPARSE_H_FILES} DESTINATION include/ifcparse)
+INSTALL(FILES ${IFCGEOM_H_FILES} DESTINATION include/ifcgeom)
+INSTALL(TARGETS IfcConvert IfcGeomServer DESTINATION bin)
INSTALL(TARGETS IfcParse IfcGeom DESTINATION lib)
diff --git a/nix/build-all.sh b/nix/build-all.sh
new file mode 100755
index 0000000000..f75be91f93
--- /dev/null
+++ b/nix/build-all.sh
@@ -0,0 +1,402 @@
+###############################################################################
+# #
+# This file is part of IfcOpenShell. #
+# #
+# IfcOpenShell is free software: you can redistribute it and/or modify #
+# it under the terms of the Lesser GNU General Public License as published by #
+# the Free Software Foundation, either version 3.0 of the License, or #
+# (at your option) any later version. #
+# #
+# IfcOpenShell is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# Lesser GNU General Public License for more details. #
+# #
+# You should have received a copy of the Lesser GNU General Public License #
+# along with this program. If not, see . #
+# #
+###############################################################################
+
+###############################################################################
+# #
+# This script builds IfcOpenShell and its dependencies #
+# #
+# Prerequisites for this script to function correctly: #
+# * git * bzip2 * tar * c(++) compilers * yacc * autoconf #
+# on debian 7.8 these can be obtained with: #
+# $ apt-get install git gcc g++ autoconf bison bzip2 #
+# on ubuntu 14.04: #
+# $ apt-get install git gcc g++ autoconf bison make #
+# on OS X El Capitan with homebrew: #
+# $ brew install git bison autoconf automake #
+# #
+###############################################################################
+
+set -e
+
+PROJECT_NAME=IfcOpenShell
+OCE_VERSION=0.16
+PYTHON_VERSIONS=(2.7.10 3.2.6 3.3.6 3.4.4 3.5.1)
+BOOST_VERSION=1.59.0
+PCRE_VERSION=8.38
+LIBXML_VERSION=2.9.3
+CMAKE_VERSION=3.4.1
+ICU_VERSION=56.1
+
+# Helper function for coloured printing
+
+BLACK_ON_WHITE="\033[0;30;107m"
+RED="\033[31m"
+GREEN="\033[32m"
+YELLOW="\033[33m"
+MAGENTA="\033[35m"
+function cecho {
+ printf "$1$2\033[0m\n"
+}
+
+function fullpath {
+ python -c "import os, sys; print os.path.realpath(os.path.dirname(sys.argv[1]))" "$1"
+}
+
+# Set defaults for missing empty environment variables
+
+if [ -z "$IFCOS_NUM_BUILD_PROCS" ]; then
+IFCOS_NUM_BUILD_PROCS=$(expr $(sysctl -n hw.ncpu 2> /dev/null || cat /proc/cpuinfo | grep processor | wc -l) + 1)
+fi
+
+if [ -z "$TARGET_ARCH" ]; then
+TARGET_ARCH="$(uname -m)"
+fi
+
+SCRIPT_DIR=`fullpath "$0"`
+CMAKE_DIR="$SCRIPT_DIR/../cmake/"
+
+if [ -z "$DEPS_DIR" ]; then
+DEPS_DIR="$SCRIPT_DIR/../build/$(uname)/$TARGET_ARCH/"
+[ -d $DEPS_DIR ] || mkdir -p $DEPS_DIR
+DEPS_DIR=`fullpath $DEPS_DIR`
+fi
+
+if [ -z "$BUILD_CFG" ]; then
+BUILD_CFG="RelWithDebInfo"
+fi
+
+if [ -z "$BUILD_TYPE" ]; then
+BUILD_TYPE=Build
+fi
+
+# Print build configuration information
+
+cecho $BLACK_ON_WHITE "This script fetches and builds $PROJECT_NAME and its dependencies"
+echo ""
+cecho $GREEN "Script configuration:"
+
+cecho $MAGENTA "* Target Architecture = $TARGET_ARCH"
+echo " - Whether 32-bit (i686) or 64-bit (x86_64) will be built."
+cecho $MAGENTA "* Dependency Directory = $DEPS_DIR"
+echo " - The directory where $PROJECT_NAME dependencies are installed."
+cecho $MAGENTA "* Build Config Type = $BUILD_CFG"
+echo " - The used build configuration type for the dependencies."
+echo " Defaults to RelWithDebInfo if not specified."
+
+if [ "$BUILD_CFG" = "MinSizeRel" ]; then
+cecho $RED " WARNING: MinSizeRel build can suffer from a significant performance loss."
+fi
+
+cecho $MAGENTA "* IFCOS_NUM_BUILD_PROCS = $IFCOS_NUM_BUILD_PROCS"
+echo " - How many compiler processes may be run in parallel."
+
+echo ""
+
+# Check that required tools are in PATH
+
+for cmd in git bunzip2 tar cc c++ autoconf automake yacc make
+do
+ which $cmd > /dev/null || { cecho $RED "Required tool '$cmd' not installed or not added to PATH" ; exit 1 ; }
+done
+
+which curl > /dev/null && DOWNLOAD="curl -sLO"
+which wget > /dev/null && DOWNLOAD="wget -q --no-check-certificate"
+
+if [ -z "$DOWNLOAD" ]; then
+ cecho $RED "No download application found, tried: curl, wget"
+ exit 1
+fi
+
+# Create log directory and file
+
+mkdir -p $DEPS_DIR/logs
+LOG_FILE=$DEPS_DIR/logs/`date +"%Y%m%d"`.log
+
+BOOST_VERSION_UNDERSCORE=${BOOST_VERSION//./_}
+ICU_VERSION_UNDERSCORE=${ICU_VERSION//./_}
+CMAKE_VERSION_2=${CMAKE_VERSION:0:3}
+
+OCE_LOCATION=https://github.com/tpaviot/oce/archive/OCE-$OCE_VERSION.tar.gz
+BOOST_LOCATION=http://downloads.sourceforge.net/project/boost/boost/$BOOST_VERSION/boost_$BOOST_VERSION_UNDERSCORE.tar.bz2
+OPENCOLLADA_LOCATION=https://github.com/KhronosGroup/OpenCOLLADA.git
+OPENCOLLADA_COMMIT=f99d59e73e565a41715eaebc00c7664e1ee5e628
+
+# Helper functions
+
+function download {
+ [ -f $2 ] || $DOWNLOAD $1$2
+}
+
+function run_autoconf {
+ if [ ! -f ../configure ]; then
+ pushd . >>$LOG_FILE 2>&1
+ cd ..
+ ./autogen.sh >>$LOG_FILE 2>&1
+ popd >>$LOG_FILE 2>&1
+ fi
+ ../configure $2 --prefix=$DEPS_DIR/install/$1 >>$LOG_FILE 2>&1
+}
+
+function run_cmake {
+ if [ -z "$3" ]; then
+ P=..
+ else
+ P=$3
+ fi
+ $DEPS_DIR/install/cmake-$CMAKE_VERSION/bin/cmake $P $2 -DCMAKE_BUILD_TYPE=$BUILD_TYPE >>$LOG_FILE 2>&1
+}
+
+function run_icu {
+ PLATFORM=`uname -s`
+ if [ $PLATFORM == "Darwin" ]; then
+ PLATFORM=MacOSX
+ fi
+ ../source/runConfigureICU $PLATFORM $2 --prefix=$DEPS_DIR/install/$1 >>$LOG_FILE 2>&1
+}
+
+function git_clone {
+ [ -d $2 ] || git clone $1 >>$LOG_FILE 2>&1
+ if [ ! -z "$3" ]; then
+ cd $2
+ git checkout $3 >>$LOG_FILE 2>&1
+ cd ..
+ fi
+}
+
+function build_dependency {
+ if [ -e $DEPS_DIR/install/$1 ]; then
+ echo "Found existing $1"
+ return
+ fi
+ mkdir -p $DEPS_DIR/build/
+ cd $DEPS_DIR/build/
+ printf "\rFetching $1... "
+ $6 $4 $5 $7
+ if [ -d $5 ]; then
+ DEP_NAME=$5
+ else
+ DEP_NAME=`tar --exclude="*/*" -tf $5`
+ [ -z $DEP_NAME ] && DEP_NAME=`tar -tf $5 2> /dev/null | head -n 1 | cut -f1 -d /`
+ [ -d $DEP_NAME ] || tar -xf $5
+ fi
+ cd $DEP_NAME
+ if [ "$2" != "bjam" ]; then
+ [ -d build ] && rm -rf build
+ mkdir build
+ cd build
+ printf "\rConfiguring $1..."
+ run_$2 $1 "$3"
+ printf "\rBuilding $1... "
+ make -j$IFCOS_NUM_BUILD_PROCS >>$LOG_FILE 2>&1
+ printf "\rInstalling $1... "
+ make install >>$LOG_FILE 2>&1
+ printf "\rInstalled $1 \n"
+ else
+ printf "\rConfiguring $1..."
+ ./bootstrap.sh >>$LOG_FILE 2>&1
+ printf "\rBuilding $1... "
+ eval ./b2 $3 >>$LOG_FILE 2>&1
+ printf "\rInstalling $1... "
+ cp -R boost $DEPS_DIR/install/boost-$BOOST_VERSION/ >>$LOG_FILE 2>&1
+ printf "\rInstalled $1 \n"
+ fi
+}
+
+cecho $GREEN "Collecting dependencies:"
+
+# Set compiler flags for 32bit builds on 64bit system
+# TODO: This is untested
+
+if [ "$TARGET_ARCH" == "i686" ] && [ "$(uname -m)" == "x86_64" ]; then
+ADDITIONAL_ARGS="-m32 -arch i386"
+BOOST_ADDRESS_MODEL="architecture=x86 address-model=32"
+fi
+
+if [ "$(uname)" == "Darwin" ]; then
+ADDITIONAL_ARGS="-mmacosx-version-min=10.6 $ADDITIONAL_ARGS"
+fi
+
+# If the linker supports GC sections, set it up to reduce binary file size
+# -fPIC is required for the shared libraries to work
+
+if man ld 2> /dev/null | grep gc-sections &> /dev/null; then
+export CXXFLAGS_MINIMAL="$CXXFLAGS -fPIC $ADDITIONAL_ARGS"
+export CFLAGS_MINIMAL="$CFLAGS -fPIC $ADDITIONAL_ARGS"
+export CXXFLAGS="$CXXFLAGS -fPIC -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden $ADDITIONAL_ARGS"
+export CFLAGS="$CFLAGS -fPIC -fdata-sections -ffunction-sections -fvisibility=hidden $ADDITIONAL_ARGS"
+export LDFLAGS="$LDFLAGS -Wl,--gc-sections $ADDITIONAL_ARGS"
+else
+export CXXFLAGS_MINIMAL="$CXXFLAGS -fPIC $ADDITIONAL_ARGS"
+export CFLAGS_MINIMAL="$CFLAGS -fPIC $ADDITIONAL_ARGS"
+export CXXFLAGS="$CXXFLAGS -fPIC -fvisibility=hidden -fvisibility-inlines-hidden $ADDITIONAL_ARGS"
+export CFLAGS="$CFLAGS -fPIC -fvisibility=hidden -fvisibility-inlines-hidden $ADDITIONAL_ARGS"
+export LDFLAGS="$LDFLAGS $ADDITIONAL_ARGS"
+fi
+
+# Some dependencies need a more recent CMake version than most distros provide
+build_dependency cmake-$CMAKE_VERSION autoconf "" https://cmake.org/files/v$CMAKE_VERSION_2/ cmake-$CMAKE_VERSION.tar.gz download
+
+# Extract compiler flags from CMake to harmonize settings with other autoconf dependencies
+CMAKE_FLAG_EXTRACT_DIR=ifcopenshell_cmake_test_`cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 32`
+[ -e $CMAKE_FLAG_EXTRACT_DIR ] && rm -rf $CMAKE_FLAG_EXTRACT_DIR
+mkdir $CMAKE_FLAG_EXTRACT_DIR
+cd $CMAKE_FLAG_EXTRACT_DIR
+BUILD_CFG_UPPER=`echo $BUILD_CFG | awk '{print toupper($0)}'`
+for FL in C CXX; do
+ echo "
+ message(\"\${CMAKE_${FL}_FLAGS_${BUILD_CFG_UPPER}}\")
+ " > CMakeLists.txt
+ FL=${FL}FLAGS
+ FLM=${FL}FLAGS_MINIMAL
+ declare ${FL}FLAGS="`$DEPS_DIR/install/cmake-$CMAKE_VERSION/bin/cmake . 2>&1 >/dev/null` ${!FL}"
+ declare ${FL}FLAGS_MINIMAL="`$DEPS_DIR/install/cmake-$CMAKE_VERSION/bin/cmake . 2>&1 >/dev/null` ${!FLM}"
+done
+cd ..
+rm -rf $CMAKE_FLAG_EXTRACT_DIR
+
+build_dependency pcre-$PCRE_VERSION autoconf "--disable-shared" ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/ pcre-$PCRE_VERSION.tar.bz2 download
+
+# An issue exists with swig-1.3 and python >= 3.2
+# Therefore, build a recent copy from source
+build_dependency swig autoconf "--with-pcre-prefix=$DEPS_DIR/install/pcre-$PCRE_VERSION" https://github.com/swig/swig.git swig git_clone rel-3.0.8
+
+build_dependency oce-$OCE_VERSION cmake "-DOCE_DISABLE_TKSERVICE_FONT=ON -DOCE_TESTING=OFF -DOCE_BUILD_SHARED_LIB=OFF -DOCE_DISABLE_X11=ON -DOCE_VISUALISATION=OFF -DOCE_OCAF=OFF -DOCE_INSTALL_PREFIX=$DEPS_DIR/install/oce-$OCE_VERSION/" https://github.com/tpaviot/oce/archive/ OCE-$OCE_VERSION.tar.gz download
+build_dependency libxml2-$LIBXML_VERSION autoconf "--without-python --disable-shared --without-zlib --without-iconv --without-lzma" ftp://xmlsoft.org/libxml2/ libxml2-$LIBXML_VERSION.tar.gz download
+build_dependency OpenCOLLADA cmake "
+-DLIBXML2_INCLUDE_DIR=$DEPS_DIR/install/libxml2-$LIBXML_VERSION/include/libxml2
+-DLIBXML2_LIBRARIES=$DEPS_DIR/install/libxml2-$LIBXML_VERSION/lib/libxml2.a
+-DPCRE_INCLUDE_DIR=$DEPS_DIR/install/pcre-$PCRE_VERSION/include
+-DPCRE_PCREPOSIX_LIBRARY=$DEPS_DIR/install/pcre-$PCRE_VERSION/lib/libpcreposix.a
+-DPCRE_PCRE_LIBRARY=$DEPS_DIR/install/pcre-$PCRE_VERSION/lib/libpcre.a
+-DCMAKE_INSTALL_PREFIX=$DEPS_DIR/install/OpenCOLLADA/" https://github.com/KhronosGroup/OpenCOLLADA.git OpenCOLLADA git_clone $OPENCOLLADA_COMMIT
+
+# Python should not be built with -fvisibility=hidden, from experience that introduces segfaults
+
+OLD_CXX_FLAGS=$CXXFLAGS
+OLD_C_FLAGS=$CFLAGS
+export CXXFLAGS=$CXXFLAGS_MINIMAL
+export CFLAGS=$CFLAGS_MINIMAL
+
+# On OSX a dynamic python library is built or it would not be compatible
+# with the system python because of some threading initialization
+if [ "$(uname)" == "Darwin" ]; then
+PYTHON_CONFIGURE_ARGS="--disable-static --enable-shared"
+fi
+
+for PYTHON_VERSION in "${PYTHON_VERSIONS[@]}"; do
+ build_dependency python-$PYTHON_VERSION autoconf "$PYTHON_CONFIGURE_ARGS" http://www.python.org/ftp/python/$PYTHON_VERSION/ Python-$PYTHON_VERSION.tgz download
+done
+
+export CXXFLAGS=$OLD_CXX_FLAGS
+export CFLAGS=$OLD_C_FLAGS
+
+build_dependency boost-$BOOST_VERSION bjam "--stagedir=$DEPS_DIR/install/boost-$BOOST_VERSION --with-system --with-program_options --with-regex --with-thread --with-date_time link=static $BOOST_ADDRESS_MODEL cxxflags=\"$CXXFLAGS\" linkflags=\"$LDFLAGS\" stage" http://downloads.sourceforge.net/project/boost/boost/$BOOST_VERSION/ boost_$BOOST_VERSION_UNDERSCORE.tar.bz2 download
+
+build_dependency icu-$ICU_VERSION icu "--enable-static --disable-shared" http://download.icu-project.org/files/icu4c/$ICU_VERSION/ icu4c-${ICU_VERSION_UNDERSCORE}-src.tgz download
+
+cecho $GREEN "Building IfcOpenShell:"
+
+IFCOS_DIR=$DEPS_DIR/build/ifcopenshell
+[ -d $IFCOS_DIR ] && rm -rf $IFCOS_DIR
+mkdir -p $IFCOS_DIR
+cd $IFCOS_DIR
+
+mkdir -p executables
+cd executables
+
+printf "\rConfiguring executables..."
+
+run_cmake "" "
+-DBOOST_ROOT=$DEPS_DIR/install/boost-$BOOST_VERSION
+-DOCC_INCLUDE_DIR=$DEPS_DIR/install/oce-$OCE_VERSION/include/oce
+-DOCC_LIBRARY_DIR=$DEPS_DIR/install/oce-$OCE_VERSION/lib
+-DOPENCOLLADA_INCLUDE_DIR=$DEPS_DIR/install/OpenCOLLADA/include/opencollada
+-DOPENCOLLADA_LIBRARY_DIR=$DEPS_DIR/install/OpenCOLLADA/lib/opencollada
+-DICU_INCLUDE_DIR=$DEPS_DIR/install/icu-$ICU_VERSION/include
+-DICU_LIBRARY_DIR=$DEPS_DIR/install/icu-$ICU_VERSION/lib
+-DPCRE_LIBRARY_DIR=$DEPS_DIR/install/pcre-$PCRE_VERSION/lib
+-DBUILD_IFCPYTHON=OFF
+" $CMAKE_DIR
+
+printf "\rBuilding executables... "
+
+make -j$IFCOS_NUM_BUILD_PROCS >>$LOG_FILE 2>&1
+
+if [ "$(uname)" == "Darwin" ]; then
+ STRIP_OPTION=-x
+else
+ STRIP_OPTION=-s
+fi
+
+strip $STRIP_OPTION IfcConvert IfcGeomServer
+
+cd ..
+
+# On OSX the actual Python library is not linked against.
+ADDITIONAL_ARGS=
+if [ "$(uname)" == "Darwin" ]; then
+ADDITIONAL_ARGS="-Wl,-flat_namespace,-undefined,suppress"
+fi
+
+export CXXFLAGS="$CXXFLAGS_MINIMAL $ADDITIONAL_ARGS"
+export CFLAGS="$CFLAGS_MINIMAL $ADDITIONAL_ARGS"
+export LDFLAGS="$LDFLAGS $ADDITIONAL_ARGS"
+
+for PYTHON_VERSION in "${PYTHON_VERSIONS[@]}"; do
+
+ printf "\rConfiguring python $PYTHON_VERSION wrapper..."
+
+ mkdir -p python-$PYTHON_VERSION
+ cd python-$PYTHON_VERSION
+
+ PYTHON_LIBRARY=`ls $DEPS_DIR/install/python-$PYTHON_VERSION/lib/libpython*.*`
+ PYTHON_INCLUDE=`ls -d $DEPS_DIR/install/python-$PYTHON_VERSION/include/python*`
+ PYTHON_EXECUTABLE=$DEPS_DIR/install/python-$PYTHON_VERSION/bin/python
+ export PYTHON_LIBRARY_BASENAME=`basename $PYTHON_LIBRARY`
+
+ run_cmake "" "
+ -DBOOST_ROOT=$DEPS_DIR/install/boost-$BOOST_VERSION
+ -DOCC_INCLUDE_DIR=$DEPS_DIR/install/oce-$OCE_VERSION/include/oce
+ -DOCC_LIBRARY_DIR=$DEPS_DIR/install/oce-$OCE_VERSION/lib
+ -DOPENCOLLADA_INCLUDE_DIR=$DEPS_DIR/install/OpenCOLLADA/include/opencollada
+ -DOPENCOLLADA_LIBRARY_DIR=$DEPS_DIR/install/OpenCOLLADA/lib/opencollada
+ -DICU_INCLUDE_DIR=$DEPS_DIR/install/icu-$ICU_VERSION/include
+ -DICU_LIBRARY_DIR=$DEPS_DIR/install/icu-$ICU_VERSION/lib
+ -DPYTHON_LIBRARY=$PYTHON_LIBRARY
+ -DPYTHON_EXECUTABLE=$PYTHON_EXECUTABLE
+ -DPYTHON_INCLUDE_DIR=$PYTHON_INCLUDE
+ -DSWIG_EXECUTABLE=$DEPS_DIR/install/swig/bin/swig
+ " $CMAKE_DIR
+
+ printf "\rBuilding python $PYTHON_VERSION wrapper... "
+
+ make -j$IFCOS_NUM_BUILD_PROCS _ifcopenshell_wrapper >>$LOG_FILE 2>&1
+
+ if [ "$(uname)" != "Darwin" ]; then
+ # TODO: This symbol name depends on the Python version?
+ strip -s \
+ -K PyInit__ifcopenshell_wrapper \
+ ifcwrap/_ifcopenshell_wrapper.so
+ fi
+
+ cd ..
+
+done
+
+printf "\rBuilt IfcOpenShell... \n\n"
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index e572379ec1..8805d40e8c 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -1,5 +1,26 @@
+################################################################################
+# #
+# This file is part of IfcOpenShell. #
+# #
+# IfcOpenShell is free software: you can redistribute it and/or modify #
+# it under the terms of the Lesser GNU General Public License as published by #
+# the Free Software Foundation, either version 3.0 of the License, or #
+# (at your option) any later version. #
+# #
+# IfcOpenShell is distributed in the hope that it will be useful, #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
+# Lesser GNU General Public License for more details. #
+# #
+# You should have received a copy of the Lesser GNU General Public License #
+# along with this program. If not, see . #
+# #
+################################################################################
+
ADD_EXECUTABLE(IfcParseExamples IfcParseExamples.cpp)
-TARGET_LINK_LIBRARIES (IfcParseExamples IfcParse)
+TARGET_LINK_LIBRARIES(IfcParseExamples IfcParse)
+set_target_properties(IfcParseExamples PROPERTIES FOLDER Examples)
ADD_EXECUTABLE(IfcOpenHouse IfcOpenHouse.cpp)
-TARGET_LINK_LIBRARIES (IfcOpenHouse IfcParse IfcGeom TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO TKFillet TKOffset)
+TARGET_LINK_LIBRARIES(IfcOpenHouse IfcParse IfcGeom ${OPENCASCADE_LIBRARIES})
+set_target_properties(IfcOpenHouse PROPERTIES FOLDER Examples)
diff --git a/src/examples/IfcOpenHouse.cpp b/src/examples/IfcOpenHouse.cpp
index 00cfe1503d..c7414e76e7 100644
--- a/src/examples/IfcOpenHouse.cpp
+++ b/src/examples/IfcOpenHouse.cpp
@@ -41,6 +41,10 @@
#include "../ifcparse/IfcHierarchyHelper.h"
#include "../ifcgeom/IfcGeom.h"
+#if USE_VLD
+#include
+#endif
+
// Some convenience typedefs and definitions.
typedef std::string S;
typedef IfcParse::IfcGlobalId guid;
@@ -50,7 +54,7 @@ boost::none_t const null = boost::none;
// The creation of Nurbs-surface for the IfcSite mesh, to be implemented lateron
void createGroundShape(TopoDS_Shape& shape);
-int main(int argc, char** argv) {
+int main() {
// The IfcHierarchyHelper is a subclass of the regular IfcFile that provides several
// convenience functions for working with geometry in IFC files.
diff --git a/src/examples/IfcParseExamples.cpp b/src/examples/IfcParseExamples.cpp
index 342a6e8674..7ae158a67f 100644
--- a/src/examples/IfcParseExamples.cpp
+++ b/src/examples/IfcParseExamples.cpp
@@ -19,6 +19,10 @@
#include "../ifcparse/IfcFile.h"
+#if USE_VLD
+#include
+#endif
+
using namespace IfcSchema;
int main(int argc, char** argv) {
diff --git a/src/ifcconvert/ColladaSerializer.cpp b/src/ifcconvert/ColladaSerializer.cpp
index 2f9b54fbf1..c8272aba64 100644
--- a/src/ifcconvert/ColladaSerializer.cpp
+++ b/src/ifcconvert/ColladaSerializer.cpp
@@ -19,48 +19,65 @@
#ifdef WITH_OPENCOLLADA
-#include
-
#include "ColladaSerializer.h"
-std::string collada_id(const std::string& s) {
- std::string id;
- id.reserve(s.size());
- for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
- const std::string::value_type c = *it;
- if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_') || ( c == '-')) {
- id.push_back(c);
- }
- }
- return id;
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+static void collada_id(std::string &s)
+{
+ IfcUtil::sanitate_material_name(s);
+ IfcUtil::escape_xml(s);
}
-void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector& floats, const char* coords /* = "XYZ" */) {
+void ColladaSerializer::ColladaExporter::ColladaGeometries::addFloatSource(const std::string& mesh_id,
+ const std::string& suffix, const std::vector& floats, const char* coords /* = "XYZ" */)
+{
COLLADASW::FloatSource source(mSW);
source.setId(mesh_id + suffix);
source.setArrayId(mesh_id + suffix + COLLADASW::LibraryGeometries::ARRAY_ID_SUFFIX);
- source.setAccessorStride(strlen(coords));
- source.setAccessorCount(floats.size() / 3);
- for (unsigned int i = 0; i < source.getAccessorStride(); ++i) {
+ const size_t num_elems = strlen(coords);
+ source.setAccessorStride(static_cast(num_elems));
+ source.setAccessorCount(static_cast(floats.size() / num_elems));
+ for (size_t i = 0; i < num_elems; ++i) {
source.getParameterNameList().push_back(std::string(1, coords[i]));
}
source.prepareToAppendValues();
- for (std::vector::const_iterator it = floats.begin(); it != floats.end(); ++it) {
+ for (std::vector::const_iterator it = floats.begin(); it != floats.end(); ++it) {
source.appendValues(*it);
}
source.finish();
}
-
-void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::string mesh_id, const std::string& default_material_name, const std::vector& positions, const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector material_ids, const std::vector& materials) {
+
+void ColladaSerializer::ColladaExporter::ColladaGeometries::write(
+ const std::string &mesh_id, const std::string& default_material_name, const std::vector& positions,
+ const std::vector& normals, const std::vector& faces, const std::vector& edges,
+ const std::vector material_ids, const std::vector& materials,
+ const std::vector& uvs)
+{
openMesh(mesh_id);
// The normals vector can be empty for example when the WELD_VERTICES setting is used.
// IfcOpenShell does not provide them with multiple face normals collapsed into a single vertex.
const bool has_normals = !normals.empty();
+ const bool has_uvs = !uvs.empty();
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::POSITIONS_SOURCE_ID_SUFFIX, positions);
if (has_normals) {
addFloatSource(mesh_id, COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, normals);
+ if (has_uvs) {
+ addFloatSource(mesh_id, COLLADASW::LibraryGeometries::TEXCOORDS_SOURCE_ID_SUFFIX, uvs, "UV");
+ }
}
COLLADASW::VerticesElement vertices(mSW);
@@ -72,21 +89,36 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str
std::vector::const_iterator material_it = material_ids.begin();
int previous_material_id = -1;
for (std::vector::const_iterator it = faces.begin(); !faces.empty(); it += 3) {
- const int current_material_id = *(material_it++);
- const int num_triangles = std::distance(index_range_start, it) / 3;
+
+ int current_material_id = 0;
+ if (material_it != material_ids.end()) {
+ // In order for the last range of equal material ids to be output as well, this loop iterates
+ // one element past the end of the vector. This needs to be observed when incrementing.
+ current_material_id = *(material_it++);
+ }
+
+ const size_t num_triangles = std::distance(index_range_start, it) / 3;
if ((previous_material_id != current_material_id && num_triangles > 0) || (it == faces.end())) {
COLLADASW::Triangles triangles(mSW);
- triangles.setMaterial(materials[previous_material_id].name());
- triangles.setCount(num_triangles);
+ std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES)
+ ? materials[previous_material_id].original_name() : materials[previous_material_id].name());
+ collada_id(material_name);
+ triangles.setMaterial(material_name);
+ triangles.setCount((unsigned long)num_triangles);
int offset = 0;
- triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++ ) );
+ triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX,"#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset++));
if (has_normals) {
- triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++ ) );
+ triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::NORMAL,"#" + mesh_id + COLLADASW::LibraryGeometries::NORMALS_SOURCE_ID_SUFFIX, offset++));
}
+ if (has_uvs) {
+ triangles.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::TEXCOORD,"#" + mesh_id + COLLADASW::LibraryGeometries::TEXCOORDS_SOURCE_ID_SUFFIX, offset++));
+ }
triangles.prepareToAppendValues();
for (std::vector::const_iterator jt = index_range_start; jt != it; ++jt) {
const int idx = *jt;
- if (has_normals) {
+ if (has_normals && has_uvs) {
+ triangles.appendValues(idx, idx, idx);
+ } else if(has_normals) {
triangles.appendValues(idx, idx);
} else {
triangles.appendValues(idx);
@@ -125,10 +157,13 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str
for (linelist_t::const_iterator it = linelist.begin(); it != linelist.end(); ++it) {
COLLADASW::Lines lines(mSW);
- lines.setMaterial(materials[it->first].name());
- lines.setCount(it->second.size());
+ std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES)
+ ? materials[it->first].original_name() : materials[it->first].name());
+ collada_id(material_name);
+ lines.setMaterial(material_name);
+ lines.setCount((unsigned long)it->second.size());
int offset = 0;
- lines.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX, "#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, 0));
+ lines.getInputList().push_back(COLLADASW::Input(COLLADASW::InputSemantic::VERTEX, "#" + mesh_id + COLLADASW::LibraryGeometries::VERTICES_ID_SUFFIX, offset));
lines.prepareToAppendValues();
lines.appendValues(it->second);
lines.finish();
@@ -141,8 +176,11 @@ void ColladaSerializer::ColladaExporter::ColladaGeometries::write(const std::str
void ColladaSerializer::ColladaExporter::ColladaGeometries::close() {
closeLibrary();
}
-
-void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector& material_ids, const std::vector& matrix) {
+
+void ColladaSerializer::ColladaExporter::ColladaScene::add(
+ const std::string& node_id, const std::string& node_name, const std::string& geom_name,
+ const std::vector& material_ids, const std::vector& matrix)
+{
if (!scene_opened) {
openVisualScene(scene_id);
scene_opened = true;
@@ -156,18 +194,24 @@ void ColladaSerializer::ColladaExporter::ColladaScene::add(const std::string& no
// The matrix attribute of an entity is basically a 4x3 representation of its ObjectPlacement.
// Note that this placement is absolute, ie it is multiplied with all parent placements.
double matrix_array[4][4] = {
- {matrix[0], matrix[3], matrix[6], matrix[ 9]},
- {matrix[1], matrix[4], matrix[7], matrix[10]},
- {matrix[2], matrix[5], matrix[8], matrix[11]},
- { 0, 0, 0, 1}
+ { (double)matrix[0], (double)matrix[3], (double)matrix[6], (double)matrix[ 9] },
+ { (double)matrix[1], (double)matrix[4], (double)matrix[7], (double)matrix[10] },
+ { (double)matrix[2], (double)matrix[5], (double)matrix[8], (double)matrix[11] },
+ { 0, 0, 0, 1 }
};
+ matrix_array[0][3] += serializer->settings().offset[0];
+ matrix_array[1][3] += serializer->settings().offset[1];
+ matrix_array[2][3] += serializer->settings().offset[2];
+
node.start();
node.addMatrix(matrix_array);
COLLADASW::InstanceGeometry instanceGeometry(mSW);
instanceGeometry.setUrl ("#" + geom_name);
- for (std::vector::const_iterator it = material_ids.begin(); it != material_ids.end(); ++it) {
- COLLADASW::InstanceMaterial material (*it, "#" + *it);
+ foreach(std::string material_name, material_ids) {
+ /// @todo This is done 6 times in this file, try to perform this once and be done with the material naming for the export.
+ collada_id(material_name);
+ COLLADASW::InstanceMaterial material (material_name, "#" + material_name);
instanceGeometry.getBindMaterial().getInstanceMaterialList().push_back(material);
}
instanceGeometry.add();
@@ -183,9 +227,13 @@ void ColladaSerializer::ColladaExporter::ColladaScene::write() {
scene.add();
}
}
-
-void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material) {
- openEffect(collada_id(material.name()) + "-fx");
+
+void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write(const IfcGeom::Material& material)
+{
+ std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES)
+ ? material.original_name() : material.name());
+ collada_id(material_name);
+ openEffect(material_name + "-fx");
COLLADASW::EffectProfile effect(mSW);
effect.setShaderType(COLLADASW::EffectProfile::LAMBERT);
if (material.hasDiffuse()) {
@@ -214,7 +262,7 @@ void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::write
void ColladaSerializer::ColladaExporter::ColladaMaterials::ColladaEffects::close() {
closeLibrary();
}
-
+
void ColladaSerializer::ColladaExporter::ColladaMaterials::add(const IfcGeom::Material& material) {
if (!contains(material)) {
effects.write(material);
@@ -228,15 +276,19 @@ bool ColladaSerializer::ColladaExporter::ColladaMaterials::contains(const IfcGeo
void ColladaSerializer::ColladaExporter::ColladaMaterials::write() {
effects.close();
- for (std::vector::const_iterator it = materials.begin(); it != materials.end(); ++it) {
- const std::string& material_name = collada_id((*it).name());
+ foreach(const IfcGeom::Material& material, materials) {
+ std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES)
+ ? material.original_name() : material.name());
+ std::string material_name_unescaped = material_name; // workaround double-escaping that would occur in addInstanceEffect()
+ IfcUtil::sanitate_material_name(material_name_unescaped);
+ collada_id(material_name);
openMaterial(material_name);
- addInstanceEffect("#" + material_name + "-fx");
+ addInstanceEffect("#" + material_name_unescaped + "-fx");
closeMaterial();
}
closeLibrary();
}
-
+
void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_name, float unit_magnitude) {
stream.startDocument();
@@ -247,35 +299,51 @@ void ColladaSerializer::ColladaExporter::startDocument(const std::string& unit_n
asset.add();
}
-void ColladaSerializer::ColladaExporter::write(const std::string& unique_id, const std::string& type, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector& material_ids, const std::vector& _materials) {
+void ColladaSerializer::ColladaExporter::write(const IfcGeom::TriangulationElement* o)
+{
+ const IfcGeom::Representation::Triangulation& mesh = o->geometry();
+ const std::string name = serializer->settings().get(IfcGeom::IteratorSettings::USE_ELEMENT_GUIDS) ?
+ o->guid() : (serializer->settings().get(IfcGeom::IteratorSettings::USE_ELEMENT_NAMES) ? o->name() : o->unique_id());
+ const std::string representation_id = "representation-" + boost::lexical_cast(o->geometry().id());
+
std::vector material_references;
- for (std::vector::const_iterator it = _materials.begin(); it != _materials.end(); ++it) {
- const IfcGeom::Material& material = *it;
+ foreach(const IfcGeom::Material& material, mesh.materials()) {
if (!materials.contains(material)) {
materials.add(material);
}
- material_references.push_back(collada_id(material.name()));
+ std::string material_name = (serializer->settings().get(IfcGeom::IteratorSettings::USE_MATERIAL_NAMES)
+ ? material.original_name() : material.name());
+ collada_id(material_name);
+ material_references.push_back(material_name);
}
- deferreds.push_back(DeferredObject(unique_id, type, matrix, vertices, normals, faces, edges, material_ids, _materials, material_references));
+
+ deferreds.push_back(
+ DeferredObject(name, representation_id, o->type(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(),
+ mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials(), material_references, mesh.uvs())
+ );
}
void ColladaSerializer::ColladaExporter::endDocument() {
// In fact due the XML based nature of Collada and its dependency on library nodes,
// only at this point all objects are written to the stream.
materials.write();
+ std::set geometries_written;
for (std::vector::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
- const std::string object_name = it->unique_id + "-representation";
- geometries.write(object_name, it->type, it->vertices, it->normals, it->faces, it->edges, it->material_ids, it->materials);
+ if (geometries_written.find(it->representation_id) != geometries_written.end()) {
+ continue;
+ }
+ geometries_written.insert(it->representation_id);
+ geometries.write(it->representation_id, it->type, it->vertices, it->normals, it->faces, it->edges, it->material_ids, it->materials, it->uvs);
}
geometries.close();
for (std::vector::const_iterator it = deferreds.begin(); it != deferreds.end(); ++it) {
const std::string object_name = it->unique_id;
- scene.add(object_name, object_name, object_name + "-representation", it->material_references, it->matrix);
+ scene.add(object_name, object_name, it->representation_id, it->material_references, it->matrix);
}
scene.write();
stream.endDocument();
}
-
+
bool ColladaSerializer::ready() {
return true;
}
@@ -284,9 +352,8 @@ void ColladaSerializer::writeHeader() {
exporter.startDocument(unit_name, unit_magnitude);
}
-void ColladaSerializer::write(const IfcGeom::TriangulationElement* o) {
- const IfcGeom::Representation::Triangulation& mesh = o->geometry();
- exporter.write(o->unique_id(), o->type(), o->transformation().matrix().data(), mesh.verts(), mesh.normals(), mesh.faces(), mesh.edges(), mesh.material_ids(), mesh.materials());
+void ColladaSerializer::write(const IfcGeom::TriangulationElement* o) {
+ exporter.write(o);
}
void ColladaSerializer::finalize() {
diff --git a/src/ifcconvert/ColladaSerializer.h b/src/ifcconvert/ColladaSerializer.h
index 63421d5f85..11f06381a1 100644
--- a/src/ifcconvert/ColladaSerializer.h
+++ b/src/ifcconvert/ColladaSerializer.h
@@ -22,18 +22,18 @@
#ifndef COLLADASERIALIZER_H
#define COLLADASERIALIZER_H
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4201 4512)
+#endif
#include
-#include
#include
-#include
-#include
-#include
-#include
#include
#include
#include
-#include
-#include
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
#include "../ifcgeom/IfcGeomIterator.h"
@@ -41,72 +41,98 @@
class ColladaSerializer : public GeometrySerializer
{
+ // TODO The vast amount of implement details of ColladaSerializer could be hidden to the cpp file.
private:
class ColladaExporter
{
private:
class ColladaGeometries : public COLLADASW::LibraryGeometries
{
+ ColladaGeometries(const ColladaGeometries&); //N/A
+ ColladaGeometries& operator =(const ColladaGeometries&); //N/A
public:
- explicit ColladaGeometries(COLLADASW::StreamWriter& stream)
+ explicit ColladaGeometries(COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryGeometries(&stream)
+ , serializer(_serializer)
{}
- void addFloatSource(const std::string& mesh_id, const std::string& suffix, const std::vector& floats, const char* coords = "XYZ");
- void write(const std::string mesh_id, const std::string& default_material_name, const std::vector& positions, const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector material_ids, const std::vector& materials);
+ void addFloatSource(const std::string& mesh_id, const std::string& suffix,
+ const std::vector& floats, const char* coords = "XYZ");
+ void write(const std::string &mesh_id, const std::string& default_material_name,
+ const std::vector& positions, const std::vector& normals,
+ const std::vector& faces, const std::vector& edges,
+ const std::vector material_ids, const std::vector& materials,
+ const std::vector& uvs);
void close();
+ ColladaSerializer *serializer;
};
class ColladaScene : public COLLADASW::LibraryVisualScenes
{
private:
+ ColladaScene(const ColladaScene&); //N/A
+ ColladaScene& operator =(const ColladaScene&); //N/A
+
const std::string scene_id;
bool scene_opened;
public:
- ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream)
+ ColladaScene(const std::string& scene_id, COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryVisualScenes(&stream)
, scene_id(scene_id)
- , scene_opened(false)
+ , scene_opened(false)
+ , serializer(_serializer)
{}
- void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name, const std::vector& material_ids, const std::vector& matrix);
+ void add(const std::string& node_id, const std::string& node_name, const std::string& geom_name,
+ const std::vector& material_ids, const std::vector& matrix);
void write();
+ ColladaSerializer *serializer;
};
class ColladaMaterials : public COLLADASW::LibraryMaterials
{
+ ColladaMaterials(const ColladaMaterials&); //N/A
+ ColladaMaterials& operator =(const ColladaMaterials&); //N/A
private:
class ColladaEffects : public COLLADASW::LibraryEffects
{
+ ColladaEffects(const ColladaEffects&); //N/A
+ ColladaEffects& operator =(const ColladaEffects&); //N/A
public:
explicit ColladaEffects(COLLADASW::StreamWriter& stream)
: COLLADASW::LibraryEffects(&stream)
{}
void write(const IfcGeom::Material& material);
void close();
+ ColladaSerializer *serializer;
};
std::vector materials;
- ColladaEffects effects;
public:
- explicit ColladaMaterials(COLLADASW::StreamWriter& stream)
+ explicit ColladaMaterials(COLLADASW::StreamWriter& stream, ColladaSerializer *_serializer)
: COLLADASW::LibraryMaterials(&stream)
, effects(stream)
+ , serializer(_serializer)
{}
void add(const IfcGeom::Material& material);
bool contains(const IfcGeom::Material& material);
void write();
+ ColladaSerializer *serializer;
+ ColladaEffects effects;
};
class DeferredObject {
public:
- std::string unique_id, type;
- std::vector matrix;
- std::vector vertices;
- std::vector normals;
+ std::string unique_id, representation_id, type;
+ std::vector matrix;
+ std::vector vertices;
+ std::vector normals;
std::vector faces;
std::vector edges;
std::vector material_ids;
std::vector materials;
std::vector material_references;
- DeferredObject(const std::string& unique_id, const std::string& type, const std::vector& matrix, const std::vector& vertices,
- const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector& material_ids,
- const std::vector& materials, const std::vector& material_references)
+ std::vector uvs;
+ DeferredObject(const std::string& unique_id, const std::string& representation_id, const std::string& type, const std::vector& matrix,
+ const std::vector& vertices, const std::vector& normals, const std::vector& faces,
+ const std::vector& edges, const std::vector& material_ids, const std::vector& materials,
+ const std::vector& material_references, const std::vector& uvs)
: unique_id(unique_id)
+ , representation_id(representation_id)
, type(type)
, matrix(matrix)
, vertices(vertices)
@@ -116,39 +142,48 @@ private:
, material_ids(material_ids)
, materials(materials)
, material_references(material_references)
+ , uvs(uvs)
{}
};
COLLADABU::NativeString filename;
COLLADASW::StreamWriter stream;
- ColladaGeometries geometries;
ColladaScene scene;
- ColladaMaterials materials;
public:
- ColladaExporter(const std::string& scene_name, const std::string& fn)
- : filename(fn.c_str())
- , stream(filename)
- , geometries(stream)
- , scene(scene_name, stream)
- , materials(stream)
- {}
+ ColladaExporter(const std::string& scene_name, const std::string& fn, ColladaSerializer *_serializer)
+ : filename(fn)
+ , stream(filename, sizeof(real_t) == sizeof(double)) // utilise Collada stream's double precision feature
+ , geometries(stream, _serializer)
+ , scene(scene_name, stream, _serializer)
+ , materials(stream, _serializer)
+ , serializer(_serializer)
+ {
+ }
+ ColladaMaterials materials;
+ ColladaSerializer *serializer;
+ ColladaGeometries geometries;
std::vector deferreds;
virtual ~ColladaExporter() {}
void startDocument(const std::string& unit_name, float unit_magnitude);
- void write(const std::string& unique_id, const std::string& type, const std::vector& matrix, const std::vector& vertices, const std::vector& normals, const std::vector& faces, const std::vector& edges, const std::vector& material_ids, const std::vector& materials);
+ void write(const IfcGeom::TriangulationElement* o);
void endDocument();
};
ColladaExporter exporter;
std::string unit_name;
float unit_magnitude;
public:
- ColladaSerializer(const std::string& dae_filename)
- : GeometrySerializer()
- , exporter("IfcOpenShell", dae_filename)
- {}
+ ColladaSerializer(const std::string& dae_filename, const IfcGeom::IteratorSettings &settings)
+ : GeometrySerializer(settings)
+ , exporter("IfcOpenShell", dae_filename, this)
+ {
+ exporter.serializer = this;
+ exporter.materials.serializer = this;
+ exporter.materials.effects.serializer = this;
+ exporter.geometries.serializer = this;
+ }
bool ready();
void writeHeader();
- void write(const IfcGeom::TriangulationElement* o);
- void write(const IfcGeom::BRepElement* o) {}
+ void write(const IfcGeom::TriangulationElement* o);
+ void write(const IfcGeom::BRepElement* /*o*/) {}
void finalize();
bool isTesselated() const { return true; }
void setUnitNameAndMagnitude(const std::string& name, float magnitude) {
diff --git a/src/ifcconvert/GeometrySerializer.h b/src/ifcconvert/GeometrySerializer.h
index 0a62defa18..c2ee0f6416 100644
--- a/src/ifcconvert/GeometrySerializer.h
+++ b/src/ifcconvert/GeometrySerializer.h
@@ -20,17 +20,30 @@
#ifndef GEOMETRYSERIALIZER_H
#define GEOMETRYSERIALIZER_H
+#ifdef IFCCONVERT_DOUBLE_PRECISION
+typedef double real_t;
+#else
+typedef float real_t;
+#endif
+
#include "../ifcconvert/Serializer.h"
#include "../ifcgeom/IfcGeomIterator.h"
class GeometrySerializer : public Serializer {
public:
+ GeometrySerializer(const IfcGeom::IteratorSettings &settings) : settings_(settings) {}
virtual ~GeometrySerializer() {}
virtual bool isTesselated() const = 0;
- virtual void write(const IfcGeom::TriangulationElement* o) = 0;
- virtual void write(const IfcGeom::BRepElement* o) = 0;
+ virtual void write(const IfcGeom::TriangulationElement* o) = 0;
+ virtual void write(const IfcGeom::BRepElement* o) = 0;
virtual void setUnitNameAndMagnitude(const std::string& name, float magnitude) = 0;
+
+ const IfcGeom::IteratorSettings& settings() const { return settings_; }
+ IfcGeom::IteratorSettings& settings() { return settings_; }
+
+protected:
+ IfcGeom::IteratorSettings settings_;
};
-#endif
\ No newline at end of file
+#endif
diff --git a/src/ifcconvert/IfcConvert.cpp b/src/ifcconvert/IfcConvert.cpp
index 0f9cb743c7..f81c3a234d 100644
--- a/src/ifcconvert/IfcConvert.cpp
+++ b/src/ifcconvert/IfcConvert.cpp
@@ -26,16 +26,6 @@
* *
********************************************************************************/
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "../ifcgeom/IfcGeomIterator.h"
-
#include "../ifcconvert/ColladaSerializer.h"
#include "../ifcconvert/IgesSerializer.h"
#include "../ifcconvert/StepSerializer.h"
@@ -43,28 +33,58 @@
#include "../ifcconvert/XmlSerializer.h"
#include "../ifcconvert/SvgSerializer.h"
-static std::string DEFAULT_EXTENSION = "obj";
+#include "../ifcgeom/IfcGeomIterator.h"
-void printVersion() {
- std::cerr << "IfcOpenShell IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#if USE_VLD
+#include
+#endif
+
+const std::string DEFAULT_EXTENSION = "obj";
+const std::string TEMP_FILE_EXTENSION = ".tmp";
+
+void print_version()
+{
+ /// @todo Why cerr used for info prints? Change to cout.
+ std::cerr << "IfcOpenShell " << IfcSchema::Identifier << " IfcConvert " << IFCOPENSHELL_VERSION << std::endl;
}
-void printUsage(const boost::program_options::options_description& generic_options, const boost::program_options::options_description& geom_options) {
- printVersion();
- std::cerr << "Usage: IfcConvert [options] [