| 180 | } |
| 181 | |
| 182 | void FeatureMergeProcessor::DoMerge(FeatureEmitterIFace & emitter) |
| 183 | { |
| 184 | while (!m_map.empty()) |
| 185 | { |
| 186 | // Get any starting feature. |
| 187 | MergedFeatureBuilders & vS = m_map.begin()->second; |
| 188 | CHECK(!vS.empty(), ()); |
| 189 | MergedFeatureBuilder * p = vS.front(); // may be 'back' is better |
| 190 | |
| 191 | // Remove next processing type. If it's a last type - remove from map. |
| 192 | uint32_t type; |
| 193 | bool isRemoved = false; |
| 194 | if (p->PopAnyType(type)) |
| 195 | { |
| 196 | isRemoved = true; |
| 197 | Remove(p); |
| 198 | } |
| 199 | |
| 200 | // We will merge to the copy of p. |
| 201 | MergedFeatureBuilder curr(*p); |
| 202 | curr.SetType(type); |
| 203 | |
| 204 | // Iterate through key points while merging. |
| 205 | // Key points are either ends of the line or any point on the "roundabout" if the line ends with it. |
| 206 | size_t ind = 0; |
| 207 | while (ind < curr.GetKeyPointsCount()) // GetKeyPointsCount() can be different on each iteration |
| 208 | { |
| 209 | std::pair<m2::PointD, bool> const pt = curr.GetKeyPoint(ind++); |
| 210 | auto it = m_map.find(GetKey(pt.first)); |
| 211 | |
| 212 | MergedFeatureBuilder * pp = 0; |
| 213 | if (it != m_map.end()) |
| 214 | { |
| 215 | // Find the shortest connected line feature to continue, |
| 216 | // it helps to spread points more evenly between the features and to avoid producing too long lines. |
| 217 | double bestPr = std::numeric_limits<double>::max(); |
| 218 | for (size_t i = 0; i < it->second.size(); ++i) |
| 219 | { |
| 220 | MergedFeatureBuilder * pTest = it->second[i]; |
| 221 | if (pTest->HasType(type)) |
| 222 | { |
| 223 | double const pr = pTest->GetSquaredLength(); |
| 224 | // It's not necessery assert, because it's possible in source data |
| 225 | // TODO(pastk) : likely caused by degenerate closed lines. |
| 226 | // ASSERT_GREATER(pr, 0.0, ()); |
| 227 | if (pr < bestPr) |
| 228 | { |
| 229 | pp = pTest; |
| 230 | bestPr = pr; |
| 231 | } |
| 232 | } |
| 233 | } |
| 234 | |
| 235 | // Merge the current feature with the best connected feature. |
| 236 | if (pp) |
| 237 | { |
| 238 | bool const toBack = pt.second; |
| 239 | bool fromBegin = true; |