/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------

Copyright (c) 2006-2017, assimp team

All rights reserved.

Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.

* Redistributions in binary form must reproduce the above
  copyright notice, this list of conditions and the
  following disclaimer in the documentation and/or other
  materials provided with the distribution.

* Neither the name of the assimp team, nor the names of its
  contributors may be used to endorse or promote products
  derived from this software without specific prior
  written permission of the assimp team.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

----------------------------------------------------------------------
*/

/** @file  IFCLoad.cpp
 *  @brief Implementation of the Industry Foundation Classes loader.
 */


#ifndef ASSIMP_BUILD_NO_IFC_IMPORTER

#include <iterator>
#include <limits>
#include <tuple>

#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
#   include <contrib/unzip/unzip.h>
#endif

#include "IFCLoader.h"
#include "STEPFileReader.h"

#include "IFCUtil.h"

#include "MemoryIOWrapper.h"
#include <assimp/scene.h>
#include <assimp/Importer.hpp>
#include <assimp/importerdesc.h>


namespace Assimp {
    template<> const char* LogFunctions<IFCImporter>::Prefix()
    {
        static auto prefix = "IFC: ";
        return prefix;
    }
}

using namespace Assimp;
using namespace Assimp::Formatter;
using namespace Assimp::IFC;

/* DO NOT REMOVE this comment block. The genentitylist.sh script
 * just looks for names adhering to the IfcSomething naming scheme
 * and includes all matches in the whitelist for code-generation. Thus,
 * all entity classes that are only indirectly referenced need to be
 * mentioned explicitly.

  IfcRepresentationMap
  IfcProductRepresentation
  IfcUnitAssignment
  IfcClosedShell
  IfcDoor

 */

namespace {


// forward declarations
void SetUnits(ConversionData& conv);
void SetCoordinateSpace(ConversionData& conv);
void ProcessSpatialStructures(ConversionData& conv);
void MakeTreeRelative(ConversionData& conv);
void ConvertUnit(const EXPRESS::DataType& dt,ConversionData& conv);

} // anon

static const aiImporterDesc desc = {
    "Industry Foundation Classes (IFC) Importer",
    "",
    "",
    "",
    aiImporterFlags_SupportBinaryFlavour,
    0,
    0,
    0,
    0,
    "ifc ifczip stp"
};


// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
IFCImporter::IFCImporter()
{}

// ------------------------------------------------------------------------------------------------
// Destructor, private as well
IFCImporter::~IFCImporter()
{
}

// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool IFCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
{
    const std::string& extension = GetExtension(pFile);
    if (extension == "ifc" || extension == "ifczip" || extension == "stp" ) {
        return true;
    } else if ((!extension.length() || checkSig) && pIOHandler)   {
        // note: this is the common identification for STEP-encoded files, so
        // it is only unambiguous as long as we don't support any further
        // file formats with STEP as their encoding.
        const char* tokens[] = {"ISO-10303-21"};
        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
    }
    return false;
}

// ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader
const aiImporterDesc* IFCImporter::GetInfo () const
{
    return &desc;
}


// ------------------------------------------------------------------------------------------------
// Setup configuration properties for the loader
void IFCImporter::SetupProperties(const Importer* pImp)
{
    settings.skipSpaceRepresentations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_SKIP_SPACE_REPRESENTATIONS,true);
    settings.useCustomTriangulation = pImp->GetPropertyBool(AI_CONFIG_IMPORT_IFC_CUSTOM_TRIANGULATION,true);
    settings.conicSamplingAngle = std::min(std::max((float) pImp->GetPropertyFloat(AI_CONFIG_IMPORT_IFC_SMOOTHING_ANGLE, AI_IMPORT_IFC_DEFAULT_SMOOTHING_ANGLE), 5.0f), 120.0f);
	settings.cylindricalTessellation = std::min(std::max(pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IFC_CYLINDRICAL_TESSELLATION, AI_IMPORT_IFC_DEFAULT_CYLINDRICAL_TESSELLATION), 3), 180);
	settings.skipAnnotations = true;
}


// ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void IFCImporter::InternReadFile( const std::string& pFile,
    aiScene* pScene, IOSystem* pIOHandler)
{
    std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile));
    if (!stream) {
        ThrowException("Could not open file for reading");
    }


    // if this is a ifczip file, decompress its contents first
    if(GetExtension(pFile) == "ifczip") {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
        unzFile zip = unzOpen( pFile.c_str() );
        if(zip == NULL) {
            ThrowException("Could not open ifczip file for reading, unzip failed");
        }

        // chop 'zip' postfix
        std::string fileName = pFile.substr(0,pFile.length() - 3);

        std::string::size_type s = pFile.find_last_of('\\');
        if(s == std::string::npos) {
            s = pFile.find_last_of('/');
        }
        if(s != std::string::npos) {
            fileName = fileName.substr(s+1);
        }

        // search file (same name as the IFCZIP except for the file extension) and place file pointer there
        if(UNZ_OK == unzGoToFirstFile(zip)) {
            do {
                // get file size, etc.
                unz_file_info fileInfo;
                char filename[256];
                unzGetCurrentFileInfo( zip , &fileInfo, filename, sizeof(filename), 0, 0, 0, 0 );
                if (GetExtension(filename) != "ifc") {
                    continue;
                }
                uint8_t* buff = new uint8_t[fileInfo.uncompressed_size];
                LogInfo("Decompressing IFCZIP file");
                unzOpenCurrentFile( zip  );
                const int ret = unzReadCurrentFile( zip, buff, fileInfo.uncompressed_size);
                size_t filesize = fileInfo.uncompressed_size;
                if ( ret < 0 || size_t(ret) != filesize )
                {
                    delete[] buff;
                    ThrowException("Failed to decompress IFC ZIP file");
                }
                unzCloseCurrentFile( zip );
                stream.reset(new MemoryIOStream(buff,fileInfo.uncompressed_size,true));
                break;

                if (unzGoToNextFile(zip) == UNZ_END_OF_LIST_OF_FILE) {
                    ThrowException("Found no IFC file member in IFCZIP file (1)");
                }

            } while(true);
        }
        else {
            ThrowException("Found no IFC file member in IFCZIP file (2)");
        }

        unzClose(zip);
#else
        ThrowException("Could not open ifczip file for reading, assimp was built without ifczip support");
#endif
    }

    std::unique_ptr<STEP::DB> db(STEP::ReadFileHeader(stream));
    const STEP::HeaderInfo& head = static_cast<const STEP::DB&>(*db).GetHeader();

    if(!head.fileSchema.size() || head.fileSchema.substr(0,3) != "IFC") {
        ThrowException("Unrecognized file schema: " + head.fileSchema);
    }

    if (!DefaultLogger::isNullLogger()) {
        LogDebug("File schema is \'" + head.fileSchema + '\'');
        if (head.timestamp.length()) {
            LogDebug("Timestamp \'" + head.timestamp + '\'');
        }
        if (head.app.length()) {
            LogDebug("Application/Exporter identline is \'" + head.app  + '\'');
        }
    }

    // obtain a copy of the machine-generated IFC scheme
    EXPRESS::ConversionSchema schema;
    GetSchema(schema);

    // tell the reader which entity types to track with special care
    static const char* const types_to_track[] = {
        "ifcsite", "ifcbuilding", "ifcproject"
    };

    // tell the reader for which types we need to simulate STEPs reverse indices
    static const char* const inverse_indices_to_track[] = {
        "ifcrelcontainedinspatialstructure", "ifcrelaggregates", "ifcrelvoidselement", "ifcreldefinesbyproperties", "ifcpropertyset", "ifcstyleditem"
    };

    // feed the IFC schema into the reader and pre-parse all lines
    STEP::ReadFile(*db, schema, types_to_track, inverse_indices_to_track);
    const STEP::LazyObject* proj =  db->GetObject("ifcproject");
    if (!proj) {
        ThrowException("missing IfcProject entity");
    }

    ConversionData conv(*db,proj->To<IfcProject>(),pScene,settings);
    SetUnits(conv);
    SetCoordinateSpace(conv);
    ProcessSpatialStructures(conv);
    MakeTreeRelative(conv);

    // NOTE - this is a stress test for the importer, but it works only
    // in a build with no entities disabled. See
    //     scripts/IFCImporter/CPPGenerator.py
    // for more information.
    #ifdef ASSIMP_IFC_TEST
        db->EvaluateAll();
    #endif

    // do final data copying
    if (conv.meshes.size()) {
        pScene->mNumMeshes = static_cast<unsigned int>(conv.meshes.size());
        pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
        std::copy(conv.meshes.begin(),conv.meshes.end(),pScene->mMeshes);

        // needed to keep the d'tor from burning us
        conv.meshes.clear();
    }

    if (conv.materials.size()) {
        pScene->mNumMaterials = static_cast<unsigned int>(conv.materials.size());
        pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
        std::copy(conv.materials.begin(),conv.materials.end(),pScene->mMaterials);

        // needed to keep the d'tor from burning us
        conv.materials.clear();
    }

    // apply world coordinate system (which includes the scaling to convert to meters and a -90 degrees rotation around x)
    aiMatrix4x4 scale, rot;
    aiMatrix4x4::Scaling(static_cast<aiVector3D>(IfcVector3(conv.len_scale)),scale);
    aiMatrix4x4::RotationX(-AI_MATH_HALF_PI_F,rot);

    pScene->mRootNode->mTransformation = rot * scale * conv.wcs * pScene->mRootNode->mTransformation;

    // this must be last because objects are evaluated lazily as we process them
    if ( !DefaultLogger::isNullLogger() ){
        LogDebug((Formatter::format(),"STEP: evaluated ",db->GetEvaluatedObjectCount()," object records"));
    }
}

