| 100 | } |
| 101 | |
| 102 | HierarchyLinker::Node::Ptr HierarchyLinker::FindPlaceParent(HierarchyPlace const & place) |
| 103 | { |
| 104 | Node::Ptr parent = nullptr; |
| 105 | auto minArea = std::numeric_limits<double>::max(); |
| 106 | auto const point = place.GetCenter(); |
| 107 | m_tree.ForEachInRect({point, point}, [&](auto const & candidateNode) |
| 108 | { |
| 109 | // https://wiki.openstreetmap.org/wiki/Simple_3D_buildings |
| 110 | // An object with tag 'building:part' is a part of a relation with outline 'building' or |
| 111 | // is contained in a object with tag 'building'. This case is second. We suppose a building part is |
| 112 | // only inside a building. |
| 113 | static auto const & buildingChecker = ftypes::IsBuildingChecker::Instance(); |
| 114 | static auto const & buildingPartChecker = ftypes::IsBuildingPartChecker::Instance(); |
| 115 | auto const & candidate = candidateNode->GetData(); |
| 116 | if (buildingPartChecker(place.GetTypes()) && |
| 117 | !(buildingChecker(candidate.GetTypes()) || buildingPartChecker(candidate.GetTypes()))) |
| 118 | { |
| 119 | return; |
| 120 | } |
| 121 | |
| 122 | // A building part must have children only with 'building:part' type. |
| 123 | if (!buildingPartChecker(place.GetTypes()) && buildingPartChecker(candidate.GetTypes())) |
| 124 | return; |
| 125 | |
| 126 | if (place.GetCompositeId() == candidate.GetCompositeId()) |
| 127 | return; |
| 128 | |
| 129 | if (candidate.GetArea() < minArea && candidate.Contains(place)) |
| 130 | { |
| 131 | // Sometimes there can be two places with the same geometry. We must check place node and |
| 132 | // its parents to avoid cyclic connections. |
| 133 | auto node = candidateNode; |
| 134 | while (node->HasParent()) |
| 135 | { |
| 136 | node = node->GetParent(); |
| 137 | if (node->GetData().GetCompositeId() == place.GetCompositeId()) |
| 138 | return; |
| 139 | } |
| 140 | |
| 141 | parent = candidateNode; |
| 142 | minArea = candidate.GetArea(); |
| 143 | } |
| 144 | }); |
| 145 | return parent; |
| 146 | } |
| 147 | |
| 148 | HierarchyLinker::Node::Ptrs HierarchyLinker::Link() |
| 149 | { |