[libcitygml] 03/35: Imported Upstream version 1.0

Sebastiaan Couwenberg sebastic at moszumanska.debian.org
Fri Jul 24 23:34:58 UTC 2015


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository libcitygml.

commit 674a92fc0b10d4a30c5f9d39cf3e94f76fe06f25
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Fri Jul 24 16:29:24 2015 +0200

    Imported Upstream version 1.0
---
 .gitignore                                         |   20 +
 .travis.yml                                        |   14 +
 CMakeLists.txt                                     |  157 +-
 CMakeModules/FindCityGML.cmake                     |    2 +-
 CMakeModules/FindIconv.cmake                       |   54 -
 CMakeModules/FindXerces.cmake                      |   18 +-
 CMakeModules/ModuleInstall.cmake                   |   35 -
 CMakeModules/cmake_uninstall.cmake.in              |    2 +-
 README                                             |    5 -
 README.md                                          |   13 +
 TODO.md                                            |   22 +
 citygml_to_libcitygml_mapping.graphml              | 1702 ++++++++++++++++++++
 debian_scripts/postinst                            |    1 +
 include/citygml.h                                  |  749 ---------
 include/vecs.h                                     |  331 ----
 libcitygml_classdiagram.graphml                    |  722 +++++++++
 osgplugin/CMakeLists.txt                           |   45 +
 osgplugin/CitygmlOsgViewer.cpp                     |   46 +
 {test/osgplugin => osgplugin}/README               |    0
 osgplugin/ReaderWriterCityGML.cpp                  |  506 ++++++
 sources/CMakeLists.txt                             |  142 ++
 sources/include/citygml/appearance.h               |   49 +
 sources/include/citygml/appearancemanager.h        |   68 +
 sources/include/citygml/appearancetarget.h         |   54 +
 .../include/citygml/appearancetargetdefinition.h   |   46 +
 sources/include/citygml/citygml.h                  |   89 +
 sources/include/citygml/citygml_api.h.in           |   20 +
 sources/include/citygml/citygmlfactory.h           |   73 +
 sources/include/citygml/citygmllogger.h            |   49 +
 sources/include/citygml/citymodel.h                |   65 +
 sources/include/citygml/cityobject.h               |  109 ++
 sources/include/citygml/envelope.h                 |   45 +
 sources/include/citygml/featureobject.h            |   25 +
 sources/include/citygml/geometry.h                 |   87 +
 sources/include/citygml/geometrymanager.h          |   42 +
 sources/include/citygml/georeferencedtexture.h     |   31 +
 sources/include/citygml/implictgeometry.h          |   45 +
 sources/include/citygml/linearring.h               |   42 +
 sources/include/citygml/material.h                 |   49 +
 sources/include/citygml/materialtargetdefinition.h |   20 +
 sources/include/citygml/object.h                   |   41 +
 sources/include/citygml/polygon.h                  |  121 ++
 sources/include/citygml/polygonmanager.h           |   42 +
 sources/include/citygml/tesselator.h               |   86 +
 sources/include/citygml/texture.h                  |   61 +
 sources/include/citygml/texturecoordinates.h       |   34 +
 sources/include/citygml/texturetargetdefinition.h  |   52 +
 sources/include/citygml/transformmatrix.h          |   26 +
 {src => sources/include/citygml}/utils.h           |  143 +-
 sources/include/citygml/vecs.hpp                   |  338 ++++
 sources/include/parser/appearanceelementparser.h   |   34 +
 sources/include/parser/attributes.h                |   36 +
 sources/include/parser/citygmldocumentparser.h     |   86 +
 sources/include/parser/citygmlelementparser.h      |   87 +
 sources/include/parser/citymodelelementparser.h    |   35 +
 sources/include/parser/cityobjectelementparser.h   |   53 +
 .../include/parser/delayedchoiceelementparser.h    |   30 +
 sources/include/parser/documentlocation.h          |   35 +
 sources/include/parser/elementparser.h             |   56 +
 sources/include/parser/geocoordinatetransformer.h  |   38 +
 sources/include/parser/geometryelementparser.h     |   36 +
 .../parser/georeferencedtextureelementparser.h     |   31 +
 .../include/parser/gmlfeaturecollectionparser.h    |   28 +
 .../include/parser/implicitgeometryelementparser.h |   36 +
 sources/include/parser/linearringelementparser.h   |   31 +
 sources/include/parser/materialelementparser.h     |   34 +
 sources/include/parser/nodetypes.h                 |  290 ++++
 sources/include/parser/parserutils.hpp             |   92 ++
 sources/include/parser/polygonelementparser.h      |   33 +
 sources/include/parser/textureelementparser.h      |   37 +
 sources/src/citygml/appearance.cpp                 |   77 +
 sources/src/citygml/appearancemanager.cpp          |  100 ++
 sources/src/citygml/appearancetarget.cpp           |  123 ++
 sources/src/citygml/citygmlfactory.cpp             |  142 ++
 sources/src/citygml/citymodel.cpp                  |  141 ++
 sources/src/citygml/cityobject.cpp                 |  252 +++
 sources/src/citygml/envelope.cpp                   |   66 +
 sources/src/citygml/featureobject.cpp              |   27 +
 sources/src/citygml/geometry.cpp                   |  140 ++
 sources/src/citygml/geometrymanager.cpp            |   56 +
 sources/src/citygml/georeferencedtexture.cpp       |   40 +
 sources/src/citygml/implictgeometry.cpp            |   56 +
 sources/src/citygml/linearring.cpp                 |  132 ++
 sources/src/citygml/material.cpp                   |   80 +
 sources/src/citygml/materialtargetdefinition.cpp   |   10 +
 sources/src/citygml/object.cpp                     |   53 +
 sources/src/citygml/polygon.cpp                    |  270 ++++
 sources/src/citygml/polygonmanager.cpp             |   56 +
 sources/src/citygml/tesselator.cpp                 |  232 +++
 sources/src/citygml/texture.cpp                    |   95 ++
 sources/src/citygml/texturecoordinates.cpp         |   40 +
 sources/src/citygml/texturetargetdefinition.cpp    |   54 +
 sources/src/citygml/transformmatrix.cpp            |   43 +
 sources/src/parser/appearanceelementparser.cpp     |  120 ++
 sources/src/parser/attributes.cpp                  |   31 +
 sources/src/parser/citygmldocumentparser.cpp       |  187 +++
 sources/src/parser/citygmlelementparser.cpp        |   57 +
 sources/src/parser/citymodelelementparser.cpp      |  100 ++
 sources/src/parser/cityobjectelementparser.cpp     |  377 +++++
 sources/src/parser/delayedchoiceelementparser.cpp  |   74 +
 sources/src/parser/elementparser.cpp               |   21 +
 sources/src/parser/geocoordinatetransformer.cpp    |  280 ++++
 sources/src/parser/geometryelementparser.cpp       |  167 ++
 .../parser/georeferencedtextureelementparser.cpp   |   64 +
 sources/src/parser/gmlfeaturecollectionparser.cpp  |   95 ++
 .../src/parser/implicitgeometryelementparser.cpp   |  129 ++
 sources/src/parser/linearringelementparser.cpp     |   95 ++
 sources/src/parser/materialelementparser.cpp       |  119 ++
 sources/src/parser/nodetypes.cpp                   |  592 +++++++
 sources/src/parser/parserxercesc.cpp               |  346 ++++
 sources/src/parser/polygonelementparser.cpp        |  109 ++
 sources/src/parser/textureelementparser.cpp        |  154 ++
 src/CMakeLists.txt                                 |   85 -
 src/citymodel.cpp                                  |  654 --------
 src/parser.cpp                                     |  909 -----------
 src/parser.h                                       |  339 ----
 src/parserlibxml2.cpp                              |  208 ---
 src/parserxercesc.cpp                              |  179 --
 src/tesselator.cpp                                 |  138 --
 src/tesselator.h                                   |   75 -
 src/transform.h                                    |   96 --
 test/CMakeLists.txt                                |   45 +-
 test/citygml2vrml/CMakeLists.txt                   |   58 -
 test/citygml2vrml/citygml2vrml.cpp                 |  365 -----
 test/citygmltest.cpp                               |  153 +-
 test/osgplugin/CMakeLists.txt                      |   10 -
 test/osgplugin/ReaderWriterCityGML.cpp             |  478 ------
 127 files changed, 11873 insertions(+), 4997 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a70a610
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,20 @@
+# 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/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..47781ae
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: 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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f87b59b..fb08801 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,30 +1,18 @@
-
-IF(WIN32)
-    CMAKE_MINIMUM_REQUIRED(VERSION 2.8.2 FATAL_ERROR)
-ELSE(WIN32)
-    IF(APPLE)
-        CMAKE_MINIMUM_REQUIRED(VERSION 2.4.6 FATAL_ERROR)
-        IF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4 AND ${CMAKE_PATCH_VERSION} LESS 7)
-            MESSAGE("Warning: A critical CMake bug exists in 2.4.6 and below. Trying to build Universal Binaries will result in a compile error that seems unrelated. Either avoid building Universal Binaries by changing the CMAKE_OSX_ARCHITECTURES field to list only your architecture, or upgrade to the current CVS version of CMake or a newer stable version if it exists.")
-        ENDIF(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4 AND ${CMAKE_PATCH_VERSION} LESS 7)
-    ELSE(APPLE)
-        CMAKE_MINIMUM_REQUIRED(VERSION 2.4.0 FATAL_ERROR)
-    ENDIF(APPLE)
-ENDIF(WIN32)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.2 FATAL_ERROR)
 
 PROJECT ( libcitygml )
 
+set(META_VERSION_MAJOR       "1")
+set(META_VERSION_MINOR       "2")
+set(META_VERSION_PATCH       "1")
+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)
-        # This option is to enable the /MP switch for Visual Studio 2005 and above compilers
-        OPTION(WIN32_USE_MP "Set to ON to build libcitygml with the /MP option (Visual Studio 2005 and above)." OFF)
-        MARK_AS_ADVANCED(WIN32_USE_MP)
-        IF(WIN32_USE_MP)
-            SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
-        ENDIF(WIN32_USE_MP)
+        SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
 
         # More MSVC specific compilation flags
         ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
@@ -35,6 +23,7 @@ IF(WIN32)
     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
@@ -65,23 +54,34 @@ IF(WIN32)
     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 !
+  # 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) 
+    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." OFF)
+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)
@@ -104,33 +104,54 @@ SET(LIBRARY_OUTPUT_PATH ${OUTPUT_LIBDIR})
 
 OPTION(LIBCITYGML_STATIC_CRT "Set to ON to link libcitygml with the multithread CRT static library (instead of DLL)." ON)
 
-# xml library
-OPTION(LIBCITYGML_USE_XERCESC "Set to ON to build libcitygml with Xerces-c library." ON)
-OPTION(LIBCITYGML_USE_LIBXML2 "Set to ON to build libcitygml with LibXml2 library." OFF)
-
 # gdal library
-OPTION(LIBCITYGML_USE_GDAL "Set to ON to build libcitygml with GDAL library and support coordinates reprojections." OFF)
-
-IF ( LIBCITYGML_USE_XERCESC )
-	IF( LIBCITYGML_USE_LIBXML2 )
-		MESSAGE("Error: You cannot build the library with Xerces-c AND LibXml2! Xerces library will be used by default.")
-		UNSET( LIBCITYGML_USE_LIBXML2 )
-	ENDIF( LIBCITYGML_USE_LIBXML2 )
-ENDIF( LIBCITYGML_USE_XERCESC )
+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( src )
+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 )
+  ADD_SUBDIRECTORY( test )
 ENDIF(LIBCITYGML_TESTS)
 
-OPTION(LIBCITYGML_VRML "Set to ON to build citygml2vrml program." ON)
-IF   (LIBCITYGML_VRML)
-	ADD_SUBDIRECTORY( test/citygml2vrml )
-ENDIF(LIBCITYGML_VRML)
 
 #-----------------------------------------------------------------------------
 ### uninstall target
@@ -140,4 +161,54 @@ CONFIGURE_FILE(
   "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
   IMMEDIATE @ONLY)
 ADD_CUSTOM_TARGET(uninstall
-  "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
\ No newline at end of file
+  "${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 <marcel.pursche at 3dcontentlogistics.com>")
+
+    # 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()
diff --git a/CMakeModules/FindCityGML.cmake b/CMakeModules/FindCityGML.cmake
index 690d768..d300ff1 100644
--- a/CMakeModules/FindCityGML.cmake
+++ b/CMakeModules/FindCityGML.cmake
@@ -41,7 +41,7 @@ IF( CITYGML_USE_LIBXML2 )
 	SET( XERCESC_LIBRARY_DEBUG "" )
 ENDIF( CITYGML_USE_LIBXML2 )
 
-FIND_PATH( CITYGML_INCLUDE_DIR citygml.h
+FIND_PATH( CITYGML_INCLUDE_DIR citygml/citygml.h
 	./include
 	../include
 	$ENV{CITYGML_DIR}/include
diff --git a/CMakeModules/FindIconv.cmake b/CMakeModules/FindIconv.cmake
deleted file mode 100644
index 4a554be..0000000
--- a/CMakeModules/FindIconv.cmake
+++ /dev/null
@@ -1,54 +0,0 @@
-# Locate iconv
-# This module defines
-# ICONV_LIBRARY
-# ICONV_FOUND, if false, do not try to link to ICONV 
-# ICONV_INCLUDE_DIR, where to find the headers
-#
-# $ICONV_DIR is an environment variable that would
-# correspond to the ./configure --prefix=$ICONV_DIR
-
-
-FIND_PATH(ICONV_INCLUDE_DIR iconv.h
-        ${ICONV_DIR}/include
-    $ENV{ICONV_DIR}/include
-    $ENV{ICONV_DIR}
-    $ENV{OSGDIR}/include
-    $ENV{OSGDIR}
-    $ENV{OSG_ROOT}/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(ICONV_LIBRARY 
-    NAMES ICONV
-    PATHS
-    ${ICONV_DIR}/lib
-    $ENV{ICONV_DIR}/lib
-    $ENV{ICONV_DIR}
-    $ENV{OSGDIR}/lib
-    $ENV{OSGDIR}
-    $ENV{OSG_ROOT}/lib
-    ~/Library/Frameworks
-    /Library/Frameworks
-    /usr/local/lib
-    /usr/lib
-    /sw/lib
-    /opt/local/lib
-    /opt/csw/lib
-    /opt/lib
-    /usr/freeware/lib64
-)
-
-SET(ICONV_FOUND "NO")
-IF(ICONV_LIBRARY AND ICONV_INCLUDE_DIR)
-    SET(ICONV_FOUND "YES")
-ENDIF(ICONV_LIBRARY AND ICONV_INCLUDE_DIR)
-
-
diff --git a/CMakeModules/FindXerces.cmake b/CMakeModules/FindXerces.cmake
index dfa41cb..3442d6a 100644
--- a/CMakeModules/FindXerces.cmake
+++ b/CMakeModules/FindXerces.cmake
@@ -21,7 +21,7 @@ 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 
+PATHS
 $ENV{XERCESC_INCLUDE_DIR}
 ${XERCESC_INCLUDE_DIR}
  /usr/local/include
@@ -60,19 +60,19 @@ ENDIF (XERCESC_STATIC)
 SET(XERCESC_FOUND FALSE)
 
 IF (XERCESC_INCLUDE AND XERCESC_LIBRARY)
-	SET(XERCESC_FOUND TRUE)
+  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})
+   SET(XERCESC_LIBRARIES
+          optimized ${XERCESC_LIBRARY}
+          debug ${XERCESC_LIBRARY_DEBUG})
   ELSE(${XERCESC_LIBRARY_DEBUG})
-		SET(XERCESC_LIBRARIES	${XERCESC_LIBRARY})
-	ENDIF(${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)
@@ -109,4 +109,4 @@ ELSE(XERCESC_FOUND)
 MESSAGE(FATAL_ERROR "Could not find Xerces-C !")
 ENDIF(XERCESC_FOUND)
 
-MARK_AS_ADVANCED(XERCESC_INCLUDE XERCESC_LIBRARY)
\ No newline at end of file
+MARK_AS_ADVANCED(XERCESC_INCLUDE XERCESC_LIBRARY)
diff --git a/CMakeModules/ModuleInstall.cmake b/CMakeModules/ModuleInstall.cmake
deleted file mode 100644
index 3d6aa07..0000000
--- a/CMakeModules/ModuleInstall.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-# INSTALL and SOURCE_GROUP commands for OSG/OT/Producer Modules
-
-# Required Vars:
-# ${LIB_NAME}
-# ${LIB_PUBLIC_HEADERS}
-
-SET(INSTALL_INCDIR include)
-SET(INSTALL_BINDIR bin)
-IF(WIN32)
-    SET(INSTALL_LIBDIR bin)
-    SET(INSTALL_ARCHIVEDIR lib)
-ELSE(WIN32)
-    SET(INSTALL_LIBDIR lib${LIB_POSTFIX})
-    SET(INSTALL_ARCHIVEDIR lib${LIB_POSTFIX})
-ENDIF(WIN32)
-
-SET(HEADERS_GROUP "Header Files")
-
-SOURCE_GROUP(
-    ${HEADERS_GROUP}
-    FILES ${LIB_PUBLIC_HEADERS}
-)
-
-
-INSTALL(
-    TARGETS ${LIB_NAME}
-    RUNTIME DESTINATION ${INSTALL_BINDIR}
-    LIBRARY DESTINATION ${INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${INSTALL_ARCHIVEDIR}
-)
-# FIXME: Do not run for OS X framework
-INSTALL(
-    FILES        ${LIB_PUBLIC_HEADERS}
-    DESTINATION ${INSTALL_INCDIR}
-)
diff --git a/CMakeModules/cmake_uninstall.cmake.in b/CMakeModules/cmake_uninstall.cmake.in
index c35ed14..e974439 100644
--- a/CMakeModules/cmake_uninstall.cmake.in
+++ b/CMakeModules/cmake_uninstall.cmake.in
@@ -19,4 +19,4 @@ FOREACH(file ${files})
   ELSE(EXISTS "${file}")
     MESSAGE(STATUS "File \"${file}\" does not exist.")
   ENDIF(EXISTS "${file}")
-ENDFOREACH(file)
\ No newline at end of file
+ENDFOREACH(file)
diff --git a/README b/README
deleted file mode 100644
index 5857eb5..0000000
--- a/README
+++ /dev/null
@@ -1,5 +0,0 @@
-libcitygml - Copyright (c) 2010 Joachim Pouderoux, BRGM
-
-http://code.google.com/p/libcitygml
-
-Use CMake on the CMakeLists.txt to generate a Visual Studio 20xy solution or a set of Makefiles.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8772897
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+libcitygml
+==========
+[![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/).
+
+
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..d940865
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,22 @@
+# libcitygml TODO List
+
+# Correctness
+* Fix texture coordinates when tesselation removes or adds vertices
+* 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
+* Check if non implicit geoemtries can be shared
+* 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)
+
+# 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)
+* Implement georefereced texture parsing
+
+# 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) 
diff --git a/citygml_to_libcitygml_mapping.graphml b/citygml_to_libcitygml_mapping.graphml
new file mode 100644
index 0000000..80c5af6
--- /dev/null
+++ b/citygml_to_libcitygml_mapping.graphml
@@ -0,0 +1,1702 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
+  <!--Created by yEd 3.13-->
+  <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
+  <key for="port" id="d1" yfiles.type="portgraphics"/>
+  <key for="port" id="d2" yfiles.type="portgeometry"/>
+  <key for="port" id="d3" yfiles.type="portuserdata"/>
+  <key attr.name="url" attr.type="string" for="node" id="d4"/>
+  <key attr.name="description" attr.type="string" for="node" id="d5"/>
+  <key for="node" id="d6" yfiles.type="nodegraphics"/>
+  <key for="graphml" id="d7" yfiles.type="resources"/>
+  <key attr.name="url" attr.type="string" for="edge" id="d8"/>
+  <key attr.name="description" attr.type="string" for="edge" id="d9"/>
+  <key for="edge" id="d10" yfiles.type="edgegraphics"/>
+  <graph edgedefault="directed" id="G">
+    <data key="d0"/>
+    <node id="n0">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="568.5833333333335" y="81.33333333333326"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="80.2353515625" x="37.88232421875" y="3.0">CityObject<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n1">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="47.0" width="210.0" x="100.16666666666697" y="81.33333333333326"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="136.36767578125" x="36.816162109375" y="25.96875">GenericCityObject<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="Feature" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n2">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="154.0" width="210.0" x="100.16666666666697" y="-132.50000000000006"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="154.0" modelName="custom" textColor="#000000" visible="true" width="210.0" x="0.0" y="0.0">Building, BuildingPart, Room, BuildingInstallation, BuildingFurniture, Door, Window, CityFurniture, Track, Road, Railway, Square, PlantCover, SolitaryVegetationObject, WaterBody, TINRelief, Land [...]
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n3">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="163.0" x="-196.75" y="90.83333333333326"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="136.79296875" x="13.103515625" y="3.0">_BoundarySurface<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n4">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="69.0" width="210.0" x="-220.25" y="-47.50000000000006"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="69.0" modelName="custom" textColor="#000000" visible="true" width="210.0" x="0.0" y="0.0">WallSurface, RoofSurface, GroundSurface, ClosureSurface, FloorSurface, InteriorWallSurface, CeilingSurface<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n5">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="210.0" x="100.16666666666697" y="169.16666666666657"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="70.93603515625" x="69.531982421875" y="3.0">Envelope<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n6">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="568.5833333333335" y="169.16666666666657"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="70.93603515625" x="42.531982421875" y="3.0">Envelope<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n7">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="100.16666666666697" y="227.16666666666657"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="93.99072265625" x="3.004638671875" y="3.0">lowerCorner<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n8">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="210.16666666666697" y="227.16666666666657"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="96.4599609375" x="1.77001953125" y="3.0">upperCorner<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n9">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="568.5833333333335" y="312.4999999999999"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="130.85791015625" x="12.571044921875" y="3.0">ImplicitGeometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n10">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="210.0" x="100.16666666666697" y="312.4999999999999"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="130.85791015625" x="39.571044921875" y="3.0">ImplicitGeometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n11">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="163.0" x="147.16666666666697" y="381.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="132.298828125" x="15.3505859375" y="3.0">relativeGeometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n12">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="147.0" x="-350.0" y="381.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="113.0908203125" x="16.95458984375" y="3.0">referencePoint<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n13">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="147.0" x="-561.25" y="381.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="74.890625" x="36.0546875" y="3.0">gml:Point<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n14">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="92.29333333333335" width="210.0" x="275.16666666666697" y="467.9566666666667"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="92.29333333333335" modelName="custom" textColor="#000000" visible="true" width="210.0" x="0.0" y="-5.6843418860808015E-14">TexturedSurface, MultiSurface, CompositeSurface, TriangulatedSurface, OrientableSurface<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n15">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="568.5833333333335" y="511.75"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="75.880859375" x="40.0595703125" y="3.0">Geometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n16">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="210.0" x="100.16666666666697" y="724.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="69.380859375" x="70.3095703125" y="3.0">_Polygon<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n17">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="69.0" width="210.0" x="275.16666666666697" y="584.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="69.0" modelName="custom" textColor="#000000" visible="true" width="210.0" x="0.0" y="0.0">surfaceMember, baseSurface, patches, trianglePatches<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n18">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="-34.83333333333303" y="570.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="62.880859375" x="36.0595703125" y="3.0">Polygon<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n19">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="-34.83333333333303" y="656.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="64.3408203125" x="35.32958984375" y="3.0">Triangle<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n20">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="568.5833333333335" y="724.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="62.880859375" x="36.0595703125" y="3.0">Polygon<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n21">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="210.0" x="-139.83333333333303" y="832.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="101.0302734375" x="54.48486328125" y="3.0">_SurfaceData<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n22">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="210.0" x="-139.83333333333303" y="782.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="91.22314453125" x="59.388427734375" y="3.0">Appearance<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n23">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="-84.83333333333303" y="732.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="50.64892578125" x="24.675537109375" y="3.0">theme<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n24">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="30.16666666666697" y="905.0833333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="94.6953125" x="2.65234375" y="3.0">X3DMaterial<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n25">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="-162.33333333333303" y="905.0833333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="129.68994140625" x="2.655029296875" y="3.0">_AbstractTexture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n26">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="198.75" x="-19.20833333333303" y="1034.708333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="168.201171875" x="15.2744140625" y="3.0">ParameterizedTexture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n27">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="198.75" x="-19.20833333333303" y="991.4999999999998"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="169.19775390625" x="14.776123046875" y="3.0">GeoreferencedTexture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n28">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="568.5833333333335" y="905.0833333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="64.8359375" x="35.08203125" y="3.0">Material<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n29">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="568.5833333333335" y="1034.708333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="60.76708984375" x="37.116455078125" y="3.0">Texture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n30">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="190.83333333333326" x="568.5833333333335" y="991.4999999999998"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="169.19775390625" x="10.817789713541629" y="3.0">GeoreferencedTexture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n31">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="30.16666666666697" y="948.2916666666665"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="49.73486328125" x="25.132568359375" y="3.0">target<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n32">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="30.16666666666697" y="1092.708333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="49.73486328125" x="25.132568359375" y="3.0">target<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n33">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="127.5" x="-60.0" y="1132.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="101.931640625" x="12.7841796875" y="3.0">TexCoordGen<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n34">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="127.5" x="97.5" y="1132.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="99.88134765625" x="13.809326171875" y="3.0">TexCoordList<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n35">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="568.5833333333335" y="948.2916666666665"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="113.22412109375" x="10.887939453125" y="3.0">MaterialTarget<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n36">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="135.0" x="568.5833333333335" y="1092.708333333333"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="109.1552734375" x="12.92236328125" y="3.0">TextureTarget<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n37">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="155.0" x="568.5833333333335" y="1132.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="149.13916015625" x="2.930419921875" y="3.0">TextureCoordinates<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n38">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="28.0" width="230.0" x="-343.75" y="220.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="199.5390625" x="15.23046875" y="5.015625">lodXMultiSurface, lodXGeometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n39">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="28.0" width="181.25" x="-103.75" y="220.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="166.603515625" x="7.3232421875" y="5.015625">lodXImplicitRepresentation<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n40">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="155.16666666666697" y="820.75"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="83.02197265625" x="8.489013671875" y="3.0">LinearRing<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n41">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="568.5833333333335" y="820.75"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="83.02197265625" x="8.489013671875" y="3.0">LinearRing<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n42">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="28.0" width="135.0" x="137.66666666666697" y="772.375"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="102.314453125" x="16.3427734375" y="5.015625">interior, exterior<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n43">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="28.0" width="128.25" x="134.41666666666697" y="501.5625"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="102.314453125" x="12.9677734375" y="5.015625">exterior, interior<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n44">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="15.75" y="499.25"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="40.51171875" x="29.744140625" y="3.0">Solid<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n45">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="28.0" width="181.25" x="-536.6666666666666" y="220.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="custom" textColor="#000000" visible="true" width="59.7578125" x="60.74609375" y="5.015625">lodXSolid<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n46">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="-537.75" y="481.04166666666646"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="62.703125" x="18.6484375" y="3.0">gml:Pos<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n47">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="155.16666666666697" y="868.5416666666665"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="89.1728515625" x="5.41357421875" y="3.0">gml:posList<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n48">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="92.29333333333332" width="169.54166666666686" x="408.4654545454546" y="-40.581818181818164"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="92.29333333333332" modelName="custom" textColor="#000000" visible="true" width="169.54166666666686" x="0.0" y="0.0">boundedBy, outerBuildingInstallation, interiorBuildingInstallation, interiorFurniture, roomInstallation, interiorRoom, opening<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n49">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="30.0" width="135.0" x="-57.5" y="442.9527272727273"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="30.0" modelName="custom" textColor="#000000" visible="true" width="135.0" x="0.0" y="0.0">solidMember<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <node id="n50">
+      <data key="d4"/>
+      <data key="d6">
+        <y:UMLNoteNode>
+          <y:Geometry height="46.99999999999994" width="181.25" x="-268.75" y="462.60136363636366"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="node_size" configuration="CroppingLabel" fontFamily="Dialog" fontSize="12" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="46.99999999999994" modelName="custom" textColor="#000000" visible="true" width="181.25" x="0.0" y="5.6843418860808015E-14">CompositeSolid, MultiSolid<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="0.0" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+        </y:UMLNoteNode>
+      </data>
+    </node>
+    <edge id="e0" source="n2" target="n1">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e1" source="n4" target="n3">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e2" source="n3" target="n1">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e3" source="n0" target="n1">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="5.83333333333303" ty="-9.5"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e4" source="n1" target="n5">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e5" source="n6" target="n5">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e6" source="n5" target="n7">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e7" source="n5" target="n8">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e8" source="n9" target="n10">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e9" source="n39" target="n1">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="-55.0" ty="9.93154761904767">
+            <y:Point x="17.0" y="158.24999999999994"/>
+            <y:Point x="150.16666666666697" y="158.24999999999994"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e10" source="n10" target="n11">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e11" source="n10" target="n12">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="-118.91666666666663" y="395.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e12" source="n12" target="n13">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e13" source="n11" target="n14">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="23.5" ty="22.40454106280186"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e14" source="n15" target="n14">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e15" source="n1" target="n38">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="129.25" y="144.75"/>
+            <y:Point x="-28.25" y="144.75"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e16" source="n16" target="n17">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="-20.91666666666697" sy="-3.3333333333333712" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e17" source="n17" target="n14">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e18" source="n18" target="n16">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e19" source="n19" target="n16">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e20" source="n16" target="n20">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e21" source="n22" target="n23">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e22" source="n25" target="n21">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e23" source="n24" target="n21">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e24" source="n26" target="n25">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="-78.125" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e25" source="n27" target="n25">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e26" source="n22" target="n21">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e27" source="n28" target="n24">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e28" source="n29" target="n26">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e29" source="n30" target="n27">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e30" source="n27" target="n12">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="-276.5" y="1005.4999999999998"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e31" source="n24" target="n31">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="-33.66666666666697" sy="-6.3333333333332575" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e32" source="n27" target="n31">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e33" source="n26" target="n32">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e34" source="n32" target="n33">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e35" source="n32" target="n34">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e36" source="n35" target="n31">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e37" source="n36" target="n32">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e38" source="n37" target="n34">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e39" source="n38" target="n14">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e40" source="n39" target="n10">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e41" source="n16" target="n42">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e42" source="n40" target="n41">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e43" source="n42" target="n40">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e44" source="n14" target="n43">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="-24.41666666666697" sy="-2.0063768115942033" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e45" source="n50" target="n49">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="18.512575757575803" sy="-11.376363636363635" tx="-31.86818181818171" ty="4.24727272727273"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e46" source="n44" target="n43">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e47" source="n1" target="n45">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="-217.16666666666663" y="155.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e48" source="n45" target="n50">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="-187.16666666666663" y="340.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e49" source="n13" target="n46">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e50" source="n46" target="n40">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="43.91666666666674" y="721.5"/>
+            <y:Point x="131.41666666666674" y="834.75"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e51" source="n40" target="n47">
+      <data key="d8"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e52" source="n1" target="n48">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="327.19393939393944" y="14.05939393939397"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e53" source="n48" target="n1">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="352.6775757575758" y="52.28484848484851"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e54" source="n49" target="n44">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e55" source="n44" target="n15">
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="65.75" y="549.4254545454546"/>
+            <y:Point x="288.2157575757577" y="576.3248484848485"/>
+            <y:Point x="524.6472727272728" y="576.3248484848485"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e56" source="n50" target="n15">
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="-99.70181818181817" y="416.34424242424245"/>
+            <y:Point x="571.3672727272728" y="416.34424242424245"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="none"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+  </graph>
+  <data key="d7">
+    <y:Resources/>
+  </data>
+</graphml>
diff --git a/debian_scripts/postinst b/debian_scripts/postinst
new file mode 100755
index 0000000..762f474
--- /dev/null
+++ b/debian_scripts/postinst
@@ -0,0 +1 @@
+ldconfig 
diff --git a/include/citygml.h b/include/citygml.h
deleted file mode 100644
index da3d97e..0000000
--- a/include/citygml.h
+++ /dev/null
@@ -1,749 +0,0 @@
-/* -*-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 __CITYGML_H__
-#define __CITYGML_H__
-
-#include <iostream>
-#include <string>
-#include <vector>
-#include <sstream>
-#include <map>
-#include <stdio.h>
-#include <stdlib.h>
-#include "vecs.h"
-
-#define LIBCITYGML_VERSION_MAJOR 0
-#define LIBCITYGML_VERSION_MINOR 1
-#define LIBCITYGML_VERSION_REVISION 4
-
-#define LIBCITYGML_VERSIONSTR "0.1.4"
-
-#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
-
-class Tesselator;
-
-namespace citygml 
-{
-	class CityModel;
-
-	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_TINRelief                   = 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_All                         = 0xFFFFFFFF
-	};
-
-	typedef unsigned int CityObjectsTypeMask;
-
-	///////////////////////////////////////////////////////////////////////////////
-	// Parsing routines
-
-	// Parameters:
-	// objectsMask: a string describing the objects types that must or must not be parsed
-	//    examples: "All&~LandUse&~TINRelief" to parse everything but landuses and TIN reliefs
-	//              "Road&Railway" to parse only roads & railways
-	// 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( void ) : objectsMask( "All" ), minLOD( 0 ), maxLOD( 4 ), optimize( false ), pruneEmptyObjects( false ), tesselate( true ), destSRS( "" ) { }
-
-	public:
-		std::string objectsMask; 
-		unsigned int minLOD; 
-		unsigned int maxLOD;
-		bool optimize; 
-		bool pruneEmptyObjects; 
-		bool tesselate;
-		std::string destSRS;
-	};
-
-	LIBCITYGML_EXPORT CityModel* load( std::istream& stream, const ParserParams& params );
-
-	LIBCITYGML_EXPORT CityModel* load( const std::string& fileName, const ParserParams& params );
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	class Envelope
-	{
-		friend class CityGMLHandler;
-	public:
-		Envelope( void ) {}
-
-		Envelope( const TVec3d& lowerBound, const TVec3d& upperBound )
-		{ 
-			_lowerBound = lowerBound; 
-			_upperBound = upperBound; 
-		}
-
-		inline const TVec3d& getLowerBound( void ) const { return _lowerBound; }
-		inline const TVec3d& getUpperBound( void ) const { return _upperBound; }
-
-	protected:
-		TVec3d _lowerBound;
-		TVec3d _upperBound;
-	};
-
-	typedef std::map< std::string, std::string > AttributesMap;
-	///////////////////////////////////////////////////////////////////////////////
-	// Base object associated with an unique id and a set of attributes (key-value pairs)
-	class Object 
-	{
-		friend class CityGMLHandler;
-		friend std::ostream& operator<<( std::ostream&, const Object & );
-	public:
-		Object( const std::string& id ) : _id( id ) { if ( _id == "" ) { std::stringstream ss; ss << "PtrId_" << this; _id = ss.str(); } }
-
-		virtual ~Object( void ) {}
-
-		inline const std::string& getId( void ) const { return _id; }
-
-		inline std::string getAttribute( const std::string& name ) const
-		{
-			std::map< std::string, std::string >::const_iterator elt = _attributes.find( name );
-			return elt != _attributes.end() ? elt->second : "";
-		}
-
-		inline const AttributesMap& getAttributes() const { return _attributes; }
-
-		inline AttributesMap& getAttributes() { return _attributes; }
-
-	protected:
-		inline void setAttribute( const std::string& name, const std::string& value, bool forceOnExist = true )
-		{
-			if ( !forceOnExist )
-			{
-				std::map< std::string, std::string >::const_iterator elt = _attributes.find( name );
-				if ( elt != _attributes.end() ) return;
-			}
-			_attributes[ name ] = value;				
-		}
-
-	protected:
-		std::string _id;
-
-		AttributesMap _attributes;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	class Appearance : public Object
-	{
-		friend class CityGMLHandler;
-	public:
-		Appearance( const std::string& id, const std::string& typeString ) : Object( id ), _typeString( typeString ), _isFront(true) {}
-
-		virtual ~Appearance( void ) {}
-
-		inline std::string getType( void ) const { return _typeString; }
-		inline bool getIsFront( void ) const { return _isFront; }
-
-		virtual std::string toString( void ) const { return _typeString + " " + _id; }
-
-	protected:
-		std::string _typeString;
-		bool _isFront;
-	};
-
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	class Texture : virtual public Appearance
-	{
-		friend class CityGMLHandler;
-		
-	public:
-		typedef enum WrapMode 
-		{
-			WM_NONE = 0,	// 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)
-		} WrapMode;
-
-		Texture( const std::string& id ) : Appearance( id, "Texture" ), _repeat( false ), _wrapMode( WM_NONE ) {}
-
-		inline std::string getUrl( void ) const { return _url; }
-
-		inline bool getRepeat( void ) const { return _repeat; }
-
-		inline WrapMode getWrapMode( void ) const { return _wrapMode; }
-
-		inline TVec4f getBorderColor( void ) const { return _borderColor; }
-
-		inline std::string toString( void ) const { return Appearance::toString() + " (url: " + _url + ")"; }
-
-	protected:
-		std::string _url;
-		bool _repeat;
-		WrapMode _wrapMode;
-		TVec4f _borderColor;
-	};
-
-	class GeoreferencedTexture : public Texture
-	{
-		friend class CityGMLHandler;
-
-	public:
-		GeoreferencedTexture( const std::string& id ) : Appearance( id, "GeoreferencedTexture" ), Texture( id ), _preferWorldFile(true) {}
-
-		inline bool getPreferWorldFile( void ) const { return _preferWorldFile; }
-
-		// TODO support referencePoint and orientation
-
-	protected:
-		bool _preferWorldFile;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	class Material : virtual public Appearance
-	{
-		friend class CityGMLHandler;
-	public:
-		Material( const std::string& id ) : Appearance( id, "Material" ), _ambientIntensity( 0.f ), _shininess( 0.f ), _transparency( 0.f ) {}
-
-		inline TVec3f getDiffuse( void ) const { return _diffuse; }
-		inline TVec3f getEmissive( void ) const { return _emissive; }
-		inline TVec3f getSpecular( void ) const { return _specular; }
-		inline float getAmbientIntensity( void ) const { return _ambientIntensity; }
-		inline float getShininess( void ) const { return _shininess; }
-		inline float getTransparency( void ) const { return _transparency; }
-
-	protected:
-		TVec3f _diffuse;
-		TVec3f _emissive;
-		TVec3f _specular;
-		float _ambientIntensity;
-		float _shininess;
-		float _transparency;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	typedef std::vector<TVec2f> TexCoords;
-
-	class AppearanceManager 
-	{
-		friend class CityGMLHandler;
-		friend class CityModel;
-	public:
-		AppearanceManager( void );
-
-		~AppearanceManager( void );
-
-		typedef enum ForSide 
-		{
-			FS_ANY = 0,	// appearance for any side
-			FS_FRONT,	// appearance for front side
-			FS_BACK		// appearance for back side
-		};
-
-		inline Appearance* getAppearance( const std::string& nodeid ) const
-		// Deprecated, use getMaterial and getTexture instead.
-		{
-			return getAppearance< Appearance* >( nodeid );
-		}
-		inline Material* getMaterial( const std::string& nodeid ) const
-		{
-			return getAppearance< Material* >( nodeid );
-		}
-
-		inline Texture* getTexture( const std::string& nodeid ) const
-		{
-			return getAppearance< Texture* >( nodeid );
-		}
-
-		// Getter for the front&back material if there is any.
-		inline Material* getMaterialFront( const std::string& nodeid ) const
-		{
-			return getAppearance< Material* >( nodeid, FS_FRONT );
-		}
-		inline Material* getMaterialBack( const std::string& nodeid ) const
-		{
-			return getAppearance< Material* >( nodeid, FS_BACK );
-		}
-
-		inline bool getTexCoords( const std::string& nodeid, TexCoords &texCoords) const
-		{
-			texCoords.clear();
-			std::map<std::string, TexCoords*>::const_iterator it = _texCoordsMap.find( nodeid );
-			if ( it == _texCoordsMap.end() || !it->second ) return false;
-			texCoords = *it->second;
-			return true;
-		}
-
-		inline Tesselator* getTesselator( void ) { return _tesselator; }
-
-	protected:
-		void refresh( void );
-
-		template < typename AppType > AppType getAppearance( const std::string& nodeid, ForSide side = FS_ANY ) const;
-		void addAppearance( Appearance* );
-		void assignNode( const std::string& nodeid );
-		bool assignTexCoords( TexCoords* );
-
-		void finish( void );
-
-	protected:
-		std::string _lastId;
-		TexCoords* _lastCoords;
-
-		std::vector< Appearance* > _appearances;
-
-		std::map< std::string, std::vector< Appearance* > > _appearancesMap;
-
-		std::map<std::string, TexCoords*> _texCoordsMap;
-        std::vector<TexCoords*> _obsoleteTexCoords;
-
-		Tesselator* _tesselator;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	class LinearRing : public Object
-	{
-		friend class CityGMLHandler;
-		friend class Polygon;
-	public:
-		LinearRing( const std::string& id, bool isExterior ) : Object( id ), _exterior( isExterior ) {}
-
-		bool isExterior( void ) const { return _exterior; }
-
-		inline unsigned int size( void ) const { return _vertices.size(); }
-
-		inline const std::vector<TVec3d>& getVertices( void ) const { return _vertices; }
-
-		inline void addVertex( const TVec3d& v ) { _vertices.push_back( v ); }
-
-		LIBCITYGML_EXPORT TVec3d computeNormal( void ) const;
-
-	protected:
-		inline std::vector<TVec3d>& getVertices( void ) { return _vertices; }
-
-		void finish( TexCoords* );
-
-	protected:		
-		bool _exterior;
-
-		std::vector<TVec3d> _vertices;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	class Geometry;
-
-	class Polygon : public Object
-	{
-		friend class CityGMLHandler;
-		friend class Geometry;
-		friend class Tesseletor;
-		friend class CityModel;
-	public:
-		enum AppearanceSide {
-			FRONT = 0,
-			BACK,
-			_NUMBER_OF_SIDES
-		};
-
-		Polygon( const std::string& id ) : 
-		  Object( id ), _appearance( 0 ), _texture( 0 ), _exteriorRing( 0 ), _negNormal( false ), _geometry( 0 ) 
-		  {
-			  _materials[ FRONT ] = 0;
-			  _materials[ BACK ] = 0;
-		  }
-
-		LIBCITYGML_EXPORT ~Polygon( void );
-
-		// Get the vertices
-		inline const std::vector<TVec3d>& getVertices( void ) const { return _vertices; }
-
-		// Get the indices
-		inline const std::vector<unsigned int>& getIndices( void ) const { return _indices; }
-
-		// Get the normals
-		inline const std::vector<TVec3f>& getNormals( void ) const { return _normals; }
-
-		// Get texture coordinates
-		inline const TexCoords& getTexCoords( void ) const { return _texCoords; }
-
-		// Get the appearance
-		inline const Appearance* getAppearance( void ) const { return _appearance; } // Deprecated! Use getMaterial and getTexture instead
-		inline const Material* getMaterial( void ) const 
-		{ 
-			if ( _materials[ FRONT ] ) { return _materials[ FRONT ]; }
-			else { return _materials[ BACK ]; }
-		}
-		inline const Texture* getTexture( void ) const { return _texture; }
-		inline const Material* getMaterialFront( void ) const { return _materials[ FRONT ]; }
-		inline const Material* getMaterialBack( void ) const { return _materials[ BACK ]; }
-
-	protected:
-		void finish( AppearanceManager&, bool doTesselate );
-		void finish( AppearanceManager&, Appearance*,  bool doTesselate );
-
-		void addRing( LinearRing* );
-
-		void tesselate( AppearanceManager &, const TVec3d& );
-		void mergeRings( AppearanceManager & );
-		void clearRings( void );
-
-		TVec3d computeNormal( void );
-
-		bool merge( Polygon* );
-
-	protected:
-		std::vector<TVec3d> _vertices;
-		std::vector<TVec3f> _normals;
-		std::vector<unsigned int> _indices;
-
-		Appearance* _appearance;
-		Material* _materials[ _NUMBER_OF_SIDES ];
-		Texture* _texture;
-
-		TexCoords _texCoords; 
-
-		LinearRing* _exteriorRing;
-		std::vector<LinearRing*> _interiorRings;
-
-		bool _negNormal;
-
-		Geometry *_geometry;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	enum GeometryType 
-	{
-		GT_Unknown = 0,
-		GT_Roof,
-		GT_Wall,
-		GT_Ground,
-		GT_Closure,
-		GT_Floor,
-		GT_InteriorWall,
-		GT_Ceiling,
-	};
-
-	class Geometry : public Object
-	{
-		friend class CityGMLHandler;
-		friend class CityObject;
-		friend std::ostream& operator<<( std::ostream&, const citygml::Geometry& );
-	public:
-		Geometry( const std::string& id, GeometryType type = GT_Unknown, unsigned int lod = 0 ) : Object( id ), _type( type ), _lod( lod ) {}
-
-		LIBCITYGML_EXPORT ~Geometry();
-
-		// Get the geometry LOD
-		inline unsigned int getLOD( void ) const { return _lod; }
-
-		// Get the polygons
-		inline unsigned int size( void ) const { return _polygons.size(); }
-		inline Polygon* operator[]( unsigned int i ) { return _polygons[i]; }
-		inline const Polygon* operator[]( unsigned int i ) const { return _polygons[i]; }
-
-		inline GeometryType getType( void ) const { return _type; }
-
-	protected:
-		void addPolygon( Polygon* );
-
-		void finish( AppearanceManager&, Appearance*, const ParserParams& );
-
-		bool merge( Geometry* );
-
-	protected:
-		GeometryType _type;
-
-		unsigned int _lod;
-
-		std::vector< Polygon* > _polygons;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	LIBCITYGML_EXPORT std::string getCityObjectsClassName( CityObjectsTypeMask mask );
-
-	LIBCITYGML_EXPORT CityObjectsTypeMask getCityObjectsTypeMaskFromString( const std::string& stringMask );
-
-	class CityObject : public Object 
-	{
-		friend class CityGMLHandler;
-		friend class CityModel;
-		friend std::ostream& operator<<( std::ostream&, const CityObject & );
-	public:
-		CityObject( const std::string& id, CityObjectsType type ) : Object( id ), _type( type ) {}
-
-		virtual ~CityObject()
-		{ 
-			std::vector< Geometry* >::const_iterator it = _geometries.begin();
-			for ( ; it != _geometries.end(); ++it ) delete *it;
-		}
-
-		// Get the object type
-		inline CityObjectsType getType( void ) const { return _type; }
-
-		inline std::string getTypeAsString( void ) const { return getCityObjectsClassName( _type ); }
-
-		// Return the envelope (ie. the bounding box) of the object
-		inline const Envelope& getEnvelope( void ) const { return _envelope; }
-
-		// Get the default diffuse color of this object class
-		virtual TVec4f getDefaultColor( void ) const = 0;
-
-		// Get the number of geometries contains in the object
-		inline unsigned int size( void ) const { return _geometries.size(); }
-
-		// Access the geometries
-		inline const Geometry* getGeometry( unsigned int i ) const { return _geometries[i]; }
-
-		// Access the children
-		inline unsigned int getChildCount( void ) const { return _children.size(); }
-
-		inline const CityObject* getChild( unsigned int i ) const { return ( i < getChildCount() ) ? _children[i] : 0; }
-
-		inline CityObject* getChild( unsigned int i ) { return ( i < getChildCount() ) ? _children[i] : 0; }
-
-		inline const std::vector< CityObject* >& getChildren( void ) const { return _children; }
-
-		inline std::vector< CityObject* >& getChildren( void ) { return _children; }
-
-	protected:
-		void finish( AppearanceManager&, const ParserParams& );
-
-	protected:
-		CityObjectsType _type;
-
-		Envelope _envelope;
-
-		std::vector< Geometry* > _geometries;		
-		std::vector< CityObject* > _children;
-	};
-
-#define MAKE_RGBA( _r_, _g_, _b_, _a_ ) TVec4f( _r_/255.f, _g_/255.f, _b_/255.f, _a_/255.f )
-#define MAKE_RGB( _r_, _g_, _b_ ) MAKE_RGBA( _r_, _g_, _b_, 255 )
-
-	// Helper macro to declare a new CityObject type from its name & default color
-#define DECLARE_SIMPLE_OBJECT_CLASS( _name_, _defcolor_ ) \
-	class _name_ : public CityObject \
-	{\
-	public:\
-	_name_( const std::string& id ) : CityObject( id, COT_ ## _name_ ) {}\
-	inline TVec4f getDefaultColor( void ) const { return _defcolor_; }\
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Building, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( BuildingPart, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Room, MAKE_RGB( 181, 180, 163 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Door, MAKE_RGB( 145, 53, 13 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Window, MAKE_RGBA( 147, 170, 209, 60 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( BuildingInstallation, MAKE_RGB( 186, 186, 177 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( BuildingFurniture, MAKE_RGB( 227, 225, 157 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( CityFurniture, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( WaterBody, MAKE_RGB( 48, 133, 187 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( PlantCover, MAKE_RGB( 0, 184, 0 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( SolitaryVegetationObject, MAKE_RGB( 10, 184, 10 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Track, MAKE_RGB( 171, 131, 46 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Road, MAKE_RGB( 159, 159, 159 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Railway, MAKE_RGB( 180, 180, 180 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Square, MAKE_RGB( 159, 159, 159 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( TINRelief, MAKE_RGB( 100, 230, 10 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Tunnel, MAKE_RGB( 180, 180, 150 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( Bridge, MAKE_RGB( 245, 30, 30 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( BridgeConstructionElement, MAKE_RGB( 245, 20, 20 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( BridgeInstallation, MAKE_RGB( 245, 80, 80 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( BridgePart, MAKE_RGB( 245, 50, 50 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( GenericCityObject, MAKE_RGB( 100, 130, 0 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( WallSurface, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( RoofSurface, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( GroundSurface, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( ClosureSurface, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( FloorSurface, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( InteriorWallSurface, MAKE_RGB( 186, 184, 135 ) );
-
-	DECLARE_SIMPLE_OBJECT_CLASS( CeilingSurface, MAKE_RGB( 186, 184, 135 ) );
-
-
-	class LandUse : public CityObject 
-	{
-	public:
-		LandUse( const std::string& id ) : CityObject( id, COT_LandUse ) {}
-
-		inline TVec4f getDefaultColor( void ) const
-		{ 
-			std::string c = getAttribute( "class" );
-			if ( c != "" )
-			{
-				int cl = atoi( c.c_str() );
-				switch ( cl ) 
-				{
-				case 1000: return MAKE_RGB( 150, 143, 134 );	// Settlement Area
-				case 1100: return MAKE_RGB( 133, 83, 101 );		// Undeveloped Area
-				case 2000: return MAKE_RGB( 159, 159, 159 );	// Traffic
-				case 3000: return MAKE_RGB( 79, 212, 53 );		// Vegetation
-				case 4000: return MAKE_RGB( 67, 109, 247 );		// Water
-				}
-			}
-			return MAKE_RGB( 10, 230, 1 ); 
-		}
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	typedef std::vector< CityObject* > CityObjects;
-	typedef std::map< CityObjectsType, CityObjects > CityObjectsMap;
-
-	class CityModel : public Object
-	{
-		friend class CityGMLHandler;
-	public:
-		CityModel( const std::string& id = "CityModel" ) : Object( id ) {} 
-
-		LIBCITYGML_EXPORT ~CityModel( void );
-
-		// Return the envelope (ie. the bounding box) of the model
-		inline const Envelope& getEnvelope( void ) const { return _envelope; }
-
-		// Return the translation parameters of the model
-		inline const TVec3d& getTranslationParameters( void ) const { return _translation; }
-
-		// Get the number of city objects 
-		inline unsigned int size( void ) const
-		{ 
-			unsigned int count = 0;
-			CityObjectsMap::const_iterator it = _cityObjectsMap.begin();
-			for ( ; it != _cityObjectsMap.end(); ++it ) count += it->second.size();
-			return count; 
-		}
-
-		inline const CityObjectsMap& getCityObjectsMap( void ) const { return _cityObjectsMap; }
-
-		inline const CityObjects* getCityObjectsByType( CityObjectsType type ) const
-		{ 
-			CityObjectsMap::const_iterator it = _cityObjectsMap.find( type );
-			return ( it != _cityObjectsMap.end() ) ? &it->second : 0;
-		}
-
-		// Return the roots elements of the model. You can then navigate the hierarchy using object->getChildren().
-		inline const CityObjects& getCityObjectsRoots( void ) const { return _roots; }
-
-		inline const std::string& getSRSName( void ) const { return _srsName; }
-
-	protected:
-		void addCityObject( CityObject* o );
-
-		inline void addCityObjectAsRoot( CityObject* o ) { if ( o ) _roots.push_back( o ); }
-
-		void finish( const ParserParams& );
-
-	protected:
-		Envelope _envelope;
-
-		CityObjects _roots;
-
-		CityObjectsMap _cityObjectsMap;
-
-		AppearanceManager _appearanceManager;
-		
-		std::string _srsName;
-		
-		TVec3d _translation;
-	};
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	std::ostream& operator<<( std::ostream&, const citygml::Envelope& );
-	std::ostream& operator<<( std::ostream&, const citygml::Object& );
-	std::ostream& operator<<( std::ostream&, const citygml::Geometry& );
-	std::ostream& operator<<( std::ostream&, const citygml::CityObject& );
-	std::ostream& operator<<( std::ostream&, const citygml::CityModel & );
-}
-
-#endif // __CITYGML_H__
diff --git a/include/vecs.h b/include/vecs.h
deleted file mode 100644
index 720a611..0000000
--- a/include/vecs.h
+++ /dev/null
@@ -1,331 +0,0 @@
-#ifndef _VECS_H_
-#define _VECS_H_
-
-#include <sstream>
-#include <iostream>
-#include <math.h>
-#include <string.h>
-
-// 2D vector class.
-
-template< class T > class TVec2
-{
-public:
-	union
-	{
-		T xy[2];
-		struct { T x, y; };
-	};
-
-public:
-	TVec2( const T x = (T)0, const T y = (T)0 );	
-	TVec2( const T vec[] );
-
-	TVec2 operator+( const TVec2<T>& v ) const;
-	TVec2 operator-( const TVec2<T>& v ) const;
-	TVec2 operator-() const;
-	TVec2 operator*( const T& v ) const;
-	TVec2 operator*( const TVec2<T>& v ) const;
-	TVec2 operator/( const T& v ) const;
-	TVec2 operator/( const TVec2<T>& v ) const;
-
-	bool operator==( const TVec2<T>& v ) const;
-	bool operator!=( const TVec2<T>& v ) const;
-
-	inline operator T*() { return xy; }
-	inline operator const T*() const { return xy; }
-};
-
-template< class T >	inline TVec2<T>::TVec2( const T x, const T y )
-{
-	this->x = x;
-	this->y = y;
-}
-
-template< class T >	inline TVec2<T>::TVec2( const T vec[] )
-{
-	memcpy( xy, vec, 2 * sizeof(T) ); 
-}
-
-template< class T >	inline TVec2<T> TVec2<T>::operator+( const TVec2<T>& v ) const
-{
-	return TVec2<T>( x + v.x, y + v.y );
-}
-
-template< class T >	inline TVec2<T> TVec2<T>::operator-( const TVec2<T>& v ) const
-{
-	return TVec2<T>( x - v.x, y - v.y );
-}	
-
-template< class T >	inline TVec2<T> TVec2<T>::operator-() const
-{
-	return TVec2<T>( -x, -y );
-}	
-
-template< class T >	inline TVec2<T> TVec2<T>::operator*( const T& v ) const
-{
-	return TVec2<T>( x * v, y * v );
-}	
-
-template< class T >	inline TVec2<T> TVec2<T>::operator*( const TVec2<T>& v ) const
-{
-	return TVec2<T>( x * v.x, y * v.y );
-}
-
-template< class T >	inline TVec2<T> TVec2<T>::operator/( const T& v ) const
-{
-	return TVec2<T>( x / v, y / v );
-}	
-
-template< class T >	inline TVec2<T> TVec2<T>::operator/( const TVec2<T>& v ) const
-{
-	return TVec2<T>( x / v.x, y / v.y );
-}	
-
-template< class T >	inline bool TVec2<T>::operator==( const TVec2<T>& v ) const
-{
-	return x == v.x && y == v.y; 
-}	
-
-template< class T >	inline bool TVec2<T>::operator!=( const TVec2<T>& v ) const
-{
-	return x != v.x || y != v.y;
-}
-
-template< class T >	inline TVec2<T> operator*( const T& val, const TVec2<T>& vec )
-{
-	return TVec2<T>( vec.x * val, vec.y * val );
-}	
-
-template<class T> inline std::ostream& operator<<(std::ostream & os, TVec2<T> const & v)
-{
-	return os << std::fixed << v.x << " " << std::fixed << v.y;
-}
-
-template<class T> inline std::istream& operator>>(std::istream & is, TVec2<T> & 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<T>& vec ) const;
-	TVec3 cross( const TVec3<T>& vec ) const;
-
-	TVec3  normal() const;
-	TVec3& normalEq();
-	TVec3& normalEq( const T length );
-
-	TVec3 operator+( const TVec3<T>& rhs ) const;
-	TVec3 operator+( const T& _v ) const;
-	TVec3 operator-( const TVec3<T>& rhs ) const;
-	TVec3 operator-( const T& _v ) const;
-	TVec3 operator-() const;
-	TVec3 operator*( const T& rhs ) const;
-	TVec3 operator*( const TVec3<T>& rhs ) const;
-	TVec3 operator/( const T& rhs ) const;
-	TVec3 operator/( const TVec3<T>& rhs ) const;
-
-	inline bool operator==( const TVec3<T>& rhs ) const;
-	inline bool operator!=( const TVec3<T>& rhs ) const;
-
-	inline operator T*() { return xyz; }
-	inline operator const T*() const { return xyz; }
-};
-
-template< class T > inline TVec3<T>::TVec3( const T x, const T y, const T z )
-{
-	this->x = x;
-	this->y = y;
-	this->z = z;
-}
-
-template< class T >	inline TVec3<T>::TVec3( const T vec[] )
-{
-	memcpy( xyz, vec, 3 * sizeof(T) ); 
-}
-
-template< class T > inline T TVec3<T>::length() const
-{	
-	return (T)sqrt( x*x + y*y + z*z );
-}
-
-template< class T > inline T TVec3<T>::sqrLength() const
-{
-	return x*x + y*y + z*z;
-}
-
-template< class T > inline T TVec3<T>::dot( const TVec3<T>& vec ) const
-{
-	return x*vec.x + y*vec.y + z*vec.z;
-}
-
-template< class T > inline TVec3<T> TVec3<T>::cross( const TVec3<T>& vec ) const
-{
-	return TVec3<T>( y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x );
-}	
-
-template< class T > inline TVec3<T> TVec3<T>::normal() const
-{
-	const T len = length();
-	const T tmp = ( len != (T)0 ) ? ( (T)1 / len ) : (T)0;
-	return TVec3<T>( x * tmp, y * tmp, z * tmp );
-}
-
-template< class T > inline TVec3<T>& TVec3<T>::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<T>& TVec3<T>::normalEq( const T length ) 
-{
-	const T len = TVec3<T>::length();
-	const T tmp = ( len != (T)0 ) ? length / len : (T)0;
-	x *= tmp;
-	y *= tmp;
-	z *= tmp;
-	return *this;
-}
-
-template< class T > inline TVec3<T> TVec3<T>::operator+( const TVec3<T>& rhs ) const
-{
-	return TVec3<T>( x + rhs.x, y + rhs.y, z + rhs.z );
-}
-
-template< class T >	inline TVec3<T> TVec3<T>::operator+( const T& _v ) const
-{
-	return TVec3<T>( x + _v, y + _v, z + _v );
-}
-
-template< class T > inline TVec3<T> TVec3<T>::operator-( const TVec3<T>& rhs ) const
-{
-	return TVec3<T>( x - rhs.x, y - rhs.y, z - rhs.z );
-}
-
-template< class T > inline TVec3<T> TVec3<T>::operator-( const T& _v ) const
-{
-	return TVec3<T>( x - _v, y - _v, z - _v );
-}
-
-template< class T >	inline TVec3<T> TVec3<T>::operator-() const
-{
-	return TVec3<T>( -x, -y, -z );
-}
-
-template< class T > inline TVec3<T> TVec3<T>::operator*( const T& rhs ) const
-{
-	return TVec3<T>( x * rhs, y * rhs, z * rhs );
-}	
-
-template< class T >	inline TVec3<T> TVec3<T>::operator*( const TVec3<T>& rhs ) const
-{
-	return TVec3<T>( x * rhs.x, y * rhs.y, z * rhs.z );
-}
-
-template< class T > inline TVec3<T> TVec3<T>::operator/( const T& rhs ) const
-{
-	return TVec3<T>( x / rhs, y / rhs, z / rhs );
-}
-
-template< class T > inline TVec3<T> TVec3<T>::operator/( const TVec3<T>& rhs ) const
-{
-	return TVec3<T>( x / rhs.x, y / rhs.y, z / rhs.z );
-}
-
-template< class T > inline bool TVec3<T>::operator==( const TVec3<T>& rhs ) const
-{
-	return x == rhs.x && y == rhs.y && z == rhs.z;
-}
-
-template< class T > inline bool TVec3<T>::operator!=( const TVec3<T>& rhs ) const
-{
-	return x != rhs.x || y != rhs.y || z != rhs.z;
-}
-
-template< class T >	inline TVec3<T> operator*( const T& val, const TVec3<T>& vec )
-{
-	return TVec3<T>( vec.x * val, vec.y * val, vec.z * val );
-}
-
-template<class T> inline std::ostream& operator<<(std::ostream & os, TVec3<T> const & v)
-{
-	return os << std::fixed << v.x << " " << std::fixed << v.y << " " << std::fixed << v.z;
-}
-
-template<class T> inline std::istream& operator>>(std::istream & is, TVec3<T> & v)
-{
-	return is >> v.x >> v.y >> v.z;
-}
-
-typedef TVec3< float >			TVec3f;
-typedef TVec3< double >			TVec3d;
-
-
-// 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<class T> inline std::ostream& operator<<( std::ostream & os, TVec4<T> const & v )
-{
-	return os << std::fixed << v.x << " " << std::fixed << v.y << " " << std::fixed << v.z << " " << std::fixed << v.w;
-}
-
-template<class T> inline std::istream& operator>>( std::istream & is, TVec4<T> & v )
-{
-	return is >> v.x >> v.y >> v.z >>  v.w;
-}
-
-typedef TVec4< float >			TVec4f;
-typedef TVec4< double >			TVec4d;
-
-#endif
diff --git a/libcitygml_classdiagram.graphml b/libcitygml_classdiagram.graphml
new file mode 100644
index 0000000..7705d12
--- /dev/null
+++ b/libcitygml_classdiagram.graphml
@@ -0,0 +1,722 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:y="http://www.yworks.com/xml/graphml" xmlns:yed="http://www.yworks.com/xml/yed/3" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd">
+  <!--Created by yEd 3.13-->
+  <key attr.name="Description" attr.type="string" for="graph" id="d0"/>
+  <key for="port" id="d1" yfiles.type="portgraphics"/>
+  <key for="port" id="d2" yfiles.type="portgeometry"/>
+  <key for="port" id="d3" yfiles.type="portuserdata"/>
+  <key attr.name="url" attr.type="string" for="node" id="d4"/>
+  <key attr.name="description" attr.type="string" for="node" id="d5"/>
+  <key for="node" id="d6" yfiles.type="nodegraphics"/>
+  <key for="graphml" id="d7" yfiles.type="resources"/>
+  <key attr.name="url" attr.type="string" for="edge" id="d8"/>
+  <key attr.name="description" attr.type="string" for="edge" id="d9"/>
+  <key for="edge" id="d10" yfiles.type="edgegraphics"/>
+  <graph edgedefault="directed" id="G">
+    <data key="d0"/>
+    <node id="n0">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="666.0" y="622.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="91.22314453125" x="4.388427734375" y="3.0">Appearance<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n1">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="163.0" x="1012.5" y="512.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="139.611328125" x="11.6943359375" y="3.0">AppearanceTarget<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n2">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="236.0" x="976.0" y="622.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="211.8984375" x="12.05078125" y="3.0">AppearanceTargetDefinition<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n3">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="154.66666666666697" x="862.6666666666665" y="103.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="109.02197265625" x="22.822347005208485" y="3.0">CityGMLModel<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n4">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="861.3333333333335" y="265.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="80.2353515625" x="37.88232421875" y="3.0">CityObject<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n5">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="153.5" x="590.8333333333335" y="181.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="70.93603515625" x="41.281982421875" y="3.0">Envelope<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n6">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="1165.3333333333335" y="427.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="75.880859375" x="40.0595703125" y="3.0">Geometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n7">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="190.0" x="520.0" y="805.25"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="169.19775390625" x="10.401123046875" y="3.0">GeoreferencedTexture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n8">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="1165.3333333333335" y="265.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="130.85791015625" x="12.571044921875" y="3.0">ImplicitGeometry<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n9">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="153.5" x="590.8333333333335" y="427.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="83.02197265625" x="35.239013671875" y="3.0">LinearRing<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n10">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="707.0" y="736.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="64.8359375" x="17.58203125" y="3.0">Material<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n11">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="236.0" x="1111.0" y="736.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="185.51123046875" x="25.244384765625" y="3.0">MaterialTargetDefinition<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n12">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="236.0" x="837.0" y="736.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="181.4423828125" x="27.27880859375" y="3.0">TextureTargetDefinition<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n13">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="156.0" x="861.3333333333335" y="427.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="62.880859375" x="46.5595703125" y="3.0">Polygon<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n14">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="100.0" x="565.0" y="736.5"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="60.76708984375" x="19.616455078125" y="3.0">Texture<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n15">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="163.0" x="873.5" y="832.25"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="149.13916015625" x="6.930419921875" y="3.0">TextureCoordinates<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <node id="n16">
+      <data key="d4"/>
+      <data key="d5"/>
+      <data key="d6">
+        <y:UMLClassNode>
+          <y:Geometry height="28.0" width="151.0" x="338.0" y="181.0"/>
+          <y:Fill color="#FFCC00" transparent="false"/>
+          <y:BorderStyle color="#000000" type="line" width="1.0"/>
+          <y:NodeLabel alignment="center" autoSizePolicy="content" fontFamily="Dialog" fontSize="13" fontStyle="bold" hasBackgroundColor="false" hasLineColor="false" height="19.1328125" modelName="custom" textColor="#000000" visible="true" width="126.763671875" x="12.1181640625" y="3.0">TransformMatrix<y:LabelModel>
+              <y:SmartNodeLabelModel distance="4.0"/>
+            </y:LabelModel>
+            <y:ModelParameter>
+              <y:SmartNodeLabelModelParameter labelRatioX="0.0" labelRatioY="0.0" nodeRatioX="0.0" nodeRatioY="-0.03703090122767855" offsetX="0.0" offsetY="0.0" upX="0.0" upY="-1.0"/>
+            </y:ModelParameter>
+          </y:NodeLabel>
+          <y:UML clipContent="true" constraint="" omitDetails="false" stereotype="" use3DEffect="true">
+            <y:AttributeLabel/>
+            <y:MethodLabel/>
+          </y:UML>
+        </y:UMLClassNode>
+      </data>
+    </node>
+    <edge id="e0" source="n14" target="n0">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e1" source="n10" target="n0">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e2" source="n7" target="n14">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e3" source="n12" target="n2">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e4" source="n11" target="n2">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e5" source="n2" target="n0">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="-35.402099609375" y="2.0">1..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotation [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="-199.888427734375" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOn [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e6" source="n12" target="n15">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="2.0" y="39.6771240234375">1..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotation [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e7" source="n2" target="n1">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="plain"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="2.0" y="-71.88330078125">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRi [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="2.0" y="-28.10205078125">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRi [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e8" source="n13" target="n1">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e9" source="n6" target="n1">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="none" target="white_delta"/>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e10" source="n6" target="n13">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="-137.90824381510402" y="2.0">0..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotat [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e11" source="n6" target="n6">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="61.666666666666515" sy="1.0" tx="77.98828125" ty="0.0">
+            <y:Point x="1305.0" y="382.0"/>
+            <y:Point x="1399.0" y="382.0"/>
+            <y:Point x="1399.0" y="441.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="2.0" y="-28.064453125">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRigh [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="26.458333333333485" y="16.029296875">0..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" an [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e12" source="n8" target="n6">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="-7.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="1.999959309895985" y="10.161376953125">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" ang [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="1.999959309895985" y="105.942626953125">0..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e13" source="n13" target="n9">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="-106.88621012369777" y="2.0">
+            <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="-106.88621012369777" y="2.0">1..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotat [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e14" source="n5" target="n16">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="-91.69366455078125" y="2.0">
+            <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e15" source="n4" target="n5">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="667.5833333333335" y="279.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="plain"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="-191.76121012369777" y="-59.875">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRota [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="-21.770975748697765" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotation [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e16" source="n3" target="n5">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0">
+            <y:Point x="667.5833333333335" y="117.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="dashed" width="1.0"/>
+          <y:Arrows source="none" target="plain"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="-193.10117594401027" y="35.90625">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRot [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="-21.777608235677235" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotation [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e17" source="n3" target="n4">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="1.9581542466403334" y="10.16357421875">
+            <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="1.5639927240067664" y="105.94482421875">1..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="1.9581542466403334" y="10.16357421875">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" ang [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e18" source="n4" target="n8">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="10.158223470052235" y="2.0">
+            <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="112.64455159505223" y="2.0">0..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotati [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="10.158223470052235" y="2.0">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationO [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e19" source="n4" target="n6">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="0.0" ty="0.0"/>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="18.15875394844727" y="13.80827251233552">
+            <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="thead" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="208.1049586166571" y="90.92927631578948">0..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="18.15875394844727" y="17.87679893092104">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" a [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+    <edge id="e20" source="n4" target="n4">
+      <data key="d8"/>
+      <data key="d9"/>
+      <data key="d10">
+        <y:PolyLineEdge>
+          <y:Path sx="0.0" sy="0.0" tx="-43.333333333333485" ty="-1.0">
+            <y:Point x="939.3333333333335" y="360.0"/>
+            <y:Point x="896.0" y="360.0"/>
+          </y:Path>
+          <y:LineStyle color="#000000" type="line" width="1.0"/>
+          <y:Arrows source="white_diamond" target="none"/>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" hasText="false" height="4.0" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="4.0" x="2.000020345052235" y="10.16357421875">
+            <y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angleRotationOnRightSide="co" distance="-1.0" frozen="true" placement="anywhere" side="anywhere" sideReference="relative_to_edge_flow"/>
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="ttail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="25.263671875" x="-41.33331298828125" y="10.16357421875">0..*<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute"  [...]
+          </y:EdgeLabel>
+          <y:EdgeLabel alignment="center" configuration="AutoFlippingLabel" distance="2.0" fontFamily="Dialog" fontSize="12" fontStyle="plain" hasBackgroundColor="false" hasLineColor="false" height="17.96875" modelName="six_pos" modelPosition="stail" preferredPlacement="anywhere" ratio="0.5" textColor="#000000" visible="true" width="11.634765625" x="2.000020345052235" y="10.16357421875">1<y:PreferredPlacementDescriptor angle="0.0" angleOffsetOnRightSide="0" angleReference="absolute" angl [...]
+          </y:EdgeLabel>
+          <y:BendStyle smoothed="false"/>
+        </y:PolyLineEdge>
+      </data>
+    </edge>
+  </graph>
+  <data key="d7">
+    <y:Resources/>
+  </data>
+</graphml>
diff --git a/osgplugin/CMakeLists.txt b/osgplugin/CMakeLists.txt
new file mode 100644
index 0000000..f63200f
--- /dev/null
+++ b/osgplugin/CMakeLists.txt
@@ -0,0 +1,45 @@
+set(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-<version> 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}
+)
diff --git a/osgplugin/CitygmlOsgViewer.cpp b/osgplugin/CitygmlOsgViewer.cpp
new file mode 100644
index 0000000..d3c72cb
--- /dev/null
+++ b/osgplugin/CitygmlOsgViewer.cpp
@@ -0,0 +1,46 @@
+#include <osgViewer/Viewer>
+#include <osgDB/Registry>
+#include <osgDB/ReadFile>
+#include <osg/Node>
+
+#include <osgGA/SphericalManipulator>
+#include <osgGA/StateSetManipulator>
+#include <osgViewer/ViewerEventHandlers>
+
+#include <iostream>
+
+int main(int argc, char *argv[])
+{
+    osg::setNotifyLevel(osg::INFO);
+
+    std::cout << "Using plugin directory: " << PLUGIN_BIN_DIR << std::endl;
+    osgDB::Registry::instance()->getLibraryFilePathList().push_front(PLUGIN_BIN_DIR);
+
+    if (argc < 2) {
+        std::cerr << "No citygml file specified..." << std::endl;
+        return 1;
+    }
+
+    osg::ref_ptr<osgDB::Options> options = new osgDB::Options("usemaxlodonly");
+    osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(argv[1], options);
+
+    if (node == nullptr) {
+        std::cerr << "Failed to load file " << argv[1] << std::endl;
+        return 1;
+    }
+
+    osg::ref_ptr<osgGA::SphericalManipulator> 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.run();
+
+    return 0;
+}
diff --git a/test/osgplugin/README b/osgplugin/README
similarity index 100%
rename from test/osgplugin/README
rename to osgplugin/README
diff --git a/osgplugin/ReaderWriterCityGML.cpp b/osgplugin/ReaderWriterCityGML.cpp
new file mode 100644
index 0000000..c8143a6
--- /dev/null
+++ b/osgplugin/ReaderWriterCityGML.cpp
@@ -0,0 +1,506 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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 <osg/Array>
+#include <osg/Node>
+#include <osg/MatrixTransform>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/StateSet>
+#include <osg/BlendFunc>
+#include <osg/BlendColor>
+#include <osg/Material>
+#include <osg/Texture2D>
+#include <osg/TexGen>
+#include <osg/TexMat>
+#include <osg/Depth>
+#include <osg/LightModel>
+#include <osg/ValueObject>
+
+#include <osgText/Font>
+#include <osgText/Text>
+
+#include <osgDB/Registry>
+#include <osgDB/ReadFile>
+#include <osgDB/WriteFile>
+#include <osgDB/FileUtils>
+#include <osgDB/FileNameUtils>
+
+#include <osgUtil/SmoothingVisitor>
+
+#include <osg/Notify>
+
+#include <citygml/citygml.h>
+#include <citygml/envelope.h>
+#include <citygml/citymodel.h>
+#include <citygml/cityobject.h>
+#include <citygml/geometry.h>
+#include <citygml/polygon.h>
+#include <citygml/material.h>
+#include <citygml/texture.h>
+#include <citygml/citygmllogger.h>
+
+#include <algorithm>
+#include <cctype>
+
+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)
+        , _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;
+
+        }
+    }
+
+public:
+    citygml::ParserParams _params;
+    bool _printNames;
+    bool _useMaxLODOnly;
+    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" );
+
+        m_logger = std::make_shared<CityGMLOSGPluginLogger>();
+    }
+
+    virtual const char* className( void ) const { return "CityGML Reader"; }
+
+    virtual ReadResult readNode( const std::string&, const osgDB::ReaderWriter::Options* ) const;
+    virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const;
+
+private:
+
+    std::shared_ptr<citygml::CityGMLLogger> m_logger;
+    static unsigned int getHighestLodForObject(const citygml::CityObject& object);
+
+    ReadResult readCity(std::shared_ptr<const citygml::CityModel>, CityGMLSettings& ) const;
+    bool createCityObject(const citygml::CityObject&, CityGMLSettings&, osg::Group*, const TVec3d &offset, 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<const citygml::CityModel> 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<const citygml::CityModel> 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<const citygml::CityModel> 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;
+
+    const citygml::Envelope& env = city->getEnvelope();
+    TVec3d offset;
+    if(env.validBounds()){
+        offset = env.getLowerBound();
+    }else{
+        const citygml::Envelope& env = roots.at(0)->getEnvelope();
+        if(env.validBounds()){
+            offset = env.getLowerBound();
+        }
+    }
+
+    osg::notify(osg::NOTICE) << "Applying model offset of " << offset.x  << ", " << offset.y << ", " << offset.z << std::endl;
+
+    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(osg::Vec3d(offset.x,offset.y,offset.z)));
+
+    return root;
+}
+
+void setTexture(osg::ref_ptr<osg::StateSet> stateset, osg::Geometry* geom, const citygml::Polygon& polygon, CityGMLSettings& settings) {
+    const citygml::Texture* citygmlTex = polygon.getTextureFor(settings._theme);
+
+    if ( !citygmlTex )
+    {
+        return;
+    }
+    const std::vector<TVec2f>& 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<osg::Vec2Array> 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<osg::StateSet> stateset, const citygml::Polygon& polygon, CityGMLSettings& settings) {
+
+    const citygml::Material* 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, 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 TVec3d& 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<TVec3d>& vert = p.getVertices();
+        vertices->reserve( vert.size() );
+        for ( unsigned int k = 0; k < vert.size(); k++ )
+        {
+            osg::Vec3d pt( vert[k].x - offset.x, vert[k].y - offset.y, vert[k].z - offset.z);
+            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<osg::StateSet> stateset = geom->getOrCreateStateSet();
+
+        setMaterial(stateset, p, settings);
+        setTexture(stateset, geom, p, settings);
+
+
+        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 TVec3d& offset, unsigned int minimumLODToConsider ) const
+{
+    // Skip objects without geometry
+    if ( !parent ) return false;
+
+    osg::ref_ptr<osg::Geode> 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<osg::Vec4Array> 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<osgText::Text> 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<osg::BlendFunc> 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<osg::BlendColor> blendColor = new osg::BlendColor(osg::Vec4( 1., 1., 1., 0.4 ));
+        geodeSS->setAttributeAndModes( blendColor.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON );
+
+        osg::ref_ptr<osg::Depth> 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;
+}
diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt
new file mode 100644
index 0000000..1ca7c03
--- /dev/null
+++ b/sources/CMakeLists.txt
@@ -0,0 +1,142 @@
+SET( 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/parser/nodetypes.cpp
+  src/parser/citygmldocumentparser.cpp
+  src/parser/citygmlelementparser.cpp
+  src/parser/elementparser.cpp
+  src/parser/delayedchoiceelementparser.cpp
+  src/parser/attributes.cpp
+  src/parser/parserxercesc.cpp
+  src/parser/geocoordinatetransformer.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/linearringelementparser.cpp
+  src/parser/implicitgeometryelementparser.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
+)
+
+SET(HEADERS
+  ${PUBLIC_HEADER}
+
+  include/citygml/citygml_api.h.in
+
+  include/parser/nodetypes.h
+  include/parser/citygmldocumentparser.h
+  include/parser/citygmlelementparser.h
+  include/parser/elementparser.h
+  include/parser/delayedchoiceelementparser.h
+  include/parser/attributes.h
+  include/parser/documentlocation.h
+  include/parser/geocoordinatetransformer.h
+  include/parser/parserutils.hpp
+  include/citygml/tesselator.h
+  include/citygml/utils.h
+  include/citygml/appearancemanager.h
+  include/citygml/polygonmanager.h
+  include/citygml/geometrymanager.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/linearringelementparser.h
+  include/parser/implicitgeometryelementparser.h
+)
+
+ADD_LIBRARY( ${target} ${LIBCITYGML_USER_DEFINED_DYNAMIC_OR_STATIC} ${SOURCES} ${HEADERS} )
+
+TARGET_LINK_LIBRARIES( ${target} ${XERCESC_LIBRARIES} ${OPENGL_LIBRARIES} ${GDAL_LIBRARY} )
+
+INSTALL(
+    TARGETS ${target}
+    RUNTIME DESTINATION bin
+    LIBRARY DESTINATION lib
+    ARCHIVE DESTINATION lib
+)
+# FIXME: Do not run for OS X framework
+INSTALL(
+    FILES        ${PUBLIC_HEADER}
+    DESTINATION  ${CMAKE_INSTALL_PREFIX}/include/${target}
+)
+
diff --git a/sources/include/citygml/appearance.h b/sources/include/citygml/appearance.h
new file mode 100644
index 0000000..d8b7014
--- /dev/null
+++ b/sources/include/citygml/appearance.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <citygml/citygml_api.h>
+#include <citygml/object.h>
+#include <citygml/appearancetarget.h>
+
+namespace citygml {
+
+    class Material;
+    class Texture;
+    class GeoreferencedTexture;
+
+    class LIBCITYGML_EXPORT Appearance : public Object, public std::enable_shared_from_this<Appearance>
+    {
+    public:
+        std::string getType() const;
+
+        bool getIsFront() const;
+        void setIsFront(bool front);
+
+        virtual std::string toString() const;
+
+        virtual std::shared_ptr<Material> asMaterial();
+        virtual std::shared_ptr<const Material> asMaterial() const;
+
+        virtual std::shared_ptr<Texture> asTexture();
+        virtual std::shared_ptr<const Texture> asTexture() const;
+
+        virtual std::shared_ptr<GeoreferencedTexture> asGeoreferencedTexture();
+        virtual std::shared_ptr<const GeoreferencedTexture> asGeoreferencedTexture() const;
+
+        bool inTheme(const std::string& themeName) const;
+        void addToTheme(std::string themeName);
+        const std::vector<std::string>& getThemes() const;
+
+        virtual ~Appearance() {}
+
+    protected:
+        Appearance( const std::string& id, const std::string& typeString );
+        std::string m_typeString;
+        std::vector<std::string> m_themes;
+        bool m_isFront;
+    };
+
+}
diff --git a/sources/include/citygml/appearancemanager.h b/sources/include/citygml/appearancemanager.h
new file mode 100644
index 0000000..2820c7e
--- /dev/null
+++ b/sources/include/citygml/appearancemanager.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_set>
+#include <unordered_map>
+
+#include <citygml/object.h>
+#include <citygml/vecs.hpp>
+
+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<CityGMLLogger> logger );
+
+        ~AppearanceManager();
+
+        /**
+         * @brief returns the appearance with the given id
+         * @return the Appearance object or nullptr if not found
+         */
+        std::shared_ptr<Appearance> 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<std::string> getAllThemes();
+
+        void addAppearanceTarget(AppearanceTarget* target);
+
+        void addAppearance(std::shared_ptr<Appearance> appearance);
+        void addTextureTargetDefinition(std::shared_ptr<TextureTargetDefinition> targetDef);
+        void addMaterialTargetDefinition(std::shared_ptr<MaterialTargetDefinition> 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<std::string, std::shared_ptr<Appearance>> m_appearancesMap;
+        std::vector<std::shared_ptr<MaterialTargetDefinition>> m_materialTargetDefinitions;
+        std::vector<std::shared_ptr<TextureTargetDefinition>> m_texTargetDefinitions;
+        std::unordered_set<std::string> m_themes;
+        std::unordered_map<std::string, AppearanceTarget*> m_appearanceTargetsMap;
+        std::shared_ptr<CityGMLLogger> m_logger;
+
+        void addThemesFrom(std::shared_ptr<Appearance> surfaceData);
+    };
+
+}
diff --git a/sources/include/citygml/appearancetarget.h b/sources/include/citygml/appearancetarget.h
new file mode 100644
index 0000000..b5db0b7
--- /dev/null
+++ b/sources/include/citygml/appearancetarget.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_map>
+
+#include <citygml/object.h>
+#include <citygml/appearancetargetdefinition.h>
+
+
+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<AppearanceTargetDefinition<Appearance>> targetDef);
+        void addTargetDefinition(std::shared_ptr<TextureTargetDefinition> targetDef);
+        void addTargetDefinition(std::shared_ptr<MaterialTargetDefinition> targetDef);
+
+        void addTargetDefinitionsOf(const AppearanceTarget& other);
+
+        MaterialTargetDefinition* getMaterialTargetDefinitionForTheme(const std::string& theme, bool front);
+        const MaterialTargetDefinition* getMaterialTargetDefinitionForTheme(const std::string& theme, bool front) const;
+
+        TextureTargetDefinition* getTextureTargetDefinitionForTheme(const std::string& theme, bool front);
+        const TextureTargetDefinition* getTextureTargetDefinitionForTheme(const std::string& theme, bool front) const;
+
+        std::vector<TextureTargetDefinition*> getTextureTargetDefinitions();
+
+        std::vector<std::string> getAllTextureThemes(bool front) const;
+
+    protected:
+        AppearanceTarget(const std::string& id);
+
+
+
+    private:
+        std::unordered_map<std::string, std::shared_ptr<MaterialTargetDefinition>> m_themeMatMapFront;
+        std::unordered_map<std::string, std::shared_ptr<MaterialTargetDefinition>> m_themeMatMapBack;
+
+        std::unordered_map<std::string, std::shared_ptr<TextureTargetDefinition>> m_themeTexMapFront;
+        std::unordered_map<std::string, std::shared_ptr<TextureTargetDefinition>> m_themeTexMapBack;
+
+    };
+}
diff --git a/sources/include/citygml/appearancetargetdefinition.h b/sources/include/citygml/appearancetargetdefinition.h
new file mode 100644
index 0000000..02b699d
--- /dev/null
+++ b/sources/include/citygml/appearancetargetdefinition.h
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include <citygml/object.h>
+
+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 T>
+    class AppearanceTargetDefinition : public Object {
+    public:
+        AppearanceTargetDefinition(const std::string& targetID, std::shared_ptr<T> 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<const T> getAppearance() const { return m_appearance; }
+        std::shared_ptr<T> getAppearance() { return m_appearance; }
+
+        virtual ~AppearanceTargetDefinition() {}
+
+    protected:
+        std::string m_targetID;
+        std::shared_ptr<T> m_appearance;
+    };
+
+}
diff --git a/sources/include/citygml/citygml.h b/sources/include/citygml/citygml.h
new file mode 100644
index 0000000..7f38105
--- /dev/null
+++ b/sources/include/citygml/citygml.h
@@ -0,0 +1,89 @@
+/* -*-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 <string>
+#include <vector>
+#include <sstream>
+#include <map>
+#include <memory>
+#include <functional>
+#include <unordered_set>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sstream>
+
+#include <citygml/citygml_api.h>
+#include <citygml/vecs.hpp>
+#include <citygml/cityobject.h>
+#include <citygml/envelope.h>
+
+
+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<const CityModel> load( std::istream& stream, const ParserParams& params, std::shared_ptr<CityGMLLogger> logger = nullptr);
+
+    LIBCITYGML_EXPORT std::shared_ptr<const CityModel> load( const std::string& fileName, const ParserParams& params, std::shared_ptr<CityGMLLogger> logger = nullptr);
+
+}
diff --git a/sources/include/citygml/citygml_api.h.in b/sources/include/citygml/citygml_api.h.in
new file mode 100644
index 0000000..eb84e8f
--- /dev/null
+++ b/sources/include/citygml/citygml_api.h.in
@@ -0,0 +1,20 @@
+#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
diff --git a/sources/include/citygml/citygmlfactory.h b/sources/include/citygml/citygmlfactory.h
new file mode 100644
index 0000000..06bdf95
--- /dev/null
+++ b/sources/include/citygml/citygmlfactory.h
@@ -0,0 +1,73 @@
+#pragma once
+
+#include "citygml/geometry.h"
+#include "citygml/cityobject.h"
+
+#include <memory>
+
+namespace citygml {
+
+    class AppearanceManager;
+    class PolygonManager;
+    class GeometryManager;
+    class CityGMLLogger;
+
+    class CityModel;
+    class AppearanceTarget;
+    class CityObject;
+    class Geometry;
+    class ImplicitGeometry;
+    class Polygon;
+
+    class Appearance;
+    class Texture;
+    class GeoreferencedTexture;
+    class Material;
+
+    class MaterialTargetDefinition;
+    class TextureTargetDefinition;
+
+    class CityGMLFactory {
+    public:
+        CityGMLFactory(std::shared_ptr<CityGMLLogger> logger);
+
+        CityModel* createCityModel(const std::string& id);
+        CityObject* createCityObject(const std::string& id, CityObject::CityObjectsType type);
+        Geometry* createGeometry(const std::string& id, Geometry::GeometryType type = Geometry::GeometryType::GT_Unknown, unsigned int lod = 0);
+
+        std::shared_ptr<Polygon> createPolygon(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<Geometry> shareGeometry(Geometry* geom);
+        void requestSharedGeometryWithID(ImplicitGeometry* implicitGeom, const std::string& id);
+
+        std::shared_ptr<Texture> createTexture(const std::string& id);
+        std::shared_ptr<Material> createMaterial(const std::string& id);
+        std::shared_ptr<GeoreferencedTexture> createGeoReferencedTexture(const std::string& id);
+
+        std::shared_ptr<MaterialTargetDefinition> createMaterialTargetDefinition(const std::string& targetID, std::shared_ptr<Material> appearance, const std::string& id);
+        std::shared_ptr<TextureTargetDefinition> createTextureTargetDefinition(const std::string& targetID, std::shared_ptr<Texture> appearance, const std::string& id);
+
+        std::shared_ptr<Appearance> getAppearanceWithID(const std::string& id);
+        std::vector<std::string> getAllThemes();
+
+        void closeFactory();
+
+        ~CityGMLFactory();
+    protected:
+        void appearanceTargetCreated(AppearanceTarget* obj);
+
+        std::shared_ptr<CityGMLLogger> m_logger;
+        std::unique_ptr<AppearanceManager> m_appearanceManager;
+        std::unique_ptr<PolygonManager> m_polygonManager;
+        std::unique_ptr<GeometryManager> m_geometryManager;
+    };
+
+}
diff --git a/sources/include/citygml/citygmllogger.h b/sources/include/citygml/citygmllogger.h
new file mode 100644
index 0000000..fcbf5c3
--- /dev/null
+++ b/sources/include/citygml/citygmllogger.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <citygml/citygml_api.h>
+
+#include <sstream>
+
+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)
+}
diff --git a/sources/include/citygml/citymodel.h b/sources/include/citygml/citymodel.h
new file mode 100644
index 0000000..16f20ec
--- /dev/null
+++ b/sources/include/citygml/citymodel.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <map>
+
+#include <citygml/citygml_api.h>
+#include <citygml/cityobject.h>
+#include <citygml/featureobject.h>
+
+namespace citygml {
+
+    class AppearanceManager;
+    class AppearanceTarget;
+    class CityGMLLogger;
+    class CityObject;
+    class CityGMLFactory;
+
+    typedef std::vector<std::unique_ptr<CityObject>> CityObjects;
+    typedef std::vector<const CityObject*> ConstCityObjects;
+    typedef std::map< CityObject::CityObjectsType, std::vector<const CityObject*> > 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<CityGMLLogger> logger);
+
+        std::vector<std::string> themes() const;
+        void setThemes(std::vector<std::string> 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<std::string> m_themes;
+    };
+
+    std::ostream& operator<<( std::ostream&, const citygml::CityModel & );
+}
diff --git a/sources/include/citygml/cityobject.h b/sources/include/citygml/cityobject.h
new file mode 100644
index 0000000..90bc564
--- /dev/null
+++ b/sources/include/citygml/cityobject.h
@@ -0,0 +1,109 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+#include <citygml/featureobject.h>
+#include <citygml/citygml_api.h>
+
+class Tesselator;
+
+namespace citygml {
+
+    class ParserParams;
+    class Geometry;
+    class ImplicitGeometry;
+    class Composite;
+    class CityGMLLogger;
+    class AppearanceManager;
+
+    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_TINRelief                   = 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_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);
+
+        void finish(Tesselator& tesselator, bool optimize, std::shared_ptr<citygml::CityGMLLogger> logger);
+
+        virtual ~CityObject();
+
+    protected:
+        CityObjectsType m_type;
+
+        std::vector<std::unique_ptr<Geometry>> m_geometries;
+        std::vector<std::unique_ptr<ImplicitGeometry>> m_implicitGeometries;
+        std::vector<std::unique_ptr<CityObject>> m_children;
+    };
+
+    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);
+}
diff --git a/sources/include/citygml/envelope.h b/sources/include/citygml/envelope.h
new file mode 100644
index 0000000..1c09247
--- /dev/null
+++ b/sources/include/citygml/envelope.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <iostream>
+
+#include <citygml/citygml_api.h>
+#include <citygml/vecs.hpp>
+
+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& );
+}
diff --git a/sources/include/citygml/featureobject.h b/sources/include/citygml/featureobject.h
new file mode 100644
index 0000000..1a0ca31
--- /dev/null
+++ b/sources/include/citygml/featureobject.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <memory>
+
+#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<Envelope> m_envelope;
+    };
+
+}
diff --git a/sources/include/citygml/geometry.h b/sources/include/citygml/geometry.h
new file mode 100644
index 0000000..757730b
--- /dev/null
+++ b/sources/include/citygml/geometry.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_set>
+
+#include <citygml/citygml_api.h>
+#include <citygml/appearancetarget.h>
+
+class Tesselator;
+
+namespace citygml {
+
+    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
+        };
+
+        // Get the geometry LOD
+        unsigned int getLOD() const;
+
+        // Get the polygons
+        unsigned int getPolygonsCount() const;
+        Polygon& getPolygon( unsigned int i );
+        const Polygon& getPolygon( 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;
+        //std::string getTypeAsString( void ) const { return getGeometryClassName( _type ); }
+
+        unsigned int lod() const;
+        void setLod(unsigned int lod);
+
+        void addPolygon(std::shared_ptr<Polygon> );
+
+        /**
+         * @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<CityGMLLogger> 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<std::shared_ptr<Geometry>> m_childGeometries;
+
+        std::vector<std::shared_ptr<Polygon>> m_polygons;
+    };
+
+    std::ostream& operator<<( std::ostream& os, const citygml::Geometry& s );
+
+}
diff --git a/sources/include/citygml/geometrymanager.h b/sources/include/citygml/geometrymanager.h
new file mode 100644
index 0000000..297d006
--- /dev/null
+++ b/sources/include/citygml/geometrymanager.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace citygml {
+
+    class ImplicitGeometry;
+    class Geometry;
+    class CityGMLLogger;
+
+    class GeometryManager {
+    public:
+        GeometryManager(std::shared_ptr<CityGMLLogger> logger);
+
+        void addSharedGeometry(std::shared_ptr<Geometry> 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<CityGMLLogger> m_logger;
+        std::vector<GeometryRequest> m_geometryRequests;
+        std::unordered_map<std::string, std::shared_ptr<Geometry>> m_sharedGeometries;
+    };
+
+}
diff --git a/sources/include/citygml/georeferencedtexture.h b/sources/include/citygml/georeferencedtexture.h
new file mode 100644
index 0000000..ea897b9
--- /dev/null
+++ b/sources/include/citygml/georeferencedtexture.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <citygml/citygml_api.h>
+#include <citygml/texture.h>
+
+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<Texture> asTexture();
+        virtual std::shared_ptr<const Texture> asTexture() const;
+
+        virtual std::shared_ptr<GeoreferencedTexture> asGeoreferencedTexture();
+        virtual std::shared_ptr<const GeoreferencedTexture> asGeoreferencedTexture() const;
+
+        // TODO support referencePoint and orientation
+
+    protected:
+        GeoreferencedTexture( const std::string& id );
+        bool m_preferWorldFile;
+    };
+
+}
diff --git a/sources/include/citygml/implictgeometry.h b/sources/include/citygml/implictgeometry.h
new file mode 100644
index 0000000..81ad53f
--- /dev/null
+++ b/sources/include/citygml/implictgeometry.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+#include <citygml/object.h>
+#include <citygml/transformmatrix.h>
+#include <citygml/vecs.hpp>
+
+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<Geometry> 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<std::shared_ptr<Geometry>>   m_geometries;
+        std::string              m_srsName;
+    };
+}
diff --git a/sources/include/citygml/linearring.h b/sources/include/citygml/linearring.h
new file mode 100644
index 0000000..acafdfe
--- /dev/null
+++ b/sources/include/citygml/linearring.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+#include <citygml/citygml_api.h>
+#include <citygml/object.h>
+#include <citygml/vecs.hpp>
+
+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<TVec3d>& getVertices() const;
+        std::vector<TVec3d>& getVertices();
+        void setVertices(std::vector<TVec3d> vertices);
+
+        void addVertex( const TVec3d& v );
+
+        TVec3d computeNormal() const;
+
+        void removeDuplicateVertices(const std::vector<TextureTargetDefinition*>& targets , std::shared_ptr<CityGMLLogger> logger);
+
+        void forgetVertices();
+
+    protected:
+        bool m_exterior;
+
+        std::vector<TVec3d> m_vertices;
+    };
+
+}
diff --git a/sources/include/citygml/material.h b/sources/include/citygml/material.h
new file mode 100644
index 0000000..312745b
--- /dev/null
+++ b/sources/include/citygml/material.h
@@ -0,0 +1,49 @@
+#pragma once
+
+#include <citygml/citygml_api.h>
+#include <citygml/appearance.h>
+#include <citygml/vecs.hpp>
+#include <unordered_set>
+
+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);
+
+        float getShininess() const;
+        void setShininess(float shininess);
+
+        float getTransparency() const;
+        void setTransparency(float transparancy);
+
+        virtual std::shared_ptr<Material> asMaterial() override;
+        virtual std::shared_ptr<const Material> 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;
+    };
+
+}
diff --git a/sources/include/citygml/materialtargetdefinition.h b/sources/include/citygml/materialtargetdefinition.h
new file mode 100644
index 0000000..63eef21
--- /dev/null
+++ b/sources/include/citygml/materialtargetdefinition.h
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <citygml/citygml_api.h>
+#include <citygml/appearancetargetdefinition.h>
+#include <citygml/material.h>
+
+namespace citygml {
+
+    class CityGMLFactory;
+
+    /**
+     * @brief The MaterialTargetDefinition associates a material with a target surface.
+     */
+    class LIBCITYGML_EXPORT MaterialTargetDefinition : public AppearanceTargetDefinition<Material> {
+        friend class CityGMLFactory;
+    protected:
+        MaterialTargetDefinition(const std::string& targetID, std::shared_ptr<Material> appearance, const std::string& id);
+
+    };
+}
diff --git a/sources/include/citygml/object.h b/sources/include/citygml/object.h
new file mode 100644
index 0000000..964fc30
--- /dev/null
+++ b/sources/include/citygml/object.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <string>
+#include <map>
+
+#include <citygml/citygml_api.h>
+
+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& );
+
+}
diff --git a/sources/include/citygml/polygon.h b/sources/include/citygml/polygon.h
new file mode 100644
index 0000000..defa024
--- /dev/null
+++ b/sources/include/citygml/polygon.h
@@ -0,0 +1,121 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_set>
+#include <unordered_map>
+
+#include <citygml/citygml_api.h>
+#include <citygml/appearancetarget.h>
+#include <citygml/vecs.hpp>
+#include <citygml/linearring.h>
+#include <citygml/geometry.h>
+
+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<TVec3d>& getVertices() const;
+        std::vector<TVec3d>& getVertices();
+
+        // Get the indices
+        const std::vector<unsigned int>& 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
+         */
+        const Material* 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
+         */
+        const Material* 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
+         */
+        const Texture* 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
+         */
+        const Texture* 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<TVec2f> 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<CityGMLLogger> logger);
+
+        virtual ~Polygon();
+
+    protected:
+        Polygon( const std::string& id, std::shared_ptr<CityGMLLogger> logger );
+
+        std::shared_ptr<const Texture> 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<CityGMLLogger> logger);
+        void createSimpleIndices(std::shared_ptr<CityGMLLogger> logger);
+        void createIndicesWithTesselation(Tesselator& tesselator, std::shared_ptr<CityGMLLogger> logger);
+        void removeDuplicateVerticesInRings(std::shared_ptr<CityGMLLogger> logger);
+        std::vector<TVec2f> getTexCoordsForRingAndTheme(const LinearRing& ring, const std::string& theme, bool front);
+        std::vector<std::vector<TVec2f> > getTexCoordListsForRing(const LinearRing& ring, const std::vector<std::string>& themesFront, const std::vector<std::string>& themesBack);
+
+        TVec3d computeNormal();
+
+        std::vector<TVec3d> m_vertices;
+        std::unordered_map<std::string, std::vector<TVec2f>> m_themeToFrontTexCoordsMap;
+        std::unordered_map<std::string, std::vector<TVec2f>> m_themeToBackTexCoordsMap;
+        std::vector<unsigned int> m_indices;
+
+        std::unique_ptr<LinearRing> m_exteriorRing;
+        std::vector<std::unique_ptr<LinearRing>> m_interiorRings;
+
+        bool m_negNormal;
+        bool m_finished;
+
+        std::shared_ptr<CityGMLLogger> m_logger;
+    };
+}
diff --git a/sources/include/citygml/polygonmanager.h b/sources/include/citygml/polygonmanager.h
new file mode 100644
index 0000000..d920deb
--- /dev/null
+++ b/sources/include/citygml/polygonmanager.h
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace citygml {
+
+    class Polygon;
+    class Geometry;
+    class CityGMLLogger;
+
+    class PolygonManager {
+    public:
+        PolygonManager(std::shared_ptr<CityGMLLogger> logger);
+
+        void addPolygon(std::shared_ptr<Polygon> 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<CityGMLLogger> m_logger;
+        std::vector<PolygonRequest> m_polygonRequests;
+        std::unordered_map<std::string, std::shared_ptr<Polygon>> m_sharedPolygons;
+    };
+
+}
diff --git a/sources/include/citygml/tesselator.h b/sources/include/citygml/tesselator.h
new file mode 100644
index 0000000..86befba
--- /dev/null
+++ b/sources/include/citygml/tesselator.h
@@ -0,0 +1,86 @@
+/* -*-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 <windows.h>
+#else
+#	define CALLBACK
+#	define APIENTRY
+#endif
+
+#ifdef __APPLE__
+  #include <OpenGL/glu.h>
+#else
+  #include <GL/glu.h>
+#endif
+
+#include "citygml/vecs.hpp"
+#include <vector>
+#include <list>
+#include <memory>
+
+namespace citygml {
+    class CityGMLLogger;
+}
+
+// GLU based polygon tesselator
+class Tesselator
+{
+public:
+    Tesselator( std::shared_ptr<citygml::CityGMLLogger> 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<TVec3d>&, std::vector<std::vector<TVec2f> > textureCoordinatesLists);
+
+    // Let's tesselate!
+    void compute();
+
+    // Tesselation result access
+    const std::vector<TVec3d> getVertices() const;
+    const std::vector<std::vector<TVec2f>>& getTexCoords() const { return _texCoordsLists; }
+    const std::vector<unsigned int>& 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<TVec3d> _vertices;
+    std::vector<std::vector<TVec2f>> _texCoordsLists;
+    std::list<unsigned int> _indices;
+    std::vector<unsigned int> _outIndices;
+
+    std::vector<unsigned int> _curIndices;
+    std::shared_ptr<citygml::CityGMLLogger> _logger;
+};
+
+#endif // __TESSELATOR_H__
diff --git a/sources/include/citygml/texture.h b/sources/include/citygml/texture.h
new file mode 100644
index 0000000..6d73d3a
--- /dev/null
+++ b/sources/include/citygml/texture.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <string>
+
+#include <citygml/citygml_api.h>
+#include <citygml/appearance.h>
+#include <citygml/vecs.hpp>
+
+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<Texture> asTexture() override;
+        virtual std::shared_ptr<const Texture> 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;
+    };
+
+}
diff --git a/sources/include/citygml/texturecoordinates.h b/sources/include/citygml/texturecoordinates.h
new file mode 100644
index 0000000..a6a4cf6
--- /dev/null
+++ b/sources/include/citygml/texturecoordinates.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <citygml/citygml_api.h>
+#include <citygml/vecs.hpp>
+#include <citygml/object.h>
+
+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<TVec2f>& getCoords() const;
+        void setCoords(std::vector<TVec2f> texCoords);
+
+        bool eraseCoordinate(unsigned int i);
+
+    protected:
+        std::string m_targetID;
+        std::vector<TVec2f> m_coordlist;
+    };
+}
diff --git a/sources/include/citygml/texturetargetdefinition.h b/sources/include/citygml/texturetargetdefinition.h
new file mode 100644
index 0000000..3de0517
--- /dev/null
+++ b/sources/include/citygml/texturetargetdefinition.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <vector>
+#include <unordered_map>
+
+#include <citygml/citygml_api.h>
+#include <citygml/appearancetargetdefinition.h>
+#include <citygml/texture.h>
+
+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<Texture> {
+        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)
+         */
+        TextureCoordinates* getTextureCoordinates(unsigned int i);
+        const TextureCoordinates* 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
+         */
+        TextureCoordinates* getTextureCoordinatesForID(const std::string& ringID);
+        const TextureCoordinates* getTextureCoordinatesForID(const std::string& ringID) const;
+
+        void addTexCoordinates(TextureCoordinates* texCoords);
+
+
+        ~TextureTargetDefinition();
+
+    protected:
+        TextureTargetDefinition(const std::string& targetID, std::shared_ptr<Texture> appearance, const std::string& id);
+        std::vector<std::shared_ptr<TextureCoordinates>> m_coordinatesList;
+        std::unordered_map<std::string, TextureCoordinates*> m_idTexCoordMap;
+    };
+}
diff --git a/sources/include/citygml/transformmatrix.h b/sources/include/citygml/transformmatrix.h
new file mode 100644
index 0000000..787f16b
--- /dev/null
+++ b/sources/include/citygml/transformmatrix.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <citygml/object.h>
+#include <memory>
+
+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];
+    };
+}
diff --git a/src/utils.h b/sources/include/citygml/utils.h
similarity index 50%
rename from src/utils.h
rename to sources/include/citygml/utils.h
index 9549162..aef4a8a 100644
--- a/src/utils.h
+++ b/sources/include/citygml/utils.h
@@ -1,69 +1,74 @@
-/* -*-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 __UTILS_H__
-#define __UTILS_H__
-
-#include <string>
-#include <vector>
-#include <algorithm>
-
-// Helpers
-
-// std::string tokenizer
-inline std::vector<std::string> tokenize( const std::string& str, const std::string& delimiters = ",|& " )
-{
-	std::vector<std::string> 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 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 );
-}
-
-#endif // __UTILS_H__
+/* -*-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 <string>
+#include <vector>
+#include <algorithm>
+
+
+// Helpers
+
+// std::string tokenizer
+inline std::vector<std::string> tokenize( const std::string& str, const std::string& delimiters = ",|& " )
+{
+    std::vector<std::string> 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 );
+}
+
diff --git a/sources/include/citygml/vecs.hpp b/sources/include/citygml/vecs.hpp
new file mode 100644
index 0000000..f1cf448
--- /dev/null
+++ b/sources/include/citygml/vecs.hpp
@@ -0,0 +1,338 @@
+#pragma once
+#include <sstream>
+#include <iostream>
+#include <math.h>
+#include <string.h>
+
+// 2D vector class.
+
+template< class T > class TVec2
+{
+public:
+    T x;
+    T y;
+
+public:
+    TVec2( const TVec2<T>& 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<T>& v ) const;
+    TVec2 operator-( const TVec2<T>& v ) const;
+    TVec2 operator-() const;
+    TVec2 operator*( const T& v ) const;
+    TVec2 operator*( const TVec2<T>& v ) const;
+    TVec2 operator/( const T& v ) const;
+    TVec2 operator/( const TVec2<T>& v ) const;
+
+    bool operator==( const TVec2<T>& v ) const;
+    bool operator!=( const TVec2<T>& v ) const;
+};
+
+template< class T > inline TVec2<T>::TVec2( const T x, const T y )
+{
+    this->x = x;
+    this->y = y;
+}
+
+template< class T >	inline TVec2<T>::TVec2( const T vec[] )
+{
+    x = vec[0];
+    y = vec[1];
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator+( const TVec2<T>& v ) const
+{
+    return TVec2<T>( x + v.x, y + v.y );
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator-( const TVec2<T>& v ) const
+{
+    return TVec2<T>( x - v.x, y - v.y );
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator-() const
+{
+    return TVec2<T>( -x, -y );
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator*( const T& v ) const
+{
+    return TVec2<T>( x * v, y * v );
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator*( const TVec2<T>& v ) const
+{
+    return TVec2<T>( x * v.x, y * v.y );
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator/( const T& v ) const
+{
+    return TVec2<T>( x / v, y / v );
+}
+
+template< class T >	inline TVec2<T> TVec2<T>::operator/( const TVec2<T>& v ) const
+{
+    return TVec2<T>( x / v.x, y / v.y );
+}
+
+template< class T >	inline bool TVec2<T>::operator==( const TVec2<T>& v ) const
+{
+    return x == v.x && y == v.y;
+}
+
+template< class T >	inline bool TVec2<T>::operator!=( const TVec2<T>& v ) const
+{
+    return x != v.x || y != v.y;
+}
+
+template< class T >	inline TVec2<T> operator*( const T& val, const TVec2<T>& vec )
+{
+    return TVec2<T>( vec.x * val, vec.y * val );
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream & os, TVec2<T> const & v)
+{
+    return os << std::fixed << v.x << " " << std::fixed << v.y;
+}
+
+template<class T> inline std::istream& operator>>(std::istream & is, TVec2<T> & 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<T>& vec ) const;
+    TVec3 cross( const TVec3<T>& vec ) const;
+
+    TVec3  normal() const;
+    TVec3& normalEq();
+    TVec3& normalEq( const T length );
+
+    TVec3 operator+( const TVec3<T>& rhs ) const;
+    TVec3 operator+( const T& _v ) const;
+    TVec3 operator-( const TVec3<T>& rhs ) const;
+    TVec3 operator-( const T& _v ) const;
+    TVec3 operator-() const;
+    TVec3 operator*( const T& rhs ) const;
+    TVec3 operator*( const TVec3<T>& rhs ) const;
+    TVec3 operator/( const T& rhs ) const;
+    TVec3 operator/( const TVec3<T>& rhs ) const;
+
+    inline bool operator==( const TVec3<T>& rhs ) const;
+    inline bool operator!=( const TVec3<T>& rhs ) const;
+
+    inline operator T*() { return xyz; }
+    inline operator const T*() const { return xyz; }
+};
+
+template< class T > inline TVec3<T>::TVec3( const T x, const T y, const T z )
+{
+    this->x = x;
+    this->y = y;
+    this->z = z;
+}
+
+template< class T >	inline TVec3<T>::TVec3( const T vec[] )
+{
+    memcpy( xyz, vec, 3 * sizeof(T) );
+}
+
+template< class T > inline T TVec3<T>::length() const
+{
+    return (T)sqrt( x*x + y*y + z*z );
+}
+
+template< class T > inline T TVec3<T>::sqrLength() const
+{
+    return x*x + y*y + z*z;
+}
+
+template< class T > inline T TVec3<T>::dot( const TVec3<T>& vec ) const
+{
+    return x*vec.x + y*vec.y + z*vec.z;
+}
+
+template< class T > inline TVec3<T> TVec3<T>::cross( const TVec3<T>& vec ) const
+{
+    return TVec3<T>( y*vec.z - z*vec.y, z*vec.x - x*vec.z, x*vec.y - y*vec.x );
+}
+
+template< class T > inline TVec3<T> TVec3<T>::normal() const
+{
+    const T len = length();
+    const T tmp = ( len != (T)0 ) ? ( (T)1 / len ) : (T)0;
+    return TVec3<T>( x * tmp, y * tmp, z * tmp );
+}
+
+template< class T > inline TVec3<T>& TVec3<T>::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<T>& TVec3<T>::normalEq( const T length )
+{
+    const T len = TVec3<T>::length();
+    const T tmp = ( len != (T)0 ) ? length / len : (T)0;
+    x *= tmp;
+    y *= tmp;
+    z *= tmp;
+    return *this;
+}
+
+template< class T > inline TVec3<T> TVec3<T>::operator+( const TVec3<T>& rhs ) const
+{
+    return TVec3<T>( x + rhs.x, y + rhs.y, z + rhs.z );
+}
+
+template< class T >	inline TVec3<T> TVec3<T>::operator+( const T& _v ) const
+{
+    return TVec3<T>( x + _v, y + _v, z + _v );
+}
+
+template< class T > inline TVec3<T> TVec3<T>::operator-( const TVec3<T>& rhs ) const
+{
+    return TVec3<T>( x - rhs.x, y - rhs.y, z - rhs.z );
+}
+
+template< class T > inline TVec3<T> TVec3<T>::operator-( const T& _v ) const
+{
+    return TVec3<T>( x - _v, y - _v, z - _v );
+}
+
+template< class T >	inline TVec3<T> TVec3<T>::operator-() const
+{
+    return TVec3<T>( -x, -y, -z );
+}
+
+template< class T > inline TVec3<T> TVec3<T>::operator*( const T& rhs ) const
+{
+    return TVec3<T>( x * rhs, y * rhs, z * rhs );
+}
+
+template< class T >	inline TVec3<T> TVec3<T>::operator*( const TVec3<T>& rhs ) const
+{
+    return TVec3<T>( x * rhs.x, y * rhs.y, z * rhs.z );
+}
+
+template< class T > inline TVec3<T> TVec3<T>::operator/( const T& rhs ) const
+{
+    return TVec3<T>( x / rhs, y / rhs, z / rhs );
+}
+
+template< class T > inline TVec3<T> TVec3<T>::operator/( const TVec3<T>& rhs ) const
+{
+    return TVec3<T>( x / rhs.x, y / rhs.y, z / rhs.z );
+}
+
+template< class T > inline bool TVec3<T>::operator==( const TVec3<T>& rhs ) const
+{
+    return x == rhs.x && y == rhs.y && z == rhs.z;
+}
+
+template< class T > inline bool TVec3<T>::operator!=( const TVec3<T>& rhs ) const
+{
+    return x != rhs.x || y != rhs.y || z != rhs.z;
+}
+
+template< class T >	inline TVec3<T> operator*( const T& val, const TVec3<T>& vec )
+{
+    return TVec3<T>( vec.x * val, vec.y * val, vec.z * val );
+}
+
+template<class T> inline std::ostream& operator<<(std::ostream & os, const TVec3<T> & v)
+{
+    return os << std::fixed << v.x << " " << std::fixed << v.y << " " << std::fixed << v.z;
+}
+
+template<class T> inline std::istream& operator>>(std::istream & is, TVec3<T> & 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<class T> inline std::ostream& operator<<( std::ostream & os, TVec4<T> const & v )
+{
+    return os << std::fixed << v.x << " " << std::fixed << v.y << " " << std::fixed << v.z << " " << std::fixed << v.w;
+}
+
+template<class T> inline std::istream& operator>>( std::istream & is, TVec4<T> & v )
+{
+    return is >> v.x >> v.y >> v.z >>  v.w;
+}
+
+typedef TVec4< float >			TVec4f;
+typedef TVec4< double >			TVec4d;
+
diff --git a/sources/include/parser/appearanceelementparser.h b/sources/include/parser/appearanceelementparser.h
new file mode 100644
index 0000000..d059fd2
--- /dev/null
+++ b/sources/include/parser/appearanceelementparser.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace citygml {
+
+    class CityObject;
+    class Appearance;
+
+    class AppearanceElementParser : public CityGMLElementParser {
+    public:
+        AppearanceElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> 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;
+
+    private:
+        std::vector<std::shared_ptr<Appearance>> m_surfaceDataList;
+        std::string m_theme;
+    };
+
+}
diff --git a/sources/include/parser/attributes.h b/sources/include/parser/attributes.h
new file mode 100644
index 0000000..a8cba55
--- /dev/null
+++ b/sources/include/parser/attributes.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <string>
+#include <memory>
+
+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;
+
+        std::string getCityGMLIDAttribute() const;
+
+        bool hasXLinkAttribute() const;
+        std::string getXLinkValue();
+
+    protected:
+        Attributes(std::shared_ptr<CityGMLLogger> logger);
+        std::shared_ptr<CityGMLLogger> m_logger;
+    };
+
+}
diff --git a/sources/include/parser/citygmldocumentparser.h b/sources/include/parser/citygmldocumentparser.h
new file mode 100644
index 0000000..c9f7a24
--- /dev/null
+++ b/sources/include/parser/citygmldocumentparser.h
@@ -0,0 +1,86 @@
+#pragma once
+
+#include <citygml/citygml.h>
+
+#include <stack>
+#include <memory>
+
+namespace citygml {
+
+    class Attributes;
+    class CityGMLLogger;
+    class DocumentLocation;
+    class CityGMLFactory;
+    class ElementParser;
+
+    class CityGMLDocumentParser {
+    public:
+        CityGMLDocumentParser(const ParserParams& params, std::shared_ptr<CityGMLLogger> logger);
+
+        std::shared_ptr<const CityModel> 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<CityGMLLogger> 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<std::shared_ptr<ElementParser>> 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<ElementParser> m_activeParser;
+
+        std::unique_ptr<CityGMLFactory> m_factory;
+        std::shared_ptr<CityModel> m_rootModel;
+        ParserParams m_parserParams;
+
+        bool m_currentElementUnknownOrUnexpected;
+        int m_unknownElementOrUnexpectedElementDepth;
+        std::string m_unknownElementOrUnexpectedElementName;
+    };
+
+}
diff --git a/sources/include/parser/citygmlelementparser.h b/sources/include/parser/citygmlelementparser.h
new file mode 100644
index 0000000..166dad8
--- /dev/null
+++ b/sources/include/parser/citygmlelementparser.h
@@ -0,0 +1,87 @@
+#pragma once
+
+#include <string>
+#include <memory>
+
+#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<CityGMLLogger> 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;
+    };
+
+}
diff --git a/sources/include/parser/citymodelelementparser.h b/sources/include/parser/citymodelelementparser.h
new file mode 100644
index 0000000..eb16c39
--- /dev/null
+++ b/sources/include/parser/citymodelelementparser.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <parser/gmlfeaturecollectionparser.h>
+
+#include <functional>
+
+namespace citygml {
+
+    class CityModel;
+
+    class CityModelElementParser : public GMLFeatureCollectionElementParser {
+    public:
+        CityModelElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(CityModel*)> 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<void(CityModel*)> m_callback;
+        CityModel* m_model;
+    };
+
+}
diff --git a/sources/include/parser/cityobjectelementparser.h b/sources/include/parser/cityobjectelementparser.h
new file mode 100644
index 0000000..abd85c7
--- /dev/null
+++ b/sources/include/parser/cityobjectelementparser.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <parser/gmlfeaturecollectionparser.h>
+
+#include <functional>
+#include <unordered_map>
+#include <unordered_set>
+#include <mutex>
+
+#include "citygml/cityobject.h"
+
+namespace citygml {
+
+    class CityObjectElementParser : public GMLFeatureCollectionElementParser {
+    public:
+        CityObjectElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(CityObject*)> 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<void(CityObject*)> m_callback;
+        std::string m_lastAttributeName;
+
+        // The nodes that are valid CityObjects
+        static std::mutex initializedTypeIDMutex;
+        static std::unordered_map<int, CityObject::CityObjectsType> typeIDTypeMap;
+        static bool typeIDTypeMapInitialized;
+
+        static std::mutex initializedAttributeSetMutex;
+        static std::unordered_set<int> attributesSet;
+        static bool attributesSetInitialized;
+
+        void parseGeometryForLODLevel(int lod);
+        void parseImplicitGeometryForLODLevel(int lod);
+    };
+
+}
diff --git a/sources/include/parser/delayedchoiceelementparser.h b/sources/include/parser/delayedchoiceelementparser.h
new file mode 100644
index 0000000..fde8aa2
--- /dev/null
+++ b/sources/include/parser/delayedchoiceelementparser.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <vector>
+#include <memory>
+
+#include "parser/citygmlelementparser.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:
+        DelayedChoiceElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr<CityGMLLogger> logger, std::vector<ElementParser*> 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<ElementParser*> m_choices;
+    };
+
+}
diff --git a/sources/include/parser/documentlocation.h b/sources/include/parser/documentlocation.h
new file mode 100644
index 0000000..69eaa6e
--- /dev/null
+++ b/sources/include/parser/documentlocation.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <string>
+#include <ostream>
+#include <stdint.h>
+
+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;
+
+    }
+}
diff --git a/sources/include/parser/elementparser.h b/sources/include/parser/elementparser.h
new file mode 100644
index 0000000..22d444a
--- /dev/null
+++ b/sources/include/parser/elementparser.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <string>
+#include <memory>
+
+#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
+     * @see CityGMLElementParser
+     */
+    class ElementParser {
+    public:
+
+        ElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr<CityGMLLogger> 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
+         */
+        virtual bool handlesElement(const NodeType::XMLNode& node) const = 0;
+
+        virtual std::string elementParserName() const = 0;
+
+        virtual ~ElementParser();
+
+    protected:
+        void setParserForNextElement(ElementParser* parser);
+        virtual const DocumentLocation& getDocumentLocation() const;
+
+        std::shared_ptr<CityGMLLogger> m_logger;
+        CityGMLDocumentParser& m_documentParser;
+    };
+
+}
diff --git a/sources/include/parser/geocoordinatetransformer.h b/sources/include/parser/geocoordinatetransformer.h
new file mode 100644
index 0000000..3bb1819
--- /dev/null
+++ b/sources/include/parser/geocoordinatetransformer.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <string>
+#include <memory>
+#include <unordered_map>
+
+class GeoTransform;
+
+namespace citygml {
+
+    class CityGMLLogger;
+    class CityModel;
+    class CityObject;
+    class ImplicitGeometry;
+    class Geometry;
+    class Polygon;
+
+    class GeoCoordinateTransformer {
+    public:
+        GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr<CityGMLLogger> logger);
+
+        void transformToDestinationSRS(CityModel* model);
+    private:
+        std::string m_destinationSRS;
+        std::shared_ptr<CityGMLLogger> m_logger;
+        std::unordered_map<std::string, std::string> m_transformedPolygonsSourceURNMap;
+
+        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);
+    };
+
+}
+
+
+
diff --git a/sources/include/parser/geometryelementparser.h b/sources/include/parser/geometryelementparser.h
new file mode 100644
index 0000000..3ef14f5
--- /dev/null
+++ b/sources/include/parser/geometryelementparser.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+#include <citygml/cityobject.h>
+
+#include <string>
+#include <functional>
+
+namespace citygml {
+
+    class Geometry;
+
+    class GeometryElementParser : public CityGMLElementParser {
+    public:
+        GeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger,
+                              int lodLevel, CityObject::CityObjectsType parentType, std::function<void(Geometry*)> 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:
+        Geometry* m_model;
+        std::function<void(Geometry*)> m_callback;
+        int m_lodLevel;
+        CityObject::CityObjectsType m_parentType;
+        std::string m_orientation;
+    };
+
+}
diff --git a/sources/include/parser/georeferencedtextureelementparser.h b/sources/include/parser/georeferencedtextureelementparser.h
new file mode 100644
index 0000000..5eee158
--- /dev/null
+++ b/sources/include/parser/georeferencedtextureelementparser.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+#include <functional>
+#include <string>
+
+namespace citygml {
+
+    class GeoreferencedTexture;
+
+    class GeoReferencedTextureElementParser : public CityGMLElementParser {
+    public:
+        GeoReferencedTextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(std::shared_ptr<GeoreferencedTexture>)> 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<void(std::shared_ptr<GeoreferencedTexture>)> m_callback;
+    };
+
+}
diff --git a/sources/include/parser/gmlfeaturecollectionparser.h b/sources/include/parser/gmlfeaturecollectionparser.h
new file mode 100644
index 0000000..9bfd9ab
--- /dev/null
+++ b/sources/include/parser/gmlfeaturecollectionparser.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+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 CityGMLElementParser {
+    public:
+        GMLFeatureCollectionElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> 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;
+
+    private:
+        Envelope* m_bounds;
+    };
+
+}
diff --git a/sources/include/parser/implicitgeometryelementparser.h b/sources/include/parser/implicitgeometryelementparser.h
new file mode 100644
index 0000000..71bf05c
--- /dev/null
+++ b/sources/include/parser/implicitgeometryelementparser.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+#include <citygml/cityobject.h>
+
+#include <string>
+#include <functional>
+
+namespace citygml {
+
+    class ImplicitGeometry;
+
+    class ImplicitGeometryElementParser : public CityGMLElementParser {
+    public:
+        ImplicitGeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger,
+                              int lodLevel, CityObject::CityObjectsType parentType, std::function<void(ImplicitGeometry*)> 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:
+        ImplicitGeometry* m_model;
+        std::function<void(ImplicitGeometry*)> m_callback;
+        int m_lodLevel;
+        CityObject::CityObjectsType m_parentType;
+        std::string m_orientation;
+    };
+
+}
diff --git a/sources/include/parser/linearringelementparser.h b/sources/include/parser/linearringelementparser.h
new file mode 100644
index 0000000..bb18118
--- /dev/null
+++ b/sources/include/parser/linearringelementparser.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+#include <functional>
+
+namespace citygml {
+
+    class LinearRing;
+
+    class LinearRingElementParser : public CityGMLElementParser {
+    public:
+        LinearRingElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, bool interior, std::function<void(LinearRing*)> 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:
+        LinearRing* m_model;
+        std::function<void(LinearRing*)> m_callback;
+        bool m_interior;
+    };
+
+}
diff --git a/sources/include/parser/materialelementparser.h b/sources/include/parser/materialelementparser.h
new file mode 100644
index 0000000..dd502e0
--- /dev/null
+++ b/sources/include/parser/materialelementparser.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+namespace citygml {
+
+    class Material;
+
+    class MaterialElementParser : public CityGMLElementParser {
+    public:
+        MaterialElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(std::shared_ptr<Material>)> 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;
+
+    private:
+        std::shared_ptr<Material> m_model;
+        std::function<void(std::shared_ptr<Material>)> m_callback;
+        std::string m_lastTargetDefinitionID;
+    };
+
+}
diff --git a/sources/include/parser/nodetypes.h b/sources/include/parser/nodetypes.h
new file mode 100644
index 0000000..1c08dcc
--- /dev/null
+++ b/sources/include/parser/nodetypes.h
@@ -0,0 +1,290 @@
+#pragma once
+
+#include <string>
+#include <ostream>
+#include <mutex>
+#include <unordered_map>
+
+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;
+            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, ImplicitGeometry )
+        NODETYPE( CORE, RelativeGMLGeometry )
+        NODETYPE( CORE, TransformationMatrix )
+
+        // GRP
+        NODETYPE( GRP, CityObjectGroup )
+        NODETYPE( GRP, GroupMember )
+
+        // GEN
+        NODETYPE( GEN, GenericCityObject )
+        NODETYPE( GEN, StringAttribute )
+        NODETYPE( GEN, DoubleAttribute )
+        NODETYPE( GEN, IntAttribute )
+        NODETYPE( GEN, DateAttribute )
+        NODETYPE( GEN, UriAttribute )
+        NODETYPE( GEN, Value )
+
+        NODETYPE( GEN, Lod1Geometry )
+        NODETYPE( GEN, Lod2Geometry )
+        NODETYPE( GEN, Lod3Geometry )
+        NODETYPE( GEN, Lod4Geometry )
+        NODETYPE( GEN, Lod1TerrainIntersection )
+        NODETYPE( GEN, Lod2TerrainIntersection )
+        NODETYPE( GEN, Lod3TerrainIntersection )
+        NODETYPE( GEN, Lod4TerrainIntersection )
+
+        // TEX
+        // NODETYPE( GML, TexturedSurface ) // Deprecated
+
+        // GML
+        NODETYPE( GML, Description )
+        NODETYPE( GML, Identifier )
+        NODETYPE( GML, Name )
+        NODETYPE( GML, DescriptionReference )
+        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 )
+
+        // 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, ExternalReference)
+        NODETYPE( BLDG, InformationSystem)
+        NODETYPE( BLDG, ExternalObject)
+        NODETYPE( BLDG, Uri)
+
+        NODETYPE( BLDG, Lod1Solid )
+        NODETYPE( BLDG, Lod2Solid )
+        NODETYPE( BLDG, Lod3Solid )
+        NODETYPE( BLDG, Lod4Solid )
+        NODETYPE( BLDG, Lod1Geometry )
+        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, 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, XalAddress )
+        NODETYPE( XAL, Administrativearea )
+        NODETYPE( XAL, Country )
+        NODETYPE( XAL, CountryName )
+        NODETYPE( XAL, Code )
+        NODETYPE( XAL, Street )
+        NODETYPE( XAL, PostalCode )
+        NODETYPE( XAL, City )
+        NODETYPE( XAL, LocalityName )
+        NODETYPE( XAL, Thoroughfare )
+        NODETYPE( XAL, ThoroughfareNumber )
+        NODETYPE( XAL, ThoroughfareName )
+        NODETYPE( XAL, Locality )
+        NODETYPE( XAL, AddressDetails )
+        NODETYPE( XAL, DependentLocalityName )
+
+        // WTR
+        NODETYPE( WTR, WaterBody )
+
+        // VEG
+        NODETYPE( VEG, PlantCover )
+        NODETYPE( VEG, SolitaryVegetationObject )
+        NODETYPE( VEG, Species )
+        NODETYPE( VEG, Lod1ImplicitRepresentation )
+        NODETYPE( VEG, Lod2ImplicitRepresentation )
+        NODETYPE( VEG, Lod3ImplicitRepresentation )
+        NODETYPE( VEG, Lod4ImplicitRepresentation )
+
+        // TRANS
+        NODETYPE( TRANS, TrafficArea )
+        NODETYPE( TRANS, AuxiliaryTrafficArea )
+        NODETYPE( TRANS, Track )
+        NODETYPE( TRANS, Road )
+        NODETYPE( TRANS, Railway )
+        NODETYPE( TRANS, Square )
+
+        // LUSE
+        NODETYPE( LUSE, LandUse )
+
+        // dem
+        NODETYPE( LUSE, Lod )
+        NODETYPE( LUSE, TINRelief )
+
+        // 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, TextureCoordinates )
+        NODETYPE( APP, TextureType )
+        NODETYPE( APP, Repeat )
+        NODETYPE( APP, WrapMode )
+        NODETYPE( APP, BorderColor )
+        NODETYPE( APP, PreferWorldFile )
+
+        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<std::string, XMLNode*> nodeNameTypeMap;
+        static std::unordered_map<std::string, XMLNode*> nodeNameWithPrefixTypeMap;
+    };
+
+    std::ostream& operator<<( std::ostream& os, const NodeType::XMLNode& o );
+}
diff --git a/sources/include/parser/parserutils.hpp b/sources/include/parser/parserutils.hpp
new file mode 100644
index 0000000..0a0c53b
--- /dev/null
+++ b/sources/include/parser/parserutils.hpp
@@ -0,0 +1,92 @@
+#pragma once
+
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <parser/documentlocation.h>
+
+#include <citygml/transformmatrix.h>
+#include <citygml/citygmllogger.h>
+#include <citygml/vecs.hpp>
+
+namespace citygml {
+
+    template<class T> inline T parseValue( const std::string &s, std::shared_ptr<citygml::CityGMLLogger>&, const DocumentLocation&)
+    {
+        std::stringstream ss;
+        ss << s;
+        T v;
+        ss >> v;
+        return v;
+    }
+
+    inline TransformationMatrix parseMatrix( const std::string &s, std::shared_ptr<citygml::CityGMLLogger>& 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<citygml::CityGMLLogger>& 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<class T> inline std::vector<T> parseVecList( const std::string &s,  std::shared_ptr<citygml::CityGMLLogger>& logger, const DocumentLocation& location )
+    {
+        std::stringstream ss;
+        ss << s;
+
+        T v;
+        std::vector<T> 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<citygml::CityGMLLogger>& 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;
+        }
+    }
+
+}
diff --git a/sources/include/parser/polygonelementparser.h b/sources/include/parser/polygonelementparser.h
new file mode 100644
index 0000000..1b3b3d7
--- /dev/null
+++ b/sources/include/parser/polygonelementparser.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+#include <functional>
+#include <memory>
+
+namespace citygml {
+
+    class Polygon;
+
+    class PolygonElementParser : public CityGMLElementParser {
+    public:
+        PolygonElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(std::shared_ptr<Polygon>)> 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::shared_ptr<Polygon> m_model;
+        std::function<void(std::shared_ptr<Polygon>)> m_callback;
+
+        void parseRingElement(bool interior);
+    };
+
+}
diff --git a/sources/include/parser/textureelementparser.h b/sources/include/parser/textureelementparser.h
new file mode 100644
index 0000000..e0574f0
--- /dev/null
+++ b/sources/include/parser/textureelementparser.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <parser/citygmlelementparser.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+namespace citygml {
+
+    class Texture;
+    class TextureTargetDefinition;
+    class TextureCoordinates;
+
+    class TextureElementParser : public CityGMLElementParser {
+    public:
+        TextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(std::shared_ptr<Texture>)> 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::shared_ptr<Texture> m_model;
+        std::function<void(std::shared_ptr<Texture>)> m_callback;
+        std::shared_ptr<TextureTargetDefinition> m_currentTexTargetDef;
+        TextureCoordinates* m_currentTexCoords;
+    };
+
+}
diff --git a/sources/src/citygml/appearance.cpp b/sources/src/citygml/appearance.cpp
new file mode 100644
index 0000000..4e7ffb8
--- /dev/null
+++ b/sources/src/citygml/appearance.cpp
@@ -0,0 +1,77 @@
+#include "citygml/appearance.h"
+
+#include <algorithm>
+
+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<Material> Appearance::asMaterial()
+    {
+        return nullptr;
+    }
+
+    std::shared_ptr<const Material> Appearance::asMaterial() const
+    {
+        return nullptr;
+    }
+
+    std::shared_ptr<Texture> Appearance::asTexture()
+    {
+        return nullptr;
+    }
+
+    std::shared_ptr<const Texture> Appearance::asTexture() const
+    {
+        return nullptr;
+    }
+
+    std::shared_ptr<GeoreferencedTexture> Appearance::asGeoreferencedTexture()
+    {
+        return nullptr;
+    }
+
+    std::shared_ptr<const GeoreferencedTexture> 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<std::string>& Appearance::getThemes() const
+    {
+        return m_themes;
+    }
+
+}
diff --git a/sources/src/citygml/appearancemanager.cpp b/sources/src/citygml/appearancemanager.cpp
new file mode 100644
index 0000000..7f04fe4
--- /dev/null
+++ b/sources/src/citygml/appearancemanager.cpp
@@ -0,0 +1,100 @@
+#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<CityGMLLogger> logger)
+    {
+        m_logger = logger;
+    }
+
+    AppearanceManager::~AppearanceManager()
+    {
+
+    }
+
+    std::shared_ptr<Appearance> 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<std::string> AppearanceManager::getAllThemes()
+    {
+        std::vector<std::string> 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> appearance)
+    {
+        m_appearancesMap[appearance->getId()] = appearance;
+    }
+
+    void AppearanceManager::addTextureTargetDefinition(std::shared_ptr<TextureTargetDefinition> targetDef)
+    {
+        m_texTargetDefinitions.push_back(targetDef);
+    }
+
+    void AppearanceManager::addMaterialTargetDefinition(std::shared_ptr<MaterialTargetDefinition> targetDef)
+    {
+        m_materialTargetDefinitions.push_back(targetDef);
+    }
+
+    template<class T> void assignTargetDefinition(std::shared_ptr<T>& targetDef, std::unordered_map<std::string, AppearanceTarget*> targetMap, std::shared_ptr<CityGMLLogger>& 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<MaterialTargetDefinition>& targetDef : m_materialTargetDefinitions ) {
+            assignTargetDefinition<MaterialTargetDefinition>(targetDef, m_appearanceTargetsMap, m_logger);
+            addThemesFrom(targetDef->getAppearance());
+        }
+
+        for (std::shared_ptr<TextureTargetDefinition>& targetDef : m_texTargetDefinitions ) {
+            assignTargetDefinition<TextureTargetDefinition>(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<Appearance> surfaceData)
+    {
+        m_themes.insert(surfaceData->getThemes().begin(), surfaceData->getThemes().end());
+    }
+
+}
diff --git a/sources/src/citygml/appearancetarget.cpp b/sources/src/citygml/appearancetarget.cpp
new file mode 100644
index 0000000..44d58b3
--- /dev/null
+++ b/sources/src/citygml/appearancetarget.cpp
@@ -0,0 +1,123 @@
+#include "citygml/appearancetarget.h"
+#include "citygml/texturetargetdefinition.h"
+#include "citygml/materialtargetdefinition.h"
+#include "citygml/appearancetargetdefinition.h"
+#include "citygml/appearance.h"
+
+#include <unordered_set>
+#include <algorithm>
+
+namespace citygml {
+
+    AppearanceTarget::AppearanceTarget(const std::string& id) : Object(id)
+    {
+
+    }
+
+
+    void AppearanceTarget::addTargetDefinition(std::shared_ptr<AppearanceTargetDefinition<Appearance> > targetDef)
+    {
+        if (targetDef->getAppearance()->asMaterial() != nullptr) {
+            addTargetDefinition(std::dynamic_pointer_cast<MaterialTargetDefinition>(targetDef));
+        } else {
+            addTargetDefinition(std::dynamic_pointer_cast<TextureTargetDefinition>(targetDef));
+        }
+    }
+
+    void AppearanceTarget::addTargetDefinition(std::shared_ptr<TextureTargetDefinition> 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<MaterialTargetDefinition> 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());
+    }
+
+    MaterialTargetDefinition* 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.get();
+    }
+
+    const MaterialTargetDefinition* 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.get();
+    }
+
+    TextureTargetDefinition* 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.get();
+    }
+
+    const TextureTargetDefinition* 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.get();
+    }
+
+    std::vector<TextureTargetDefinition*> AppearanceTarget::getTextureTargetDefinitions()
+    {
+        std::unordered_set<TextureTargetDefinition*> texTargetDefs;
+        for (auto& pair : m_themeTexMapFront) {
+            texTargetDefs.insert(pair.second.get());
+        }
+        for (auto& pair : m_themeTexMapBack) {
+            texTargetDefs.insert(pair.second.get());
+        }
+        return std::vector<TextureTargetDefinition*>(texTargetDefs.begin(), texTargetDefs.end());
+    }
+
+    std::vector<std::string> AppearanceTarget::getAllTextureThemes(bool front) const
+    {
+        auto& map = front ? m_themeTexMapFront : m_themeTexMapBack;
+        std::vector<std::string> themes;
+        for (const auto& pair : map) {
+            themes.push_back(pair.first);
+        }
+        return themes;
+    }
+
+
+
+}
diff --git a/sources/src/citygml/citygmlfactory.cpp b/sources/src/citygml/citygmlfactory.cpp
new file mode 100644
index 0000000..1da94c4
--- /dev/null
+++ b/sources/src/citygml/citygmlfactory.cpp
@@ -0,0 +1,142 @@
+#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/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<CityGMLLogger> logger)
+    {
+        m_appearanceManager = std::unique_ptr<AppearanceManager>(new AppearanceManager(logger));
+        m_polygonManager = std::unique_ptr<PolygonManager>(new PolygonManager(logger));
+        m_geometryManager = std::unique_ptr<GeometryManager>(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* CityGMLFactory::createGeometry(const std::string& id, Geometry::GeometryType type, unsigned int lod)
+    {
+        Geometry* geom = new Geometry(id, type, lod);
+        appearanceTargetCreated(geom);
+        return geom;
+    }
+
+    std::shared_ptr<Polygon> CityGMLFactory::createPolygon(const std::string& id)
+    {
+        Polygon* poly = new Polygon(id, m_logger);
+        appearanceTargetCreated(poly);
+
+        std::shared_ptr<Polygon> shared = std::shared_ptr<Polygon>(poly);
+        m_polygonManager->addPolygon(shared);
+
+        return shared;
+    }
+
+    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<Geometry> CityGMLFactory::shareGeometry(Geometry* geom)
+    {
+        std::shared_ptr<Geometry> shared = std::shared_ptr<Geometry>(geom);
+
+        m_geometryManager->addSharedGeometry(shared);
+
+        return shared;
+    }
+
+    void CityGMLFactory::requestSharedGeometryWithID(ImplicitGeometry* implicitGeom, const std::string& id)
+    {
+        m_geometryManager->requestSharedGeometryForImplicitGeometry(implicitGeom, id);
+    }
+
+    std::shared_ptr<Texture> CityGMLFactory::createTexture(const std::string& id)
+    {
+        std::shared_ptr<Texture> tex = std::shared_ptr<Texture>(new Texture(id));
+        m_appearanceManager->addAppearance(tex);
+        return tex;
+    }
+
+    std::shared_ptr<Material> CityGMLFactory::createMaterial(const std::string& id)
+    {
+        std::shared_ptr<Material> mat = std::shared_ptr<Material>(new Material(id));
+        m_appearanceManager->addAppearance(mat);
+        return mat;
+    }
+
+    std::shared_ptr<GeoreferencedTexture> CityGMLFactory::createGeoReferencedTexture(const std::string& id)
+    {
+        std::shared_ptr<GeoreferencedTexture> tex = std::shared_ptr<GeoreferencedTexture>(new GeoreferencedTexture(id));
+        m_appearanceManager->addAppearance(tex);
+        return tex;
+    }
+
+    std::shared_ptr<MaterialTargetDefinition> CityGMLFactory::createMaterialTargetDefinition(const std::string& targetID, std::shared_ptr<Material> appearance, const std::string& id)
+    {
+        std::shared_ptr<MaterialTargetDefinition> targetDef = std::shared_ptr<MaterialTargetDefinition>(new MaterialTargetDefinition(targetID, appearance, id));
+        m_appearanceManager->addMaterialTargetDefinition(targetDef);
+        return targetDef;
+    }
+
+    std::shared_ptr<TextureTargetDefinition> CityGMLFactory::createTextureTargetDefinition(const std::string& targetID, std::shared_ptr<Texture> appearance, const std::string& id)
+    {
+        std::shared_ptr<TextureTargetDefinition> targetDef = std::shared_ptr<TextureTargetDefinition>(new TextureTargetDefinition(targetID, appearance, id));
+        m_appearanceManager->addTextureTargetDefinition(targetDef);
+        return targetDef;
+    }
+
+    std::shared_ptr<Appearance> CityGMLFactory::getAppearanceWithID(const std::string& id)
+    {
+        return m_appearanceManager->getAppearanceByID(id);
+    }
+
+    std::vector<std::string> 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);
+    }
+}
diff --git a/sources/src/citygml/citymodel.cpp b/sources/src/citygml/citymodel.cpp
new file mode 100644
index 0000000..eab81ce
--- /dev/null
+++ b/sources/src/citygml/citymodel.cpp
@@ -0,0 +1,141 @@
+/* -*-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 <float.h>
+#include <string.h>
+#include <algorithm>
+
+#include <iterator>
+#include <set>
+
+#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<const CityObject*> tmp;
+            tmp.push_back(cityObj);
+            m_cityObjectsMap[cityObj->getType()] = std::vector<const CityObject*>(tmp);
+        } else {
+            it->second.push_back(cityObj);
+        }
+
+        for (int i = 0; i < cityObj->getChildCityObjectsCount(); i++) {
+            addToCityObjectsMapRecursive(&cityObj->getChildCityObject(i));
+        }
+    }
+    std::vector<std::string> CityModel::themes() const
+    {
+        return m_themes;
+    }
+
+    void CityModel::setThemes(std::vector<std::string> 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<CityObject>& cityObj : m_roots) {
+            list.push_back(cityObj.get());
+        }
+        return list;
+    }
+
+    void CityModel::addRootObject(CityObject* obj)
+    {
+        m_roots.push_back(std::unique_ptr<CityObject>(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<CityGMLLogger> logger)
+    {
+        // Finish all cityobjcts
+        for (auto& cityObj : m_roots) {
+            cityObj->finish(tesselator, optimize, logger);
+        }
+
+        // Build city objects map
+        for (std::unique_ptr<CityObject>& 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;
+    }
+
+}
diff --git a/sources/src/citygml/cityobject.cpp b/sources/src/citygml/cityobject.cpp
new file mode 100644
index 0000000..6c08b21
--- /dev/null
+++ b/sources/src/citygml/cityobject.cpp
@@ -0,0 +1,252 @@
+#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 <unordered_map>
+#include <algorithm>
+
+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<Geometry>(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<ImplicitGeometry>(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<CityObject>(cityObj));
+    }
+
+    void CityObject::finish(Tesselator& tesselator, bool optimize, std::shared_ptr<CityGMLLogger> logger)
+    {
+        for (std::unique_ptr<Geometry>& geom : m_geometries) {
+            geom->finish(tesselator, optimize, logger);
+        }
+
+        for (std::unique_ptr<ImplicitGeometry>& implictGeom : m_implicitGeometries) {
+            for (int i = 0; i < implictGeom->getGeometriesCount(); i++) {
+                implictGeom->getGeometry(i).finish(tesselator, optimize, logger);
+            }
+        }
+
+        for (std::unique_ptr<CityObject>& 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_TINRelief:
+            return "TINRelief";
+        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";
+        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<std::string, CityObject::CityObjectsType> 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_TINRelief), CityObject::COT_TINRelief},
+         {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},
+    };
+
+    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;
+    }
+
+}
diff --git a/sources/src/citygml/envelope.cpp b/sources/src/citygml/envelope.cpp
new file mode 100644
index 0000000..f0e9275
--- /dev/null
+++ b/sources/src/citygml/envelope.cpp
@@ -0,0 +1,66 @@
+#include "citygml/envelope.h"
+
+#include <numeric>
+#include <cmath>
+
+#ifndef NAN
+  #define NAN std::numeric_limits<double>::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();
+    }
+
+}
diff --git a/sources/src/citygml/featureobject.cpp b/sources/src/citygml/featureobject.cpp
new file mode 100644
index 0000000..5765604
--- /dev/null
+++ b/sources/src/citygml/featureobject.cpp
@@ -0,0 +1,27 @@
+#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<Envelope>(e);
+    }
+
+    FeatureObject::~FeatureObject()
+    {
+
+    }
+
+}
diff --git a/sources/src/citygml/geometry.cpp b/sources/src/citygml/geometry.cpp
new file mode 100644
index 0000000..46705c9
--- /dev/null
+++ b/sources/src/citygml/geometry.cpp
@@ -0,0 +1,140 @@
+#include "citygml/geometry.h"
+
+#include <citygml/polygon.h>
+#include <citygml/appearancemanager.h>
+#include <citygml/appearance.h>
+#include <citygml/citygmllogger.h>
+
+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();
+    }
+
+    Polygon& Geometry::getPolygon(unsigned int i)
+    {
+        return *m_polygons.at(i);
+    }
+
+    const Polygon& Geometry::getPolygon(unsigned int i) const
+    {
+        return *m_polygons.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<Geometry>(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<Polygon> p )
+    {
+        m_polygons.push_back( p );
+    }
+
+    void Geometry::finish(Tesselator& tesselator, bool optimize, std::shared_ptr<CityGMLLogger> logger)
+    {
+        // only need to finish geometry once
+        if (m_finished) {
+            return;
+        }
+
+        m_finished = true;
+
+        for (std::shared_ptr<Geometry>&  child : m_childGeometries) {
+            child->addTargetDefinitionsOf(*this);
+            child->finish(tesselator, optimize, logger);
+        }
+
+        for (std::shared_ptr<Polygon>& 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;
+    }
+
+}
diff --git a/sources/src/citygml/geometrymanager.cpp b/sources/src/citygml/geometrymanager.cpp
new file mode 100644
index 0000000..1bdfbb6
--- /dev/null
+++ b/sources/src/citygml/geometrymanager.cpp
@@ -0,0 +1,56 @@
+#include "citygml/geometrymanager.h"
+
+#include "citygml/geometry.h"
+#include "citygml/implictgeometry.h"
+#include "citygml/citygmllogger.h"
+
+namespace citygml {
+
+    GeometryManager::GeometryManager(std::shared_ptr<CityGMLLogger> logger)
+    {
+        m_logger = logger;
+    }
+
+    void GeometryManager::addSharedGeometry(std::shared_ptr<Geometry> 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()
+    {
+
+    }
+
+
+}
diff --git a/sources/src/citygml/georeferencedtexture.cpp b/sources/src/citygml/georeferencedtexture.cpp
new file mode 100644
index 0000000..be8aba0
--- /dev/null
+++ b/sources/src/citygml/georeferencedtexture.cpp
@@ -0,0 +1,40 @@
+#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<Texture> GeoreferencedTexture::asTexture()
+    {
+        return std::static_pointer_cast<Texture>(shared_from_this());
+    }
+
+    std::shared_ptr<const Texture> GeoreferencedTexture::asTexture() const
+    {
+        return std::static_pointer_cast<const Texture>(shared_from_this());
+    }
+
+    std::shared_ptr<GeoreferencedTexture> GeoreferencedTexture::asGeoreferencedTexture()
+    {
+        return std::static_pointer_cast<GeoreferencedTexture>(shared_from_this());
+    }
+
+    std::shared_ptr<const GeoreferencedTexture> GeoreferencedTexture::asGeoreferencedTexture() const
+    {
+        return std::static_pointer_cast<const GeoreferencedTexture>(shared_from_this());
+    }
+
+}
diff --git a/sources/src/citygml/implictgeometry.cpp b/sources/src/citygml/implictgeometry.cpp
new file mode 100644
index 0000000..32b576f
--- /dev/null
+++ b/sources/src/citygml/implictgeometry.cpp
@@ -0,0 +1,56 @@
+#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<Geometry> 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;
+    }
+
+}
diff --git a/sources/src/citygml/linearring.cpp b/sources/src/citygml/linearring.cpp
new file mode 100644
index 0000000..45eb24a
--- /dev/null
+++ b/sources/src/citygml/linearring.cpp
@@ -0,0 +1,132 @@
+#include "citygml/linearring.h"
+#include "citygml/texturecoordinates.h"
+#include "citygml/texture.h"
+#include "citygml/texturetargetdefinition.h"
+#include "citygml/citygmllogger.h"
+#include <float.h>
+#include <assert.h>
+
+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<TVec3d>& LinearRing::getVertices()
+    {
+        return m_vertices;
+    }
+
+    void LinearRing::setVertices(std::vector<TVec3d> vertices)
+    {
+        m_vertices = vertices;
+    }
+
+    const std::vector<TVec3d>& LinearRing::getVertices() const
+    {
+        return m_vertices;
+    }
+
+    void LinearRing::removeDuplicateVertices(const std::vector<TextureTargetDefinition*>& targets, std::shared_ptr<CityGMLLogger> 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<TextureCoordinates*> coordinatesList;
+
+        bool textureCoordinatesVerticesMismatch = false;
+
+        for (auto& texTarget : targets) {
+
+            for (unsigned int i = 0; i < texTarget->getTextureCoordinatesCount(); i++) {
+                TextureCoordinates* 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 (TextureCoordinates* 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 (TextureCoordinates* 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() << " != " <<coordinates->getCoords().size() << ")");
+            }
+        }
+#endif
+    }
+
+    void LinearRing::forgetVertices()
+    {
+        m_vertices.clear();
+    }
+
+}
diff --git a/sources/src/citygml/material.cpp b/sources/src/citygml/material.cpp
new file mode 100644
index 0000000..08c2a42
--- /dev/null
+++ b/sources/src/citygml/material.cpp
@@ -0,0 +1,80 @@
+#include "citygml/material.h"
+
+namespace citygml {
+
+    Material::Material(const std::string& id) : Appearance( id, "Material" ), m_ambientIntensity( 0.f ), m_shininess( 0.f ), m_transparency( 0.f )
+    {
+
+    }
+
+    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> Material::asMaterial()
+    {
+        return std::static_pointer_cast<Material>(shared_from_this());
+    }
+
+    std::shared_ptr<const Material> Material::asMaterial() const
+    {
+        return std::static_pointer_cast<const Material>(shared_from_this());
+    }
+
+}
diff --git a/sources/src/citygml/materialtargetdefinition.cpp b/sources/src/citygml/materialtargetdefinition.cpp
new file mode 100644
index 0000000..24399e0
--- /dev/null
+++ b/sources/src/citygml/materialtargetdefinition.cpp
@@ -0,0 +1,10 @@
+#include "citygml/materialtargetdefinition.h"
+
+namespace citygml {
+
+    MaterialTargetDefinition::MaterialTargetDefinition(const std::string& targetID, std::shared_ptr<Material> appearance, const std::string& id) : AppearanceTargetDefinition(targetID, appearance, id)
+    {
+
+    }
+
+}
diff --git a/sources/src/citygml/object.cpp b/sources/src/citygml/object.cpp
new file mode 100644
index 0000000..94b9957
--- /dev/null
+++ b/sources/src/citygml/object.cpp
@@ -0,0 +1,53 @@
+#include "citygml/object.h"
+
+#include <sstream>
+#include <iostream>
+
+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();
+    }
+
+}
diff --git a/sources/src/citygml/polygon.cpp b/sources/src/citygml/polygon.cpp
new file mode 100644
index 0000000..2d2c5c6
--- /dev/null
+++ b/sources/src/citygml/polygon.cpp
@@ -0,0 +1,270 @@
+#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 <algorithm>
+#include <stdexcept>
+#include <assert.h>
+#include <stdexcept>
+
+#include <iostream>
+
+namespace citygml {
+
+    Polygon::Polygon(const std::string& id, std::shared_ptr<CityGMLLogger> logger)  : AppearanceTarget( id ), m_negNormal( false )
+    {
+        m_logger = logger;
+        m_finished = false;
+    }
+
+    const std::vector<TVec3d>& Polygon::getVertices() const
+    {
+        return m_vertices;
+    }
+
+    std::vector<TVec3d>& Polygon::getVertices()
+    {
+        return m_vertices;
+    }
+
+    const std::vector<unsigned int>& Polygon::getIndices() const
+    {
+        return m_indices;
+    }
+
+
+    const Material* Polygon::getMaterialFor(const std::string& theme, bool front) const
+    {
+        const MaterialTargetDefinition* targetDef = getMaterialTargetDefinitionForTheme(theme, front);
+        if (targetDef == nullptr) {
+            return nullptr;
+        }
+        return targetDef->getAppearance().get();
+    }
+
+    const Material* Polygon::getMaterialFor(const std::string& theme) const
+    {
+        const Material* result = getMaterialFor(theme, true);
+        if (result != nullptr) {
+            return result;
+        }
+        return getMaterialFor(theme, false);
+    }
+
+    const Texture* Polygon::getTextureFor(const std::string& theme, bool front) const
+    {
+        const TextureTargetDefinition* targetDef = getTextureTargetDefinitionForTheme(theme, front);
+        if (targetDef == nullptr) {
+            return nullptr;
+        }
+        return targetDef->getAppearance().get();
+    }
+
+    const Texture* Polygon::getTextureFor(const std::string& theme) const
+    {
+        const Texture* result = getTextureFor(theme, true);
+        if (result != nullptr) {
+            return result;
+        }
+        return getTextureFor(theme, false);
+    }
+
+    const std::vector<TVec2f> 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<TVec2f>();
+        }
+
+        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<const Texture> Polygon::getTextureForTheme(const std::string& theme, bool front) const
+    {
+        const TextureTargetDefinition* 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<CityGMLLogger> logger) {
+        std::vector<TextureTargetDefinition*> 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<LinearRing>& ring : m_interiorRings )
+        {
+            ring->removeDuplicateVertices( texTargetDefinitions, logger );
+        }
+    }
+
+    std::vector<TVec2f> Polygon::getTexCoordsForRingAndTheme(const LinearRing& ring, const std::string& theme, bool front) {
+
+        const TextureTargetDefinition* targetDef = getTextureTargetDefinitionForTheme(theme, front);
+
+        if (targetDef == nullptr) {
+            return std::vector<TVec2f>();
+        }
+
+        const TextureCoordinates* coords = targetDef->getTextureCoordinatesForID(ring.getId());
+
+        if (coords == nullptr || coords->getCoords().empty()) {
+            return std::vector<TVec2f>();
+        }
+
+        return coords->getCoords();
+    }
+
+    std::vector<std::vector<TVec2f>> Polygon::getTexCoordListsForRing(const LinearRing& ring, const std::vector<std::string>& themesFront, const std::vector<std::string>& themesBack) {
+        std::vector<std::vector<TVec2f>> 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<CityGMLLogger> logger)
+    {
+        TVec3d normal = computeNormal();
+
+        std::vector<std::string> themesFront = getAllTextureThemes(true);
+        std::vector<std::string> 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<LinearRing>& 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<std::vector<TVec2f>>& 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<CityGMLLogger> 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<CityGMLLogger> 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<LinearRing>(ring);
+        }
+        else {
+            m_interiorRings.push_back( std::unique_ptr<LinearRing>(ring) );
+        }
+    }
+
+    Polygon::~Polygon()
+    {
+    }
+
+}
diff --git a/sources/src/citygml/polygonmanager.cpp b/sources/src/citygml/polygonmanager.cpp
new file mode 100644
index 0000000..5340c1f
--- /dev/null
+++ b/sources/src/citygml/polygonmanager.cpp
@@ -0,0 +1,56 @@
+#include "citygml/polygonmanager.h"
+
+#include "citygml/polygon.h"
+#include "citygml/citygmllogger.h"
+#include "citygml/geometry.h"
+
+namespace citygml {
+
+    PolygonManager::PolygonManager(std::shared_ptr<CityGMLLogger> logger)
+    {
+        m_logger = logger;
+    }
+
+    void PolygonManager::addPolygon(std::shared_ptr<Polygon> 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()
+    {
+
+    }
+
+
+}
diff --git a/sources/src/citygml/tesselator.cpp b/sources/src/citygml/tesselator.cpp
new file mode 100644
index 0000000..7b85bc8
--- /dev/null
+++ b/sources/src/citygml/tesselator.cpp
@@ -0,0 +1,232 @@
+/* -*-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 <stdint.h>
+#endif
+
+#include <citygml/citygml.h>
+#include <citygml/citygmllogger.h>
+
+#include <iostream>
+#include <assert.h>
+
+Tesselator::Tesselator(std::shared_ptr<citygml::CityGMLLogger> 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<TVec3d> Tesselator::getVertices() const
+{
+    return std::vector<TVec3d>(_vertices.begin(), _vertices.end());
+}
+
+const std::vector<unsigned int>& Tesselator::getIndices() const
+{
+    return _outIndices;
+}
+
+void Tesselator::addContour(const std::vector<TVec3d>& pts, std::vector<std::vector<TVec2f>> textureCoordinatesLists )
+{
+    unsigned int len = pts.size();
+    if ( len < 3 ) return;
+
+    for (size_t i = 0; i < textureCoordinatesLists.size(); i++) {
+
+        std::vector<TVec2f>& 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<TVec2f> 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<Tesselator*>(userData);
+    tess->_curMode = which;
+}
+
+void CALLBACK Tesselator::vertexDataCallback( GLvoid *data, void* userData )
+{
+    Tesselator *tess = static_cast<Tesselator*>(userData);
+    unsigned int index = *reinterpret_cast<unsigned int*>(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<Tesselator*>(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<TVec2f>& 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<unsigned int*>(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<Tesselator*>(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<Tesselator*>(userData);
+    CITYGML_LOG_ERROR(tess->_logger, "Tesselator error: " << gluErrorString( errorCode ));
+}
diff --git a/sources/src/citygml/texture.cpp b/sources/src/citygml/texture.cpp
new file mode 100644
index 0000000..42b7dd8
--- /dev/null
+++ b/sources/src/citygml/texture.cpp
@@ -0,0 +1,95 @@
+#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> Texture::asTexture()
+    {
+        return std::static_pointer_cast<Texture>(shared_from_this());
+    }
+
+    std::shared_ptr<const Texture> Texture::asTexture() const
+    {
+        return std::static_pointer_cast<const Texture>(shared_from_this());
+    }
+
+    Texture::~Texture()
+    {
+    }
+
+
+}
diff --git a/sources/src/citygml/texturecoordinates.cpp b/sources/src/citygml/texturecoordinates.cpp
new file mode 100644
index 0000000..dea3397
--- /dev/null
+++ b/sources/src/citygml/texturecoordinates.cpp
@@ -0,0 +1,40 @@
+#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<TVec2f>& TextureCoordinates::getCoords() const
+    {
+        return m_coordlist;
+    }
+
+    void TextureCoordinates::setCoords(std::vector<TVec2f> texCoords)
+    {
+        m_coordlist = texCoords;
+    }
+
+}
diff --git a/sources/src/citygml/texturetargetdefinition.cpp b/sources/src/citygml/texturetargetdefinition.cpp
new file mode 100644
index 0000000..65b9d97
--- /dev/null
+++ b/sources/src/citygml/texturetargetdefinition.cpp
@@ -0,0 +1,54 @@
+#include "citygml/texturetargetdefinition.h"
+#include "citygml/texturecoordinates.h"
+
+namespace citygml {
+
+    TextureTargetDefinition::TextureTargetDefinition(const std::string& targetID, std::shared_ptr<Texture> appearance, const std::string& id) : AppearanceTargetDefinition(targetID, appearance, id)
+    {
+    }
+
+    unsigned int TextureTargetDefinition::getTextureCoordinatesCount() const
+    {
+        return m_coordinatesList.size();
+    }
+
+    TextureCoordinates* TextureTargetDefinition::getTextureCoordinates(unsigned int i)
+    {
+        return m_coordinatesList.at(i).get();
+    }
+
+    const TextureCoordinates*TextureTargetDefinition::getTextureCoordinates(unsigned int i) const
+    {
+        return m_coordinatesList.at(i).get();
+    }
+
+    TextureCoordinates* TextureTargetDefinition::getTextureCoordinatesForID(const std::string& ringID)
+    {
+        auto it = m_idTexCoordMap.find(ringID);
+        if (it != m_idTexCoordMap.end()) {
+            return it->second;
+        }
+        return nullptr;
+    }
+
+    const TextureCoordinates* 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(TextureCoordinates* texCoords)
+    {
+        m_coordinatesList.push_back(std::unique_ptr<TextureCoordinates>(texCoords));
+        m_idTexCoordMap[texCoords->getTargetLinearRingID()] = texCoords;
+    }
+
+    TextureTargetDefinition::~TextureTargetDefinition()
+    {
+
+    }
+
+}
diff --git a/sources/src/citygml/transformmatrix.cpp b/sources/src/citygml/transformmatrix.cpp
new file mode 100644
index 0000000..85d2afa
--- /dev/null
+++ b/sources/src/citygml/transformmatrix.cpp
@@ -0,0 +1,43 @@
+#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()
+    {
+
+    }
+
+}
diff --git a/sources/src/parser/appearanceelementparser.cpp b/sources/src/parser/appearanceelementparser.cpp
new file mode 100644
index 0000000..7e2ff36
--- /dev/null
+++ b/sources/src/parser/appearanceelementparser.cpp
@@ -0,0 +1,120 @@
+#include "parser/appearanceelementparser.h"
+
+#include <unordered_map>
+#include <functional>
+
+#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 "citygml/appearance.h"
+#include "citygml/texture.h"
+#include "citygml/material.h"
+#include "citygml/georeferencedtexture.h"
+#include "citygml/citygmlfactory.h"
+#include "citygml/citygmllogger.h"
+
+#include <stdexcept>
+
+namespace citygml {
+
+    AppearanceElementParser::AppearanceElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger)
+        : CityGMLElementParser(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.");
+        }
+        return true;
+    }
+
+    bool AppearanceElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&)
+    {
+        if (m_theme.empty()) {
+            CITYGML_LOG_ERROR(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<Appearance>& 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<Appearance> 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<void(std::shared_ptr<Appearance>)> callback = [this] (std::shared_ptr<Appearance> surfacedata) {
+                    this->m_surfaceDataList.push_back(surfacedata);
+                };
+
+                std::vector<ElementParser*> 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 false;
+    }
+
+    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 false;
+    }
+
+
+
+
+}
diff --git a/sources/src/parser/attributes.cpp b/sources/src/parser/attributes.cpp
new file mode 100644
index 0000000..a207751
--- /dev/null
+++ b/sources/src/parser/attributes.cpp
@@ -0,0 +1,31 @@
+#include "parser/attributes.h"
+#include "parser/parserutils.hpp"
+#include "parser/documentlocation.h"
+
+#include "citygml/citygmllogger.h"
+
+namespace citygml {
+
+    Attributes::Attributes(std::shared_ptr<CityGMLLogger> logger)
+    {
+        m_logger = logger;
+    }
+
+    std::string Attributes::getCityGMLIDAttribute() const
+    {
+        return getAttribute("gml:id", "");
+    }
+
+    bool Attributes::hasXLinkAttribute() const
+    {
+        return !getAttribute("xlink:href", "").empty();
+    }
+
+    std::string Attributes::getXLinkValue()
+    {
+        return parseReference(getAttribute("xlink:href", ""), m_logger, getDocumentLocation());
+    }
+
+
+
+}
diff --git a/sources/src/parser/citygmldocumentparser.cpp b/sources/src/parser/citygmldocumentparser.cpp
new file mode 100644
index 0000000..a792d39
--- /dev/null
+++ b/sources/src/parser/citygmldocumentparser.cpp
@@ -0,0 +1,187 @@
+#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 <stdexcept>
+
+namespace citygml {
+
+    CityGMLDocumentParser::CityGMLDocumentParser(const ParserParams& params, std::shared_ptr<CityGMLLogger> logger)
+    {
+        m_logger = logger;
+        m_factory = std::unique_ptr<CityGMLFactory>(new CityGMLFactory(logger));
+        m_parserParams = params;
+        m_activeParser = nullptr;
+        m_currentElementUnknownOrUnexpected = false;
+        m_unknownElementOrUnexpectedElementDepth = 0;
+        m_unknownElementOrUnexpectedElementName = "";
+    }
+
+    std::shared_ptr<const CityModel> CityGMLDocumentParser::getModel()
+    {
+        return m_rootModel;
+    }
+
+    void CityGMLDocumentParser::setCurrentElementParser(ElementParser* parser)
+    {
+        m_parserStack.push(std::shared_ptr<ElementParser>(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<CityModelElementParser>(new CityModelElementParser(*this, *m_factory, m_logger, [this](CityModel* cityModel) {
+                this->m_rootModel = std::unique_ptr<CityModel>(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()
+    {
+
+    }
+
+}
diff --git a/sources/src/parser/citygmlelementparser.cpp b/sources/src/parser/citygmlelementparser.cpp
new file mode 100644
index 0000000..16e93d7
--- /dev/null
+++ b/sources/src/parser/citygmlelementparser.cpp
@@ -0,0 +1,57 @@
+#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 <stdexcept>
+
+namespace citygml {
+
+    CityGMLElementParser::CityGMLElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> 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.: <surfaceMember xlink:href="#..."/>
+            // 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()
+    {
+
+    }
+
+}
diff --git a/sources/src/parser/citymodelelementparser.cpp b/sources/src/parser/citymodelelementparser.cpp
new file mode 100644
index 0000000..9d2b135
--- /dev/null
+++ b/sources/src/parser/citymodelelementparser.cpp
@@ -0,0 +1,100 @@
+#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 <stdexcept>
+
+namespace citygml {
+
+    CityModelElementParser::CityModelElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void (CityModel*)> 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;
+    }
+
+}
diff --git a/sources/src/parser/cityobjectelementparser.cpp b/sources/src/parser/cityobjectelementparser.cpp
new file mode 100644
index 0000000..3445fb0
--- /dev/null
+++ b/sources/src/parser/cityobjectelementparser.cpp
@@ -0,0 +1,377 @@
+#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 "citygml/citygmlfactory.h"
+#include "citygml/citygmllogger.h"
+
+#include <stdexcept>
+
+namespace citygml {
+
+    bool CityObjectElementParser::typeIDTypeMapInitialized = false;
+    bool CityObjectElementParser::attributesSetInitialized = false;
+
+    std::unordered_map<int, CityObject::CityObjectsType> CityObjectElementParser::typeIDTypeMap = std::unordered_map<int, CityObject::CityObjectsType>();
+    std::unordered_set<int> CityObjectElementParser::attributesSet = std::unordered_set<int>();
+
+    std::mutex CityObjectElementParser::initializedTypeIDMutex;
+    std::mutex CityObjectElementParser::initializedAttributeSetMutex;
+
+    #define HANDLE_TYPE( prefix, elementName ) std::pair<int, CityObject::CityObjectsType>(NodeType::prefix ## _ ## elementName ## Node.typeID(), CityObject::COT_ ## elementName)
+    #define HANDLE_ATTR( prefix, elementName ) NodeType::prefix ## _ ## elementName ## Node.typeID()
+
+    CityObjectElementParser::CityObjectElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void (CityObject*)> 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<std::mutex> 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_TYPE(VEG, PlantCover));
+                typeIDTypeMap.insert(HANDLE_TYPE(VEG, SolitaryVegetationObject));
+                typeIDTypeMap.insert(HANDLE_TYPE(WTR, WaterBody));
+                typeIDTypeMap.insert(HANDLE_TYPE(LUSE, TINRelief));
+                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));
+
+                typeIDTypeMapInitialized = true;
+            }
+        }
+    }
+
+    void CityObjectElementParser::initializeAttributesSet()
+    {
+        // double-checked lock
+        if (!attributesSetInitialized) {
+            std::lock_guard<std::mutex> 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, StoreysBelowGround));
+                attributesSet.insert(HANDLE_ATTR(BLDG, MeasuredHeight));
+                attributesSet.insert(HANDLE_ATTR(BLDG, Address));
+                attributesSet.insert(HANDLE_ATTR(BLDG, RoofType));
+                attributesSet.insert(HANDLE_ATTR(XAL, XalAddress));
+                attributesSet.insert(HANDLE_ATTR(XAL, Administrativearea));
+                attributesSet.insert(HANDLE_ATTR(XAL, Country));
+                attributesSet.insert(HANDLE_ATTR(XAL, CountryName));
+                attributesSet.insert(HANDLE_ATTR(XAL, Code));
+                attributesSet.insert(HANDLE_ATTR(XAL, Street));
+                attributesSet.insert(HANDLE_ATTR(XAL, PostalCode));
+                attributesSet.insert(HANDLE_ATTR(XAL, City));
+                attributesSet.insert(HANDLE_ATTR(XAL, LocalityName));
+                attributesSet.insert(HANDLE_ATTR(XAL, Thoroughfare));
+                attributesSet.insert(HANDLE_ATTR(XAL, ThoroughfareNumber));
+                attributesSet.insert(HANDLE_ATTR(XAL, ThoroughfareName));
+                attributesSet.insert(HANDLE_ATTR(XAL, Locality));
+                attributesSet.insert(HANDLE_ATTR(XAL, AddressDetails));
+                attributesSet.insert(HANDLE_ATTR(XAL, DependentLocalityName));
+
+                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<CityObject::CityObjectsType>(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) {
+            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_Lod1GeometryNode
+                   || node == NodeType::BLDG_Lod1MultiCurveNode
+                   || node == NodeType::BLDG_Lod1MultiSurfaceNode
+                   || node == NodeType::BLDG_Lod1SolidNode
+                   || node == NodeType::BLDG_Lod1TerrainIntersectionNode
+                   || node == NodeType::GEN_Lod1GeometryNode
+                   || node == NodeType::GEN_Lod1TerrainIntersectionNode
+                   || node == NodeType::FRN_Lod1GeometryNode
+                   || node == NodeType::FRN_Lod1TerrainIntersectionNode) {
+
+            parseGeometryForLODLevel(1);
+        } else if (node == NodeType::BLDG_Lod2GeometryNode
+                   || node == NodeType::BLDG_Lod2MultiCurveNode
+                   || node == NodeType::BLDG_Lod2MultiSurfaceNode
+                   || node == NodeType::BLDG_Lod2SolidNode
+                   || node == NodeType::BLDG_Lod2TerrainIntersectionNode
+                   || node == NodeType::GEN_Lod2GeometryNode
+                   || node == NodeType::GEN_Lod2TerrainIntersectionNode
+                   || node == NodeType::FRN_Lod2GeometryNode
+                   || node == NodeType::FRN_Lod2TerrainIntersectionNode) {
+
+            parseGeometryForLODLevel(2);
+        } else if (node == NodeType::BLDG_Lod3GeometryNode
+                   || node == NodeType::BLDG_Lod3MultiCurveNode
+                   || node == NodeType::BLDG_Lod3MultiSurfaceNode
+                   || node == NodeType::BLDG_Lod3SolidNode
+                   || node == NodeType::BLDG_Lod3TerrainIntersectionNode
+                   || node == NodeType::GEN_Lod3GeometryNode
+                   || node == NodeType::GEN_Lod3TerrainIntersectionNode
+                   || node == NodeType::FRN_Lod3GeometryNode
+                   || node == NodeType::FRN_Lod3TerrainIntersectionNode) {
+
+            parseGeometryForLODLevel(3);
+        } else if (node == NodeType::BLDG_Lod4GeometryNode
+                   || node == NodeType::BLDG_Lod4MultiCurveNode
+                   || node == NodeType::BLDG_Lod4MultiSurfaceNode
+                   || node == NodeType::BLDG_Lod4SolidNode
+                   || node == NodeType::BLDG_Lod4TerrainIntersectionNode
+                   || node == NodeType::GEN_Lod4GeometryNode
+                   || node == NodeType::GEN_Lod4TerrainIntersectionNode
+                   || node == NodeType::FRN_Lod4GeometryNode
+                   || node == NodeType::FRN_Lod4TerrainIntersectionNode) {
+
+            parseGeometryForLODLevel(4);
+        } else if (node == NodeType::VEG_Lod1ImplicitRepresentationNode
+                   || node == NodeType::FRN_Lod1ImplicitRepresentationNode) {
+
+            parseImplicitGeometryForLODLevel(1);
+        } else if (node == NodeType::VEG_Lod2ImplicitRepresentationNode
+                   || node == NodeType::FRN_Lod2ImplicitRepresentationNode) {
+
+            parseImplicitGeometryForLODLevel(2);
+        } else if (node == NodeType::VEG_Lod3ImplicitRepresentationNode
+                   || node == NodeType::FRN_Lod3ImplicitRepresentationNode) {
+
+            parseImplicitGeometryForLODLevel(3);
+        } else if (node == NodeType::VEG_Lod4ImplicitRepresentationNode
+                   || node == NodeType::FRN_Lod4ImplicitRepresentationNode) {
+
+            parseImplicitGeometryForLODLevel(4);
+        } else if (node == NodeType::BLDG_ExternalReferenceNode
+                   || node == NodeType::BLDG_InformationSystemNode
+                   || node == NodeType::BLDG_ExternalObjectNode
+                   || node == NodeType::BLDG_UriNode) {
+            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_Lod1GeometryNode
+                    || 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::VEG_Lod1ImplicitRepresentationNode
+                    || node == NodeType::VEG_Lod2ImplicitRepresentationNode
+                    || node == NodeType::VEG_Lod3ImplicitRepresentationNode
+                    || node == NodeType::VEG_Lod4ImplicitRepresentationNode
+                    || node == NodeType::BLDG_ExternalReferenceNode
+                    || node == NodeType::BLDG_InformationSystemNode
+                    || node == NodeType::BLDG_ExternalObjectNode
+                    || node == NodeType::BLDG_UriNode
+                    || 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) {
+
+            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);
+        }));
+    }
+
+}
diff --git a/sources/src/parser/delayedchoiceelementparser.cpp b/sources/src/parser/delayedchoiceelementparser.cpp
new file mode 100644
index 0000000..ebba494
--- /dev/null
+++ b/sources/src/parser/delayedchoiceelementparser.cpp
@@ -0,0 +1,74 @@
+#include "parser/delayedchoiceelementparser.h"
+
+#include "parser/documentlocation.h"
+#include "parser/citygmldocumentparser.h"
+
+#include "citygml/citygmllogger.h"
+
+#include <sstream>
+#include <stdexcept>
+
+namespace citygml {
+
+    DelayedChoiceElementParser::DelayedChoiceElementParser(CityGMLDocumentParser& documentParser, std::shared_ptr<CityGMLLogger> logger, std::vector<ElementParser*> 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();
+    }
+
+}
diff --git a/sources/src/parser/elementparser.cpp b/sources/src/parser/elementparser.cpp
new file mode 100644
index 0000000..ecc7986
--- /dev/null
+++ b/sources/src/parser/elementparser.cpp
@@ -0,0 +1,21 @@
+#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()
+    {
+
+    }
+}
diff --git a/sources/src/parser/geocoordinatetransformer.cpp b/sources/src/parser/geocoordinatetransformer.cpp
new file mode 100644
index 0000000..36f23a4
--- /dev/null
+++ b/sources/src/parser/geocoordinatetransformer.cpp
@@ -0,0 +1,280 @@
+#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/vecs.hpp"
+#include "citygml/envelope.h"
+
+#ifdef USE_GDAL
+#include "ogrsf_frmts.h"
+
+#include <stdexcept>
+
+class GeoTransform
+{
+public:
+    GeoTransform( const std::string& destURN, std::shared_ptr<citygml::CityGMLLogger> 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<citygml::CityGMLLogger> m_logger;
+};
+
+namespace citygml {
+
+    GeoCoordinateTransformer::GeoCoordinateTransformer(const std::string& destSRS, std::shared_ptr<CityGMLLogger> 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++) {
+
+            Polygon& poly = obj.getPolygon(i);
+
+            auto it = m_transformedPolygonsSourceURNMap.find(poly.getId());
+
+            if (it == m_transformedPolygonsSourceURNMap.end()) {
+
+                for (TVec3d& vertex : poly.getVertices()) {
+                    transformation.transform(vertex);
+                }
+
+                m_transformedPolygonsSourceURNMap[poly.getId()] = 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.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
+
+
+
+
diff --git a/sources/src/parser/geometryelementparser.cpp b/sources/src/parser/geometryelementparser.cpp
new file mode 100644
index 0000000..11ad015
--- /dev/null
+++ b/sources/src/parser/geometryelementparser.cpp
@@ -0,0 +1,167 @@
+#include "parser/geometryelementparser.h"
+
+#include <unordered_set>
+
+#include "parser/nodetypes.h"
+#include "parser/attributes.h"
+#include "parser/documentlocation.h"
+#include "parser/polygonelementparser.h"
+#include "parser/delayedchoiceelementparser.h"
+
+#include "citygml/geometry.h"
+#include "citygml/citygmlfactory.h"
+#include "citygml/citygmllogger.h"
+#include "citygml/polygon.h"
+
+#include <stdexcept>
+
+namespace citygml {
+
+
+    // The nodes that are valid Geometry Objects
+    std::unordered_set<int> geometryTypeIDSet;
+    bool geometryTypeIDSetInitialized = false;
+
+    GeometryElementParser::GeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger,
+                                                 int lodLevel, CityObject::CityObjectsType parentType,  std::function<void(Geometry*)> callback)
+        : CityGMLElementParser(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) {
+            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());
+            geometryTypeIDSetInitialized = true;
+        }
+
+        return geometryTypeIDSet.count(node.typeID()) > 0;
+    }
+
+    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;
+        }
+
+    }
+
+    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(), mapCityObjectsTypeToGeometryType(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
+                   || node == NodeType::GML_PatchesNode
+                   || node == NodeType::GML_TrianglePatchesNode) {
+
+            if (attributes.hasXLinkAttribute()) {
+                m_factory.requestSharedPolygonForGeometry(m_model, attributes.getXLinkValue());
+            } else {
+                std::vector<ElementParser*> parsers;
+
+                std::function<void(std::shared_ptr<Polygon>)> callback1 = [this](std::shared_ptr<Polygon> poly) {m_model->addPolygon(poly);};
+                std::function<void(Geometry*)>                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;
+        }
+
+        return false;
+    }
+
+    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 false;
+
+    }
+
+}
diff --git a/sources/src/parser/georeferencedtextureelementparser.cpp b/sources/src/parser/georeferencedtextureelementparser.cpp
new file mode 100644
index 0000000..3e14aeb
--- /dev/null
+++ b/sources/src/parser/georeferencedtextureelementparser.cpp
@@ -0,0 +1,64 @@
+#include "parser/georeferencedtextureelementparser.h"
+
+#include <unordered_map>
+
+#include "parser/nodetypes.h"
+#include "parser/attributes.h"
+#include "parser/documentlocation.h"
+
+#include "citygml/georeferencedtexture.h"
+#include "citygml/citygmlfactory.h"
+#include "citygml/citygmllogger.h"
+
+#include <stdexcept>
+
+namespace citygml {
+
+    GeoReferencedTextureElementParser::GeoReferencedTextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger,
+                                                                         std::function<void (std::shared_ptr<GeoreferencedTexture>)> 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.");
+        }
+        return true;
+    }
+
+    bool GeoReferencedTextureElementParser::parseElementEndTag(const NodeType::XMLNode&, const std::string&)
+    {
+        // Not Implemented
+        return false;
+    }
+
+    bool GeoReferencedTextureElementParser::parseChildElementStartTag(const NodeType::XMLNode&, Attributes&)
+    {
+        // Not Implemented
+        return false;
+    }
+
+    bool GeoReferencedTextureElementParser::parseChildElementEndTag(const NodeType::XMLNode&, const std::string&)
+    {
+        // Not Implemented
+        return false;
+    }
+
+
+
+
+}
diff --git a/sources/src/parser/gmlfeaturecollectionparser.cpp b/sources/src/parser/gmlfeaturecollectionparser.cpp
new file mode 100644
index 0000000..a0e6920
--- /dev/null
+++ b/sources/src/parser/gmlfeaturecollectionparser.cpp
@@ -0,0 +1,95 @@
+#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 <stdexcept>
+
+namespace citygml {
+
+    GMLFeatureCollectionElementParser::GMLFeatureCollectionElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger)
+        : CityGMLElementParser(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_DescriptionNode
+            || node == NodeType::GML_IdentifierNode
+            || node == NodeType::GML_NameNode
+            || node == NodeType::GML_DescriptionReferenceNode
+            || 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 false;
+    }
+
+    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_DescriptionNode
+            || node == NodeType::GML_IdentifierNode
+            || node == NodeType::GML_NameNode
+            || node == NodeType::GML_DescriptionReferenceNode) {
+
+                getFeatureObject()->setAttribute(node.name(), characters);
+                return true;
+        } else if (node == NodeType::GML_LowerCornerNode) {
+
+            if (m_bounds != nullptr) {
+                m_bounds->setLowerBound(parseValue<TVec3d>(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->setLowerBound(parseValue<TVec3d>(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 false;
+    }
+
+
+
+}
diff --git a/sources/src/parser/implicitgeometryelementparser.cpp b/sources/src/parser/implicitgeometryelementparser.cpp
new file mode 100644
index 0000000..5d37387
--- /dev/null
+++ b/sources/src/parser/implicitgeometryelementparser.cpp
@@ -0,0 +1,129 @@
+#include "parser/implicitgeometryelementparser.h"
+
+#include <unordered_set>
+
+#include "parser/nodetypes.h"
+#include "parser/attributes.h"
+#include "parser/documentlocation.h"
+#include "parser/geometryelementparser.h"
+#include "parser/parserutils.hpp"
+
+#include "citygml/implictgeometry.h"
+#include "citygml/citygmlfactory.h"
+#include "citygml/citygmllogger.h"
+
+#include <stdexcept>
+
+namespace citygml {
+
+
+    ImplicitGeometryElementParser::ImplicitGeometryElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger,
+                                                 int lodLevel, CityObject::CityObjectsType parentType,  std::function<void(ImplicitGeometry*)> callback)
+        : CityGMLElementParser(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::GML_ReferencePointNode) {
+
+            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 {
+
+                setParserForNextElement(new GeometryElementParser(m_documentParser, m_factory, m_logger, m_lodLevel, m_parentType, [this](Geometry* geom) {
+                                        std::shared_ptr<Geometry> shared = m_factory.shareGeometry(geom);
+                                        m_model->addGeometry(shared);
+                                    }));
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    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<TVec3d>(characters, m_logger, getDocumentLocation()));
+            return true;
+        } else if (   node == NodeType::CORE_RelativeGMLGeometryNode
+                   || node == NodeType::GML_PointNode
+                   || node == NodeType::GML_ReferencePointNode) {
+
+            return true;
+        }
+
+        return false;
+
+    }
+
+}
diff --git a/sources/src/parser/linearringelementparser.cpp b/sources/src/parser/linearringelementparser.cpp
new file mode 100644
index 0000000..13ba822
--- /dev/null
+++ b/sources/src/parser/linearringelementparser.cpp
@@ -0,0 +1,95 @@
+#include "parser/linearringelementparser.h"
+
+#include <unordered_map>
+
+#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 <stdexcept>
+
+namespace citygml {
+
+    LinearRingElementParser::LinearRingElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, bool interior, std::function<void(LinearRing*)> callback)
+        : CityGMLElementParser(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 false;
+    }
+
+    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<TVec3d>(characters, m_logger, getDocumentLocation()));
+            return true;
+        } else if (node == NodeType::GML_PosNode) {
+            m_model->addVertex(parseValue<TVec3d>(characters, m_logger, getDocumentLocation()));
+            return true;
+        }
+
+        return false;
+
+    }
+
+}
diff --git a/sources/src/parser/materialelementparser.cpp b/sources/src/parser/materialelementparser.cpp
new file mode 100644
index 0000000..31428f9
--- /dev/null
+++ b/sources/src/parser/materialelementparser.cpp
@@ -0,0 +1,119 @@
+#include "parser/materialelementparser.h"
+
+#include <unordered_map>
+
+#include "parser/nodetypes.h"
+#include "parser/attributes.h"
+#include "parser/documentlocation.h"
+#include "parser/parserutils.hpp"
+
+#include "citygml/material.h"
+#include "citygml/citygmlfactory.h"
+#include "citygml/citygmllogger.h"
+
+#include <stdexcept>
+
+namespace citygml {
+
+    MaterialElementParser::MaterialElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(std::shared_ptr<Material>)> callback)
+        : CityGMLElementParser(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<Material>(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::GML_NameNode
+            || 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) {
+            return true;
+        } else if (node == NodeType::APP_TargetNode) {
+            m_lastTargetDefinitionID = attributes.getCityGMLIDAttribute();
+            return true;
+        }
+
+        return false;
+    }
+
+    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::GML_NameNode) {
+
+            m_model->setAttribute(node.name(), characters);
+        } else if (node == NodeType::APP_DiffuseColorNode) {
+
+            m_model->setDiffuse(parseValue<TVec3f>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_EmissiveColorNode) {
+
+            m_model->setEmissive(parseValue<TVec3f>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_SpecularColorNode) {
+
+            m_model->setSpecular(parseValue<TVec3f>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_ShininessNode) {
+
+            m_model->setShininess(parseValue<float>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_TransparencyNode) {
+
+            m_model->setTransparency(parseValue<float>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_AmbientIntensityNode) {
+
+            m_model->setAmbientIntensity(parseValue<float>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_IsFrontNode) {
+
+            m_model->setIsFront(parseValue<bool>(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 false;
+        }
+        return true;
+    }
+
+
+
+
+}
diff --git a/sources/src/parser/nodetypes.cpp b/sources/src/parser/nodetypes.cpp
new file mode 100644
index 0000000..5e5dcde
--- /dev/null
+++ b/sources/src/parser/nodetypes.cpp
@@ -0,0 +1,592 @@
+#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<std::string, NodeType::XMLNode*> NodeType::nodeNameTypeMap;
+    std::unordered_map<std::string, NodeType::XMLNode*> 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_name;
+    }
+
+    const std::string&NodeType::XMLNode::prefix() const
+    {
+        return m_prefix;
+    }
+
+    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();
+    }
+
+#define INITIALIZE_NODE( prefix, elementname ) \
+    NodeType::prefix ## _ ## elementname ## Node = XMLNode( #prefix , #elementname ); \
+    NodeType::nodeNameTypeMap[toLower(#elementname)] = &NodeType::prefix ## _ ## elementname ## Node; \
+    NodeType::nodeNameWithPrefixTypeMap[toLower(#prefix) + ":" + toLower(#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<std::mutex> 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, ImplicitGeometry )
+                INITIALIZE_NODE( CORE, RelativeGMLGeometry )
+                INITIALIZE_NODE( CORE, TransformationMatrix )
+
+                // GRP
+                INITIALIZE_NODE( GRP, CityObjectGroup )
+                INITIALIZE_NODE( GRP, GroupMember )
+
+                // GEN
+                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, Lod1Geometry )
+                INITIALIZE_NODE( GEN, Lod2Geometry )
+                INITIALIZE_NODE( GEN, Lod3Geometry )
+                INITIALIZE_NODE( GEN, Lod4Geometry )
+                INITIALIZE_NODE( GEN, Lod1TerrainIntersection )
+                INITIALIZE_NODE( GEN, Lod2TerrainIntersection )
+                INITIALIZE_NODE( GEN, Lod3TerrainIntersection )
+                INITIALIZE_NODE( GEN, Lod4TerrainIntersection )
+
+                // 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, 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( BLDG, Lod1Solid )
+                INITIALIZE_NODE( BLDG, Lod2Solid )
+                INITIALIZE_NODE( BLDG, Lod3Solid )
+                INITIALIZE_NODE( BLDG, Lod4Solid )
+                INITIALIZE_NODE( BLDG, Lod1Geometry )
+                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, Address )
+                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, 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, ExternalReference)
+                INITIALIZE_NODE( BLDG, InformationSystem)
+                INITIALIZE_NODE( BLDG, ExternalObject)
+                INITIALIZE_NODE( BLDG, Uri)
+
+                INITIALIZE_NODE( BLDG, CityFurniture )
+
+                // ADDRESS
+                INITIALIZE_NODE( XAL, XalAddress )
+                INITIALIZE_NODE( XAL, Administrativearea )
+                INITIALIZE_NODE( XAL, Country )
+                INITIALIZE_NODE( XAL, CountryName )
+                INITIALIZE_NODE( XAL, Code )
+                INITIALIZE_NODE( XAL, Street )
+                INITIALIZE_NODE( XAL, PostalCode )
+                INITIALIZE_NODE( XAL, City )
+                INITIALIZE_NODE( XAL, LocalityName )
+                INITIALIZE_NODE( XAL, Thoroughfare )
+                INITIALIZE_NODE( XAL, ThoroughfareNumber )
+                INITIALIZE_NODE( XAL, ThoroughfareName )
+                INITIALIZE_NODE( XAL, Locality )
+                INITIALIZE_NODE( XAL, AddressDetails )
+                INITIALIZE_NODE( XAL, DependentLocalityName )
+                // WTR
+                INITIALIZE_NODE( WTR, WaterBody )
+
+                // VEG
+                INITIALIZE_NODE( VEG, PlantCover )
+                INITIALIZE_NODE( VEG, SolitaryVegetationObject )
+                INITIALIZE_NODE( VEG, Species )
+                INITIALIZE_NODE( VEG, Lod1ImplicitRepresentation )
+                INITIALIZE_NODE( VEG, Lod2ImplicitRepresentation )
+                INITIALIZE_NODE( VEG, Lod3ImplicitRepresentation )
+                INITIALIZE_NODE( VEG, Lod4ImplicitRepresentation )
+
+                // TRANS
+                INITIALIZE_NODE( TRANS, TrafficArea )
+                INITIALIZE_NODE( TRANS, AuxiliaryTrafficArea )
+                INITIALIZE_NODE( TRANS, Track )
+                INITIALIZE_NODE( TRANS, Road )
+                INITIALIZE_NODE( TRANS, Railway )
+                INITIALIZE_NODE( TRANS, Square )
+
+                // LUSE
+                INITIALIZE_NODE( LUSE, LandUse )
+
+                // dem
+                INITIALIZE_NODE( LUSE, Lod )
+                INITIALIZE_NODE( LUSE, TINRelief )
+
+                // 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, 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 = name.find_first_of( ":" );
+        if ( pos != std::string::npos ) {
+            nodeName = name.substr(pos);
+        }
+
+        auto it = nodeNameTypeMap.find(nodeName);
+
+        if (it == nodeNameTypeMap.end()) {
+            return InvalidNode;
+        } else {
+            return *it->second;
+        }
+    }
+
+    std::ostream& operator<<(std::ostream& os, const NodeType::XMLNode& o)
+    {
+        if (!o.valid()) {
+            os << "InvalidNode";
+        } else {
+            if (!o.prefix().empty()) {
+                os << o.prefix() << ":";
+            }
+            os << o.name();
+        }
+
+        return os;
+    }
+
+    const NodeType::XMLNode NodeType::InvalidNode = XMLNode("", "");
+
+#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, ImplicitGeometry )
+    DEFINE_NODE( CORE, RelativeGMLGeometry )
+    DEFINE_NODE( CORE, TransformationMatrix )
+
+    // GRP
+    DEFINE_NODE( GRP, CityObjectGroup )
+    DEFINE_NODE( GRP, GroupMember )
+
+    // GEN
+    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, Lod1Geometry )
+    DEFINE_NODE( GEN, Lod2Geometry )
+    DEFINE_NODE( GEN, Lod3Geometry )
+    DEFINE_NODE( GEN, Lod4Geometry )
+    DEFINE_NODE( GEN, Lod1TerrainIntersection )
+    DEFINE_NODE( GEN, Lod2TerrainIntersection )
+    DEFINE_NODE( GEN, Lod3TerrainIntersection )
+    DEFINE_NODE( GEN, Lod4TerrainIntersection )
+
+    // 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, 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, Lod1Geometry )
+    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 )
+
+    // 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, Address )
+    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, 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, ExternalReference)
+    DEFINE_NODE( BLDG, InformationSystem)
+    DEFINE_NODE( BLDG, ExternalObject)
+    DEFINE_NODE( BLDG, Uri)
+
+    DEFINE_NODE( BLDG, CityFurniture )
+
+    // ADDRESS
+    DEFINE_NODE( XAL, XalAddress )
+    DEFINE_NODE( XAL, Administrativearea )
+    DEFINE_NODE( XAL, Country )
+    DEFINE_NODE( XAL, CountryName )
+    DEFINE_NODE( XAL, Code )
+    DEFINE_NODE( XAL, Street )
+    DEFINE_NODE( XAL, PostalCode )
+    DEFINE_NODE( XAL, City )
+    DEFINE_NODE( XAL, LocalityName )
+    DEFINE_NODE( XAL, Thoroughfare )
+    DEFINE_NODE( XAL, ThoroughfareNumber )
+    DEFINE_NODE( XAL, ThoroughfareName )
+    DEFINE_NODE( XAL, Locality )
+    DEFINE_NODE( XAL, AddressDetails )
+    DEFINE_NODE( XAL, DependentLocalityName )
+    // WTR
+    DEFINE_NODE( WTR, WaterBody )
+
+    // VEG
+    DEFINE_NODE( VEG, PlantCover )
+    DEFINE_NODE( VEG, SolitaryVegetationObject )
+    DEFINE_NODE( VEG, Species )
+    DEFINE_NODE( VEG, Lod1ImplicitRepresentation )
+    DEFINE_NODE( VEG, Lod2ImplicitRepresentation )
+    DEFINE_NODE( VEG, Lod3ImplicitRepresentation )
+    DEFINE_NODE( VEG, Lod4ImplicitRepresentation )
+
+    // TRANS
+    DEFINE_NODE( TRANS, TrafficArea )
+    DEFINE_NODE( TRANS, AuxiliaryTrafficArea )
+    DEFINE_NODE( TRANS, Track )
+    DEFINE_NODE( TRANS, Road )
+    DEFINE_NODE( TRANS, Railway )
+    DEFINE_NODE( TRANS, Square )
+
+    // LUSE
+    DEFINE_NODE( LUSE, LandUse )
+
+    // dem
+    DEFINE_NODE( LUSE, Lod )
+    DEFINE_NODE( LUSE, TINRelief )
+
+    // 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, 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 )
+
+}
diff --git a/sources/src/parser/parserxercesc.cpp b/sources/src/parser/parserxercesc.cpp
new file mode 100644
index 0000000..1ee2649
--- /dev/null
+++ b/sources/src/parser/parserxercesc.cpp
@@ -0,0 +1,346 @@
+/* -*-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 <fstream>
+#include <string>
+#include <memory>
+#include <mutex>
+
+#include "citygml/citygmllogger.h"
+#include "parser/citygmldocumentparser.h"
+#include "parser/documentlocation.h"
+#include "parser/attributes.h"
+
+#include <xercesc/sax2/DefaultHandler.hpp>
+#include <xercesc/sax/Locator.hpp>
+#include <xercesc/sax2/Attributes.hpp>
+#include <xercesc/util/XMLString.hpp>
+#include <xercesc/sax2/SAX2XMLReader.hpp>
+#include <xercesc/sax2/XMLReaderFactory.hpp>
+#include <xercesc/sax/InputSource.hpp>
+#include <xercesc/util/BinInputStream.hpp>
+#include <xercesc/framework/LocalFileInputSource.hpp>
+#include <xercesc/util/PlatformUtils.hpp>
+
+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<XMLCh> 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<XMLCh>(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<CityGMLLogger> 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<XMLCh> 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<CityGMLLogger> 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<char*>(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<CityGMLLogger> 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<const CityModel> parse(xercesc::InputSource& stream, const ParserParams& params, std::shared_ptr<CityGMLLogger> 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<const CityModel> load(std::istream& stream, const ParserParams& params, std::shared_ptr<CityGMLLogger> logger)
+    {
+        if (!logger) {
+            logger = std::make_shared<StdLogger>();
+        }
+
+        if (!initXerces(logger)) {
+            return nullptr;
+        }
+
+        StdBinInputSource streamSource(stream);
+        return parse(streamSource, params, logger);
+    }
+
+    std::shared_ptr<const CityModel> load( const std::string& fname, const ParserParams& params , std::shared_ptr<CityGMLLogger> logger)
+    {
+        if (!logger) {
+            logger = std::make_shared<StdLogger>();
+        }
+
+        if (!initXerces(logger)) {
+            return nullptr;
+        }
+
+        std::shared_ptr<XMLCh> 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
+
+    }
+}
+
diff --git a/sources/src/parser/polygonelementparser.cpp b/sources/src/parser/polygonelementparser.cpp
new file mode 100644
index 0000000..3d54b82
--- /dev/null
+++ b/sources/src/parser/polygonelementparser.cpp
@@ -0,0 +1,109 @@
+#include "parser/polygonelementparser.h"
+
+#include <unordered_map>
+
+#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 <stdexcept>
+
+namespace citygml {
+
+
+    // The nodes that are valid Polygon Objects
+    std::unordered_set<int> typeIDSet;
+    bool typeIDSetInitialized = false;
+
+    PolygonElementParser::PolygonElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void(std::shared_ptr<Polygon>)> callback)
+        : CityGMLElementParser(documentParser, factory, logger)
+    {
+        m_callback = callback;
+    }
+
+    std::string PolygonElementParser::elementParserName() const
+    {
+        return "PolygonElementParser";
+    }
+
+    bool PolygonElementParser::handlesElement(const NodeType::XMLNode& node) const
+    {
+        if(!typeIDSetInitialized) {
+            typeIDSet.insert(NodeType::GML_TriangleNode.typeID());
+            typeIDSet.insert(NodeType::GML_RectangleNode.typeID());
+            typeIDSet.insert(NodeType::GML_PolygonNode.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 false;
+    }
+
+    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 false;
+
+    }
+
+    void PolygonElementParser::parseRingElement(bool interior)
+    {
+        setParserForNextElement(new LinearRingElementParser(m_documentParser, m_factory, m_logger, interior, [this](LinearRing* ring){
+            m_model->addRing(ring);
+        }));
+    }
+
+}
diff --git a/sources/src/parser/textureelementparser.cpp b/sources/src/parser/textureelementparser.cpp
new file mode 100644
index 0000000..176342e
--- /dev/null
+++ b/sources/src/parser/textureelementparser.cpp
@@ -0,0 +1,154 @@
+#include "parser/textureelementparser.h"
+
+#include <unordered_map>
+
+#include "parser/nodetypes.h"
+#include "parser/attributes.h"
+#include "parser/documentlocation.h"
+#include "parser/parserutils.hpp"
+
+#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 <stdexcept>
+
+namespace citygml {
+
+    TextureElementParser::TextureElementParser(CityGMLDocumentParser& documentParser, CityGMLFactory& factory, std::shared_ptr<CityGMLLogger> logger, std::function<void (std::shared_ptr<Texture>)> callback)
+        : CityGMLElementParser(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::GML_NameNode
+            || 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 = new TextureCoordinates(attributes.getCityGMLIDAttribute(), parseReference(attributes.getAttribute("ring"), m_logger, getDocumentLocation()));
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    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::GML_NameNode) {
+
+            m_model->setAttribute(node.name(), characters);
+        } else 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<bool>(characters, m_logger, getDocumentLocation()));
+        } else if (node == NodeType::APP_BorderColorNode) {
+
+            std::vector<float> colorValues = parseVecList<float>(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());
+                delete m_currentTexCoords;
+                m_currentTexCoords = nullptr;
+            }
+
+        } else if (node == NodeType::APP_TextureCoordinatesNode) {
+
+            if (m_currentTexCoords != nullptr && m_currentTexTargetDef != nullptr) {
+                m_currentTexCoords->setCoords(parseVecList<TVec2f>(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) {
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+
+
+
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
deleted file mode 100644
index 5af46d7..0000000
--- a/src/CMakeLists.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-IF ( LIBCITYGML_USE_XERCESC )
-	FIND_PACKAGE( Xerces REQUIRED )
-	ADD_DEFINITIONS( -DUSE_XERCESC )
-	SET( LIBXML2_INCLUDE_DIR "" )
-	SET( LIBXML2_LIBRARIES "" )
-ENDIF( LIBCITYGML_USE_XERCESC )
-
-IF( LIBCITYGML_USE_LIBXML2 )
-	FIND_PACKAGE( LibXml2 REQUIRED )
-	FIND_PACKAGE( Iconv REQUIRED )
-	ADD_DEFINITIONS( -DUSE_LIBXML2 )
-	ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS} )
-	SET( XERCESC_INCLUDE "" )
-	SET( XERCESC_LIBRARY "" )
-ENDIF( LIBCITYGML_USE_LIBXML2 )
-	
-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 )
-	
-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 )
-
-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 )
-
-SET( LIB_NAME citygml )
-
-INCLUDE_DIRECTORIES( ../include ${XERCESC_INCLUDE} ${LIBXML2_INCLUDE_DIR} ${ICONV_INCLUDE_DIR} ${GLU_INCLUDE_PATH} ${GDAL_INCLUDE_DIR} )
-
-SET( LIB_SRCS
-	citymodel.cpp
-	parser.cpp
-	parserxercesc.cpp
-	parserlibxml2.cpp
-	tesselator.cpp
-)
-
-SET( LIB_PUBLIC_HEADERS
-	../include/citygml.h
-	../include/vecs.h
-	./parser.h
-	./transform.h
-	./tesselator.h
-	./utils.h
-)
-
-ADD_LIBRARY( ${LIB_NAME} ${LIBCITYGML_USER_DEFINED_DYNAMIC_OR_STATIC} ${LIB_SRCS} ${LIB_PUBLIC_HEADERS} )
-
-TARGET_LINK_LIBRARIES( ${LIB_NAME} ${XERCESC_LIBRARIES} ${LIBXML2_LIBRARIES} ${OPENGL_LIBRARIES} ${GDAL_LIBRARY} )
-
-# IF( MSVC_IDE )
-	# SET_TARGET_PROPERTIES( ${LIB_NAME} PROPERTIES PREFIX "../" )
-# ENDIF( MSVC_IDE )
-
-INCLUDE(ModuleInstall OPTIONAL)
diff --git a/src/citymodel.cpp b/src/citymodel.cpp
deleted file mode 100644
index 2eb1986..0000000
--- a/src/citymodel.cpp
+++ /dev/null
@@ -1,654 +0,0 @@
-/* -*-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 "tesselator.h"
-#include "citygml.h"
-#include "utils.h"
-#include <string.h>
-#include <limits>
-#include <iterator>
-#include <set>
-
-#ifndef min
-#	define min( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
-namespace citygml
-{
-	std::ostream& operator<<( std::ostream& os, const Envelope& e ) 
-	{
-		return os << e.getLowerBound() << " " << e.getUpperBound();
-	}
-
-	std::ostream& operator<<( std::ostream& os, const Object& o ) 
-	{ 
-		return os << o.getId();
-	}
-
-	std::ostream& operator<<( std::ostream& os, const citygml::Geometry& s )
-	{
-		unsigned int count = 0;
-		for ( unsigned int i = 0; i < s.size(); i++ )
-		{
-			os << *s[i];
-			count += s[i]->getVertices().size();
-		}
-
-		os << "  @ " << s._polygons.size() << " polys [" << count << " vertices]" << std::endl;
-
-		return os;
-	}
-
-	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._attributes.begin();
-		while ( it != o._attributes.end() )
-		{
-			os << "  + " << it->first << ": " << it->second << std::endl;
-			it++;
-		}
-
-		std::vector< Geometry* >::const_iterator itp = o._geometries.begin();
-		for ( ; itp != o._geometries.end(); itp++ ) 
-			os << **itp;
-
-		os << "  * " << o._geometries.size() << " geometries." << std::endl;
-
-		return os;
-	}
-
-	std::ostream& operator<<( std::ostream& out, const CityModel& model ) 
-	{
-		const CityObjectsMap& cityObjectsMap = model.getCityObjectsMap();
-
-		CityObjectsMap::const_iterator it = cityObjectsMap.begin();
-
-		for ( ; it != cityObjectsMap.end(); ++it )
-
-			for ( unsigned int i = 0; i < it->second.size(); i++ ) out << *(it->second[i]);
-
-		out << model.size() << " city objects." << std::endl;	
-
-		return out;
-	}
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	TVec3d LinearRing::computeNormal( void ) 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 = _vertices[i];
-			const TVec3d& next = _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();
-	}
-
-	void LinearRing::finish( TexCoords* texCoords )
-	{
-		// Remove duplicated vertex
-		unsigned int len = _vertices.size();
-		if ( len < 2 ) return;
-
-		for ( unsigned int i = 0; i < len; i++ )
-		{
-			if ( ( _vertices[i] - _vertices[ ( i + 1 ) % len ] ).sqrLength() <= std::numeric_limits<float>::epsilon() )
-			{
-				_vertices.erase( _vertices.begin() + i );
-				if ( texCoords && texCoords->size() > i) texCoords->erase( texCoords->begin() + i );
-				finish( texCoords );
-				return;
-			}
-		}
-	}
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	AppearanceManager::AppearanceManager( void ) : _lastId( "" ), _lastCoords( 0 ) 
-	{
-		_tesselator = new ::Tesselator();
-	}
-
-	AppearanceManager::~AppearanceManager( void ) 
-	{
-		for ( unsigned int i = 0; i < _appearances.size(); i++ ) delete _appearances[i];
-
-		std::set<TexCoords*> texCoords;
-		for ( std::map<std::string, TexCoords*>::iterator it = _texCoordsMap.begin(); it != _texCoordsMap.end(); ++it )
-		{
-			if ( it->second && texCoords.find(it->second) == texCoords.end() ) 
-			{
-				texCoords.insert(it->second);
-				delete it->second;
-			}
-		}
-
-		for ( std::vector<TexCoords*>::iterator it = _obsoleteTexCoords.begin(); it != _obsoleteTexCoords.end(); it++ )
-			if ( texCoords.find(*it) == texCoords.end() )
-				delete *it;
-
-		delete _tesselator;
-	}
-
-	void AppearanceManager::refresh( void )
-	{
-		_lastCoords = 0;
-		_lastId = "";
-	}
-
-	template <typename AppType>
-	AppType AppearanceManager::getAppearance( const std::string& nodeid, ForSide side /*= FS_ANY*/ ) const
-	{
-		std::map< std::string, std::vector< Appearance* > >::const_iterator map_iterator = _appearancesMap.find( nodeid );
-		if ( map_iterator == _appearancesMap.end() ) return 0;
-
-		std::vector< Appearance* >::const_iterator vector_iterator = ( map_iterator->second ).begin();
-		for( ; vector_iterator != ( map_iterator->second ).end(); ++vector_iterator ) {
-			if ( AppType appType = dynamic_cast< AppType >( *vector_iterator ) ) {
-				if ( side == FS_ANY || 
-					( side == FS_FRONT && appType->getIsFront() ) ||
-					( side == FS_BACK && !appType->getIsFront() ) )
-				{
-					return appType;
-				}
-			}
-		}
-
-		return 0;
-	}
-
-	void AppearanceManager::addAppearance( Appearance* app ) 
-	{ 
-		if ( app ) _appearances.push_back( app ); 
-	}
-
-	void AppearanceManager::assignNode( const std::string& nodeid )
-	{ 
-		_lastId = nodeid; 
-
-		if ( !getAppearance< Appearance * >( nodeid ) )
-			_appearancesMap[ nodeid ] = std::vector< Appearance* >(0);
-
-		Appearance* currentAppearance = _appearances[ _appearances.size() - 1 ];
-		ForSide side = currentAppearance->getIsFront() ? FS_FRONT : FS_BACK;
-		if ( dynamic_cast< Texture* >( currentAppearance ) && !getAppearance< Texture* >( nodeid, side ) ||
-			 dynamic_cast< Material* >( currentAppearance ) && !getAppearance< Material* >( nodeid, side ) )
-		{
-			(_appearancesMap[ nodeid ]).push_back( currentAppearance );
-			if ( _lastCoords ) { assignTexCoords( _lastCoords ); _lastId = ""; }
-		}
-	}
-
-	bool AppearanceManager::assignTexCoords( TexCoords* tex ) 
-	{ 
-		_lastCoords = tex;
-        if ( _lastId == "" )
-		{
-            _obsoleteTexCoords.push_back( tex );   
-            return false;
-        }
-		_texCoordsMap[ _lastId ] = tex; 
-		_lastCoords = 0;
-		_lastId = "";
-		return true;
-	}
-
-    void AppearanceManager::finish(void)
-    {
-        std::set<TexCoords*> useLessTexCoords;
-
-		for ( std::map<std::string, TexCoords*>::iterator it = _texCoordsMap.begin(); it != _texCoordsMap.end(); ++it )
-		{
-			if ( it->second && useLessTexCoords.find( it->second ) == useLessTexCoords.end() )
-			{
-				useLessTexCoords.insert( it->second );
-				delete it->second;
-			}
-		}
-
-        for ( std::vector<TexCoords*>::iterator it = _obsoleteTexCoords.begin(); it != _obsoleteTexCoords.end(); it++ )
-            if ( useLessTexCoords.find( *it ) == useLessTexCoords.end() )
-                delete *it;
-
-		_appearancesMap.clear();
-        _texCoordsMap.clear();
-        _obsoleteTexCoords.clear();
-    }
-		
-	///////////////////////////////////////////////////////////////////////////////
-
-	Polygon::~Polygon( void ) 
-	{ 
-		delete _exteriorRing;
-		std::vector< LinearRing* >::const_iterator it = _interiorRings.begin();
-		for ( ; it != _interiorRings.end(); ++it ) delete *it;
-	}
-
-	TVec3d Polygon::computeNormal( void ) 
-	{
-		if ( !_exteriorRing ) return TVec3d();
-
-		TVec3d normal = _exteriorRing->computeNormal();
-
-		return _negNormal ? -normal : normal;
-	}
-
-	void Polygon::tesselate( AppearanceManager &appearanceManager, const TVec3d& normal )
-	{
-		_indices.clear();
-
-		if ( !_exteriorRing || _exteriorRing->size() < 3 )
-		{ 
-			mergeRings( appearanceManager );
-			return;
-		}
-
-		TexCoords texCoords;
-		bool t = appearanceManager.getTexCoords( _exteriorRing->getId(), texCoords );
-		_exteriorRing->finish( t ? &texCoords : &_texCoords );
-		if ( t ) std::copy( texCoords.begin(), texCoords.end(), std::back_inserter( _texCoords ) );
-
-		for ( unsigned int i = 0; i < _interiorRings.size(); i++ ) {
-			TexCoords texCoords;
-			bool t = appearanceManager.getTexCoords( _interiorRings[i]->getId(), texCoords );
-			_interiorRings[i]->finish( t ? &texCoords : &_texCoords );
-			if ( t ) std::copy( texCoords.begin(), texCoords.end(), std::back_inserter( _texCoords ) );
-		}
-
-		// Compute the total number of vertices
-		unsigned int vsize = _exteriorRing->size();
-		for ( unsigned int i = 0; i < _interiorRings.size(); i++ )
-			vsize += _interiorRings[i]->size();
-
-		Tesselator* tess = appearanceManager.getTesselator();
-		tess->init( vsize, normal );
-
-		tess->addContour( _exteriorRing->getVertices(), texCoords );
-
-		for ( unsigned int i = 0; i < _interiorRings.size(); i++ )
-			tess->addContour( _interiorRings[i]->getVertices(), texCoords ); 
-
-		tess->compute();
-		_vertices.reserve( tess->getVertices().size() );
-		std::copy( tess->getVertices().begin(), tess->getVertices().end(), std::back_inserter( _vertices ) );
-
-		unsigned int indicesSize = tess->getIndices().size();
-		if ( indicesSize > 0 ) 
-		{
-			_indices.resize( indicesSize );
-			memcpy( &_indices[0], &tess->getIndices()[0], indicesSize * sizeof(unsigned int) );
-		}
-		clearRings();
-	}
-
-	void Polygon::mergeRings( AppearanceManager &appearanceManager )
-	{
-		_vertices.reserve( _vertices.size() + _exteriorRing->size() );
-		TexCoords texCoords;
-		bool t = appearanceManager.getTexCoords( _exteriorRing->getId(), texCoords );
-		_exteriorRing->finish( t ? &texCoords : &_texCoords ); 
-		if ( t ) std::copy( texCoords.begin(), texCoords.end(), std::back_inserter( _texCoords ) );
-
-		std::copy( _exteriorRing->getVertices().begin(), _exteriorRing->getVertices().end(), std::back_inserter( _vertices ) );
-
-		for ( unsigned int i = 0; i < _interiorRings.size(); i++ )
-		{
-			TexCoords texCoords;
-			bool t = appearanceManager.getTexCoords( _interiorRings[i]->getId(), texCoords );
-			_interiorRings[i]->finish( t ? &texCoords : &_texCoords );
-			if ( t ) std::copy( texCoords.begin(), texCoords.end(), std::back_inserter( _texCoords ) );
-
-			_vertices.reserve( _vertices.size() + _interiorRings[i]->size() );
-
-			std::copy( _interiorRings[i]->getVertices().begin(), _interiorRings[i]->getVertices().end(), std::back_inserter( _vertices ) );
-		}
-		clearRings();
-		_indices.clear();
-
-		if ( _vertices.size() < 3 ) return;
-
-		// Create triangles' indices
-		int indicesSize = 3 * ( _vertices.size() - 2 );
-		if ( indicesSize < 3 ) return;
-		_indices.resize( indicesSize );
-		for ( int i = 0, p = 0; p < indicesSize - 2; i++, p += 3 )
-			for ( unsigned int j = 0; j < 3; j++ )
-				_indices[ p + j ] = i + j;
-	}
-
-	void Polygon::clearRings( void )
-	{
-		delete _exteriorRing;
-		_exteriorRing = 0;
-		for ( unsigned int i = 0; i < _interiorRings.size(); i++ ) delete _interiorRings[i]; 
-		_interiorRings.clear();
-	}
-
-	// Merge polygon p into the current polygon
-	bool Polygon::merge( Polygon* p )
-	{
-		if ( !p ) return false;
-
-		if ( p->getAppearance() != getAppearance() ) return false;
-
-		if ( p->getVertices().size() == 0 ) return true;
-
-		// merge vertices
-		unsigned int oldVSize = _vertices.size();
-		unsigned int pVSize = p->_vertices.size();
-		_vertices.resize( oldVSize + pVSize );
-		for ( unsigned int i = 0; i < pVSize; i++ )
-			_vertices[ oldVSize + i ] = p->_vertices[i];
-		p->_vertices.clear();
-		
-		// merge indices
-		{
-			unsigned int oldSize = _indices.size();
-			unsigned int pSize = p->_indices.size();
-			_indices.resize( oldSize + pSize );
-			for ( unsigned int i = 0; i < pSize; i++ )
-				_indices[ oldSize + i ] = oldVSize + p->_indices[i];
-			p->_indices.clear();
-		}
-
-		// merge normals
-		{
-			unsigned int oldSize = _normals.size();
-			unsigned int pSize = p->_normals.size();
-			_normals.resize( oldSize + pSize );
-			for ( unsigned int i = 0; i < pSize; i++ )
-				_normals[ oldSize + i ] = p->_normals[i];
-			p->_normals.clear();
-		}
-
-		// merge texcoords
-		{
-			unsigned int oldSize = min( _texCoords.size(), oldVSize );
-			unsigned int pSize = min( p->_texCoords.size(), pVSize );
-			_texCoords.resize( oldSize + pSize );
-			for ( unsigned int i = 0; i < pSize; i++ )
-				_texCoords[ oldSize + i ] = p->_texCoords[i];
-			p->_texCoords.clear();
-		}
-
-		// merge ids
-		_id += "+" + p->_id;
-
-		return true;
-	}
-
-	void Polygon::finish( AppearanceManager& appearanceManager, bool doTesselate ) 
-	{
-		TVec3d normal = computeNormal();
-		if ( doTesselate ) tesselate( appearanceManager, normal );	else mergeRings( appearanceManager );
-
-		// Create the normal per point field
-		_normals.resize( _vertices.size() );
-		for ( unsigned int i = 0; i < _vertices.size(); i++ )
-			_normals[i] = TVec3f( (float)normal.x, (float)normal.y, (float)normal.z );
-	}
-
-	void Polygon::finish( AppearanceManager& appearanceManager, Appearance* defAppearance, bool doTesselate )
-	{	
-		if ( !appearanceManager.getTexCoords( getId(), _texCoords ) ) 
-			appearanceManager.getTexCoords( _geometry->getId(), _texCoords );
-				
-		finish( appearanceManager, doTesselate );
-		
-		_texCoords.resize( _vertices.size() );
-		
-		const std::string id = getId();
-		_appearance = appearanceManager.getAppearance( id );
-		if ( !_appearance ) _appearance = defAppearance;
-
-		_materials[ FRONT ] = appearanceManager.getMaterialFront( id );
-		_materials[ BACK ] = appearanceManager.getMaterialBack( id );
- 		if ( !_materials[ FRONT ]  && !_materials[ BACK ])
- 			_materials[ FRONT ] = dynamic_cast< Material * >( defAppearance );
-
-		_texture = appearanceManager.getTexture( id );
-		if ( !_texture ) _texture = dynamic_cast< Texture * >( defAppearance );
-	}
-
-	void Polygon::addRing( LinearRing* ring ) 
-	{
-		if ( ring->isExterior() ) _exteriorRing = ring;
-		else _interiorRings.push_back( ring );
-	}
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	Geometry::~Geometry() 
-	{ 
-		std::vector< Polygon* >::const_iterator it = _polygons.begin();
-		for ( ; it != _polygons.end(); ++it ) delete *it;
-	}
-
-	void Geometry::addPolygon( Polygon* p ) 
-	{ 
-		p->_geometry = this;
-		_polygons.push_back( p ); 
-	}
-
-	void Geometry::finish( AppearanceManager& appearanceManager, Appearance* defAppearance,  const ParserParams& params )
-	{
-		Appearance* myappearance = appearanceManager.getAppearance( getId() );
-		std::vector< Polygon* >::const_iterator it = _polygons.begin();
-		for ( ; it != _polygons.end(); ++it ) (*it)->finish( appearanceManager, myappearance ? myappearance : defAppearance, params.tesselate );
-
-		bool finish = false;
-		while ( !finish && params.optimize ) 
-		{			
-			finish = true;
-			int len = (int)_polygons.size();			
-			for ( int i = 0; finish && i < len - 1; i++ ) 
-			{
-				for ( int j = i+1; finish && j < len - 1; j++ ) 
-				{
-					if ( !_polygons[i]->merge( _polygons[j] ) ) continue;
-					delete _polygons[j];
-					_polygons.erase( _polygons.begin() + j );
-					finish = false;		
-				}
-			}
-		}
-	}
-
-	bool Geometry::merge( Geometry* g ) 
-	{
-		if ( !g || g->_lod != _lod || g->_type != _type ) return false;
-
-		unsigned int pSize = g->_polygons.size();
-		for ( unsigned int i = 0; i < pSize; i++ )
-			_polygons.push_back( g->_polygons[i] );
-
-		g->_polygons.clear();
-
-		_id += "+" + g->_id;
-
-		return true;
-	}
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	std::string getCityObjectsClassName( CityObjectsTypeMask mask )
-	{
-#define GETCITYNAME( _t_ ) if ( mask & COT_ ## _t_ ) ss << # _t_ << "|";
-		std::stringstream ss;
-		GETCITYNAME( GenericCityObject );
-        GETCITYNAME( Building );
-		GETCITYNAME( BuildingPart );
-		GETCITYNAME( Room );
-		GETCITYNAME( BuildingInstallation );
-		GETCITYNAME( BuildingFurniture );
-		GETCITYNAME( Door );
-		GETCITYNAME( Window );
-		GETCITYNAME( CityFurniture );
-		GETCITYNAME( Track );
-		GETCITYNAME( Road );
-		GETCITYNAME( Railway );
-		GETCITYNAME( Square );
-		GETCITYNAME( PlantCover );
-		GETCITYNAME( SolitaryVegetationObject );
-		GETCITYNAME( WaterBody );
-		GETCITYNAME( TINRelief );
-		GETCITYNAME( LandUse );
-		GETCITYNAME( Tunnel );
-		GETCITYNAME( Bridge );
-		GETCITYNAME( BridgeConstructionElement );
-		GETCITYNAME( BridgeInstallation );
-		GETCITYNAME( BridgePart );
-		GETCITYNAME( RoofSurface );
-		GETCITYNAME( WallSurface );
-		GETCITYNAME( GroundSurface );
-		GETCITYNAME( ClosureSurface );      
-		GETCITYNAME( FloorSurface );        
-		GETCITYNAME( InteriorWallSurface );
-		GETCITYNAME( CeilingSurface );
-#undef GETCITYNAME
-		std::string s = ss.str();
-		if ( s != "" ) s.erase( s.length() - 1, 1 ); // remove the last | char
-		return s;
-	};
-
-	CityObjectsTypeMask getCityObjectsTypeMaskFromString( const std::string& stringMask ) 
-	{
-		CityObjectsTypeMask mask = 0;
-
-		std::vector<std::string> tokens = tokenize( stringMask );
-
-#define COMPARECITYNAMEMASK( _t_ ) {\
-	bool neg = ( tokens[i][0] == '~' || tokens[i][0] == '!' );\
-	if ( ci_string_compare( #_t_, neg ? tokens[i].substr(1) : tokens[i] ) ) { mask = neg ? ( mask & (~ COT_ ## _t_ )) : ( mask | COT_ ## _t_ );}\
-	}
-
-		for ( unsigned int i = 0; i < tokens.size(); i++ ) 
-		{
-			if ( tokens[i].length() == 0 ) continue;
-
-			COMPARECITYNAMEMASK( GenericCityObject );
-			COMPARECITYNAMEMASK( Building );
-			COMPARECITYNAMEMASK( BuildingPart );
-			COMPARECITYNAMEMASK( Room );
-			COMPARECITYNAMEMASK( BuildingInstallation );
-			COMPARECITYNAMEMASK( BuildingFurniture );
-			COMPARECITYNAMEMASK( Door );
-			COMPARECITYNAMEMASK( Window );
-			COMPARECITYNAMEMASK( CityFurniture );
-			COMPARECITYNAMEMASK( Track );				 
-			COMPARECITYNAMEMASK( Road );				 
-			COMPARECITYNAMEMASK( Railway );
-			COMPARECITYNAMEMASK( Square	);				 
-			COMPARECITYNAMEMASK( PlantCover	);
-			COMPARECITYNAMEMASK( SolitaryVegetationObject );
-			COMPARECITYNAMEMASK( WaterBody );
-			COMPARECITYNAMEMASK( TINRelief );					 
-			COMPARECITYNAMEMASK( LandUse );
-			COMPARECITYNAMEMASK( Tunnel );
-			COMPARECITYNAMEMASK( Bridge );
-			COMPARECITYNAMEMASK( BridgeConstructionElement );
-			COMPARECITYNAMEMASK( BridgeInstallation );
-			COMPARECITYNAMEMASK( BridgePart );
-			COMPARECITYNAMEMASK( GenericCityObject );
-
-			COMPARECITYNAMEMASK( WallSurface );
-			COMPARECITYNAMEMASK( RoofSurface );         
-			COMPARECITYNAMEMASK( GroundSurface );        
-			COMPARECITYNAMEMASK( ClosureSurface );      
-			COMPARECITYNAMEMASK( FloorSurface );        
-			COMPARECITYNAMEMASK( InteriorWallSurface );
-			COMPARECITYNAMEMASK( CeilingSurface );
-			COMPARECITYNAMEMASK( All );					
-		}
-#undef COMPARECITYNAMEMASK
-		return mask;
-	}
-
-	void CityObject::finish( AppearanceManager& appearanceManager, const ParserParams& params ) 
-	{
-		Appearance* myappearance = appearanceManager.getAppearance( getId() );
-		std::vector< Geometry* >::const_iterator it = _geometries.begin();
-		for ( ; it != _geometries.end(); ++it ) (*it)->finish( appearanceManager, myappearance ? myappearance : 0, params );
-
-		bool finish = false;
-		while ( !finish && params.optimize ) 
-		{
-			finish = true;
-			int len = _geometries.size();
-			for ( int i = 0; finish && i < len - 2; i++ ) 
-			{
-				for ( int j = i+1; finish && j < len - 1; j++ ) 
-				{
-					if ( !_geometries[i]->merge( _geometries[j] ) ) continue;
-					delete _geometries[j];					
-					_geometries.erase( _geometries.begin() + j );
-					finish = false;
-				}
-			}
-		}
-	}
-
-	///////////////////////////////////////////////////////////////////////////////
-
-	CityModel::~CityModel( void ) 
-	{ 	
-		CityObjectsMap::const_iterator it = _cityObjectsMap.begin();
-		for ( ; it != _cityObjectsMap.end(); ++it ) 
-			for ( unsigned int i = 0; i < it->second.size(); i++ )
-				delete it->second[i];
-	}
-
-	void CityModel::addCityObject( CityObject* o )
-	{
-		CityObjectsMap::iterator it = _cityObjectsMap.find( o->getType() );
-		if ( it == _cityObjectsMap.end() )
-		{
-			CityObjects v;
-			v.push_back( o );
-			_cityObjectsMap[ o->getType() ] = v;
-		}
-		else
-			it->second.push_back( o );
-	}
-
-	void CityModel::finish( const ParserParams& params ) 
-	{
-		// Assign appearances to cityobjects => geometries => polygons
-		CityObjectsMap::const_iterator it = _cityObjectsMap.begin();
-		for ( ; it != _cityObjectsMap.end(); ++it ) 
-			for ( unsigned int i = 0; i < it->second.size(); i++ )
-				it->second[i]->finish( _appearanceManager, params );
-
-		_appearanceManager.finish();
-	}
-}
diff --git a/src/parser.cpp b/src/parser.cpp
deleted file mode 100644
index 99df90b..0000000
--- a/src/parser.cpp
+++ /dev/null
@@ -1,909 +0,0 @@
-/* -*-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.
-*/
-
-// libcitygml implements a SAX Parser for CityGML v0.3 - v1.0 file format
-// See schemas at:
-//  http://www.citygml.org/citygml/1/0/0/CityGML.xsd
-//  http://www.citygml.org/fileadmin/citygml/docs/CityGML_1_0_0_UML_diagrams.pdf
-
-#include "parser.h"
-#include "transform.h"
-#include "utils.h"
-
-#ifndef MSVC
-	#include <typeinfo>
-#endif
-
-using namespace citygml;
-
-std::map<std::string, CityGMLNodeType> CityGMLHandler::s_cityGMLNodeTypeMap;
-std::vector< std::string > CityGMLHandler::s_knownNamespace;
-
-CityGMLHandler::CityGMLHandler( const ParserParams& params ) 
-: _params( params ), _model( 0 ), _currentCityObject( 0 ), _currentObject( 0 ),
-_currentGeometry( 0 ), _currentPolygon( 0 ), _currentRing( 0 ),  _currentGeometryType( GT_Unknown ),
-_currentAppearance( 0 ), _currentLOD( params.minLOD ), 
-_filterNodeType( false ), _filterDepth( 0 ), _exterior( true ), _geoTransform( 0 )
-{ 
-	_objectsMask = getCityObjectsTypeMaskFromString( _params.objectsMask );
-	initNodes(); 
-}
-
-CityGMLHandler::~CityGMLHandler( void ) 
-{
-    for ( std::set<Geometry*>::iterator it = _geometries.begin(); it != _geometries.end(); it++ )
-        delete *it;
-}
-
-void CityGMLHandler::initNodes( void ) 
-{
-	if ( s_cityGMLNodeTypeMap.size() != 0 ) return;
-
-#define INSERTNODETYPE(_t_) s_cityGMLNodeTypeMap[ #_t_ ] = CG_ ## _t_;
-
-	// core
-	INSERTNODETYPE( CityModel );
-	INSERTNODETYPE( cityObjectMember );
-	INSERTNODETYPE( creationDate );
-	INSERTNODETYPE( terminationDate );
-
-	// grp
-	INSERTNODETYPE( CityObjectGroup );
-	INSERTNODETYPE( groupMember );
-
-	// gen
-	INSERTNODETYPE( GenericCityObject );
-	INSERTNODETYPE( stringAttribute );
-	INSERTNODETYPE( doubleAttribute );
-	INSERTNODETYPE( intAttribute );
-	INSERTNODETYPE( dateAttribute );
-	INSERTNODETYPE( uriAttribute );
-	INSERTNODETYPE( value );
-
-	// gml
-	INSERTNODETYPE( name );
-	INSERTNODETYPE( pos );
-	INSERTNODETYPE( coordinates );
-	INSERTNODETYPE( description );
-	INSERTNODETYPE( boundedBy );
-	INSERTNODETYPE( Envelope );
-	INSERTNODETYPE( lowerCorner );
-	INSERTNODETYPE( upperCorner );
-	INSERTNODETYPE( Solid );
-	INSERTNODETYPE( surfaceMember );
-	INSERTNODETYPE( CompositeSurface );
-	INSERTNODETYPE( TriangulatedSurface );
-	INSERTNODETYPE( TexturedSurface );
-	INSERTNODETYPE( Triangle );
-	INSERTNODETYPE( Polygon );
-	INSERTNODETYPE( posList );
-	INSERTNODETYPE( OrientableSurface );
-	INSERTNODETYPE( LinearRing );
-
-	INSERTNODETYPE( lod1Solid );
-	INSERTNODETYPE( lod2Solid );
-	INSERTNODETYPE( lod3Solid );
-	INSERTNODETYPE( lod4Solid );
-	INSERTNODETYPE( lod1Geometry );
-	INSERTNODETYPE( lod2Geometry );
-	INSERTNODETYPE( lod3Geometry );
-	INSERTNODETYPE( lod4Geometry );
-
-	// bldg
-	INSERTNODETYPE( Building );
-	INSERTNODETYPE( BuildingPart );
-	INSERTNODETYPE( Room );
-	INSERTNODETYPE( Door );
-	INSERTNODETYPE( Window );
-	INSERTNODETYPE( BuildingInstallation );
-	INSERTNODETYPE( address );
-	INSERTNODETYPE( measuredHeight );
-	INSERTNODETYPE( class );
-	INSERTNODETYPE( type );
-	INSERTNODETYPE( function );
-	INSERTNODETYPE( usage );
-	INSERTNODETYPE( yearOfConstruction );
-	INSERTNODETYPE( yearOfDemolition );
-	INSERTNODETYPE( storeysAboveGround );
-	INSERTNODETYPE( storeysBelowGround );
-	INSERTNODETYPE( storeyHeightsAboveGround );
-	INSERTNODETYPE( storeyHeightsBelowGround );
-
-	// address
-	INSERTNODETYPE( administrativearea );
-	INSERTNODETYPE( country );
-	INSERTNODETYPE( code );
-	INSERTNODETYPE( street );
-	INSERTNODETYPE( postalCode );
-	INSERTNODETYPE( city );
-
-	// BoundarySurfaceType
-	INSERTNODETYPE( WallSurface );
-	INSERTNODETYPE( RoofSurface );
-	INSERTNODETYPE( GroundSurface );
-	INSERTNODETYPE( ClosureSurface );
-	INSERTNODETYPE( FloorSurface );
-	INSERTNODETYPE( InteriorWallSurface );
-	INSERTNODETYPE( CeilingSurface );
-	INSERTNODETYPE( BuildingFurniture );
-
-	INSERTNODETYPE( CityFurniture );
-
-	INSERTNODETYPE( interior );
-	INSERTNODETYPE( exterior );
-
-	// wtr
-	INSERTNODETYPE( WaterBody );
-
-	// veg
-	INSERTNODETYPE( PlantCover );
-	INSERTNODETYPE( SolitaryVegetationObject );
-
-	// trans
-	INSERTNODETYPE( TrafficArea );
-	INSERTNODETYPE( AuxiliaryTrafficArea );
-	INSERTNODETYPE( Track );
-	INSERTNODETYPE( Road );
-	INSERTNODETYPE( Railway );
-	INSERTNODETYPE( Square );
-
-	// luse
-	INSERTNODETYPE( LandUse );
-
-	// dem
-	INSERTNODETYPE( lod );
-	INSERTNODETYPE( TINRelief );
-
-	// sub
-	INSERTNODETYPE( Tunnel );
-	INSERTNODETYPE( relativeToTerrain );
-
-	// brid
-	INSERTNODETYPE( Bridge );
-	INSERTNODETYPE( BridgeConstructionElement );
-	INSERTNODETYPE( BridgeInstallation );
-	INSERTNODETYPE( BridgePart );
-
-	// app
-	INSERTNODETYPE( SimpleTexture );
-	INSERTNODETYPE( ParameterizedTexture );
-	INSERTNODETYPE( GeoreferencedTexture );
-	INSERTNODETYPE( imageURI );
-	INSERTNODETYPE( textureMap );
-	INSERTNODETYPE( target );
-	INSERTNODETYPE( textureCoordinates );
-	INSERTNODETYPE( textureType );
-	INSERTNODETYPE( repeat );
-	INSERTNODETYPE( wrapMode );
-	INSERTNODETYPE( borderColor );
-	INSERTNODETYPE( preferWorldFile );
-
-	INSERTNODETYPE( X3DMaterial );
-	INSERTNODETYPE( Material );
-	INSERTNODETYPE( appearanceMember );
-	INSERTNODETYPE( surfaceDataMember );		
-	INSERTNODETYPE( shininess );
-	INSERTNODETYPE( transparency );
-	INSERTNODETYPE( specularColor );
-	INSERTNODETYPE( diffuseColor );
-	INSERTNODETYPE( emissiveColor );
-	INSERTNODETYPE( ambientIntensity );
-	INSERTNODETYPE( isFront );
-
-	// Set the known namespaces
-
-#define INSERTKNOWNNAMESPACE(_t_) s_knownNamespace.push_back( #_t_ );
-
-	INSERTKNOWNNAMESPACE( gml );
-	INSERTKNOWNNAMESPACE( citygml );
-	INSERTKNOWNNAMESPACE( core );
-	INSERTKNOWNNAMESPACE( app );
-	INSERTKNOWNNAMESPACE( bldg );
-	INSERTKNOWNNAMESPACE( frn );
-	INSERTKNOWNNAMESPACE( grp );
-	INSERTKNOWNNAMESPACE( gen );
-	INSERTKNOWNNAMESPACE( luse );
-	INSERTKNOWNNAMESPACE( dem );
-	INSERTKNOWNNAMESPACE( tran );
-	INSERTKNOWNNAMESPACE( trans );
-	INSERTKNOWNNAMESPACE( veg );
-	INSERTKNOWNNAMESPACE( wtr );
-	INSERTKNOWNNAMESPACE( tex );
-	INSERTKNOWNNAMESPACE( sub );
-	INSERTKNOWNNAMESPACE( brid );
-}
-
-CityGMLNodeType CityGMLHandler::getNodeTypeFromName( const std::string& name )
-{
-	std::map<std::string, CityGMLNodeType>::const_iterator elt = s_cityGMLNodeTypeMap.find( name );
-
-	if ( elt == s_cityGMLNodeTypeMap.end() ) return CG_Unknown;
-
-	return elt->second;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Helpers
-
-template<class T> inline void parseValue( std::stringstream &s, T &v ) 
-{
-	if ( !s.eof() ) s >> v;
-}
-
-template<> inline void parseValue( std::stringstream &s, bool &v ) 
-{
-	// parsing a bool is special because "true" and "1" are true while "false" and "0" are false
-	std::string value = s.str();
-	if (value == "1" || value == "true")
-		v = true;
-	else if (value == "0" || value == "false")
-		v = false;
-	else
-		std::cerr << "Error ! Boolean expected, got " << value << std::endl;
-}
-
-template<class T> inline void parseValue( std::stringstream &s, T &v, GeoTransform* transform, const TVec3d &translate ) 
-{
-	parseValue( s, v );
-	
-	if ( transform ) transform->transform( v );
-	
-	// Translate based on bounding box of whole model
-	v[0] -= translate[0];
-	v[1] -= translate[1];
-	v[2] -= translate[2];
-}
-
-template<class T> inline void parseVecList( std::stringstream &s, std::vector<T> &vec ) 
-{
-	T v;
-	unsigned int oldSize( vec.size() );
-	while ( s >> v )
-		vec.push_back( v );
-	if ( !s.eof() )
-	{
-		std::cerr << "Error ! Mismatch type: " << typeid(T).name() << " expected. Ring/Polygon discarded!" << std::endl;
-		vec.resize( oldSize );
-	}
-}
-
-template<class T> inline void parseVecList( std::stringstream &s, std::vector<T> &vec, GeoTransform* transform, const TVec3d &translate ) 
-{
-	T v;
-	unsigned int oldSize( vec.size() );
-	while ( s >> v )
-	{
-		if ( transform ) transform->transform( v );
-		
-		// Translate based on bounding box of whole model
-		v[0] -= translate[0];
-		v[1] -= translate[1];
-		v[2] -= translate[2];
-		
-		vec.push_back( v );
-	}
-	if ( !s.eof() )
-	{
-		std::cerr << "Error ! Mismatch type: " << typeid(T).name() << " expected. Ring/Polygon discarded!" << std::endl;
-		vec.resize( oldSize );
-	}
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-std::string CityGMLHandler::getNodeName( const std::string& name ) 
-{
-	// remove the known namespace if it exists
-
-	size_t pos = name.find_first_of( ":" );
-	if ( pos == std::string::npos ) return name;
-
-	std::string nspace = name.substr( 0, pos );
-
-	for ( int i = s_knownNamespace.size() - 1; i >= 0; i-- ) 
-		if ( nspace == s_knownNamespace[i] ) 
-			return name.substr( s_knownNamespace[i].length() + 1 );
-
-	return name;
-}
-
-void CityGMLHandler::startElement( const std::string& name, void* attributes ) 
-{
-	std::string localname = getNodeName( name );
-
-	_nodePath.push_back( localname );
-
-	CityGMLNodeType nodeType = getNodeTypeFromName( localname );
-
-	// get the LOD level if node name starts with 'lod'
-	if ( localname.length() > 3 && localname.find( "lod" ) == 0 ) _currentLOD = localname[3] - '0';
-
-#define LOD_FILTER() if ( _currentLOD < (int)_params.minLOD || _currentLOD > (int)_params.maxLOD ) break;
-
-#define NODETYPE_FILTER() ( _filterNodeType && getPathDepth() > _filterDepth )
-
-#define MODEL_FILTER() if ( !_model ) break;
-
-	if ( NODETYPE_FILTER() ) return;
-
-	switch ( nodeType ) 
-	{
-	case NODETYPE( CityModel ):
-		_model = new CityModel();
-		pushObject( _model );
-		break;
-
-		// City objects management
-#define MANAGE_OBJECT( _t_ )\
-	case CG_ ## _t_ :\
-	if ( _objectsMask & COT_ ## _t_ )\
-		{ pushCityObject( new _t_( getGmlIdAttribute( attributes ) ) ); pushObject( _currentCityObject ); /*std::cout << "new "<< #_t_ " - " << _currentCityObject->getId() << std::endl;*/ }\
-	else { pushCityObject( 0 ); _filterNodeType = true; _filterDepth = getPathDepth(); }\
-	break;
-
-		MANAGE_OBJECT( GenericCityObject );
-		MANAGE_OBJECT( Building );
-		MANAGE_OBJECT( BuildingPart );
-		MANAGE_OBJECT( Room );
-		MANAGE_OBJECT( BuildingInstallation );
-		MANAGE_OBJECT( BuildingFurniture );
-		MANAGE_OBJECT( Door );
-		MANAGE_OBJECT( Window );
-		MANAGE_OBJECT( CityFurniture );
-		MANAGE_OBJECT( Track );
-		MANAGE_OBJECT( Road );
-		MANAGE_OBJECT( Railway );
-		MANAGE_OBJECT( Square );
-		MANAGE_OBJECT( PlantCover );
-		MANAGE_OBJECT( SolitaryVegetationObject );
-		MANAGE_OBJECT( WaterBody );
-		MANAGE_OBJECT( TINRelief );
-		MANAGE_OBJECT( LandUse );		
-		MANAGE_OBJECT( Tunnel );
-		MANAGE_OBJECT( Bridge );
-		MANAGE_OBJECT( BridgeConstructionElement );
-		MANAGE_OBJECT( BridgeInstallation );
-		MANAGE_OBJECT( BridgePart );
-#undef MANAGE_OBJECT
-
-		// BoundarySurfaceType
-#define MANAGE_SURFACETYPE( _t_ ) case CG_ ## _t_ ## Surface : _currentGeometryType = GT_ ## _t_;\
-									if ( _objectsMask & COT_ ## _t_ ## Surface )\
-		{ pushCityObject( new _t_ ## Surface( getGmlIdAttribute( attributes ) ) ); pushObject( _currentCityObject ); /*std::cout << "new "<< #_t_ " - " << _currentCityObject->getId() << std::endl;*/ }\
-	else { pushCityObject( 0 ); _filterNodeType = true; _filterDepth = getPathDepth(); }\
-	break;
-		MANAGE_SURFACETYPE( Wall );
-		MANAGE_SURFACETYPE( Roof );
-		MANAGE_SURFACETYPE( Ground );
-		MANAGE_SURFACETYPE( Closure );
-		MANAGE_SURFACETYPE( Floor );
-		MANAGE_SURFACETYPE( InteriorWall );
-		MANAGE_SURFACETYPE( Ceiling );
-#undef MANAGE_SURFACETYPE
-
-		// Geometry management
-
-	case NODETYPE( TexturedSurface ):
-	case NODETYPE( OrientableSurface ):
-		_orientation = getAttribute( attributes, "orientation", "+" )[0];
-		break;
-
-	case NODETYPE( surfaceMember ):
-	case NODETYPE( TriangulatedSurface ):
-		LOD_FILTER();
-		//_orientation = getAttribute( attributes, "orientation", "+" )[0];
-		_orientation = '+';
-		_currentGeometry = new Geometry( getGmlIdAttribute( attributes ), _currentGeometryType, _currentLOD );
-        _geometries.insert( _currentGeometry );
-		pushObject( _currentGeometry );
-		break;
-
-	case NODETYPE( Triangle ):
-	case NODETYPE( Polygon ):
-		LOD_FILTER();
-		_currentPolygon = new Polygon( getGmlIdAttribute( attributes ) );
-		pushObject( _currentPolygon );
-		break;
-
-	case NODETYPE( Envelope ): 
-		createGeoTransform( getAttribute( attributes, "srsName", "" ) );
-		break;
-
-	case NODETYPE( posList ):
-		LOD_FILTER();
-		_srsDimension = atoi( getAttribute( attributes, "srsDimension", "3" ).c_str() );
-		if ( _srsDimension != 3 ) 
-			std::cerr << "Warning ! srsDimension of gml:posList not set to 3!" << std::endl;
-
-		createGeoTransform( getAttribute( attributes, "srsName", "" ) );		
-		break;
-
-	case NODETYPE( interior ): _exterior = false; break;
-	case NODETYPE( exterior ): _exterior = true;  break;
-
-	case NODETYPE( LinearRing ): 
-		LOD_FILTER();
-		_currentRing = new LinearRing( getGmlIdAttribute( attributes ), _exterior ); 
-		pushObject( _currentRing );
-		break;
-
-		// Material management
-
-	case NODETYPE( target ):
-		if ( _currentAppearance ) 
-		{
-			std::string uri = getAttribute( attributes, "uri" );
-			if ( uri != "" ) 
-			{
-				if ( uri.length() > 0 && uri[0] == '#' ) uri = uri.substr( 1 );		
-				_model->_appearanceManager.assignNode( uri );
-				_appearanceAssigned = true;
-			}
-		}
-		break;
-
-	case NODETYPE( textureCoordinates ):
-		MODEL_FILTER();
-		if ( Texture* texture = dynamic_cast<Texture*>( _currentAppearance ) ) 
-		{			
-			std::string ring = getAttribute( attributes, "ring" );
-			if ( ring != "" )
-			{
-				if ( ring.length() > 0 && ring[0] == '#' ) ring = ring.substr( 1 );
-				_model->_appearanceManager.assignNode( ring );
-			}
-		}
-		break;
-
-	case NODETYPE( SimpleTexture ):
-	case NODETYPE( ParameterizedTexture ):
-		_currentAppearance = new Texture( getGmlIdAttribute( attributes ) );
-		_model->_appearanceManager.addAppearance( _currentAppearance );
-		_appearanceAssigned = false;
-		pushObject( _currentAppearance );
-		break;
-
-	case NODETYPE( GeoreferencedTexture ):
-		_currentAppearance = new GeoreferencedTexture( getGmlIdAttribute( attributes ) );
-		_model->_appearanceManager.addAppearance( _currentAppearance );
-		_appearanceAssigned = false;
-		pushObject( _currentAppearance );
-		break;
-
-	case NODETYPE( Material ):
-	case NODETYPE( X3DMaterial ):
-		_currentAppearance = new Material( getGmlIdAttribute( attributes ) );
-		_model->_appearanceManager.addAppearance( _currentAppearance );
-		_appearanceAssigned = false;
-		pushObject( _currentAppearance );
-		break;
-
-	case NODETYPE( stringAttribute ):
-	case NODETYPE( doubleAttribute ):
-	case NODETYPE( intAttribute ):
-	case NODETYPE( dateAttribute ):
-	case NODETYPE( uriAttribute ):
-		_attributeName = getAttribute( attributes, "name", "" );
-		break;
-
-	default:
-		break;
-	};
-}
-
-void CityGMLHandler::endElement( const std::string& name ) 
-{
-	std::string localname = getNodeName( name );
-
-	_nodePath.pop_back();
-
-	CityGMLNodeType nodeType = getNodeTypeFromName( localname );
-
-	if ( NODETYPE_FILTER() ) { clearBuffer(); return; }
-
-	if ( nodeType == NODETYPE( Unknown ) ) // unknown node ? skip now to avoid the buffer triming pass
-	{
-		clearBuffer();
-		return; 
-	}
-
-	// Trim the char buffer  
-	std::stringstream buffer;
-	buffer << trim( _buff.str() );
-
-	// set the LOD level if node name starts with 'lod'
-	if ( localname.find( "lod" ) == 0 ) _currentLOD = _params.minLOD;
-
-	switch ( nodeType ) 
-	{
-	case NODETYPE( CityModel ):
-		MODEL_FILTER();
-		_model->finish( _params );
-		if ( _geoTransform )
-		{
-			std::cout << "The coordinates were transformed from " << _model->_srsName << " to "
-								<< ((GeoTransform*)_geoTransform)->getDestURN() << std::endl;
-			_model->_srsName = ((GeoTransform*)_geoTransform)->getDestURN();
-		}
-		if ( _model->_srsName == "" )
-		{
-			_model->_srsName = _params.destSRS;
-			std::cerr << "Warning: No SRS was set in the file. The model SRS has been set "
-									"without transformation to " << _params.destSRS << std::endl;
-		}
-		
-		_model->_translation = _translate;
-		std::cout << std::fixed << "The model coordinates were translated by x:" << _translate.x
-				      << " y:" << _translate.y << " z:" << _translate.z << std::endl;
-		
-		popObject();
-		break;
-
-		// City objects management
-
-	case NODETYPE( GenericCityObject ):
-	case NODETYPE( Building ):
-	case NODETYPE( BuildingPart ):
-	case NODETYPE( Room ):
-	case NODETYPE( BuildingInstallation ):
-	case NODETYPE( BuildingFurniture ):
-	case NODETYPE( Door ):
-	case NODETYPE( Window ):
-	case NODETYPE( CityFurniture ):
-	case NODETYPE( Track ):
-	case NODETYPE( Road ):
-	case NODETYPE( Railway ):
-	case NODETYPE( Square ):
-	case NODETYPE( PlantCover ):
-	case NODETYPE( SolitaryVegetationObject ):
-	case NODETYPE( WaterBody ):
-	case NODETYPE( TINRelief ):
-	case NODETYPE( LandUse ):
-	case NODETYPE( Tunnel ):
-	case NODETYPE( Bridge ):
-	case NODETYPE( BridgeConstructionElement ):
-	case NODETYPE( BridgeInstallation ):
-	case NODETYPE( BridgePart ):
-	case NODETYPE( WallSurface ):
-	case NODETYPE( RoofSurface ):
-	case NODETYPE( GroundSurface ):
-	case NODETYPE( ClosureSurface ):
-	case NODETYPE( FloorSurface ):
-	case NODETYPE( InteriorWallSurface ):
-	case NODETYPE( CeilingSurface ):
-		MODEL_FILTER();
-		if ( _currentCityObject && ( _currentCityObject->size() > 0 || _currentCityObject->getChildCount() > 0 || !_params.pruneEmptyObjects ) ) 
-		{	// Prune empty objects 
-			_model->addCityObject( _currentCityObject );
-			if ( _cityObjectStack.size() == 1 ) _model->addCityObjectAsRoot( _currentCityObject );
-		}
-		else delete _currentCityObject; 
-		popCityObject();
-		popObject();
-		_filterNodeType = false;
-		_currentGeometryType = GT_Unknown;
-		break;
-
-	case NODETYPE( Envelope ): 
-		MODEL_FILTER();
-		if ( _points.size() >= 2 ) 
-		{
-			if ( getPathDepth() == 2 ) // CityModel envelope
-			{
-				_model->_envelope._lowerBound = _points[0];
-				_model->_envelope._upperBound = _points[1];
-				/*
-				// Translation works only if model as an envelope on CityModel set
-				// It is assumed that the envelope is correct and valid
-				// If there is no envelope set the translation parameters are zero
-				// and no translation of the model will be applied -> but also no
-				// correct tesselation will be possible
-				_translate[0] = _model->_envelope._lowerBound.x;
-				_translate[1] = _model->_envelope._lowerBound.y;
-				_translate[2] = _model->_envelope._lowerBound.z;
-
-				// Possible optimization 1: Make a first scan through whole document
-				// and compute correct envelope if no one is present. Afterwards
-				// start the real parsing.
-
-				// Possible optimization 2: Implement scaling so the model coordinates
-				// are between 0 and 1.
-
-				// Currently not implemented: The Citygml object model should have its
-				// real coordinates in dest SRS after parsing. Currently the translation
-				// parameters are applied to the coordinates in dest SRS. What needs still
-				// to be implemented is that after tesselation the coordinates are translated
-				// back. Only for visualisation e.g. via OSG the saved translation parameters
-				// should be applied before creation of OSG geometry.
-				
-				// The envelope is already transformed to destination SRS
-				// so we now translation parameters in dest SRS and recompute envelope
-				_model->_envelope._lowerBound = _model->_envelope._lowerBound - _translate;
-				_model->_envelope._upperBound = _model->_envelope._upperBound - _translate;*/
-			}
-			else if ( _currentCityObject )
-			{
-				_currentCityObject->_envelope._lowerBound = _points[0];
-				_currentCityObject->_envelope._upperBound = _points[1];
-			}
-		}
-		_points.clear();
-		break;
-
-	case NODETYPE( lowerCorner ):
-	case NODETYPE( upperCorner ):
-		{
-			TVec3d p;
-			parseValue( buffer, p, (GeoTransform*)_geoTransform, _translate );
-			if ( nodeType == NODETYPE( lowerCorner ) )
-				_points.insert( _points.begin(), p );
-			else
-				_points.push_back( p );
-		}
-		break;
-
-	case NODETYPE( lod ):
-		parseValue( buffer, _currentLOD );
-		break;
-
-	case NODETYPE( name ):
-	case NODETYPE( description ):
-		if ( _currentCityObject ) _currentCityObject->setAttribute( localname, buffer.str() );
-		else if ( _model && getPathDepth() == 1 ) _model->setAttribute( localname, buffer.str() );
-		break;
-
-	case NODETYPE( class ):
-	case NODETYPE( type ):
-	case NODETYPE( function ):
-	case NODETYPE( usage ):
-	case NODETYPE( yearOfConstruction ):
-	case NODETYPE( yearOfDemolition ):
-	case NODETYPE( storeysAboveGround ):
-	case NODETYPE( storeysBelowGround ):
-	case NODETYPE( storeyHeightsAboveGround ):
-	case NODETYPE( storeyHeightsBelowGround ):
-	case NODETYPE( administrativearea ):
-	case NODETYPE( country ):
-	case NODETYPE( code ):
-	case NODETYPE( street ):
-	case NODETYPE( postalCode ):
-	case NODETYPE( city ):
-	case NODETYPE( measuredHeight ):
-	case NODETYPE( creationDate ):
-	case NODETYPE( terminationDate ):
-		if ( _currentObject ) _currentObject->setAttribute( localname, buffer.str(), false );
-		break;
-
-	case NODETYPE( value ):
-		if ( _attributeName != "" && _currentObject )
-		{
-			if ( _currentObject ) _currentObject->setAttribute( _attributeName, buffer.str(), false );
-			else if ( _model && getPathDepth() == 1 ) _model->setAttribute( _attributeName, buffer.str(), false );
-		}
-		break;
-
-		// Geometry management 
-
-	case NODETYPE( surfaceMember ):
-	case NODETYPE( TriangulatedSurface ):
-		if ( _currentCityObject && _currentGeometry )
-        	_currentCityObject->_geometries.push_back( _currentGeometry );          
-		else 
-			delete _currentGeometry;
-		_geometries.erase( _currentGeometry );
-		_currentGeometry = 0;
-		popObject();
-		break;
-
-	case NODETYPE( Triangle ):
-	case NODETYPE( Polygon ):
-		if ( _currentGeometry && _currentPolygon )
-		{
-			//_currentPolygon->finish( ( nodeType == NODETYPE( Triangle ) ) ? false : _params.tesselate );							
-			_currentGeometry->addPolygon( _currentPolygon );
-		}
-		_currentPolygon = 0;
-		popObject();
-		break;
-
-	case NODETYPE( pos ):
-		if ( _currentCityObject )
-		{
-			TVec3d p;
-			parseValue( buffer, p, (GeoTransform*)_geoTransform, _translate );
-			if ( !_currentPolygon )
-				_points.push_back( p );
-			else if ( _currentRing )
-				_currentRing->addVertex( p );
-		}
-		break;
-
-	case NODETYPE( coordinates ):
-	case NODETYPE( posList ):
-		if ( !_currentPolygon ) { parseVecList( buffer, _points, (GeoTransform*)_geoTransform, _translate ); break; }
-		_currentPolygon->_negNormal = ( _orientation != '+' );
-		if ( _currentRing ) 
-			parseVecList( buffer, _currentRing->getVertices(), (GeoTransform*)_geoTransform, _translate );
-		break;
-
-	case NODETYPE( interior ):
-	case NODETYPE( exterior ): _exterior = true; break;
-
-	case NODETYPE( LinearRing ): 
-		if ( _currentPolygon && _currentRing ) 
-			_currentPolygon->addRing( _currentRing );	
-		_currentRing = 0;
-		break;
-
-		// Material management
-
-	case NODETYPE( textureMap ):
-	case NODETYPE( imageURI ):
-		if ( Texture* texture = dynamic_cast<Texture*>( _currentAppearance ) ) 
-		{
-			texture->_url = buffer.str();
-			std::replace( texture->_url.begin(), texture->_url.end(), '\\', '/' );
-		}
-		break;
-
-	case NODETYPE( target ):
-		MODEL_FILTER();
-		if ( _currentAppearance && !_appearanceAssigned )
-		{
-			std::string uri = buffer.str();
-			if ( uri != "" ) 
-			{
-				if ( uri.length() > 0 && uri[0] == '#' ) uri = uri.substr( 1 );
-				_model->_appearanceManager.assignNode( uri );
-			}
-		}
-		break;
-
-	case NODETYPE( textureCoordinates ):
-		MODEL_FILTER();
-		if ( Texture* texture = dynamic_cast<Texture*>( _currentAppearance ) ) 
-		{            
-			TexCoords *vec = new TexCoords();
-			parseVecList( buffer, *vec );			
-			_model->_appearanceManager.assignTexCoords( vec );
-		}
-		break;
-
-	case NODETYPE( isFront ):
-		if ( _currentAppearance )  
-		{
-			bool val;
-			parseValue( buffer, val );
-			_currentAppearance->_isFront = val;
-		}
-		break;
-
-	case NODETYPE( SimpleTexture ):
-	case NODETYPE( ParameterizedTexture ):
-	case NODETYPE( GeoreferencedTexture ):
-	case NODETYPE( Material ):
-	case NODETYPE( X3DMaterial ):
-		if ( _currentAppearance && _currentGeometry && !_appearanceAssigned )
-			_model->_appearanceManager.assignNode( _currentGeometry->getId() );
-		_model->_appearanceManager.refresh();
-		_currentAppearance = 0;
-		popObject();
-		break;
-
-	case NODETYPE( diffuseColor ):
-	case NODETYPE( emissiveColor ):
-	case NODETYPE( specularColor ):
-		if ( Material* mat = dynamic_cast<Material*>( _currentAppearance ) ) 
-		{
-			TVec3f col;
-			parseValue( buffer, col );	
-			if ( nodeType == NODETYPE( diffuseColor ) ) mat->_diffuse = col;
-			else if ( nodeType == NODETYPE( emissiveColor ) ) mat->_emissive = col;
-			else if ( nodeType == NODETYPE( specularColor ) ) mat->_specular = col;
-		}
-		break;
-
-	case NODETYPE( ambientIntensity ):
-	case NODETYPE( shininess ):
-	case NODETYPE( transparency ):
-		if ( Material* mat = dynamic_cast<Material*>( _currentAppearance ) ) 
-		{
-			float val;
-			parseValue( buffer, val );	
-			if ( nodeType == NODETYPE( shininess ) ) mat->_shininess = val;
-			else if ( nodeType == NODETYPE( transparency ) ) mat->_transparency = val;
-			else if ( nodeType == NODETYPE( ambientIntensity ) ) mat->_ambientIntensity = val;
-		}
-		break;
-
-	case NODETYPE( wrapMode ):
-		if ( Texture* texture = dynamic_cast<Texture*>( _currentAppearance ) )             
-		{
-			std::string s( buffer.str() );
-			if ( ci_string_compare( s, "wrap" ) ) texture->_wrapMode = Texture::WM_WRAP;
-			else if ( ci_string_compare( s, "mirror" ) ) texture->_wrapMode = Texture::WM_MIRROR;
-			else if ( ci_string_compare( s, "clamp" ) ) texture->_wrapMode = Texture::WM_CLAMP;
-			else if ( ci_string_compare( s, "border" ) ) texture->_wrapMode = Texture::WM_BORDER;
-		}
-		break;
-
-	case NODETYPE( borderColor ):
-		if ( Texture* texture = dynamic_cast<Texture*>( _currentAppearance ) )  
-		{
-			std::vector<float> col;
-			parseVecList( buffer, col );
-			col.push_back( 1.f ); // if 3 values are given, the fourth (A = opacity) is set to 1.0 by default
-			if ( col.size() >= 4 )
-				memcpy( &texture->_borderColor.r, &col[0], 4 * sizeof(float) );
-		}
-		break;
-
-	case NODETYPE( preferWorldFile ):
-		if ( GeoreferencedTexture* geoRefTexture = dynamic_cast<GeoreferencedTexture*>( _currentAppearance ) )  
-		{
-			parseValue( buffer, geoRefTexture->_preferWorldFile );
-		}
-		break;
-	default:
-		break;
-	};
-
-	clearBuffer();
-}
-
-void CityGMLHandler::createGeoTransform( std::string srsName )
-{	
-	if ( srsName == "" ) return; 
-
-	// Support SRS pattern like: 
-	//	urn:EPSG:geographicCRS:4326
-	// 	urn:ogc:def:crs:EPSG:6.6:4326
-	//	http://www.opengis.net/gml/srs/epsg.xml#4326
-	//	http://www.epsg.org/6.11.2/4326
-	//	EPSG:4326
-
-	bool latlon = false;
-
-	std::string proj4Name = srsName;
-
-	if ( srsName.find( "urn:" ) == 0 )
-	{
-		// Manage URN composition but retain only the first SRS
-		// ie. transform: urn:ogc:def:crs,crs:EPSG:6.12:3068,crs:EPSG:6.12:5783
-		// to urn:ogc:def:crs:EPSG:6.12:3068
-		std::vector<std::string> tokens = tokenize( srsName, "," );
-		if ( tokens.size() > 1 )
-		{
-			std::string::size_type p = tokens[1].find( ':' );
-			proj4Name = ( p != std::string::npos ) ? tokens[0] + tokens[1].substr( p ) : srsName = tokens[0] + tokens[1];		
-		}
-		latlon = true;
-	}
-	else if ( srsName.find( "http://www.opengis.net/gml/srs/epsg.xml#" ) != std::string::npos )	
-		proj4Name = "EPSG:" + srsName.substr( srsName.find_last_of( '#' ) + 1 );
-
-	else if ( srsName.find( "http://www.epsg.org/" ) != std::string::npos )
-		proj4Name = "EPSG:" + srsName.substr( srsName.find_last_of( '/' ) + 1 );
-	
-	if ( _model->_srsName == "" ) _model->_srsName = srsName;
-
-	if ( srsName != _model->_srsName ) { std::cerr << "Warning: More than one SRS is defined. The SRS " << srsName << " is declared while the scene SRS has been set to " << _model->_srsName << std::endl; /*return;*/ }
-
-	if ( _params.destSRS == "" ) return;
-	
-	delete (GeoTransform*)_geoTransform;
-	_geoTransform = new GeoTransform( proj4Name, _params.destSRS );
-}
diff --git a/src/parser.h b/src/parser.h
deleted file mode 100644
index f15073d..0000000
--- a/src/parser.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/* -*-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.
-*/
-
-// libcitygml implements a SAX Parser for CityGML v0.3 - v1.0 file format
-// See schemas at:
-//  http://www.citygml.org/citygml/1/0/0/CityGML.xsd
-//  http://www.citygml.org/fileadmin/citygml/docs/CityGML_1_0_0_UML_diagrams.pdf
-
-
-#ifndef __PARSER_H__
-#define __PARSER_H__
-
-#include "citygml.h"
-
-#include <string>
-#include <algorithm>
-#include <stack>
-#include <fstream>
-#include <set>
-
-namespace citygml
-{	
-	#define NODETYPE(_t_) CG_ ## _t_
-
-	// CityGML node types
-	enum CityGMLNodeType
-	{
-		NODETYPE( Unknown ) = 0,
-
-		// core
-		NODETYPE( CityModel ),
-		NODETYPE( cityObjectMember ),
-		NODETYPE( creationDate ),	
-		NODETYPE( terminationDate ),
-
-		// grp
-		NODETYPE( CityObjectGroup ),
-		NODETYPE( groupMember ),
-
-		// gen
-		NODETYPE( GenericCityObject ),
-		NODETYPE( stringAttribute ),
-		NODETYPE( doubleAttribute ),
-		NODETYPE( intAttribute ),
-		NODETYPE( dateAttribute ),
-		NODETYPE( uriAttribute ),
-		NODETYPE( value ),
-
-		// gml
-		NODETYPE( description ),
-		NODETYPE( name ),
-		NODETYPE( coordinates ),
-		NODETYPE( pos ),
-		NODETYPE( boundedBy ),
-		NODETYPE( Envelope ),
-		NODETYPE( lowerCorner ),
-		NODETYPE( upperCorner ),
-		NODETYPE( Solid ),
-		NODETYPE( surfaceMember ),
-		NODETYPE( CompositeSurface ),
-		NODETYPE( TriangulatedSurface ),
-		NODETYPE( TexturedSurface ),
-		NODETYPE( Triangle ),
-		NODETYPE( Polygon ),
-		NODETYPE( posList ),
-		NODETYPE( OrientableSurface ),
-		NODETYPE( LinearRing ),
-
-		NODETYPE( lod1Solid ),
-		NODETYPE( lod2Solid ),
-		NODETYPE( lod3Solid ),
-		NODETYPE( lod4Solid ),
-		NODETYPE( lod1Geometry ),
-		NODETYPE( lod2Geometry ),
-		NODETYPE( lod3Geometry ),
-		NODETYPE( lod4Geometry ),
-
-		// bldg
-		NODETYPE( Building ),
-		NODETYPE( BuildingPart ),
-		NODETYPE( Room ),
-		NODETYPE( Door ),
-		NODETYPE( Window ),
-		NODETYPE( BuildingInstallation ),
-		NODETYPE( address ),
-		NODETYPE( measuredHeight ),
-		NODETYPE( class ),
-		NODETYPE( type ),
-		NODETYPE( function ),
-		NODETYPE( usage ),
-		NODETYPE( yearOfConstruction ),
-		NODETYPE( yearOfDemolition ),
-		NODETYPE( storeysAboveGround ),
-		NODETYPE( storeysBelowGround ),
-		NODETYPE( storeyHeightsAboveGround ),
-		NODETYPE( storeyHeightsBelowGround ),
-
-		// address
-		NODETYPE( administrativearea ),
-		NODETYPE( country ),
-		NODETYPE( code ),
-		NODETYPE( street ),
-		NODETYPE( postalCode ),
-		NODETYPE( city ),
-
-		// BoundarySurfaceType
-		NODETYPE( WallSurface ),
-		NODETYPE( RoofSurface ),
-		NODETYPE( GroundSurface ),
-		NODETYPE( ClosureSurface ),
-		NODETYPE( FloorSurface ),
-		NODETYPE( InteriorWallSurface ),
-		NODETYPE( CeilingSurface ),
-		NODETYPE( BuildingFurniture ),
-
-		NODETYPE( CityFurniture ),
-
-		NODETYPE( interior ),
-		NODETYPE( exterior ),
-
-		// wtr
-		NODETYPE( WaterBody ),
-
-		// veg
-		NODETYPE( PlantCover ),
-		NODETYPE( SolitaryVegetationObject ),
-
-		// trans
-		NODETYPE( TrafficArea ),
-		NODETYPE( AuxiliaryTrafficArea ),
-		NODETYPE( Track ),
-		NODETYPE( Road ),
-		NODETYPE( Railway ),
-		NODETYPE( Square ),
-
-		// luse
-		NODETYPE( LandUse ),
-
-		// dem
-		NODETYPE( lod ),
-		NODETYPE( TINRelief ),
-
-		// sub
-		NODETYPE( Tunnel ),
-		NODETYPE( relativeToTerrain ),
-
-		// brid
-		NODETYPE( Bridge ),
-		NODETYPE( BridgeConstructionElement ),
-		NODETYPE( BridgeInstallation ),
-		NODETYPE( BridgePart ),
-		
-		// app
-		NODETYPE( SimpleTexture ),	
-		NODETYPE( ParameterizedTexture ),
-		NODETYPE( GeoreferencedTexture ),
-		NODETYPE( imageURI ),
-		NODETYPE( textureMap ),
-		NODETYPE( target ),
-		NODETYPE( textureCoordinates ),
-		NODETYPE( textureType ),
-		NODETYPE( repeat ),
-		NODETYPE( wrapMode ),
-		NODETYPE( borderColor ),
-		NODETYPE( preferWorldFile ),
-
-		NODETYPE( X3DMaterial ),
-		NODETYPE( Material ),
-		NODETYPE( appearanceMember ),
-		NODETYPE( surfaceDataMember ),
-		NODETYPE( shininess ),
-		NODETYPE( transparency ),
-		NODETYPE( specularColor ),
-		NODETYPE( diffuseColor ),
-		NODETYPE( emissiveColor ),
-		NODETYPE( ambientIntensity ),
-		NODETYPE( isFront )
-	};
-	
-	// CityGML SAX parsing handler
-	class CityGMLHandler
-	{
-	public:
-
-		CityGMLHandler( const ParserParams& params );
-
-		~CityGMLHandler( void );
-
-		virtual void startDocument( void ) {}
-
-		virtual void endDocument( void ) {}
-
-		virtual void startElement( const std::string&, void* );
-
-		virtual void endElement( const std::string& );
-
-		virtual void fatalError( const std::string& error ) 
-		{
-			std::cerr << "Fatal error while parsing CityGML file: " << error << std::endl;
-			std::cerr << "  Full path was: " << getFullPath() << std::endl;
-		}
-
-		inline CityModel* getModel( void ) { return _model; }
-
-	protected:
-
-		inline int searchInNodePath( const std::string& name ) const 
-		{
-			for ( int i = _nodePath.size() - 1; i >= 0; i-- )
-				if ( _nodePath[i] == name ) return i;
-			return -1;
-		}
-
-		inline std::string getFullPath( void ) const 
-		{
-			std::stringstream ss;
-			for ( unsigned int i = 0; i < _nodePath.size(); i++ )
-				ss << _nodePath[i] << "/";
-			return ss.str();
-		}
-
-		inline std::string getPrevNode( void ) const { return _nodePath.size() > 2 ? _nodePath[ _nodePath.size() - 2 ] : ""; }
-
-		inline unsigned int getPathDepth( void ) const { return _nodePath.size(); }
-
-		inline CityGMLNodeType getPrevNodeType( void ) const { return getNodeTypeFromName( getPrevNode() ); }
-
-		inline void clearBuffer( void ) { _buff.str(""); _buff.clear(); }  
-		
-		inline void pushCityObject( CityObject* object )
-		{
-			if ( _currentCityObject && object ) _currentCityObject->getChildren().push_back( object );
-			_cityObjectStack.push( _currentCityObject );
-			_currentCityObject = object;
-		}
-
-		inline void popCityObject( void )
-		{
-			_currentCityObject = 0; 
-			if ( _cityObjectStack.empty() ) return; 
-			_currentCityObject = _cityObjectStack.top(); 
-			_cityObjectStack.pop();
-		}
-
-		inline void pushObject( Object* object )
-		{
-			_objectStack.push( object );
-			_currentObject = object;
-		}
-
-		inline void popObject( void )
-		{
-			_currentObject = 0; 
-			if ( _objectStack.empty() ) return; 
-			_objectStack.pop();
-			_currentObject = _objectStack.empty() ? 0 : _objectStack.top();			
-		}
-
-		virtual std::string getAttribute( void* attributes, const std::string& attname, const std::string& defvalue = "" ) = 0;
-
-		inline std::string getGmlIdAttribute( void* attributes ) { return getAttribute( attributes, "gml:id", "" ); }
-
-		void createGeoTransform( std::string );
-		
-		static void initNodes( void );
-
-		static std::string getNodeName( const std::string& );
-
-		static CityGMLNodeType getNodeTypeFromName( const std::string& );
-
-	protected:
-
-		static std::map< std::string, CityGMLNodeType > s_cityGMLNodeTypeMap;
-		static std::vector< std::string > s_knownNamespace;
-
-		std::vector< std::string > _nodePath;
-
-		std::stringstream _buff;
-
-		ParserParams _params;
-		
-		CityModel* _model;
-
-		TVec3d _translate;
-
-		CityObject* _currentCityObject;
-		std::stack<CityObject*> _cityObjectStack;
-
-		Object* _currentObject;
-		std::stack<Object*> _objectStack;
-
-		Geometry* _currentGeometry;
-        std::set<Geometry*> _geometries;
-
-		Polygon* _currentPolygon;
-
-		LinearRing* _currentRing;
-
-		Appearance* _currentAppearance;
-
-		CityObjectsTypeMask _objectsMask;
-
-		std::string _attributeName;
-
-		int _currentLOD;
-
-		bool _filterNodeType;
-		unsigned int _filterDepth;
-
-		std::vector<TVec3d> _points;
-
-		int _srsDimension;
-
-		char _orientation;
-
-		bool _exterior;
-
-		bool _appearanceAssigned;
-
-		GeometryType _currentGeometryType;
-
-		void* _geoTransform;
-	};
-}
-
-#endif
diff --git a/src/parserlibxml2.cpp b/src/parserlibxml2.cpp
deleted file mode 100644
index 6292909..0000000
--- a/src/parserlibxml2.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-/* -*-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.
-*/
-
-// This is the implementation file for LibXml2 parser
-
-#ifdef USE_LIBXML2
-
-#include "parser.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <libxml/parser.h>
-#include <libxml/SAX.h>
-
-using namespace citygml;
-
-// CityGML LibXml2 SAX parsing handler
-
-class CityGMLHandlerLibXml2 : public CityGMLHandler
-{
-public:
-	CityGMLHandlerLibXml2( const ParserParams& params ) : CityGMLHandler( params ) {}
-
-	void startElement( const xmlChar* name, const xmlChar** attrs ) 
-	{
-		CityGMLHandler::startElement( wstos( name ), attrs );
-	}
-
-	void endElement( const xmlChar* name )
-	{
-		CityGMLHandler::endElement( wstos( name ) );
-	}
-
-	void characters( const xmlChar *chars, int length ) 
-	{
-		for ( int i = 0; i < length; i++ ) _buff << (char)chars[i]; 
-	}
-
-	static inline std::string wstos( const xmlChar* const str ) 
-	{
-		return std::string( (const char*)str );
-	}
-
-protected:
-	std::string getAttribute( void* attributes, const std::string& attname, const std::string& defvalue = "" )
-	{
-		const xmlChar **attrs = (const xmlChar**)attributes;
-		if ( !attrs ) return defvalue;
-		for ( int i = 0; attrs[i] != 0; i += 2 ) 
-			if ( wstos( attrs[i] ) == attname ) return wstos( attrs[ i + 1 ] );
-		return defvalue;
-	}
-};
-
-void startDocument( void *user_data ) 
-{
-	static_cast<CityGMLHandlerLibXml2*>(user_data)->startDocument();
-}
-
-void endDocument( void *user_data ) 
-{
-	static_cast<CityGMLHandlerLibXml2*>(user_data)->endDocument();
-}
-
-void startElement( void *user_data, const xmlChar *name, const xmlChar **attrs ) 
-{
-	static_cast<CityGMLHandlerLibXml2*>(user_data)->startElement( name, attrs );
-}
-
-void endElement( void *user_data, const xmlChar *name )
-{
-	static_cast<CityGMLHandlerLibXml2*>(user_data)->endElement( name );
-}
-
-void characters( void *user_data, const xmlChar *ch, int len )
-{
-	static_cast<CityGMLHandlerLibXml2*>(user_data)->characters( ch, len );
-}
-
-void fatalError( void *user_data, const char *msg, ... ) 
-{
-	std::string error = "Parsing error!";
-
-	va_list args;
-	va_start( args, msg );
-#ifdef MSVC
-	size_t len = _vscprintf( msg, args ) + 1;
-	std::vector<char> buffer( len, '\0' );
-	if ( _vsnprintf_s( &buffer[0], buffer.size(), len, msg, args ) ) error = &buffer[0];
-#else
-	size_t len = 1024;
-	std::vector<char> buffer( len, '\0' );
-	if ( vsnprintf( &buffer[0], buffer.size(), msg, args ) ) error = &buffer[0];
-#endif
-	va_end( args );
-
-	static_cast<CityGMLHandlerLibXml2*>(user_data)->fatalError( error );
-	throw new std::string( error );
-}
-
-// Parsing methods
-namespace citygml
-{
-	CityModel* load( std::istream& stream, const ParserParams& params )
-	{
-		CityGMLHandlerLibXml2* handler = new CityGMLHandlerLibXml2( params );
-
-		xmlSAXHandler sh = { 0 };
-		sh.startDocument = startDocument;
-		sh.endDocument = endDocument;
-		sh.startElement = startElement;
-		sh.endElement = endElement;
-		sh.characters = characters;
-		sh.error = fatalError;
-		sh.fatalError = fatalError;
-
-		xmlParserCtxtPtr context = xmlCreatePushParserCtxt( &sh, handler, 0, 0, "" );
-		if ( !context ) 
-		{
-			std::cerr << "CityGML: Unable to create LibXml2 context!" << std::endl;
-			delete handler;
-			return 0;
-		}	
-
-		context->validate = 0;
-
-		try 
-		{ 
-			// stream parsing
-			std::string line;
-			while ( std::getline( stream, line ) )
-			{
-				line += '\n';
-				xmlParseChunk( context, line.c_str(), line.length(), 0 );
-			}
-
-			xmlParseChunk( context, 0, 0, 1 ); 		
-		}
-		catch ( ... ) 
-		{
-		}
-
-		xmlFreeParserCtxt( context );
-
-		CityModel* model = handler->getModel();
-
-		delete handler;
-
-		return model;	
-	}
-
-	CityModel* load( const std::string& fname, const ParserParams& params )
-	{
-		CityGMLHandlerLibXml2* handler = new CityGMLHandlerLibXml2( params );
-
-		xmlSAXHandler sh = { 0 };
-		sh.startDocument = startDocument;
-		sh.endDocument = endDocument;
-		sh.startElement = startElement;
-		sh.endElement = endElement;
-		sh.characters = characters;
-		sh.error = fatalError;
-		sh.fatalError = fatalError;
-
-
-		xmlParserInputBufferPtr inputBuffer = xmlParserInputBufferCreateFilename( fname.c_str(), XML_CHAR_ENCODING_NONE );
-		xmlParserCtxtPtr context = xmlCreateIOParserCtxt( &sh, handler, inputBuffer->readcallback, inputBuffer->closecallback, inputBuffer->context, XML_CHAR_ENCODING_NONE );
-		if ( !context ) 
-		{
-			std::cerr << "CityGML: Unable to create LibXml2 context!" << std::endl;
-			delete handler;
-			return 0;
-		}
-
-		context->validate = 0;
-
-		try 
-		{ 
-			xmlParseDocument( context );
-		}
-		catch ( ... ) 
-		{
-		}
-
-		xmlFreeParserCtxt( context );
-
-		CityModel* model = handler->getModel();
-
-		delete handler;
-
-		return model;	
-	}
-}
-
-#endif
diff --git a/src/parserxercesc.cpp b/src/parserxercesc.cpp
deleted file mode 100644
index 5d86f54..0000000
--- a/src/parserxercesc.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*-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.
-*/
-
-// This is the implementation file for Xerces-c parser
-
-#ifdef USE_XERCESC
-
-#include "parser.h"
-
-#include <xercesc/util/XMLString.hpp>
-#include <xercesc/parsers/SAXParser.hpp>
-#include <xercesc/sax/HandlerBase.hpp>
-#include <xercesc/sax/InputSource.hpp>
-#include <xercesc/util/BinInputStream.hpp>
-
-using namespace citygml;
-
-// CityGML Xerces-c SAX parsing handler
-class CityGMLHandlerXerces : public CityGMLHandler, public xercesc::HandlerBase 
-{
-public:
-	CityGMLHandlerXerces( const ParserParams& params ) : CityGMLHandler( params ) {}
-
-	void startElement( const XMLCh* const name, xercesc::AttributeList& attr )
-	{
-		CityGMLHandler::startElement( wstos( name ), &attr );
-	}
-
-	void endElement( const XMLCh* const name ) 
-	{
-		CityGMLHandler::endElement( wstos( name ) );
-	}
-
-	void characters( const XMLCh* const chars, const XMLSize_t length )
-	{
-		for ( unsigned int i = 0; i < length; i++ ) _buff << (char)chars[i]; 
-	}
-
-	void fatalError( const xercesc::SAXParseException& e ) 
-	{
-		CityGMLHandler::fatalError( wstos( e.getMessage() ) );
-	}
-
-	static inline std::string wstos( const XMLCh* const wstr ) 
-	{
-#ifdef MSVC
-		std::wstring w( (const wchar_t*)wstr );
-		return std::string( w.begin(), w.end() );
-#else
-		char* tmp = xercesc::XMLString::transcode(wstr);
-		std::string str(tmp);
-		xercesc::XMLString::release(&tmp);
-		return str;
-#endif
-	}
-
-protected:
-	std::string getAttribute( void* attributes, const std::string& attname, const std::string& defvalue = "" )
-	{
-		if (!attributes) return defvalue;
-		xercesc::AttributeList* attrs = (xercesc::AttributeList*)attributes;
-		const XMLCh* att = attrs->getValue( attname.c_str() );
-		return att ? wstos( att ) : defvalue;
-	}
-};
-
-class StdBinInputStream : public xercesc::BinInputStream
-{
-public:
-	StdBinInputStream( std::istream& stream ) : BinInputStream(), m_stream( stream ) {}
-
-	virtual ~StdBinInputStream( void ) {}
-
-	virtual XMLFilePos curPos( void ) 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<char*>(buf), maxToRead );
-		return (XMLSize_t)m_stream.gcount();
-	}
-
-	virtual const XMLCh* getContentType() const { return 0; }
-
-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 );
-	}
-
-private:
-	std::istream& m_stream;
-};
-
-// Parsing methods
-namespace citygml
-{
-	CityModel* load( std::istream& stream, const ParserParams& params )
-	{
-		try 
-		{
-			xercesc::XMLPlatformUtils::Initialize();
-		}
-		catch ( const xercesc::XMLException& e ) 
-		{
-			std::cerr << "CityGML: XML Exception occures during initialization!" << std::endl << CityGMLHandlerXerces::wstos( e.getMessage() ) << std::endl;
-			return false;
-		}
-
-		CityGMLHandlerXerces* handler = new CityGMLHandlerXerces( params );
-
-		xercesc::SAXParser* parser = new xercesc::SAXParser();
-		parser->setDoNamespaces( false );
-		parser->setDocumentHandler( handler );
-		parser->setErrorHandler( handler );
-
-		CityModel* model = 0;
-
-		try 
-		{
-			StdBinInputSource input( stream );
-			parser->parse( input );
-			model = handler->getModel();
-		}
-		catch ( const xercesc::XMLException& e ) 
-		{
-			std::cerr << "CityGML: XML Exception occures!" << std::endl << CityGMLHandlerXerces::wstos( e.getMessage() ) << std::endl;
-			delete handler->getModel();
-		}
-		catch ( const xercesc::SAXParseException& e ) 
-		{
-			std::cerr << "CityGML: SAXParser Exception occures!" << std::endl << CityGMLHandlerXerces::wstos( e.getMessage() ) << std::endl;
-			delete handler->getModel();
-		}
-		catch ( ... ) 
-		{
-			std::cerr << "CityGML: Unexpected Exception occures!" << std::endl ;
-			delete handler->getModel();
-		}
-
-		delete parser;
-		delete handler;
-		return model;
-	}
-
-	CityModel* load( const std::string& fname, const ParserParams& params )
-	{
-		std::ifstream file;
-		file.open( fname.c_str(), std::ifstream::in );
-		if ( file.fail() ) { std::cerr << "CityGML: Unable to open file " << fname << "!" << std::endl; return 0; }
-		CityModel* model = load( file, params );
-		file.close();
-		return model;
-	}
-}
-
-#endif
diff --git a/src/tesselator.cpp b/src/tesselator.cpp
deleted file mode 100644
index 600f4ba..0000000
--- a/src/tesselator.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/* -*-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 "tesselator.h"
-#ifndef WIN32
-#	include <stdint.h>
-#endif
-
-Tesselator::Tesselator( void )
-{
-	_tobj = gluNewTess(); 
-
-	gluTessCallback( _tobj, GLU_TESS_VERTEX_DATA, (GLU_TESS_CALLBACK)&vertexCallback );
-	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( unsigned int verticesCount, 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();
-	_vertices.reserve( verticesCount );
-	_indices.clear();
-	_curIndices.clear();
-}
-
-Tesselator::~Tesselator( void ) 
-{
-	gluDeleteTess( _tobj );
-}
-
-void Tesselator::compute( void ) 
-{
-	gluTessEndPolygon( _tobj );  
-}
-
-void Tesselator::addContour( const std::vector<TVec3d>& pts, const std::vector<TVec2f>& tex )
-{		
-	unsigned int len = pts.size();
-	if ( len < 3 ) return;
-
-	unsigned int pos = _vertices.size();
-
-	gluTessBeginContour( _tobj );
-
-	for ( unsigned int i = 0; i < len; i++ ) 
-	{
-		_vertices.push_back( pts[i] );
-
-		gluTessVertex( _tobj, &(_vertices[pos+i][0]), (void*)(pos+i) );
-	}
-
-	gluTessEndContour( _tobj );
-}
-
-void CALLBACK Tesselator::beginCallback( GLenum which, void* userData ) 
-{
-	Tesselator *tess = (Tesselator*)userData;
-	tess->_curMode = which;
-}
-
-void CALLBACK Tesselator::vertexCallback( GLvoid *data, void* userData ) 
-{
-	Tesselator *tess = (Tesselator*)userData;
-	tess->_curIndices.push_back( (intptr_t)data );
-}
-
-void CALLBACK Tesselator::combineCallback( GLdouble coords[3], void* vertex_data[4], GLfloat weight[4], void** outData, void* userData )
-{
-	Tesselator *tess = (Tesselator*)userData;
-	unsigned int npoint = tess->_vertices.size();
-	tess->_vertices.push_back( TVec3d( coords[0], coords[1], coords[2] ) );
-
-	*outData = (void*)npoint;
-}
-
-void CALLBACK Tesselator::endCallback( void* userData ) 
-{
-	Tesselator *tess = (Tesselator*)userData;
-
-	unsigned int len = tess->_curIndices.size();
-
-	switch ( tess->_curMode ) 
-	{
-	case GL_TRIANGLES:
-		for ( unsigned int i = 0; i < len; i++ ) tess->_indices.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];
-
-			for ( unsigned int i = 2; i < len; i++ ) 
-			{
-				if ( tess->_curMode == GL_TRIANGLE_FAN || i%2 == 0 ) tess->_indices.push_back( first );
-				tess->_indices.push_back( prev );
-				if ( tess->_curMode == GL_TRIANGLE_STRIP )
-				{
-					if ( i%2 == 1) tess->_indices.push_back( first );
-					first = prev;
-				}
-				prev = tess->_curIndices[i];
-				tess->_indices.push_back( prev );
-			}
-		}
-		break;
-	default: std::cerr << "CityGML tesselator: non-supported GLU tesselator primitive " << tess->_curMode << std::endl;
-	}
-	tess->_curIndices.clear();
-}
-
-void CALLBACK Tesselator::errorCallback( GLenum errorCode, void* /*userData*/ )
-{
-	std::cerr << "CityGML tesselator error: " << gluErrorString( errorCode ) << std::endl;
-}
diff --git a/src/tesselator.h b/src/tesselator.h
deleted file mode 100644
index a454829..0000000
--- a/src/tesselator.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -*-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 <windows.h>
-#else
-#	define CALLBACK
-#	define APIENTRY
-#endif
-
-#ifdef __APPLE__
-  #include <OpenGL/glu.h>
-#else
-  #include <GL/glu.h>
-#endif
-
-#include "vecs.h"
-#include <vector>
-
-// GLU based polygon tesselator
-class Tesselator 
-{		
-public:
-	Tesselator( void ); 
-	~Tesselator( void );
-
-	void init( unsigned int verticesCount, const TVec3d& normal, GLenum winding_rule = GLU_TESS_WINDING_ODD );
-
-	// Add a new contour - add the exterior ring first, then interiors 
-	void addContour( const std::vector<TVec3d>&, const std::vector<TVec2f>& );
-
-	// Let's tesselate!
-	void compute( void );
-
-	// Tesselation result access
-	inline const std::vector<TVec3d>& getVertices( void ) const { return _vertices; }
-	inline const std::vector<TVec2f>& getTexCoords( void ) const { return _texCoords; }
-	inline const std::vector<unsigned int>& getIndices( void ) const { return _indices; }
-
-private:
-	typedef void (APIENTRY *GLU_TESS_CALLBACK)();
-	static void CALLBACK beginCallback( GLenum, void* );
-	static void CALLBACK vertexCallback( 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::vector<TVec3d> _vertices;		
-	std::vector<TVec2f> _texCoords;
-	std::vector<unsigned int> _indices;
-
-	std::vector<unsigned int> _curIndices;
-};
-
-#endif // __TESSELATOR_H__
diff --git a/src/transform.h b/src/transform.h
deleted file mode 100644
index 8bf3172..0000000
--- a/src/transform.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*-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 __TRANSFORM_H__
-#define __TRANSFORM_H__
-
-#include "citygml.h"
-#ifdef USE_GDAL
-#	include "ogrsf_frmts.h"
-#endif
-
-class GeoTransform 
-{
-public:
-	GeoTransform( const std::string& sourceURN, const std::string& destURN ) : _sourceURN( sourceURN ), _destURN( destURN )
-	{
-#ifdef USE_GDAL
-		_sourceSRS = getProjection( _sourceURN );
-		_destSRS = getProjection( _destURN );
-		_trans = ( _sourceSRS && _destSRS ) ? OGRCreateCoordinateTransformation( (OGRSpatialReference*)_sourceSRS, (OGRSpatialReference*)_destSRS ) : 0;
-#else
-		_sourceSRS = 0;
-		_destSRS = 0;
-		_trans = 0;
-#endif
-	}
-
-	~GeoTransform( void )
-	{
-#ifdef USE_GDAL
-		if ( _sourceSRS ) OSRDestroySpatialReference( _sourceSRS );
-		if ( _destSRS ) OSRDestroySpatialReference( _destSRS );
-		if ( _trans ) OCTDestroyCoordinateTransformation( _trans );
-#endif
-	}
-
-#ifdef USE_GDAL
-	inline void transform( TVec3d &p ) const
-	{
-		if ( _trans ) ((OGRCoordinateTransformation*)_trans)->Transform( 1, &p.x, &p.y );
-#else
-	inline void transform( TVec3d & ) const
-	{
-#endif
-	}
-
-#ifdef USE_GDAL
-	inline void transform( TVec2d &p ) const
-	{
-		if ( _trans ) ((OGRCoordinateTransformation*)_trans)->Transform( 1, &p.x, &p.y );
-#else
-	inline void transform( TVec2d & ) const
-	{
-#endif
-	}
-
-	inline const std::string& getSourceURN( void ) const { return _sourceURN; }
-
-	inline const std::string& getDestURN( void ) const { return _destURN; }
-
-#ifdef USE_GDAL
-	static void* getProjection( const std::string &str )
-	{
-		OGRSpatialReference* proj = (OGRSpatialReference*)OSRNewSpatialReference(0);
-		OGRErr err = proj->SetFromUserInput( str.c_str() );
-		if ( err == OGRERR_NONE ) return proj;
-
-		delete proj; 
-		std::cerr << "Error : Unable to create projection from definition " << str << " (error code: " << err << ")" << std::endl
-			<< "        Did you correctly set the GDAL_DATA env. var?" << std::endl;
-		return 0;
-	}
-#endif
-
-private:
-	std::string _sourceURN;
-	std::string _destURN;
-	void* _sourceSRS;
-	void* _destSRS;
-	void* _trans;
-};
-
-#endif // __TRANSFORM_H__
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 7938a77..fca674f 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,57 +2,42 @@ IF(WIN32)
     SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
 ENDIF()
 
-IF( LIBCITYGML_USE_XERCESC )
-	FIND_PACKAGE( Xerces REQUIRED )
-	ADD_DEFINITIONS( -DUSE_XERCESC )
-	SET( LIBXML2_INCLUDE_DIR "" )
-	SET( LIBXML2_LIBRARIES "" )
-ENDIF( LIBCITYGML_USE_XERCESC )
-
-IF( LIBCITYGML_USE_LIBXML2 )
-	FIND_PACKAGE( LibXml2 REQUIRED )
-	ADD_DEFINITIONS( -DUSE_LIBXML2 )
-	ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS} )
-	SET( XERCESC_INCLUDE "" )
-	SET( XERCESC_LIBRARY "" )
-ENDIF( LIBCITYGML_USE_LIBXML2 )
-
 FIND_PACKAGE( OpenGL REQUIRED )
 #FIND_PACKAGE( GLU REQUIRED ) # deprecated, GLU is now found with FindOpenGL
 
 IF( COMMAND cmake_policy )
-	cmake_policy( SET CMP0003 NEW )
+  cmake_policy( SET CMP0003 NEW )
 ENDIF( COMMAND cmake_policy )
 
 IF( LIBCITYGML_STATIC )
-	ADD_DEFINITIONS( -DLIBCITYGML_STATIC )
+  ADD_DEFINITIONS( -DLIBCITYGML_STATIC )
 ENDIF( LIBCITYGML_STATIC )
 
 IF( LIBCITYGML_DYNAMIC )
-	ADD_DEFINITIONS( -DLIBCITYGML_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 )
+  #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( ../include )
+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 "../" )
+  # SET_TARGET_PROPERTIES( citygmltest PROPERTIES PREFIX "../" )
 # ENDIF( MSVC_IDE )
 
-TARGET_LINK_LIBRARIES( citygmltest citygml ${XERCESC_LIBRARY} ${LIBXML2_LIBRARIES} ${OPENGL_LIBRARIES} )
+TARGET_LINK_LIBRARIES( citygmltest citygml ${XERCESC_LIBRARY} ${OPENGL_LIBRARIES} )
diff --git a/test/citygml2vrml/CMakeLists.txt b/test/citygml2vrml/CMakeLists.txt
deleted file mode 100644
index e192583..0000000
--- a/test/citygml2vrml/CMakeLists.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-IF(WIN32)
-    SET(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /NODEFAULTLIB:MSVCRT")
-ENDIF()
-
-IF( LIBCITYGML_USE_XERCESC )
-	FIND_PACKAGE( Xerces REQUIRED )
-	ADD_DEFINITIONS( -DUSE_XERCESC )
-	SET( LIBXML2_INCLUDE_DIR "" )
-	SET( LIBXML2_LIBRARIES "" )
-ENDIF( LIBCITYGML_USE_XERCESC )
-
-IF( LIBCITYGML_USE_LIBXML2 )
-	FIND_PACKAGE( LibXml2 REQUIRED )
-	ADD_DEFINITIONS( -DUSE_LIBXML2 )
-	ADD_DEFINITIONS( ${LIBXML2_DEFINITIONS} )
-	SET( XERCESC_INCLUDE "" )
-	SET( XERCESC_LIBRARY "" )
-ENDIF( LIBCITYGML_USE_LIBXML2 )
-
-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( ../../include )
-
-SET( PRG_SRCS citygml2vrml.cpp )
-
-ADD_EXECUTABLE( citygml2vrml ${PRG_SRCS} )
-
-IF( MSVC_IDE )
-	# SET_TARGET_PROPERTIES( citygml2vrml PROPERTIES PREFIX "../" )
-	SET_TARGET_PROPERTIES( citygml2vrml PROPERTIES LINK_FLAGS "" )
-ENDIF( MSVC_IDE )
-
-TARGET_LINK_LIBRARIES( citygml2vrml citygml ${XERCESC_LIBRARY} ${LIBXML2_LIBRARIES} ${OPENGL_LIBRARIES} )
diff --git a/test/citygml2vrml/citygml2vrml.cpp b/test/citygml2vrml/citygml2vrml.cpp
deleted file mode 100644
index 4906b8d..0000000
--- a/test/citygml2vrml/citygml2vrml.cpp
+++ /dev/null
@@ -1,365 +0,0 @@
-/* -*-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 <iostream>
-#include <fstream>
-#include <time.h> 
-#include <algorithm>
-#include "citygml.h"
-
-// VRML97 Helper class to produce a hierarchy of VRML nodes with attributes 
-class VRML97Printer 
-{
-public:
-	VRML97Printer( citygml::CityModel* city ) : _cityModel( city ), _indentCount( 0 ) {}
-
-	bool save( const std::string& outFilename );
-
-private:
-	void dumpCityObject( const citygml::CityObject* );
-
-	void dumpGeometry( const citygml::CityObject*, const citygml::Geometry* );
-
-	void dumpPolygon( const citygml::CityObject*, const citygml::Geometry*, const citygml::Polygon* );
-
-protected:
-	inline void addHeader( void ) { _out << "#VRML V2.0 utf8" << std::endl; }
-
-	inline void printIndent( void ) { for ( int i = 0; i < _indentCount; i++ ) _out << "\t"; }
-
-	inline void addComment(const std::string& cmt) {  printIndent(); _out << "# " << cmt << std::endl; }
-
-	inline void beginNode( const std::string &node ) { printIndent(); _out << node << " {" << std::endl; _indentCount++; }
-
-	inline void endNode( void ) { _indentCount--; printIndent(); _out << "}" << std::endl; }
-
-	inline void addAttribute( const std::string &attr ) { printIndent(); _out << attr << " "; }
-
-	template<class T> inline void addAttributeValue( const std::string &attr, T val ) { printIndent(); _out << attr << " " << val << std::endl; }
-
-	inline void addAttributeValue( const std::string &attr, const char* val ) { printIndent(); _out << attr << " " << val << std::endl; }
-
-	inline void beginAttributeNode( const std::string &attr, const std::string &node ) { printIndent(); _out << attr << " " << node << " {" << std::endl; _indentCount++; }
-
-	inline void beginAttributeArray( const std::string &attr ) { addAttribute( attr ); _out << " [" << std::endl; _indentCount++; }
-
-	inline void endAttributeArray( void ) { _indentCount--; printIndent(); _out << "]" << std::endl; }
-
-	inline void beginGroup( void ) { beginNode("Group"); beginAttributeArray( "children" ); }
-
-	inline void endGroup( void ) { endAttributeArray(); endNode(); }
-
-private:
-	citygml::CityModel* _cityModel;
-	int _indentCount;
-	std::ofstream _out;
-};
-
-bool g_comments = false;
-bool g_center = false;
-
-void usage() 
-{
-	std::cout << std::endl << "This program converts CityGML files to a VRML97 representation" << std::endl;
-	std::cout << "More info & updates on http://code.google.com/p/libcitygml" << std::endl;
-	std::cout << "Version built on " << __DATE__ << " at " << __TIME__ << " with libcitygml v." << LIBCITYGML_VERSIONSTR << std::endl << std::endl;
-	std::cout << " Usage: citygml2vrml [-options...] <input.gml> [output.wrl]" << std::endl; 
-	std::cout << " Options:" << std::endl;
-	std::cout << "  -optimize       Merge geometries & polygons with similar properties to" << std::endl
-		<< "                  reduce file & scene size (recommended)" << std::endl;
-	std::cout << "  -comments       Add comments about the object ids to the VRML file" << std::endl;
-	std::cout << "  -center         Center the model around the first encountered point" << std::endl
-		<< "                  (may be used to reduce z-fighting artifacts)" << std::endl;
-	std::cout << "  -filter <mask>  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 << "  -minLOD <level> Minimum LOD level to parse (default:0)" << std::endl;
-	std::cout << "  -maxLOD <level> Maximum LOD level to parse (default:4)" << std::endl;
-	std::cout << "  -destSRS <srs> Destination SRS (default: no transform)" << std::endl;
-	exit( EXIT_FAILURE );
-}
-
-int main( int argc, char **argv )
-{
-	std::cout << "citygml2vrml v." << LIBCITYGML_VERSIONSTR << " (c) 2010 Joachim Pouderoux, BRGM" << std::endl;
-
-	int fargc = 1;
-
-	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 == "-optimize" ) { params.optimize = true; fargc = i+1; }
-		if ( param == "-comments" ) { g_comments = true; fargc = i+1; }
-		if ( param == "-center" ) { g_center = true; fargc = i+1; }
-		if ( param == "-filter" ) { if ( i == argc - 1 ) usage(); params.objectsMask = argv[i+1]; i++; fargc = i+1; }
-		if ( param == "-minlod" ) { if ( i == argc - 1 ) usage(); params.minLOD = atoi( argv[i+1] ); i++; fargc = i+1; }
-		if ( param == "-maxlod" ) { if ( i == argc - 1 ) usage(); params.maxLOD = atoi( 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] << "..." << std::endl;
-
-	time_t start;
-	time( &start );
-
-	citygml::CityModel *city = citygml::load( argv[fargc], params );
-
-	time_t end;
-	time( &end );
-
-	if ( !city ) return EXIT_FAILURE;
-
-	std::cout << "Done in " << difftime( end, start ) << " seconds." << std::endl << city->size() << " city objects read." << std::endl;
-
-	std::cout << city->getCityObjectsRoots().size() << " root nodes" << std::endl;
-	if ( city->getSRSName() != "" ) std::cout << "The actual model SRS is " << city->getSRSName() << std::endl;
-	
-	std::string outfile;
-	if ( argc - fargc == 1 ) 
-	{
-		outfile = argv[ fargc ];
-		outfile = outfile.substr( 0, outfile.find_last_of( "." ) ) + ".wrl";
-	}
-	else outfile = argv[ fargc + 1 ];
-	
-	std::cout << "Converting the city model to VRML97 file " << outfile << "..." << std::endl;
-
-	VRML97Printer printer( city );
-
-	if ( printer.save( outfile ) )
-		std::cout << "Done." << std::endl;
-	else 
-		std::cout << "Failed!" << std::endl;
-
-	return EXIT_SUCCESS;
-}
-
-// VRML97 city converter
-
-bool VRML97Printer::save( const std::string& outFilename )
-{
-	if ( !_cityModel ) return false;
-
-	_out.open( outFilename.c_str() );
-
-	if ( _out.fail() ) { std::cerr << "Unable to create file " << outFilename << "!" << std::endl; return false; }
-
-	addHeader();
-
-	addComment( "Converted from a CityGML model using citygml2vrml (http://code.google.com/p/libcitygml)\n" );
-
-#define RECURSIVE_DUMP
-
-#ifndef RECURSIVE_DUMP
-	const citygml::CityObjectsMap& cityObjectsMap = _cityModel->getCityObjectsMap();
-
-	citygml::CityObjectsMap::const_iterator it = cityObjectsMap.begin();
-
-	for ( ; it != cityObjectsMap.end(); it++ )
-	{
-		const citygml::CityObjects& v = it->second;
-
-		std::cout << " Creation of " << v.size() << " " << citygml::getCityObjectsClassName( it->first ) << ( ( v.size() > 1 ) ? "s" : "" ) << "..." << std::endl;
-
-		addComment( "Object type: " + citygml::getCityObjectsClassName( it->first ) + ( ( v.size() > 1 ) ? "s" : "" ) );
-		
-		beginGroup();
-		for ( unsigned int i = 0; i < v.size(); i++ ) dumpCityObject( v[i] );
-		endGroup();
-	}
-#else
-	const citygml::CityObjects& roots = _cityModel->getCityObjectsRoots();
-
-	for ( unsigned int i = 0; i < roots.size(); i++ ) dumpCityObject( roots[i] );
-#endif
-
-	_out.close();
-
-	return true;
-}
-
-void VRML97Printer::dumpCityObject( const citygml::CityObject* object ) 
-{
-	if ( !object ) return;
-
-	if ( g_comments ) addComment(  object->getTypeAsString() + ": " + object->getId() );
-
-	beginGroup();	
-
-	for ( unsigned int i = 0; i < object->size(); i++ ) dumpGeometry( object, object->getGeometry( i ) );
-
-#ifdef RECURSIVE_DUMP
-	for ( unsigned int i = 0; i < object->getChildCount(); i++ ) dumpCityObject( object->getChild( i ) );
-#endif
-
-	endGroup();
-}
-
-void VRML97Printer::dumpGeometry( const citygml::CityObject* object, const citygml::Geometry* g )
-{
-	if ( !g ) return;
-
-	if ( g_comments ) addComment( "Geometry: " + g->getId() );
-
-	for ( unsigned int i = 0; i < g->size(); i++ ) dumpPolygon( object, g, (*g)[i] );
-}
-
-void VRML97Printer::dumpPolygon( const citygml::CityObject* object, const citygml::Geometry* g, const citygml::Polygon* p )
-{
-	static bool s_isFirstVert = true;
-	static TVec3d s_firstVert;
-
-	if ( !p || p->getIndices().size() == 0 ) return;
-
-	if ( g_comments ) 
-	{
-		std::stringstream ss;
-		ss << "  " << p->getVertices().size() << " points, " << p->getIndices().size()/3 << " triangles, " << p->getNormals().size() << " normals, " << p->getTexCoords().size() << " texCoords";
-		addComment( "Polygon: " + p->getId() + ss.str() );
-	}
-
-	beginNode( "Shape" );
-
-	// Geometry management
-	beginAttributeNode( "geometry", "IndexedFaceSet" );
-
-	{
-		const std::vector<TVec3d>& vertices = p->getVertices();
-		beginAttributeNode( "coord", "Coordinate" );
-		beginAttributeArray( "point" );
-		printIndent();
-		if ( !g_center )
-		{
-			for ( unsigned int k = 0; k < vertices.size(); k++ ) _out << vertices[k] << ", ";
-		}
-		else 
-		{
-			if ( s_isFirstVert ) { s_firstVert = vertices[0]; s_isFirstVert = false; }
-			for ( unsigned int k = 0; k < vertices.size(); k++ ) _out << ( vertices[k] - s_firstVert ) << ", ";
-		}
-
-		_out << std::endl;
-		endAttributeArray();
-		endNode();
-	}
-
-	{
-		const std::vector<unsigned int>& indices = p->getIndices();
-		beginAttributeArray( "coordIndex" );
-		printIndent();
-		for ( unsigned int k = 0 ; k < indices.size() / 3; k++ )
-			_out << indices[ k * 3 + 0 ] << " " << indices[ k * 3 + 1 ] << " " << indices[ k * 3 + 2 ] << " -1, ";
-		_out << std::endl;
-		endAttributeArray();
-	}
-
-	// Normal management
-	if ( p->getNormals().size() > 0 )
-	{
-		const std::vector<TVec3f>& normals = p->getNormals();
-		beginAttributeNode( "normal", "Normal" );
-		beginAttributeArray( "vector" );
-		printIndent();
-		for ( unsigned int k = 0 ; k < normals.size(); k++ ) _out << normals[k] << ", ";
-		_out << std::endl;
-		endAttributeArray();
-		endNode();
-		addAttributeValue( "normalPerVertex", "TRUE" );
-	}
-
-	addAttributeValue( "solid", "FALSE" ); //draw both sides of faces
-
-	// Texture coordinates
-	if ( dynamic_cast<const citygml::Texture*>( p->getAppearance() ) && p->getTexCoords().size() > 0 )
-	{
-		const citygml::TexCoords& texCoords = p->getTexCoords();
-		beginAttributeNode( "texCoord", "TextureCoordinate" );
-
-		beginAttributeArray( "point" );
-		printIndent();
-		for ( unsigned int k = 0; k < texCoords.size(); k++ ) _out << texCoords[k] << ", ";
-		_out << std::endl;
-		endAttributeArray();
-
-		endNode();
-	}
-
-	endNode();
-
-	// Material management
-	{
-		beginAttributeNode( "appearance", "Appearance" );
-
-		bool colorset = false;
-
-		const citygml::Appearance *mat = p->getAppearance();
-
-		if ( const citygml::Material* m = dynamic_cast<const citygml::Material*>( mat ) )
-		{
-			beginAttributeNode( "material", "Material" );
-
-			addAttributeValue( "diffuseColor", m->getDiffuse() );
-			addAttributeValue( "ambientIntensity", m->getAmbientIntensity() );
-			addAttributeValue( "specularColor", m->getSpecular() );
-			addAttributeValue( "emissiveColor", m->getEmissive() );
-			addAttributeValue( "shininess", m->getShininess() );
-			addAttributeValue( "transparency", m->getTransparency() );
-
-			endNode();
-			colorset = true;
-		}
-
-		if ( const citygml::Texture* t = dynamic_cast<const citygml::Texture*>( mat ) ) 
-		{
-			beginAttributeNode( "texture", "ImageTexture" );
-			addAttributeValue( "url", "\"" + t->getUrl() + "\"" );
-			endNode();
-			colorset = true;
-		}
-
-		if ( !colorset )
-		{
-			beginAttributeNode( "material", "Material" );
-
-			TVec4f color( object->getDefaultColor().rgba );
-			if ( g->getType() == citygml::GT_Roof ) color = TVec4f( 0.9f, 0.1f, 0.1f, 1.f );
-			TVec3f crgb( color.r, color.g, color.b );
-			addAttributeValue( "diffuseColor", crgb );
-			if ( color.a != 1.f  ) addAttributeValue( "transparency", 1.f - color.a );
-
-			endNode();
-		}
-
-		endNode();
-	}
-
-	// That's it!		
-	endNode();
-}
diff --git a/test/citygmltest.cpp b/test/citygmltest.cpp
index f98180d..74811d4 100644
--- a/test/citygmltest.cpp
+++ b/test/citygmltest.cpp
@@ -16,117 +16,118 @@
 
 #include <iostream>
 #include <fstream>
-#include <time.h> 
+#include <time.h>
 #include <algorithm>
-#include "citygml.h"
+#include <citygml/citygml.h>
+#include <citygml/citymodel.h>
+#include <citygml/cityobject.h>
 
 void analyzeObject( const citygml::CityObject*, unsigned int );
 
-void usage() 
+void usage()
 {
-	std::cout << "Usage: citygmltest [-options...] <filename>" << std::endl;
-	std::cout << " Options:" << std::endl;
-	std::cout << "  -log            Print some informations during parsing" << std::endl;
-	std::cout << "  -filter <mask>  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 <srs> Destination SRS (default: no transform)" << std::endl;
-	exit( EXIT_FAILURE );
+    std::cout << "Usage: citygmltest [-options...] <filename>" << std::endl;
+    std::cout << " Options:" << std::endl;
+    std::cout << "  -log            Print some informations during parsing" << std::endl;
+    std::cout << "  -filter <mask>  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 <srs> Destination SRS (default: no transform)" << std::endl;
+    exit( EXIT_FAILURE );
 }
 
 int main( int argc, char **argv )
 {
-	if ( argc < 2 ) usage();
+    if ( argc < 2 ) usage();
 
-	int fargc = 1;
+    int fargc = 1;
 
-	bool log = false;
+    bool log = false;
 
-	citygml::ParserParams params;
+    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; }
-	}
+    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();
+    if ( argc - fargc < 1 ) usage();
 
-	std::cout << "Parsing CityGML file " << argv[fargc] << " using libcitygml v." << LIBCITYGML_VERSIONSTR << "..." << std::endl;
+    std::cout << "Parsing CityGML file " << argv[fargc] << " using libcitygml v." << LIBCITYGML_VERSIONSTR << "..." << std::endl;
 
-	time_t start;
-	time( &start );
+    time_t start;
+    time( &start );
 
 #if 0
-	std::ifstream file;
-	file.open( argv[fargc], std::ifstream::in );
-	citygml::CityModel *city = citygml::load( file, params );
+    std::ifstream file;
+    file.open( argv[fargc], std::ifstream::in );
+     std::shared_ptr<const citygml::CityModel> city = citygml::load( file, params );
 #else
-	citygml::CityModel *city = citygml::load( argv[fargc], params );
+    std::shared_ptr<const citygml::CityModel> city = citygml::load( argv[fargc], params );
 #endif
 
-	time_t end;
-	time( &end );
+    time_t end;
+    time( &end );
 
-	if ( !city ) return EXIT_FAILURE;
+    if ( !city ) return EXIT_FAILURE;
 
-	std::cout << "Done in " << difftime( end, start ) << " seconds." << std::endl << city->size() << " city objects read." << std::endl;
+    std::cout << "Done in " << difftime( end, start ) << " seconds." << std::endl;
 
-	std::cout << "Analyzing the city objects..." << std::endl;
+    /*
+    std::cout << "Analyzing the city objects..." << std::endl;
 
+    citygml::CityObjectsMap::const_iterator it = cityObjectsMap.begin();
 
-	const citygml::CityObjectsMap& cityObjectsMap = city->getCityObjectsMap();
+    for ( ; it != cityObjectsMap.end(); ++it )
+    {
+        const citygml::CityObjects& v = it->second;
 
-	citygml::CityObjectsMap::const_iterator it = cityObjectsMap.begin();
+        std::cout << ( log ? " Analyzing " : " Found " ) << v.size() << " " << citygml::getCityObjectsClassName( it->first ) << ( ( v.size() > 1 ) ? "s" : "" ) << "..." << std::endl;
 
-	for ( ; it != cityObjectsMap.end(); ++it )
-	{
-		const citygml::CityObjects& v = it->second;
+        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;
+            }
+        }
+    }
+    */
 
-		std::cout << ( log ? " Analyzing " : " Found " ) << v.size() << " " << citygml::getCityObjectsClassName( it->first ) << ( ( v.size() > 1 ) ? "s" : "" ) << "..." << std::endl;
+    if ( log )
+    {
+        std::cout << std::endl << "Objects hierarchy:" << std::endl;
+        const citygml::ConstCityObjects& roots = city->getRootCityObjects();
 
-		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;
-			}
-		}
-	}
+//        for ( unsigned int i = 0; i < roots.size(); i++ ) analyzeObject( roots[ i ], 2 );
+    }
 
-	if ( log ) 
-	{
-		std::cout << std::endl << "Objects hierarchy:" << std::endl;
-		const citygml::CityObjects& roots = city->getCityObjectsRoots();
+    std::cout << "Done." << std::endl;
 
-		for ( unsigned int i = 0; i < roots.size(); i++ ) analyzeObject( roots[ i ], 2 );
-	}
-
-	std::cout << "Done." << std::endl;
-
-	return EXIT_SUCCESS;
+    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 < 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 );
+//    for ( unsigned int i = 0; i < object->getChildCount(); i++ )
+//        analyzeObject( object->getChild(i), indent+1 );
 }
diff --git a/test/osgplugin/CMakeLists.txt b/test/osgplugin/CMakeLists.txt
deleted file mode 100644
index a382262..0000000
--- a/test/osgplugin/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-FIND_PACKAGE( CityGML REQUIRED )
-
-INCLUDE_DIRECTORIES( ${OSG_INCLUDE_DIRS} ${CITYGML_INCLUDE_DIR} )
-
-SET( TARGET_SRC ReaderWriterCityGML.cpp )
-
-SET( TARGET_ADDED_LIBRARIES osgText )
-SET( TARGET_LIBRARIES_VARS CITYGML_LIBRARY XERCESC_LIBRARY LIBXML2_LIBRARY OPENGL_glu_LIBRARY )
-
-SETUP_PLUGIN( citygml )
diff --git a/test/osgplugin/ReaderWriterCityGML.cpp b/test/osgplugin/ReaderWriterCityGML.cpp
deleted file mode 100644
index 9cffe3c..0000000
--- a/test/osgplugin/ReaderWriterCityGML.cpp
+++ /dev/null
@@ -1,478 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// 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 <osg/Array>
-#include <osg/Node>
-#include <osg/MatrixTransform>
-#include <osg/Geode>
-#include <osg/Geometry>
-#include <osg/StateSet>
-#include <osg/BlendFunc>
-#include <osg/BlendColor>
-#include <osg/Material>
-#include <osg/Texture2D>
-#include <osg/TexGen>
-#include <osg/TexMat>
-#include <osg/Depth>
-#include <osg/LightModel>
-
-#include <osgText/Font>
-#include <osgText/Text>
-
-#include <osgDB/Registry>
-#include <osgDB/ReadFile>
-#include <osgDB/WriteFile>
-#include <osgDB/FileUtils>
-#include <osgDB/FileNameUtils>
-
-#include "citygml.h"
-
-#include <algorithm>
-#include <cctype> 
-
-
-class ReaderWriterCityGML : public osgDB::ReaderWriter
-{
-public:
-	ReaderWriterCityGML( void )
-	{ 
-		supportsExtension( "citygml", "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" );
-	}
-
-	virtual const char* className( void ) const { return "CityGML Reader"; }
-
-	virtual ReadResult readNode( const std::string&, const osgDB::ReaderWriter::Options* ) const;
-	virtual ReadResult readNode( std::istream&, const osgDB::ReaderWriter::Options* ) const;
-
-private:
-	class Settings 
-	{
-	public:
-		Settings( void ) : _printNames( false ),
-			_first(true), _origin( 0.f, 0.f, 0.f ),
-             _useMaxLODOnly(false){}
-
-		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;		
-			}
-		}
-
-	public:
-		citygml::ParserParams _params;
-		bool _printNames;
-		bool _first;
-        bool _useMaxLODOnly;
-		osg::Vec3 _origin;
-		std::map< std::string, osg::Texture2D* > _textureMap;
-	};
-
-    static unsigned int getHighestLodForObject( const citygml::CityObject * object);
-
-private:
-	ReadResult readCity( const citygml::CityModel *, Settings& ) const;
-	bool createCityObject( const citygml::CityObject*, Settings&, osg::Group*, 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;
-	}
-
-	Settings 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;
-
-	citygml::CityModel *city = citygml::load( fileName, settings._params );
-
-    ReadResult rr = readCity( city, settings );
-
-	if ( rr.status() == ReadResult::FILE_LOADED && rr.getNode() )
-		rr.getNode()->setName( fileName );
-
-	delete city;
-
-	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
-{
-	Settings 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;
-
-	citygml::CityModel *city = citygml::load( fin, settings._params );
-	
-	ReadResult rr = readCity( city, settings );
-
-	delete city;
-
-	// Restore cout/cerr streams
-	std::cout.rdbuf( coutsb );
-	std::cerr.rdbuf( cerrsb );
-
-	return rr;
-}
-
-osgDB::ReaderWriter::ReadResult ReaderWriterCityGML::readCity( const citygml::CityModel * city, Settings& settings ) const
-{
-	if ( !city ) return NULL;
-
-	osg::notify(osg::NOTICE) << city->size() << " city objects read." << std::endl;
-	
-	osg::notify(osg::NOTICE) << "Creation of the OSG city objects' geometry..." << std::endl;
-	
-	// Apply translation
-	const TVec3d& t = city->getTranslationParameters();
-	
-	osg::MatrixTransform *root = new osg::MatrixTransform();
-
-	root->setName( city->getId() );
-
-#define RECURSIVE_DUMP
-
-#ifndef RECURSIVE_DUMP
-	const citygml::CityObjectsMap& cityObjectsMap = city->getCityObjectsMap();
-	citygml::CityObjectsMap::const_iterator it = cityObjectsMap.begin();
-
-	for ( ; it != cityObjectsMap.end(); ++it )
-	{
-		const citygml::CityObjects& v = it->second;
-
-		osg::notify(osg::NOTICE) << " Creation of " << v.size() << " " << citygml::getCityObjectsClassName( it->first ) << ( ( v.size() > 1 ) ? "s" : "" ) << "..." << std::endl;
-
-		osg::Group* grp = new osg::Group;
-		grp->setName( citygml::getCityObjectsClassName( it->first ) );
-		root->addChild( grp );
-
-		for ( unsigned int i = 0; i < v.size(); ++i ){
-			createCityObject( v[i], settings, grp);	
-        }
-	}
-#else
-
-	const citygml::CityObjects& roots = city->getCityObjectsRoots();
-
-	for ( unsigned int i = 0; i < roots.size(); ++i ) createCityObject( roots[i], settings, root );
-#endif
-	
-	root->setMatrix(osg::Matrixd::translate(t.x + settings._origin.x(), t.y + settings._origin.y(), t.z + settings._origin.z()));
-
-	osg::notify(osg::NOTICE) << "Done." << std::endl;
-
-	return root;
-}
-
-bool ReaderWriterCityGML::createCityObject( const citygml::CityObject* object, Settings& settings, osg::Group* parent, unsigned int minimumLODToConsider ) const
-{
-	// Skip objects without geometry
-	if ( !object || !parent ) return false;
-
-	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
-	geode->setName( object->getId() );
-
-#ifdef RECURSIVE_DUMP
-	osg::Group* grp = new osg::Group;
-	grp->setName( object->getId() );
-	grp->addChild( geode );
-	parent->addChild( grp );
-#else
-	parent->addChild( geode );
-#endif
-
-	// Get the default color for the whole city object
-	osg::ref_ptr<osg::Vec4Array> shared_colors = new osg::Vec4Array;
-	shared_colors->push_back( osg::Vec4( object->getDefaultColor().r, object->getDefaultColor().g, object->getDefaultColor().b, object->getDefaultColor().a ) );
-
-	osg::ref_ptr<osg::Vec4Array> 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->size(); i++ ) 
-	{
-		const citygml::Geometry& geometry = *object->getGeometry( i );
-
-        const unsigned int currentLOD = geometry.getLOD();
-
-        if (settings._useMaxLODOnly && (currentLOD < highestLOD || currentLOD < minimumLODToConsider )){
-            continue;
-        }
-
-		for ( unsigned int j = 0; j < geometry.size(); j++ ) 
-		{
-			const citygml::Polygon* p = geometry[j];
-            
-			if ( p->getIndices().size() == 0 ) continue;
-
-			// Geometry management
-
-			osg::Geometry* geom = new osg::Geometry;
-
-			// Vertices
-			osg::Vec3Array* vertices = new osg::Vec3Array;
-			const std::vector<TVec3d>& vert = p->getVertices();
-			vertices->reserve( vert.size() );
-			for ( unsigned int k = 0; k < vert.size(); k++ )
-			{
-				osg::Vec3d pt( vert[k].x, vert[k].y, vert[k].z );
-                if ( settings._first )
-				{
-					settings._origin.set( pt );
-					settings._first = false;
-				}
-				vertices->push_back( pt - settings._origin );
-			}
-
-			geom->setVertexArray( vertices );
-
-			// Indices
-			osg::DrawElementsUInt* indices = new osg::DrawElementsUInt( osg::PrimitiveSet::TRIANGLES, 0 );
-			const std::vector<unsigned int>& ind = p->getIndices();
-			indices->reserve( ind.size() );
-			for ( unsigned int i = 0 ; i < ind.size() / 3; i++ )
-			{
-				indices->push_back( ind[ i * 3 + 0 ] );
-				indices->push_back( ind[ i * 3 + 1 ] );
-				indices->push_back( ind[ i * 3 + 2 ] );	
-			}
-
-			geom->addPrimitiveSet( indices );
-
-			// Normals			
-			osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array;
-			const std::vector<TVec3f>& norm = p->getNormals();
-			normals->reserve( norm.size() );
-			for ( unsigned int k = 0; k < norm.size(); k++ )
-				normals->push_back( osg::Vec3( norm[k].x, norm[k].y, norm[k].z ) );
-
-			geom->setNormalArray( normals.get() );
-			geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
-
-			// Material management
-
-			osg::ref_ptr<osg::StateSet> stateset = geom->getOrCreateStateSet();
-
-			const citygml::Appearance *mat = p->getAppearance();
-
-			bool colorset = false;
-
-			if ( mat )
-			{
-				shared_colors->clear();
-				shared_colors->push_back( osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
-
-				if ( const citygml::Material* m = dynamic_cast<const citygml::Material*>( mat ) )
-				{
-#define TOVEC4(_t_) osg::Vec4( _t_.r, _t_.g, _t_.b, _t_.a ) 
-					osg::ref_ptr<osg::Vec4Array> color = new osg::Vec4Array;
-					TVec4f diffuse( m->getDiffuse(), 0.f );
-					TVec4f emissive( m->getEmissive(), 0.f );
-					TVec4f specular( m->getSpecular(), 0.f );
-					float ambient = m->getAmbientIntensity();
-
-					osg::Material* material = new osg::Material;
-					material->setColorMode( osg::Material::OFF );
-					material->setDiffuse( osg::Material::FRONT_AND_BACK, TOVEC4( diffuse ) );
-					material->setSpecular( osg::Material::FRONT_AND_BACK, TOVEC4( specular ) );
-					material->setEmission( osg::Material::FRONT_AND_BACK, TOVEC4( emissive ) );					
-					material->setShininess( osg::Material::FRONT_AND_BACK, m->getShininess() );					
-					material->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( ambient, ambient, ambient, 1.0 ) );
-					material->setTransparency( osg::Material::FRONT_AND_BACK, m->getTransparency() );
-					stateset->setAttributeAndModes( material, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON );
-					stateset->setMode( GL_LIGHTING, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON );
-
-					colorset = true;
-				}
-				else if ( const citygml::Texture* t = dynamic_cast<const citygml::Texture*>( mat ) ) 
-				{
-					const citygml::TexCoords& texCoords = p->getTexCoords();
-
-					if ( texCoords.size() > 0 )
-					{
-						osg::Texture2D* texture = 0;
-
-						if ( settings._textureMap.find( t->getUrl() ) == settings._textureMap.end() )
-						{
-							// Load a new texture 
-							osg::notify(osg::NOTICE) << "  Loading texture " << t->getUrl() << "..." << std::endl;
-
-							if ( osg::Image* image = osgDB::readImageFile( t->getUrl() ) )
-							{
-								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 );
-							}
-							else
-								osg::notify(osg::NOTICE) << "  Warning: Texture " << t->getUrl() << " not found!" << std::endl;
-
-							settings._textureMap[ t->getUrl() ] = texture;
-						}
-						else
-							texture = settings._textureMap[ t->getUrl() ];
-
-						if ( texture )
-						{
-							osg::ref_ptr<osg::Vec2Array> 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 );
-
-							colorset = true;
-						}
-					}
-					else 
-						osg::notify(osg::NOTICE) << "  Warning: Texture coordinates not found for poly " << p->getId() << std::endl;
-				}
-			}
-
-			// Color management
-
-			geom->setColorArray( ( !colorset && geometry.getType() == citygml::GT_Roof ) ? roof_color.get() : shared_colors.get() );
-
-			geom->setColorBinding( osg::Geometry::BIND_OVERALL );
-#if 0
-			// Set lighting model to two sided
-			osg::ref_ptr< osg::LightModel > lightModel = new osg::LightModel;
-			lightModel->setTwoSided( true );
-			stateset->setAttributeAndModes( lightModel.get(), osg::StateAttribute::ON );
-#endif
-			// That's it!
-			geode->addDrawable( geom );			
-		}
-	}
-
-	if ( settings._printNames ) 
-	{
-		// Print the city object name on top of it
-		geode->getBoundingBox().center();
-		osg::ref_ptr<osgText::Text> 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::COT_Window )
-	{
-		osg::StateSet *geodeSS( geode->getOrCreateStateSet() );
-
-        osg::ref_ptr<osg::BlendFunc> 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<osg::BlendColor> blendColor = new osg::BlendColor(osg::Vec4( 1., 1., 1., object->getDefaultColor().a ));
-		geodeSS->setAttributeAndModes( blendColor.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON );
-
-        osg::ref_ptr<osg::Depth> depth = new osg::Depth;
-        depth->setWriteMask( false );
-        geodeSS->setAttributeAndModes( depth.get(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON );
-   
-		geodeSS->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
-	}
-
-#ifdef RECURSIVE_DUMP
-	for ( unsigned int i = 0; i < object->getChildCount(); ++i )
-        createCityObject( object->getChild(i), settings, grp, highestLOD);
-#endif
-
-	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->size(); i++) {
-        const citygml::Geometry &geometry = *object->getGeometry(i);
-
-        if (geometry.getLOD() > highestLOD){
-            highestLOD = geometry.getLOD();
-        }
-    }
-
-#ifdef RECURSIVE_DUMP
-    //check for the highest LODs of Children
-    for (unsigned int i = 0; i < object->getChildCount(); ++i){
-        unsigned int tempHighestLOD = ReaderWriterCityGML::getHighestLodForObject(object->getChild(i));
-        if (tempHighestLOD > highestLOD){
-            tempHighestLOD = highestLOD;
-        }            
-    }        
-#endif
-    return highestLOD;
-}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/libcitygml.git



More information about the Pkg-grass-devel mailing list