namespace {


// ------------------------------------------------------------------------------------------------
void ConvertUnit(const IfcNamedUnit& unit,ConversionData& conv)
{
    if(const IfcSIUnit* const si = unit.ToPtr<IfcSIUnit>()) {

        if(si->UnitType == "LENGTHUNIT") {
            conv.len_scale = si->Prefix ? ConvertSIPrefix(si->Prefix) : 1.f;
            IFCImporter::LogDebug("got units used for lengths");
        }
        if(si->UnitType == "PLANEANGLEUNIT") {
            if (si->Name != "RADIAN") {
                IFCImporter::LogWarn("expected base unit for angles to be radian");
            }
        }
    }
    else if(const IfcConversionBasedUnit* const convu = unit.ToPtr<IfcConversionBasedUnit>()) {

        if(convu->UnitType == "PLANEANGLEUNIT") {
            try {
                conv.angle_scale = convu->ConversionFactor->ValueComponent->To<EXPRESS::REAL>();
                ConvertUnit(*convu->ConversionFactor->UnitComponent,conv);
                IFCImporter::LogDebug("got units used for angles");
            }
            catch(std::bad_cast&) {
                IFCImporter::LogError("skipping unknown IfcConversionBasedUnit.ValueComponent entry - expected REAL");
            }
        }
    }
}

// ------------------------------------------------------------------------------------------------
void ConvertUnit(const EXPRESS::DataType& dt,ConversionData& conv)
{
    try {
        const EXPRESS::ENTITY& e = dt.To<ENTITY>();

        const IfcNamedUnit& unit = e.ResolveSelect<IfcNamedUnit>(conv.db);
        if(unit.UnitType != "LENGTHUNIT" && unit.UnitType != "PLANEANGLEUNIT") {
            return;
        }

        ConvertUnit(unit,conv);
    }
    catch(std::bad_cast&) {
        // not entity, somehow
        IFCImporter::LogError("skipping unknown IfcUnit entry - expected entity");
    }
}

// ------------------------------------------------------------------------------------------------
void SetUnits(ConversionData& conv)
{
    // see if we can determine the coordinate space used to express.
    for(size_t i = 0; i <  conv.proj.UnitsInContext->Units.size(); ++i ) {
        ConvertUnit(*conv.proj.UnitsInContext->Units[i],conv);
    }
}


// ------------------------------------------------------------------------------------------------
void SetCoordinateSpace(ConversionData& conv)
{
    const IfcRepresentationContext* fav = NULL;
    for(const IfcRepresentationContext& v : conv.proj.RepresentationContexts) {
        fav = &v;
        // Model should be the most suitable type of context, hence ignore the others
        if (v.ContextType && v.ContextType.Get() == "Model") {
            break;
        }
    }
    if (fav) {
        if(const IfcGeometricRepresentationContext* const geo = fav->ToPtr<IfcGeometricRepresentationContext>()) {
            ConvertAxisPlacement(conv.wcs, *geo->WorldCoordinateSystem, conv);
            IFCImporter::LogDebug("got world coordinate system");
        }
    }
}


// ------------------------------------------------------------------------------------------------
void ResolveObjectPlacement(aiMatrix4x4& m, const IfcObjectPlacement& place, ConversionData& conv)
{
    if (const IfcLocalPlacement* const local = place.ToPtr<IfcLocalPlacement>()){
        IfcMatrix4 tmp;
        ConvertAxisPlacement(tmp, *local->RelativePlacement, conv);

        m = static_cast<aiMatrix4x4>(tmp);

        if (local->PlacementRelTo) {
            aiMatrix4x4 tmp;
            ResolveObjectPlacement(tmp,local->PlacementRelTo.Get(),conv);
            m = tmp * m;
        }
    }
    else {
        IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName());
    }
}

