File indexing completed on 2024-12-01 10:29:54

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "pathutil.h"
0008 #include "element.h"
0009 
0010 #include <cassert>
0011 
0012 using namespace OSM;
0013 
0014 static OSM::Id appendNextPath(const DataSet &dataSet, std::vector<const Node*> &nodes, OSM::Id startNode, std::vector<const Way*> &ways)
0015 {
0016     if (ways.empty()) {
0017         return {};
0018     }
0019 
0020     for (auto it = std::next(ways.begin()); it != ways.end(); ++it) {
0021         if ((*it)->nodes.empty()) {
0022             continue;
0023         }
0024         if ((*it)->nodes.front() == startNode) {
0025             appendNodesFromWay(dataSet, nodes, (*it)->nodes.begin(), (*it)->nodes.end());
0026             const auto lastNodeId = (*it)->nodes.back();
0027             ways.erase(it);
0028             return lastNodeId;
0029         }
0030         // path segments can also be backwards
0031         if ((*it)->nodes.back() == startNode) {
0032             appendNodesFromWay(dataSet, nodes, (*it)->nodes.rbegin(), (*it)->nodes.rend());
0033             const auto lastNodeId = (*it)->nodes.front();
0034             ways.erase(it);
0035             return lastNodeId;
0036         }
0037     }
0038 
0039     return {};
0040 }
0041 
0042 void OSM::assemblePath(const DataSet &dataSet, std::vector<const Way*> &&ways, std::vector<const Node*> &path)
0043 {
0044     for (auto it = ways.begin(); it != ways.end();) {
0045         if ((*it)->nodes.empty()) {
0046             ++it;
0047             continue;
0048         }
0049         appendNodesFromWay(dataSet, path, (*it)->nodes.begin(), (*it)->nodes.end());
0050         const auto startNode = (*it)->nodes.front();
0051         auto lastNode = (*it)->nodes.back();
0052 
0053         do {
0054             lastNode = appendNextPath(dataSet, path, lastNode, ways);
0055         } while (lastNode && lastNode != startNode);
0056 
0057         it = ways.erase(it);
0058     }
0059 }
0060 
0061 void OSM::assemblePath(const OSM::DataSet &dataSet, const std::vector<OSM::Element> &ways, std::vector<const Node*> &path)
0062 {
0063     std::vector<const OSM::Way*> w;
0064     w.reserve(ways.size());
0065     for (auto e : ways) {
0066         if (e.type() == OSM::Type::Way) {
0067             w.push_back(e.way());
0068         }
0069     }
0070     assemblePath(dataSet, std::move(w), path);
0071 }