File indexing completed on 2024-05-19 03:53:14

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2016 Dennis Nienhüser <nienhueser@kde.org>
0004 //
0005 
0006 //Self
0007 #include "OsmDocumentTagTranslator.h"
0008 
0009 //Marble
0010 #include "OsmNodeTagWriter.h"
0011 #include "OsmWayTagWriter.h"
0012 #include "OsmElementDictionary.h"
0013 #include "GeoDataDocument.h"
0014 #include "GeoWriter.h"
0015 #include "GeoDataPlacemark.h"
0016 #include "GeoDataGeometry.h"
0017 #include "GeoDataPoint.h"
0018 #include "GeoDataPolygon.h"
0019 #include "GeoDataRelation.h"
0020 #include "GeoDataLinearRing.h"
0021 #include "GeoDataBuilding.h"
0022 #include "GeoDataMultiGeometry.h"
0023 #include "osm/OsmPlacemarkData.h"
0024 #include "osm/OsmObjectManager.h"
0025 #include "OsmRelationTagWriter.h"
0026 
0027 #include <QDebug>
0028 
0029 namespace Marble
0030 {
0031 
0032 void OsmConverter::read(const GeoDataDocument *document)
0033 {
0034     m_nodes.clear();
0035     m_ways.clear();
0036     m_relations.clear();
0037 
0038     // Writing all the component nodes ( points, nodes of polylines, nodes of polygons )
0039     for (auto feature: document->featureList()) {
0040         if (auto placemark = geodata_cast<GeoDataPlacemark>(feature)) {
0041             // If the placemark's osmData is not complete, it is initialized by the OsmObjectManager
0042             OsmObjectManager::initializeOsmData( placemark );
0043             const OsmPlacemarkData & osmData = placemark->osmData();
0044 
0045             if (geodata_cast<GeoDataPoint>(placemark->geometry())) {
0046                 m_nodes << OsmConverter::Node(placemark->coordinate(), osmData);
0047             } else if (const auto lineString = geodata_cast<GeoDataLineString>(placemark->geometry())) {
0048                 for (auto const &coordinates: *lineString) {
0049                     m_nodes << OsmConverter::Node(coordinates, osmData.nodeReference(coordinates));
0050                 }
0051                 m_ways << OsmConverter::Way(lineString, osmData);
0052             } else if (const auto linearRing = geodata_cast<GeoDataLinearRing>(placemark->geometry())) {
0053                 processLinearRing(linearRing, osmData);
0054             } else if (const auto polygon = geodata_cast<GeoDataPolygon>(placemark->geometry())) {
0055                 processPolygon(polygon, osmData, placemark);
0056             } else if (const auto building = geodata_cast<GeoDataBuilding>(placemark->geometry())) {
0057                 if (const auto linearRing = geodata_cast<GeoDataLinearRing>(&building->multiGeometry()->at(0))) {
0058                     processLinearRing(linearRing, osmData);
0059                 } else if (const auto polygon = geodata_cast<GeoDataPolygon>(&building->multiGeometry()->at(0))) {
0060                     processPolygon(polygon, osmData, placemark);
0061                 }
0062             }
0063         } else if (const auto placemark = geodata_cast<GeoDataRelation>(feature)) {
0064             m_relations.append(OsmConverter::Relation(placemark, placemark->osmData()));
0065         }
0066     }
0067 
0068     // Sort by id ascending since some external tools rely on that
0069     std::sort(m_nodes.begin(), m_nodes.end(), [] (const Node &a, const Node &b) { return a.second.id() < b.second.id(); });
0070     std::sort(m_ways.begin(), m_ways.end(), [] (const Way &a, const Way &b) { return a.second.id() < b.second.id(); });
0071     std::sort(m_relations.begin(), m_relations.end(), [] (const Relation &a, const Relation &b) { return a.second.id() < b.second.id(); });
0072 }
0073 
0074 const OsmConverter::Nodes &OsmConverter::nodes() const
0075 {
0076     return m_nodes;
0077 }
0078 
0079 const OsmConverter::Ways &OsmConverter::ways() const
0080 {
0081     return m_ways;
0082 }
0083 
0084 const OsmConverter::Relations &OsmConverter::relations() const
0085 {
0086     return m_relations;
0087 }
0088 
0089 void OsmConverter::processLinearRing(GeoDataLinearRing *linearRing,
0090                                      const OsmPlacemarkData& osmData)
0091 {
0092     for (auto const &coordinates: *linearRing) {
0093         m_nodes << OsmConverter::Node(coordinates, osmData.nodeReference(coordinates));
0094     }
0095     m_ways << OsmConverter::Way(linearRing, osmData);
0096 }
0097 
0098 void OsmConverter::processPolygon(GeoDataPolygon *polygon,
0099                                   const OsmPlacemarkData& osmData,
0100                                   GeoDataPlacemark* placemark)
0101 {
0102     int index = -1;
0103 
0104     // Writing all the outerRing's nodes
0105     const GeoDataLinearRing &outerRing = polygon->outerBoundary();
0106     const OsmPlacemarkData outerRingOsmData = osmData.memberReference( index );
0107     for (auto const &coordinates: outerRing) {
0108         m_nodes << OsmConverter::Node(coordinates, outerRingOsmData.nodeReference(coordinates));
0109     }
0110     m_ways << OsmConverter::Way(&outerRing, outerRingOsmData);
0111 
0112     // Writing all nodes for each innerRing
0113     for (auto const &innerRing: polygon->innerBoundaries() ) {
0114         ++index;
0115         const OsmPlacemarkData innerRingOsmData = osmData.memberReference( index );
0116         for (auto const &coordinates: innerRing) {
0117             m_nodes << OsmConverter::Node(coordinates, innerRingOsmData.nodeReference(coordinates));
0118         }
0119         m_ways << OsmConverter::Way(&innerRing, innerRingOsmData);
0120     }
0121     m_relations.append(OsmConverter::Relation(placemark, osmData));
0122 }
0123 
0124 }
0125