// ------------------------------------------------------------------------------------------------
bool ProcessMappedItem(const IfcMappedItem& mapped, aiNode* nd_src, std::vector< aiNode* >& subnodes_src, unsigned int matid, ConversionData& conv)
{
    // insert a custom node here, the cartesian transform operator is simply a conventional transformation matrix
    std::unique_ptr<aiNode> nd(new aiNode());
    nd->mName.Set("IfcMappedItem");

    // handle the Cartesian operator
    IfcMatrix4 m;
    ConvertTransformOperator(m, *mapped.MappingTarget);

    IfcMatrix4 msrc;
    ConvertAxisPlacement(msrc,*mapped.MappingSource->MappingOrigin,conv);

    msrc = m*msrc;

    std::vector<unsigned int> meshes;
    const size_t old_openings = conv.collect_openings ? conv.collect_openings->size() : 0;
    if (conv.apply_openings) {
        IfcMatrix4 minv = msrc;
        minv.Inverse();
        for(TempOpening& open :*conv.apply_openings){
            open.Transform(minv);
        }
    }

    unsigned int localmatid = ProcessMaterials(mapped.GetID(),matid,conv,false);
    const IfcRepresentation& repr = mapped.MappingSource->MappedRepresentation;

    bool got = false;
    for(const IfcRepresentationItem& item : repr.Items) {
        if(!ProcessRepresentationItem(item,localmatid,meshes,conv)) {
            IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated");
        }
        else got = true;
    }

    if (!got) {
        return false;
    }

    AssignAddedMeshes(meshes,nd.get(),conv);
    if (conv.collect_openings) {

        // if this pass serves us only to collect opening geometry,
        // make sure we transform the TempMesh's which we need to
        // preserve as well.
        if(const size_t diff = conv.collect_openings->size() - old_openings) {
            for(size_t i = 0; i < diff; ++i) {
                (*conv.collect_openings)[old_openings+i].Transform(msrc);
            }
        }
    }

    nd->mTransformation =  nd_src->mTransformation * static_cast<aiMatrix4x4>( msrc );
    subnodes_src.push_back(nd.release());

    return true;
}

// ------------------------------------------------------------------------------------------------
struct RateRepresentationPredicate {

    int Rate(const IfcRepresentation* r) const {
        // the smaller, the better

        if (! r->RepresentationIdentifier) {
            // neutral choice if no extra information is specified
            return 0;
        }


        const std::string& name = r->RepresentationIdentifier.Get();
        if (name == "MappedRepresentation") {
            if (!r->Items.empty()) {
                // take the first item and base our choice on it
                const IfcMappedItem* const m = r->Items.front()->ToPtr<IfcMappedItem>();
                if (m) {
                    return Rate(m->MappingSource->MappedRepresentation);
                }
            }
            return 100;
        }

        return Rate(name);
    }

