| 24 | #include <deque> |
| 25 | |
| 26 | taxonomy::ptr mapping::map_impl(const IfcSchema::IfcObjectPlacement* inst) { |
| 27 | if (placement_rel_to_type_ || placement_rel_to_instance_) { |
| 28 | using QueueItem = std::pair<const IfcUtil::IfcBaseEntity*, int>; |
| 29 | std::deque<QueueItem> q = {{inst, 0}}; |
| 30 | while (!q.empty()) { |
| 31 | auto [placement_entity, depth] = q.front(); |
| 32 | q.pop_front(); |
| 33 | |
| 34 | auto placement = placement_entity->as<typename IfcSchema::IfcObjectPlacement>(); |
| 35 | if (!placement) { |
| 36 | continue; |
| 37 | } |
| 38 | |
| 39 | auto self_places = placement->PlacesObject(); |
| 40 | for (auto iter = self_places->begin(); iter != self_places->end(); ++iter) { |
| 41 | if ((placement_rel_to_type_ && (*iter)->declaration().is(*placement_rel_to_type_)) || |
| 42 | (placement_rel_to_instance_ && (*iter)->as<IfcUtil::IfcBaseEntity>() == placement_rel_to_instance_)) { |
| 43 | return taxonomy::make<taxonomy::matrix4>(); |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | // Look for two levels deep, we want to know if we're at or *above* the |
| 48 | // element we're ignoring, but we don't want to traverse the entire model. |
| 49 | #ifdef SCHEMA_IfcObjectPlacement_HAS_ReferencedByPlacements |
| 50 | if (depth < 2) { |
| 51 | auto refs = placement->ReferencedByPlacements(); |
| 52 | for (auto& ref : *refs) { |
| 53 | q.emplace_back(ref, depth + 1); |
| 54 | } |
| 55 | } |
| 56 | #else |
| 57 | Logger::Warning("Using --site-local-placement or --building-local-placement on IFC4.2 might have issues"); |
| 58 | #endif |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | const IfcSchema::IfcObjectPlacement* relative_to = nullptr; |
| 63 | const IfcUtil::IfcBaseInterface* transform; |
| 64 | |
| 65 | const IfcSchema::IfcAxis2Placement3D* fallback = nullptr; |
| 66 | |
| 67 | if (inst->as<IfcSchema::IfcLocalPlacement>()) { |
| 68 | transform = inst->as<IfcSchema::IfcLocalPlacement>()->RelativePlacement(); |
| 69 | } |
| 70 | #ifdef SCHEMA_HAS_IfcLinearPlacement |
| 71 | else if (inst->as<IfcSchema::IfcLinearPlacement>()) { |
| 72 | #ifdef SCHEMA_IfcLinearPlacement_HAS_RelativePlacement |
| 73 | transform = inst->as<IfcSchema::IfcLinearPlacement>()->RelativePlacement(); |
| 74 | fallback = inst->as<IfcSchema::IfcLinearPlacement>()->CartesianPosition(); |
| 75 | #else |
| 76 | // @todo Ifc4x1 and Ifc4x2 don't have RelativePlacement |
| 77 | return nullptr; |
| 78 | #endif |
| 79 | } |
| 80 | #endif |
| 81 | else if (inst->as<IfcSchema::IfcGridPlacement>()) { |
| 82 | // @todo a bit harder to map without kernel |
| 83 | return nullptr; |