Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the...
authorLeo Terziman <leo.terziman@clarte.asso.fr>
Thu, 1 Jun 2017 07:47:50 +0000 (09:47 +0200)
committerLeo Terziman <leo.terziman@clarte.asso.fr>
Thu, 1 Jun 2017 07:47:50 +0000 (09:47 +0200)
code/IFCLoader.cpp

index 24c5452..463803a 100644 (file)
@@ -882,6 +882,7 @@ void ProcessSpatialStructures(ConversionData& conv)
         }
     }
 
+       std::vector<aiNode*> nodes;
 
     for(const STEP::LazyObject* lz : *range) {
         const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
@@ -890,20 +891,19 @@ void ProcessSpatialStructures(ConversionData& conv)
         }
         IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType? " which is of type " + prod->ObjectType.Get():""));
 
-        // the primary site is referenced by an IFCRELAGGREGATES element which assigns it to the IFCPRODUCT
+        // 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 range = refs.equal_range(conv.proj.GetID());
-        for(;range.first != range.second; ++range.first) {
-            if(const IfcRelAggregates* const aggr = conv.db.GetObject((*range.first).second)->ToPtr<IfcRelAggregates>()) {
+        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 the primary site.
-                        conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
-                        return;
+                        // got it, this is one primary site.
+                                               nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
                     }
                 }
 
@@ -911,19 +911,42 @@ void ProcessSpatialStructures(ConversionData& conv)
         }
     }
 
+       size_t nb_nodes = nodes.size();
 
-    IFCImporter::LogWarn("failed to determine primary site element, taking the first IfcSite");
-    for(const STEP::LazyObject* lz : *range) {
-        const IfcSpatialStructureElement* const prod = lz->ToPtr<IfcSpatialStructureElement>();
-        if(!prod) {
-            continue;
-        }
+       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;
+                       }
 
-        conv.out->mRootNode = ProcessSpatialStructure(NULL,*prod,conv,NULL);
-        return;
-    }
+                       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;
 
-    IFCImporter::ThrowException("failed to determine primary site element");
+                       conv.out->mRootNode->mChildren[i] = node;
+               }
+       }
+       else {
+               IFCImporter::ThrowException("failed to determine primary site element");
+       }
 }
 
 // ------------------------------------------------------------------------------------------------