    int Rate(const std::string& r) const {


        if (r == "SolidModel") {
            return -3;
        }

        // give strong preference to extruded geometry.
        if (r == "SweptSolid") {
            return -10;
        }

        if (r == "Clipping") {
            return -5;
        }

        // 'Brep' is difficult to get right due to possible voids in the
        // polygon boundaries, so take it only if we are forced to (i.e.
        // if the only alternative is (non-clipping) boolean operations,
        // which are not supported at all).
        if (r == "Brep") {
            return -2;
        }

        // Curves, bounding boxes - those will most likely not be loaded
        // as we can't make any use out of this data. So consider them
        // last.
        if (r == "BoundingBox" || r == "Curve2D") {
            return 100;
        }
        return 0;
    }

    bool operator() (const IfcRepresentation* a, const IfcRepresentation* b) const {
        return Rate(a) < Rate(b);
    }
};

// ------------------------------------------------------------------------------------------------
void ProcessProductRepresentation(const IfcProduct& el, aiNode* nd, std::vector< aiNode* >& subnodes, ConversionData& conv)
{
    if(!el.Representation) {
        return;
    }

    // extract Color from metadata, if present
    unsigned int matid = ProcessMaterials( el.GetID(), std::numeric_limits<uint32_t>::max(), conv, false);
    std::vector<unsigned int> meshes;

    // we want only one representation type, so bring them in a suitable order (i.e try those
    // that look as if we could read them quickly at first). This way of reading
    // representation is relatively generic and allows the concrete implementations
    // for the different representation types to make some sensible choices what
    // to load and what not to load.
    const STEP::ListOf< STEP::Lazy< IfcRepresentation >, 1, 0 >& src = el.Representation.Get()->Representations;
    std::vector<const IfcRepresentation*> repr_ordered(src.size());
    std::copy(src.begin(),src.end(),repr_ordered.begin());
    std::sort(repr_ordered.begin(),repr_ordered.end(),RateRepresentationPredicate());
    for(const IfcRepresentation* repr : repr_ordered) {
        bool res = false;
        for(const IfcRepresentationItem& item : repr->Items) {
            if(const IfcMappedItem* const geo = item.ToPtr<IfcMappedItem>()) {
                res = ProcessMappedItem(*geo,nd,subnodes,matid,conv) || res;
            }
            else {
                res = ProcessRepresentationItem(item,matid,meshes,conv) || res;
            }
        }
        // if we got something meaningful at this point, skip any further representations
        if(res) {
            break;
        }
    }
    AssignAddedMeshes(meshes,nd,conv);
}

typedef std::map<std::string, std::string> Metadata;

// ------------------------------------------------------------------------------------------------
void ProcessMetadata(const ListOf< Lazy< IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties,
    const std::string& prefix = "",
    unsigned int nest = 0)
{
    for(const IfcProperty& property : set) {
        const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name;
        if (const IfcPropertySingleValue* const singleValue = property.ToPtr<IfcPropertySingleValue>()) {
            if (singleValue->NominalValue) {
                if (const EXPRESS::STRING* str = singleValue->NominalValue.Get()->ToPtr<EXPRESS::STRING>()) {
                    std::string value = static_cast<std::string>(*str);
                    properties[key]=value;
                }
                else if (const EXPRESS::REAL* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::REAL>()) {
                    float value = static_cast<float>(*val);
                    std::stringstream s;
                    s << value;
                    properties[key]=s.str();
                }
                else if (const EXPRESS::INTEGER* val = singleValue->NominalValue.Get()->ToPtr<EXPRESS::INTEGER>()) {
                    int64_t value = static_cast<int64_t>(*val);
                    std::stringstream s;
                    s << value;
                    properties[key]=s.str();
                }
            }
        }
        else if (const IfcPropertyListValue* const listValue = property.ToPtr<IfcPropertyListValue>()) {
            std::stringstream ss;
            ss << "[";
            unsigned index=0;
            for(const IfcValue::Out& v : listValue->ListValues) {
                if (!v) continue;
                if (const EXPRESS::STRING* str = v->ToPtr<EXPRESS::STRING>()) {
                    std::string value = static_cast<std::string>(*str);
                    ss << "'" << value << "'";
                }
                else if (const EXPRESS::REAL* val = v->ToPtr<EXPRESS::REAL>()) {
                    float value = static_cast<float>(*val);
                    ss << value;
                }
                else if (const EXPRESS::INTEGER* val = v->ToPtr<EXPRESS::INTEGER>()) {
                    int64_t value = static_cast<int64_t>(*val);
                    ss << value;
                }
                if (index+1<listValue->ListValues.size()) {
                    ss << ",";
                }
                index++;
            }
            ss << "]";
            properties[key]=ss.str();
        }
        else if (const IfcComplexProperty* const complexProp = property.ToPtr<IfcComplexProperty>()) {
            if(nest > 2) { // mostly arbitrary limit to prevent stack overflow vulnerabilities
                IFCImporter::LogError("maximum nesting level for IfcComplexProperty reached, skipping this property.");
            }
            else {
                ProcessMetadata(complexProp->HasProperties, conv, properties, key, nest + 1);
            }
        }
        else {
            properties[key]="";
        }
    }
}


