| 120 | } |
| 121 | |
| 122 | void emit_line_strings( |
| 123 | std::ostream& os, |
| 124 | const std::vector<double>& vertices, |
| 125 | const std::vector<int>& lines, |
| 126 | bool force_2d = false) |
| 127 | { |
| 128 | std::unordered_map<int, std::vector<int>> adjacencyList; |
| 129 | std::unordered_set<int> visited; |
| 130 | |
| 131 | for (size_t i = 0; i < lines.size(); i += 2) { |
| 132 | for (size_t j = 0; j < 2; ++j) { |
| 133 | const auto& p0 = lines[i + (j ? 1 : 0)]; |
| 134 | const auto& p1 = lines[i + (j ? 0 : 1)]; |
| 135 | adjacencyList[p0].push_back(p1); |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | auto traverseComponent = [&](int start) { |
| 140 | std::vector<int> component; // To store the current component |
| 141 | std::queue<int> toVisit; |
| 142 | toVisit.push(start); |
| 143 | visited.insert(start); |
| 144 | |
| 145 | while (!toVisit.empty()) { |
| 146 | int current = toVisit.front(); |
| 147 | toVisit.pop(); |
| 148 | component.push_back(current); |
| 149 | |
| 150 | for (int neighbor : adjacencyList[current]) { |
| 151 | if (visited.find(neighbor) == visited.end()) { |
| 152 | toVisit.push(neighbor); |
| 153 | visited.insert(neighbor); |
| 154 | } |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | return component; |
| 159 | }; |
| 160 | |
| 161 | std::vector<std::vector<int>> components; |
| 162 | |
| 163 | for (auto it = lines.begin(); it != lines.end(); it += 2) { |
| 164 | if (visited.find(*it) == visited.end()) { |
| 165 | components.emplace_back(std::move(traverseComponent(*it))); |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | if (components.size() == 1) { |
| 170 | emit_line_component(os, vertices, components.front(), force_2d); |
| 171 | } else { |
| 172 | os << "GEOMETRYCOLLECTION("; |
| 173 | for (auto it = components.begin(); it != components.end(); ++it) { |
| 174 | if (it != components.begin()) { |
| 175 | os << ","; |
| 176 | } |
| 177 | emit_line_component(os, vertices, *it, force_2d); |
| 178 | } |
| 179 | os << ")"; |