| 62 | } |
| 63 | |
| 64 | void ComplexFinalProcessor::Process() |
| 65 | { |
| 66 | LOG(LINFO, ("Processing complex features...")); |
| 67 | |
| 68 | if (!m_buildingPartsFilename.empty()) |
| 69 | m_buildingToParts = std::make_unique<BuildingToBuildingPartsMap>(m_buildingPartsFilename); |
| 70 | |
| 71 | std::mutex mutex; |
| 72 | std::vector<HierarchyEntry> allLines; |
| 73 | ForEachMwmTmp(m_mwmTmpPath, [&](auto const & name, auto const & path) |
| 74 | { |
| 75 | // https://wiki.openstreetmap.org/wiki/Simple_3D_buildings |
| 76 | // An object with tag 'building:part' is a part of a relation with outline 'building' or |
| 77 | // is contained in an object with tag 'building'. We will split data and work with |
| 78 | // these cases separately. First of all let's remove objects with tag building:part is |
| 79 | // contained in relations. We will add them back after data processing. |
| 80 | ankerl::unordered_dense::map<base::GeoObjectId, FeatureBuilder> relationBuildingParts; |
| 81 | |
| 82 | auto fbs = ReadAllDatRawFormat<serialization_policy::MaxAccuracy>(path); |
| 83 | |
| 84 | if (m_buildingToParts) |
| 85 | relationBuildingParts = RemoveRelationBuildingParts(fbs); |
| 86 | |
| 87 | // This case is second. We build a hierarchy using the geometry of objects and their nesting. |
| 88 | auto trees = hierarchy::BuildHierarchy(std::move(fbs), m_getMainType, m_filter); |
| 89 | |
| 90 | // We remove tree roots with tag 'building:part'. |
| 91 | base::EraseIf(trees, [](auto const & node) |
| 92 | { |
| 93 | static auto const & buildingPartChecker = ftypes::IsBuildingPartChecker::Instance(); |
| 94 | return buildingPartChecker(node->GetData().GetTypes()); |
| 95 | }); |
| 96 | |
| 97 | // We want to transform |
| 98 | // building |
| 99 | // |_building-part |
| 100 | // |_building-part |
| 101 | // to |
| 102 | // building |
| 103 | // |_building-part |
| 104 | // |_building-part |
| 105 | hierarchy::FlattenBuildingParts(trees); |
| 106 | // In the end we add objects, which were saved by the collector. |
| 107 | if (m_buildingToParts) |
| 108 | { |
| 109 | hierarchy::AddChildrenTo(trees, [&](auto const & compositeId) |
| 110 | { |
| 111 | auto const & ids = m_buildingToParts->GetBuildingPartsByOutlineId(compositeId); |
| 112 | std::vector<hierarchy::HierarchyPlace> places; |
| 113 | places.reserve(ids.size()); |
| 114 | for (auto const & id : ids) |
| 115 | { |
| 116 | if (relationBuildingParts.count(id) == 0) |
| 117 | continue; |
| 118 | |
| 119 | places.emplace_back(hierarchy::HierarchyPlace(relationBuildingParts[id])); |
| 120 | } |
| 121 | return places; |
nothing calls this directly
no test coverage detected