// ------------------------------------------------------------------------------------------------
void ProcessMetadata(uint64_t relDefinesByPropertiesID, ConversionData& conv, Metadata& properties)
{
    if (const IfcRelDefinesByProperties* const pset = conv.db.GetObject(relDefinesByPropertiesID)->ToPtr<IfcRelDefinesByProperties>()) {
        if (const IfcPropertySet* const set = conv.db.GetObject(pset->RelatingPropertyDefinition->GetID())->ToPtr<IfcPropertySet>()) {
            ProcessMetadata(set->HasProperties, conv, properties);
        }
    }
}

// ------------------------------------------------------------------------------------------------
aiNode* ProcessSpatialStructure(aiNode* parent, const IfcProduct& el, ConversionData& conv, std::vector<TempOpening>* collect_openings = NULL)
{
    const STEP::DB::RefMap& refs = conv.db.GetRefs();

    // skip over space and annotation nodes - usually, these have no meaning in Assimp's context
    bool skipGeometry = false;
    if(conv.settings.skipSpaceRepresentations) {
        if(el.ToPtr<IfcSpace>()) {
            IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
            skipGeometry = true;
        }
    }

    if(conv.settings.skipAnnotations) {
        if(el.ToPtr<IfcAnnotation>()) {
            IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings");
            return NULL;
        }
    }

    // add an output node for this spatial structure
    std::unique_ptr<aiNode> nd(new aiNode());
    nd->mName.Set(el.GetClassName()+"_"+(el.Name?el.Name.Get():"Unnamed")+"_"+el.GlobalId);
    nd->mParent = parent;

    conv.already_processed.insert(el.GetID());

    // check for node metadata
    STEP::DB::RefMapRange children = refs.equal_range(el.GetID());
    if (children.first!=refs.end()) {
        Metadata properties;
        if (children.first==children.second) {
            // handles single property set
            ProcessMetadata((*children.first).second, conv, properties);
        }
        else {
            // handles multiple property sets (currently all property sets are merged,
            // which may not be the best solution in the long run)
            for (STEP::DB::RefMap::const_iterator it=children.first; it!=children.second; ++it) {
                ProcessMetadata((*it).second, conv, properties);
            }
        }

        if (!properties.empty()) {
            aiMetadata* data = aiMetadata::Alloc( static_cast<unsigned int>(properties.size()) );
            unsigned int index( 0 );
            for ( const Metadata::value_type& kv : properties ) {
                data->Set( index++, kv.first, aiString( kv.second ) );
            }
            nd->mMetaData = data;
        }
    }

    if(el.ObjectPlacement) {
        ResolveObjectPlacement(nd->mTransformation,el.ObjectPlacement.Get(),conv);
    }

    std::vector<TempOpening> openings;

    IfcMatrix4 myInv;
    bool didinv = false;

    // convert everything contained directly within this structure,
    // this may result in more nodes.
    std::vector< aiNode* > subnodes;
    try {
        // locate aggregates and 'contained-in-here'-elements of this spatial structure and add them in recursively
        // on our way, collect openings in *this* element
        STEP::DB::RefMapRange range = refs.equal_range(el.GetID());

        for(STEP::DB::RefMapRange range2 = range; range2.first != range.second; ++range2.first) {
            // skip over meshes that have already been processed before. This is strictly necessary
            // because the reverse indices also include references contained in argument lists and
            // therefore every element has a back-reference hold by its parent.
            if (conv.already_processed.find((*range2.first).second) != conv.already_processed.end()) {
                continue;
            }
            const STEP::LazyObject& obj = conv.db.MustGetObject((*range2.first).second);

            // handle regularly-contained elements
            if(const IfcRelContainedInSpatialStructure* const cont = obj->ToPtr<IfcRelContainedInSpatialStructure>()) {
                if(cont->RelatingStructure->GetID() != el.GetID()) {
                    continue;
                }
                for(const IfcProduct& pro : cont->RelatedElements) {
                    if(pro.ToPtr<IfcOpeningElement>()) {
                        // IfcOpeningElement is handled below. Sadly we can't use it here as is:
                        // The docs say that opening elements are USUALLY attached to building storey,
                        // but we want them for the building elements to which they belong.
                        continue;
                    }

                    aiNode* const ndnew = ProcessSpatialStructure(nd.get(),pro,conv,NULL);
                    if(ndnew) {
                        subnodes.push_back( ndnew );
                    }
                }
            }
            // handle openings, which we collect in a list rather than adding them to the node graph
            else if(const IfcRelVoidsElement* const fills = obj->ToPtr<IfcRelVoidsElement>()) {
                if(fills->RelatingBuildingElement->GetID() == el.GetID()) {
                    const IfcFeatureElementSubtraction& open = fills->RelatedOpeningElement;

                    // move opening elements to a separate node since they are semantically different than elements that are just 'contained'
                    std::unique_ptr<aiNode> nd_aggr(new aiNode());
                    nd_aggr->mName.Set("$RelVoidsElement");
                    nd_aggr->mParent = nd.get();

                    nd_aggr->mTransformation = nd->mTransformation;

                    std::vector<TempOpening> openings_local;
                    aiNode* const ndnew = ProcessSpatialStructure( nd_aggr.get(),open, conv,&openings_local);
                    if (ndnew) {

                        nd_aggr->mNumChildren = 1;
                        nd_aggr->mChildren = new aiNode*[1]();


                        nd_aggr->mChildren[0] = ndnew;

                        if(openings_local.size()) {
                            if (!didinv) {
                                myInv = aiMatrix4x4(nd->mTransformation ).Inverse();
                                didinv = true;
                            }

                            // we need all openings to be in the local space of *this* node, so transform them
                            for(TempOpening& op :openings_local) {
                                op.Transform( myInv*nd_aggr->mChildren[0]->mTransformation);
                                openings.push_back(op);
                            }
                        }
                        subnodes.push_back( nd_aggr.release() );
                    }
                }
            }
        }

        for(;range.first != range.second; ++range.first) {
            // see note in loop above
            if (conv.already_processed.find((*range.first).second) != conv.already_processed.end()) {
                continue;
            }
            if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
                if(aggr->RelatingObject->GetID() != el.GetID()) {
                    continue;
                }

                // move aggregate elements to a separate node since they are semantically different than elements that are just 'contained'
                std::unique_ptr<aiNode> nd_aggr(new aiNode());
                nd_aggr->mName.Set("$RelAggregates");
                nd_aggr->mParent = nd.get();

                nd_aggr->mTransformation = nd->mTransformation;

                nd_aggr->mChildren = new aiNode*[aggr->RelatedObjects.size()]();
                for(const IfcObjectDefinition& def : aggr->RelatedObjects) {
                    if(const IfcProduct* const prod = def.ToPtr<IfcProduct>()) {

                        aiNode* const ndnew = ProcessSpatialStructure(nd_aggr.get(),*prod,conv,NULL);
                        if(ndnew) {
                            nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew;
                        }
                    }
                }

                subnodes.push_back( nd_aggr.release() );
            }
        }

        conv.collect_openings = collect_openings;
        if(!conv.collect_openings) {
            conv.apply_openings = &openings;
        }

        if (!skipGeometry) {
          ProcessProductRepresentation(el,nd.get(),subnodes,conv);
          conv.apply_openings = conv.collect_openings = NULL;
        }

        if (subnodes.size()) {
            nd->mChildren = new aiNode*[subnodes.size()]();
            for(aiNode* nd2 : subnodes) {
                nd->mChildren[nd->mNumChildren++] = nd2;
                nd2->mParent = nd.get();
            }
        }
    }
    catch(...) {
        // it hurts, but I don't want to pull boost::ptr_vector into -noboost only for these few spots here
        std::for_each(subnodes.begin(),subnodes.end(),delete_fun<aiNode>());
        throw;
    }

    ai_assert(conv.already_processed.find(el.GetID()) != conv.already_processed.end());
    conv.already_processed.erase(conv.already_processed.find(el.GetID()));
    return nd.release();
}

