#include #include #include namespace mbgl { namespace util { using Index = std::unordered_map; unsigned int mergeFromRight(std::vector &features, Index &rightIndex, Index::iterator left, size_t rightKey, GeometryCollection &geom) { unsigned int index = left->second; rightIndex.erase(left); rightIndex[rightKey] = index; features[index].geometry[0].pop_back(); features[index].geometry[0].insert( features[index].geometry[0].end(), geom[0].begin(), geom[0].end()); geom[0].clear(); return index; } unsigned int mergeFromLeft(std::vector &features, Index &leftIndex, size_t leftKey, Index::iterator right, GeometryCollection &geom) { unsigned int index = right->second; leftIndex.erase(right); leftIndex[leftKey] = index; geom[0].pop_back(); geom[0].insert( geom[0].end(), features[index].geometry[0].begin(), features[index].geometry[0].end()); features[index].geometry[0].clear(); std::swap(features[index].geometry[0], geom[0]); return index; } enum class Side { Left = false, Right = true, }; size_t getKey(const std::u16string& text, const GeometryCollection& geom, Side side) { const GeometryCoordinate& coord = side == Side::Right ? geom[0].back() : geom[0].front(); auto hash = std::hash()(text); boost::hash_combine(hash, coord.x); boost::hash_combine(hash, coord.y); return hash; } void mergeLines(std::vector &features) { Index leftIndex; Index rightIndex; for (unsigned int k = 0; k < features.size(); k++) { SymbolFeature &feature = features[k]; GeometryCollection &geometry = feature.geometry; if (!feature.text) { continue; } const auto leftKey = getKey(*feature.text, geometry, Side::Left); const auto rightKey = getKey(*feature.text, geometry, Side::Right); const auto left = rightIndex.find(leftKey); const auto right = leftIndex.find(rightKey); if ((left != rightIndex.end()) && (right != leftIndex.end()) && (left->second != right->second)) { // found lines with the same text adjacent to both ends of the current line, merge all // three unsigned int j = mergeFromLeft(features, leftIndex, leftKey, right, geometry); unsigned int i = mergeFromRight(features, rightIndex, left, rightKey, features[j].geometry); leftIndex.erase(leftKey); rightIndex.erase(rightKey); rightIndex[getKey(*feature.text, features[i].geometry, Side::Right)] = i; } else if (left != rightIndex.end()) { // found mergeable line adjacent to the start of the current line, merge mergeFromRight(features, rightIndex, left, rightKey, geometry); } else if (right != leftIndex.end()) { // found mergeable line adjacent to the end of the current line, merge mergeFromLeft(features, leftIndex, leftKey, right, geometry); } else { // no adjacent lines, add as a new item leftIndex[leftKey] = k; rightIndex[rightKey] = k; } } } } // end namespace util } // end namespace mbgl