pax_global_header00006660000000000000000000000064125606620550014521gustar00rootroot0000000000000052 comment=144f3048830896a89f03bce9143aea9131bb3431 libcitygml-2.0/000077500000000000000000000000001256066205500135215ustar00rootroot00000000000000libcitygml-2.0/.gitignore000066400000000000000000000003031256066205500155050ustar00rootroot00000000000000# Compiled Object files *.slo *.lo *.o # Compiled Dynamic libraries *.so *.dylib # Compiled Static libraries *.lai *.la *.a build build_debug CMakeLists.txt.user* install build/ buildRelease/ libcitygml-2.0/.travis.yml000066400000000000000000000010301256066205500156240ustar00rootroot00000000000000language: cpp compiler: - gcc - clang before_install: - echo $LANG - echo $LC_ALL - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get update -qq - sudo apt-get update --fix-missing - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get install -y libxerces-c-dev libxerces-c3.1 libgdal1h libgdal-dev cmake; fi - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi script: mkdir build && cd build && cmake ../ && make libcitygml-2.0/CMakeLists.txt000066400000000000000000000253411256066205500162660ustar00rootroot00000000000000CMAKE_MINIMUM_REQUIRED(VERSION 2.8.2 FATAL_ERROR) PROJECT ( libcitygml ) set(META_VERSION_MAJOR "2") set(META_VERSION_MINOR "0") set(META_VERSION_PATCH "0") set(META_VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}") SET( CMAKE_MODULE_PATH "${libcitygml_SOURCE_DIR}/CMakeModules/;${CMAKE_MODULE_PATH}" ) IF(WIN32) IF(MSVC) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") # More MSVC specific compilation flags ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) ENDIF(MSVC) # Both Cygwin and Msys need -DNOMINMAX ??? IF(UNIX) ADD_DEFINITIONS(-DNOMINMAX) ENDIF(UNIX) ######################################################################################################## # the foolowing options are MSVC specific, # the first OSG_MSVC_VERSIONED_DLL activate a custom build-time layout that should allow to run examples and application # fron bin folder without requiring installation step. # it also prepend "osg${OPENSCENEGRAPH_SOVERSION}-" to only .dll files, leaving .lib files untouched in lib # it also use a hack to get rid of Debug and Release folder in MSVC projects # all the .dll and .pdb are in bin and all the .lib and .exp are in lib # # the second option disable incremental linking in debug build , that is enabled by default by CMake ########################################################################################################## IF(MSVC) # IF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4 AND ${CMAKE_PATCH_VERSION} LESS 7) # MESSAGE("Warning: disabling versioned options 2.4.6 exibits inconsintencies in .pdb naming, at least under MSVC, suggested upgrading at least to 2.4.7") # SET(OSG_MSVC_VERSIONED_DLL OFF) # SET(OSG_MSVC_DEBUG_INCREMENTAL_LINK ON) # ELSE(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4 AND ${CMAKE_PATCH_VERSION} LESS 7) OPTION(LIBCITYGML_MSVC_VERSIONED_DLL "Set to ON to build libcitygml with versioned dll names" ON) MARK_AS_ADVANCED(LIBCITYGML_MSVC_VERSIONED_DLL) OPTION(LIBCITYGML_MSVC_DEBUG_INCREMENTAL_LINK "Set to OFF to build libcitygml without incremental linking in debug (release is off by default)" ON) MARK_AS_ADVANCED(LIBCITYGML_MSVC_DEBUG_INCREMENTAL_LINK) IF(NOT LIBCITYGML_MSVC_DEBUG_INCREMENTAL_LINK) SET(CMAKE_MODULE_LINKER_FLAGS_DEBUG "/debug /INCREMENTAL:NO") SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/debug /INCREMENTAL:NO") SET(CMAKE_EXE_LINKER_FLAGS_DEBUG "/debug /INCREMENTAL:NO") ENDIF(NOT LIBCITYGML_MSVC_DEBUG_INCREMENTAL_LINK) # ENDIF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4 AND ${CMAKE_PATCH_VERSION} LESS 7) ENDIF(MSVC) ENDIF(WIN32) if(UNIX) if(APPLE) MESSAGE(STATUS "APPLE") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC") else(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC") MESSAGE(STATUS "Setting UNIX compile flags: ${CMAKE_CXX_FLAGS}") endif(APPLE) endif(UNIX) IF(MSVC_IDE) # From CMake 2.8.2, new way to manage output generation dirs ! # SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES PREFIX "../") SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin) SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin) SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/lib) SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/lib) SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin) SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin) ENDIF(MSVC_IDE) SET(CMAKE_DEBUG_POSTFIX "d") # Dynamic vs Static Linking OPTION(LIBCITYGML_DYNAMIC "Set to ON to build libcitygml for dynamic linking. Use OFF for static." ON) IF (LIBCITYGML_DYNAMIC) SET(LIBCITYGML_USER_DEFINED_DYNAMIC_OR_STATIC "SHARED") ELSE (LIBCITYGML_DYNAMIC) SET(LIBCITYGML_USER_DEFINED_DYNAMIC_OR_STATIC "STATIC") ENDIF(LIBCITYGML_DYNAMIC) SET(OUTPUT_BINDIR ${PROJECT_BINARY_DIR}/bin) MAKE_DIRECTORY(${OUTPUT_BINDIR}) SET(EXECUTABLE_OUTPUT_PATH ${OUTPUT_BINDIR}) SET(OUTPUT_LIBDIR ${PROJECT_BINARY_DIR}/lib) MAKE_DIRECTORY(${OUTPUT_LIBDIR}) SET(LIBRARY_OUTPUT_PATH ${OUTPUT_LIBDIR}) if(NOT DEFINED BIN_INSTALL_DIR) set(BIN_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin") endif(NOT DEFINED BIN_INSTALL_DIR) if(NOT DEFINED LIB_INSTALL_DIR) set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib") endif(NOT DEFINED LIB_INSTALL_DIR) if(NOT DEFINED DATA_INSTALL_DIR) set(DATA_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share") endif(NOT DEFINED DATA_INSTALL_DIR) if(NOT DEFINED INCLUDE_INSTALL_DIR) set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include/citygml") endif(NOT DEFINED INCLUDE_INSTALL_DIR) if(NOT DEFINED MAN_INSTALL_DIR) set(MAN_INSTALL_DIR "${DATA_INSTALL_DIR}/man") endif(NOT DEFINED MAN_INSTALL_DIR) if(NOT DEFINED RESOURCE_INSTALL_DIR) set(RESOURCE_INSTALL_DIR "${DATA_INSTALL_DIR}/libcitygml${META_VERSION_MAJOR}/resource/") endif(NOT DEFINED RESOURCE_INSTALL_DIR) if(NOT DEFINED LOCALE_INSTALL_DIR) set(LOCALE_INSTALL_DIR "${DATA_INSTALL_DIR}/locale/") endif(NOT DEFINED LOCALE_INSTALL_DIR) # IF( DEBUG_BUILD ) # SET( CMAKE_BUILD_TYPE "Debug" ) # ELSE( DEBUG_BUILD ) # SET( CMAKE_BUILD_TYPE "Release" ) # ENDIF( DEBUG_BUILD ) OPTION(LIBCITYGML_STATIC_CRT "Set to ON to link libcitygml with the multithread CRT static library (instead of DLL)." ON) # gdal library OPTION(LIBCITYGML_USE_GDAL "Set to ON to build libcitygml with GDAL library so that it supports coordinates transformations." ON) FIND_PACKAGE( Xerces REQUIRED ) IF( LIBCITYGML_USE_GDAL ) FIND_PACKAGE( GDAL REQUIRED ) ADD_DEFINITIONS( -DUSE_GDAL ) ELSE( LIBCITYGML_USE_GDAL ) SET( GDAL_INCLUDE_DIR "" ) SET( GDAL_LIBRARY "" ) ENDIF( LIBCITYGML_USE_GDAL ) FIND_PACKAGE( OpenGL REQUIRED ) #FIND_PACKAGE( GLU REQUIRED ) # deprecated, GLU is now found with FindOpenGL IF( COMMAND cmake_policy ) cmake_policy( SET CMP0003 NEW ) ENDIF( COMMAND cmake_policy ) IF( MSVC AND LIBCITYGML_STATIC_CRT ) #We statically link to reduce dependancies FOREACH( flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO ) IF( ${flag_var} MATCHES "/MD" ) string( REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}" ) ENDIF( ${flag_var} MATCHES "/MD" ) IF( ${flag_var} MATCHES "/MDd" ) string( REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}" ) ENDIF( ${flag_var} MATCHES "/MDd" ) ENDFOREACH( flag_var ) ENDIF( MSVC AND LIBCITYGML_STATIC_CRT ) # core ADD_SUBDIRECTORY( sources ) # osg plugin OPTION(LIBCITYGML_OSGPLUGIN "Set to ON to build libcitygml osgplugin programs." OFF) IF (LIBCITYGML_OSGPLUGIN) ADD_SUBDIRECTORY( osgplugin ) ENDIF(LIBCITYGML_OSGPLUGIN) # test OPTION(LIBCITYGML_TESTS "Set to ON to build libcitygml tests programs." ON) IF (LIBCITYGML_TESTS) ADD_SUBDIRECTORY( test ) ENDIF(LIBCITYGML_TESTS) #----------------------------------------------------------------------------- ### uninstall target #----------------------------------------------------------------------------- CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") # Create debian package option(BUILD_DEBIAN_PACKAGE "Creates a debian package" ON) if(BUILD_DEBIAN_PACKAGE) # set project description for packaging set(META_PROJECT_NAME "libcitygml") set(META_PROJECT_SUMMARY "Open source C++ library for parsing CityGML files") set(META_PROJECT_DESCRIPTION "libcitygml is a small and easy to use open source C++ library for parsing CityGML files in such a way that data can be easily exploited by 3D rendering applications (geometry data are tesselated and optimized for rendering during parsing). For instance, it can be used to develop readers of CityGML files in many 3D based applications (OpenGL, OpenSceneGraph, ...) Most metadata are not lost, they are available through a per-node hashmap. CityGML (City Geography Markup Language) is an XML-based schema for the modelling and exchange of georeferenced 3D city and landscape models that is quickly being adopted on an international level.") set(META_AUTHOR_ORGANIZATION "3D Content Logistics") set(META_AUTHOR_DOMAIN "https://github.com/jklimke/libcitygml.git") set(META_AUTHOR_MAINTAINER "Marcel Pursche ") # Package information string(TOLOWER ${META_PROJECT_NAME} package_name) # Package name set(CPACK_PACKAGE_NAME "${META_PROJECT_NAME}") set(CPACK_PACKAGE_VENDOR "${META_AUTHOR_ORGANIZATION}") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${META_PROJECT_SUMMARY}") set(CPACK_PACKAGE_DESCRIPTION "${META_PROJECT_DESCRIPTION}") set(CPACK_PACKAGE_VERSION "${META_VERSION}") set(CPACK_PACKAGE_VERSION_MAJOR "${META_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${META_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${META_VERSION_PATCH}") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") set(CPACK_PACKAGE_RELOCATABLE OFF) # Debian package information set(CPACK_DEBIAN_PACKAGE_NAME "${package_name}") set(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${META_AUTHOR_MAINTAINER}") set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") set(CPACK_DEBIAN_PACKAGE_SECTION "Development") set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libgdal1h (>= 1.10.1), libxerces-c3.1 (>= 3.1.1-5)") set(CPACK_DEBIAN_PACKAGE_CONFLICTS "libcitygml0, libcitygml0-dev") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${META_AUTHOR_DOMAIN}") set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/debian_scripts/postinst;") set(CPACK_GENERATOR "DEB") include(CPack) endif() libcitygml-2.0/CMakeModules/000077500000000000000000000000001256066205500160325ustar00rootroot00000000000000libcitygml-2.0/CMakeModules/FindCityGML.cmake000066400000000000000000000056721256066205500211170ustar00rootroot00000000000000# Locate libcitygml # This module defines # CITYGML_LIBRARY # CITYGML_LIBRARY_DEBUG # CITYGML_LIBRARIES, choses the correct debug or optimized library for linking, add this as Target Link library in your project # CITYGML_FOUND, if false, do not try to link to CITYGML # CITYGML_INCLUDE_DIR, where to find the headers # # $CITYGML_DIR is an environment variable that would # correspond to the ./configure --prefix=$CITYGML_DIR OPTION(CITYGML_DYNAMIC "Set to ON if libcitygml was built using dynamic linking. Use OFF for static." OFF) OPTION(CITYGML_USE_XERCESC "Set to ON to build libcitygml with Xerces-c library." ON) OPTION(CITYGML_USE_LIBXML2 "Set to ON to build libcitygml with LibXml2 library." OFF) IF( CITYGML_DYNAMIC ) ADD_DEFINITIONS( -DLIBCITYGML_DYNAMIC ) ENDIF( CITYGML_DYNAMIC ) IF ( CITYGML_USE_XERCESC AND CITYGML_USE_LIBXML2 ) MESSAGE("Error: You cannot build the library with Xerces-c AND LibXml2! Xerces library will be used by default.") SET( CITYGML_USE_LIBXML2 OFF CACHE BOOL "Set to ON to build libcitygml with LibXml2 library." FORCE) ENDIF( CITYGML_USE_XERCESC AND CITYGML_USE_LIBXML2 ) IF( CITYGML_USE_XERCESC ) FIND_PACKAGE( Xerces REQUIRED ) ADD_DEFINITIONS( -DUSE_XERCESC ) SET( LIBXML2_INCLUDE_DIR "" ) # SET( LIBXML2_LIBRARIES "" ) SET( LIBXML2_LIBRARY "" ) SET( LIBXML2_LIBRARY_DEBUG "" ) ENDIF( CITYGML_USE_XERCESC ) IF( CITYGML_USE_LIBXML2 ) FIND_PACKAGE( LibXml2 REQUIRED ) ADD_DEFINITIONS( -DUSE_LIBXML2 ) ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS} ) SET( XERCESC_INCLUDE "" ) SET( XERCESC_LIBRARY "" ) SET( XERCESC_LIBRARY_DEBUG "" ) ENDIF( CITYGML_USE_LIBXML2 ) FIND_PATH( CITYGML_INCLUDE_DIR citygml/citygml.h ./include ../include $ENV{CITYGML_DIR}/include ~/Library/Frameworks /Library/Frameworks /usr/local/include /usr/include /sw/include # Fink /opt/local/include # DarwinPorts /opt/csw/include # Blastwave /opt/include /usr/freeware/include ) FIND_LIBRARY( CITYGML_LIBRARY NAMES citygml PATHS ./lib ../lib $ENV{CITYGML_DIR}/lib $ENV{CITYGML_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_LIBRARY( CITYGML_LIBRARY_DEBUG NAMES citygmld PATHS ./lib ../lib $ENV{CITYGML_DIR}/lib $ENV{CITYGML_DIR} ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET( CITYGML_FOUND FALSE ) IF(CITYGML_LIBRARY AND CITYGML_INCLUDE_DIR) SET(CITYGML_FOUND TRUE) IF(NOT CITYGML_LIBRARY_DEBUG) MESSAGE("-- Warning Debug LibCityGML not found, using: ${CITYGML_LIBRARY}") SET(CITYGML_LIBRARY_DEBUG "${CITYGML_LIBRARY}" CACHE FILEPATH "Path to a library." FORCE) ENDIF(NOT CITYGML_LIBRARY_DEBUG) ENDIF(CITYGML_LIBRARY AND CITYGML_INCLUDE_DIR) SET(CITYGML_LIBRARIES optimized ${CITYGML_LIBRARY} debug ${CITYGML_LIBRARY_DEBUG}) libcitygml-2.0/CMakeModules/FindXerces.cmake000066400000000000000000000065031256066205500210720ustar00rootroot00000000000000# - Try to find Xerces-C # Once done this will define # # XERCESC_FOUND - system has Xerces-C # XERCESC_INCLUDE - the Xerces-C include directory # XERCESC_LIBRARY - Link these to use Xerces-C # XERCESC_VERSION - Xerces-C found version IF (XERCESC_INCLUDE AND XERCESC_LIBRARY) # in cache already SET(XERCESC_FIND_QUIETLY TRUE) ENDIF (XERCESC_INCLUDE AND XERCESC_LIBRARY) OPTION(XERCESC_STATIC "Set to ON to link your project with static library (instead of DLL)." ON) IF (NOT ${XERCESC_WAS_STATIC} STREQUAL ${XERCESC_STATIC}) UNSET(XERCESC_LIBRARY CACHE) UNSET(XERCESC_LIBRARY_DEBUG CACHE) ENDIF (NOT ${XERCESC_WAS_STATIC} STREQUAL ${XERCESC_STATIC}) SET(XERCESC_WAS_STATIC ${XERCESC_STATIC} CACHE INTERNAL "" ) FIND_PATH(XERCESC_INCLUDE NAMES xercesc/util/XercesVersion.hpp PATHS $ENV{XERCESC_INCLUDE_DIR} ${XERCESC_INCLUDE_DIR} /usr/local/include /usr/include ) IF (XERCESC_STATIC) FIND_LIBRARY(XERCESC_LIBRARY NAMES xerces-c_static_3 xerces-c-3.1 xerces-c PATHS $ENV{XERCESC_LIBRARY_DIR} ${XERCESC_LIBRARY_DIR} /usr/lib /usr/local/lib ) FIND_LIBRARY(XERCESC_LIBRARY_DEBUG NAMES xerces-c_static_3D xerces-c-3.1D PATHS $ENV{XERCESC_LIBRARY_DIR} ${XERCESC_LIBRARY_DIR} /usr/lib /usr/local/lib ) ADD_DEFINITIONS( -DXERCES_STATIC_LIBRARY ) ELSE (XERCESC_STATIC) FIND_LIBRARY(XERCESC_LIBRARY NAMES xerces-c_3 PATHS $ENV{XERCESC_LIBRARY_DIR} ${XERCESC_LIBRARY_DIR} ) FIND_LIBRARY(XERCESC_LIBRARY_DEBUG NAMES xerces-c_3D PATHS $ENV{XERCESC_LIBRARY_DIR} ${XERCESC_LIBRARY_DIR} ) ENDIF (XERCESC_STATIC) SET(XERCESC_FOUND FALSE) IF (XERCESC_INCLUDE AND XERCESC_LIBRARY) SET(XERCESC_FOUND TRUE) ENDIF (XERCESC_INCLUDE AND XERCESC_LIBRARY) IF(XERCESC_FOUND) IF(${XERCESC_LIBRARY_DEBUG}) SET(XERCESC_LIBRARIES optimized ${XERCESC_LIBRARY} debug ${XERCESC_LIBRARY_DEBUG}) ELSE(${XERCESC_LIBRARY_DEBUG}) SET(XERCESC_LIBRARIES ${XERCESC_LIBRARY}) ENDIF(${XERCESC_LIBRARY_DEBUG}) FIND_PATH(XERCESC_XVERHPPPATH NAMES XercesVersion.hpp PATHS ${XERCESC_INCLUDE} PATH_SUFFIXES xercesc/util) IF ( ${XERCESC_XVERHPPPATH} STREQUAL XERCESC_XVERHPPPATH-NOTFOUND ) SET(XERCES_VERSION "0") ELSE( ${XERCESC_XVERHPPPATH} STREQUAL XERCESC_XVERHPPPATH-NOTFOUND ) FILE(READ ${XERCESC_XVERHPPPATH}/XercesVersion.hpp XVERHPP) STRING(REGEX MATCHALL "\n *#define XERCES_VERSION_MAJOR +[0-9]+" XVERMAJ ${XVERHPP}) STRING(REGEX MATCH "\n *#define XERCES_VERSION_MINOR +[0-9]+" XVERMIN ${XVERHPP}) STRING(REGEX MATCH "\n *#define XERCES_VERSION_REVISION +[0-9]+" XVERREV ${XVERHPP}) STRING(REGEX REPLACE "\n *#define XERCES_VERSION_MAJOR +" "" XVERMAJ ${XVERMAJ}) STRING(REGEX REPLACE "\n *#define XERCES_VERSION_MINOR +" "" XVERMIN ${XVERMIN}) STRING(REGEX REPLACE "\n *#define XERCES_VERSION_REVISION +" "" XVERREV ${XVERREV}) SET(XERCESC_VERSION ${XVERMAJ}.${XVERMIN}.${XVERREV}) ENDIF ( ${XERCESC_XVERHPPPATH} STREQUAL XERCESC_XVERHPPPATH-NOTFOUND ) IF(NOT XERCESC_FIND_QUIETLY) MESSAGE(STATUS "Found Xerces-C: ${XERCESC_LIBRARY}") MESSAGE(STATUS " : ${XERCESC_INCLUDE}") MESSAGE(STATUS " Version: ${XERCESC_VERSION}") ENDIF(NOT XERCESC_FIND_QUIETLY) ELSE(XERCESC_FOUND) MESSAGE(FATAL_ERROR "Could not find Xerces-C !") ENDIF(XERCESC_FOUND) MARK_AS_ADVANCED(XERCESC_INCLUDE XERCESC_LIBRARY) libcitygml-2.0/CMakeModules/cmake_uninstall.cmake.in000066400000000000000000000016031256066205500226120ustar00rootroot00000000000000IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"${file}\"") IF(EXISTS "${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF("${rm_retval}" STREQUAL 0) ELSE("${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"${file}\"") ENDIF("${rm_retval}" STREQUAL 0) ELSE(EXISTS "${file}") MESSAGE(STATUS "File \"${file}\" does not exist.") ENDIF(EXISTS "${file}") ENDFOREACH(file) libcitygml-2.0/LICENSE000066400000000000000000000636311256066205500145370ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; 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 2.1 of the License, or (at your option) any later version. This library 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 GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libcitygml-2.0/README.md000066400000000000000000000023211256066205500147760ustar00rootroot00000000000000libcitygml ========== [![Build Status](https://travis-ci.org/jklimke/libcitygml.svg?branch=master)](https://travis-ci.org/jklimke/libcitygml) [CityGML](http://www.citygml.org/) (City Geography Markup Language) is an XML-based schema for the modelling and exchange of georeferenced 3D city and landscape models that is quickly being adopted on an international level. libcitygml is a small and easy to use open source C++ library for parsing CityGML files in such a way that data can be easily exploited by 3D rendering applications (geometry data are tesselated and optimized for rendering during parsing). For instance, it can be used to develop readers of CityGML files in many 3D based applications (OpenGL, OpenSceneGraph, ...) Most metadata are not lost, they are available through a per-node hashmap. libcitygml was initally developed by the 3D team of BRGM (the French leading public institution involved in the Earth Science field for the sustainable management of natural resources and surface and subsurface risks) for the research project DeepCity3D. It is now conducted as a Github open source project. It was moved to github due to inactivity of the project on google code (https://code.google.com/p/libcitygml/). libcitygml-2.0/SpecsToCheck.md000066400000000000000000000041741256066205500163670ustar00rootroot00000000000000# Specification of Modules to check ## CityGML CityGML Module | Namespace identifier | schemaLocation | Recommended namespace prefix | Checked --- | --- | --- | ---- | --- Core | http://www.opengis.net/citygml/1.0 | http://schemas.opengis.net/citygml/1.0/cityGMLBase.xsd | core | ☑ Appearance | http://www.opengis.net/citygml/appearance/1.0 | http://schemas.opengis.net/citygml/appearance/1.0/appearance.xsd | app | ☑ Building | http://www.opengis.net/citygml/building/1.0 | http://schemas.opengis.net/citygml/building/1.0/building.xsd | bldg | ☑ CityFurniture | http://www.opengis.net/citygml/cityfurniture/1.0 | http://schemas.opengis.net/citygml/cityfurniture/1.0/cityFurniture.xsd | frn | ☑ CityObjectGroup | http://www.opengis.net/citygml/cityobjectgroup/1.0 | http://schemas.opengis.net/citygml/cityobjectgroup/1.0/cityObjectGroup.xsd | grp | ☑ Generics | http://www.opengis.net/citygml/generics/1.0 | http://schemas.opengis.net/citygml/generics/1.0/generics.xsd | gen | ☑ LandUse | http://www.opengis.net/citygml/landuse/1.0 | http://schemas.opengis.net/citygml/landuse/1.0/landUse.xsd | luse | ☑ Relief | http://www.opengis.net/citygml/relief/1.0 | http://schemas.opengis.net/citygml/relief/1.0/relief.xsd | dem | ☑ Transportation | http://www.opengis.net/citygml/transportation/1.0 | http://schemas.opengis.net/citygml/transportation/1.0/transportation.xsd | tran | ☑ Vegetation | http://www.opengis.net/citygml/vegetation/1.0 | http://schemas.opengis.net/citygml/vegetation/1.0/vegetation.xsd | veg | ☑ WaterBody | http://www.opengis.net/citygml/waterbody/1.0 | http://schemas.opengis.net/citygml/waterbody/1.0/waterBody.xsd | wtr | ☑ ## GML GML Module | schemaLocation | Checked --- | --- | --- Basic Types | http://schemas.opengis.net/gml/3.1.1/base/basicTypes.xsd | ☐ Geometry | http://schemas.opengis.net/gml/3.1.1/base/geometryBasic0d1d.xsd | ☐libcitygml-2.0/TODO.md000066400000000000000000000065531256066205500146210ustar00rootroot00000000000000# libcitygml TODO List # Correctness * Check if the normals calculated for tesselation is always correct even if the vertices are in a spherical coordinate system ... if not one should think about removing the tesselation from libcitygml * Check if OrientableSurfaces are supported properly... may be the vertices must be reverted if the orientation is '-' * Check if Appearance assignment is correct for shared polygons * Ensure that polygons that are children of shared geometries are not also children of non shared geometries (otherwise a coordinate transformation might be applied on the vertices which is not allowed for shared geometries) * The namespace of the different modules may differ from the recommended one... make a namespace mapping based on the uri * Currently different city object types are grouped under the same enum type (CityObjectType) e.g. WaterSurface, WaterGroundSurface, WaterClosureSurface and WaterBody are of type COT_WaterBody. The reason for this is that every enum type is identified by an individual bit... however there are only 32 bits. Check if the bitmask is actually used... if not remove that constraint and define an individual enum type for every CityObject type * Some polygon types (PolygonSurface, Polygon, Triangle etc.) have an implicit ("planar") or explicit gml:SurfaceInterpolationType attribute... currently its ignored # Completness * Implement parsing of CityObject `` member (contains a cityobject or references one that is the generalization of the current one) =>` requires cityobject sharing * Implement parsing of CityObject `` member * Implement complete address parsing: Currently the address attributes (street, postalcode, etc.) are stored as indivdual address attributes. However a address can be assigned zero or more 2D or 3D point geometries (one gml:MultiPoint geometry) locating the entrance. This requires parsing of the `
` as an individual element * Implement parsing of ImplicitGeometry `` member * Implement GeoreferencedTexture parsing * Implement appearence `` support * Implement `` support (Darunter kann eine beliebige GML Geometrie hängen) * Implement full support for `` and `` (requires city object sharing, currently only inline definitions are supported) * Implement sharing for all geometries (currently onl ImplicitGeometries) * Implement lod0 parsing * Implement Relief/Terrain Model (Namespace DEM) parsing. More precisely implement ReliefComponentPropertyType parsing. * Requires gml:MultiPointPropertyType parsing * Requires gml:MultiCurvePropertyType parsing (also required for wtr module) * Requires gml:RectifiedGridCoverage parsing * Implement gml:Tin parsing (possible child of `` element that uses delauny triangulation) # Refactoring * Change the NodeTypes so that typeID is a constant expression -> Use switch-case structures instead of if-then-else in the element parsers * Rename Appearance in SurfaceData (an Appearance is actually the objects that defines a Theme) # Features * Enable CityObject filering by type mask (ParserParams) # Optimization * Remove empty objects * In the finish step check if the geometry hierachy can be folded. It should be possible to merge all geometries of the same lod level together... however thats not so simple with shared geometries (ImplicitGeomentry) libcitygml-2.0/citygml_to_libcitygml_mapping.graphml000066400000000000000000002450311256066205500232060ustar00rootroot00000000000000 CityObject GenericCityObject Building, BuildingPart, Room, BuildingInstallation, BuildingFurniture, Door, Window, CityFurniture, Track, Road, Railway, Square, PlantCover, SolitaryVegetationObject, WaterBody, TINRelief, LandUse, Tunnel, Bridge, BridgeConstructionElement, BridgeInstallation, BridgePart _BoundarySurface WallSurface, RoofSurface, GroundSurface, ClosureSurface, FloorSurface, InteriorWallSurface, CeilingSurface Envelope Envelope lowerCorner upperCorner ImplicitGeometry ImplicitGeometry relativeGeometry referencePoint gml:Point TexturedSurface, MultiSurface, CompositeSurface, TriangulatedSurface, OrientableSurface Geometry _Polygon surfaceMember, baseSurface, patches, trianglePatches Polygon Triangle Polygon _SurfaceData Appearance theme X3DMaterial _AbstractTexture ParameterizedTexture GeoreferencedTexture Material Texture GeoreferencedTexture target target TexCoordGen TexCoordList MaterialTarget TextureTarget TextureCoordinates lodXMultiSurface, lodXGeometry lodXImplicitRepresentation LinearRing LinearRing interior, exterior exterior, interior Solid lodXSolid gml:Pos gml:posList boundedBy, outerBuildingInstallation, interiorBuildingInstallation, interiorFurniture, roomInstallation, interiorRoom, opening solidMember CompositeSolid, MultiSolid libcitygml-2.0/debian_scripts/000077500000000000000000000000001256066205500165125ustar00rootroot00000000000000libcitygml-2.0/debian_scripts/postinst000077500000000000000000000000121256066205500203140ustar00rootroot00000000000000ldconfig libcitygml-2.0/libcitygml_classdiagram.graphml000066400000000000000000001412551256066205500217560ustar00rootroot00000000000000 Appearance AppearanceTarget AppearanceTargetDefinition CityGMLModel CityObject Envelope Geometry GeoreferencedTexture ImplicitGeometry LinearRing Material MaterialTargetDefinition TextureTargetDefinition Polygon Texture TextureCoordinates TransformMatrix 1..* 1 1..* 1 1 0..* 1 0..* 1 0..* 1..* 1 1 1 1 1..* 1 0..* 1 0..* 1 0..* 1 libcitygml-2.0/osgplugin/000077500000000000000000000000001256066205500155305ustar00rootroot00000000000000libcitygml-2.0/osgplugin/CMakeLists.txt000066400000000000000000000027051256066205500202740ustar00rootroot00000000000000set(target osgdb_citygml) set_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON) find_package( OpenSceneGraph REQUIRED osgDB osgViewer osgGA osgUtil osgText) include_directories( ${OPENSCENEGRAPH_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/sources/include ${CMAKE_BINARY_DIR}/include ) set( sources ReaderWriterCityGML.cpp ) add_library(${target} SHARED ${sources}) set_target_properties(${target} PROPERTIES PREFIX "") if(APPLE) SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") endif(APPLE) target_link_libraries(${target} ${OPENSCENEGRAPH_LIBRARIES} citygml) set(OSG_PLUGINS "osgPlugins-${OPENSCENEGRAPH_VERSION}") set(LIBCITYGML_OSG_PLUGIN_INSTALL_DIR "" CACHE PATH "The directory in which the plugin will be installed. (osgPlugins- is appended to this path)") set(PLUGIN_INSTALL_PATH lib/${OSG_PLUGINS}) if (LIBCITYGML_OSG_PLUGIN_INSTALL_DIR) set(PLUGIN_INSTALL_PATH ${LIBCITYGML_OSG_PLUGIN_INSTALL_DIR}/${OSG_PLUGINS}) endif() add_definitions(-DPLUGIN_BIN_DIR=\"${CMAKE_BINARY_DIR}/lib\") add_executable(citygmlOsgViewer CitygmlOsgViewer.cpp) target_link_libraries(citygmlOsgViewer ${OPENSCENEGRAPH_LIBRARIES} citygml) INSTALL( TARGETS ${target} RUNTIME DESTINATION ${PLUGIN_INSTALL_PATH} LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH} ARCHIVE DESTINATION ${PLUGIN_INSTALL_PATH} ) INSTALL( TARGETS citygmlOsgViewer RUNTIME DESTINATION bin LIBRARY DESTINATION ${PLUGIN_INSTALL_PATH} ARCHIVE DESTINATION ${PLUGIN_INSTALL_PATH} ) libcitygml-2.0/osgplugin/CitygmlOsgViewer.cpp000066400000000000000000000076621256066205500215120ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include class PickingHandler : public osgGA::GUIEventHandler { public: PickingHandler() { m_xMouseCoordAtLastPress = -1; m_yMouseCoordAtLastPress = -1; } // EventHandler interface virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor*) { if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) { if (m_xMouseCoordAtLastPress != ea.getX() || m_yMouseCoordAtLastPress != ea.getY()) { return false; } return printDescriptionOfIntersectedDrawable(ea, aa); } else if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) { m_xMouseCoordAtLastPress = ea.getX(); m_yMouseCoordAtLastPress = ea.getY(); } return false; } private: bool printDescriptionOfIntersectedDrawable(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) { osgUtil::LineSegmentIntersector::Intersections intersections; if (!aa.computeIntersections(ea, intersections)) { return false; } osgUtil::LineSegmentIntersector::Intersection firstIntersection = *intersections.begin(); if (firstIntersection.drawable == nullptr) { return false; } if (firstIntersection.drawable->getNumDescriptions() == 0) { std::cout << "Intersected drawable has no description:" << std::endl; return true; } std::cout << "Description of intersected drawable:" << std::endl; for (const std::string& desc : firstIntersection.drawable->getDescriptions()) { std::cout << " " << desc << std::endl; } std::cout << std::endl; return true; } int m_xMouseCoordAtLastPress; int m_yMouseCoordAtLastPress; }; int main(int argc, char *argv[]) { osg::setNotifyLevel(osg::WARN); std::cout << "Using plugin directory: " << PLUGIN_BIN_DIR << std::endl; osgDB::Registry::instance()->getLibraryFilePathList().push_front(PLUGIN_BIN_DIR); osgDB::Registry::instance()->addFileExtensionAlias("gml", "citygml"); if (argc < 2) { std::cerr << "No citygml file specified..." << std::endl; return 1; } osg::ref_ptr options = new osgDB::Options("usemaxlodonly storegeomids"); std::cout << "Loading file: " << argv[1] << std::endl; osg::ref_ptr node = osgDB::readNodeFile(argv[1], options); if (node == nullptr) { std::cerr << "Failed to load file " << argv[1] << std::endl; return 1; } std::cout << "Optimizing node..." << std::endl; osgUtil::Optimizer optimizer; optimizer.optimize(node, osgUtil::Optimizer::ALL_OPTIMIZATIONS); std::cout << "Setup viewer..." << std::endl; osg::ref_ptr manip = new osgGA::SphericalManipulator(); manip->setAutoComputeHomePosition(true); manip->setNode(node); osgViewer::Viewer viewer; viewer.setUpViewInWindow(0, 0, 800, 600); viewer.setSceneData(node); viewer.setCameraManipulator(manip); viewer.addEventHandler(new osgGA::StateSetManipulator(node->getOrCreateStateSet())); viewer.addEventHandler(new osgViewer::StatsHandler()); viewer.addEventHandler(new osgViewer::WindowSizeHandler()); viewer.addEventHandler(new PickingHandler()); viewer.addEventHandler(new osgViewer::HelpHandler()); viewer.run(); return 0; } libcitygml-2.0/osgplugin/README000066400000000000000000000017051256066205500164130ustar00rootroot00000000000000libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM http://code.google.com/p/libcitygml To use libcitygml with OpenSceneGraph (min 2.8), here is some instructions: - Copy FindCityGML.cmake and FindXerces.cmake from libcitygml/CMakeModules to $(OSG_SRC_DIR)/CMakeModules - Copy libcitygml/test/osgplugin/* to $(OSG_SRC_DIR)/src/osgPlugins/citygml - Add the following line to $(OSG_SRC_DIR)/src/osgPlugins/CMakeLists.txt ADD_SUBDIRECTORY(citygml) Use CMake to reconfigure OpenSceneGraph installation. Generate project and build! You can use Open Scene Graph plugin with LibXml2 or Xerces (default), according to your libcitygml building configuration. WARNING: no control is done, it is your responsability to select the corresponding parameters. (i.e. if your build libcitygml with libxml2, you have to select LibXml2 when configuring the Open Scene Graph plugin. Please report any bugs to http://code.google.com/p/libcitygml/issues/list Thank you.libcitygml-2.0/osgplugin/ReaderWriterCityGML.cpp000066400000000000000000000452361256066205500220360ustar00rootroot00000000000000/////////////////////////////////////////////////////////////////////////////// // OSG plugin for reading OGC CityGML v0.3 - v1.0 format using libcitygml // http://code.google.com/p/libcitygml // Copyright(c) 2010 Joachim Pouderoux, BRGM ////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class CityGMLOSGPluginLogger : public citygml::CityGMLLogger { public: virtual void log(LOGLEVEL level, const std::string& message, const char* file, int line) const { std::ostream& stream = getLogStreamFor(level); if (file) { stream << " [" << file; if (line > -1) { stream << ":" << line; } stream << "]"; } stream << " " << message << std::endl; } virtual bool isEnabledFor(LOGLEVEL) const { return true; } private: std::ostream& getLogStreamFor(LOGLEVEL level) const { switch(level) { case LOGLEVEL::LL_DEBUG: return osg::notify(osg::DEBUG_INFO); case LOGLEVEL::LL_WARNING: return osg::notify(osg::WARN); case LOGLEVEL::LL_TRACE: return osg::notify(osg::DEBUG_FP); case LOGLEVEL::LL_ERROR: return osg::notify(osg::FATAL); case LOGLEVEL::LL_INFO: return osg::notify(osg::INFO); default: return osg::notify(osg::INFO); } } }; class CityGMLSettings { public: CityGMLSettings( void ) : _printNames(false) , _useMaxLODOnly(false) , _storeGeomIDs(false) , _theme("") {} void parseOptions( const osgDB::ReaderWriter::Options* options) { if ( !options ) return; std::istringstream iss( options->getOptionString() ); std::string currentOption; while ( iss >> currentOption ) { std::transform( currentOption.begin(), currentOption.end(), currentOption.begin(), ::tolower ); if ( currentOption == "names" ) _printNames = true; else if ( currentOption == "mask" ) iss >> _params.objectsMask; else if ( currentOption == "minlod" ) iss >> _params.minLOD; else if ( currentOption == "maxlod" ) iss >> _params.maxLOD; else if ( currentOption == "optimize" ) _params.optimize = true; else if ( currentOption == "pruneemptyobjects" ) _params.pruneEmptyObjects = true; else if ( currentOption == "usemaxlodonly" ) _useMaxLODOnly = true; else if ( currentOption == "usetheme" ) iss >> _theme; else if ( currentOption == "storegeomids" ) _storeGeomIDs = true; } } public: citygml::ParserParams _params; bool _printNames; bool _useMaxLODOnly; bool _storeGeomIDs; std::map< std::string, osg::Texture2D* > _textureMap; std::string _theme; }; class ReaderWriterCityGML : public osgDB::ReaderWriter { public: ReaderWriterCityGML( void ) { supportsExtension( "citygml", "CityGML format" ); supportsExtension( "gml", "CityGML format" ); supportsOption( "names", "Add the name of the city objects on top of them" ); supportsOption( "mask", "Set the objects mask" ); supportsOption( "minLOD", "Minimum LOD level to fetch" ); supportsOption( "maxLOD", "Maximum LOD level to fetch" ); supportsOption( "optimize", "Optimize the geometries & polygons of the CityGML model to reduce the number of instanced objects" ); supportsOption( "pruneEmptyObjects", "Prune empty objects (ie. without -supported- geometry)" ); supportsOption( "destSRS", "Transform geometry to given reference system" ); supportsOption( "useMaxLODonly", "Use the highest available LOD for geometry of one object" ); supportsOption( "appearanceTheme", "Name of the appearance theme to use" ); supportsOption( "storegeomids", "Store the citygml id of geometry objects in the corresponding osg::Geometry object as a description string." ); m_logger = std::make_shared(); } virtual const char* className( void ) const override { return "CityGML Reader"; } virtual ReadResult readNode( const std::string&, const osgDB::ReaderWriter::Options* ) const override; virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const override; private: std::shared_ptr m_logger; static unsigned int getHighestLodForObject(const citygml::CityObject& object); ReadResult readCity(std::shared_ptr, CityGMLSettings& ) const; bool createCityObject(const citygml::CityObject&, CityGMLSettings&, osg::Group*, const osg::Vec3d& offset = osg::Vec3d(0.0, 0.0, 0.0), unsigned int minimumLODToConsider = 0) const; }; // Register with Registry to instantiate the above reader/writer. REGISTER_OSGPLUGIN( citygml, ReaderWriterCityGML ) // Read CityGML file using libcitygml and generate the OSG scenegraph osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readNode( const std::string& file, const osgDB::ReaderWriter::Options* options ) const { std::string ext = osgDB::getLowerCaseFileExtension( file ); if ( !acceptsExtension( ext ) ) return ReadResult::FILE_NOT_HANDLED; // try to open the file as is std::string fileName = osgDB::findDataFile( file, options ); if ( fileName.empty() ) { // not found, so remove the .citygml extension file std::string fname = osgDB::getNameLessExtension( file ); fileName = osgDB::findDataFile( fname, options ); if ( fileName.empty() ) return ReadResult::FILE_NOT_FOUND; } CityGMLSettings settings; settings.parseOptions( options ); osgDB::getDataFilePathList().push_front( osgDB::getFilePath( fileName ) ); // Redirect both std::cout & std::cerr (used by libcitygml) to osg::notify stream std::streambuf* coutsb = std::cout.rdbuf( osg::notify(osg::NOTICE).rdbuf() ); std::streambuf* cerrsb = std::cerr.rdbuf( osg::notify(osg::NOTICE).rdbuf() ); osg::notify(osg::NOTICE) << "Parsing CityGML file " << fileName << "..." << std::endl; std::shared_ptr city = citygml::load( fileName, settings._params, m_logger ); ReadResult rr = readCity( city, settings ); if ( rr.status() == ReadResult::FILE_LOADED && rr.getNode() ) { rr.getNode()->setName( fileName ); // Let osg calculate the normals osgUtil::SmoothingVisitor sv; rr.getNode()->accept(sv); } osgDB::getDataFilePathList().pop_front(); // Restore cout/cerr streams std::cout.rdbuf( coutsb ); std::cerr.rdbuf( cerrsb ); return rr; } osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readNode( std::istream& fin, const osgDB::ReaderWriter::Options* options ) const { CityGMLSettings settings; settings.parseOptions( options ); // Redirect both std::cout & std::cerr (used by CityGML parser) to osg::notify stream std::streambuf* coutsb = std::cout.rdbuf( osg::notify(osg::NOTICE).rdbuf() ); std::streambuf* cerrsb = std::cerr.rdbuf( osg::notify(osg::NOTICE).rdbuf() ); osg::notify(osg::NOTICE) << "Parsing CityGML stream..." << std::endl; std::shared_ptr city = citygml::load( fin, settings._params ); ReadResult rr = readCity( city, settings ); // Restore cout/cerr streams std::cout.rdbuf( coutsb ); std::cerr.rdbuf( cerrsb ); return rr; } osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readCity(std::shared_ptr city, CityGMLSettings& settings ) const { if ( !city ) return nullptr; osg::notify(osg::NOTICE) << city->getNumRootCityObjects() << " city objects read." << std::endl; osg::notify(osg::NOTICE) << "Creation of the OSG city objects' geometry..." << std::endl; osg::MatrixTransform* root = new osg::MatrixTransform(); root->setName( city->getId() ); if (settings._theme.empty() && !city->themes().empty()) { settings._theme = city->themes().front(); } const citygml::ConstCityObjects& roots = city->getRootCityObjects(); if(roots.size() == 0) return nullptr; osg::Vec3d offset(0, 0, 0); if (city->getEnvelope().validBounds()) { TVec3d lb = city->getEnvelope().getLowerBound(); offset = osg::Vec3d(lb.x, lb.y, lb.z); } for ( unsigned int i = 0; i < roots.size(); ++i ) createCityObject( *roots[i], settings, root, offset ); osg::notify(osg::NOTICE) << "Done." << std::endl; root->setMatrix( osg::Matrixd::translate(offset)); return root; } void setTexture(osg::ref_ptr stateset, osg::Geometry* geom, const citygml::Polygon& polygon, CityGMLSettings& settings) { const auto citygmlTex = polygon.getTextureFor(settings._theme); if ( !citygmlTex ) { return; } const std::vector& texCoords = polygon.getTexCoordsForTheme(settings._theme, true); if (texCoords.empty()) { osg::notify(osg::WARN) << "Texture coordinates not found for poly " << polygon.getId() << std::endl; } osg::Texture2D* texture = nullptr; if ( settings._textureMap.find( citygmlTex->getUrl() ) == settings._textureMap.end() ) { std::string fullPath = osgDB::findDataFile(citygmlTex->getUrl()); if (fullPath.empty()) { osg::notify(osg::NOTICE) << " Texture file " << citygmlTex->getUrl() << " not found..." << std::endl; return; } // Load a new texture osg::notify(osg::NOTICE) << " Loading texture " << fullPath << "..." << std::endl; osg::Image* image = osgDB::readImageFile( citygmlTex->getUrl() ); if (!image) { osg::notify(osg::NOTICE) << " Warning: Failed to read Texture " << fullPath << std::endl; return; } texture = new osg::Texture2D; texture->setImage( image ); texture->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR ); texture->setFilter( osg::Texture::MAG_FILTER, osg::Texture::NEAREST ); texture->setWrap( osg::Texture::WRAP_S, osg::Texture::REPEAT ); texture->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT ); texture->setWrap( osg::Texture::WRAP_R, osg::Texture::REPEAT ); settings._textureMap[ citygmlTex->getUrl() ] = texture; } else { texture = settings._textureMap[ citygmlTex->getUrl() ]; } if ( !texture ) { return; } osg::ref_ptr tex = new osg::Vec2Array; tex->reserve( texCoords.size() ); for ( unsigned int k = 0; k < texCoords.size(); k++ ) tex->push_back( osg::Vec2( texCoords[k].x, texCoords[k].y ) ); geom->setTexCoordArray( 0, tex ); stateset->setTextureAttributeAndModes( 0, texture, osg::StateAttribute::ON ); } void setMaterial(osg::ref_ptr stateset, const citygml::Polygon& polygon, CityGMLSettings& settings) { const auto citygmlMaterial = polygon.getMaterialFor(settings._theme); if (!citygmlMaterial) { return; } TVec4f diffuse( citygmlMaterial->getDiffuse(), 0.f ); TVec4f emissive( citygmlMaterial->getEmissive(), 0.f ); TVec4f specular( citygmlMaterial->getSpecular(), 0.f ); float ambient = citygmlMaterial->getAmbientIntensity(); osg::Material* material = new osg::Material; material->setColorMode( osg::Material::OFF ); material->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a ) ); material->setSpecular( osg::Material::FRONT_AND_BACK, osg::Vec4(specular.r, specular.g, specular.b, specular.a ) ); material->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4(emissive.r, emissive.g, emissive.b, emissive.a ) ); material->setShininess( osg::Material::FRONT_AND_BACK, 128.f * citygmlMaterial->getShininess() ); material->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( ambient, ambient, ambient, 1.0 ) ); material->setTransparency( osg::Material::FRONT_AND_BACK, citygmlMaterial->getTransparency() ); stateset->setAttributeAndModes( material, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); stateset->setMode( GL_LIGHTING, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); } void createOsgGeometryFromCityGMLGeometry(const citygml::Geometry& geometry, CityGMLSettings& settings, osg::Geode* geometryContainer, const osg::Vec3d& offset ) { for ( unsigned int j = 0; j < geometry.getPolygonsCount(); j++ ) { const citygml::Polygon& p = *geometry.getPolygon(j); if ( p.getIndices().size() == 0 ) continue; // Geometry management osg::Geometry* geom = new osg::Geometry; geom->setName( p.getId() ); geom->setUserValue("cot_type", geometry.getTypeAsString()); // Vertices osg::Vec3Array* vertices = new osg::Vec3Array; const std::vector& vert = p.getVertices(); vertices->reserve( vert.size() ); for ( unsigned int k = 0; k < vert.size(); k++ ) { TVec3d v = vert[k]; osg::Vec3d pt = osg::Vec3d( v.x, v.y, v.z ) - offset; vertices->push_back( pt ); } geom->setVertexArray( vertices ); // Indices osg::DrawElementsUInt* indices = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, p.getIndices().begin(), p.getIndices().end()); geom->addPrimitiveSet( indices ); // Appearance osg::ref_ptr stateset = geom->getOrCreateStateSet(); setMaterial(stateset, p, settings); setTexture(stateset, geom, p, settings); if (settings._storeGeomIDs) { geom->addDescription(p.getId()); } geometryContainer->addDrawable( geom ); } // Parse child geoemtries for (unsigned int i = 0; i < geometry.getGeometriesCount(); i++) { createOsgGeometryFromCityGMLGeometry(geometry.getGeometry(i), settings, geometryContainer, offset); } } bool ReaderWriterCityGML::createCityObject(const citygml::CityObject& object, CityGMLSettings& settings, osg::Group* parent, const osg::Vec3d& offset , unsigned int minimumLODToConsider) const { // Skip objects without geometry if ( !parent ) return false; osg::ref_ptr geode = new osg::Geode; geode->setName( object.getId() ); osg::Group* grp = new osg::Group; grp->setName( object.getId() ); grp->setUserValue("cot_type", object.getTypeAsString()); grp->addChild( geode ); parent->addChild( grp ); osg::ref_ptr roof_color = new osg::Vec4Array; roof_color->push_back( osg::Vec4( 0.9f, 0.1f, 0.1f, 1.0f ) ); unsigned int highestLOD = ReaderWriterCityGML::getHighestLodForObject(object); for ( unsigned int i = 0; i < object.getGeometriesCount(); i++ ) { const citygml::Geometry& geometry = object.getGeometry( i ); const unsigned int currentLOD = geometry.getLOD(); if (settings._useMaxLODOnly && (currentLOD < highestLOD || currentLOD < minimumLODToConsider )){ continue; } createOsgGeometryFromCityGMLGeometry(geometry, settings, geode, offset); } if ( settings._printNames ) { // Print the city object name on top of it geode->getBoundingBox().center(); osg::ref_ptr text = new osgText::Text; text->setFont( "arial.ttf" ); text->setCharacterSize( 2 ); text->setBackdropType( osgText::Text::OUTLINE ); text->setFontResolution( 64, 64 ); text->setText( object.getId(), osgText::String::ENCODING_UTF8 ); text->setCharacterSizeMode( osgText::TextBase::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT ); text->setAxisAlignment( osgText::TextBase::SCREEN ); text->setAlignment( osgText::TextBase::CENTER_BOTTOM ); text->setPosition( geode->getBoundingBox().center() + osg::Vec3( 0, 0, geode->getBoundingBox().radius() ) ); text->getOrCreateStateSet()->setMode( GL_LIGHTING, osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF ); geode->addDrawable( text.get() ); } // Manage transparency for windows if ( object.getType() == citygml::CityObject::CityObjectsType::COT_Window ) { osg::StateSet *geodeSS( geode->getOrCreateStateSet() ); osg::ref_ptr blendFunc = new osg::BlendFunc(osg::BlendFunc::ONE_MINUS_CONSTANT_ALPHA,osg::BlendFunc::CONSTANT_ALPHA); geodeSS->setAttributeAndModes( blendFunc.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON ); osg::ref_ptr blendColor = new osg::BlendColor(osg::Vec4( 1., 1., 1., 0.4 )); geodeSS->setAttributeAndModes( blendColor.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON ); osg::ref_ptr depth = new osg::Depth; depth->setWriteMask( false ); geodeSS->setAttributeAndModes( depth.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON ); geodeSS->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } for ( unsigned int i = 0; i < object.getChildCityObjectsCount(); ++i ) createCityObject( object.getChildCityObject(i), settings, grp, offset, highestLOD); return true; } unsigned int ReaderWriterCityGML::getHighestLodForObject( const citygml::CityObject& object){ unsigned int highestLOD = 0; // first find out highest LOD for this object for (unsigned int i = 0; i < object.getGeometriesCount(); i++) { const citygml::Geometry &geometry = object.getGeometry(i); if (geometry.getLOD() > highestLOD){ highestLOD = geometry.getLOD(); } } //check for the highest LODs of Children for (unsigned int i = 0; i < object.getChildCityObjectsCount(); ++i){ unsigned int tempHighestLOD = ReaderWriterCityGML::getHighestLodForObject(object.getChildCityObject(i)); if (tempHighestLOD > highestLOD){ tempHighestLOD = highestLOD; } } return highestLOD; } libcitygml-2.0/sources/000077500000000000000000000000001256066205500152045ustar00rootroot00000000000000libcitygml-2.0/sources/CMakeLists.txt000066400000000000000000000121271256066205500177470ustar00rootroot00000000000000SET( target citygml ) ADD_DEFINITIONS( -DCITYGML_LIBRARY ) ADD_DEFINITIONS( -DLIBCITYGML_BUILD ) IF( LIBCITYGML_STATIC ) ADD_DEFINITIONS( -DLIBCITYGML_STATIC ) ENDIF( LIBCITYGML_STATIC ) IF( LIBCITYGML_DYNAMIC ) ADD_DEFINITIONS( -DLIBCITYGML_DYNAMIC ) ENDIF( LIBCITYGML_DYNAMIC ) configure_file(include/citygml/citygml_api.h.in ${CMAKE_BINARY_DIR}/include/citygml/citygml_api.h) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/sources/include ${XERCESC_INCLUDE} ${ICONV_INCLUDE_DIR} ${GLU_INCLUDE_PATH} ${GDAL_INCLUDE_DIR} ${CMAKE_BINARY_DIR}/include) SET(SOURCES src/citygml/citymodel.cpp src/citygml/tesselator.cpp src/citygml/object.cpp src/citygml/featureobject.cpp src/citygml/appearance.cpp src/citygml/texture.cpp src/citygml/material.cpp src/citygml/georeferencedtexture.cpp src/citygml/envelope.cpp src/citygml/appearancemanager.cpp src/citygml/cityobject.cpp src/citygml/geometry.cpp src/citygml/implictgeometry.cpp src/citygml/linearring.cpp src/citygml/polygon.cpp src/citygml/transformmatrix.cpp src/citygml/texturetargetdefinition.cpp src/citygml/materialtargetdefinition.cpp src/citygml/texturecoordinates.cpp src/citygml/appearancetarget.cpp src/citygml/citygmlfactory.cpp src/citygml/polygonmanager.cpp src/citygml/geometrymanager.cpp src/citygml/linestring.cpp src/citygml/address.cpp src/parser/nodetypes.cpp src/parser/attributes.cpp src/parser/geocoordinatetransformer.cpp src/parser/citygmldocumentparser.cpp src/parser/parserxercesc.cpp src/parser/citygmlelementparser.cpp src/parser/elementparser.cpp src/parser/delayedchoiceelementparser.cpp src/parser/skipelementparser.cpp src/parser/sequenceparser.cpp src/parser/gmlobjectparser.cpp src/parser/gmlfeaturecollectionparser.cpp src/parser/citymodelelementparser.cpp src/parser/cityobjectelementparser.cpp src/parser/appearanceelementparser.cpp src/parser/materialelementparser.cpp src/parser/textureelementparser.cpp src/parser/georeferencedtextureelementparser.cpp src/parser/geometryelementparser.cpp src/parser/polygonelementparser.cpp src/parser/linestringelementparser.cpp src/parser/linearringelementparser.cpp src/parser/implicitgeometryelementparser.cpp src/parser/addressparser.cpp ) SET(PUBLIC_HEADER ${CMAKE_BINARY_DIR}/include/citygml/citygml_api.h include/citygml/citygmllogger.h include/citygml/polygon.h include/citygml/material.h include/citygml/geometry.h include/citygml/object.h include/citygml/featureobject.h include/citygml/georeferencedtexture.h include/citygml/cityobject.h include/citygml/envelope.h include/citygml/appearance.h include/citygml/vecs.hpp include/citygml/citymodel.h include/citygml/linearring.h include/citygml/citygml.h include/citygml/transformmatrix.h include/citygml/implictgeometry.h include/citygml/tesselator.h include/citygml/texture.h include/citygml/appearancetargetdefinition.h include/citygml/texturetargetdefinition.h include/citygml/materialtargetdefinition.h include/citygml/texturecoordinates.h include/citygml/appearancetarget.h include/citygml/citygmlfactory.h include/citygml/linestring.h include/citygml/address.h ) SET(HEADERS ${PUBLIC_HEADER} include/citygml/citygml_api.h.in include/citygml/tesselator.h include/citygml/utils.h include/citygml/appearancemanager.h include/citygml/polygonmanager.h include/citygml/geometrymanager.h include/parser/nodetypes.h include/parser/attributes.h include/parser/documentlocation.h include/parser/parserutils.hpp include/parser/geocoordinatetransformer.h include/parser/citygmldocumentparser.h include/parser/citygmlelementparser.h include/parser/elementparser.h include/parser/delayedchoiceelementparser.h include/parser/skipelementparser.h include/parser/sequenceparser.h include/parser/gmlobjectparser.h include/parser/gmlfeaturecollectionparser.h include/parser/citymodelelementparser.h include/parser/cityobjectelementparser.h include/parser/appearanceelementparser.h include/parser/materialelementparser.h include/parser/textureelementparser.h include/parser/georeferencedtextureelementparser.h include/parser/geometryelementparser.h include/parser/polygonelementparser.h include/parser/linestringelementparser.h include/parser/linearringelementparser.h include/parser/implicitgeometryelementparser.h include/parser/addressparser.h ) ADD_LIBRARY( ${target} ${LIBCITYGML_USER_DEFINED_DYNAMIC_OR_STATIC} ${SOURCES} ${HEADERS} ) TARGET_LINK_LIBRARIES( ${target} ${XERCESC_LIBRARIES} ${OPENGL_LIBRARIES} ${GDAL_LIBRARY} ) set_target_properties( ${target} PROPERTIES VERSION ${META_VERSION} SOVERSION ${META_VERSION_MAJOR} ) INSTALL( TARGETS ${target} RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ) # FIXME: Do not run for OS X framework INSTALL( FILES ${PUBLIC_HEADER} DESTINATION ${INCLUDE_INSTALL_DIR} ) configure_file(citygml.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/citygml.pc) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/citygml.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) libcitygml-2.0/sources/citygml.pc.cmake000066400000000000000000000004531256066205500202610ustar00rootroot00000000000000prefix=${CMAKE_INSTALL_PREFIX} exec_prefix=${BIN_INSTALL_DIR} libdir=${LIB_INSTALL_DIR} includedir=${INCLUDE_INSTALL_DIR} Name: citygml Description: Read and Write CityGML files Requires: libxml-2.0 glu Version: ${META_VERSION} Libs: -L${LIB_INSTALL_DIR} -lcitygml Cflags: -I${INCLUDE_INSTALL_DIR} libcitygml-2.0/sources/include/000077500000000000000000000000001256066205500166275ustar00rootroot00000000000000libcitygml-2.0/sources/include/citygml/000077500000000000000000000000001256066205500202775ustar00rootroot00000000000000libcitygml-2.0/sources/include/citygml/address.h000066400000000000000000000017451256066205500221040ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class LIBCITYGML_EXPORT Address: public Object { public: Address(const std::string& id); const std::string& country() const; void setCountry(const std::string& country); const std::string& locality() const; void setLocality(const std::string& locality); const std::string& postalCode() const; void setPostalCode(const std::string& postalCode); const std::string& thoroughfareName() const; void setThoroughfareName(const std::string& thoroughfareName); const std::string& thoroughfareNumber() const; void setThoroughfareNumber(const std::string& thoroughfareNumber); protected: std::string m_country; std::string m_locality; std::string m_thoroughfareName; std::string m_thoroughfareNumber; std::string m_postalCode; }; } /* namespace citygml */ libcitygml-2.0/sources/include/citygml/appearance.h000066400000000000000000000025211256066205500225470ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include namespace citygml { class Material; class Texture; class GeoreferencedTexture; class LIBCITYGML_EXPORT Appearance : public Object, public std::enable_shared_from_this { public: std::string getType() const; bool getIsFront() const; void setIsFront(bool front); virtual std::string toString() const; virtual std::shared_ptr asMaterial(); virtual std::shared_ptr asMaterial() const; virtual std::shared_ptr asTexture(); virtual std::shared_ptr asTexture() const; virtual std::shared_ptr asGeoreferencedTexture(); virtual std::shared_ptr asGeoreferencedTexture() const; bool inTheme(const std::string& themeName) const; void addToTheme(std::string themeName); const std::vector& getThemes() const; virtual ~Appearance() {} protected: Appearance( const std::string& id, const std::string& typeString ); std::string m_typeString; std::vector m_themes; bool m_isFront; }; } libcitygml-2.0/sources/include/citygml/appearancemanager.h000066400000000000000000000041611256066205500241040ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include class Tesselator; namespace citygml { class CityGMLLogger; class Appearance; class AppearanceTarget; class Material; class Texture; class MaterialTargetDefinition; class TextureTargetDefinition; class AppearanceManager { public: AppearanceManager(std::shared_ptr logger ); ~AppearanceManager(); /** * @brief returns the appearance with the given id * @return the Appearance object or nullptr if not found */ std::shared_ptr getAppearanceByID( const std::string& id ) const; /** * @brief all themes found in the parsed citygml file * @return a list of theme identifiers * @note should be called after assignAppearancesToTargets (otherwise the list will be empty) */ std::vector getAllThemes(); void addAppearanceTarget(AppearanceTarget* target); void addAppearance(std::shared_ptr appearance); void addTextureTargetDefinition(std::shared_ptr targetDef); void addMaterialTargetDefinition(std::shared_ptr targetDef); /** * @brief assigns each appearance to all targets for which a coresponding AppearanceTargetDefinition exits. * @note should be called once after parsing has finished */ void assignAppearancesToTargets(); protected: std::unordered_map> m_appearancesMap; std::vector> m_materialTargetDefinitions; std::vector> m_texTargetDefinitions; std::unordered_set m_themes; std::unordered_map m_appearanceTargetsMap; std::shared_ptr m_logger; void addThemesFrom(std::shared_ptr surfaceData); }; } libcitygml-2.0/sources/include/citygml/appearancetarget.h000066400000000000000000000040161256066205500237570ustar00rootroot00000000000000#pragma once #include #include #include #include #include namespace citygml { class MaterialTargetDefinition; class TextureTargetDefinition; class Appearance; /** * @brief The AppearanceTarget class is the base class for all citygml objects that can be targets of appearances * * Ensures that there is only one texture and material per theme */ class AppearanceTarget : public citygml::Object { public: void addTargetDefinition(std::shared_ptr> targetDef); void addTargetDefinition(std::shared_ptr targetDef); void addTargetDefinition(std::shared_ptr targetDef); void addTargetDefinitionsOf(const AppearanceTarget& other); std::shared_ptr getMaterialTargetDefinitionForTheme(const std::string& theme, bool front); std::shared_ptr getMaterialTargetDefinitionForTheme(const std::string& theme, bool front) const; std::shared_ptr getTextureTargetDefinitionForTheme(const std::string& theme, bool front); std::shared_ptr getTextureTargetDefinitionForTheme(const std::string& theme, bool front) const; std::vector getTextureTargetDefinitions(); std::vector getAllTextureThemes(bool front) const; protected: AppearanceTarget(const std::string& id); private: std::unordered_map> m_themeMatMapFront; std::unordered_map> m_themeMatMapBack; std::unordered_map> m_themeTexMapFront; std::unordered_map> m_themeTexMapBack; }; } libcitygml-2.0/sources/include/citygml/appearancetargetdefinition.h000066400000000000000000000037311256066205500260330ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { /* * TODO: * - store the target id here * - store the appearance object here as a shared pointer * - create a subclass for material appearance type and texture appearance type (TextureTargetDefinition, MaterialTargetDefinition) * - modify AppearanceTarget so that is contains distinct lists for TextureTargetDefinition and MaterialTargetDefinition definitions... store the AppearanceTargetDefinitions as shared_ptr * - remove all knowledge of thier targets from the appearance objects (Texture, Material) * - let the appearance manager store the AppearanceTargetDefinition objects and the Appearance objects until they are assigned... then remove them from the appearance manager * - when finishing the AppearanceTarget objcts pass down the AppearanceTargetDefinition * - when finishing the polygon object remove all AppearanceTargetDefinition that are unused */ /** * @brief defines the association between an Appearance object and an AppearanceTarget object */ template class AppearanceTargetDefinition : public Object { public: AppearanceTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id) : Object(id), m_targetID(targetID), m_appearance(appearance) {} /** * @brief the id of the target surface * @note The targetID must not be the id of the object on which the texture is applied at the end (may be passed down to the children of the target object) */ std::string getTargetID() const { return m_targetID; } std::shared_ptr getAppearance() const { return m_appearance; } std::shared_ptr getAppearance() { return m_appearance; } virtual ~AppearanceTargetDefinition() {} protected: std::string m_targetID; std::shared_ptr m_appearance; }; } libcitygml-2.0/sources/include/citygml/citygml.h000066400000000000000000000056111256066205500221230ustar00rootroot00000000000000/* -*-c++-*- libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include class Tesselator; namespace citygml { class CityModel; class CityGMLLogger; class Appearance; class Texture; class Material; class AppearanceManager; typedef unsigned int CityObjectsTypeMask; /////////////////////////////////////////////////////////////////////////////// // Parsing routines // Parameters: // objectsMask: a bit mask that defines which CityObjectsTypes are parsed // examples: CityObject::CityObjectsType::COT_Building | CityObject::CityObjectsType::COT_Room <- parses only Building and Room objects" // minLOD: the minimal LOD that will be parsed // maxLOD: the maximal LOD that will be parsed // optimize: merge geometries & polygons that share the same appearance in the same object in order to reduce the global hierarchy // pruneEmptyObjects: remove the objects which do not contains any geometrical entity // tesselate: convert the interior & exteriors polygons to triangles // destSRS: the SRS (WKT, EPSG, OGC URN, etc.) where the coordinates must be transformed, default ("") is no transformation class ParserParams { public: ParserParams() : objectsMask( CityObject::CityObjectsType::COT_All ) , minLOD( 0 ) , maxLOD( 4 ) , optimize( false ) , pruneEmptyObjects( false ) , destSRS( "" ) { } public: CityObjectsTypeMask objectsMask; unsigned int minLOD; unsigned int maxLOD; bool optimize; bool pruneEmptyObjects; bool tesselate; std::string destSRS; }; LIBCITYGML_EXPORT std::shared_ptr load( std::istream& stream, const ParserParams& params, std::shared_ptr logger = nullptr); LIBCITYGML_EXPORT std::shared_ptr load( const std::string& fileName, const ParserParams& params, std::shared_ptr logger = nullptr); } libcitygml-2.0/sources/include/citygml/citygml_api.h.in000066400000000000000000000017551256066205500233660ustar00rootroot00000000000000#define LIBCITYGML_VERSION_MAJOR @META_VERSION_MAJOR@ #define LIBCITYGML_VERSION_MINOR @META_VERSION_MINOR@ #define LIBCITYGML_VERSION_REVISION @META_VERSION_PATCH@ #define LIBCITYGML_CREATE_VERSION_STRING(major,minor,revision) "#major.#minor.#revision" #define LIBCITYGML_VERSIONSTR LIBCITYGML_CREATE_VERSION_STRING(LIBCITYGML_VERSION_MAJOR, LIBCITYGML_VERSION_MINOR, LIBCITYGML_VERSION_REVISION) #define LIBCITYGML_VERSION_LESS(major, minor, revision) major > LIBCITYGML_VERSION_MAJOR || \ (major == LIBCITYGML_VERSION_MAJOR && (minor > LIBCITYGML_VERSION_MINOR || \ (minor == LIBCITYGML_VERSION_MINOR && revision > LIBCITYGML_VERSION_REVISION))) #if defined( _MSC_VER ) && defined( LIBCITYGML_DYNAMIC ) # ifdef LIBCITYGML_BUILD # define LIBCITYGML_EXPORT __declspec( dllexport ) # else # define LIBCITYGML_EXPORT __declspec( dllimport ) # endif #else # define LIBCITYGML_EXPORT #endif libcitygml-2.0/sources/include/citygml/citygmlfactory.h000066400000000000000000000053321256066205500235130ustar00rootroot00000000000000#pragma once #include "citygml/geometry.h" #include "citygml/cityobject.h" #include namespace citygml { class AppearanceManager; class PolygonManager; class GeometryManager; class CityGMLLogger; class CityModel; class AppearanceTarget; class CityObject; class Geometry; class ImplicitGeometry; class Polygon; class LineString; class Appearance; class Texture; class GeoreferencedTexture; class Material; class MaterialTargetDefinition; class TextureTargetDefinition; class CityGMLFactory { public: CityGMLFactory(std::shared_ptr logger); CityModel* createCityModel(const std::string& id); CityObject* createCityObject(const std::string& id, CityObject::CityObjectsType type); Geometry* createGeometry(const std::string& id, const CityObject::CityObjectsType& cityObjType = CityObject::CityObjectsType::COT_All, unsigned int lod = 0); std::shared_ptr createPolygon(const std::string& id); std::shared_ptr createLineString(const std::string& id); /** * @brief requests a polygon for a Geometry object that will be added later * @param geom the Geometry object to which the polygon will be added * @param polygonId the id of the polygon */ void requestSharedPolygonForGeometry(Geometry* geom, const std::string& polygonId); ImplicitGeometry* createImplictGeometry(const std::string& id); std::shared_ptr shareGeometry(Geometry* geom); void requestSharedGeometryWithID(ImplicitGeometry* implicitGeom, const std::string& id); std::shared_ptr createTexture(const std::string& id); std::shared_ptr createMaterial(const std::string& id); std::shared_ptr createGeoReferencedTexture(const std::string& id); std::shared_ptr createMaterialTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id); std::shared_ptr createTextureTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id); std::shared_ptr getAppearanceWithID(const std::string& id); std::vector getAllThemes(); void closeFactory(); ~CityGMLFactory(); protected: void appearanceTargetCreated(AppearanceTarget* obj); std::shared_ptr m_logger; std::unique_ptr m_appearanceManager; std::unique_ptr m_polygonManager; std::unique_ptr m_geometryManager; }; } libcitygml-2.0/sources/include/citygml/citygmllogger.h000066400000000000000000000036751256066205500233330ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class LIBCITYGML_EXPORT CityGMLLogger { public: enum class LOGLEVEL { LL_ERROR, LL_WARNING, LL_INFO, LL_DEBUG, LL_TRACE }; /** * @brief logs a message. Might be called from different threads. */ virtual void log(LOGLEVEL level, const std::string& message, const char* file=nullptr, int line=-1) const = 0; virtual bool isEnabledFor(LOGLEVEL level) const = 0; }; /** * @brief logs a message for a certain log level * @param logger a pointer to a CityGMLLogger * @param level the CityGMLLogger::LOGLEVEL * @param message a string or a stream expression */ #define CITYGML_LOG(logger, level, message) \ do { \ if (logger->isEnabledFor(level)) { \ std::stringstream ss; \ ss << message; \ logger->log(level, ss.str(), __FILE__, __LINE__); \ } \ } while (0); #define CITYGML_LOG_ERROR(logger, message) CITYGML_LOG(logger, citygml::CityGMLLogger::LOGLEVEL::LL_ERROR, message) #define CITYGML_LOG_WARN(logger, message) CITYGML_LOG(logger, citygml::CityGMLLogger::LOGLEVEL::LL_WARNING, message) #define CITYGML_LOG_INFO(logger, message) CITYGML_LOG(logger, citygml::CityGMLLogger::LOGLEVEL::LL_INFO, message) #define CITYGML_LOG_DEBUG(logger, message) CITYGML_LOG(logger, citygml::CityGMLLogger::LOGLEVEL::LL_DEBUG, message) #define CITYGML_LOG_TRACE(logger, message) CITYGML_LOG(logger, citygml::CityGMLLogger::LOGLEVEL::LL_TRACE, message) } libcitygml-2.0/sources/include/citygml/citymodel.h000066400000000000000000000033401256066205500224410ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include namespace citygml { class AppearanceManager; class AppearanceTarget; class CityGMLLogger; class CityObject; class CityGMLFactory; typedef std::vector> CityObjects; typedef std::vector ConstCityObjects; typedef std::map< CityObject::CityObjectsType, std::vector > CityObjectsMap; class LIBCITYGML_EXPORT CityModel : public FeatureObject { friend class CityGMLFactory; public: /** * @brief Return the roots elements of the model. */ const ConstCityObjects getRootCityObjects() const; void addRootObject(CityObject* obj); unsigned int getNumRootCityObjects() const; CityObject& getRootCityObject(int i); const CityObject& getRootCityObject(int i) const; const ConstCityObjects getAllCityObjectsOfType( CityObject::CityObjectsType type ) const; const std::string& getSRSName() const; void finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger); std::vector themes() const; void setThemes(std::vector themes); ~CityModel(); protected: CityModel( const std::string& id = "CityModel"); void addToCityObjectsMapRecursive(const CityObject* cityObj); CityObjects m_roots; CityObjectsMap m_cityObjectsMap; std::string m_srsName; std::vector m_themes; }; std::ostream& operator<<( std::ostream&, const citygml::CityModel & ); } libcitygml-2.0/sources/include/citygml/cityobject.h000066400000000000000000000105221256066205500226070ustar00rootroot00000000000000#pragma once #include #include #include #include class Tesselator; namespace citygml { class ParserParams; class Geometry; class ImplicitGeometry; class Composite; class CityGMLLogger; class AppearanceManager; class Address; class LIBCITYGML_EXPORT CityObject : public FeatureObject { public: enum CityObjectsType { COT_GenericCityObject = 1 << 0, COT_Building = 1 << 1, COT_Room = 1 << 2, COT_BuildingInstallation = 1 << 3, COT_BuildingFurniture = 1 << 4, COT_Door = 1 << 5, COT_Window = 1 << 6, COT_CityFurniture = 1 << 7, COT_Track = 1 << 8, COT_Road = 1 << 9, COT_Railway = 1 << 10, COT_Square = 1 << 11, COT_PlantCover = 1 << 12, COT_SolitaryVegetationObject = 1 << 13, COT_WaterBody = 1 << 14, COT_ReliefFeature = 1 << 15, COT_LandUse = 1 << 16, COT_Tunnel = 1 << 17, COT_Bridge = 1 << 18, COT_BridgeConstructionElement = 1 << 19, COT_BridgeInstallation = 1 << 20, COT_BridgePart = 1 << 21, COT_BuildingPart = 1 << 22, COT_WallSurface = 1 << 23, COT_RoofSurface = 1 << 24, COT_GroundSurface = 1 << 25, COT_ClosureSurface = 1 << 26, COT_FloorSurface = 1 << 27, COT_InteriorWallSurface = 1 << 28, COT_CeilingSurface = 1 << 29, COT_CityObjectGroup = 1 << 30, // covers all supertypes of tran::_TransportationObject that are not Track, Road, Railway or Square... // there are to many for to few bits to explicitly enumerate them. However Track, Road, Railway or Square should be used most of the time COT_TransportationObject = 1 << 31, COT_All = 0xFFFFFFFF }; CityObject( const std::string& id, CityObjectsType type ); // Get the object type CityObjectsType getType() const; std::string getTypeAsString() const; // Get the number of geometries contains in the object unsigned int getGeometriesCount() const; // Access the geometries const Geometry& getGeometry( unsigned int i ) const; Geometry& getGeometry( unsigned int i ); void addGeometry(Geometry* geom); // Get the number of implicit geometries contains in the object unsigned int getImplicitGeometryCount() const; // Access the implicit geometries const ImplicitGeometry& getImplicitGeometry( unsigned int i ) const; ImplicitGeometry& getImplicitGeometry( unsigned int i ); void addImplictGeometry(ImplicitGeometry* implictGeom); // Access the children unsigned int getChildCityObjectsCount() const; const CityObject& getChildCityObject( unsigned int i ) const; CityObject& getChildCityObject( unsigned int i ); void addChildCityObject(CityObject* cityObj); // Access address const Address* address() const; void setAddress(std::unique_ptr
&& address); void finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger); virtual ~CityObject(); protected: CityObjectsType m_type; std::vector> m_geometries; std::vector> m_implicitGeometries; std::vector> m_children; std::unique_ptr
m_address; }; std::ostream& operator<<( std::ostream& os, const CityObject& o ); std::string cityObjectsTypeToString(const CityObject::CityObjectsType& t); CityObject::CityObjectsType cityObjectsTypeFromString(const std::string& s, bool& valid); } libcitygml-2.0/sources/include/citygml/envelope.h000066400000000000000000000021441256066205500222660ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { /** * @brief The Envelope class defines a bounding box in an spatial reference system (gml:Envelope) */ class LIBCITYGML_EXPORT Envelope { public: Envelope(); Envelope(const std::string& srsName); /** * @brief lower left front corner of the bounding box in srs coordinates */ const TVec3d& getLowerBound() const; void setLowerBound(const TVec3d& coordinate); /** * @brief upper right back corner of the bounding box in srs coordinates */ const TVec3d& getUpperBound() const; void setUpperBound(const TVec3d& coordinate); /** * @brief the name of the spatial reference system */ const std::string& srsName() const; const bool validBounds() const; protected: TVec3d m_lowerBound; TVec3d m_upperBound; std::string m_srsName; }; std::ostream& operator<<( std::ostream&, const citygml::Envelope& ); } libcitygml-2.0/sources/include/citygml/featureobject.h000066400000000000000000000006601256066205500232740ustar00rootroot00000000000000#pragma once #include #include "citygml/citygml_api.h" #include "citygml/object.h" namespace citygml { class Envelope; class FeatureObject : public Object { public: FeatureObject(const std::string& gmlID); const Envelope& getEnvelope() const; void setEnvelope(Envelope* e); virtual ~FeatureObject(); protected: std::unique_ptr m_envelope; }; } libcitygml-2.0/sources/include/citygml/geometry.h000066400000000000000000000053001256066205500223010ustar00rootroot00000000000000#pragma once #include #include #include #include #include class Tesselator; namespace citygml { class LineString; class Polygon; class AppearanceManager; class Appearance; class ParserParams; class CityGMLFactory; class CityGMLLogger; class LIBCITYGML_EXPORT Geometry : public AppearanceTarget { friend class CityGMLFactory; public: enum class GeometryType { GT_Unknown = 1 << 0, GT_Roof = 1 << 1, GT_Wall = 1 << 2, GT_Ground = 1 << 3, GT_Closure = 1 << 4, GT_Floor = 1 << 5, GT_InteriorWall = 1 << 6, GT_Ceiling = 1 << 7 }; unsigned int getLOD() const; unsigned int getPolygonsCount() const; std::shared_ptr getPolygon( unsigned int i ); std::shared_ptr getPolygon( unsigned int i ) const; unsigned int getLineStringCount() const; std::shared_ptr getLineString( unsigned int i ); std::shared_ptr getLineString( unsigned int i ) const; unsigned int getGeometriesCount() const; const Geometry& getGeometry( unsigned int i ) const; Geometry& getGeometry( unsigned int i ); void addGeometry(Geometry* geom); GeometryType getType() const; std::string getTypeAsString() const; unsigned int lod() const; void setLod(unsigned int lod); void addPolygon(std::shared_ptr ); void addLineString(std::shared_ptr); /** * @brief finishes the geometry by finishing its child polygons after broadcasting its appearances to all child polygons * @param tesselate determines wether the polygons are tesselated * @param tesselator the tesselator to be used for tesselation * @param mergePolygons determines wether all polygons are merged into one */ void finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger); ~Geometry(); protected: Geometry( const std::string& id, GeometryType type = GeometryType::GT_Unknown, unsigned int lod = 0 ); bool m_finished; GeometryType m_type; unsigned int m_lod; std::vector> m_childGeometries; std::vector> m_polygons; std::vector> m_lineStrings; }; std::ostream& operator<<( std::ostream& os, const citygml::Geometry& s ); } libcitygml-2.0/sources/include/citygml/geometrymanager.h000066400000000000000000000023351256066205500236410ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class ImplicitGeometry; class Geometry; class CityGMLLogger; class GeometryManager { public: GeometryManager(std::shared_ptr logger); void addSharedGeometry(std::shared_ptr geom); /** * @brief the Geometry with id geometryID will be added to geom when finished is called * @param geom the ImplicitGeometry object to which the Geometry object will be added * @param geometryID the id of the Geometry */ void requestSharedGeometryForImplicitGeometry(ImplicitGeometry* geom, const std::string& geometryID); void finish(); ~GeometryManager(); private: struct GeometryRequest { GeometryRequest(ImplicitGeometry* target, std::string geometryID) : target(target), geometryID(geometryID) {} ImplicitGeometry* target; std::string geometryID; }; std::shared_ptr m_logger; std::vector m_geometryRequests; std::unordered_map> m_sharedGeometries; }; } libcitygml-2.0/sources/include/citygml/georeferencedtexture.h000066400000000000000000000014341256066205500246700ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class CityGMLFactory; class LIBCITYGML_EXPORT GeoreferencedTexture : public Texture { friend class CityGMLFactory; public: bool getPreferWorldFile() const; void setPreferWorldFile(bool value); virtual std::shared_ptr asTexture(); virtual std::shared_ptr asTexture() const; virtual std::shared_ptr asGeoreferencedTexture(); virtual std::shared_ptr asGeoreferencedTexture() const; // TODO support referencePoint and orientation protected: GeoreferencedTexture( const std::string& id ); bool m_preferWorldFile; }; } libcitygml-2.0/sources/include/citygml/implictgeometry.h000066400000000000000000000023161256066205500236670ustar00rootroot00000000000000#pragma once #include #include #include #include #include namespace citygml { class Geometry; class CityGMLFactory; class ImplicitGeometry : public Object { friend class CityGMLFactory; public: void setTransformMatrix(const TransformationMatrix matrix); const TransformationMatrix& getTransformMatrix() const; void setReferencePoint(const TVec3d& referencePoint); TVec3d getReferencePoint() const; void addGeometry(std::shared_ptr geom); // Get the number of geometries contains in the object unsigned int getGeometriesCount() const; // Access the geometries Geometry& getGeometry( unsigned int i ) const; // Access the srs of the implicit geometry std::string getSRSName() const; void setSRSName(const std::string& srsName); protected: ImplicitGeometry(const std::string& id); TransformationMatrix m_matrix; TVec3d m_referencePoint; std::vector> m_geometries; std::string m_srsName; }; } libcitygml-2.0/sources/include/citygml/linearring.h000066400000000000000000000016351256066205500226070ustar00rootroot00000000000000#pragma once #include #include #include #include #include namespace citygml { class TextureTargetDefinition; class CityGMLLogger; class LIBCITYGML_EXPORT LinearRing : public Object { public: LinearRing( const std::string& id, bool isExterior ); bool isExterior() const; unsigned int size() const; const std::vector& getVertices() const; std::vector& getVertices(); void setVertices(std::vector vertices); void addVertex( const TVec3d& v ); TVec3d computeNormal() const; void removeDuplicateVertices(const std::vector& targets , std::shared_ptr logger); void forgetVertices(); protected: bool m_exterior; std::vector m_vertices; }; } libcitygml-2.0/sources/include/citygml/linestring.h000066400000000000000000000020111256066205500226200ustar00rootroot00000000000000#pragma once #include #include #include #include #include namespace citygml { class CityGMLFactory; /** * @brief The LineString class implements the gml:LineString object may also be used as a container of a single gml::Point */ class LIBCITYGML_EXPORT LineString : public Object { friend class CityGMLFactory; public: int getDimensions() const; const std::vector& getVertices2D() const; const std::vector& getVertices3D() const; std::vector& getVertices2D(); std::vector& getVertices3D(); void setVertices2D(const std::vector& vertices); void setVertices3D(const std::vector& vertices); void setDimensions(int dim); protected: LineString(const std::string& id); std::vector m_vertices_2d; std::vector m_vertices_3d; int m_dimensions; }; } libcitygml-2.0/sources/include/citygml/material.h000066400000000000000000000030061256066205500222450ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class CityGMLFactory; class LIBCITYGML_EXPORT Material : public Appearance { friend class CityGMLFactory; public: TVec3f getDiffuse() const; void setDiffuse(TVec3f diffuse); TVec3f getEmissive() const; void setEmissive(TVec3f emissive); TVec3f getSpecular() const; void setSpecular(TVec3f specular); float getAmbientIntensity() const; void setAmbientIntensity(float intensity); /** * @brief the shininess of the material * @return a value between 0 and 1, where 1 is the brightest intensity * @note openGL defines the shininess as a value beteen 0 and 128 with 128 beeing the brightest intensity */ float getShininess() const; void setShininess(float shininess); float getTransparency() const; void setTransparency(float transparancy); bool isSmooth() const; void setIsSmooth(bool isSmooth); virtual std::shared_ptr asMaterial() override; virtual std::shared_ptr asMaterial() const override; protected: Material( const std::string& id ); TVec3f m_diffuse; TVec3f m_emissive; TVec3f m_specular; float m_ambientIntensity; float m_shininess; float m_transparency; bool m_isSmooth; }; } libcitygml-2.0/sources/include/citygml/materialtargetdefinition.h000066400000000000000000000010651256066205500255300ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { class CityGMLFactory; /** * @brief The MaterialTargetDefinition associates a material with a target surface. */ class LIBCITYGML_EXPORT MaterialTargetDefinition : public AppearanceTargetDefinition { friend class CityGMLFactory; protected: MaterialTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id); }; } libcitygml-2.0/sources/include/citygml/object.h000066400000000000000000000015571256066205500217260ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { typedef std::map< std::string, std::string > AttributesMap; /** * @brief The base object associated with an unique id and a set of attributes (key-value pairs) */ class LIBCITYGML_EXPORT Object { public: Object( const std::string& id ); const std::string& getId() const; std::string getAttribute( const std::string& name ) const; const AttributesMap& getAttributes() const; AttributesMap& getAttributes(); virtual ~Object() {} void setAttribute(const std::string& name, const std::string& value, bool overwrite = true ); protected: std::string m_id; AttributesMap m_attributes; }; std::ostream& operator<<( std::ostream&, const citygml::Object& ); } libcitygml-2.0/sources/include/citygml/polygon.h000066400000000000000000000117111256066205500221400ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #include #include class Tesselator; namespace citygml { class TextureCoordinates; class CityGMLFactory; class Texture; class Material; /** * @brief The Polygon class implements the functionality of gml::Polygon and gml::SurfacePatch (gml::Rectangle, gml::Triangle) objects */ class LIBCITYGML_EXPORT Polygon : public AppearanceTarget { friend class CityGMLFactory; public: enum class AppearanceSide { FRONT, BACK }; // Get the vertices const std::vector& getVertices() const; std::vector& getVertices(); // Get the indices const std::vector& getIndices() const; /** * @brief returns the material of this polygon for the given theme and side * @param theme a name of an appearance theme * @param front determines for which side the material should be returned (true = front side, false = backside) * @return a Material object or nullptr if there is no material for the theme and side */ std::shared_ptr getMaterialFor(const std::string& theme, bool front) const; /** * @brief returns the material of this polygon for the given theme. Prefers front side materials over back side materials * @param theme a name of an appearance theme * @return a Material object or nullptr if there is no material for the theme */ std::shared_ptr getMaterialFor(const std::string& theme) const; /** * @brief returns the texture of this polygon for the given theme and side * @param theme a name of an appearance theme * @param front determines for which side the texture should be returned (true = front side, false = backside) * @return a Texture object or nullptr if there is no texture for the theme and side */ std::shared_ptr getTextureFor(const std::string& theme, bool front) const; /** * @brief returns the texture of this polygon for the given theme. Prefers front side textures over back side textures * @param theme a name of an appearance theme * @return a Texture object or nullptr if there is no texture for the theme */ std::shared_ptr getTextureFor(const std::string& theme) const; /** * @brief returns the texture coordinates for the given theme and side * @param theme a name of an appearance theme * @param front determines for which side the texture coordinates should be returned (true = front side, false = backside) * @return the texture coordinates or an empty list if there are no texture coordinates for this theme and side */ const std::vector getTexCoordsForTheme(const std::string& theme, bool front) const; bool negNormal() const; void setNegNormal(bool negNormal); void addRing( LinearRing* ); void finish(Tesselator& tesselator , bool optimize, std::shared_ptr logger); virtual ~Polygon(); protected: Polygon( const std::string& id, std::shared_ptr logger ); std::shared_ptr getTextureForTheme(const std::string& theme, bool front) const; /** * @brief fill the vertex array and creates a corresponding index array * @param tesselate if true the tesselator will be used to tesselate the linear rings * @param tesselator the Tesselator object */ void computeIndices(Tesselator& tesselator, std::shared_ptr logger); void createSimpleIndices(std::shared_ptr logger); void createIndicesWithTesselation(Tesselator& tesselator, std::shared_ptr logger); void removeDuplicateVerticesInRings(std::shared_ptr logger); std::vector getTexCoordsForRingAndTheme(const LinearRing& ring, const std::string& theme, bool front); std::vector > getTexCoordListsForRing(const LinearRing& ring, const std::vector& themesFront, const std::vector& themesBack); TVec3d computeNormal(); std::vector m_vertices; std::unordered_map> m_themeToFrontTexCoordsMap; std::unordered_map> m_themeToBackTexCoordsMap; std::vector m_indices; std::unique_ptr m_exteriorRing; std::vector> m_interiorRings; bool m_negNormal; bool m_finished; std::shared_ptr m_logger; }; } libcitygml-2.0/sources/include/citygml/polygonmanager.h000066400000000000000000000022101256066205500234650ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class Polygon; class Geometry; class CityGMLLogger; class PolygonManager { public: PolygonManager(std::shared_ptr logger); void addPolygon(std::shared_ptr poly); /** * @brief the polygon with id polygonID will be added to geom when finished is called * @param geom the geometry object to which the polygon will be added * @param polygonID the id of the polygon */ void requestSharedPolygonForGeometry(Geometry* geom, const std::string& polygonID); void finish(); ~PolygonManager(); private: struct PolygonRequest { PolygonRequest(Geometry* target, std::string polygonID) : target(target), polygonID(polygonID) {} Geometry* target; std::string polygonID; }; std::shared_ptr m_logger; std::vector m_polygonRequests; std::unordered_map> m_sharedPolygons; }; } libcitygml-2.0/sources/include/citygml/tesselator.h000066400000000000000000000050501256066205500226350ustar00rootroot00000000000000/* -*-c++-*- libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #ifndef __TESSELATOR_H__ #define __TESSELATOR_H__ #ifdef WIN32 # include #else # define CALLBACK # define APIENTRY #endif #ifdef __APPLE__ #include #else #include #endif #include "citygml/vecs.hpp" #include #include #include namespace citygml { class CityGMLLogger; } // GLU based polygon tesselator class Tesselator { public: Tesselator( std::shared_ptr logger ); ~Tesselator(); void init(const TVec3d& normal, GLenum winding_rule = GLU_TESS_WINDING_ODD ); /** * @brief Add a new contour - add the exterior ring first, then interiors * @param textureCoordinatesLists a list of texture coordinates lists for the countour. Each list contains one texture coordinate for each vertex. */ void addContour(const std::vector&, std::vector > textureCoordinatesLists); // Let's tesselate! void compute(); // Tesselation result access const std::vector getVertices() const; const std::vector>& getTexCoords() const { return _texCoordsLists; } const std::vector& getIndices() const; private: typedef void (APIENTRY *GLU_TESS_CALLBACK)(); static void CALLBACK beginCallback( GLenum, void* ); static void CALLBACK vertexDataCallback( GLvoid*, void* ); static void CALLBACK combineCallback( GLdouble[3], void* [4], GLfloat [4], void** , void* ); static void CALLBACK endCallback( void* ); static void CALLBACK errorCallback(GLenum, void*); private: GLUtesselator *_tobj; GLenum _curMode; std::list _vertices; std::vector> _texCoordsLists; std::list _indices; std::vector _outIndices; std::vector _curIndices; std::shared_ptr _logger; }; #endif // __TESSELATOR_H__ libcitygml-2.0/sources/include/citygml/texture.h000066400000000000000000000032711256066205500221530ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class CityGMLFactory; class LIBCITYGML_EXPORT Texture : public Appearance { friend class CityGMLFactory; public: enum class WrapMode { WM_NONE, // the resulting color is fully transparent WM_WRAP, // the texture is repeated WM_MIRROR, // the texture is repeated and mirrored WM_CLAMP, // the texture is clamped to its edges WM_BORDER // the resulting color is specified by the borderColor element (RGBA) }; std::string getUrl() const; void setUrl(const std::string& url); bool getRepeat() const; WrapMode getWrapMode() const; void setWrapMode(WrapMode mode); /** * @brief tries to interpret the string as a WrapMode. Does nothing on failure. * @param wrapMode the string e.g. ("WM_NONE") * @return true if the string could be interpreted as a WrapMode, false otherwise */ bool setWrapModeFromString(std::string wrapMode); TVec4f getBorderColor() const; void setBorderColor(TVec4f color); std::string toString() const; virtual std::shared_ptr asTexture() override; virtual std::shared_ptr asTexture() const override; virtual ~Texture(); protected: Texture( const std::string& id ); Texture( const std::string& id, const std::string& type ); std::string m_url; bool m_repeat; WrapMode m_wrapMode; TVec4f m_borderColor; }; } libcitygml-2.0/sources/include/citygml/texturecoordinates.h000066400000000000000000000014661256066205500244120ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include namespace citygml { class LinearRing; /** * @brief The TextureCoordinates class describes a mapping of texture coordinates to the vertices of a linear ring */ class TextureCoordinates : public Object { public: TextureCoordinates(std::string id, std::string targetID); bool targets(const LinearRing& ring) const; std::string getTargetLinearRingID() const; const std::vector& getCoords() const; void setCoords(std::vector texCoords); bool eraseCoordinate(unsigned int i); protected: std::string m_targetID; std::vector m_coordlist; }; } libcitygml-2.0/sources/include/citygml/texturetargetdefinition.h000066400000000000000000000041501256066205500254300ustar00rootroot00000000000000#pragma once #include #include #include #include #include namespace citygml { class TextureCoordinates; class CityGMLFactory; /** * @brief The TextureTargetDefinition associates a texture with a target surface and defines the mapping of the texture. * @note may be shared between different texture objects using the 'xlink:href' attribute. * TextureTargets are applicable only to polygonal surfaces, whose boundaries are described by gml:LinearRing * (e.g. gml:Triangle, gml:Polygon, or a gml:MultiSurface consisting of gml:Polygons). */ class LIBCITYGML_EXPORT TextureTargetDefinition : public AppearanceTargetDefinition { friend class CityGMLFactory; public: /** * @brief the number of TextureCoordinates objects for this texture target */ unsigned int getTextureCoordinatesCount() const; /** * @brief the i-th texture coordinates in texture coordinates list (gml::TexCoordList) */ std::shared_ptr getTextureCoordinates(unsigned int i); std::shared_ptr getTextureCoordinates(unsigned int i) const; /** * @brief the texture coordinates for linear ring with the given id * @return the TextureCoordinates object or nullptr if no such object exists for ringID */ std::shared_ptr getTextureCoordinatesForID(const std::string& ringID); std::shared_ptr getTextureCoordinatesForID(const std::string& ringID) const; void addTexCoordinates(std::shared_ptr texCoords); ~TextureTargetDefinition(); protected: TextureTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id); std::vector> m_coordinatesList; std::unordered_map> m_idTexCoordMap; }; } libcitygml-2.0/sources/include/citygml/transformmatrix.h000066400000000000000000000007001256066205500237050ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class TransformationMatrix : public Object { public: TransformationMatrix(); TransformationMatrix(double* matrix); const double* getMatrix() const; const double* getTransposedMatrix() const; ~TransformationMatrix(); protected: double m_matrix[16]; double m_transposedMatrix[16]; }; } libcitygml-2.0/sources/include/citygml/utils.h000066400000000000000000000044751256066205500216220ustar00rootroot00000000000000/* -*-c++-*- libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #pragma once #include #include #include // Helpers // std::string tokenizer inline std::vector tokenize( const std::string& str, const std::string& delimiters = ",|& " ) { std::vector tokens; std::string::size_type lastPos = str.find_first_not_of( delimiters, 0 ); std::string::size_type pos = str.find_first_of( delimiters, lastPos ); while ( pos != std::string::npos || lastPos != std::string::npos ) { tokens.push_back( str.substr( lastPos, pos - lastPos ) ); lastPos = str.find_first_not_of( delimiters, pos ); pos = str.find_first_of( delimiters, lastPos ); } return tokens; } inline bool ci_string_compare( const std::string& str1, const std::string& str2 ) { std::string s1( str1 ); std::transform( s1.begin(), s1.end(), s1.begin(), ::tolower ); std::string s2( str2 ); std::transform( s2.begin(), s2.end(), s2.begin(), ::tolower ); return s1 == s2; } inline std::string toLower(const std::string& s) { std::string lower = s; std::transform( lower.begin(), lower.end(), lower.begin(), ::tolower ); return lower; } inline std::string trim_left( const std::string& s, const std::string& t = " \t\r\n" ) { std::string d( s ); return d.erase( 0, s.find_first_not_of( t ) ); } inline std::string trim_right( const std::string& s, const std::string& t = " \t\r\n" ) { std::string d( s ); size_t endpos = d.find_last_not_of( t ); return ( endpos != std::string::npos ) ? d.erase( endpos + 1 ) : d; } inline std::string trim( const std::string& s, const std::string& t = " \t\r\n" ) { return trim_left( trim_right( s, t ), t ); } libcitygml-2.0/sources/include/citygml/vecs.hpp000066400000000000000000000200201256066205500217420ustar00rootroot00000000000000#pragma once #include #include #include #include // 2D vector class. template< class T > class TVec2 { public: T x; T y; public: TVec2( const TVec2& o) { this->x = o.x; this->y = o.y; } TVec2( const T x = (T)0, const T y = (T)0 ); TVec2( const T vec[] ); TVec2 operator+( const TVec2& v ) const; TVec2 operator-( const TVec2& v ) const; TVec2 operator-() const; TVec2 operator*( const T& v ) const; TVec2 operator*( const TVec2& v ) const; TVec2 operator/( const T& v ) const; TVec2 operator/( const TVec2& v ) const; bool operator==( const TVec2& v ) const; bool operator!=( const TVec2& v ) const; }; template< class T > inline TVec2::TVec2( const T x, const T y ) { this->x = x; this->y = y; } template< class T > inline TVec2::TVec2( const T vec[] ) { x = vec[0]; y = vec[1]; } template< class T > inline TVec2 TVec2::operator+( const TVec2& v ) const { return TVec2( x + v.x, y + v.y ); } template< class T > inline TVec2 TVec2::operator-( const TVec2& v ) const { return TVec2( x - v.x, y - v.y ); } template< class T > inline TVec2 TVec2::operator-() const { return TVec2( -x, -y ); } template< class T > inline TVec2 TVec2::operator*( const T& v ) const { return TVec2( x * v, y * v ); } template< class T > inline TVec2 TVec2::operator*( const TVec2& v ) const { return TVec2( x * v.x, y * v.y ); } template< class T > inline TVec2 TVec2::operator/( const T& v ) const { return TVec2( x / v, y / v ); } template< class T > inline TVec2 TVec2::operator/( const TVec2& v ) const { return TVec2( x / v.x, y / v.y ); } template< class T > inline bool TVec2::operator==( const TVec2& v ) const { return x == v.x && y == v.y; } template< class T > inline bool TVec2::operator!=( const TVec2& v ) const { return x != v.x || y != v.y; } template< class T > inline TVec2 operator*( const T& val, const TVec2& vec ) { return TVec2( vec.x * val, vec.y * val ); } template inline std::ostream& operator<<(std::ostream & os, TVec2 const & v) { return os << std::fixed << v.x << " " << std::fixed << v.y; } template inline std::istream& operator>>(std::istream & is, TVec2 & v) { return is >> v.x >> v.y; } typedef TVec2< float > TVec2f; typedef TVec2< double > TVec2d; // 3D vector class. template< class T > class TVec3 { public: union { T xyz[3]; T rgb[3]; struct { T x, y, z; }; struct { T r, g, b; }; }; public: TVec3( const T x = (T)0, const T y = (T)0, const T z = (T)0 ); TVec3( const T vec[] ); inline T length() const; inline T sqrLength() const; T dot( const TVec3& vec ) const; TVec3 cross( const TVec3& vec ) const; TVec3 normal() const; TVec3& normalEq(); TVec3& normalEq( const T length ); TVec3 operator+( const TVec3& rhs ) const; TVec3 operator+( const T& _v ) const; TVec3 operator-( const TVec3& rhs ) const; TVec3 operator-( const T& _v ) const; TVec3 operator-() const; TVec3 operator*( const T& rhs ) const; TVec3 operator*( const TVec3& rhs ) const; TVec3 operator/( const T& rhs ) const; TVec3 operator/( const TVec3& rhs ) const; inline bool operator==( const TVec3& rhs ) const; inline bool operator!=( const TVec3& rhs ) const; inline operator T*() { return xyz; } inline operator const T*() const { return xyz; } }; template< class T > inline TVec3::TVec3( const T x, const T y, const T z ) { this->x = x; this->y = y; this->z = z; } template< class T > inline TVec3::TVec3( const T vec[] ) { memcpy( xyz, vec, 3 * sizeof(T) ); } template< class T > inline T TVec3::length() const { return (T)sqrt( x*x + y*y + z*z ); } template< class T > inline T TVec3::sqrLength() const { return x*x + y*y + z*z; } template< class T > inline T TVec3::dot( const TVec3& vec ) const { return x*vec.x + y*vec.y + z*vec.z; } template< class T > inline TVec3 TVec3::cross( const TVec3& vec ) const { return TVec3( y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x ); } template< class T > inline TVec3 TVec3::normal() const { const T len = length(); const T tmp = ( len != (T)0 ) ? ( (T)1 / len ) : (T)0; return TVec3( x * tmp, y * tmp, z * tmp ); } template< class T > inline TVec3& TVec3::normalEq() { const T len = length(); const T tmp = ( len != (T)0 ) ? ( (T)1 / len ) : (T)0; x *= tmp; y *= tmp; z *= tmp; return *this; } template< class T > inline TVec3& TVec3::normalEq( const T length ) { const T len = TVec3::length(); const T tmp = ( len != (T)0 ) ? length / len : (T)0; x *= tmp; y *= tmp; z *= tmp; return *this; } template< class T > inline TVec3 TVec3::operator+( const TVec3& rhs ) const { return TVec3( x + rhs.x, y + rhs.y, z + rhs.z ); } template< class T > inline TVec3 TVec3::operator+( const T& _v ) const { return TVec3( x + _v, y + _v, z + _v ); } template< class T > inline TVec3 TVec3::operator-( const TVec3& rhs ) const { return TVec3( x - rhs.x, y - rhs.y, z - rhs.z ); } template< class T > inline TVec3 TVec3::operator-( const T& _v ) const { return TVec3( x - _v, y - _v, z - _v ); } template< class T > inline TVec3 TVec3::operator-() const { return TVec3( -x, -y, -z ); } template< class T > inline TVec3 TVec3::operator*( const T& rhs ) const { return TVec3( x * rhs, y * rhs, z * rhs ); } template< class T > inline TVec3 TVec3::operator*( const TVec3& rhs ) const { return TVec3( x * rhs.x, y * rhs.y, z * rhs.z ); } template< class T > inline TVec3 TVec3::operator/( const T& rhs ) const { return TVec3( x / rhs, y / rhs, z / rhs ); } template< class T > inline TVec3 TVec3::operator/( const TVec3& rhs ) const { return TVec3( x / rhs.x, y / rhs.y, z / rhs.z ); } template< class T > inline bool TVec3::operator==( const TVec3& rhs ) const { return x == rhs.x && y == rhs.y && z == rhs.z; } template< class T > inline bool TVec3::operator!=( const TVec3& rhs ) const { return x != rhs.x || y != rhs.y || z != rhs.z; } template< class T > inline TVec3 operator*( const T& val, const TVec3& vec ) { return TVec3( vec.x * val, vec.y * val, vec.z * val ); } template inline std::ostream& operator<<(std::ostream & os, const TVec3 & v) { return os << std::fixed << v.x << " " << std::fixed << v.y << " " << std::fixed << v.z; } template inline std::istream& operator>>(std::istream & is, TVec3 & v) { return is >> v.x >> v.y >> v.z; } typedef TVec3< float > TVec3f; typedef TVec3< double > TVec3d; //std::istream& operator>>(std::istream & is, TVec3d & v) //{ // return is >> v.x >> v.y >> v.z; //} //std::istream& operator>>(std::istream & is, TVec3f & v) //{ // return is >> v.x >> v.y >> v.z; //} // 4D vector class. template< class T > class TVec4 { public: union { T xyzw[4]; T rgba[4]; struct { T x, y, z, w; }; struct { T r, g, b, a; }; }; public: TVec4( const T x = (T)0, const T y = (T)0, const T z = (T)0, const T w = (T)0 ) { this->x = x; this->y = y; this->z = z; this->w = w; } TVec4( const T vec[], const T w ) { memcpy( xyzw, vec, 4 * sizeof(T) ); this->w = w; } TVec4( const T vec[] ) { memcpy( xyzw, vec, 4 * sizeof(T) ); } }; template inline std::ostream& operator<<( std::ostream & os, TVec4 const & v ) { return os << std::fixed << v.x << " " << std::fixed << v.y << " " << std::fixed << v.z << " " << std::fixed << v.w; } template inline std::istream& operator>>( std::istream & is, TVec4 & v ) { return is >> v.x >> v.y >> v.z >> v.w; } typedef TVec4< float > TVec4f; typedef TVec4< double > TVec4d; libcitygml-2.0/sources/include/parser/000077500000000000000000000000001256066205500201235ustar00rootroot00000000000000libcitygml-2.0/sources/include/parser/addressparser.h000066400000000000000000000021671256066205500231440ustar00rootroot00000000000000#pragma once #include namespace citygml { class Address; class AddressParser: public CityGMLElementParser { public: using Callback = std::function&&)>; public: AddressParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, const Callback& callback); virtual std::string elementParserName() const override; virtual bool handlesElement(const NodeType::XMLNode& node) const override; protected: virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes ) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters ) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes ) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters ) override; protected: std::unique_ptr
m_address; Callback m_callback; }; } /* namespace citygml */ libcitygml-2.0/sources/include/parser/appearanceelementparser.h000066400000000000000000000024611256066205500251650ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class CityObject; class Appearance; class AppearanceElementParser : public GMLObjectElementParser { public: AppearanceElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: std::vector> m_surfaceDataList; std::shared_ptr m_appearanceObj; std::string m_theme; }; } libcitygml-2.0/sources/include/parser/attributes.h000066400000000000000000000023611256066205500224640ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class CityGMLLogger; class DocumentLocation; /** * @brief The Attributes class provides methods to access the attributes of an xml element */ class Attributes { public: /** * @brief get the value of an attribute * @param attname the name of the attribute * @param defvalue the default value * @return the value of the attribute or defvalue if no such attribute exists */ virtual std::string getAttribute( const std::string& attname, const std::string& defvalue = "" ) const = 0; virtual const DocumentLocation& getDocumentLocation() const = 0; /** * @brief gets the citygml id attribute value or if not present generates a value based on the document location * @return the value of the gml::id attribute or "genID___" if there is no id attribute */ std::string getCityGMLIDAttribute() const; bool hasXLinkAttribute() const; std::string getXLinkValue(); protected: Attributes(std::shared_ptr logger); std::shared_ptr m_logger; }; } libcitygml-2.0/sources/include/parser/citygmldocumentparser.h000066400000000000000000000052611256066205500247240ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { class Attributes; class CityGMLLogger; class DocumentLocation; class CityGMLFactory; class ElementParser; class CityGMLDocumentParser { public: CityGMLDocumentParser(const ParserParams& params, std::shared_ptr logger); std::shared_ptr getModel(); // Methods used by CityGMLElementParser void setCurrentElementParser(ElementParser* parser); void removeCurrentElementParser(const ElementParser* caller); /** * @brief the current location in the document */ virtual const DocumentLocation& getDocumentLocation() const = 0; virtual ~CityGMLDocumentParser(); protected: /** * @brief must be called for each xml element start tag * @param name the name of the xml element * @param attributes the attribut data of the xml element */ void startElement( const std::string& name, Attributes& attributes); /** * @brief must be called for each xml element end tag * @param name the name of the xml element * @param characters the character data of the element or empty string if it contains no charcter data */ void endElement( const std::string& name, const std::string& characters ); /** * @brief must be called at the start of the document */ void startDocument(); /** * @brief must be called at the end of the document */ void endDocument(); std::shared_ptr m_logger; private: void skipUnknownOrUnexpectedElement(const std::string& name); bool checkCurrentElementUnownOrUnexpected_start(const std::string& name); bool checkCurrentElementUnownOrUnexpected_end(const std::string& name); std::stack> m_parserStack; /** * @brief The currently active parser (the one on which startElement or endElement was called last) * * The active parser can remove itself from the stack at any time. Hence we need another shared_ptr reference * to it so that it does not delete itself when removed from the stack. */ std::shared_ptr m_activeParser; std::unique_ptr m_factory; std::shared_ptr m_rootModel; ParserParams m_parserParams; bool m_currentElementUnknownOrUnexpected; int m_unknownElementOrUnexpectedElementDepth; std::string m_unknownElementOrUnexpectedElementName; }; } libcitygml-2.0/sources/include/parser/citygmlelementparser.h000066400000000000000000000076131256066205500245420ustar00rootroot00000000000000#pragma once #include #include #include "parser/elementparser.h" #include "parser/nodetypes.h" namespace citygml { class Attributes; class CityGMLDocumentParser; class CityGMLLogger; class CityGMLFactory; class DocumentLocation; /** * @brief The CityGMLElementParser class is a xml sax parser that is responsible for parsing a specific subset of elements * * The CityGMLDocumentParser uses CityGMLElementParser objects to parse the elements that are found in the document. * Only the CityGMLElementParser objects for the root elements of a citygml document are known by the CityGMLDocumentParser. * Whenever it encounters such an element it delegates the startElement and endElement class to the corresponding CityGMLElementParser object. * A CityGMLElementParser object can itself invoke other CityGMLElementParser objects to parse its child elements. * * After a CityGMLElementParser object has been set as the active element parser by the CityGMLDocumentParser or another CityGMLElementParser (the caller) * it will be bound to the xml element whose start tag is found next by the sax parser. * As soon as the end tag of the bound element is detected the control flow is returned to the caller. * How the result values are shared between caller and callee is up to the concrete implementation. * Usally a callback mechanism is used. */ class CityGMLElementParser : public ElementParser { public: CityGMLElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger); /** * @brief must be called for xml tag that starts a child of the elements handeld by this parser or starts one of the elements itself * @return true if the node was expected otherwise false * @note the CityGMLDocumentParser calls this method */ virtual bool startElement(const NodeType::XMLNode& node, Attributes& attributes) override; /** * @brief must be called for each xml tag that ends a child of the elements handeld by this parser or ends one of the elements itself * @return true if the node was expected otherwise false * @note the CityGMLDocumentParser calls this method */ virtual bool endElement(const NodeType::XMLNode& node, const std::string& characters ) override; virtual ~CityGMLElementParser(); protected: // Template methods to be implemented by subclasses /** * @brief called for the start tag of the element to which the parser is bound * @return true if the node was expected otherwise false */ virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes ) = 0; /** * @brief called for the end tag of the element to which the parser is bound * @return true if the node was expected otherwise false */ virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters ) = 0; /** * @brief called for the start tag of each child inside the element to which the parser is bound * @return true if the node was expected otherwise false */ virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes ) = 0; /** * @brief called for the end tag of each child inside the element to which the parser is bound * @return true if the node was expected otherwise false * @note if a callback mechanism is used to share the result of this parser this method would be the right place to invoke the callback */ virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters ) = 0; CityGMLFactory& m_factory; private: NodeType::XMLNode m_boundElement; }; } libcitygml-2.0/sources/include/parser/citymodelelementparser.h000066400000000000000000000024201256066205500250520ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class CityModel; class CityModelElementParser : public GMLFeatureCollectionElementParser { public: CityModelElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLFeatureCollectionElementParser interface virtual FeatureObject* getFeatureObject() override; private: std::function m_callback; CityModel* m_model; }; } libcitygml-2.0/sources/include/parser/cityobjectelementparser.h000066400000000000000000000040521256066205500252230ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include "citygml/cityobject.h" namespace citygml { class CityObjectElementParser : public GMLFeatureCollectionElementParser { public: CityObjectElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLFeatureCollectionElementParser interface virtual FeatureObject* getFeatureObject() override; private: static void initializeTypeIDTypeMap(); static void initializeAttributesSet(); CityObject* m_model; std::function m_callback; std::string m_lastAttributeName; // The nodes that are valid CityObjects static std::mutex initializedTypeIDMutex; static std::unordered_map typeIDTypeMap; static bool typeIDTypeMapInitialized; static std::mutex initializedAttributeSetMutex; static std::unordered_set attributesSet; static bool attributesSetInitialized; void parseGeometryForLODLevel(int lod); void parseImplicitGeometryForLODLevel(int lod); void parseGeometryPropertyElementForLODLevel(int lod, const std::string& id); }; } libcitygml-2.0/sources/include/parser/delayedchoiceelementparser.h000066400000000000000000000025131256066205500256460ustar00rootroot00000000000000#pragma once #include #include #include "parser/elementparser.h" namespace citygml { /** * @brief The DelayedChoiceElementParser allows to parse xml elements of which the concrete type is not known in advance * * The DelayedChoiceElementParser is initialized with a list of possible parses. When the start element of the next node is parsed it chooses the * first parser that can handle the element. */ class DelayedChoiceElementParser : public ElementParser { public: /** * @brief creates a DelayedChoiceElementParser * @param documentParser * @param logger * @param choices the parsers to choose from. The DelayedChoiceElementParser takes ownership of the parsers. */ DelayedChoiceElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger, std::vector choices); // ElementParser interface virtual bool startElement(const NodeType::XMLNode& node, Attributes& attributes); virtual bool endElement(const NodeType::XMLNode& node, const std::string& characters); virtual bool handlesElement(const NodeType::XMLNode& node) const; virtual std::string elementParserName() const; private: std::vector m_choices; }; } libcitygml-2.0/sources/include/parser/documentlocation.h000066400000000000000000000014671256066205500236530ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { class DocumentLocation { public: virtual const std::string& getDocumentFileName() const = 0; virtual uint64_t getCurrentLine() const = 0; virtual uint64_t getCurrentColumn() const = 0; }; inline std::ostream& operator<<( std::ostream& os, const DocumentLocation& o ) { if (o.getCurrentLine() == 0) { os << " unknown location"; } else { os << " line " << o.getCurrentLine(); if (o.getCurrentColumn() > 0) { os << ", column " << o.getCurrentColumn(); } } if (!o.getDocumentFileName().empty()) { os << " in file " << o.getDocumentFileName(); } return os; } } libcitygml-2.0/sources/include/parser/elementparser.h000066400000000000000000000047331256066205500231510ustar00rootroot00000000000000#pragma once #include #include #include "parser/nodetypes.h" namespace citygml { class Attributes; class CityGMLDocumentParser; class CityGMLLogger; class CityGMLFactory; class DocumentLocation; /** * @brief The ElementParser is the base class for parsers that only handle a specific subset of elements * * For a basic explanation of the parsing process @see CityGMLElementParser */ class ElementParser { public: ElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger) : m_logger(logger), m_documentParser(documentParser) {} /** * @brief must be called for xml tag that starts a child of the elements handeld by this parser or starts one of the elements itself * @return true if the node was expected otherwise false * @note the CityGMLDocumentParser calls this method */ virtual bool startElement(const NodeType::XMLNode& node, Attributes& attributes) = 0; /** * @brief must be called for each xml tag that ends a child of the elements handeld by this parser or ends one of the elements itself * @return true if the node was expected otherwise false * @note the CityGMLDocumentParser calls this method */ virtual bool endElement(const NodeType::XMLNode& node, const std::string& characters ) = 0; /** * @brief returns wether the parser handels elements of type node * @note this is required for the delayed choice mechanism @see DelayedChoiceElementParser * @return true if node is a valid !!root!! element for this parser * (e.g. is valid root element for the appearance parser but is not since its a child element of an appearance) */ virtual bool handlesElement(const NodeType::XMLNode& node) const = 0; /** * @brief the name of the parser (for logging purposes) */ virtual std::string elementParserName() const = 0; virtual ~ElementParser(); protected: /** * @brief sets a parser that will be called for the next element. * @note The parser will be deleted after parsing the elment. */ void setParserForNextElement(ElementParser* parser); virtual const DocumentLocation& getDocumentLocation() const; std::shared_ptr m_logger; CityGMLDocumentParser& m_documentParser; }; } libcitygml-2.0/sources/include/parser/geocoordinatetransformer.h000066400000000000000000000022461256066205500254050ustar00rootroot00000000000000#pragma once #include #include #include class GeoTransform; namespace citygml { class CityGMLLogger; class CityModel; class CityObject; class ImplicitGeometry; class Geometry; class Polygon; class LineString; class GeoCoordinateTransformer { public: GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr logger); void transformToDestinationSRS(CityModel* model); private: std::string m_destinationSRS; std::shared_ptr m_logger; std::unordered_map m_transformedPolygonsSourceURNMap; std::unordered_map m_transformedLineStringsSourceURNMap; void transformRecursive(CityObject& obj, GeoTransform& transformation); void transformRecursive_helper(CityObject& obj, GeoTransform& transformation); void transformRecursive(ImplicitGeometry& obj, GeoTransform& transformation); void transformRecursive_helper(ImplicitGeometry& obj, GeoTransform& transformation); void transform(Geometry& obj, GeoTransform& transformation); }; } libcitygml-2.0/sources/include/parser/geometryelementparser.h000066400000000000000000000027141256066205500247220ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class Geometry; class GeometryElementParser : public GMLObjectElementParser { public: GeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, int lodLevel, CityObject::CityObjectsType parentType, std::function callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: Geometry* m_model; std::function m_callback; int m_lodLevel; CityObject::CityObjectsType m_parentType; std::string m_orientation; }; } libcitygml-2.0/sources/include/parser/georeferencedtextureelementparser.h000066400000000000000000000023251256066205500273030ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { class GeoreferencedTexture; class GeoReferencedTextureElementParser : public CityGMLElementParser { public: GeoReferencedTextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; private: std::function)> m_callback; }; } libcitygml-2.0/sources/include/parser/gmlfeaturecollectionparser.h000066400000000000000000000017541256066205500257270ustar00rootroot00000000000000#pragma once #include namespace citygml { class Envelope; class FeatureObject; /** * @brief abstract base class for all CityGMLElementParser's that parse citygml elements which inherit from gml:AbstractFeatureCollectionType */ class GMLFeatureCollectionElementParser : public GMLObjectElementParser { public: GMLFeatureCollectionElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger); protected: // CityGMLElementParser interface virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual FeatureObject* getFeatureObject() = 0; // GMLObjectElementParser interface virtual Object* getObject() override; private: Envelope* m_bounds; }; } libcitygml-2.0/sources/include/parser/gmlobjectparser.h000066400000000000000000000016101256066205500234550ustar00rootroot00000000000000#pragma once #include namespace citygml { class Object; /** * @brief abstract base class for all CityGMLElementParser's that parse citygml elements which inherit from gml:AbstractGMLType */ class GMLObjectElementParser : public CityGMLElementParser { public: GMLObjectElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger); protected: // CityGMLElementParser interface virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; /** * @brief returns the object in which the parsed information will be stored */ virtual Object* getObject() = 0; }; } libcitygml-2.0/sources/include/parser/implicitgeometryelementparser.h000066400000000000000000000027741256066205500264630ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class ImplicitGeometry; class ImplicitGeometryElementParser : public GMLObjectElementParser { public: ImplicitGeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, int lodLevel, CityObject::CityObjectsType parentType, std::function callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: ImplicitGeometry* m_model; std::function m_callback; int m_lodLevel; CityObject::CityObjectsType m_parentType; std::string m_orientation; }; } libcitygml-2.0/sources/include/parser/linearringelementparser.h000066400000000000000000000024151256066205500252170ustar00rootroot00000000000000#pragma once #include #include namespace citygml { class LinearRing; class LinearRingElementParser : public GMLObjectElementParser { public: LinearRingElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, bool interior, std::function callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: LinearRing* m_model; std::function m_callback; bool m_interior; }; } libcitygml-2.0/sources/include/parser/linestringelementparser.h000066400000000000000000000025351256066205500252460ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { class LineString; class LineStringElementParser : public GMLObjectElementParser { public: LineStringElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: std::shared_ptr m_model; std::function)> m_callback; void parseDimension(Attributes& attributes); }; } libcitygml-2.0/sources/include/parser/materialelementparser.h000066400000000000000000000025231256066205500246630ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class Material; class MaterialElementParser : public GMLObjectElementParser { public: MaterialElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback); // ElementParser interface virtual std::string elementParserName() const; bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: std::shared_ptr m_model; std::function)> m_callback; std::string m_lastTargetDefinitionID; }; } libcitygml-2.0/sources/include/parser/nodetypes.h000066400000000000000000000320351256066205500223110ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class NodeType { public: class XMLNode { public: XMLNode(); XMLNode(std::string prefix, std::string name); const std::string name() const; const std::string& prefix() const; const std::string& baseName() const; int typeID() const; bool operator==(const XMLNode& other) const; bool operator!=(const XMLNode& other) const; bool valid() const; private: std::string m_name; std::string m_prefix; int m_typeID; }; static const XMLNode& getXMLNodeFor(const std::string& name); static const XMLNode InvalidNode; #define NODETYPE( prefix, elementName ) static XMLNode prefix ## _ ## elementName ## Node; // CORE NODETYPE( CORE, CityModel ) NODETYPE( CORE, CityObjectMember ) NODETYPE( CORE, CreationDate ) NODETYPE( CORE, TerminationDate ) NODETYPE( CORE, GeneralizesTo) NODETYPE( CORE, ExternalReference) NODETYPE( CORE, InformationSystem) NODETYPE( CORE, ExternalObject) NODETYPE( CORE, Uri) NODETYPE( CORE, Name) NODETYPE( CORE, Address ) NODETYPE( CORE, XalAddress ) NODETYPE( CORE, ImplicitGeometry ) NODETYPE( CORE, RelativeGMLGeometry ) NODETYPE( CORE, TransformationMatrix ) NODETYPE( CORE, ReferencePoint) NODETYPE( CORE, MimeType) NODETYPE( CORE, LibraryObject) // GRP NODETYPE( GRP, CityObjectGroup ) NODETYPE( GRP, GroupMember ) NODETYPE( GRP, Class ) NODETYPE( GRP, Function ) NODETYPE( GRP, Usage ) NODETYPE( GRP, Parent ) NODETYPE( GRP, Geometry ) // GEN NODETYPE( GEN, Class ) NODETYPE( GEN, Function ) NODETYPE( GEN, Usage ) NODETYPE( GEN, GenericCityObject ) NODETYPE( GEN, StringAttribute ) NODETYPE( GEN, DoubleAttribute ) NODETYPE( GEN, IntAttribute ) NODETYPE( GEN, DateAttribute ) NODETYPE( GEN, UriAttribute ) NODETYPE( GEN, Value ) NODETYPE( GEN, Lod0Geometry ) NODETYPE( GEN, Lod1Geometry ) NODETYPE( GEN, Lod2Geometry ) NODETYPE( GEN, Lod3Geometry ) NODETYPE( GEN, Lod4Geometry ) NODETYPE( GEN, Lod0TerrainIntersection ) NODETYPE( GEN, Lod1TerrainIntersection ) NODETYPE( GEN, Lod2TerrainIntersection ) NODETYPE( GEN, Lod3TerrainIntersection ) NODETYPE( GEN, Lod4TerrainIntersection ) NODETYPE( GEN, Lod0ImplicitRepresentation ) NODETYPE( GEN, Lod1ImplicitRepresentation ) NODETYPE( GEN, Lod2ImplicitRepresentation ) NODETYPE( GEN, Lod3ImplicitRepresentation ) NODETYPE( GEN, Lod4ImplicitRepresentation ) // TEX // NODETYPE( GML, TexturedSurface ) // Deprecated // GML NODETYPE( GML, Description ) NODETYPE( GML, Identifier ) NODETYPE( GML, Name ) NODETYPE( GML, DescriptionReference ) NODETYPE( GML, MetaDataProperty ) NODETYPE( GML, Coordinates ) NODETYPE( GML, Pos ) NODETYPE( GML, BoundedBy ) NODETYPE( GML, Envelope ) NODETYPE( GML, LowerCorner ) NODETYPE( GML, UpperCorner ) NODETYPE( GML, Solid ) NODETYPE( GML, SurfaceMember ) NODETYPE( GML, BaseSurface ) NODETYPE( GML, Patches ) NODETYPE( GML, TrianglePatches ) NODETYPE( GML, SolidMember ) NODETYPE( GML, TriangulatedSurface ) NODETYPE( GML, Triangle ) NODETYPE( GML, Polygon ) NODETYPE( GML, Rectangle ) NODETYPE( GML, PosList ) NODETYPE( GML, OrientableSurface ) NODETYPE( GML, LinearRing ) NODETYPE( GML, MultiPoint ) NODETYPE( GML, MultiCurve ) NODETYPE( GML, MultiSurface ) NODETYPE( GML, MultiSolid ) NODETYPE( GML, CompositeCurve ) NODETYPE( GML, CompositeSurface ) NODETYPE( GML, CompositeSolid ) NODETYPE( GML, ReferencePoint ) NODETYPE( GML, Point ) NODETYPE( GML, Interior ) NODETYPE( GML, Exterior ) NODETYPE( GML, Shell ) NODETYPE( GML, PolyhedralSurface ) NODETYPE( GML, Surface ) NODETYPE( GML, PolygonPatch) NODETYPE( GML, LineString ) // BLDG NODETYPE( BLDG, Building ) NODETYPE( BLDG, BuildingPart ) NODETYPE( BLDG, Room ) NODETYPE( BLDG, Door ) NODETYPE( BLDG, Window ) NODETYPE( BLDG, BuildingInstallation ) NODETYPE( BLDG, MeasuredHeight ) NODETYPE( BLDG, Class ) NODETYPE( BLDG, Type ) NODETYPE( BLDG, Function ) NODETYPE( BLDG, Usage ) NODETYPE( BLDG, YearOfConstruction ) NODETYPE( BLDG, YearOfDemolition ) NODETYPE( BLDG, StoreysAboveGround ) NODETYPE( BLDG, StoreysBelowGround ) NODETYPE( BLDG, StoreyHeightsAboveGround ) NODETYPE( BLDG, StoreyHeightsBelowGround ) NODETYPE( BLDG, BoundedBy ) NODETYPE( BLDG, OuterBuildingInstallation) NODETYPE( BLDG, InteriorBuildingInstallation) NODETYPE( BLDG, InteriorRoom) NODETYPE( BLDG, InteriorFurniture) NODETYPE( BLDG, RoomInstallation) NODETYPE( BLDG, Opening) NODETYPE( BLDG, RoofType) NODETYPE( BLDG, Lod1Solid ) NODETYPE( BLDG, Lod2Solid ) NODETYPE( BLDG, Lod3Solid ) NODETYPE( BLDG, Lod4Solid ) NODETYPE( BLDG, Lod2Geometry ) NODETYPE( BLDG, Lod3Geometry ) NODETYPE( BLDG, Lod4Geometry ) NODETYPE( BLDG, Lod1MultiCurve ) NODETYPE( BLDG, Lod2MultiCurve ) NODETYPE( BLDG, Lod3MultiCurve ) NODETYPE( BLDG, Lod4MultiCurve ) NODETYPE( BLDG, Lod1MultiSurface ) NODETYPE( BLDG, Lod2MultiSurface ) NODETYPE( BLDG, Lod3MultiSurface ) NODETYPE( BLDG, Lod4MultiSurface ) NODETYPE( BLDG, Lod1TerrainIntersection ) NODETYPE( BLDG, Lod2TerrainIntersection ) NODETYPE( BLDG, Lod3TerrainIntersection ) NODETYPE( BLDG, Lod4TerrainIntersection ) NODETYPE( BLDG, ConsistsOfBuildingPart ) // BoundarySurfaceType NODETYPE( BLDG, WallSurface ) NODETYPE( BLDG, RoofSurface ) NODETYPE( BLDG, GroundSurface ) NODETYPE( BLDG, ClosureSurface ) NODETYPE( BLDG, FloorSurface ) NODETYPE( BLDG, InteriorWallSurface ) NODETYPE( BLDG, CeilingSurface ) NODETYPE( BLDG, BuildingFurniture ) NODETYPE( BLDG, CityFurniture ) NODETYPE( BLDG, Address) // CityFurniture NODETYPE( FRN, Class ) NODETYPE( FRN, Function ) NODETYPE( FRN, CityFurniture ) NODETYPE( FRN, Lod1Geometry ) NODETYPE( FRN, Lod2Geometry ) NODETYPE( FRN, Lod3Geometry ) NODETYPE( FRN, Lod4Geometry ) NODETYPE( FRN, Lod1TerrainIntersection ) NODETYPE( FRN, Lod2TerrainIntersection ) NODETYPE( FRN, Lod3TerrainIntersection ) NODETYPE( FRN, Lod4TerrainIntersection ) NODETYPE( FRN, Lod1ImplicitRepresentation ) NODETYPE( FRN, Lod2ImplicitRepresentation ) NODETYPE( FRN, Lod3ImplicitRepresentation ) NODETYPE( FRN, Lod4ImplicitRepresentation ) // ADDRESS NODETYPE( XAL, AddressDetails ) NODETYPE( XAL, Country ) NODETYPE( XAL, CountryName ) NODETYPE( XAL, CountryNameCode ) NODETYPE( XAL, AdministrativeArea ) NODETYPE( XAL, AdministrativeAreaName ) NODETYPE( XAL, Locality ) NODETYPE( XAL, LocalityName ) NODETYPE( XAL, PostalCode ) NODETYPE( XAL, PostalCodeNumber ) NODETYPE( XAL, Thoroughfare ) NODETYPE( XAL, ThoroughfareName ) NODETYPE( XAL, ThoroughfareNumber ) // WTR NODETYPE( WTR, WaterBody ) NODETYPE( WTR, WaterSurface ) NODETYPE( WTR, WaterGroundSurface ) NODETYPE( WTR, WaterClosureSurface ) NODETYPE( WTR, Class ) NODETYPE( WTR, Function ) NODETYPE( WTR, Usage ) NODETYPE( WTR, WaterLevel ) NODETYPE( WTR, Lod0MultiCurve ) NODETYPE( WTR, Lod0MultiSurface ) NODETYPE( WTR, Lod1MultiCurve ) NODETYPE( WTR, Lod1MultiSurface ) NODETYPE( WTR, Lod1Solid ) NODETYPE( WTR, Lod2Solid ) NODETYPE( WTR, Lod3Solid ) NODETYPE( WTR, Lod4Solid ) NODETYPE( WTR, Lod2Surface ) NODETYPE( WTR, Lod3Surface ) NODETYPE( WTR, Lod4Surface ) NODETYPE( WTR, BoundedBy ) // VEG NODETYPE( VEG, PlantCover ) NODETYPE( VEG, SolitaryVegetationObject ) NODETYPE( VEG, Lod1ImplicitRepresentation ) NODETYPE( VEG, Lod2ImplicitRepresentation ) NODETYPE( VEG, Lod3ImplicitRepresentation ) NODETYPE( VEG, Lod4ImplicitRepresentation ) NODETYPE( VEG, Class ) NODETYPE( VEG, Function ) NODETYPE( VEG, AverageHeight ) NODETYPE( VEG, Species ) NODETYPE( VEG, Height ) NODETYPE( VEG, TrunkDiameter ) NODETYPE( VEG, CrownDiameter ) NODETYPE( VEG, Lod0Geometry ) NODETYPE( VEG, Lod1Geometry ) NODETYPE( VEG, Lod2Geometry ) NODETYPE( VEG, Lod3Geometry ) NODETYPE( VEG, Lod4Geometry ) // TRANS NODETYPE( TRANS, TransportationComplex ) NODETYPE( TRANS, TrafficArea ) NODETYPE( TRANS, AuxiliaryTrafficArea ) NODETYPE( TRANS, Track ) NODETYPE( TRANS, Road ) NODETYPE( TRANS, Railway ) NODETYPE( TRANS, Square ) NODETYPE( TRANS, Usage ) NODETYPE( TRANS, Function ) NODETYPE( TRANS, SurfaceMaterial ) NODETYPE( TRANS, Lod0Network ) NODETYPE( TRANS, Lod1MultiSurface ) NODETYPE( TRANS, Lod2MultiSurface ) NODETYPE( TRANS, Lod3MultiSurface ) NODETYPE( TRANS, Lod4MultiSurface ) // LUSE NODETYPE( LUSE, LandUse ) NODETYPE( LUSE, Class ) NODETYPE( LUSE, Usage ) NODETYPE( LUSE, Function ) NODETYPE( LUSE, Lod1MultiSurface ) NODETYPE( LUSE, Lod2MultiSurface ) NODETYPE( LUSE, Lod3MultiSurface ) NODETYPE( LUSE, Lod4MultiSurface ) // DEM (Relief) NODETYPE( DEM, ReliefFeature ) NODETYPE( DEM, TINRelief ) NODETYPE( DEM, RasterRelief ) NODETYPE( DEM, MassPointRelief ) NODETYPE( DEM, BreaklineRelief ) NODETYPE( DEM, Lod ) NODETYPE( DEM, Extent ) NODETYPE( DEM, ReliefComponent ) NODETYPE( DEM, Tin ) NODETYPE( DEM, Grid ) NODETYPE( DEM, ReliefPoints ) NODETYPE( DEM, RidgeOrValleyLines ) NODETYPE( DEM, Breaklines ) NODETYPE( DEM, Elevation ) // SUB NODETYPE( SUB, Tunnel ) NODETYPE( SUB, RelativeToTerrain ) // BRID NODETYPE( BRID, Bridge ) NODETYPE( BRID, BridgeConstructionElement ) NODETYPE( BRID, BridgeInstallation ) NODETYPE( BRID, BridgePart ) // APP NODETYPE( APP, Appearance ) NODETYPE( APP, AppearanceMember ) NODETYPE( APP, SimpleTexture ) NODETYPE( APP, ParameterizedTexture ) NODETYPE( APP, GeoreferencedTexture ) NODETYPE( APP, ImageURI ) NODETYPE( APP, TextureMap ) NODETYPE( APP, Target ) NODETYPE( APP, TexCoordList ) NODETYPE( APP, TexCoordGen ) NODETYPE( APP, TextureCoordinates ) NODETYPE( APP, WorldToTexture ) NODETYPE( APP, TextureType ) NODETYPE( APP, Repeat ) NODETYPE( APP, WrapMode ) NODETYPE( APP, BorderColor ) NODETYPE( APP, PreferWorldFile ) NODETYPE( APP, ReferencePoint) NODETYPE( APP, Orientation) NODETYPE( APP, isSmooth) NODETYPE( APP, X3DMaterial ) NODETYPE( APP, Material ) NODETYPE( APP, SurfaceDataMember ) NODETYPE( APP, Shininess ) NODETYPE( APP, Transparency ) NODETYPE( APP, SpecularColor ) NODETYPE( APP, DiffuseColor ) NODETYPE( APP, EmissiveColor ) NODETYPE( APP, AmbientIntensity ) NODETYPE( APP, IsFront ) NODETYPE( APP, Theme ) NODETYPE( APP, MimeType ) private: static void initializeNodeTypes(); static std::mutex initializedMutex; static bool nodesInitialized; static int typeCount; static std::unordered_map nodeNameTypeMap; static std::unordered_map nodeNameWithPrefixTypeMap; }; std::ostream& operator<<( std::ostream& os, const NodeType::XMLNode& o ); } namespace std { template <> struct hash { size_t operator()(const citygml::NodeType::XMLNode& node) const { return node.typeID(); } }; template <> struct hash { size_t operator()(const citygml::NodeType::XMLNode& node) const { return node.typeID(); } }; } // namespace std libcitygml-2.0/sources/include/parser/parserutils.hpp000066400000000000000000000053331256066205500232150ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #include namespace citygml { template inline T parseValue( const std::string &s, std::shared_ptr&, const DocumentLocation&) { std::stringstream ss; ss << s; T v; ss >> v; return v; } inline TransformationMatrix parseMatrix( const std::string &s, std::shared_ptr& logger, const DocumentLocation& location) { std::stringstream ss; ss << s; double matrix[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 }; for (size_t i = 0; i < 16; ++i) { if(ss.eof()) { CITYGML_LOG_WARN(logger, "Matrix with 16 elements expected, got '" << i + 1 << "' at " << location << ". Matrix may be invalid."); break; } ss >> matrix[i]; } return TransformationMatrix(matrix); } template<> inline bool parseValue( const std::string &s, std::shared_ptr& logger, const DocumentLocation& location ) { // parsing a bool is special because "true" and "1" are true while "false" and "0" are false if (s == "1" || s == "true") { return true; } else if (s == "0" || s == "false") { return false; } else { CITYGML_LOG_WARN(logger, "Boolean expected, got '" << s << "' at " << location << " set value to false."); } return false; } template inline std::vector parseVecList( const std::string &s, std::shared_ptr& logger, const DocumentLocation& location ) { std::stringstream ss; ss << s; T v; std::vector vec; while ( ss >> v ) vec.push_back( v ); if ( !ss.eof() ) { CITYGML_LOG_WARN(logger, "Mismatch type, list of " << typeid(T).name() << " expected at " << location << " Ring/Polygon may be incomplete!"); } return vec; } inline std::string parseReference(const std::string& reference, std::shared_ptr& logger, const DocumentLocation& location) { if (reference.empty()) { CITYGML_LOG_WARN(logger, "Invalid reference value at " << location); } if (reference[0] == '#') { return reference.substr(1); } else { return reference; } } } libcitygml-2.0/sources/include/parser/polygonelementparser.h000066400000000000000000000025041256066205500245530ustar00rootroot00000000000000#pragma once #include #include #include namespace citygml { class Polygon; class PolygonElementParser : public GMLObjectElementParser { public: PolygonElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: std::shared_ptr m_model; std::function)> m_callback; void parseRingElement(bool interior); }; } libcitygml-2.0/sources/include/parser/sequenceparser.h000066400000000000000000000034171256066205500233260ustar00rootroot00000000000000#pragma once #include #include #include #include "parser/citygmlelementparser.h" namespace citygml { /** * @brief The SequenceParser parses a sequence of elements * * The sequence parser can be used if an xml element can contain more than one child elements. If a * parser finds the start tag of such an element (e.g. ) it can invoke the sequence parser, which * in turn calls a predefined parser for each child until the end tag of the element is found. */ class SequenceParser : public ElementParser { public: /** * @brief initializes the parser for an element that can contain multiple children * @param documentParser the CityGMLDocumentParser instance * @param logger a CityGMLLogger logger instance * @param childParserFactory a factory for the parser for the child elements * @param parentElement the element that contains the child objects */ SequenceParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger, std::function childParserFactory, const NodeType::XMLNode& parentElement); // ElementParser interface virtual bool startElement(const NodeType::XMLNode& node, Attributes& attributes); virtual bool endElement(const NodeType::XMLNode& node, const std::string& characters); virtual bool handlesElement(const NodeType::XMLNode& node) const; virtual std::string elementParserName() const; private: std::function m_childParserFactory; mutable std::unique_ptr m_childParserInstance; NodeType::XMLNode m_containerType; ElementParser& getChildParserDummyInstance() const; }; } libcitygml-2.0/sources/include/parser/skipelementparser.h000066400000000000000000000031421256066205500240310ustar00rootroot00000000000000#pragma once #include namespace citygml { /** * @brief A parser that just skips over the element (and all its child elements) for which it was called * @note The SkipElementParser can be called for the content of an element that might be empty. In * that case the SkipElementParser will return control to the calling parser after the end element of that element was parsed. * Hence the the calling parser should not expect to parse the end element. */ class SkipElementParser : public ElementParser { public: /** * @brief initializes the SkipElementParser * @param skipNode if a valid node is passed the skip parser is bound to that node and skips all its children. * In that case the start tag of the node must already been parsed. * If the node is not valid (Default) the skip parser will be bound to the first element it encounters. */ SkipElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger, const NodeType::XMLNode& skipNode = NodeType::XMLNode()); // ElementParser interface virtual std::string elementParserName() const override; virtual bool handlesElement(const NodeType::XMLNode &node) const override; virtual bool startElement(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool endElement(const NodeType::XMLNode& node, const std::string& characters) override; private: NodeType::XMLNode m_skipNode; int m_depth; }; } libcitygml-2.0/sources/include/parser/textureelementparser.h000066400000000000000000000027611256066205500245710ustar00rootroot00000000000000#pragma once #include #include #include #include namespace citygml { class Texture; class TextureTargetDefinition; class TextureCoordinates; class TextureElementParser : public GMLObjectElementParser { public: TextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback); // ElementParser interface virtual std::string elementParserName() const; virtual bool handlesElement(const NodeType::XMLNode &node) const override; protected: // CityGMLElementParser interface virtual bool parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; virtual bool parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) override; virtual bool parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) override; // GMLObjectElementParser interface virtual Object* getObject() override; private: std::shared_ptr m_model; std::function)> m_callback; std::shared_ptr m_currentTexTargetDef; std::shared_ptr m_currentTexCoords; }; } libcitygml-2.0/sources/src/000077500000000000000000000000001256066205500157735ustar00rootroot00000000000000libcitygml-2.0/sources/src/citygml/000077500000000000000000000000001256066205500174435ustar00rootroot00000000000000libcitygml-2.0/sources/src/citygml/address.cpp000066400000000000000000000022411256066205500215730ustar00rootroot00000000000000#include namespace citygml { Address::Address(const std::string& id) : Object(id) { } const std::string& Address::country() const { return m_country; } void Address::setCountry(const std::string& country) { m_country = country; } const std::string& Address::locality() const { return m_locality; } void Address::setLocality(const std::string& locality) { m_locality = locality; } const std::string& Address::postalCode() const { return m_postalCode; } void Address::setPostalCode(const std::string& postalCode) { m_postalCode = postalCode; } const std::string& Address::thoroughfareName() const { return m_thoroughfareName; } void Address::setThoroughfareName(const std::string& thoroughfareName) { m_thoroughfareName = thoroughfareName; } const std::string& Address::thoroughfareNumber() const { return m_thoroughfareNumber; } void Address::setThoroughfareNumber(const std::string& thoroughfareNumber) { m_thoroughfareNumber = thoroughfareNumber; } } /* namespace citygml */ libcitygml-2.0/sources/src/citygml/appearance.cpp000066400000000000000000000030701256066205500222460ustar00rootroot00000000000000#include "citygml/appearance.h" #include namespace citygml { Appearance::Appearance(const std::string& id, const std::string& typeString) : Object( id ), m_typeString( typeString ), m_isFront(true) { } std::string Appearance::getType() const { return m_typeString; } bool Appearance::getIsFront() const { return m_isFront; } void Appearance::setIsFront(bool front) { m_isFront = front; } std::string Appearance::toString() const { return m_typeString + " " + m_id; } std::shared_ptr Appearance::asMaterial() { return nullptr; } std::shared_ptr Appearance::asMaterial() const { return nullptr; } std::shared_ptr Appearance::asTexture() { return nullptr; } std::shared_ptr Appearance::asTexture() const { return nullptr; } std::shared_ptr Appearance::asGeoreferencedTexture() { return nullptr; } std::shared_ptr Appearance::asGeoreferencedTexture() const { return nullptr; } bool Appearance::inTheme(const std::string& themeName) const { return std::find(m_themes.begin(), m_themes.end(), themeName) != m_themes.end(); } void Appearance::addToTheme(std::string themeName) { m_themes.push_back(themeName); } const std::vector& Appearance::getThemes() const { return m_themes; } } libcitygml-2.0/sources/src/citygml/appearancemanager.cpp000066400000000000000000000071021256066205500236010ustar00rootroot00000000000000#include "citygml/appearancemanager.h" #include "citygml/appearance.h" #include "citygml/appearancetarget.h" #include "citygml/citygmllogger.h" #include "citygml/materialtargetdefinition.h" #include "citygml/texturetargetdefinition.h" namespace citygml { AppearanceManager::AppearanceManager(std::shared_ptr logger) { m_logger = logger; } AppearanceManager::~AppearanceManager() { } std::shared_ptr AppearanceManager::getAppearanceByID(const std::string& id) const { auto it = m_appearancesMap.find(id); if (it == m_appearancesMap.end()) { return nullptr; } return it->second; } std::vector AppearanceManager::getAllThemes() { std::vector themes(m_themes.begin(), m_themes.end()); return themes; } void AppearanceManager::addAppearanceTarget(AppearanceTarget* target) { m_appearanceTargetsMap[target->getId()] = target; } void AppearanceManager::addAppearance(std::shared_ptr appearance) { m_appearancesMap[appearance->getId()] = appearance; } void AppearanceManager::addTextureTargetDefinition(std::shared_ptr targetDef) { m_texTargetDefinitions.push_back(targetDef); } void AppearanceManager::addMaterialTargetDefinition(std::shared_ptr targetDef) { m_materialTargetDefinitions.push_back(targetDef); } template void assignTargetDefinition(std::shared_ptr& targetDef, const std::unordered_map& targetMap, std::shared_ptr& logger) { std::string targetID = targetDef->getTargetID(); auto it = targetMap.find(targetID); if (it == targetMap.end()) { CITYGML_LOG_WARN(logger, "Appearance with id '" << targetDef->getAppearance()->getId() << "' targets object with id " << targetID << " but no such object exists."); } else { it->second->addTargetDefinition(targetDef); } } void AppearanceManager::assignAppearancesToTargets() { CITYGML_LOG_INFO(m_logger, "Start assignment of appearances to targets (" << m_materialTargetDefinitions.size() << " material target definition(s), " << m_texTargetDefinitions.size() << " texture target definition(s))."); for (std::shared_ptr& targetDef : m_materialTargetDefinitions ) { assignTargetDefinition(targetDef, m_appearanceTargetsMap, m_logger); addThemesFrom(targetDef->getAppearance()); } for (std::shared_ptr& targetDef : m_texTargetDefinitions ) { assignTargetDefinition(targetDef, m_appearanceTargetsMap, m_logger); addThemesFrom(targetDef->getAppearance()); } m_materialTargetDefinitions.clear(); m_texTargetDefinitions.clear(); m_appearanceTargetsMap.clear(); m_appearancesMap.clear(); CITYGML_LOG_INFO(m_logger, "Finished assignment of appearances to targets (" << m_materialTargetDefinitions.size() << " material target definition(s), " << m_texTargetDefinitions.size() << " texture target definition(s))."); } void AppearanceManager::addThemesFrom(std::shared_ptr surfaceData) { m_themes.insert(surfaceData->getThemes().begin(), surfaceData->getThemes().end()); } } libcitygml-2.0/sources/src/citygml/appearancetarget.cpp000066400000000000000000000112161256066205500234560ustar00rootroot00000000000000#include "citygml/appearancetarget.h" #include "citygml/texturetargetdefinition.h" #include "citygml/materialtargetdefinition.h" #include "citygml/appearancetargetdefinition.h" #include "citygml/appearance.h" #include #include namespace citygml { AppearanceTarget::AppearanceTarget(const std::string& id) : Object(id) { } void AppearanceTarget::addTargetDefinition(std::shared_ptr > targetDef) { if (targetDef->getAppearance()->asMaterial() != nullptr) { addTargetDefinition(std::dynamic_pointer_cast(targetDef)); } else { addTargetDefinition(std::dynamic_pointer_cast(targetDef)); } } void AppearanceTarget::addTargetDefinition(std::shared_ptr targetDef) { for (const std::string& theme : targetDef->getAppearance()->getThemes()) { if (targetDef->getAppearance()->getIsFront() && m_themeTexMapFront.count(theme) == 0) { m_themeTexMapFront[theme] = targetDef; } else if (!targetDef->getAppearance()->getIsFront() && m_themeTexMapBack.count(theme) == 0) { m_themeTexMapBack[theme] = targetDef; } } } void AppearanceTarget::addTargetDefinition(std::shared_ptr targetDef) { for (const std::string& theme : targetDef->getAppearance()->getThemes()) { if (targetDef->getAppearance()->getIsFront() && m_themeMatMapFront.count(theme) == 0) { m_themeMatMapFront[theme] = targetDef; } else if (!targetDef->getAppearance()->getIsFront() && m_themeMatMapBack.count(theme) == 0) { m_themeMatMapBack[theme] = targetDef; } } } void AppearanceTarget::addTargetDefinitionsOf(const AppearanceTarget& other) { // Insert the TargetDefinitions of the other AppearanceTarget that belong to a themes for which this AppearanceTarget contains no TargetDefinitions m_themeMatMapFront.insert(other.m_themeMatMapFront.begin(), other.m_themeMatMapFront.end()); m_themeMatMapBack.insert(other.m_themeMatMapBack.begin(), other.m_themeMatMapBack.end()); m_themeTexMapFront.insert(other.m_themeTexMapFront.begin(), other.m_themeTexMapFront.end()); m_themeTexMapBack.insert(other.m_themeTexMapBack.begin(), other.m_themeTexMapBack.end()); } std::shared_ptr AppearanceTarget::getMaterialTargetDefinitionForTheme(const std::string& theme, bool front) { auto& map = front ? m_themeMatMapFront : m_themeMatMapBack; auto it = map.find(theme); if (it == map.end()) { return nullptr; } return it->second; } std::shared_ptr AppearanceTarget::getMaterialTargetDefinitionForTheme(const std::string& theme, bool front) const { auto& map = front ? m_themeMatMapFront : m_themeMatMapBack; const auto it = map.find(theme); if (it == map.end()) { return nullptr; } return it->second; } std::shared_ptr AppearanceTarget::getTextureTargetDefinitionForTheme(const std::string& theme, bool front) { auto& map = front ? m_themeTexMapFront : m_themeTexMapBack; auto it = map.find(theme); if (it == map.end()) { return nullptr; } return it->second; } std::shared_ptr AppearanceTarget::getTextureTargetDefinitionForTheme(const std::string& theme, bool front) const { auto& map = front ? m_themeTexMapFront : m_themeTexMapBack; const auto it = map.find(theme); if (it == map.end()) { return nullptr; } return it->second; } std::vector AppearanceTarget::getTextureTargetDefinitions() { std::unordered_set texTargetDefs; for (auto& pair : m_themeTexMapFront) { texTargetDefs.insert(pair.second.get()); } for (auto& pair : m_themeTexMapBack) { texTargetDefs.insert(pair.second.get()); } return std::vector(texTargetDefs.begin(), texTargetDefs.end()); } std::vector AppearanceTarget::getAllTextureThemes(bool front) const { auto& map = front ? m_themeTexMapFront : m_themeTexMapBack; std::vector themes; for (const auto& pair : map) { themes.push_back(pair.first); } return themes; } } libcitygml-2.0/sources/src/citygml/citygmlfactory.cpp000066400000000000000000000143571256066205500232210ustar00rootroot00000000000000#include "citygml/citygmlfactory.h" #include "citygml/appearancemanager.h" #include "citygml/polygonmanager.h" #include "citygml/geometrymanager.h" #include "citygml/cityobject.h" #include "citygml/appearancetarget.h" #include "citygml/polygon.h" #include "citygml/linestring.h" #include "citygml/implictgeometry.h" #include "citygml/texture.h" #include "citygml/georeferencedtexture.h" #include "citygml/material.h" #include "citygml/materialtargetdefinition.h" #include "citygml/texturetargetdefinition.h" #include "citygml/citymodel.h" #include "citygml/implictgeometry.h" #include "citygml/citygmllogger.h" namespace citygml { CityGMLFactory::CityGMLFactory(std::shared_ptr logger) { m_appearanceManager = std::unique_ptr(new AppearanceManager(logger)); m_polygonManager = std::unique_ptr(new PolygonManager(logger)); m_geometryManager = std::unique_ptr(new GeometryManager(logger)); m_logger = logger; } CityModel* CityGMLFactory::createCityModel(const std::string& id) { return new CityModel(id); } CityObject* CityGMLFactory::createCityObject(const std::string& id, CityObject::CityObjectsType type) { CityObject* cityObject = new CityObject(id, type); return cityObject; } Geometry::GeometryType mapCityObjectsTypeToGeometryType(const CityObject::CityObjectsType& cityObjType) { switch (cityObjType) { case CityObject::CityObjectsType::COT_RoofSurface: return Geometry::GeometryType::GT_Roof; case CityObject::CityObjectsType::COT_WallSurface: return Geometry::GeometryType::GT_Wall; case CityObject::CityObjectsType::COT_GroundSurface: return Geometry::GeometryType::GT_Ground; case CityObject::CityObjectsType::COT_ClosureSurface: return Geometry::GeometryType::GT_Closure; case CityObject::CityObjectsType::COT_FloorSurface: return Geometry::GeometryType::GT_Floor; case CityObject::CityObjectsType::COT_InteriorWallSurface: return Geometry::GeometryType::GT_InteriorWall; case CityObject::CityObjectsType::COT_CeilingSurface: return Geometry::GeometryType::GT_Ceiling; default: return Geometry::GeometryType::GT_Unknown; } } Geometry* CityGMLFactory::createGeometry(const std::string& id, const CityObject::CityObjectsType& cityObjType, unsigned int lod) { Geometry* geom = new Geometry(id, mapCityObjectsTypeToGeometryType(cityObjType), lod); appearanceTargetCreated(geom); return geom; } std::shared_ptr CityGMLFactory::createPolygon(const std::string& id) { Polygon* poly = new Polygon(id, m_logger); appearanceTargetCreated(poly); std::shared_ptr shared = std::shared_ptr(poly); m_polygonManager->addPolygon(shared); return shared; } std::shared_ptr CityGMLFactory::createLineString(const std::string& id) { LineString* lineString = new LineString(id); return std::shared_ptr(lineString); } void CityGMLFactory::requestSharedPolygonForGeometry(Geometry* geom, const std::string& polygonId) { m_polygonManager->requestSharedPolygonForGeometry(geom, polygonId); } ImplicitGeometry *CityGMLFactory::createImplictGeometry(const std::string& id) { return new ImplicitGeometry(id); } std::shared_ptr CityGMLFactory::shareGeometry(Geometry* geom) { std::shared_ptr shared = std::shared_ptr(geom); m_geometryManager->addSharedGeometry(shared); return shared; } void CityGMLFactory::requestSharedGeometryWithID(ImplicitGeometry* implicitGeom, const std::string& id) { m_geometryManager->requestSharedGeometryForImplicitGeometry(implicitGeom, id); } std::shared_ptr CityGMLFactory::createTexture(const std::string& id) { std::shared_ptr tex = std::shared_ptr(new Texture(id)); m_appearanceManager->addAppearance(tex); return tex; } std::shared_ptr CityGMLFactory::createMaterial(const std::string& id) { std::shared_ptr mat = std::shared_ptr(new Material(id)); m_appearanceManager->addAppearance(mat); return mat; } std::shared_ptr CityGMLFactory::createGeoReferencedTexture(const std::string& id) { std::shared_ptr tex = std::shared_ptr(new GeoreferencedTexture(id)); m_appearanceManager->addAppearance(tex); return tex; } std::shared_ptr CityGMLFactory::createMaterialTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id) { std::shared_ptr targetDef = std::shared_ptr(new MaterialTargetDefinition(targetID, appearance, id)); m_appearanceManager->addMaterialTargetDefinition(targetDef); return targetDef; } std::shared_ptr CityGMLFactory::createTextureTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id) { std::shared_ptr targetDef = std::shared_ptr(new TextureTargetDefinition(targetID, appearance, id)); m_appearanceManager->addTextureTargetDefinition(targetDef); return targetDef; } std::shared_ptr CityGMLFactory::getAppearanceWithID(const std::string& id) { return m_appearanceManager->getAppearanceByID(id); } std::vector CityGMLFactory::getAllThemes() { return m_appearanceManager->getAllThemes(); } void CityGMLFactory::closeFactory() { m_polygonManager->finish(); m_geometryManager->finish(); m_appearanceManager->assignAppearancesToTargets(); } CityGMLFactory::~CityGMLFactory() { } void CityGMLFactory::appearanceTargetCreated(AppearanceTarget* obj) { m_appearanceManager->addAppearanceTarget(obj); } } libcitygml-2.0/sources/src/citygml/citymodel.cpp000066400000000000000000000074051256066205500221460ustar00rootroot00000000000000/* -*-c++-*- libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * Contributors: * - Manuel Garnier, BRGM - better normal computation * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #include "citygml/citymodel.h" #include "citygml/appearancemanager.h" #include "citygml/appearance.h" #include "citygml/citygmllogger.h" #include #include #include #include #include #ifndef min # define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) #endif /////////////////////////////////////////////////////////////////////////////// namespace citygml { CityModel::CityModel(const std::string& id) : FeatureObject( id ) { } void CityModel::addToCityObjectsMapRecursive(const CityObject* cityObj) { CityObjectsMap::iterator it = m_cityObjectsMap.find(cityObj->getType()); if (it == m_cityObjectsMap.end()) { std::vector tmp; tmp.push_back(cityObj); m_cityObjectsMap[cityObj->getType()] = std::vector(tmp); } else { it->second.push_back(cityObj); } for (int i = 0; i < cityObj->getChildCityObjectsCount(); i++) { addToCityObjectsMapRecursive(&cityObj->getChildCityObject(i)); } } std::vector CityModel::themes() const { return m_themes; } void CityModel::setThemes(std::vector themes) { m_themes = themes; } CityModel::~CityModel() { } const ConstCityObjects CityModel::getAllCityObjectsOfType( CityObject::CityObjectsType type ) const { CityObjectsMap::const_iterator it = m_cityObjectsMap.find( type ); return it->second; } const ConstCityObjects CityModel::getRootCityObjects() const { ConstCityObjects list; for (const std::unique_ptr& cityObj : m_roots) { list.push_back(cityObj.get()); } return list; } void CityModel::addRootObject(CityObject* obj) { m_roots.push_back(std::unique_ptr(obj)); } unsigned int CityModel::getNumRootCityObjects() const { return m_roots.size(); } CityObject& CityModel::getRootCityObject(int i) { return *m_roots.at(i); } const CityObject& CityModel::getRootCityObject(int i) const { return *m_roots.at(i); } const std::string& CityModel::getSRSName() const { return m_srsName; } void CityModel::finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger) { // Finish all cityobjcts for (auto& cityObj : m_roots) { cityObj->finish(tesselator, optimize, logger); } // Build city objects map for (std::unique_ptr& obj : m_roots) { addToCityObjectsMapRecursive(obj.get()); } } std::ostream& operator<<( std::ostream& out, const CityModel& model ) { out << "Root CityObjects: " << std::endl; ConstCityObjects rootObjcts = model.getRootCityObjects(); for (const CityObject* cityObj : rootObjcts) { out << cityObj << std::endl; } return out; } } libcitygml-2.0/sources/src/citygml/cityobject.cpp000066400000000000000000000235731256066205500223200ustar00rootroot00000000000000#include "citygml/cityobject.h" #include "citygml/geometry.h" #include "citygml/implictgeometry.h" #include "citygml/appearancemanager.h" #include "citygml/citygml.h" #include "citygml/citygmllogger.h" #include "citygml/address.h" #include #include namespace citygml { CityObject::CityObject(const std::string& id, CityObject::CityObjectsType type) : FeatureObject( id ), m_type( type ) { } CityObject::CityObjectsType CityObject::getType() const { return m_type; } std::string CityObject::getTypeAsString() const { return cityObjectsTypeToString(m_type); } unsigned int CityObject::getGeometriesCount() const { return m_geometries.size(); } const Geometry& CityObject::getGeometry(unsigned int i) const { return *m_geometries[i]; } Geometry& CityObject::getGeometry(unsigned int i) { return *m_geometries[i]; } void CityObject::addGeometry(Geometry* geom) { m_geometries.push_back(std::unique_ptr(geom)); } unsigned int CityObject::getImplicitGeometryCount() const { return m_implicitGeometries.size(); } const ImplicitGeometry& CityObject::getImplicitGeometry(unsigned int i) const { return *m_implicitGeometries[i]; } ImplicitGeometry& CityObject::getImplicitGeometry(unsigned int i) { return *m_implicitGeometries[i]; } void CityObject::addImplictGeometry(ImplicitGeometry* implictGeom) { m_implicitGeometries.push_back(std::unique_ptr(implictGeom)); } unsigned int CityObject::getChildCityObjectsCount() const { return m_children.size(); } const CityObject& CityObject::getChildCityObject(unsigned int i) const { return *m_children[i]; } CityObject& CityObject::getChildCityObject(unsigned int i) { return *m_children[i]; } void CityObject::addChildCityObject(CityObject* cityObj) { m_children.push_back(std::unique_ptr(cityObj)); } const Address* CityObject::address() const { return m_address.get(); } void CityObject::setAddress(std::unique_ptr
&& address) { m_address = std::move(address); } void CityObject::finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger) { for (std::unique_ptr& geom : m_geometries) { geom->finish(tesselator, optimize, logger); } for (std::unique_ptr& implictGeom : m_implicitGeometries) { for (int i = 0; i < implictGeom->getGeometriesCount(); i++) { implictGeom->getGeometry(i).finish(tesselator, optimize, logger); } } for (std::unique_ptr& child : m_children) { child->finish(tesselator, optimize, logger); } } CityObject::~CityObject() { } std::ostream& operator<<( std::ostream& os, const CityObject& o ) { os << o.getType() << ": " << o.getId() << std::endl; os << " Envelope: " << o.getEnvelope() << std::endl; AttributesMap::const_iterator it = o.getAttributes().begin(); while ( it != o.getAttributes().end() ) { os << " + " << it->first << ": " << it->second << std::endl; it++; } for (unsigned int i = 0; i < o.getGeometriesCount(); i++) { os << o.getGeometry(i); } os << " * " << o.getGeometriesCount() << " geometries." << std::endl; return os; } std::string cityObjectsTypeToString(const CityObject::CityObjectsType& t) { switch (t) { case CityObject::COT_GenericCityObject: return "GenericCityObject"; case CityObject::COT_Building: return "Building"; case CityObject::COT_Room: return "Room"; case CityObject::COT_BuildingInstallation: return "BuildingInstallation"; case CityObject::COT_BuildingFurniture: return "BuildingFurniture"; case CityObject::COT_Door: return "Door"; case CityObject::COT_Window: return "Window"; case CityObject::COT_CityFurniture: return "CityFurniture"; case CityObject::COT_Track: return "Track"; case CityObject::COT_Road: return "Road"; case CityObject::COT_Railway: return "Railway"; case CityObject::COT_Square: return "Square"; case CityObject::COT_PlantCover: return "PlantCover"; case CityObject::COT_SolitaryVegetationObject: return "SolitaryVegetationObject"; case CityObject::COT_WaterBody: return "WaterBody"; case CityObject::COT_ReliefFeature: return "ReliefFeature"; case CityObject::COT_LandUse: return "LandUse"; case CityObject::COT_Tunnel: return "Tunnel"; case CityObject::COT_Bridge: return "Bridge"; case CityObject::COT_BridgeConstructionElement: return "BridgeConstructionElement"; case CityObject::COT_BridgeInstallation: return "BridgeInstallation"; case CityObject::COT_BridgePart: return "BridgePart"; case CityObject::COT_BuildingPart: return "BuildingPart"; case CityObject::COT_WallSurface: return "WallSurface"; case CityObject::COT_RoofSurface: return "RoofSurface"; case CityObject::COT_GroundSurface: return "GroundSurface"; case CityObject::COT_ClosureSurface: return "ClosureSurface"; case CityObject::COT_FloorSurface: return "FloorSurface"; case CityObject::COT_InteriorWallSurface: return "InteriorWallSurface"; case CityObject::COT_CeilingSurface: return "CeilingSurface"; case CityObject::COT_TransportationObject: return "TransportationObject"; default: return "Unknown"; } } std::string cityObjectsTypeToLowerString(const CityObject::CityObjectsType& t) { std::string str = cityObjectsTypeToString(t); std::transform(str.begin(), str.end(), str.begin(), ::tolower); return str; } std::unordered_map stringTypeMap = { {cityObjectsTypeToLowerString(CityObject::COT_GenericCityObject), CityObject::COT_GenericCityObject}, {cityObjectsTypeToLowerString(CityObject::COT_Building), CityObject::COT_Building}, {cityObjectsTypeToLowerString(CityObject::COT_Room), CityObject::COT_Room}, {cityObjectsTypeToLowerString(CityObject::COT_BuildingInstallation), CityObject::COT_BuildingInstallation}, {cityObjectsTypeToLowerString(CityObject::COT_BuildingFurniture), CityObject::COT_BuildingFurniture}, {cityObjectsTypeToLowerString(CityObject::COT_Door), CityObject::COT_Door}, {cityObjectsTypeToLowerString(CityObject::COT_Window), CityObject::COT_Window}, {cityObjectsTypeToLowerString(CityObject::COT_CityFurniture), CityObject::COT_CityFurniture}, {cityObjectsTypeToLowerString(CityObject::COT_Track), CityObject::COT_Track}, {cityObjectsTypeToLowerString(CityObject::COT_Road), CityObject::COT_Road}, {cityObjectsTypeToLowerString(CityObject::COT_Railway), CityObject::COT_Railway}, {cityObjectsTypeToLowerString(CityObject::COT_Square), CityObject::COT_Square}, {cityObjectsTypeToLowerString(CityObject::COT_PlantCover), CityObject::COT_PlantCover}, {cityObjectsTypeToLowerString(CityObject::COT_SolitaryVegetationObject), CityObject::COT_SolitaryVegetationObject}, {cityObjectsTypeToLowerString(CityObject::COT_WaterBody), CityObject::COT_WaterBody}, {cityObjectsTypeToLowerString(CityObject::COT_ReliefFeature), CityObject::COT_ReliefFeature}, {cityObjectsTypeToLowerString(CityObject::COT_LandUse), CityObject::COT_LandUse}, {cityObjectsTypeToLowerString(CityObject::COT_Tunnel), CityObject::COT_Tunnel}, {cityObjectsTypeToLowerString(CityObject::COT_Bridge), CityObject::COT_Bridge}, {cityObjectsTypeToLowerString(CityObject::COT_BridgeConstructionElement), CityObject::COT_BridgeConstructionElement}, {cityObjectsTypeToLowerString(CityObject::COT_BridgeInstallation), CityObject::COT_BridgeInstallation}, {cityObjectsTypeToLowerString(CityObject::COT_BridgePart), CityObject::COT_BridgePart}, {cityObjectsTypeToLowerString(CityObject::COT_BuildingPart), CityObject::COT_BuildingPart}, {cityObjectsTypeToLowerString(CityObject::COT_WallSurface), CityObject::COT_WallSurface}, {cityObjectsTypeToLowerString(CityObject::COT_RoofSurface), CityObject::COT_RoofSurface}, {cityObjectsTypeToLowerString(CityObject::COT_GroundSurface), CityObject::COT_GroundSurface}, {cityObjectsTypeToLowerString(CityObject::COT_ClosureSurface), CityObject::COT_ClosureSurface}, {cityObjectsTypeToLowerString(CityObject::COT_FloorSurface), CityObject::COT_FloorSurface}, {cityObjectsTypeToLowerString(CityObject::COT_InteriorWallSurface), CityObject::COT_InteriorWallSurface}, {cityObjectsTypeToLowerString(CityObject::COT_CeilingSurface), CityObject::COT_CeilingSurface}, {cityObjectsTypeToLowerString(CityObject::COT_TransportationObject), CityObject::COT_TransportationObject} }; CityObject::CityObjectsType cityObjectsTypeFromString(const std::string& s, bool& valid) { std::string lower_s = s; std::transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); auto it = stringTypeMap.find(lower_s); valid = it != stringTypeMap.end(); if (valid) { return it->second; } return CityObject::COT_All; } } libcitygml-2.0/sources/src/citygml/envelope.cpp000066400000000000000000000025021256066205500217630ustar00rootroot00000000000000#include "citygml/envelope.h" #include #include #ifndef NAN #define NAN std::numeric_limits::quiet_NaN() #endif #ifdef WIN32 #define ISNAN _isnan #else #define ISNAN std::isnan #endif namespace citygml { Envelope::Envelope() { m_lowerBound = TVec3d(NAN,NAN,NAN); m_upperBound = TVec3d(NAN,NAN,NAN); } Envelope::Envelope(const std::string& srsName) { m_srsName = srsName; } const TVec3d& Envelope::getLowerBound() const { return m_lowerBound; } void Envelope::setLowerBound(const TVec3d& coordinate) { m_lowerBound = coordinate; } const TVec3d& Envelope::getUpperBound() const { return m_upperBound; } void Envelope::setUpperBound(const TVec3d& coordinate) { m_upperBound = coordinate; } const std::string& Envelope::srsName() const { return m_srsName; } const bool Envelope::validBounds() const { return !(ISNAN(m_lowerBound[0]) || ISNAN(m_lowerBound[1]) || ISNAN(m_lowerBound[2]) || ISNAN(m_upperBound[0]) || ISNAN(m_upperBound[1]) || ISNAN(m_upperBound[2])); } std::ostream& operator<<( std::ostream& os, const Envelope& e ) { return os << e.getLowerBound() << " " << e.getUpperBound(); } } libcitygml-2.0/sources/src/citygml/featureobject.cpp000066400000000000000000000007321256066205500227730ustar00rootroot00000000000000#include "citygml/featureobject.h" #include "citygml/envelope.h" namespace citygml { FeatureObject::FeatureObject(const std::string& gmlID) : Object(gmlID) { setEnvelope(new Envelope()); } const Envelope& FeatureObject::getEnvelope() const { return *m_envelope; } void FeatureObject::setEnvelope(Envelope* e) { m_envelope = std::unique_ptr(e); } FeatureObject::~FeatureObject() { } } libcitygml-2.0/sources/src/citygml/geometry.cpp000066400000000000000000000074031256066205500220060ustar00rootroot00000000000000#include "citygml/geometry.h" #include #include #include #include namespace citygml { Geometry::Geometry(const std::string& id, Geometry::GeometryType type, unsigned int lod) : AppearanceTarget( id ), m_finished(false), m_type( type ), m_lod( lod ) { } unsigned int Geometry::getLOD() const { return m_lod; } unsigned int Geometry::getPolygonsCount() const { return m_polygons.size(); } std::shared_ptr Geometry::getPolygon(unsigned int i) { return m_polygons.at(i); } std::shared_ptr Geometry::getPolygon(unsigned int i) const { return m_polygons.at(i); } unsigned int Geometry::getLineStringCount() const { return m_lineStrings.size(); } std::shared_ptr Geometry::getLineString(unsigned int i) { return m_lineStrings.at(i); } std::shared_ptr Geometry::getLineString(unsigned int i) const { return m_lineStrings.at(i); } unsigned int Geometry::getGeometriesCount() const { return m_childGeometries.size(); } const Geometry& Geometry::getGeometry(unsigned int i) const { return *m_childGeometries.at(i); } Geometry& Geometry::getGeometry(unsigned int i) { return *m_childGeometries.at(i); } void Geometry::addGeometry(Geometry* geom) { m_childGeometries.push_back(std::unique_ptr(geom)); } Geometry::GeometryType Geometry::getType() const { return m_type; } std::string Geometry::getTypeAsString() const { switch (m_type) { case GeometryType::GT_Unknown: return "Unknown"; case GeometryType::GT_Roof: return "Roof"; case GeometryType::GT_Wall: return "Wall"; case GeometryType::GT_Ground: return "Ground"; case GeometryType::GT_Closure: return "Closure"; case GeometryType::GT_Floor: return "Floor"; case GeometryType::GT_InteriorWall: return "InteriorWall"; case GeometryType::GT_Ceiling: return "Ceiling"; default: return "Unknown"; } } Geometry::~Geometry() { } unsigned int Geometry::lod() const { return m_lod; } void Geometry::setLod(unsigned int lod) { m_lod = lod; } void Geometry::addPolygon( std::shared_ptr p ) { m_polygons.push_back(p); } void Geometry::addLineString(std::shared_ptr l) { m_lineStrings.push_back(l); } void Geometry::finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger) { // only need to finish geometry once if (m_finished) { return; } m_finished = true; for (std::shared_ptr& child : m_childGeometries) { child->addTargetDefinitionsOf(*this); child->finish(tesselator, optimize, logger); } for (std::shared_ptr& polygon : m_polygons) { polygon->addTargetDefinitionsOf(*this); polygon->finish(tesselator, optimize, logger); } } std::ostream& operator<<( std::ostream& os, const citygml::Geometry& s ) { unsigned int count = 0; for ( unsigned int i = 0; i < s.getPolygonsCount(); i++ ) { os << s.getPolygon(i); count += s.getPolygon(i)->getVertices().size(); } os << " @ " << s.getPolygonsCount() << " polys [" << count << " vertices]" << std::endl; return os; } } libcitygml-2.0/sources/src/citygml/geometrymanager.cpp000066400000000000000000000033541256066205500233420ustar00rootroot00000000000000#include "citygml/geometrymanager.h" #include "citygml/geometry.h" #include "citygml/implictgeometry.h" #include "citygml/citygmllogger.h" namespace citygml { GeometryManager::GeometryManager(std::shared_ptr logger) { m_logger = logger; } void GeometryManager::addSharedGeometry(std::shared_ptr geom) { if (m_sharedGeometries.count(geom->getId()) > 0) { CITYGML_LOG_WARN(m_logger, "Duplicate definition of shared geometry with id '" << geom->getId() << "'... overwriting existing object."); } m_sharedGeometries[geom->getId()] = geom; } void GeometryManager::requestSharedGeometryForImplicitGeometry(ImplicitGeometry* geom, const std::string& geometryID) { m_geometryRequests.push_back(GeometryRequest(geom, geometryID)); } void GeometryManager::finish() { CITYGML_LOG_INFO(m_logger, "Start processing shared geometry requests (" << m_geometryRequests.size() << ")."); for (const GeometryRequest& request : m_geometryRequests) { auto it = m_sharedGeometries.find(request.geometryID); if (it == m_sharedGeometries.end()) { CITYGML_LOG_WARN(m_logger, "ImplicitGeometry object with id '" << request.target->getId() << "' requests Geometry with id '" << request.geometryID << "' but no such" << "shared Geometry object exists."); continue; } request.target->addGeometry(it->second); } m_sharedGeometries.clear(); m_geometryRequests.clear(); CITYGML_LOG_INFO(m_logger, "Finished processing shared geometry requests."); } GeometryManager::~GeometryManager() { } } libcitygml-2.0/sources/src/citygml/georeferencedtexture.cpp000066400000000000000000000021501256066205500243630ustar00rootroot00000000000000#include "citygml/georeferencedtexture.h" namespace citygml { GeoreferencedTexture::GeoreferencedTexture(const std::string& id) : Texture( id, "GeoreferencedTexture" ), m_preferWorldFile(true) { } bool GeoreferencedTexture::getPreferWorldFile() const { return m_preferWorldFile; } void GeoreferencedTexture::setPreferWorldFile(bool value) { m_preferWorldFile = value; } std::shared_ptr GeoreferencedTexture::asTexture() { return std::static_pointer_cast(shared_from_this()); } std::shared_ptr GeoreferencedTexture::asTexture() const { return std::static_pointer_cast(shared_from_this()); } std::shared_ptr GeoreferencedTexture::asGeoreferencedTexture() { return std::static_pointer_cast(shared_from_this()); } std::shared_ptr GeoreferencedTexture::asGeoreferencedTexture() const { return std::static_pointer_cast(shared_from_this()); } } libcitygml-2.0/sources/src/citygml/implictgeometry.cpp000066400000000000000000000022511256066205500233640ustar00rootroot00000000000000#include "citygml/implictgeometry.h" #include "citygml/geometry.h" namespace citygml { ImplicitGeometry::ImplicitGeometry(const std::string& id) : Object(id) { } void ImplicitGeometry::setTransformMatrix(const TransformationMatrix matrix) { m_matrix = matrix; } const TransformationMatrix& ImplicitGeometry::getTransformMatrix() const { return m_matrix; } void ImplicitGeometry::setReferencePoint(const TVec3d& referencePoint) { m_referencePoint = referencePoint; } TVec3d ImplicitGeometry::getReferencePoint() const { return m_referencePoint; } void ImplicitGeometry::addGeometry(std::shared_ptr geom) { m_geometries.push_back(geom); } unsigned int ImplicitGeometry::getGeometriesCount() const { return m_geometries.size(); } Geometry& ImplicitGeometry::getGeometry(unsigned int i) const { return *m_geometries[i]; } std::string ImplicitGeometry::getSRSName() const { return m_srsName; } void ImplicitGeometry::setSRSName(const std::string& srsName) { m_srsName = srsName; } } libcitygml-2.0/sources/src/citygml/linearring.cpp000066400000000000000000000106141256066205500223030ustar00rootroot00000000000000#include "citygml/linearring.h" #include "citygml/texturecoordinates.h" #include "citygml/texture.h" #include "citygml/texturetargetdefinition.h" #include "citygml/citygmllogger.h" #include #include namespace citygml { LinearRing::LinearRing(const std::string& id, bool isExterior) : Object( id ), m_exterior( isExterior ) { } bool LinearRing::isExterior() const { return m_exterior; } unsigned int LinearRing::size() const { return m_vertices.size(); } void LinearRing::addVertex(const TVec3d& v) { m_vertices.push_back( v ); } TVec3d LinearRing::computeNormal() const { unsigned int len = size(); if ( len < 3 ) return TVec3d(); // Tampieri, F. 1992. Newell's method for computing the plane equation of a polygon. In Graphics Gems III, pp.231-232. TVec3d n( 0., 0., 0. ); for ( unsigned int i = 0; i < len; i++ ) { const TVec3d& current = m_vertices[i]; const TVec3d& next = m_vertices[ ( i + 1 ) % len]; n.x += ( current.y - next.y ) * ( current.z + next.z ); n.y += ( current.z - next.z ) * ( current.x + next.x ); n.z += ( current.x - next.x ) * ( current.y + next.y ); } return n.normal(); } std::vector& LinearRing::getVertices() { return m_vertices; } void LinearRing::setVertices(std::vector vertices) { m_vertices = vertices; } const std::vector& LinearRing::getVertices() const { return m_vertices; } void LinearRing::removeDuplicateVertices(const std::vector& targets, std::shared_ptr logger ) { // Currently TextureCoordinates sharing via xlink is not supported (every TextureTargetDefinition is the // sole owner of its TextureCoordinate objects... if this ever changes use an unordered_set for the texture coordinates std::vector> coordinatesList; bool textureCoordinatesVerticesMismatch = false; for (auto& texTarget : targets) { for (unsigned int i = 0; i < texTarget->getTextureCoordinatesCount(); i++) { auto texCoords = texTarget->getTextureCoordinates(i); if (texCoords->targets(*this)) { coordinatesList.push_back(texCoords); if (m_vertices.size() != texCoords->getCoords().size()) { CITYGML_LOG_WARN(logger, "Number of vertices in LinearRing with id '" << this->getId() << "' (" << m_vertices.size() << ") does not match with number of texture coordinates in coordinates list " << " with id '" << texCoords->getId() << "' (" << texCoords->getCoords().size() << ")"); textureCoordinatesVerticesMismatch = true; } } } } // Remove duplicated vertex unsigned int len = m_vertices.size(); if ( len < 2 ) return; unsigned int i = 0; while ( i < m_vertices.size() && m_vertices.size() > 2 ) { if ( ( m_vertices[i] - m_vertices[ ( i + 1 ) % m_vertices.size() ] ).sqrLength() <= DBL_EPSILON ) { m_vertices.erase( m_vertices.begin() + i ); for (auto coordinates : coordinatesList) { coordinates->eraseCoordinate(i); } } else { i++; } } #ifndef NDEBUG // Check integrity after duplicate removel... no need when the input was already corrupted if (textureCoordinatesVerticesMismatch) { return; } for (auto coordinates : coordinatesList) { if (coordinates->getCoords().size() != m_vertices.size()) { CITYGML_LOG_ERROR(logger, "Broken implementation. Duplicate vertex removal in LinearRing with id '" << this->getId() << "' caused a mismatch of texture coordinates in coordinates list with id '" << coordinates->getId() << "' (" << m_vertices.size() << " != " <getCoords().size() << ")"); } } #endif } void LinearRing::forgetVertices() { m_vertices.clear(); } } libcitygml-2.0/sources/src/citygml/linestring.cpp000066400000000000000000000025301256066205500223250ustar00rootroot00000000000000#include #include #include citygml::LineString::LineString(const std::string& id) : Object(id) { m_dimensions = -1; } int citygml::LineString::getDimensions() const { return m_dimensions; } const std::vector& citygml::LineString::getVertices2D() const { return m_vertices_2d; } const std::vector& citygml::LineString::getVertices3D() const { return m_vertices_3d; } std::vector& citygml::LineString::getVertices2D() { return m_vertices_2d; } std::vector& citygml::LineString::getVertices3D() { return m_vertices_3d; } void citygml::LineString::setVertices2D(const std::vector& vertices) { if (m_dimensions != 2) { setDimensions(2); } m_vertices_2d = vertices; } void citygml::LineString::setVertices3D(const std::vector& vertices) { if (m_dimensions != 3) { setDimensions(3); } m_vertices_3d = vertices; } void citygml::LineString::setDimensions(int dim) { m_dimensions = dim; if (dim != 2 && !m_vertices_2d.empty()) { throw std::runtime_error("LineString not set to dimension 2 but contains 2D vertices."); } else if (dim != 3 && !m_vertices_3d.empty()) { throw std::runtime_error("LineString not set to dimension 3 but contains 3D vertices."); } } libcitygml-2.0/sources/src/citygml/material.cpp000066400000000000000000000040311256066205500217430ustar00rootroot00000000000000#include "citygml/material.h" namespace citygml { Material::Material(const std::string& id) : Appearance( id, "Material" ) { // Sets default values of the X3DMaterial definied in the citygml 1.0.0 spec see page 32 (section 9.3 Material) m_ambientIntensity = 0.2f; m_diffuse = TVec3f(0.8f, 0.8f, 0.8f); m_emissive = TVec3f(0.f, 0.f, 0.f); m_specular = TVec3f(1.f, 1.f, 1.f); m_shininess = 0.2f; m_transparency = 0.f; m_isSmooth = false; } bool Material::isSmooth() const { return m_isSmooth; } void Material::setIsSmooth(bool isSmooth) { m_isSmooth = isSmooth; } TVec3f Material::getDiffuse() const { return m_diffuse; } void Material::setDiffuse(TVec3f diffuse) { m_diffuse = diffuse; } TVec3f Material::getEmissive() const { return m_emissive; } void Material::setEmissive(TVec3f emissive) { m_emissive = emissive; } TVec3f Material::getSpecular() const { return m_specular; } void Material::setSpecular(TVec3f specular) { m_specular = specular; } float Material::getAmbientIntensity() const { return m_ambientIntensity; } void Material::setAmbientIntensity(float intensity) { m_ambientIntensity = intensity; } float Material::getShininess() const { return m_shininess; } void Material::setShininess(float shininess) { m_shininess = shininess; } float Material::getTransparency() const { return m_transparency; } void Material::setTransparency(float transparancy) { m_transparency = transparancy; } std::shared_ptr Material::asMaterial() { return std::static_pointer_cast(shared_from_this()); } std::shared_ptr Material::asMaterial() const { return std::static_pointer_cast(shared_from_this()); } } libcitygml-2.0/sources/src/citygml/materialtargetdefinition.cpp000066400000000000000000000004341256066205500252260ustar00rootroot00000000000000#include "citygml/materialtargetdefinition.h" namespace citygml { MaterialTargetDefinition::MaterialTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id) : AppearanceTargetDefinition(targetID, appearance, id) { } } libcitygml-2.0/sources/src/citygml/object.cpp000066400000000000000000000021771256066205500214240ustar00rootroot00000000000000#include "citygml/object.h" #include #include namespace citygml { Object::Object(const std::string& id) : m_id( id ) { if ( m_id == "" ) { std::stringstream ss; ss << "PtrId_" << this; m_id = ss.str(); } } const std::string&Object::getId() const { return m_id; } std::string Object::getAttribute(const std::string& name) const { std::map< std::string, std::string >::const_iterator elt = m_attributes.find( name ); return elt != m_attributes.end() ? elt->second : ""; } const AttributesMap&Object::getAttributes() const { return m_attributes; } AttributesMap&Object::getAttributes() { return m_attributes; } void Object::setAttribute(const std::string& name, const std::string& value, bool overwrite) { if ( !overwrite ) { if ( m_attributes.count(name) > 1 ) return; } m_attributes[ name ] = value; } std::ostream& operator<<( std::ostream& os, const Object& o ) { return os << o.getId(); } } libcitygml-2.0/sources/src/citygml/polygon.cpp000066400000000000000000000205141256066205500216400ustar00rootroot00000000000000#include "citygml/polygon.h" #include "citygml/appearance.h" #include "citygml/texture.h" #include "citygml/texturecoordinates.h" #include "citygml/tesselator.h" #include "citygml/citygmllogger.h" #include "citygml/texturetargetdefinition.h" #include "citygml/materialtargetdefinition.h" #include #include #include #include #include namespace citygml { Polygon::Polygon(const std::string& id, std::shared_ptr logger) : AppearanceTarget( id ), m_negNormal( false ) { m_logger = logger; m_finished = false; } const std::vector& Polygon::getVertices() const { return m_vertices; } std::vector& Polygon::getVertices() { return m_vertices; } const std::vector& Polygon::getIndices() const { return m_indices; } std::shared_ptr Polygon::getMaterialFor(const std::string& theme, bool front) const { const auto targetDef = getMaterialTargetDefinitionForTheme(theme, front); if (targetDef == nullptr) { return nullptr; } return targetDef->getAppearance(); } std::shared_ptr Polygon::getMaterialFor(const std::string& theme) const { const auto result = getMaterialFor(theme, true); if (result != nullptr) { return result; } return getMaterialFor(theme, false); } std::shared_ptr Polygon::getTextureFor(const std::string& theme, bool front) const { const auto targetDef = getTextureTargetDefinitionForTheme(theme, front); if (targetDef == nullptr) { return nullptr; } return targetDef->getAppearance(); } std::shared_ptr Polygon::getTextureFor(const std::string& theme) const { const auto result = getTextureFor(theme, true); if (result != nullptr) { return result; } return getTextureFor(theme, false); } const std::vector Polygon::getTexCoordsForTheme(const std::string& theme, bool front) const { auto& map = front ? m_themeToFrontTexCoordsMap : m_themeToBackTexCoordsMap; auto it = map.find(theme); if (it == map.end()) { return std::vector(); } if (it->second.size() != m_vertices.size()) { CITYGML_LOG_ERROR(m_logger, "Number of texture coordinates (" << it->second.size() << ") for theme " << theme << " in polygon with id " << this->getId() << " does not match number of vertices (" << m_vertices.size() << ")."); } assert(it->second.size() == m_vertices.size()); return it->second; } std::shared_ptr Polygon::getTextureForTheme(const std::string& theme, bool front) const { const auto targetDef = getTextureTargetDefinitionForTheme(theme, front); if (targetDef == nullptr) { return nullptr; } return targetDef->getAppearance(); } TVec3d Polygon::computeNormal() { if ( m_exteriorRing == nullptr ) return TVec3d(); TVec3d normal = m_exteriorRing->computeNormal(); return m_negNormal ? -normal : normal; } bool Polygon::negNormal() const { return m_negNormal; } void Polygon::setNegNormal(bool negNormal) { m_negNormal = negNormal; } void Polygon::removeDuplicateVerticesInRings(std::shared_ptr logger) { std::vector texTargetDefinitions = this->getTextureTargetDefinitions(); // mergeRings should be done before merging polygons... hence m_exteriorRings should only contain one object if ( m_exteriorRing != nullptr ) { m_exteriorRing->removeDuplicateVertices( texTargetDefinitions, logger ); } for ( std::unique_ptr& ring : m_interiorRings ) { ring->removeDuplicateVertices( texTargetDefinitions, logger ); } } std::vector Polygon::getTexCoordsForRingAndTheme(const LinearRing& ring, const std::string& theme, bool front) { const auto targetDef = getTextureTargetDefinitionForTheme(theme, front); if (targetDef == nullptr) { return std::vector(); } const auto coords = targetDef->getTextureCoordinatesForID(ring.getId()); if (coords == nullptr || coords->getCoords().empty()) { return std::vector(); } return coords->getCoords(); } std::vector> Polygon::getTexCoordListsForRing(const LinearRing& ring, const std::vector& themesFront, const std::vector& themesBack) { std::vector> texCoordsLists; for (const std::string& theme : themesFront) { texCoordsLists.push_back(getTexCoordsForRingAndTheme(ring, theme, true)); } for (const std::string& theme : themesBack) { texCoordsLists.push_back(getTexCoordsForRingAndTheme(ring, theme, false)); } return texCoordsLists; } void Polygon::createIndicesWithTesselation(Tesselator& tesselator, std::shared_ptr logger) { TVec3d normal = computeNormal(); std::vector themesFront = getAllTextureThemes(true); std::vector themesBack = getAllTextureThemes(false); tesselator.init(normal); if (m_exteriorRing != nullptr) { tesselator.addContour( m_exteriorRing->getVertices(), getTexCoordListsForRing(*m_exteriorRing, themesFront, themesBack)); m_exteriorRing->forgetVertices(); } for ( std::unique_ptr& ring : m_interiorRings ) { tesselator.addContour( ring->getVertices(), getTexCoordListsForRing(*ring, themesFront, themesBack) ); ring->forgetVertices(); } tesselator.compute(); m_vertices = tesselator.getVertices(); m_indices = tesselator.getIndices(); if (m_vertices.empty()) { return; } const std::vector>& texCoordLists = tesselator.getTexCoords(); for (size_t i = 0; i < themesFront.size(); i++) { assert(texCoordLists.at(i).size() == m_vertices.size()); m_themeToFrontTexCoordsMap[themesFront.at(i)] = texCoordLists.at(i); } for (size_t i = 0; i < themesBack.size(); i++) { assert(texCoordLists.at(i + themesFront.size()).size() == m_vertices.size()); m_themeToBackTexCoordsMap[themesBack.at(i)] = texCoordLists.at(i + themesFront.size()); } } void Polygon::computeIndices(Tesselator& tesselator, std::shared_ptr logger ) { m_indices.clear(); m_vertices.clear(); createIndicesWithTesselation(tesselator, logger); if ( m_vertices.size() < 3 ) { CITYGML_LOG_WARN(logger, "Polygon with id " << this->getId() << " has less than 3 vertices."); } } void Polygon::finish(Tesselator& tesselator, bool optimize, std::shared_ptr logger) { if (m_finished) { // This may happen as Polygons can be shared between geometries return; } m_finished = true; if (optimize) { removeDuplicateVerticesInRings(logger); } computeIndices(tesselator, logger); } void Polygon::addRing( LinearRing* ring ) { if (m_finished) { throw std::runtime_error("Can't add LinearRing to finished Polygon."); } if (ring->isExterior() && m_exteriorRing != nullptr) { CITYGML_LOG_WARN(m_logger, "Duplicate definition of exterior LinearRing for Polygon with id '" << this->getId() << "'." << " Keeping exterior LinearRing with id '" << m_exteriorRing->getId() << "' and ignore LinearRing with id '" << ring->getId() << "'"); delete ring; return; } if ( ring->isExterior() ) { m_exteriorRing = std::unique_ptr(ring); } else { m_interiorRings.push_back( std::unique_ptr(ring) ); } } Polygon::~Polygon() { } } libcitygml-2.0/sources/src/citygml/polygonmanager.cpp000066400000000000000000000032061256066205500231720ustar00rootroot00000000000000#include "citygml/polygonmanager.h" #include "citygml/polygon.h" #include "citygml/citygmllogger.h" #include "citygml/geometry.h" namespace citygml { PolygonManager::PolygonManager(std::shared_ptr logger) { m_logger = logger; } void PolygonManager::addPolygon(std::shared_ptr poly) { if (m_sharedPolygons.count(poly->getId()) > 0) { CITYGML_LOG_WARN(m_logger, "Duplicate definition of Polygon with id '" << poly->getId() << "'... overwriting existing object."); } m_sharedPolygons[poly->getId()] = poly; } void PolygonManager::requestSharedPolygonForGeometry(Geometry* geom, const std::string& polygonID) { m_polygonRequests.push_back(PolygonRequest(geom, polygonID)); } void PolygonManager::finish() { CITYGML_LOG_INFO(m_logger, "Start processing polygon requests (" << m_polygonRequests.size() << ")."); for (const PolygonRequest& request : m_polygonRequests) { auto it = m_sharedPolygons.find(request.polygonID); if (it == m_sharedPolygons.end()) { CITYGML_LOG_WARN(m_logger, "Geometry object with id '" << request.target->getId() << "' requests Polygon with id '" << request.polygonID << "' but no such" << " Polygon object exists."); continue; } request.target->addPolygon(it->second); } m_sharedPolygons.clear(); m_polygonRequests.clear(); CITYGML_LOG_INFO(m_logger, "Finished processing polygon requests."); } PolygonManager::~PolygonManager() { } } libcitygml-2.0/sources/src/citygml/tesselator.cpp000066400000000000000000000163361256066205500223450ustar00rootroot00000000000000/* -*-c++-*- libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * Contributors: * - Manuel Garnier, BRGM - better normal computation * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #ifdef WIN32 #define WINDOWS_LEAN_AND_MEAN #define NOMINMAX #endif #include "citygml/tesselator.h" #ifndef WIN32 # include #endif #include #include #include #include Tesselator::Tesselator(std::shared_ptr logger ) { _logger = logger; _tobj = gluNewTess(); gluTessCallback( _tobj, GLU_TESS_VERTEX_DATA, (GLU_TESS_CALLBACK)&vertexDataCallback ); gluTessCallback( _tobj, GLU_TESS_BEGIN_DATA, (GLU_TESS_CALLBACK)&beginCallback ); gluTessCallback( _tobj, GLU_TESS_END_DATA, (GLU_TESS_CALLBACK)&endCallback ); gluTessCallback( _tobj, GLU_TESS_COMBINE_DATA, (GLU_TESS_CALLBACK)&combineCallback ); gluTessCallback( _tobj, GLU_TESS_ERROR_DATA, (GLU_TESS_CALLBACK)&errorCallback ); } void Tesselator::init( const TVec3d& normal, GLenum winding_rule ) { gluTessBeginPolygon( _tobj, this ); gluTessProperty( _tobj, GLU_TESS_WINDING_RULE, winding_rule ); gluTessNormal( _tobj, normal.x, normal.y, normal.z ); _vertices.clear(); _indices.clear(); _curIndices.clear(); _texCoordsLists.clear(); _outIndices.clear(); } Tesselator::~Tesselator() { gluDeleteTess( _tobj ); } void Tesselator::compute() { gluTessEndPolygon( _tobj ); } const std::vector Tesselator::getVertices() const { return std::vector(_vertices.begin(), _vertices.end()); } const std::vector& Tesselator::getIndices() const { return _outIndices; } void Tesselator::addContour(const std::vector& pts, std::vector> textureCoordinatesLists ) { unsigned int len = pts.size(); if ( len < 3 ) return; for (size_t i = 0; i < textureCoordinatesLists.size(); i++) { std::vector& texCoords = textureCoordinatesLists.at(i); if (texCoords.size() != pts.size()) { if (!texCoords.empty()) { CITYGML_LOG_ERROR(_logger, "Invalid call to 'addContour'. The number of texture coordinates in list " << i << " (" << texCoords.size() << ") " "does not match the number of vertices (" << pts.size() << "). The texture coordinates list will be resized which may cause invalid texture coordinates."); } texCoords.resize(pts.size(), TVec2f(0.f, 0.f)); } } for (size_t i = 0; i < std::max(_texCoordsLists.size(), textureCoordinatesLists.size()); i++) { if (i >= _texCoordsLists.size()) { std::vector texCoords(_vertices.size(), TVec2f(0.f, 0.f)); texCoords.insert(texCoords.end(), textureCoordinatesLists.at(i).begin(), textureCoordinatesLists.at(i).end()); _texCoordsLists.push_back(texCoords); } else if (i >= textureCoordinatesLists.size()) { _texCoordsLists.at(i).resize(_texCoordsLists.at(i).size() + pts.size(), TVec2f(0.f, 0.f)); } else { _texCoordsLists.at(i).insert(_texCoordsLists.at(i).end(), textureCoordinatesLists.at(i).begin(), textureCoordinatesLists.at(i).end()); } } unsigned int pos = _vertices.size(); gluTessBeginContour( _tobj ); for ( unsigned int i = 0; i < len; i++ ) { _vertices.push_back( pts[i] ); _indices.push_back(pos + i); gluTessVertex( _tobj, &(_vertices.back()[0]), &_indices.back() ); } gluTessEndContour( _tobj ); #ifndef NDEBUG for (size_t i = 0; i < _texCoordsLists.size(); i++) { assert(_texCoordsLists.at(i).size() == _vertices.size()); } #endif } void CALLBACK Tesselator::beginCallback( GLenum which, void* userData ) { Tesselator* tess = static_cast(userData); tess->_curMode = which; } void CALLBACK Tesselator::vertexDataCallback( GLvoid *data, void* userData ) { Tesselator *tess = static_cast(userData); unsigned int index = *reinterpret_cast(data); assert(index < tess->_vertices.size()); tess->_curIndices.push_back( index ); } void CALLBACK Tesselator::combineCallback( GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** outData, void* userData ) { Tesselator *tess = static_cast(userData); tess->_indices.push_back(tess->_indices.size()); tess->_vertices.push_back( TVec3d( coords[0], coords[1], coords[2] ) ); if (!tess->_texCoordsLists.empty()) { for (std::vector& texcords : tess->_texCoordsLists) { if (texcords.empty()) { continue; } TVec2f newTexCoord(0,0); for (int i = 0; i < 4; i++) { if (vertex_data[i] != nullptr) { unsigned int vertexIndex = *reinterpret_cast(vertex_data[i]); newTexCoord = newTexCoord + weight[i] * texcords.at(vertexIndex); } } texcords.push_back(newTexCoord); assert(texcords.size() == tess->_vertices.size()); } } *outData = &tess->_indices.back(); } void CALLBACK Tesselator::endCallback( void* userData ) { Tesselator *tess = static_cast(userData); unsigned int len = tess->_curIndices.size(); switch ( tess->_curMode ) { case GL_TRIANGLES: for ( unsigned int i = 0; i < len; i++ ) tess->_outIndices.push_back( tess->_curIndices[i] ); break; case GL_TRIANGLE_FAN: case GL_TRIANGLE_STRIP: { unsigned int first = tess->_curIndices[0]; unsigned int prev = tess->_curIndices[1]; assert(first < tess->_vertices.size()); assert(prev < tess->_vertices.size()); for ( unsigned int i = 2; i < len; i++ ) { if ( tess->_curMode == GL_TRIANGLE_FAN || i%2 == 0 ) tess->_outIndices.push_back( first ); tess->_outIndices.push_back( prev ); if ( tess->_curMode == GL_TRIANGLE_STRIP ) { if ( i%2 == 1) tess->_outIndices.push_back( first ); first = prev; } prev = tess->_curIndices[i]; tess->_outIndices.push_back( prev ); } } break; default: CITYGML_LOG_WARN(tess->_logger, "Tesselator: non-supported GLU tesselator primitive " << tess->_curMode); } tess->_curIndices.clear(); } void CALLBACK Tesselator::errorCallback( GLenum errorCode, void* userData ) { Tesselator *tess = static_cast(userData); CITYGML_LOG_ERROR(tess->_logger, "Tesselator error: " << gluErrorString( errorCode )); } libcitygml-2.0/sources/src/citygml/texture.cpp000066400000000000000000000042461256066205500216550ustar00rootroot00000000000000#include "citygml/texture.h" #include "citygml/utils.h" namespace citygml { Texture::Texture(const std::string& id) : Appearance( id, "Texture" ), m_repeat( false ), m_wrapMode( WrapMode::WM_NONE ) { } Texture::Texture(const std::string& id, const std::string& type) : Appearance( id, type ), m_repeat( false ), m_wrapMode( WrapMode::WM_NONE ) { } std::string Texture::getUrl() const { return m_url; } void Texture::setUrl(const std::string& url) { m_url = url; } bool Texture::getRepeat() const { return m_repeat; } Texture::WrapMode Texture::getWrapMode() const { return m_wrapMode; } void Texture::setWrapMode(Texture::WrapMode mode) { m_wrapMode = mode; } bool Texture::setWrapModeFromString(std::string wrapMode) { if ( ci_string_compare( wrapMode, "wrap" ) ) { this->setWrapMode(Texture::WrapMode::WM_WRAP); } else if ( ci_string_compare( wrapMode, "mirror" ) ) { this->setWrapMode(Texture::WrapMode::WM_MIRROR); } else if ( ci_string_compare( wrapMode, "clamp" ) ) { this->setWrapMode(Texture::WrapMode::WM_CLAMP); } else if ( ci_string_compare( wrapMode, "border" ) ) { this->setWrapMode(Texture::WrapMode::WM_BORDER); } else if ( ci_string_compare( wrapMode, "none" ) ) { this->setWrapMode(Texture::WrapMode::WM_NONE); } else { return false; } return true; } TVec4f Texture::getBorderColor() const { return m_borderColor; } void Texture::setBorderColor(TVec4f color) { m_borderColor = color; } std::string Texture::toString() const { return Appearance::toString() + " (url: " + m_url + ")"; } std::shared_ptr Texture::asTexture() { return std::static_pointer_cast(shared_from_this()); } std::shared_ptr Texture::asTexture() const { return std::static_pointer_cast(shared_from_this()); } Texture::~Texture() { } } libcitygml-2.0/sources/src/citygml/texturecoordinates.cpp000066400000000000000000000016221256066205500241030ustar00rootroot00000000000000#include "citygml/texturecoordinates.h" #include "citygml/linearring.h" namespace citygml { TextureCoordinates::TextureCoordinates(std::string id, std::string targetID) : Object(id) { m_targetID = targetID; } bool TextureCoordinates::targets(const LinearRing& ring) const { return m_targetID == ring.getId(); } std::string TextureCoordinates::getTargetLinearRingID() const { return m_targetID; } bool TextureCoordinates::eraseCoordinate(unsigned int i) { if (i < m_coordlist.size()) { m_coordlist.erase(m_coordlist.begin() + i); return true; } return false; } const std::vector& TextureCoordinates::getCoords() const { return m_coordlist; } void TextureCoordinates::setCoords(std::vector texCoords) { m_coordlist = texCoords; } } libcitygml-2.0/sources/src/citygml/texturetargetdefinition.cpp000066400000000000000000000032071256066205500251310ustar00rootroot00000000000000#include "citygml/texturetargetdefinition.h" #include "citygml/texturecoordinates.h" namespace citygml { TextureTargetDefinition::TextureTargetDefinition(const std::string& targetID, std::shared_ptr appearance, const std::string& id) : AppearanceTargetDefinition(targetID, appearance, id) { } unsigned int TextureTargetDefinition::getTextureCoordinatesCount() const { return m_coordinatesList.size(); } std::shared_ptr TextureTargetDefinition::getTextureCoordinates(unsigned int i) { return m_coordinatesList.at(i); } std::shared_ptr TextureTargetDefinition::getTextureCoordinates(unsigned int i) const { return m_coordinatesList.at(i); } std::shared_ptr TextureTargetDefinition::getTextureCoordinatesForID(const std::string& ringID) { auto it = m_idTexCoordMap.find(ringID); if (it != m_idTexCoordMap.end()) { return it->second; } return nullptr; } std::shared_ptr TextureTargetDefinition::getTextureCoordinatesForID(const std::string& ringID) const { const auto it = m_idTexCoordMap.find(ringID); if (it != m_idTexCoordMap.end()) { return it->second; } return nullptr; } void TextureTargetDefinition::addTexCoordinates(std::shared_ptr texCoords) { m_coordinatesList.push_back(texCoords); m_idTexCoordMap[texCoords->getTargetLinearRingID()] = texCoords; } TextureTargetDefinition::~TextureTargetDefinition() { } } libcitygml-2.0/sources/src/citygml/transformmatrix.cpp000066400000000000000000000017021256066205500234070ustar00rootroot00000000000000#include "citygml/transformmatrix.h" namespace citygml { TransformationMatrix::TransformationMatrix() : Object("") { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { m_matrix[i + j * 4] = i == j; m_transposedMatrix[i + j * 4] = i == j; } } } TransformationMatrix::TransformationMatrix(double* matrix) : Object("") { for (size_t i = 0; i < 16; ++i) { m_matrix[i] = matrix[i]; } for (size_t i = 0; i < 4; ++i) { for (size_t j = 0; j < 4; ++j) { m_transposedMatrix[i+j*4] = m_matrix[j+i*4]; } } } const double* TransformationMatrix::getMatrix() const { return m_matrix; } const double* TransformationMatrix::getTransposedMatrix() const { return m_transposedMatrix; } TransformationMatrix::~TransformationMatrix() { } } libcitygml-2.0/sources/src/parser/000077500000000000000000000000001256066205500172675ustar00rootroot00000000000000libcitygml-2.0/sources/src/parser/addressparser.cpp000066400000000000000000000100061256066205500226320ustar00rootroot00000000000000#include #include #include #include #include #include #include #include namespace citygml { namespace { template std::unique_ptr make_unique(Args&&... args) { return std::unique_ptr(new T(std::forward(args)...)); } auto k_rootElements = std::unordered_set(); auto k_subElements = std::unordered_set(); auto k_dataElements = std::unordered_map>(); std::mutex g_nodeSetMutex; bool g_nodeSetsInitialized = false; void initializeNodeSets() { if (!g_nodeSetsInitialized) { std::lock_guard lock(g_nodeSetMutex); if (!g_nodeSetsInitialized) { k_rootElements = { NodeType::CORE_AddressNode, NodeType::BLDG_AddressNode, NodeType::CORE_XalAddressNode }; k_subElements = { NodeType::XAL_AddressDetailsNode, NodeType::XAL_CountryNode, NodeType::XAL_LocalityNode, NodeType::XAL_PostalCodeNode, NodeType::XAL_ThoroughfareNode }; k_dataElements = { { NodeType::XAL_CountryNameNode, &Address::setCountry }, { NodeType::XAL_LocalityNameNode, &Address::setLocality }, { NodeType::XAL_ThoroughfareNameNode, &Address::setThoroughfareName }, { NodeType::XAL_ThoroughfareNumberNode, &Address::setThoroughfareNumber }, { NodeType::XAL_PostalCodeNumberNode, &Address::setPostalCode } }; g_nodeSetsInitialized = true; } } } } // anonymous namespace AddressParser::AddressParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, const Callback& callback) : CityGMLElementParser(documentParser, factory, logger) , m_callback(callback) { initializeNodeSets(); } std::string AddressParser::elementParserName() const { return "AddressParser"; } bool AddressParser::handlesElement(const NodeType::XMLNode& node) const { return k_rootElements.count(node) > 0; } bool AddressParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (k_rootElements.count(node) == 0) { CITYGML_LOG_ERROR(m_logger, "Expected an address start tag but got <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_address = make_unique
(attributes.getCityGMLIDAttribute()); return true; } bool AddressParser::parseElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { m_callback(std::move(m_address)); m_address = nullptr; return k_rootElements.count(node) > 0; } bool AddressParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { return k_subElements.count(node) > 0 || k_dataElements.count(node) > 0 || k_rootElements.count(node) > 0; } bool AddressParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { const auto itr = k_dataElements.find(node); if (itr != k_dataElements.end()) { itr->second(m_address.get(), characters); return true; } return k_subElements.count(node) > 0 || k_dataElements.count(node) > 0 || k_rootElements.count(node) > 0; } } /* namespace citygml */ libcitygml-2.0/sources/src/parser/appearanceelementparser.cpp000066400000000000000000000116711256066205500246670ustar00rootroot00000000000000#include "parser/appearanceelementparser.h" #include #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/delayedchoiceelementparser.h" #include "parser/textureelementparser.h" #include "parser/materialelementparser.h" #include "parser/georeferencedtextureelementparser.h" #include "parser/skipelementparser.h" #include "citygml/appearance.h" #include "citygml/texture.h" #include "citygml/material.h" #include "citygml/georeferencedtexture.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include "citygml/object.h" #include namespace citygml { AppearanceElementParser::AppearanceElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger) : GMLObjectElementParser(documentParser, factory, logger) { } std::string AppearanceElementParser::elementParserName() const { return "AppearanceElementParser"; } bool AppearanceElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::APP_AppearanceNode; } bool AppearanceElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (node != NodeType::APP_AppearanceNode) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::APP_AppearanceNode.name() << "> got <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_appearanceObj = std::make_shared(attributes.getCityGMLIDAttribute()); return true; } bool AppearanceElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { if (m_theme.empty()) { CITYGML_LOG_INFO(m_logger, "Appearance node that ends at " << getDocumentLocation() << " has not theme defined. Using empty theme."); } if (m_surfaceDataList.empty()) { CITYGML_LOG_ERROR(m_logger, "Appearance node that ends at " << getDocumentLocation() << " has no surfaceData elements."); } // assign the theme to all members for (std::shared_ptr& surfaceData : m_surfaceDataList) { surfaceData->addToTheme(m_theme); } return true; } bool AppearanceElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (node == NodeType::APP_ThemeNode) { return true; } else if (node == NodeType::APP_SurfaceDataMemberNode) { if (attributes.hasXLinkAttribute()) { // surfaceDataMemberNode links to an existing surfaceData member std::shared_ptr sharedAppearance = m_factory.getAppearanceWithID(attributes.getXLinkValue()); if (sharedAppearance != nullptr) { m_surfaceDataList.push_back(sharedAppearance); } else { CITYGML_LOG_WARN(m_logger, "SurfaceDataMember node with invalid xlink attribute. SurfaceData object with id " << attributes.getXLinkValue() << " does not exist."); } } else { // surfaceDataMemberNode contains a surfaceData object (material, texture or georeferencedtexture) std::function)> callback = [this] (std::shared_ptr surfacedata) { this->m_surfaceDataList.push_back(surfacedata); }; std::vector choices; choices.push_back(new MaterialElementParser(m_documentParser, m_factory, m_logger, callback)); choices.push_back(new TextureElementParser(m_documentParser, m_factory, m_logger, callback)); choices.push_back(new GeoReferencedTextureElementParser(m_documentParser, m_factory, m_logger, callback)); setParserForNextElement(new DelayedChoiceElementParser(m_documentParser, m_logger, choices)); } return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool AppearanceElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (node == NodeType::APP_ThemeNode) { if (!m_theme.empty()) { CITYGML_LOG_WARN(m_logger, "Duplicate definition of theme in appearance node at " << getDocumentLocation() << ". Overwriting last theme '" << m_theme << "' with '" << characters << "'"); } m_theme = characters; return true; } else if (node == NodeType::APP_SurfaceDataMemberNode) { return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* AppearanceElementParser::getObject() { return m_appearanceObj.get(); } } libcitygml-2.0/sources/src/parser/attributes.cpp000066400000000000000000000017451256066205500221700ustar00rootroot00000000000000#include "parser/attributes.h" #include "parser/parserutils.hpp" #include "parser/documentlocation.h" #include "citygml/citygmllogger.h" #include "sstream" namespace citygml { Attributes::Attributes(std::shared_ptr logger) { m_logger = logger; } std::string Attributes::getCityGMLIDAttribute() const { std::string id = getAttribute("gml:id", ""); if (id.empty()) { std::stringstream defaultID; defaultID << "genID_" << getDocumentLocation().getDocumentFileName() << "_" << getDocumentLocation().getCurrentLine() << "_" << + getDocumentLocation().getCurrentColumn(); id = defaultID.str(); } return id; } bool Attributes::hasXLinkAttribute() const { return !getAttribute("xlink:href", "").empty(); } std::string Attributes::getXLinkValue() { return parseReference(getAttribute("xlink:href", ""), m_logger, getDocumentLocation()); } } libcitygml-2.0/sources/src/parser/citygmldocumentparser.cpp000066400000000000000000000164621256066205500244300ustar00rootroot00000000000000#include "parser/citygmldocumentparser.h" #include "parser/documentlocation.h" #include "parser/nodetypes.h" #include "parser/elementparser.h" #include "parser/citymodelelementparser.h" #include "parser/geocoordinatetransformer.h" #include "citygml/citygmllogger.h" #include "citygml/citygmlfactory.h" #include "citygml/citymodel.h" #include "citygml/tesselator.h" #include namespace citygml { CityGMLDocumentParser::CityGMLDocumentParser(const ParserParams& params, std::shared_ptr logger) { m_logger = logger; m_factory = std::unique_ptr(new CityGMLFactory(logger)); m_parserParams = params; m_activeParser = nullptr; m_currentElementUnknownOrUnexpected = false; m_unknownElementOrUnexpectedElementDepth = 0; m_unknownElementOrUnexpectedElementName = ""; } std::shared_ptr CityGMLDocumentParser::getModel() { return m_rootModel; } void CityGMLDocumentParser::setCurrentElementParser(ElementParser* parser) { m_parserStack.push(std::shared_ptr(parser)); } void CityGMLDocumentParser::removeCurrentElementParser(const ElementParser* caller) { if (m_parserStack.top().get() != caller) { throw std::runtime_error("A CityGMLElementParser object tries to remove another CityGMLElementParser object from the control flow which is not allowed."); } m_parserStack.pop(); } void CityGMLDocumentParser::startElement(const std::string& name, Attributes& attributes) { if (checkCurrentElementUnownOrUnexpected_start(name)) { CITYGML_LOG_DEBUG(m_logger, "Skipping element <" << name << "> at " << getDocumentLocation()); return; } const NodeType::XMLNode& node = NodeType::getXMLNodeFor(name); if (!node.valid()) { CITYGML_LOG_WARN(m_logger, "Found start tag of unknown node <" << name << "> at " << getDocumentLocation() << ". Skip to next element."); skipUnknownOrUnexpectedElement(name); return; } if (m_parserStack.empty()) { m_parserStack.push(std::unique_ptr(new CityModelElementParser(*this, *m_factory, m_logger, [this](CityModel* cityModel) { this->m_rootModel = std::unique_ptr(cityModel); }))); } m_activeParser = m_parserStack.top(); CITYGML_LOG_TRACE(m_logger, "Invoke " << m_activeParser->elementParserName() << "::startElement for <" << node << "> at " << getDocumentLocation()); if (!m_activeParser->startElement(node, attributes)) { CITYGML_LOG_WARN(m_logger, "Skipping element with unexpected start tag <" << node << "> at " << getDocumentLocation() << " (active parser " << m_activeParser->elementParserName() << ")"); skipUnknownOrUnexpectedElement(name); } } void CityGMLDocumentParser::endElement(const std::string& name, const std::string& characters) { if (checkCurrentElementUnownOrUnexpected_end(name)) { CITYGML_LOG_DEBUG(m_logger, "Skipped element <" << name << "> at " << getDocumentLocation()); return; } const NodeType::XMLNode& node = NodeType::getXMLNodeFor(name); if (!node.valid()) { CITYGML_LOG_WARN(m_logger, "Found end tag of unknown node <" << name << "> at " << getDocumentLocation()); return; } if (m_parserStack.empty()) { CITYGML_LOG_ERROR(m_logger, "Found element end tag at" << getDocumentLocation() << "but parser stack is empty (either a bug or corrupted xml document)"); throw std::runtime_error("Unexpected element end."); } m_activeParser = m_parserStack.top(); CITYGML_LOG_TRACE(m_logger, "Invoke " << m_activeParser->elementParserName() << "::endElement for <" << node << "> at " << getDocumentLocation()); if (!m_activeParser->endElement(node, characters)) { CITYGML_LOG_ERROR(m_logger, "Active parser " << m_activeParser->elementParserName() << " reports end tag <" << node << "> at " << getDocumentLocation() << " as " << "unknown, but it seems as if the corresponding start tag was not reported as unknown. Please check the parser implementation." << "Ignoring end tag and continue parsing."); } } void CityGMLDocumentParser::startDocument() { CITYGML_LOG_INFO(m_logger, "Start parsing citygml file (" << getDocumentLocation() << ")"); } void CityGMLDocumentParser::endDocument() { if (!m_parserStack.empty()) { CITYGML_LOG_WARN(m_logger, "Reached end of document but the parser stack is not empty (either a bug or corrupted xml document)"); } CITYGML_LOG_INFO(m_logger, "Finished parsing ciytgml file (" << getDocumentLocation() << ")"); m_factory->closeFactory(); if (m_rootModel != nullptr) { Tesselator tesselator(m_logger); CITYGML_LOG_INFO(m_logger, "Start postprocessing of the citymodel."); m_rootModel->finish(tesselator, m_parserParams.optimize, m_logger); CITYGML_LOG_INFO(m_logger, "Finished postprocessing of the citymodel."); m_rootModel->setThemes(m_factory->getAllThemes()); if (!m_parserParams.destSRS.empty()) { try { CITYGML_LOG_INFO(m_logger, "Start coordinates transformation ."); GeoCoordinateTransformer transformer(m_parserParams.destSRS, m_logger); transformer.transformToDestinationSRS(m_rootModel.get()); CITYGML_LOG_INFO(m_logger, "Finished coordinates transformation ."); } catch (const std::runtime_error& e) { CITYGML_LOG_ERROR(m_logger, "Coordinate transformation aborted: " << e.what()); } } } else { CITYGML_LOG_WARN(m_logger, "Reached end of document but no CityModel was parsed."); } } void CityGMLDocumentParser::skipUnknownOrUnexpectedElement(const std::string& name) { m_unknownElementOrUnexpectedElementName = name; m_unknownElementOrUnexpectedElementDepth = 0; m_currentElementUnknownOrUnexpected = true; } bool CityGMLDocumentParser::checkCurrentElementUnownOrUnexpected_start(const std::string& name) { if (!m_currentElementUnknownOrUnexpected) { return false; } if (m_unknownElementOrUnexpectedElementName == name) { m_unknownElementOrUnexpectedElementDepth++; } return true; } bool CityGMLDocumentParser::checkCurrentElementUnownOrUnexpected_end(const std::string& name) { if (!m_currentElementUnknownOrUnexpected) { return false; } if (m_unknownElementOrUnexpectedElementName == name) { if (m_unknownElementOrUnexpectedElementDepth == 0) { // End tag of initial unknown element reached... m_unknownElementOrUnexpectedElementName = ""; m_currentElementUnknownOrUnexpected = false; } m_unknownElementOrUnexpectedElementDepth--; } return true; } CityGMLDocumentParser::~CityGMLDocumentParser() { } } libcitygml-2.0/sources/src/parser/citygmlelementparser.cpp000066400000000000000000000042621256066205500242360ustar00rootroot00000000000000#include "parser/citygmlelementparser.h" #include "citygml/utils.h" #include "citygml/citygmllogger.h" #include "parser/citygmldocumentparser.h" #include "parser/documentlocation.h" #include "parser/nodetypes.h" #include namespace citygml { CityGMLElementParser::CityGMLElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger) : ElementParser(documentParser, logger), m_factory(factory), m_boundElement(NodeType::InvalidNode) { } bool CityGMLElementParser::startElement(const NodeType::XMLNode& node, Attributes& attributes) { if (!node.valid()) { CITYGML_LOG_ERROR(m_logger, "Invalid xml start tag (no name) found at " << getDocumentLocation()); throw std::runtime_error("Error parsing xml document. Invalid start tag."); } if (!m_boundElement.valid()) { m_boundElement = node; return parseElementStartTag(node, attributes); } else { return parseChildElementStartTag(node, attributes); } } bool CityGMLElementParser::endElement(const NodeType::XMLNode& node, const std::string& characters) { if (!m_boundElement.valid()) { // This might happen if an container element that usally contains a child element links to an exting object using XLink an thus // uses a combined start/end element: e.g.: // For such elements a child parser must only be created if there is no xlink attribute. CITYGML_LOG_ERROR(m_logger, "CityGMLElementParser::endElement called on unbound " << elementParserName() << " object for element <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("CityGMLElementParser::endElement called on unbound CityGMLElementParser object."); } if (m_boundElement == node) { m_documentParser.removeCurrentElementParser(this); return parseElementEndTag(node, characters); } else { return parseChildElementEndTag(node, characters); } } CityGMLElementParser::~CityGMLElementParser() { } } libcitygml-2.0/sources/src/parser/citymodelelementparser.cpp000066400000000000000000000074261256066205500245640ustar00rootroot00000000000000#include "parser/citymodelelementparser.h" #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/cityobjectelementparser.h" #include "parser/appearanceelementparser.h" #include "citygml/citymodel.h" #include "citygml/citygmllogger.h" #include "citygml/citygmlfactory.h" #include "citygml/cityobject.h" #include namespace citygml { CityModelElementParser::CityModelElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function callback) : GMLFeatureCollectionElementParser(documentParser, factory, logger) { m_callback = callback; m_model = nullptr; } bool CityModelElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::CORE_CityModelNode; } std::string CityModelElementParser::elementParserName() const { return "CityModelElementParser"; } bool CityModelElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (node != NodeType::CORE_CityModelNode) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::CORE_CityModelNode.name() << "> got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createCityModel(attributes.getCityGMLIDAttribute()); return true; } bool CityModelElementParser::parseElementEndTag(const NodeType::XMLNode& node, const std::string&) { if (node != NodeType::CORE_CityModelNode) { CITYGML_LOG_WARN(m_logger, "Expected end tag <" << NodeType::CORE_CityModelNode.name() << "> got <" << node.name() << "> at " << getDocumentLocation()); } m_callback(m_model); return true; } bool CityModelElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("CityModelElementParser::parseChildElementStartTag called before CityModelElementParser::parseElementStartTag"); } if (node == NodeType::CORE_CityObjectMemberNode) { setParserForNextElement(new CityObjectElementParser(m_documentParser, m_factory, m_logger, [this](CityObject* obj) { this->m_model->addRootObject(obj); })); return true; } else if (node == NodeType::APP_AppearanceNode // Compatibility with CityGML 1.0 (in CityGML 2 CityObjects can only contain appearanceMember elements) || node == NodeType::APP_AppearanceMemberNode) { setParserForNextElement(new AppearanceElementParser(m_documentParser, m_factory, m_logger)); return true; } else { return GMLFeatureCollectionElementParser::parseChildElementStartTag(node, attributes); } return false; } bool CityModelElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("CityModelElementParser::parseChildElementEndTag called before CityModelElementParser::parseElementStartTag"); } if (node == NodeType::CORE_CityObjectMemberNode || node == NodeType::APP_AppearanceNode || node == NodeType::APP_AppearanceMemberNode) { return true; } else { return GMLFeatureCollectionElementParser::parseChildElementEndTag(node, characters); } return false; } FeatureObject* CityModelElementParser::getFeatureObject() { return m_model; } } libcitygml-2.0/sources/src/parser/cityobjectelementparser.cpp000066400000000000000000000674111256066205500247320ustar00rootroot00000000000000#include "parser/cityobjectelementparser.h" #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/appearanceelementparser.h" #include "parser/geometryelementparser.h" #include "parser/implicitgeometryelementparser.h" #include "parser/polygonelementparser.h" #include "parser/skipelementparser.h" #include "parser/delayedchoiceelementparser.h" #include "parser/linestringelementparser.h" #include "parser/addressparser.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include "citygml/address.h" #include #include namespace citygml { bool CityObjectElementParser::typeIDTypeMapInitialized = false; bool CityObjectElementParser::attributesSetInitialized = false; std::unordered_map CityObjectElementParser::typeIDTypeMap = std::unordered_map(); std::unordered_set CityObjectElementParser::attributesSet = std::unordered_set(); std::mutex CityObjectElementParser::initializedTypeIDMutex; std::mutex CityObjectElementParser::initializedAttributeSetMutex; #define HANDLE_TYPE( prefix, elementName ) std::pair(NodeType::prefix ## _ ## elementName ## Node.typeID(), CityObject::COT_ ## elementName) #define HANDLE_GROUP_TYPE( prefix, elementName, enumtype ) std::pair(NodeType::prefix ## _ ## elementName ## Node.typeID(), enumtype) #define HANDLE_ATTR( prefix, elementName ) NodeType::prefix ## _ ## elementName ## Node.typeID() CityObjectElementParser::CityObjectElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function callback) : GMLFeatureCollectionElementParser(documentParser, factory, logger) { m_callback = callback; } std::string CityObjectElementParser::elementParserName() const { return "CityObjectElementParser"; } void CityObjectElementParser::initializeTypeIDTypeMap() { // double-checked lock if (!typeIDTypeMapInitialized) { std::lock_guard lock(CityObjectElementParser::initializedTypeIDMutex); if (!typeIDTypeMapInitialized) { typeIDTypeMap.insert(HANDLE_TYPE(GEN, GenericCityObject)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, Building)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, BuildingPart)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, Room)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, BuildingInstallation)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, BuildingFurniture)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, Door)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, Window)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, CityFurniture)); typeIDTypeMap.insert(HANDLE_TYPE(FRN, CityFurniture)); typeIDTypeMap.insert(HANDLE_TYPE(TRANS, Track)); typeIDTypeMap.insert(HANDLE_TYPE(TRANS, Road)); typeIDTypeMap.insert(HANDLE_TYPE(TRANS, Railway)); typeIDTypeMap.insert(HANDLE_TYPE(TRANS, Square)); typeIDTypeMap.insert(HANDLE_GROUP_TYPE(TRANS, TransportationComplex, CityObject::CityObjectsType::COT_TransportationObject)); typeIDTypeMap.insert(HANDLE_GROUP_TYPE(TRANS, TrafficArea, CityObject::CityObjectsType::COT_TransportationObject)); typeIDTypeMap.insert(HANDLE_GROUP_TYPE(TRANS, AuxiliaryTrafficArea, CityObject::CityObjectsType::COT_TransportationObject)); typeIDTypeMap.insert(HANDLE_TYPE(VEG, PlantCover)); typeIDTypeMap.insert(HANDLE_TYPE(VEG, SolitaryVegetationObject)); typeIDTypeMap.insert(HANDLE_TYPE(WTR, WaterBody)); typeIDTypeMap.insert(HANDLE_GROUP_TYPE(WTR, WaterSurface, CityObject::COT_WaterBody)); typeIDTypeMap.insert(HANDLE_GROUP_TYPE(WTR, WaterGroundSurface, CityObject::COT_WaterBody)); typeIDTypeMap.insert(HANDLE_GROUP_TYPE(WTR, WaterClosureSurface, CityObject::COT_WaterBody)); typeIDTypeMap.insert(HANDLE_TYPE(LUSE, LandUse)); typeIDTypeMap.insert(HANDLE_TYPE(SUB, Tunnel)); typeIDTypeMap.insert(HANDLE_TYPE(BRID, Bridge)); typeIDTypeMap.insert(HANDLE_TYPE(BRID, BridgeConstructionElement)); typeIDTypeMap.insert(HANDLE_TYPE(BRID, BridgeInstallation)); typeIDTypeMap.insert(HANDLE_TYPE(BRID, BridgePart)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, WallSurface)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, RoofSurface)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, GroundSurface)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, ClosureSurface)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, FloorSurface)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, InteriorWallSurface)); typeIDTypeMap.insert(HANDLE_TYPE(BLDG, CeilingSurface)); typeIDTypeMap.insert(HANDLE_TYPE(GRP, CityObjectGroup)); typeIDTypeMap.insert(HANDLE_TYPE(DEM, ReliefFeature)); typeIDTypeMapInitialized = true; } } } void CityObjectElementParser::initializeAttributesSet() { // double-checked lock if (!attributesSetInitialized) { std::lock_guard lock(CityObjectElementParser::initializedAttributeSetMutex); if (!attributesSetInitialized) { attributesSet.insert(HANDLE_ATTR(CORE, CreationDate)); attributesSet.insert(HANDLE_ATTR(CORE, TerminationDate)); attributesSet.insert(HANDLE_ATTR(BLDG, Type)); attributesSet.insert(HANDLE_ATTR(BLDG, Class)); attributesSet.insert(HANDLE_ATTR(BLDG, Function)); attributesSet.insert(HANDLE_ATTR(BLDG, Usage)); attributesSet.insert(HANDLE_ATTR(BLDG, YearOfConstruction)); attributesSet.insert(HANDLE_ATTR(BLDG, YearOfDemolition)); attributesSet.insert(HANDLE_ATTR(BLDG, StoreyHeightsAboveGround)); attributesSet.insert(HANDLE_ATTR(BLDG, StoreyHeightsBelowGround)); attributesSet.insert(HANDLE_ATTR(BLDG, StoreysBelowGround)); attributesSet.insert(HANDLE_ATTR(BLDG, StoreysAboveGround)); attributesSet.insert(HANDLE_ATTR(BLDG, MeasuredHeight)); attributesSet.insert(HANDLE_ATTR(BLDG, RoofType)); attributesSet.insert(HANDLE_ATTR(VEG, Class )); attributesSet.insert(HANDLE_ATTR(VEG, Function )); attributesSet.insert(HANDLE_ATTR(VEG, AverageHeight )); attributesSet.insert(HANDLE_ATTR(VEG, Species )); attributesSet.insert(HANDLE_ATTR(VEG, Height )); attributesSet.insert(HANDLE_ATTR(VEG, TrunkDiameter )); attributesSet.insert(HANDLE_ATTR(VEG, CrownDiameter )); attributesSet.insert(HANDLE_ATTR(FRN, Class)); attributesSet.insert(HANDLE_ATTR(FRN, Function)); attributesSet.insert(HANDLE_ATTR(GRP, Class)); attributesSet.insert(HANDLE_ATTR(GRP, Function)); attributesSet.insert(HANDLE_ATTR(GRP, Usage)); attributesSet.insert(HANDLE_ATTR(GEN, Class)); attributesSet.insert(HANDLE_ATTR(GEN, Function)); attributesSet.insert(HANDLE_ATTR(GEN, Usage)); attributesSet.insert(HANDLE_ATTR(LUSE, Class)); attributesSet.insert(HANDLE_ATTR(LUSE, Function)); attributesSet.insert(HANDLE_ATTR(LUSE, Usage)); attributesSet.insert(HANDLE_ATTR(DEM, Lod)); attributesSet.insert(HANDLE_ATTR(TRANS, Usage)); attributesSet.insert(HANDLE_ATTR(TRANS, Function)); attributesSet.insert(HANDLE_ATTR(TRANS, SurfaceMaterial)); attributesSet.insert(HANDLE_ATTR(WTR, Class)); attributesSet.insert(HANDLE_ATTR(WTR, Function)); attributesSet.insert(HANDLE_ATTR(WTR, Usage)); attributesSet.insert(HANDLE_ATTR(WTR, WaterLevel)); attributesSetInitialized = true; } } } bool CityObjectElementParser::handlesElement(const NodeType::XMLNode& node) const { initializeTypeIDTypeMap(); return typeIDTypeMap.count(node.typeID()) > 0; } bool CityObjectElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { initializeTypeIDTypeMap(); auto it = typeIDTypeMap.find(node.typeID()); if (it == typeIDTypeMap.end()) { CITYGML_LOG_ERROR(m_logger, "Expected start tag of CityObject but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createCityObject(attributes.getCityGMLIDAttribute(), static_cast(it->second)); return true; } bool CityObjectElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { m_callback(m_model); m_model = nullptr; return true; } bool CityObjectElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { initializeAttributesSet(); if (m_model == nullptr) { throw std::runtime_error("CityObjectElementParser::parseChildElementStartTag called before CityObjectElementParser::parseElementStartTag"); } if ( node == NodeType::GEN_StringAttributeNode || node == NodeType::GEN_DoubleAttributeNode || node == NodeType::GEN_IntAttributeNode || node == NodeType::GEN_DateAttributeNode || node == NodeType::GEN_UriAttributeNode) { m_lastAttributeName = attributes.getAttribute("name"); } else if (attributesSet.count(node.typeID()) > 0 || node == NodeType::GEN_ValueNode) { return true; } else if (node == NodeType::BLDG_BoundedByNode || node == NodeType::BLDG_OuterBuildingInstallationNode || node == NodeType::BLDG_InteriorBuildingInstallationNode || node == NodeType::BLDG_InteriorFurnitureNode || node == NodeType::BLDG_RoomInstallationNode || node == NodeType::BLDG_InteriorRoomNode || node == NodeType::BLDG_OpeningNode || node == NodeType::BLDG_ConsistsOfBuildingPartNode || node == NodeType::GRP_GroupMemberNode || node == NodeType::GRP_ParentNode || node == NodeType::TRANS_TrafficAreaNode || node == NodeType::TRANS_AuxiliaryTrafficAreaNode || node == NodeType::WTR_BoundedByNode) { setParserForNextElement(new CityObjectElementParser(m_documentParser, m_factory, m_logger, [this](CityObject* obj) { m_model->addChildCityObject(obj); })); } else if (node == NodeType::APP_AppearanceNode // Compatibility with CityGML 1.0 (in CityGML 2 CityObjects can only contain appearanceMember elements) || node == NodeType::APP_AppearanceMemberNode) { setParserForNextElement(new AppearanceElementParser(m_documentParser, m_factory, m_logger)); } else if (node == NodeType::BLDG_Lod1MultiCurveNode || node == NodeType::BLDG_Lod1MultiSurfaceNode || node == NodeType::BLDG_Lod1SolidNode || node == NodeType::BLDG_Lod1TerrainIntersectionNode || node == NodeType::GEN_Lod1TerrainIntersectionNode || node == NodeType::FRN_Lod1TerrainIntersectionNode || node == NodeType::LUSE_Lod1MultiSurfaceNode || node == NodeType::TRANS_Lod1MultiSurfaceNode || node == NodeType::WTR_Lod1MultiCurveNode || node == NodeType::WTR_Lod1MultiSurfaceNode || node == NodeType::WTR_Lod1SolidNode) { parseGeometryForLODLevel(1); } else if (node == NodeType::BLDG_Lod2MultiCurveNode || node == NodeType::BLDG_Lod2MultiSurfaceNode || node == NodeType::BLDG_Lod2SolidNode || node == NodeType::BLDG_Lod2TerrainIntersectionNode || node == NodeType::GEN_Lod2TerrainIntersectionNode || node == NodeType::FRN_Lod2TerrainIntersectionNode || node == NodeType::LUSE_Lod2MultiSurfaceNode || node == NodeType::TRANS_Lod2MultiSurfaceNode || node == NodeType::WTR_Lod2SolidNode || node == NodeType::WTR_Lod2SurfaceNode) { parseGeometryForLODLevel(2); } else if (node == NodeType::BLDG_Lod3MultiCurveNode || node == NodeType::BLDG_Lod3MultiSurfaceNode || node == NodeType::BLDG_Lod3SolidNode || node == NodeType::BLDG_Lod3TerrainIntersectionNode || node == NodeType::GEN_Lod3TerrainIntersectionNode || node == NodeType::FRN_Lod3TerrainIntersectionNode || node == NodeType::LUSE_Lod3MultiSurfaceNode || node == NodeType::TRANS_Lod3MultiSurfaceNode || node == NodeType::WTR_Lod3SolidNode || node == NodeType::WTR_Lod3SurfaceNode) { parseGeometryForLODLevel(3); } else if (node == NodeType::BLDG_Lod4MultiCurveNode || node == NodeType::BLDG_Lod4MultiSurfaceNode || node == NodeType::BLDG_Lod4SolidNode || node == NodeType::BLDG_Lod4TerrainIntersectionNode || node == NodeType::GEN_Lod4TerrainIntersectionNode || node == NodeType::FRN_Lod4TerrainIntersectionNode || node == NodeType::LUSE_Lod4MultiSurfaceNode || node == NodeType::TRANS_Lod4MultiSurfaceNode || node == NodeType::WTR_Lod4SolidNode || node == NodeType::WTR_Lod4SurfaceNode) { parseGeometryForLODLevel(4); } else if (node == NodeType::GEN_Lod1GeometryNode || node == NodeType::FRN_Lod1GeometryNode || node == NodeType::VEG_Lod1GeometryNode) { parseGeometryPropertyElementForLODLevel(1, attributes.getCityGMLIDAttribute()); } else if (node == NodeType::GEN_Lod2GeometryNode || node == NodeType::FRN_Lod2GeometryNode || node == NodeType::BLDG_Lod2GeometryNode || node == NodeType::VEG_Lod2GeometryNode) { parseGeometryPropertyElementForLODLevel(2, attributes.getCityGMLIDAttribute()); } else if (node == NodeType::GEN_Lod3GeometryNode || node == NodeType::FRN_Lod3GeometryNode || node == NodeType::BLDG_Lod3GeometryNode || node == NodeType::VEG_Lod3GeometryNode) { parseGeometryPropertyElementForLODLevel(3, attributes.getCityGMLIDAttribute()); } else if (node == NodeType::GEN_Lod4GeometryNode || node == NodeType::FRN_Lod4GeometryNode || node == NodeType::BLDG_Lod4GeometryNode || node == NodeType::VEG_Lod4GeometryNode) { parseGeometryPropertyElementForLODLevel(4, attributes.getCityGMLIDAttribute()); } else if (node == NodeType::VEG_Lod1ImplicitRepresentationNode || node == NodeType::FRN_Lod1ImplicitRepresentationNode || node == NodeType::GEN_Lod1ImplicitRepresentationNode) { parseImplicitGeometryForLODLevel(1); } else if (node == NodeType::VEG_Lod2ImplicitRepresentationNode || node == NodeType::FRN_Lod2ImplicitRepresentationNode || node == NodeType::GEN_Lod2ImplicitRepresentationNode) { parseImplicitGeometryForLODLevel(2); } else if (node == NodeType::VEG_Lod3ImplicitRepresentationNode || node == NodeType::FRN_Lod3ImplicitRepresentationNode || node == NodeType::GEN_Lod3ImplicitRepresentationNode) { parseImplicitGeometryForLODLevel(3); } else if (node == NodeType::VEG_Lod4ImplicitRepresentationNode || node == NodeType::FRN_Lod4ImplicitRepresentationNode || node == NodeType::GEN_Lod4ImplicitRepresentationNode) { parseImplicitGeometryForLODLevel(4); } else if (node == NodeType::CORE_GeneralizesToNode || node == NodeType::CORE_ExternalReferenceNode || node == NodeType::GML_MultiPointNode || node == NodeType::GRP_GeometryNode || node == NodeType::DEM_ReliefComponentNode || node == NodeType::GEN_Lod0GeometryNode || node == NodeType::GEN_Lod0ImplicitRepresentationNode || node == NodeType::GEN_Lod0TerrainIntersectionNode || node == NodeType::TRANS_Lod0NetworkNode || node == NodeType::WTR_Lod0MultiCurveNode || node == NodeType::WTR_Lod0MultiSurfaceNode) { CITYGML_LOG_INFO(m_logger, "Skipping CityObject child element <" << node << "> at " << getDocumentLocation() << " (Currently not supported!)"); setParserForNextElement(new SkipElementParser(m_documentParser, m_logger, node)); return true; } else if (node == NodeType::BLDG_AddressNode || node == NodeType::CORE_AddressNode || node == NodeType::CORE_XalAddressNode) { setParserForNextElement(new AddressParser(m_documentParser, m_factory, m_logger, [this](std::unique_ptr
&& address) { m_model->setAddress(std::move(address)); })); return true; } else { return GMLFeatureCollectionElementParser::parseChildElementStartTag(node, attributes); } return true; } bool CityObjectElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("CityObjectElementParser::parseChildElementEndTag called before CityObjectElementParser::parseElementStartTag"); } initializeAttributesSet(); if ( node == NodeType::GEN_StringAttributeNode || node == NodeType::GEN_DoubleAttributeNode || node == NodeType::GEN_IntAttributeNode || node == NodeType::GEN_DateAttributeNode || node == NodeType::GEN_UriAttributeNode) { m_lastAttributeName = ""; return true; } else if (node == NodeType::GEN_ValueNode) { if (!m_lastAttributeName.empty()) { m_model->setAttribute(m_lastAttributeName, characters); } else { CITYGML_LOG_WARN(m_logger, "Found value node (" << NodeType::GEN_ValueNode << ") outside attribute node... ignore."); } return true; } else if (attributesSet.count(node.typeID()) > 0) { if (!characters.empty()) { m_model->setAttribute(node.name(), characters); } return true; } else if (node == NodeType::BLDG_BoundedByNode || node == NodeType::BLDG_OuterBuildingInstallationNode || node == NodeType::BLDG_InteriorBuildingInstallationNode || node == NodeType::BLDG_InteriorFurnitureNode || node == NodeType::BLDG_RoomInstallationNode || node == NodeType::BLDG_InteriorRoomNode || node == NodeType::BLDG_OpeningNode || node == NodeType::APP_AppearanceNode || node == NodeType::APP_AppearanceMemberNode || node == NodeType::BLDG_Lod1MultiCurveNode || node == NodeType::BLDG_Lod1MultiSurfaceNode || node == NodeType::BLDG_Lod1SolidNode || node == NodeType::BLDG_Lod1TerrainIntersectionNode || node == NodeType::BLDG_Lod2GeometryNode || node == NodeType::BLDG_Lod2MultiCurveNode || node == NodeType::BLDG_Lod2MultiSurfaceNode || node == NodeType::BLDG_Lod2SolidNode || node == NodeType::BLDG_Lod2TerrainIntersectionNode || node == NodeType::BLDG_Lod3GeometryNode || node == NodeType::BLDG_Lod3MultiCurveNode || node == NodeType::BLDG_Lod3MultiSurfaceNode || node == NodeType::BLDG_Lod3SolidNode || node == NodeType::BLDG_Lod3TerrainIntersectionNode || node == NodeType::BLDG_Lod4GeometryNode || node == NodeType::BLDG_Lod4MultiCurveNode || node == NodeType::BLDG_Lod4MultiSurfaceNode || node == NodeType::BLDG_Lod4SolidNode || node == NodeType::BLDG_Lod4TerrainIntersectionNode || node == NodeType::GEN_Lod1GeometryNode || node == NodeType::GEN_Lod2GeometryNode || node == NodeType::GEN_Lod3GeometryNode || node == NodeType::GEN_Lod4GeometryNode || node == NodeType::GEN_Lod1TerrainIntersectionNode || node == NodeType::GEN_Lod2TerrainIntersectionNode || node == NodeType::GEN_Lod3TerrainIntersectionNode || node == NodeType::GEN_Lod4TerrainIntersectionNode || node == NodeType::GEN_Lod1ImplicitRepresentationNode || node == NodeType::GEN_Lod2ImplicitRepresentationNode || node == NodeType::GEN_Lod3ImplicitRepresentationNode || node == NodeType::GEN_Lod4ImplicitRepresentationNode || node == NodeType::VEG_Lod1ImplicitRepresentationNode || node == NodeType::VEG_Lod2ImplicitRepresentationNode || node == NodeType::VEG_Lod3ImplicitRepresentationNode || node == NodeType::VEG_Lod4ImplicitRepresentationNode || node == NodeType::CORE_ExternalReferenceNode || node == NodeType::BLDG_ConsistsOfBuildingPartNode || node == NodeType::FRN_Lod1GeometryNode || node == NodeType::FRN_Lod1TerrainIntersectionNode || node == NodeType::FRN_Lod1ImplicitRepresentationNode || node == NodeType::FRN_Lod2GeometryNode || node == NodeType::FRN_Lod2TerrainIntersectionNode || node == NodeType::FRN_Lod2ImplicitRepresentationNode || node == NodeType::FRN_Lod3GeometryNode || node == NodeType::FRN_Lod3TerrainIntersectionNode || node == NodeType::FRN_Lod3ImplicitRepresentationNode || node == NodeType::FRN_Lod4GeometryNode || node == NodeType::FRN_Lod4TerrainIntersectionNode || node == NodeType::FRN_Lod4ImplicitRepresentationNode || node == NodeType::CORE_GeneralizesToNode || node == NodeType::GML_MultiPointNode || node == NodeType::GRP_GroupMemberNode || node == NodeType::GRP_ParentNode || node == NodeType::LUSE_Lod1MultiSurfaceNode || node == NodeType::LUSE_Lod2MultiSurfaceNode || node == NodeType::LUSE_Lod3MultiSurfaceNode || node == NodeType::LUSE_Lod4MultiSurfaceNode || node == NodeType::DEM_ReliefComponentNode || node == NodeType::GEN_Lod0GeometryNode || node == NodeType::GEN_Lod0ImplicitRepresentationNode || node == NodeType::GEN_Lod0TerrainIntersectionNode || node == NodeType::TRANS_Lod0NetworkNode || node == NodeType::TRANS_TrafficAreaNode || node == NodeType::TRANS_AuxiliaryTrafficAreaNode || node == NodeType::TRANS_Lod1MultiSurfaceNode || node == NodeType::TRANS_Lod2MultiSurfaceNode || node == NodeType::TRANS_Lod3MultiSurfaceNode || node == NodeType::TRANS_Lod4MultiSurfaceNode || node == NodeType::WTR_Lod0MultiCurveNode || node == NodeType::WTR_Lod0MultiSurfaceNode || node == NodeType::WTR_Lod1MultiCurveNode || node == NodeType::WTR_Lod1MultiSurfaceNode || node == NodeType::WTR_Lod1SolidNode || node == NodeType::WTR_Lod2SolidNode || node == NodeType::WTR_Lod3SolidNode || node == NodeType::WTR_Lod4SolidNode || node == NodeType::WTR_Lod2SurfaceNode || node == NodeType::WTR_Lod3SurfaceNode || node == NodeType::WTR_Lod4SurfaceNode || node == NodeType::WTR_BoundedByNode || node == NodeType::BLDG_AddressNode || node == NodeType::CORE_AddressNode || node == NodeType::CORE_XalAddressNode) { return true; } return GMLFeatureCollectionElementParser::parseChildElementEndTag(node, characters); } FeatureObject* CityObjectElementParser::getFeatureObject() { return m_model; } void CityObjectElementParser::parseGeometryForLODLevel(int lod) { setParserForNextElement(new GeometryElementParser(m_documentParser, m_factory, m_logger, lod, m_model->getType(), [this](Geometry* geom) { m_model->addGeometry(geom); })); } void CityObjectElementParser::parseImplicitGeometryForLODLevel(int lod) { setParserForNextElement(new ImplicitGeometryElementParser(m_documentParser, m_factory, m_logger, lod, m_model->getType(), [this](ImplicitGeometry* imp) { m_model->addImplictGeometry(imp); })); } void CityObjectElementParser::parseGeometryPropertyElementForLODLevel(int lod, const std::string& id) { setParserForNextElement(new DelayedChoiceElementParser(m_documentParser, m_logger, { new PolygonElementParser(m_documentParser, m_factory, m_logger, [id, lod, this](std::shared_ptr p) { Geometry* geom = m_factory.createGeometry(id, m_model->getType(), lod); geom->addPolygon(p); m_model->addGeometry(geom); }), new LineStringElementParser(m_documentParser, m_factory, m_logger, [id, lod, this](std::shared_ptr l) { Geometry* geom = m_factory.createGeometry(id, m_model->getType(), lod); geom->addLineString(l); m_model->addGeometry(geom); }), new GeometryElementParser(m_documentParser, m_factory, m_logger, lod, m_model->getType(), [this](Geometry* geom) { m_model->addGeometry(geom); }) })); } } libcitygml-2.0/sources/src/parser/delayedchoiceelementparser.cpp000066400000000000000000000043401256066205500253450ustar00rootroot00000000000000#include "parser/delayedchoiceelementparser.h" #include "parser/documentlocation.h" #include "parser/citygmldocumentparser.h" #include "citygml/citygmllogger.h" #include #include namespace citygml { DelayedChoiceElementParser::DelayedChoiceElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger, std::vector choices) : ElementParser(documentParser, logger) { m_choices = choices; } bool DelayedChoiceElementParser::startElement(const NodeType::XMLNode& node, Attributes& attributes) { ElementParser* choosenParser = nullptr; for (ElementParser* parser : m_choices) { if (choosenParser == nullptr && parser->handlesElement(node)) { choosenParser = parser; } else { delete parser; } } if (choosenParser != nullptr) { m_documentParser.removeCurrentElementParser(this); m_documentParser.setCurrentElementParser(choosenParser); return choosenParser->startElement(node, attributes); } else { CITYGML_LOG_ERROR(m_logger, "DelayedChoiceElementParser could not find a parser to handle <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("No parser for XML element found."); } } bool DelayedChoiceElementParser::endElement(const NodeType::XMLNode&, const std::string&) { throw std::runtime_error("DelayedChoiceElementParser::endElement must never be called."); } bool DelayedChoiceElementParser::handlesElement(const NodeType::XMLNode& node) const { for (const ElementParser* parser : m_choices) { if (parser->handlesElement(node)) { return true; } } return false; } std::string DelayedChoiceElementParser::elementParserName() const { std::stringstream ss; ss << "DelayedChoiceElementParser ("; for (size_t i = 0; i < m_choices.size(); i++) { if (i > 0) { ss << " | "; } ss << m_choices[i]->elementParserName(); } ss << ")"; return ss.str(); } } libcitygml-2.0/sources/src/parser/elementparser.cpp000066400000000000000000000006571256066205500226510ustar00rootroot00000000000000#include "parser/elementparser.h" #include "parser/citygmldocumentparser.h" namespace citygml { void ElementParser::setParserForNextElement(ElementParser* parser) { m_documentParser.setCurrentElementParser(parser); } const DocumentLocation& ElementParser::getDocumentLocation() const { return m_documentParser.getDocumentLocation(); } ElementParser::~ElementParser() { } } libcitygml-2.0/sources/src/parser/geocoordinatetransformer.cpp000066400000000000000000000260011256066205500250770ustar00rootroot00000000000000#include "parser/geocoordinatetransformer.h" #include "citygml/citygmllogger.h" #include "citygml/citymodel.h" #include "citygml/cityobject.h" #include "citygml/implictgeometry.h" #include "citygml/geometry.h" #include "citygml/polygon.h" #include "citygml/linestring.h" #include "citygml/vecs.hpp" #include "citygml/envelope.h" #ifdef USE_GDAL #include "ogrsf_frmts.h" #include class GeoTransform { public: GeoTransform( const std::string& destURN, std::shared_ptr logger ) { m_logger = logger; m_transformation = nullptr; m_destSRSURN = destURN; m_sourceURN = ""; OGRErr err = m_destSRS.SetFromUserInput(destURN.c_str()); if (err != OGRERR_NONE) { CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for destination SRS " << destURN << ". OGR error code: " << err << "."); throw std::runtime_error("Invalid destination spatial reference system."); } } GeoTransform(const GeoTransform& other) { m_logger = other.m_logger; m_destSRSURN = other.m_destSRSURN; m_destSRS = other.m_destSRS; m_sourceURN = ""; m_transformation = nullptr; } ~GeoTransform() { if (m_transformation != nullptr) { OCTDestroyCoordinateTransformation(m_transformation); } } bool valid() const { return m_transformation != nullptr; } void transform( TVec3d &p ) const { if (m_transformation == nullptr) { return; } m_transformation->Transform( 1, &p.x, &p.y ); } void transform( TVec2d &p ) const { if (m_transformation == nullptr) { return; } m_transformation->Transform( 1, &p.x, &p.y ); } bool hasSourceSRS(const std::string& sourceURN) { if (m_transformation == nullptr) { return false; } OGRSpatialReference refSys; OGRErr err = refSys.SetFromUserInput(sourceURN.c_str()); if (err != OGRERR_NONE) { return false; } return refSys.IsSame(m_transformation->GetSourceCS()); } void setSourceSRS(const std::string& sourceURN) { if (m_transformation != nullptr) { OCTDestroyCoordinateTransformation(m_transformation); m_transformation = nullptr; } OGRSpatialReference sourceSRS; OGRErr err = sourceSRS.SetFromUserInput(sourceURN.c_str()); if (err != OGRERR_NONE) { CITYGML_LOG_ERROR(m_logger, "Could not create OGRSpatialReference for source SRS " << sourceURN << ". OGR error code: " << err << "."); return; } m_transformation = OGRCreateCoordinateTransformation(&sourceSRS, &m_destSRS); if (m_transformation == nullptr) { CITYGML_LOG_ERROR(m_logger, "Could not create transformation from source SRS " << sourceURN << " to destination SRS " << m_destSRSURN << "."); return; } m_sourceURN = sourceURN; } std::string sourceURN() const { return m_sourceURN; } private: OGRSpatialReference m_destSRS; std::string m_destSRSURN; std::string m_sourceURN; OGRCoordinateTransformation* m_transformation; std::shared_ptr m_logger; }; namespace citygml { GeoCoordinateTransformer::GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr logger) { m_destinationSRS = destSRS; m_logger = logger; } void GeoCoordinateTransformer::transformToDestinationSRS(CityModel* model) { GeoTransform transformation(m_destinationSRS, m_logger); if (!model->getEnvelope().srsName().empty()) { transformation.setSourceSRS(model->getEnvelope().srsName()); } for (unsigned int i = 0; i < model->getNumRootCityObjects(); i++) { transformRecursive(model->getRootCityObject(i), transformation); } } void GeoCoordinateTransformer::transformRecursive(CityObject& obj, GeoTransform& transformation) { if (!obj.getEnvelope().srsName().empty() && !transformation.hasSourceSRS(obj.getEnvelope().srsName())) { GeoTransform childTransformation = transformation; childTransformation.setSourceSRS(obj.getEnvelope().srsName()); transformRecursive_helper(obj, childTransformation); } else { transformRecursive_helper(obj, transformation); } } void GeoCoordinateTransformer::transformRecursive_helper(CityObject& obj, GeoTransform& transformation) { if (obj.getEnvelope().validBounds()) { if (transformation.valid()) { TVec3d lowerBound = obj.getEnvelope().getLowerBound(); TVec3d upperBound = obj.getEnvelope().getUpperBound(); transformation.transform(lowerBound); transformation.transform(upperBound); Envelope* newEnvelope = new Envelope(m_destinationSRS); newEnvelope->setLowerBound(lowerBound); newEnvelope->setUpperBound(upperBound); obj.setEnvelope(newEnvelope); } else { CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for CityObject with id '" << obj.getId() << "'. Envelope (Bounding Box) is not transformed."); } } for (unsigned int i = 0; i < obj.getChildCityObjectsCount(); i++) { transformRecursive(obj.getChildCityObject(i), transformation); } for (unsigned int i = 0; i < obj.getImplicitGeometryCount(); i++) { transformRecursive(obj.getImplicitGeometry(i), transformation); } for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) { transform(obj.getGeometry(i), transformation); } } void GeoCoordinateTransformer::transformRecursive(ImplicitGeometry& obj, GeoTransform& transformation) { if (!obj.getSRSName().empty() && !transformation.hasSourceSRS(obj.getSRSName())) { GeoTransform childTransformation = transformation; childTransformation.setSourceSRS(obj.getSRSName()); transformRecursive_helper(obj, childTransformation); } else { transformRecursive_helper(obj, transformation); } } void GeoCoordinateTransformer::transformRecursive_helper(ImplicitGeometry& obj, GeoTransform& transformation) { TVec3d referencePoint = obj.getReferencePoint(); if (transformation.valid()) { transformation.transform(referencePoint); obj.setReferencePoint(referencePoint); obj.setSRSName(m_destinationSRS); } else { CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for ImplicitGeometry with id '" << obj.getId() << "'. Reference Point is not transformed."); } // Do not transform the geometry of an ImplicitGeometry object. Implicit Geometries share Geometry objects but each implicit geometry // defines its own transformation on the vertices of the shared geometry. Hence those vertices are in a local coordinate system. Read // the citygml documentation for more details. //for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) { // transform(obj.getGeometry(i), transformation); //} } void GeoCoordinateTransformer::transform(Geometry& obj, GeoTransform& transformation) { if (!transformation.valid()) { CITYGML_LOG_WARN(m_logger, "No valid spatial reference system is given for Geometry with id '" << obj.getId() << "'. Child Polygons are not transformed" << "(unless they are shared with another geometry for which a spatial reference system is defined)"); return; } for (unsigned int i = 0; i < obj.getPolygonsCount(); i++) { const auto poly = obj.getPolygon(i); auto it = m_transformedPolygonsSourceURNMap.find(poly.get()); if (it == m_transformedPolygonsSourceURNMap.end()) { for (TVec3d& vertex : poly->getVertices()) { transformation.transform(vertex); } m_transformedPolygonsSourceURNMap[poly.get()] = transformation.sourceURN(); } else if (it->second != transformation.sourceURN()) { CITYGML_LOG_WARN(m_logger, "Polygon with id '" << poly->getId() << "' was already transformed from " << it->second << " to " << m_destinationSRS << ". But the spatial reference system of Geometry object with id '" << obj.getId() << "' that also contains the polygon is different " << "(" << transformation.sourceURN() << "). Ignoring new source SRS."); } } for (unsigned int i = 0; i < obj.getLineStringCount(); i++) { const auto lineString = obj.getLineString(i); auto it = m_transformedLineStringsSourceURNMap.find(lineString.get()); if (it == m_transformedLineStringsSourceURNMap.end()) { if (lineString->getDimensions() == 2) { for (TVec2d& vertex : lineString->getVertices2D()) { transformation.transform(vertex); } } else if (lineString->getDimensions() == 3) { for (TVec3d& vertex : lineString->getVertices3D()) { transformation.transform(vertex); } } m_transformedLineStringsSourceURNMap[lineString.get()] = transformation.sourceURN(); } else if (it->second != transformation.sourceURN()) { CITYGML_LOG_WARN(m_logger, "LineString with id '" << lineString->getId() << "' was already transformed from " << it->second << " to " << m_destinationSRS << ". But the spatial reference system of Geometry object with id '" << obj.getId() << "' that also contains the LineString is different " << "(" << transformation.sourceURN() << "). Ignoring new source SRS."); } } for (unsigned int i = 0; i < obj.getGeometriesCount(); i++) { transform(obj.getGeometry(i), transformation); } } } #else class GeoTransform { }; namespace citygml { void GeoCoordinateTransformer::transformToDestinationSRS(CityModel* model) { CITYGML_LOG_WARN(m_logger, "Coordinate transformation to " << m_destinationSRS << " requested, but libcitygml was build without GDAL. The coordinates will not be transformed."); } void GeoCoordinateTransformer::transformRecursive(CityObject&, GeoTransform&) {} void GeoCoordinateTransformer::transformRecursive_helper(CityObject&, GeoTransform&) {} void GeoCoordinateTransformer::transformRecursive(ImplicitGeometry&, GeoTransform&) {} void GeoCoordinateTransformer::transformRecursive_helper(ImplicitGeometry&, GeoTransform&) {} void GeoCoordinateTransformer::transform(Geometry&, GeoTransform&) {} } #endif libcitygml-2.0/sources/src/parser/geometryelementparser.cpp000066400000000000000000000153641256066205500244260ustar00rootroot00000000000000#include "parser/geometryelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/polygonelementparser.h" #include "parser/delayedchoiceelementparser.h" #include "parser/sequenceparser.h" #include "citygml/geometry.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include "citygml/polygon.h" #include #include namespace citygml { // The nodes that are valid Geometry Objects std::unordered_set geometryTypeIDSet; bool geometryTypeIDSetInitialized = false; std::mutex geometryElement_initializedTypeIDMutex; GeometryElementParser::GeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, int lodLevel, CityObject::CityObjectsType parentType, std::function callback) : GMLObjectElementParser(documentParser, factory, logger) { m_callback = callback; m_lodLevel = lodLevel; m_parentType = parentType; } std::string GeometryElementParser::elementParserName() const { return "GeometryElementParser"; } bool GeometryElementParser::handlesElement(const NodeType::XMLNode& node) const { if(!geometryTypeIDSetInitialized) { std::lock_guard lock(geometryElement_initializedTypeIDMutex); if (!geometryTypeIDSetInitialized) { geometryTypeIDSet.insert(NodeType::GML_CompositeSolidNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_SolidNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_MultiSurfaceNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_CompositeSurfaceNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_TriangulatedSurfaceNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_OrientableSurfaceNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_MultiSolidNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_CompositeSolidNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_ShellNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_PolyhedralSurfaceNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_SurfaceNode.typeID()); geometryTypeIDSet.insert(NodeType::GML_ShellNode.typeID()); geometryTypeIDSetInitialized = true; } } return geometryTypeIDSet.count(node.typeID()) > 0; } bool GeometryElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag of GeometryObject but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createGeometry(attributes.getCityGMLIDAttribute(), m_parentType, m_lodLevel); m_orientation = attributes.getAttribute("orientation", "+"); // A gml:OrientableSurface may define a negative orientation return true; } bool GeometryElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { if (m_orientation == "-") { for (int i = 0; i < m_model->getPolygonsCount(); i++) { m_model->getPolygon(i)->setNegNormal(true); } } m_callback(m_model); return true; } bool GeometryElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("GeometryElementParser::parseChildElementStartTag called before GeometryElementParser::parseElementStartTag"); } if (node == NodeType::GML_InteriorNode || node == NodeType::GML_ExteriorNode || node == NodeType::GML_SolidMemberNode) { setParserForNextElement(new GeometryElementParser(m_documentParser, m_factory, m_logger, m_lodLevel, m_parentType, [this](Geometry* child) { m_model->addGeometry(child); })); return true; } else if (node == NodeType::GML_SurfaceMemberNode || node == NodeType::GML_BaseSurfaceNode) { if (attributes.hasXLinkAttribute()) { m_factory.requestSharedPolygonForGeometry(m_model, attributes.getXLinkValue()); } else { std::vector parsers; std::function)> callback1 = [this](std::shared_ptr poly) {m_model->addPolygon(poly);}; std::function callback2 = [this](Geometry* child) {m_model->addGeometry(child);}; parsers.push_back(new PolygonElementParser(m_documentParser, m_factory, m_logger, callback1)); parsers.push_back(new GeometryElementParser(m_documentParser, m_factory, m_logger, m_lodLevel, m_parentType, callback2)); setParserForNextElement(new DelayedChoiceElementParser(m_documentParser, m_logger, parsers)); } return true; } else if (node == NodeType::GML_PatchesNode || node == NodeType::GML_TrianglePatchesNode) { std::function patchParserFactory = [this]() { return new PolygonElementParser(m_documentParser, m_factory, m_logger, [this](std::shared_ptr poly) {m_model->addPolygon(poly);}); }; setParserForNextElement(new SequenceParser(m_documentParser, m_logger, patchParserFactory, node)); } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool GeometryElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("GeometryElementParser::parseChildElementEndTag called before GeometryElementParser::parseElementStartTag"); } if (node == NodeType::GML_InteriorNode || node == NodeType::GML_ExteriorNode || node == NodeType::GML_SolidMemberNode || node == NodeType::GML_SurfaceMemberNode || node == NodeType::GML_BaseSurfaceNode || node == NodeType::GML_PatchesNode || node == NodeType::GML_TrianglePatchesNode) { return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* GeometryElementParser::getObject() { return m_model; } } libcitygml-2.0/sources/src/parser/georeferencedtextureelementparser.cpp000066400000000000000000000044771256066205500270140ustar00rootroot00000000000000#include "parser/georeferencedtextureelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/skipelementparser.h" #include "citygml/georeferencedtexture.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include namespace citygml { GeoReferencedTextureElementParser::GeoReferencedTextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback) : CityGMLElementParser(documentParser, factory, logger) { m_callback = callback; } std::string GeoReferencedTextureElementParser::elementParserName() const { return "GeoReferencedTextureElementParser"; } bool GeoReferencedTextureElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::APP_GeoreferencedTextureNode; } bool GeoReferencedTextureElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (node != NodeType::APP_GeoreferencedTextureNode) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::APP_GeoreferencedTextureNode.name() << "> got " << node << " at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } CITYGML_LOG_WARN(m_logger, "Skipping contents of GeoReferencedTextureElement at " << getDocumentLocation() << ". (Currently not supported!)"); return true; } bool GeoReferencedTextureElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { // Not Implemented return true; } bool GeoReferencedTextureElementParser::parseChildElementStartTag(const NodeType::XMLNode&, Attributes&) { setParserForNextElement(new SkipElementParser(m_documentParser, m_logger)); return true; } bool GeoReferencedTextureElementParser::parseChildElementEndTag(const NodeType::XMLNode&, const std::string&) { setParserForNextElement(new SkipElementParser(m_documentParser, m_logger)); return true; } } libcitygml-2.0/sources/src/parser/gmlfeaturecollectionparser.cpp000066400000000000000000000062201256066205500254170ustar00rootroot00000000000000#include "parser/gmlfeaturecollectionparser.h" #include "parser/attributes.h" #include "parser/parserutils.hpp" #include "parser/nodetypes.h" #include "citygml/citygmllogger.h" #include "citygml/envelope.h" #include "citygml/object.h" #include "citygml/vecs.hpp" #include "citygml/featureobject.h" #include namespace citygml { GMLFeatureCollectionElementParser::GMLFeatureCollectionElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger) : GMLObjectElementParser(documentParser, factory, logger) { m_bounds = nullptr; } bool GMLFeatureCollectionElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (getFeatureObject() == nullptr) { throw std::runtime_error("Invalid call to GMLFeatureCollectionElementParser::parseChildElementStartTag"); } if (node == NodeType::GML_LowerCornerNode || node == NodeType::GML_UpperCornerNode || node == NodeType::GML_BoundedByNode) { return true; } else if (node == NodeType::GML_EnvelopeNode) { if (m_bounds != nullptr) { CITYGML_LOG_WARN(m_logger, "Duplicate definition of " << NodeType::GML_EnvelopeNode << " at " << getDocumentLocation()); return true; } m_bounds = new Envelope(attributes.getAttribute("srsName")); return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool GMLFeatureCollectionElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (getFeatureObject() == nullptr) { throw std::runtime_error("Invalid call to GMLFeatureCollectionElementParser::parseChildElementEndTag"); } if (node == NodeType::GML_LowerCornerNode) { if (m_bounds != nullptr) { m_bounds->setLowerBound(parseValue(characters, m_logger, getDocumentLocation())); } else { CITYGML_LOG_WARN(m_logger, "Definition of " << NodeType::GML_LowerCornerNode << " outside " << NodeType::GML_EnvelopeNode << " at " << getDocumentLocation()); } return true; } else if (node == NodeType::GML_UpperCornerNode) { if (m_bounds != nullptr) { m_bounds->setUpperBound(parseValue(characters, m_logger, getDocumentLocation())); } else { CITYGML_LOG_WARN(m_logger, "Definition of " << NodeType::GML_UpperCornerNode << " outside " << NodeType::GML_EnvelopeNode << " at " << getDocumentLocation()); } return true; } else if (node == NodeType::GML_EnvelopeNode) { getFeatureObject()->setEnvelope(m_bounds); return true; } else if (node == NodeType::GML_BoundedByNode) { return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* GMLFeatureCollectionElementParser::getObject() { return getFeatureObject(); } } libcitygml-2.0/sources/src/parser/gmlobjectparser.cpp000066400000000000000000000031341256066205500231570ustar00rootroot00000000000000#include "parser/gmlobjectparser.h" #include namespace citygml { GMLObjectElementParser::GMLObjectElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger) : CityGMLElementParser(documentParser, factory, logger) { } bool GMLObjectElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (getObject() == nullptr) { throw std::runtime_error("Invalid call to GMLObjectElementParser::parseChildElementStartTag"); } if ( node == NodeType::GML_DescriptionNode || node == NodeType::GML_IdentifierNode || node == NodeType::GML_NameNode || node == NodeType::GML_DescriptionReferenceNode || node == NodeType::GML_MetaDataPropertyNode) { return true; } return false; } bool GMLObjectElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (getObject() == nullptr) { throw std::runtime_error("Invalid call to GMLObjectElementParser::parseChildElementEndTag"); } if ( node == NodeType::GML_DescriptionNode || node == NodeType::GML_IdentifierNode || node == NodeType::GML_NameNode || node == NodeType::GML_DescriptionReferenceNode || node == NodeType::GML_MetaDataPropertyNode) { getObject()->setAttribute(node.name(), characters); return true; } return false; } } libcitygml-2.0/sources/src/parser/implicitgeometryelementparser.cpp000066400000000000000000000157771256066205500261710ustar00rootroot00000000000000#include "parser/implicitgeometryelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/geometryelementparser.h" #include "parser/parserutils.hpp" #include "parser/skipelementparser.h" #include "parser/linestringelementparser.h" #include "parser/polygonelementparser.h" #include "parser/delayedchoiceelementparser.h" #include "citygml/implictgeometry.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include namespace citygml { ImplicitGeometryElementParser::ImplicitGeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, int lodLevel, CityObject::CityObjectsType parentType, std::function callback) : GMLObjectElementParser(documentParser, factory, logger) { m_callback = callback; m_lodLevel = lodLevel; m_parentType = parentType; } std::string ImplicitGeometryElementParser::elementParserName() const { return "ImplicitGeometryElementParser"; } bool ImplicitGeometryElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::CORE_ImplicitGeometryNode; } bool ImplicitGeometryElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag of ImplicitGeometryObject but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createImplictGeometry(attributes.getCityGMLIDAttribute()); return true; } bool ImplicitGeometryElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { m_callback(m_model); return true; } bool ImplicitGeometryElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("ImplicitGeometryElementParser::parseChildElementStartTag called before ImplicitGeometryElementParser::parseElementStartTag"); } if ( node == NodeType::CORE_TransformationMatrixNode || node == NodeType::CORE_ReferencePointNode || node == NodeType::GML_ReferencePointNode || node == NodeType::CORE_MimeTypeNode) { return true; } else if (node == NodeType::GML_PointNode) { m_model->setSRSName(attributes.getAttribute("srsName")); return true; } else if (node == NodeType::GML_PosNode) { std::string srsDimension = attributes.getAttribute("srsDimension","3"); if (srsDimension != "3") { CITYGML_LOG_WARN(m_logger, NodeType::GML_PosNode << " element at " << getDocumentLocation() << " in ImplicitGeometry node has an unsupported 'srsDimension' attribute value of " << srsDimension << " (Only 3 is supported). Trying to parse it anyway."); } return true; } else if (node == NodeType::CORE_RelativeGMLGeometryNode) { if (attributes.hasXLinkAttribute()) { std::string sharedGeomID = attributes.getXLinkValue(); m_factory.requestSharedGeometryWithID(m_model, sharedGeomID); } else { std::string id = attributes.getCityGMLIDAttribute(); setParserForNextElement(new DelayedChoiceElementParser(m_documentParser, m_logger, { new PolygonElementParser(m_documentParser, m_factory, m_logger, [id, this](std::shared_ptr p) { Geometry* geom = m_factory.createGeometry(id, m_parentType, m_lodLevel); geom->addPolygon(p); m_model->addGeometry(m_factory.shareGeometry(geom)); }), new LineStringElementParser(m_documentParser, m_factory, m_logger, [id, this](std::shared_ptr l) { Geometry* geom = m_factory.createGeometry(id, m_parentType, m_lodLevel); geom->addLineString(l); m_model->addGeometry(m_factory.shareGeometry(geom)); }), new GeometryElementParser(m_documentParser, m_factory, m_logger, m_lodLevel, m_parentType, [this](Geometry* geom) { m_model->addGeometry(m_factory.shareGeometry(geom)); }) })); } return true; } else if (node == NodeType::CORE_LibraryObjectNode) { CITYGML_LOG_INFO(m_logger, "Skipping ImplicitGeometry child element <" << node << "> at " << getDocumentLocation() << " (Currently not supported!)"); setParserForNextElement(new SkipElementParser(m_documentParser, m_logger)); return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool ImplicitGeometryElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("ImplicitGeometryElementParser::parseChildElementEndTag called before ImplicitGeometryElementParser::parseElementStartTag"); } if (node == NodeType::CORE_TransformationMatrixNode) { m_model->setTransformMatrix(parseMatrix(characters, m_logger, getDocumentLocation())); return true; } else if (node == NodeType::GML_PosNode) { m_model->setReferencePoint(parseValue(characters, m_logger, getDocumentLocation())); return true; } else if ( node == NodeType::CORE_RelativeGMLGeometryNode || node == NodeType::GML_PointNode || node == NodeType::CORE_ReferencePointNode || node == NodeType::GML_ReferencePointNode || node == NodeType::CORE_LibraryObjectNode) { return true; } else if (node == NodeType::CORE_MimeTypeNode) { m_model->setAttribute(node.name(), characters); } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* ImplicitGeometryElementParser::getObject() { return m_model; } } libcitygml-2.0/sources/src/parser/linearringelementparser.cpp000066400000000000000000000067611256066205500247260ustar00rootroot00000000000000#include "parser/linearringelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/parserutils.hpp" #include "citygml/linearring.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include namespace citygml { LinearRingElementParser::LinearRingElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, bool interior, std::function callback) : GMLObjectElementParser(documentParser, factory, logger) { m_callback = callback; m_interior = interior; } std::string LinearRingElementParser::elementParserName() const { return "LinearRingElementParser"; } bool LinearRingElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::GML_LinearRingNode; } bool LinearRingElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::GML_LinearRingNode << "> but got <" << node << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = new LinearRing(attributes.getCityGMLIDAttribute(), !m_interior); return true; } bool LinearRingElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { if (m_model->getVertices().size() < 4) { CITYGML_LOG_WARN(m_logger, "LinearRing with end tag at " << getDocumentLocation() << " contains less than 4 vertices."); } m_callback(m_model); return true; } bool LinearRingElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("LinearRingElementParser::parseChildElementStartTag called before LinearRingElementParser::parseElementStartTag"); } if (node == NodeType::GML_PosListNode || node == NodeType::GML_PosNode) { std::string dimensions = attributes.getAttribute("srsDimension", "3"); if (dimensions != "3") { CITYGML_LOG_WARN(m_logger, "Attribute srsDimension of element " << node << " contains unsupported value '" << dimensions << "' (only 3 dimensions are support). Trying to parse it anyway..."); } return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool LinearRingElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("LinearRingElementParser::parseChildElementEndTag called before LinearRingElementParser::parseElementStartTag"); } if (node == NodeType::GML_PosListNode) { m_model->setVertices(parseVecList(characters, m_logger, getDocumentLocation())); return true; } else if (node == NodeType::GML_PosNode) { m_model->addVertex(parseValue(characters, m_logger, getDocumentLocation())); return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* LinearRingElementParser::getObject() { return m_model; } } libcitygml-2.0/sources/src/parser/linestringelementparser.cpp000066400000000000000000000077141256066205500247510ustar00rootroot00000000000000#include "parser/linestringelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/parserutils.hpp" #include "citygml/linestring.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include #include namespace citygml { LineStringElementParser::LineStringElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback) : GMLObjectElementParser(documentParser, factory, logger) { m_callback = callback; } std::string LineStringElementParser::elementParserName() const { return "LineStringElementParser"; } bool LineStringElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::GML_LineStringNode || node == NodeType::GML_PointNode; } bool LineStringElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::GML_LineStringNode << "> or <" << NodeType::GML_PointNode << "> but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createLineString(attributes.getCityGMLIDAttribute()); parseDimension(attributes); return true; } bool LineStringElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { m_callback(m_model); return true; } bool LineStringElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("LineStringElementParser::parseChildElementStartTag called before LineStringElementParser::parseElementStartTag"); } if (node == NodeType::GML_PosListNode || node == NodeType::GML_PosNode) { parseDimension(attributes); return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool LineStringElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("LineStringElementParser::parseChildElementEndTag called before LineStringElementParser::parseElementStartTag"); } if (node == NodeType::GML_PosListNode || node == NodeType::GML_PosNode) { if (m_model->getDimensions() < 0) { CITYGML_LOG_ERROR(m_logger, "No srsDimension given for LineString before or as attribute of <" << NodeType::GML_PosListNode << "> child element at " << getDocumentLocation()); } else if (m_model->getDimensions() == 2) { m_model->setVertices2D(parseVecList(characters, m_logger, getDocumentLocation())); } else if (m_model->getDimensions() == 3) { m_model->setVertices3D(parseVecList(characters, m_logger, getDocumentLocation())); } else { CITYGML_LOG_WARN(m_logger, "Unsupported dimension of LineString positions at " << getDocumentLocation() << ". Only 2 and 3 dimensions are supported."); } return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* LineStringElementParser::getObject() { return m_model.get(); } void LineStringElementParser::parseDimension(Attributes& attributes) { std::string dim_str = attributes.getAttribute("srsDimension", ""); if (dim_str.empty()) { return; } int dim = std::stoi(dim_str); m_model->setDimensions(dim); } } libcitygml-2.0/sources/src/parser/materialelementparser.cpp000066400000000000000000000113241256066205500243610ustar00rootroot00000000000000#include "parser/materialelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/parserutils.hpp" #include "parser/skipelementparser.h" #include "citygml/material.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include namespace citygml { MaterialElementParser::MaterialElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback) : GMLObjectElementParser(documentParser, factory, logger) { m_model = nullptr; m_callback = callback; } std::string MaterialElementParser::elementParserName() const { return "MaterialElementParser"; } bool MaterialElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::APP_MaterialNode || node == NodeType::APP_X3DMaterialNode; } bool MaterialElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::APP_MaterialNode.name() << "> got " << node << " at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = std::shared_ptr(m_factory.createMaterial(attributes.getCityGMLIDAttribute())); return true; } bool MaterialElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { m_callback(m_model); return true; } bool MaterialElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("MaterialElementParser::parseChildElementStartTag called before MaterialElementParser::parseElementStartTag"); } if (node == NodeType::APP_DiffuseColorNode || node == NodeType::APP_EmissiveColorNode || node == NodeType::APP_SpecularColorNode || node == NodeType::APP_ShininessNode || node == NodeType::APP_TransparencyNode || node == NodeType::APP_AmbientIntensityNode || node == NodeType::APP_IsFrontNode || node == NodeType::APP_isSmoothNode) { return true; } else if (node == NodeType::APP_TargetNode) { m_lastTargetDefinitionID = attributes.getCityGMLIDAttribute(); return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool MaterialElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("MaterialElementParser::parseChildElementEndTag called before MaterialElementParser::parseElementStartTag"); } if (node == NodeType::APP_DiffuseColorNode) { m_model->setDiffuse(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_EmissiveColorNode) { m_model->setEmissive(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_SpecularColorNode) { m_model->setSpecular(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_ShininessNode) { m_model->setShininess(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_TransparencyNode) { m_model->setTransparency(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_AmbientIntensityNode) { m_model->setAmbientIntensity(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_IsFrontNode) { m_model->setIsFront(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_isSmoothNode) { m_model->setIsSmooth(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_TargetNode) { m_factory.createMaterialTargetDefinition(parseReference(characters, m_logger, getDocumentLocation()), m_model, m_lastTargetDefinitionID); m_lastTargetDefinitionID = ""; } else { return GMLObjectElementParser::parseChildElementEndTag(node, characters); } return true; } Object* MaterialElementParser::getObject() { return m_model.get(); } } libcitygml-2.0/sources/src/parser/nodetypes.cpp000066400000000000000000000734471256066205500220240ustar00rootroot00000000000000#include "parser/nodetypes.h" #include "citygml/utils.h" namespace citygml { // declare static class members std::mutex NodeType::initializedMutex; bool NodeType::nodesInitialized = false; int NodeType::typeCount = -1; std::unordered_map NodeType::nodeNameTypeMap; std::unordered_map NodeType::nodeNameWithPrefixTypeMap; NodeType::XMLNode::XMLNode() { // } NodeType::XMLNode::XMLNode(std::string prefix, std::string name ) : m_name(toLower(name)), m_prefix(toLower(prefix)) { m_typeID = NodeType::typeCount++; } const std::string NodeType::XMLNode::name() const { return m_prefix + ":" + m_name; } const std::string& NodeType::XMLNode::prefix() const { return m_prefix; } const std::string& NodeType::XMLNode::baseName() const { return m_name; } int NodeType::XMLNode::typeID() const { return m_typeID; } bool NodeType::XMLNode::operator==(const NodeType::XMLNode& other) const { return typeID() == other.typeID(); } bool NodeType::XMLNode::operator!=(const NodeType::XMLNode& other) const { return !(*this == other); } bool NodeType::XMLNode::valid() const { return !m_name.empty(); } std::ostream& operator<<(std::ostream& os, const NodeType::XMLNode& o) { if (!o.valid()) { os << "InvalidNode"; } else { os << o.name(); } return os; } const NodeType::XMLNode NodeType::InvalidNode = XMLNode("", ""); #define INITIALIZE_NODE( prefix, elementname ) \ NodeType::prefix ## _ ## elementname ## Node = XMLNode( #prefix , #elementname ); \ NodeType::nodeNameTypeMap[toLower(#elementname)] = &NodeType::prefix ## _ ## elementname ## Node; \ NodeType::nodeNameWithPrefixTypeMap[toLower(#prefix ":" #elementname)] = &NodeType::prefix ## _ ## elementname ## Node; void NodeType::initializeNodeTypes() { // double-checked locking to prevent synchronisation when the node types are already intialized if(!nodesInitialized) { std::lock_guard lock(NodeType::initializedMutex); if (!nodesInitialized) { // CORE INITIALIZE_NODE( CORE, CityModel ) INITIALIZE_NODE( CORE, CityObjectMember ) INITIALIZE_NODE( CORE, CreationDate ) INITIALIZE_NODE( CORE, TerminationDate ) INITIALIZE_NODE( CORE, GeneralizesTo) INITIALIZE_NODE( CORE, ExternalReference) INITIALIZE_NODE( CORE, InformationSystem) INITIALIZE_NODE( CORE, ExternalObject) INITIALIZE_NODE( CORE, Uri) INITIALIZE_NODE( CORE, Name) INITIALIZE_NODE( CORE, Address ) INITIALIZE_NODE( CORE, XalAddress ) INITIALIZE_NODE( CORE, ImplicitGeometry ) INITIALIZE_NODE( CORE, RelativeGMLGeometry ) INITIALIZE_NODE( CORE, TransformationMatrix ) INITIALIZE_NODE( CORE, ReferencePoint) INITIALIZE_NODE( CORE, MimeType) INITIALIZE_NODE( CORE, LibraryObject) // GRP INITIALIZE_NODE( GRP, CityObjectGroup ) INITIALIZE_NODE( GRP, GroupMember ) INITIALIZE_NODE( GRP, Class ) INITIALIZE_NODE( GRP, Function ) INITIALIZE_NODE( GRP, Usage ) INITIALIZE_NODE( GRP, Parent ) INITIALIZE_NODE( GRP, Geometry ) // GEN INITIALIZE_NODE( GEN, Class ) INITIALIZE_NODE( GEN, Function ) INITIALIZE_NODE( GEN, Usage ) INITIALIZE_NODE( GEN, GenericCityObject ) INITIALIZE_NODE( GEN, StringAttribute ) INITIALIZE_NODE( GEN, DoubleAttribute ) INITIALIZE_NODE( GEN, IntAttribute ) INITIALIZE_NODE( GEN, DateAttribute ) INITIALIZE_NODE( GEN, UriAttribute ) INITIALIZE_NODE( GEN, Value ) INITIALIZE_NODE( GEN, Lod0Geometry ) INITIALIZE_NODE( GEN, Lod1Geometry ) INITIALIZE_NODE( GEN, Lod2Geometry ) INITIALIZE_NODE( GEN, Lod3Geometry ) INITIALIZE_NODE( GEN, Lod4Geometry ) INITIALIZE_NODE( GEN, Lod0TerrainIntersection ) INITIALIZE_NODE( GEN, Lod1TerrainIntersection ) INITIALIZE_NODE( GEN, Lod2TerrainIntersection ) INITIALIZE_NODE( GEN, Lod3TerrainIntersection ) INITIALIZE_NODE( GEN, Lod4TerrainIntersection ) INITIALIZE_NODE( GEN, Lod0ImplicitRepresentation ) INITIALIZE_NODE( GEN, Lod1ImplicitRepresentation ) INITIALIZE_NODE( GEN, Lod2ImplicitRepresentation ) INITIALIZE_NODE( GEN, Lod3ImplicitRepresentation ) INITIALIZE_NODE( GEN, Lod4ImplicitRepresentation ) // TEX // INITIALIZE_NODE( GML, TexturedSurface ) // Deprecated // GML INITIALIZE_NODE( GML, Description ) INITIALIZE_NODE( GML, Identifier ) INITIALIZE_NODE( GML, Name ) INITIALIZE_NODE( GML, DescriptionReference ) INITIALIZE_NODE( GML, MetaDataProperty ) INITIALIZE_NODE( GML, Coordinates ) INITIALIZE_NODE( GML, Pos ) INITIALIZE_NODE( GML, BoundedBy ) INITIALIZE_NODE( GML, Envelope ) INITIALIZE_NODE( GML, LowerCorner ) INITIALIZE_NODE( GML, UpperCorner ) INITIALIZE_NODE( GML, Solid ) INITIALIZE_NODE( GML, SurfaceMember ) INITIALIZE_NODE( GML, BaseSurface ) INITIALIZE_NODE( GML, Patches ) INITIALIZE_NODE( GML, TrianglePatches ) INITIALIZE_NODE( GML, SolidMember ) INITIALIZE_NODE( GML, TriangulatedSurface ) INITIALIZE_NODE( GML, Triangle ) INITIALIZE_NODE( GML, Polygon ) INITIALIZE_NODE( GML, Rectangle ) INITIALIZE_NODE( GML, PosList ) INITIALIZE_NODE( GML, OrientableSurface ) INITIALIZE_NODE( GML, LinearRing ) INITIALIZE_NODE( GML, Shell ) INITIALIZE_NODE( GML, PolyhedralSurface ) INITIALIZE_NODE( GML, Surface ) INITIALIZE_NODE( GML, PolygonPatch) INITIALIZE_NODE( GML, LineString) INITIALIZE_NODE( BLDG, Lod1Solid ) INITIALIZE_NODE( BLDG, Lod2Solid ) INITIALIZE_NODE( BLDG, Lod3Solid ) INITIALIZE_NODE( BLDG, Lod4Solid ) INITIALIZE_NODE( BLDG, Lod2Geometry ) INITIALIZE_NODE( BLDG, Lod3Geometry ) INITIALIZE_NODE( BLDG, Lod4Geometry ) INITIALIZE_NODE( BLDG, Lod1MultiCurve ) INITIALIZE_NODE( BLDG, Lod2MultiCurve ) INITIALIZE_NODE( BLDG, Lod3MultiCurve ) INITIALIZE_NODE( BLDG, Lod4MultiCurve ) INITIALIZE_NODE( BLDG, Lod1MultiSurface ) INITIALIZE_NODE( BLDG, Lod2MultiSurface ) INITIALIZE_NODE( BLDG, Lod3MultiSurface ) INITIALIZE_NODE( BLDG, Lod4MultiSurface ) INITIALIZE_NODE( BLDG, Lod1TerrainIntersection ) INITIALIZE_NODE( BLDG, Lod2TerrainIntersection ) INITIALIZE_NODE( BLDG, Lod3TerrainIntersection ) INITIALIZE_NODE( BLDG, Lod4TerrainIntersection ) INITIALIZE_NODE( GML, MultiPoint ) INITIALIZE_NODE( GML, MultiCurve ) INITIALIZE_NODE( GML, MultiSurface ) INITIALIZE_NODE( GML, MultiSolid ) INITIALIZE_NODE( GML, CompositeCurve ) INITIALIZE_NODE( GML, CompositeSurface ) INITIALIZE_NODE( GML, CompositeSolid ) INITIALIZE_NODE( GML, ReferencePoint ) INITIALIZE_NODE( GML, Point ) INITIALIZE_NODE( GML, Interior ) INITIALIZE_NODE( GML, Exterior ) // BLDG INITIALIZE_NODE( BLDG, Building ) INITIALIZE_NODE( BLDG, BuildingPart ) INITIALIZE_NODE( BLDG, Room ) INITIALIZE_NODE( BLDG, Door ) INITIALIZE_NODE( BLDG, Window ) INITIALIZE_NODE( BLDG, BuildingInstallation ) INITIALIZE_NODE( BLDG, MeasuredHeight ) INITIALIZE_NODE( BLDG, Class ) INITIALIZE_NODE( BLDG, Type ) INITIALIZE_NODE( BLDG, Function ) INITIALIZE_NODE( BLDG, Usage ) INITIALIZE_NODE( BLDG, YearOfConstruction ) INITIALIZE_NODE( BLDG, YearOfDemolition ) INITIALIZE_NODE( BLDG, StoreysAboveGround ) INITIALIZE_NODE( BLDG, StoreysBelowGround ) INITIALIZE_NODE( BLDG, StoreyHeightsAboveGround ) INITIALIZE_NODE( BLDG, StoreyHeightsBelowGround ) INITIALIZE_NODE( BLDG, BoundedBy ) INITIALIZE_NODE( BLDG, OuterBuildingInstallation) INITIALIZE_NODE( BLDG, InteriorBuildingInstallation) INITIALIZE_NODE( BLDG, InteriorRoom) INITIALIZE_NODE( BLDG, InteriorFurniture) INITIALIZE_NODE( BLDG, RoomInstallation) INITIALIZE_NODE( BLDG, Opening) INITIALIZE_NODE( BLDG, ConsistsOfBuildingPart ) // CityFurniture INITIALIZE_NODE( FRN, Class ) INITIALIZE_NODE( FRN, Function ) INITIALIZE_NODE( FRN, CityFurniture ) INITIALIZE_NODE( FRN, Lod1Geometry ) INITIALIZE_NODE( FRN, Lod2Geometry ) INITIALIZE_NODE( FRN, Lod3Geometry ) INITIALIZE_NODE( FRN, Lod4Geometry ) INITIALIZE_NODE( FRN, Lod1TerrainIntersection ) INITIALIZE_NODE( FRN, Lod2TerrainIntersection ) INITIALIZE_NODE( FRN, Lod3TerrainIntersection ) INITIALIZE_NODE( FRN, Lod4TerrainIntersection ) INITIALIZE_NODE( FRN, Lod1ImplicitRepresentation ) INITIALIZE_NODE( FRN, Lod2ImplicitRepresentation ) INITIALIZE_NODE( FRN, Lod3ImplicitRepresentation ) INITIALIZE_NODE( FRN, Lod4ImplicitRepresentation ) // BoundarySurfaceType INITIALIZE_NODE( BLDG, WallSurface ) INITIALIZE_NODE( BLDG, RoofSurface ) INITIALIZE_NODE( BLDG, GroundSurface ) INITIALIZE_NODE( BLDG, ClosureSurface ) INITIALIZE_NODE( BLDG, FloorSurface ) INITIALIZE_NODE( BLDG, InteriorWallSurface ) INITIALIZE_NODE( BLDG, CeilingSurface ) INITIALIZE_NODE( BLDG, BuildingFurniture ) INITIALIZE_NODE( BLDG, RoofType) INITIALIZE_NODE( BLDG, CityFurniture ) INITIALIZE_NODE( BLDG, Address) // ADDRESS INITIALIZE_NODE( XAL, AddressDetails ) INITIALIZE_NODE( XAL, Country ) INITIALIZE_NODE( XAL, CountryName ) INITIALIZE_NODE( XAL, CountryNameCode ) INITIALIZE_NODE( XAL, AdministrativeArea ) INITIALIZE_NODE( XAL, AdministrativeAreaName ) INITIALIZE_NODE( XAL, Locality ) INITIALIZE_NODE( XAL, LocalityName ) INITIALIZE_NODE( XAL, PostalCode ) INITIALIZE_NODE( XAL, PostalCodeNumber ) INITIALIZE_NODE( XAL, Thoroughfare ) INITIALIZE_NODE( XAL, ThoroughfareName ) INITIALIZE_NODE( XAL, ThoroughfareNumber ) // WTR INITIALIZE_NODE( WTR, WaterBody ) INITIALIZE_NODE( WTR, WaterSurface ) INITIALIZE_NODE( WTR, WaterGroundSurface ) INITIALIZE_NODE( WTR, WaterClosureSurface ) INITIALIZE_NODE( WTR, Class ) INITIALIZE_NODE( WTR, Function ) INITIALIZE_NODE( WTR, Usage ) INITIALIZE_NODE( WTR, WaterLevel ) INITIALIZE_NODE( WTR, Lod0MultiCurve ) INITIALIZE_NODE( WTR, Lod0MultiSurface ) INITIALIZE_NODE( WTR, Lod1MultiCurve ) INITIALIZE_NODE( WTR, Lod1MultiSurface ) INITIALIZE_NODE( WTR, Lod1Solid ) INITIALIZE_NODE( WTR, Lod2Solid ) INITIALIZE_NODE( WTR, Lod3Solid ) INITIALIZE_NODE( WTR, Lod4Solid ) INITIALIZE_NODE( WTR, Lod2Surface ) INITIALIZE_NODE( WTR, Lod3Surface ) INITIALIZE_NODE( WTR, Lod4Surface ) INITIALIZE_NODE( WTR, BoundedBy ) // VEG INITIALIZE_NODE( VEG, PlantCover ) INITIALIZE_NODE( VEG, SolitaryVegetationObject ) INITIALIZE_NODE( VEG, Lod1ImplicitRepresentation ) INITIALIZE_NODE( VEG, Lod2ImplicitRepresentation ) INITIALIZE_NODE( VEG, Lod3ImplicitRepresentation ) INITIALIZE_NODE( VEG, Lod4ImplicitRepresentation ) INITIALIZE_NODE( VEG, Class ) INITIALIZE_NODE( VEG, Function ) INITIALIZE_NODE( VEG, AverageHeight ) INITIALIZE_NODE( VEG, Species ) INITIALIZE_NODE( VEG, Height ) INITIALIZE_NODE( VEG, TrunkDiameter ) INITIALIZE_NODE( VEG, CrownDiameter ) INITIALIZE_NODE( VEG, Lod0Geometry ) INITIALIZE_NODE( VEG, Lod1Geometry ) INITIALIZE_NODE( VEG, Lod2Geometry ) INITIALIZE_NODE( VEG, Lod3Geometry ) INITIALIZE_NODE( VEG, Lod4Geometry ) // TRANS INITIALIZE_NODE( TRANS, TransportationComplex ) INITIALIZE_NODE( TRANS, TrafficArea ) INITIALIZE_NODE( TRANS, AuxiliaryTrafficArea ) INITIALIZE_NODE( TRANS, Track ) INITIALIZE_NODE( TRANS, Road ) INITIALIZE_NODE( TRANS, Railway ) INITIALIZE_NODE( TRANS, Square ) INITIALIZE_NODE( TRANS, Usage ) INITIALIZE_NODE( TRANS, Function ) INITIALIZE_NODE( TRANS, SurfaceMaterial ) INITIALIZE_NODE( TRANS, Lod0Network ) INITIALIZE_NODE( TRANS, Lod1MultiSurface ) INITIALIZE_NODE( TRANS, Lod2MultiSurface ) INITIALIZE_NODE( TRANS, Lod3MultiSurface ) INITIALIZE_NODE( TRANS, Lod4MultiSurface ) // LUSE INITIALIZE_NODE( LUSE, LandUse ) INITIALIZE_NODE( LUSE, Class ) INITIALIZE_NODE( LUSE, Usage ) INITIALIZE_NODE( LUSE, Function ) INITIALIZE_NODE( LUSE, Lod1MultiSurface ) INITIALIZE_NODE( LUSE, Lod2MultiSurface ) INITIALIZE_NODE( LUSE, Lod3MultiSurface ) INITIALIZE_NODE( LUSE, Lod4MultiSurface ) // DEM (Relief) INITIALIZE_NODE( DEM, ReliefFeature ) INITIALIZE_NODE( DEM, TINRelief ) INITIALIZE_NODE( DEM, RasterRelief ) INITIALIZE_NODE( DEM, MassPointRelief ) INITIALIZE_NODE( DEM, BreaklineRelief ) INITIALIZE_NODE( DEM, Lod ) INITIALIZE_NODE( DEM, Extent ) INITIALIZE_NODE( DEM, ReliefComponent ) INITIALIZE_NODE( DEM, Tin ) INITIALIZE_NODE( DEM, Grid ) INITIALIZE_NODE( DEM, ReliefPoints ) INITIALIZE_NODE( DEM, RidgeOrValleyLines ) INITIALIZE_NODE( DEM, Breaklines ) INITIALIZE_NODE( DEM, Elevation ) // SUB INITIALIZE_NODE( SUB, Tunnel ) INITIALIZE_NODE( SUB, RelativeToTerrain ) // BRID INITIALIZE_NODE( BRID, Bridge ) INITIALIZE_NODE( BRID, BridgeConstructionElement ) INITIALIZE_NODE( BRID, BridgeInstallation ) INITIALIZE_NODE( BRID, BridgePart ) // APP INITIALIZE_NODE( APP, Appearance ) INITIALIZE_NODE( APP, SimpleTexture ) INITIALIZE_NODE( APP, ParameterizedTexture ) INITIALIZE_NODE( APP, GeoreferencedTexture ) INITIALIZE_NODE( APP, ImageURI ) INITIALIZE_NODE( APP, TextureMap ) INITIALIZE_NODE( APP, Target ) INITIALIZE_NODE( APP, TexCoordList ) INITIALIZE_NODE( APP, TextureCoordinates ) INITIALIZE_NODE( APP, TextureType ) INITIALIZE_NODE( APP, Repeat ) INITIALIZE_NODE( APP, WrapMode ) INITIALIZE_NODE( APP, BorderColor ) INITIALIZE_NODE( APP, PreferWorldFile ) INITIALIZE_NODE( APP, ReferencePoint) INITIALIZE_NODE( APP, Orientation) INITIALIZE_NODE( APP, isSmooth) INITIALIZE_NODE( APP, X3DMaterial ) INITIALIZE_NODE( APP, Material ) INITIALIZE_NODE( APP, AppearanceMember ) INITIALIZE_NODE( APP, SurfaceDataMember ) INITIALIZE_NODE( APP, Shininess ) INITIALIZE_NODE( APP, Transparency ) INITIALIZE_NODE( APP, SpecularColor ) INITIALIZE_NODE( APP, DiffuseColor ) INITIALIZE_NODE( APP, EmissiveColor ) INITIALIZE_NODE( APP, AmbientIntensity ) INITIALIZE_NODE( APP, IsFront ) INITIALIZE_NODE( APP, Theme ) INITIALIZE_NODE( APP, MimeType ) nodesInitialized = true; } } } const NodeType::XMLNode&NodeType::getXMLNodeFor(const std::string& name) { initializeNodeTypes(); std::string lowerName = toLower(name); { auto it = nodeNameWithPrefixTypeMap.find(lowerName); if (it != nodeNameWithPrefixTypeMap.end()) { return *it->second; } } std::string nodeName = lowerName; size_t pos = nodeName.find_first_of( ":" ); if ( pos != std::string::npos ) { nodeName = nodeName.substr(pos + 1); } else { // node has no prefix... try with core prefix return getXMLNodeFor("core:" + name); } auto it = nodeNameTypeMap.find(nodeName); if (it == nodeNameTypeMap.end()) { return InvalidNode; } else { return *it->second; } } #define DEFINE_NODE( prefix, elementname ) NodeType::XMLNode NodeType::prefix ## _ ## elementname ## Node; // CORE DEFINE_NODE( CORE, CityModel ) DEFINE_NODE( CORE, CityObjectMember ) DEFINE_NODE( CORE, CreationDate ) DEFINE_NODE( CORE, TerminationDate ) DEFINE_NODE( CORE, GeneralizesTo) DEFINE_NODE( CORE, ExternalReference) DEFINE_NODE( CORE, InformationSystem) DEFINE_NODE( CORE, ExternalObject) DEFINE_NODE( CORE, Uri) DEFINE_NODE( CORE, Name) DEFINE_NODE( CORE, Address ) DEFINE_NODE( CORE, XalAddress ) DEFINE_NODE( CORE, ImplicitGeometry ) DEFINE_NODE( CORE, RelativeGMLGeometry ) DEFINE_NODE( CORE, TransformationMatrix ) DEFINE_NODE( CORE, ReferencePoint) DEFINE_NODE( CORE, MimeType) DEFINE_NODE( CORE, LibraryObject) // GRP DEFINE_NODE( GRP, CityObjectGroup ) DEFINE_NODE( GRP, GroupMember ) DEFINE_NODE( GRP, Class ) DEFINE_NODE( GRP, Function ) DEFINE_NODE( GRP, Usage ) DEFINE_NODE( GRP, Parent ) DEFINE_NODE( GRP, Geometry ) // GEN DEFINE_NODE( GEN, Class ) DEFINE_NODE( GEN, Function ) DEFINE_NODE( GEN, Usage ) DEFINE_NODE( GEN, GenericCityObject ) DEFINE_NODE( GEN, StringAttribute ) DEFINE_NODE( GEN, DoubleAttribute ) DEFINE_NODE( GEN, IntAttribute ) DEFINE_NODE( GEN, DateAttribute ) DEFINE_NODE( GEN, UriAttribute ) DEFINE_NODE( GEN, Value ) DEFINE_NODE( GEN, Lod0Geometry ) DEFINE_NODE( GEN, Lod1Geometry ) DEFINE_NODE( GEN, Lod2Geometry ) DEFINE_NODE( GEN, Lod3Geometry ) DEFINE_NODE( GEN, Lod4Geometry ) DEFINE_NODE( GEN, Lod0TerrainIntersection ) DEFINE_NODE( GEN, Lod1TerrainIntersection ) DEFINE_NODE( GEN, Lod2TerrainIntersection ) DEFINE_NODE( GEN, Lod3TerrainIntersection ) DEFINE_NODE( GEN, Lod4TerrainIntersection ) DEFINE_NODE( GEN, Lod0ImplicitRepresentation ) DEFINE_NODE( GEN, Lod1ImplicitRepresentation ) DEFINE_NODE( GEN, Lod2ImplicitRepresentation ) DEFINE_NODE( GEN, Lod3ImplicitRepresentation ) DEFINE_NODE( GEN, Lod4ImplicitRepresentation ) // TEX // DEFINE_NODE( GML, TexturedSurface ) // Deprecated // GML DEFINE_NODE( GML, Description ) DEFINE_NODE( GML, Identifier ) DEFINE_NODE( GML, Name ) DEFINE_NODE( GML, DescriptionReference ) DEFINE_NODE( GML, MetaDataProperty ) DEFINE_NODE( GML, Coordinates ) DEFINE_NODE( GML, Pos ) DEFINE_NODE( GML, BoundedBy ) DEFINE_NODE( GML, Envelope ) DEFINE_NODE( GML, LowerCorner ) DEFINE_NODE( GML, UpperCorner ) DEFINE_NODE( GML, Solid ) DEFINE_NODE( GML, SurfaceMember ) DEFINE_NODE( GML, BaseSurface ) DEFINE_NODE( GML, Patches ) DEFINE_NODE( GML, TrianglePatches ) DEFINE_NODE( GML, SolidMember ) DEFINE_NODE( GML, TriangulatedSurface ) DEFINE_NODE( GML, Triangle ) DEFINE_NODE( GML, Polygon ) DEFINE_NODE( GML, Rectangle ) DEFINE_NODE( GML, PosList ) DEFINE_NODE( GML, OrientableSurface ) DEFINE_NODE( GML, LinearRing ) DEFINE_NODE( BLDG, Lod1Solid ) DEFINE_NODE( BLDG, Lod2Solid ) DEFINE_NODE( BLDG, Lod3Solid ) DEFINE_NODE( BLDG, Lod4Solid ) DEFINE_NODE( BLDG, Lod2Geometry ) DEFINE_NODE( BLDG, Lod3Geometry ) DEFINE_NODE( BLDG, Lod4Geometry ) DEFINE_NODE( BLDG, Lod1MultiCurve ) DEFINE_NODE( BLDG, Lod2MultiCurve ) DEFINE_NODE( BLDG, Lod3MultiCurve ) DEFINE_NODE( BLDG, Lod4MultiCurve ) DEFINE_NODE( BLDG, Lod1MultiSurface ) DEFINE_NODE( BLDG, Lod2MultiSurface ) DEFINE_NODE( BLDG, Lod3MultiSurface ) DEFINE_NODE( BLDG, Lod4MultiSurface ) DEFINE_NODE( BLDG, Lod1TerrainIntersection ) DEFINE_NODE( BLDG, Lod2TerrainIntersection ) DEFINE_NODE( BLDG, Lod3TerrainIntersection ) DEFINE_NODE( BLDG, Lod4TerrainIntersection ) DEFINE_NODE( GML, MultiPoint ) DEFINE_NODE( GML, MultiCurve ) DEFINE_NODE( GML, MultiSurface ) DEFINE_NODE( GML, MultiSolid ) DEFINE_NODE( GML, CompositeCurve ) DEFINE_NODE( GML, CompositeSurface ) DEFINE_NODE( GML, CompositeSolid ) DEFINE_NODE( GML, ReferencePoint ) DEFINE_NODE( GML, Point ) DEFINE_NODE( GML, Interior ) DEFINE_NODE( GML, Exterior ) DEFINE_NODE( GML, Shell ) DEFINE_NODE( GML, PolyhedralSurface ) DEFINE_NODE( GML, Surface ) DEFINE_NODE( GML, PolygonPatch) DEFINE_NODE( GML, LineString) // BLDG DEFINE_NODE( BLDG, Building ) DEFINE_NODE( BLDG, BuildingPart ) DEFINE_NODE( BLDG, Room ) DEFINE_NODE( BLDG, Door ) DEFINE_NODE( BLDG, Window ) DEFINE_NODE( BLDG, BuildingInstallation ) DEFINE_NODE( BLDG, MeasuredHeight ) DEFINE_NODE( BLDG, Class ) DEFINE_NODE( BLDG, Type ) DEFINE_NODE( BLDG, Function ) DEFINE_NODE( BLDG, Usage ) DEFINE_NODE( BLDG, YearOfConstruction ) DEFINE_NODE( BLDG, YearOfDemolition ) DEFINE_NODE( BLDG, StoreysAboveGround ) DEFINE_NODE( BLDG, StoreysBelowGround ) DEFINE_NODE( BLDG, StoreyHeightsAboveGround ) DEFINE_NODE( BLDG, StoreyHeightsBelowGround ) DEFINE_NODE( BLDG, BoundedBy ) DEFINE_NODE( BLDG, OuterBuildingInstallation) DEFINE_NODE( BLDG, InteriorBuildingInstallation) DEFINE_NODE( BLDG, InteriorRoom) DEFINE_NODE( BLDG, InteriorFurniture) DEFINE_NODE( BLDG, RoomInstallation) DEFINE_NODE( BLDG, Opening) DEFINE_NODE( BLDG, ConsistsOfBuildingPart ) // CityFurniture DEFINE_NODE( FRN, Class ) DEFINE_NODE( FRN, Function ) DEFINE_NODE( FRN, CityFurniture ) DEFINE_NODE( FRN, Lod1Geometry ) DEFINE_NODE( FRN, Lod2Geometry ) DEFINE_NODE( FRN, Lod3Geometry ) DEFINE_NODE( FRN, Lod4Geometry ) DEFINE_NODE( FRN, Lod1TerrainIntersection ) DEFINE_NODE( FRN, Lod2TerrainIntersection ) DEFINE_NODE( FRN, Lod3TerrainIntersection ) DEFINE_NODE( FRN, Lod4TerrainIntersection ) DEFINE_NODE( FRN, Lod1ImplicitRepresentation ) DEFINE_NODE( FRN, Lod2ImplicitRepresentation ) DEFINE_NODE( FRN, Lod3ImplicitRepresentation ) DEFINE_NODE( FRN, Lod4ImplicitRepresentation ) // BoundarySurfaceType DEFINE_NODE( BLDG, WallSurface ) DEFINE_NODE( BLDG, RoofSurface ) DEFINE_NODE( BLDG, GroundSurface ) DEFINE_NODE( BLDG, ClosureSurface ) DEFINE_NODE( BLDG, FloorSurface ) DEFINE_NODE( BLDG, InteriorWallSurface ) DEFINE_NODE( BLDG, CeilingSurface ) DEFINE_NODE( BLDG, BuildingFurniture ) DEFINE_NODE( BLDG, RoofType) DEFINE_NODE( BLDG, CityFurniture ) DEFINE_NODE( BLDG, Address) // ADDRESS DEFINE_NODE( XAL, AddressDetails ) DEFINE_NODE( XAL, Country ) DEFINE_NODE( XAL, CountryName ) DEFINE_NODE( XAL, CountryNameCode ) DEFINE_NODE( XAL, AdministrativeArea ) DEFINE_NODE( XAL, AdministrativeAreaName ) DEFINE_NODE( XAL, Locality ) DEFINE_NODE( XAL, LocalityName ) DEFINE_NODE( XAL, PostalCode ) DEFINE_NODE( XAL, PostalCodeNumber ) DEFINE_NODE( XAL, Thoroughfare ) DEFINE_NODE( XAL, ThoroughfareName ) DEFINE_NODE( XAL, ThoroughfareNumber ) // WTR DEFINE_NODE( WTR, WaterBody ) DEFINE_NODE( WTR, WaterSurface ) DEFINE_NODE( WTR, WaterGroundSurface ) DEFINE_NODE( WTR, WaterClosureSurface ) DEFINE_NODE( WTR, Class ) DEFINE_NODE( WTR, Function ) DEFINE_NODE( WTR, Usage ) DEFINE_NODE( WTR, WaterLevel ) DEFINE_NODE( WTR, Lod0MultiCurve ) DEFINE_NODE( WTR, Lod0MultiSurface ) DEFINE_NODE( WTR, Lod1MultiCurve ) DEFINE_NODE( WTR, Lod1MultiSurface ) DEFINE_NODE( WTR, Lod1Solid ) DEFINE_NODE( WTR, Lod2Solid ) DEFINE_NODE( WTR, Lod3Solid ) DEFINE_NODE( WTR, Lod4Solid ) DEFINE_NODE( WTR, Lod2Surface ) DEFINE_NODE( WTR, Lod3Surface ) DEFINE_NODE( WTR, Lod4Surface ) DEFINE_NODE( WTR, BoundedBy ) // VEG DEFINE_NODE( VEG, PlantCover ) DEFINE_NODE( VEG, SolitaryVegetationObject ) DEFINE_NODE( VEG, Lod1ImplicitRepresentation ) DEFINE_NODE( VEG, Lod2ImplicitRepresentation ) DEFINE_NODE( VEG, Lod3ImplicitRepresentation ) DEFINE_NODE( VEG, Lod4ImplicitRepresentation ) DEFINE_NODE( VEG, Class ) DEFINE_NODE( VEG, Function ) DEFINE_NODE( VEG, AverageHeight ) DEFINE_NODE( VEG, Species ) DEFINE_NODE( VEG, Height ) DEFINE_NODE( VEG, TrunkDiameter ) DEFINE_NODE( VEG, CrownDiameter ) DEFINE_NODE( VEG, Lod0Geometry ) DEFINE_NODE( VEG, Lod1Geometry ) DEFINE_NODE( VEG, Lod2Geometry ) DEFINE_NODE( VEG, Lod3Geometry ) DEFINE_NODE( VEG, Lod4Geometry ) // TRANS DEFINE_NODE( TRANS, TransportationComplex ) DEFINE_NODE( TRANS, TrafficArea ) DEFINE_NODE( TRANS, AuxiliaryTrafficArea ) DEFINE_NODE( TRANS, Track ) DEFINE_NODE( TRANS, Road ) DEFINE_NODE( TRANS, Railway ) DEFINE_NODE( TRANS, Square ) DEFINE_NODE( TRANS, Usage ) DEFINE_NODE( TRANS, Function ) DEFINE_NODE( TRANS, SurfaceMaterial ) DEFINE_NODE( TRANS, Lod0Network ) DEFINE_NODE( TRANS, Lod1MultiSurface ) DEFINE_NODE( TRANS, Lod2MultiSurface ) DEFINE_NODE( TRANS, Lod3MultiSurface ) DEFINE_NODE( TRANS, Lod4MultiSurface ) // LUSE DEFINE_NODE( LUSE, LandUse ) DEFINE_NODE( LUSE, Class ) DEFINE_NODE( LUSE, Usage ) DEFINE_NODE( LUSE, Function ) DEFINE_NODE( LUSE, Lod1MultiSurface ) DEFINE_NODE( LUSE, Lod2MultiSurface ) DEFINE_NODE( LUSE, Lod3MultiSurface ) DEFINE_NODE( LUSE, Lod4MultiSurface ) // DEM (Relief) DEFINE_NODE( DEM, ReliefFeature ) DEFINE_NODE( DEM, TINRelief ) DEFINE_NODE( DEM, RasterRelief ) DEFINE_NODE( DEM, MassPointRelief ) DEFINE_NODE( DEM, BreaklineRelief ) DEFINE_NODE( DEM, Lod ) DEFINE_NODE( DEM, Extent ) DEFINE_NODE( DEM, ReliefComponent ) DEFINE_NODE( DEM, Tin ) DEFINE_NODE( DEM, Grid ) DEFINE_NODE( DEM, ReliefPoints ) DEFINE_NODE( DEM, RidgeOrValleyLines ) DEFINE_NODE( DEM, Breaklines ) DEFINE_NODE( DEM, Elevation ) // SUB DEFINE_NODE( SUB, Tunnel ) DEFINE_NODE( SUB, RelativeToTerrain ) // BRID DEFINE_NODE( BRID, Bridge ) DEFINE_NODE( BRID, BridgeConstructionElement ) DEFINE_NODE( BRID, BridgeInstallation ) DEFINE_NODE( BRID, BridgePart ) // APP DEFINE_NODE( APP, Appearance ) DEFINE_NODE( APP, SimpleTexture ) DEFINE_NODE( APP, ParameterizedTexture ) DEFINE_NODE( APP, GeoreferencedTexture ) DEFINE_NODE( APP, ImageURI ) DEFINE_NODE( APP, TextureMap ) DEFINE_NODE( APP, Target ) DEFINE_NODE( APP, TexCoordList ) DEFINE_NODE( APP, TextureCoordinates ) DEFINE_NODE( APP, TextureType ) DEFINE_NODE( APP, Repeat ) DEFINE_NODE( APP, WrapMode ) DEFINE_NODE( APP, BorderColor ) DEFINE_NODE( APP, PreferWorldFile ) DEFINE_NODE( APP, ReferencePoint) DEFINE_NODE( APP, Orientation) DEFINE_NODE( APP, isSmooth) DEFINE_NODE( APP, X3DMaterial ) DEFINE_NODE( APP, Material ) DEFINE_NODE( APP, AppearanceMember ) DEFINE_NODE( APP, SurfaceDataMember ) DEFINE_NODE( APP, Shininess ) DEFINE_NODE( APP, Transparency ) DEFINE_NODE( APP, SpecularColor ) DEFINE_NODE( APP, DiffuseColor ) DEFINE_NODE( APP, EmissiveColor ) DEFINE_NODE( APP, AmbientIntensity ) DEFINE_NODE( APP, IsFront ) DEFINE_NODE( APP, Theme ) DEFINE_NODE( APP, MimeType ) } libcitygml-2.0/sources/src/parser/parserxercesc.cpp000066400000000000000000000243341256066205500226520ustar00rootroot00000000000000/* -*-c++-*- libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #include "citygml/citygml.h" #include #include #include #include #include "citygml/citygmllogger.h" #include "parser/citygmldocumentparser.h" #include "parser/documentlocation.h" #include "parser/attributes.h" #include #include #include #include #include #include #include #include #include #include using namespace citygml; std::string toStdString( const XMLCh* const wstr ) { if (wstr == nullptr) { return ""; } char* tmp = xercesc::XMLString::transcode(wstr); std::string str(tmp); xercesc::XMLString::release(&tmp); return str; } std::shared_ptr toXercesString(const std::string& str) { XMLCh* conv = xercesc::XMLString::transcode(str.c_str()); // Pack xerces string into shared_ptr with custom delete function return std::shared_ptr(conv, [=](XMLCh* str) { xercesc::XMLString::release(&str); }); } class DocumentLocationXercesAdapter : public citygml::DocumentLocation { public: DocumentLocationXercesAdapter(const std::string& fileName) { m_locator = nullptr; m_fileName = fileName; } void setLocator(const xercesc::Locator* locator) { m_locator = locator; } // DocumentLocation interface virtual const std::string& getDocumentFileName() const { return m_fileName; } virtual uint64_t getCurrentLine() const { return m_locator != nullptr ? m_locator->getLineNumber() : 0; } virtual uint64_t getCurrentColumn() const { return m_locator != nullptr ? m_locator->getColumnNumber() : 0; } protected: const xercesc::Locator* m_locator; std::string m_fileName; }; class AttributesXercesAdapter : public citygml::Attributes { public: AttributesXercesAdapter(const xercesc::Attributes& attrs, const citygml::DocumentLocation& docLoc, std::shared_ptr logger) : citygml::Attributes(logger), m_attrs(attrs), m_location(docLoc) {} // Attributes interface virtual std::string getAttribute(const std::string& attname, const std::string& defvalue) const { std::shared_ptr name = toXercesString(attname); std::string value = toStdString(m_attrs.getValue(name.get())); return value.empty() ? defvalue : value; } virtual const DocumentLocation& getDocumentLocation() const { return m_location; } protected: const xercesc::Attributes& m_attrs; const citygml::DocumentLocation& m_location; }; // CityGML Xerces-c SAX parsing handler class CityGMLHandlerXerces : public xercesc::DefaultHandler, public citygml::CityGMLDocumentParser { public: CityGMLHandlerXerces( const ParserParams& params, const std::string& fileName, std::shared_ptr logger) : citygml::CityGMLDocumentParser(params, logger), m_documentLocation(DocumentLocationXercesAdapter(fileName)) {} // ContentHandler interface virtual void startElement(const XMLCh* const, const XMLCh* const, const XMLCh* const qname, const xercesc::Attributes& attrs) override { AttributesXercesAdapter attributes(attrs, m_documentLocation, m_logger); CityGMLDocumentParser::startElement(toStdString(qname), attributes); } virtual void endElement(const XMLCh* const, const XMLCh* const, const XMLCh* const qname) override { CityGMLDocumentParser::endElement(toStdString(qname), m_lastcharacters); m_lastcharacters = ""; } virtual void characters(const XMLCh* const chars, const XMLSize_t) override { m_lastcharacters = toStdString(chars); } virtual void startDocument() override { CityGMLDocumentParser::startDocument(); } virtual void endDocument() override { CityGMLDocumentParser::endDocument(); } virtual void setDocumentLocator(const xercesc::Locator* const locator) { m_documentLocation.setLocator(locator); } // CityGMLDocumentParser interface virtual const citygml::DocumentLocation& getDocumentLocation() const { return m_documentLocation; } protected: DocumentLocationXercesAdapter m_documentLocation; std::string m_lastcharacters; }; class StdBinInputStream : public xercesc::BinInputStream { public: StdBinInputStream( std::istream& stream ) : BinInputStream(), m_stream( stream ) {} virtual ~StdBinInputStream() {} virtual XMLFilePos curPos() const { return m_stream.tellg(); } virtual XMLSize_t readBytes( XMLByte* const buf, const XMLSize_t maxToRead ) { assert( sizeof(XMLByte) == sizeof(char) ); if ( !m_stream ) return 0; m_stream.read( reinterpret_cast(buf), maxToRead ); return (XMLSize_t)m_stream.gcount(); } virtual const XMLCh* getContentType() const { return nullptr; } private: std::istream& m_stream; }; class StdBinInputSource : public xercesc::InputSource { public: StdBinInputSource( std::istream& stream ) : m_stream( stream ) {} virtual xercesc::BinInputStream* makeStream() const { return new StdBinInputStream( m_stream ); } ~StdBinInputSource() { } private: std::istream& m_stream; }; // Parsing methods namespace citygml { class StdLogger : public CityGMLLogger { public: virtual void log(LOGLEVEL level, const std::string& message, const char* file, int line) const { std::ostream& stream = level == LOGLEVEL::LL_ERROR ? std::cerr : std::cout; switch(level) { case LOGLEVEL::LL_DEBUG: stream << "DEBUG"; break; case LOGLEVEL::LL_WARNING: stream << "WARNING"; break; case LOGLEVEL::LL_TRACE: stream << "TRACE"; break; case LOGLEVEL::LL_ERROR: stream << "ERROR"; break; case LOGLEVEL::LL_INFO: stream << "INFO"; break; } if (file) { stream << " [" << file; if (line > -1) { stream << ":" << line; } stream << "]"; } stream << " " << message << std::endl; } virtual bool isEnabledFor(LOGLEVEL) const { return true; } }; std::mutex xerces_init_mutex; bool xerces_initialized; bool initXerces(std::shared_ptr logger) { if (xerces_initialized) { return true; } try { xerces_init_mutex.lock(); // Check xerces_initialized again... it could have changed while waiting for the mutex if (!xerces_initialized) { xercesc::XMLPlatformUtils::Initialize(); xerces_initialized = true; } xerces_init_mutex.unlock(); } catch (const xercesc::XMLException& e) { CITYGML_LOG_ERROR(logger, "Could not initialize xercesc XMLPlatformUtils, a XML Exception occured : " << toStdString(e.getMessage())); return false; } return true; } std::shared_ptr parse(xercesc::InputSource& stream, const ParserParams& params, std::shared_ptr logger, std::string filename = "") { CityGMLHandlerXerces handler( params, filename, logger ); xercesc::SAX2XMLReader* parser = xercesc::XMLReaderFactory::createXMLReader(); parser->setFeature(xercesc::XMLUni::fgSAX2CoreNameSpaces, false); parser->setContentHandler( &handler ); parser->setErrorHandler( &handler ); #ifdef NDEBUG try { #endif parser->parse(stream); #ifdef NDEBUG } catch ( const xercesc::XMLException& e ) { CITYGML_LOG_ERROR(logger, "XML Exception occured: " << toStdString(e.getMessage())); } catch ( const xercesc::SAXParseException& e ) { CITYGML_LOG_ERROR(logger, "SAXParser Exception occured: " << toStdString(e.getMessage())); } catch ( const std::exception& e ) { CITYGML_LOG_ERROR(logger, "Unexpected Exception occured: " << e.what()); } #endif delete parser; return handler.getModel(); } std::shared_ptr load(std::istream& stream, const ParserParams& params, std::shared_ptr logger) { if (!logger) { logger = std::make_shared(); } if (!initXerces(logger)) { return nullptr; } StdBinInputSource streamSource(stream); return parse(streamSource, params, logger); } std::shared_ptr load( const std::string& fname, const ParserParams& params , std::shared_ptr logger) { if (!logger) { logger = std::make_shared(); } if (!initXerces(logger)) { return nullptr; } std::shared_ptr fileName = toXercesString(fname); #ifdef NDEBUG try { #endif xercesc::LocalFileInputSource fileSource(fileName.get()); return parse(fileSource, params, logger, fname); #ifdef NDEBUG } catch (xercesc::XMLException& e) { CITYGML_LOG_ERROR(logger, "Error parsing file " << fname << ": " << e.getMessage()); return nullptr; } #endif } } libcitygml-2.0/sources/src/parser/polygonelementparser.cpp000066400000000000000000000073651256066205500242640ustar00rootroot00000000000000#include "parser/polygonelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/linearringelementparser.h" #include "citygml/polygon.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include #include namespace citygml { // The nodes that are valid Polygon Objects std::unordered_set typeIDSet; bool typeIDSetInitialized = false; std::mutex polygonElementParser_initializedTypeIDMutex; PolygonElementParser::PolygonElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback) : GMLObjectElementParser(documentParser, factory, logger) { m_callback = callback; } std::string PolygonElementParser::elementParserName() const { return "PolygonElementParser"; } bool PolygonElementParser::handlesElement(const NodeType::XMLNode& node) const { if (!typeIDSetInitialized) { std::lock_guard lock(polygonElementParser_initializedTypeIDMutex); if(!typeIDSetInitialized) { typeIDSet.insert(NodeType::GML_TriangleNode.typeID()); typeIDSet.insert(NodeType::GML_RectangleNode.typeID()); typeIDSet.insert(NodeType::GML_PolygonNode.typeID()); typeIDSet.insert(NodeType::GML_PolygonPatchNode.typeID()); typeIDSetInitialized = true; } } return typeIDSet.count(node.typeID()) > 0; } bool PolygonElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (!handlesElement(node)) { CITYGML_LOG_ERROR(m_logger, "Expected start tag of PolygonObject but got <" << node.name() << "> at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createPolygon(attributes.getCityGMLIDAttribute()); return true; } bool PolygonElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { m_callback(m_model); return true; } bool PolygonElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("PolygonElementParser::parseChildElementStartTag called before PolygonElementParser::parseElementStartTag"); } if (node == NodeType::GML_InteriorNode) { parseRingElement(true); return true; } else if (node == NodeType::GML_ExteriorNode) { parseRingElement(false); return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool PolygonElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("PolygonElementParser::parseChildElementEndTag called before PolygonElementParser::parseElementStartTag"); } if (node == NodeType::GML_InteriorNode || node == NodeType::GML_ExteriorNode) { return true; } return GMLObjectElementParser::parseChildElementEndTag(node, characters); } Object* PolygonElementParser::getObject() { return m_model.get(); } void PolygonElementParser::parseRingElement(bool interior) { setParserForNextElement(new LinearRingElementParser(m_documentParser, m_factory, m_logger, interior, [this](LinearRing* ring){ m_model->addRing(ring); })); } } libcitygml-2.0/sources/src/parser/sequenceparser.cpp000066400000000000000000000042271256066205500230250ustar00rootroot00000000000000#include "parser/sequenceparser.h" #include "citygml/citygmllogger.h" #include "parser/documentlocation.h" #include "parser/citygmldocumentparser.h" namespace citygml { SequenceParser::SequenceParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger, std::function childParserFactory, const NodeType::XMLNode& parentElement) : ElementParser(documentParser, logger) { m_childParserFactory = childParserFactory; m_containerType = parentElement; m_childParserInstance = nullptr; } bool SequenceParser::startElement(const NodeType::XMLNode& node, Attributes& attributes) { // Note that at this point the start tag of the parent element has already been parsed... hence node must be a child element ElementParser* childParser = m_childParserFactory(); setParserForNextElement(childParser); return childParser->startElement(node, attributes); } bool SequenceParser::endElement(const NodeType::XMLNode& node, const std::string&) { if (node != m_containerType) { CITYGML_LOG_ERROR(m_logger, "Sequence parser was bound to container element <" << m_containerType << "> but found unexpected" " end tag <" << node << "> at " << getDocumentLocation() << ". Ignoring tag..."); return false; } else { m_documentParser.removeCurrentElementParser(this); } return true; } bool SequenceParser::handlesElement(const NodeType::XMLNode& node) const { return getChildParserDummyInstance().handlesElement(node); } std::string SequenceParser::elementParserName() const { return "SequenceParser (" + getChildParserDummyInstance().elementParserName() + ")"; } ElementParser& SequenceParser::getChildParserDummyInstance() const { // Lazy initialize the dummy object (its only used for logging and error reporting) if (m_childParserInstance == nullptr) { m_childParserInstance = std::unique_ptr(m_childParserFactory()); } return *m_childParserInstance; } } libcitygml-2.0/sources/src/parser/skipelementparser.cpp000066400000000000000000000027501256066205500235340ustar00rootroot00000000000000#include #include #include #include namespace citygml { SkipElementParser::SkipElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr logger, const NodeType::XMLNode& skipNode) : ElementParser(documentParser, logger) { m_skipNode = skipNode; if (skipNode.valid()) { m_depth = 1; } } std::string SkipElementParser::elementParserName() const { return "SkipElementParser"; } bool SkipElementParser::handlesElement(const NodeType::XMLNode&) const { return true; } bool SkipElementParser::startElement(const NodeType::XMLNode& node, Attributes&) { if (!m_skipNode.valid()) { CITYGML_LOG_TRACE(m_logger, "Skipping element <" << node << "> at " << getDocumentLocation()); m_skipNode = node; m_depth = 1; } else if (node == m_skipNode) { m_depth++; } return true; } bool SkipElementParser::endElement(const NodeType::XMLNode& node, const std::string&) { if (!m_skipNode.valid()) { m_documentParser.removeCurrentElementParser(this); } else if (node == m_skipNode) { m_depth--; if (m_depth == 0) { m_documentParser.removeCurrentElementParser(this); } } return true; } } libcitygml-2.0/sources/src/parser/textureelementparser.cpp000066400000000000000000000152421256066205500242660ustar00rootroot00000000000000#include "parser/textureelementparser.h" #include #include "parser/nodetypes.h" #include "parser/attributes.h" #include "parser/documentlocation.h" #include "parser/parserutils.hpp" #include "parser/skipelementparser.h" #include "citygml/cityobject.h" #include "citygml/citygmlfactory.h" #include "citygml/citygmllogger.h" #include "citygml/texture.h" #include "citygml/texturetargetdefinition.h" #include "citygml/texturecoordinates.h" #include namespace citygml { TextureElementParser::TextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr logger, std::function)> callback) : GMLObjectElementParser(documentParser, factory, logger) { m_callback = callback; m_model = nullptr; m_currentTexCoords = nullptr; } std::string TextureElementParser::elementParserName() const { return "TextureElementParser"; } bool TextureElementParser::handlesElement(const NodeType::XMLNode& node) const { return node == NodeType::APP_ParameterizedTextureNode; } bool TextureElementParser::parseElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (node != NodeType::APP_ParameterizedTextureNode) { CITYGML_LOG_ERROR(m_logger, "Expected start tag <" << NodeType::APP_ParameterizedTextureNode.name() << "> got " << node << " at " << getDocumentLocation()); throw std::runtime_error("Unexpected start tag found."); } m_model = m_factory.createTexture(attributes.getCityGMLIDAttribute()); return true; } bool TextureElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&) { m_callback(m_model); return true; } bool TextureElementParser::parseChildElementStartTag(const NodeType::XMLNode& node, Attributes& attributes) { if (m_model == nullptr) { throw std::runtime_error("TextureElementParser::parseChildElementStartTag called before TextureElementParser::parseElementStartTag"); } if (node == NodeType::APP_ImageURINode || node == NodeType::APP_TextureTypeNode || node == NodeType::APP_WrapModeNode || node == NodeType::APP_BorderColorNode || node == NodeType::APP_TexCoordListNode || node == NodeType::APP_IsFrontNode || node == NodeType::APP_MimeTypeNode) { return true; } else if (node == NodeType::APP_TargetNode) { if (m_currentTexTargetDef != nullptr) { CITYGML_LOG_WARN(m_logger, "Nested texture target definition detected at: " << getDocumentLocation()); } else { m_currentTexTargetDef = m_factory.createTextureTargetDefinition(parseReference(attributes.getAttribute("uri"), m_logger, getDocumentLocation()), m_model, attributes.getCityGMLIDAttribute()); } return true; } else if (node == NodeType::APP_TextureCoordinatesNode) { if (m_currentTexTargetDef == nullptr) { CITYGML_LOG_WARN(m_logger, "Found texture coordinates node (" << NodeType::APP_TextureCoordinatesNode << ") outside Texture target node at: " << getDocumentLocation()); } else if (m_currentTexCoords != nullptr) { CITYGML_LOG_WARN(m_logger, "Nested texture coordinates definition detected at: " << getDocumentLocation()); } else { m_currentTexCoords = std::make_shared(attributes.getCityGMLIDAttribute(), parseReference(attributes.getAttribute("ring"), m_logger, getDocumentLocation())); } return true; } return GMLObjectElementParser::parseChildElementStartTag(node, attributes); } bool TextureElementParser::parseChildElementEndTag(const NodeType::XMLNode& node, const std::string& characters) { if (m_model == nullptr) { throw std::runtime_error("TextureElementParser::parseChildElementEndTag called before TextureElementParser::parseElementStartTag"); } if (node == NodeType::APP_ImageURINode) { m_model->setUrl(characters); } else if (node == NodeType::APP_TextureTypeNode) { m_model->setAttribute(node.name(), characters); } else if (node == NodeType::APP_WrapModeNode) { if (!m_model->setWrapModeFromString(characters)) { CITYGML_LOG_WARN(m_logger, "Unknown texture wrap mode " << characters << " at: " << getDocumentLocation()); } } else if (node == NodeType::APP_IsFrontNode) { m_model->setIsFront(parseValue(characters, m_logger, getDocumentLocation())); } else if (node == NodeType::APP_BorderColorNode) { std::vector colorValues = parseVecList(characters, m_logger, getDocumentLocation()); colorValues.push_back(1.f); // if 3 values are given, the fourth (alpha) is set to 1.0 by default if (colorValues.size() >= 4) { m_model->setBorderColor(TVec4f(colorValues[0], colorValues[1], colorValues[2], colorValues[3])); } else { CITYGML_LOG_WARN(m_logger, "Expected 3 or more float values in node " << NodeType::APP_BorderColorNode << " but got " << colorValues.size() << " at: " << getDocumentLocation()); } } else if (node == NodeType::APP_TexCoordListNode) { if (m_currentTexCoords != nullptr) { CITYGML_LOG_WARN(m_logger, "TexCoordList node finished before TextureCoordinates child is finished at " << getDocumentLocation()); m_currentTexCoords = nullptr; } } else if (node == NodeType::APP_TextureCoordinatesNode) { if (m_currentTexCoords != nullptr && m_currentTexTargetDef != nullptr) { m_currentTexCoords->setCoords(parseVecList(characters, m_logger, getDocumentLocation())); m_currentTexTargetDef->addTexCoordinates(m_currentTexCoords); m_currentTexCoords = nullptr; } else { CITYGML_LOG_WARN(m_logger, "Unexpected end tag <" << NodeType::APP_TextureCoordinatesNode << " at: " << getDocumentLocation()); } } else if (node == NodeType::APP_TargetNode) { m_currentTexTargetDef = nullptr; } else if (node == NodeType::APP_MimeTypeNode) { m_model->setAttribute(node.name(), characters); } else { return GMLObjectElementParser::parseChildElementEndTag(node, characters); } return true; } Object* TextureElementParser::getObject() { return m_model.get(); } } libcitygml-2.0/test/000077500000000000000000000000001256066205500145005ustar00rootroot00000000000000libcitygml-2.0/test/CMakeLists.txt000066400000000000000000000031111256066205500172340ustar00rootroot00000000000000IF(WIN32) SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT") ENDIF() FIND_PACKAGE( OpenGL REQUIRED ) #FIND_PACKAGE( GLU REQUIRED ) # deprecated, GLU is now found with FindOpenGL IF( COMMAND cmake_policy ) cmake_policy( SET CMP0003 NEW ) ENDIF( COMMAND cmake_policy ) IF( LIBCITYGML_STATIC ) ADD_DEFINITIONS( -DLIBCITYGML_STATIC ) ENDIF( LIBCITYGML_STATIC ) IF( LIBCITYGML_DYNAMIC ) ADD_DEFINITIONS( -DLIBCITYGML_DYNAMIC ) ENDIF( LIBCITYGML_DYNAMIC ) IF( MSVC AND LIBCITYGML_STATIC_CRT ) #We statically link to reduce dependancies FOREACH( flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO ) IF( ${flag_var} MATCHES "/MD" ) string( REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}" ) ENDIF( ${flag_var} MATCHES "/MD" ) IF( ${flag_var} MATCHES "/MDd" ) string( REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}" ) ENDIF( ${flag_var} MATCHES "/MDd" ) ENDFOREACH( flag_var ) ENDIF( MSVC AND LIBCITYGML_STATIC_CRT ) # INCLUDE_DIRECTORIES( ${CITYGML_INCLUDE_DIR} ) INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/sources/include ${CMAKE_BINARY_DIR}/include) SET( PRG_SRCS citygmltest.cpp ) ADD_EXECUTABLE( citygmltest ${PRG_SRCS} ) # IF( MSVC_IDE ) # SET_TARGET_PROPERTIES( citygmltest PROPERTIES PREFIX "../" ) # ENDIF( MSVC_IDE ) TARGET_LINK_LIBRARIES( citygmltest citygml ${XERCESC_LIBRARY} ${OPENGL_LIBRARIES} ) install(TARGETS citygmltest RUNTIME DESTINATION ${BIN_INSTALL_DIR}) libcitygml-2.0/test/citygmltest.cpp000066400000000000000000000122671256066205500175640ustar00rootroot00000000000000/* -*-c++-*- citygml2vrml - Copyright (c) 2010 Joachim Pouderoux, BRGM * * This file is part of libcitygml library * http://code.google.com/p/libcitygml * * libcitygml is free software: 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 2.1 of the License, or * (at your option) any later version. * * libcitygml 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 * GNU Lesser General Public License for more details. */ #include #include #include #include #include #include #include void analyzeObject( const citygml::CityObject*, unsigned int ); void usage() { std::cout << "Usage: citygmltest [-options...] " << std::endl; std::cout << " Options:" << std::endl; std::cout << " -log Print some information during parsing" << std::endl; std::cout << " -filter CityGML objects to parse (default:All)" << std::endl << " The mask is composed of:" << std::endl << " GenericCityObject, Building, Room," << std::endl << " BuildingInstallation, BuildingFurniture, Door, Window, " << std::endl << " CityFurniture, Track, Road, Railway, Square, PlantCover," << std::endl << " SolitaryVegetationObject, WaterBody, TINRelief, LandUse," << std::endl << " Tunnel, Bridge, BridgeConstructionElement," << std::endl << " BridgeInstallation, BridgePart, All" << std::endl << " and seperators |,&,~." << std::endl << " Examples:" << std::endl << " \"All&~Track&~Room\" to parse everything but tracks & rooms" << std::endl << " \"Road&Railway\" to parse only roads & railways" << std::endl; std::cout << " -destSRS Destination SRS (default: no transform)" << std::endl; exit( EXIT_FAILURE ); } int main( int argc, char **argv ) { if ( argc < 2 ) usage(); int fargc = 1; bool log = false; citygml::ParserParams params; for ( int i = 1; i < argc; i++ ) { std::string param = std::string( argv[i] ); std::transform( param.begin(), param.end(), param.begin(), tolower ); if ( param == "-log" ) { log = true; fargc = i+1; } //if ( param == "-filter" ) { if ( i == argc - 1 ) usage(); params.objectsMask = argv[i+1]; i++; fargc = i+1; } if ( param == "-destsrs" ) { if ( i == argc - 1 ) usage(); params.destSRS = argv[i+1]; i++; fargc = i+1; } } if ( argc - fargc < 1 ) usage(); std::cout << "Parsing CityGML file " << argv[fargc] << " using libcitygml v." << LIBCITYGML_VERSIONSTR << "..." << std::endl; time_t start; time( &start ); #if 0 std::ifstream file; file.open( argv[fargc], std::ifstream::in ); std::shared_ptr city = citygml::load( file, params ); #else std::shared_ptr city = citygml::load( argv[fargc], params ); #endif time_t end; time( &end ); if ( !city ) return EXIT_FAILURE; std::cout << "Done in " << difftime( end, start ) << " seconds." << std::endl; /* std::cout << "Analyzing the city objects..." << std::endl; citygml::CityObjectsMap::const_iterator it = cityObjectsMap.begin(); for ( ; it != cityObjectsMap.end(); ++it ) { const citygml::CityObjects& v = it->second; std::cout << ( log ? " Analyzing " : " Found " ) << v.size() << " " << citygml::getCityObjectsClassName( it->first ) << ( ( v.size() > 1 ) ? "s" : "" ) << "..." << std::endl; if ( log ) { for ( unsigned int i = 0; i < v.size(); i++ ) { std::cout << " + found object " << v[i]->getId(); if ( v[i]->getChildCount() > 0 ) std::cout << " with " << v[i]->getChildCount() << " children"; std::cout << " with " << v[i]->size() << " geometr" << ( ( v[i]->size() > 1 ) ? "ies" : "y" ); std::cout << std::endl; } } } */ if ( log ) { std::cout << std::endl << "Objects hierarchy:" << std::endl; const citygml::ConstCityObjects& roots = city->getRootCityObjects(); // for ( unsigned int i = 0; i < roots.size(); i++ ) analyzeObject( roots[ i ], 2 ); } std::cout << "Done." << std::endl; return EXIT_SUCCESS; } void analyzeObject( const citygml::CityObject* object, unsigned int indent ) { // for ( unsigned int i = 0; i < indent; i++ ) std::cout << " "; // std::cout << "Object " << citygml::getCityObjectsClassName( object->getType() ) << ": " << object->getId() << std::endl; // for ( unsigned int i = 0; i < object->getChildCount(); i++ ) // analyzeObject( object->getChild(i), indent+1 ); }