------------------------------------------------------------------------------------------------
| 823 | |
| 824 | // ------------------------------------------------------------------------------------------------ |
| 825 | void ProcessSpatialStructures(ConversionData &conv) { |
| 826 | // XXX add support for multiple sites (i.e. IfcSpatialStructureElements with composition == COMPLEX) |
| 827 | |
| 828 | // process all products in the file. it is reasonable to assume that a |
| 829 | // file that is relevant for us contains at least a site or a building. |
| 830 | const STEP::DB::ObjectMapByType &map = conv.db.GetObjectsByType(); |
| 831 | |
| 832 | ai_assert(map.find("ifcsite") != map.end()); |
| 833 | const STEP::DB::ObjectSet *range = &map.find("ifcsite")->second; |
| 834 | |
| 835 | if (range->empty()) { |
| 836 | ai_assert(map.find("ifcbuilding") != map.end()); |
| 837 | range = &map.find("ifcbuilding")->second; |
| 838 | if (range->empty()) { |
| 839 | // no site, no building - fail; |
| 840 | IFCImporter::ThrowException("no root element found (expected IfcBuilding or preferably IfcSite)"); |
| 841 | } |
| 842 | } |
| 843 | |
| 844 | std::vector<aiNode *> nodes; |
| 845 | |
| 846 | for (const STEP::LazyObject *lz : *range) { |
| 847 | const Schema_2x3::IfcSpatialStructureElement *const prod = lz->ToPtr<Schema_2x3::IfcSpatialStructureElement>(); |
| 848 | if (!prod) { |
| 849 | continue; |
| 850 | } |
| 851 | IFCImporter::LogVerboseDebug("looking at spatial structure `", (prod->Name ? prod->Name.Get() : "unnamed"), "`", (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); |
| 852 | |
| 853 | // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT |
| 854 | const STEP::DB::RefMap &refs = conv.db.GetRefs(); |
| 855 | STEP::DB::RefMapRange ref_range = refs.equal_range(conv.proj.GetID()); |
| 856 | for (; ref_range.first != ref_range.second; ++ref_range.first) { |
| 857 | if (const Schema_2x3::IfcRelAggregates *const aggr = conv.db.GetObject((*ref_range.first).second)->ToPtr<Schema_2x3::IfcRelAggregates>()) { |
| 858 | |
| 859 | for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) { |
| 860 | // comparing pointer values is not sufficient, we would need to cast them to the same type first |
| 861 | // as there is multiple inheritance in the game. |
| 862 | if (def.GetID() == prod->GetID()) { |
| 863 | IFCImporter::LogVerboseDebug("selecting this spatial structure as root structure"); |
| 864 | // got it, this is one primary site. |
| 865 | nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr)); |
| 866 | } |
| 867 | } |
| 868 | } |
| 869 | } |
| 870 | } |
| 871 | |
| 872 | size_t nb_nodes = nodes.size(); |
| 873 | |
| 874 | if (nb_nodes == 0) { |
| 875 | IFCImporter::LogWarn("failed to determine primary site element, taking all the IfcSite"); |
| 876 | for (const STEP::LazyObject *lz : *range) { |
| 877 | const Schema_2x3::IfcSpatialStructureElement *const prod = lz->ToPtr<Schema_2x3::IfcSpatialStructureElement>(); |
| 878 | if (!prod) { |
| 879 | continue; |
| 880 | } |
| 881 | |
| 882 | nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr)); |
no test coverage detected