// ------------------------------------------------------------------------------------------------
void ProcessSpatialStructures(ConversionData& conv)
{
    // XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX)


    // process all products in the file. it is reasonable to assume that a
    // file that is relevant for us contains at least a site or a building.
    const STEP::DB::ObjectMapByType& map = conv.db.GetObjectsByType();

    ai_assert(map.find("ifcsite") != map.end());
    const STEP::DB::ObjectSet* range = &map.find("ifcsite")->second;

    if (range->empty()) {
        ai_assert(map.find("ifcbuilding") != map.end());
        range = &map.find("ifcbuilding")->second;
        if (range->empty()) {
            // no site, no building -  fail;
            IFCImporter::ThrowException("no root element found (expected IfcBuilding or preferably IfcSite)");
        }
    }

	std::vector<aiNode*> nodes;

    for(const STEP::LazyObject* lz : *range) {
        const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
        if(!prod) {
            continue;
        }
        IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():""));

        // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT
        const STEP::DB::RefMap& refs = conv.db.GetRefs();
        STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID());
        for(; ref_range.first != ref_range.second; ++ref_range.first) {
            if(const IfcRelAggregates* const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr<IfcRelAggregates>()) {

                for(const IfcObjectDefinition& def : aggr->RelatedObjects) {
                    // comparing pointer values is not sufficient, we would need to cast them to the same type first
                    // as there is multiple inheritance in the game.
                    if (def.GetID() == prod->GetID()) {
                        IFCImporter::LogDebug("selecting this spatial structure as root structure");
                        // got it, this is one primary site.
						nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
                    }
                }

            }
        }
    }

	size_t nb_nodes = nodes.size();

	if (nb_nodes == 0) {
		IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite");
		for (const STEP::LazyObject* lz : *range) {
			const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
			if (!prod) {
				continue;
			}

			nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
		}

		nb_nodes = nodes.size();
	}

	if (nb_nodes == 1) {
		conv.out->mRootNode = nodes[0];
	}
	else if (nb_nodes > 1) {
		conv.out->mRootNode = new aiNode("Root");
		conv.out->mRootNode->mParent = NULL;
		conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
		conv.out->mRootNode->mChildren = new aiNode*[conv.out->mRootNode->mNumChildren];
		
		for (size_t i = 0; i < nb_nodes; ++i) {
			aiNode* node = nodes[i];

			node->mParent = conv.out->mRootNode;

			conv.out->mRootNode->mChildren[i] = node;
		}
	}
	else {
		IFCImporter::ThrowException("failed to determine primary site element");
	}
}

// ------------------------------------------------------------------------------------------------
void MakeTreeRelative(aiNode* start, const aiMatrix4x4& combined)
{
    // combined is the parent's absolute transformation matrix
    const aiMatrix4x4 old = start->mTransformation;

    if (!combined.IsIdentity()) {
        start->mTransformation = aiMatrix4x4(combined).Inverse() * start->mTransformation;
    }

    // All nodes store absolute transformations right now, so we need to make them relative
    for (unsigned int i = 0; i < start->mNumChildren; ++i) {
        MakeTreeRelative(start->mChildren[i],old);
    }
}

// ------------------------------------------------------------------------------------------------
void MakeTreeRelative(ConversionData& conv)
{
    MakeTreeRelative(conv.out->mRootNode,IfcMatrix4());
}

} // !anon



#endif
