1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2015 Stanciu Marius-Valeriu <stanciumarius94@gmail.com>
4 //
5 
6 // Self
7 #include "OsmObjectManager.h"
8 
9 // Marble
10 #include "GeoDataPlacemark.h"
11 #include "GeoDataLinearRing.h"
12 #include "GeoDataPolygon.h"
13 #include "GeoDataBuilding.h"
14 #include "GeoDataMultiGeometry.h"
15 #include "osm/OsmPlacemarkData.h"
16 
17 namespace Marble {
18 
19 qint64 OsmObjectManager::m_minId = -1;
20 
initializeOsmData(GeoDataPlacemark * placemark)21 void OsmObjectManager::initializeOsmData( GeoDataPlacemark* placemark )
22 {
23     OsmPlacemarkData &osmData = placemark->osmData();
24 
25     bool isNull = osmData.isNull();
26     if ( isNull ) {
27         // The "--m_minId" assignments mean: assigning an id lower( by 1 ) than the current lowest,
28         // and updating the current lowest id.
29         osmData.setId( --m_minId );
30     }
31 
32     // Assigning osmData to each of the line's nodes ( if they don't already have data )
33     if (const auto lineString = geodata_cast<GeoDataLineString>(placemark->geometry())) {
34         QVector<GeoDataCoordinates>::const_iterator it =  lineString->constBegin();
35         QVector<GeoDataCoordinates>::ConstIterator const end = lineString->constEnd();
36 
37         for ( ; it != end; ++it ) {
38             if (osmData.nodeReference(*it).isNull()) {
39                 osmData.nodeReference(*it).setId(--m_minId);
40             }
41         }
42     }
43 
44     const auto building = geodata_cast<GeoDataBuilding>(placemark->geometry());
45 
46     const GeoDataLinearRing* lineString;
47     if (building) {
48         lineString = geodata_cast<GeoDataLinearRing>(&static_cast<const GeoDataMultiGeometry*>(building->multiGeometry())->at(0));
49     } else {
50         lineString = geodata_cast<GeoDataLinearRing>(placemark->geometry());
51     }
52     // Assigning osmData to each of the line's nodes ( if they don't already have data )
53     if (lineString) {
54         for (auto it =lineString->constBegin(), end = lineString->constEnd(); it != end; ++it ) {
55             if (osmData.nodeReference(*it).isNull()) {
56                 osmData.nodeReference(*it).setId(--m_minId);
57             }
58         }
59     }
60 
61     const GeoDataPolygon* polygon;
62     if (building) {
63         polygon = geodata_cast<GeoDataPolygon>(&static_cast<const GeoDataMultiGeometry*>(building->multiGeometry())->at(0));
64     } else {
65         polygon = geodata_cast<GeoDataPolygon>(placemark->geometry());
66     }
67     // Assigning osmData to each of the polygons boundaries, and to each of the
68     // nodes that are part of those boundaries ( if they don't already have data )
69     if (polygon) {
70         const GeoDataLinearRing &outerBoundary = polygon->outerBoundary();
71         int index = -1;
72         if ( isNull ) {
73             osmData.addTag(QStringLiteral("type"), QStringLiteral("multipolygon"));
74         }
75 
76         // Outer boundary
77         OsmPlacemarkData &outerBoundaryData = osmData.memberReference( index );
78         if (outerBoundaryData.isNull()) {
79             outerBoundaryData.setId(--m_minId);
80         }
81 
82         // Outer boundary nodes
83         QVector<GeoDataCoordinates>::const_iterator it =  outerBoundary.constBegin();
84         QVector<GeoDataCoordinates>::ConstIterator const end = outerBoundary.constEnd();
85 
86         for ( ; it != end; ++it ) {
87             if (outerBoundaryData.nodeReference(*it).isNull()) {
88                 outerBoundaryData.nodeReference(*it).setId(--m_minId);
89             }
90         }
91 
92         // Each inner boundary
93         for( const GeoDataLinearRing &innerRing: polygon->innerBoundaries() ) {
94             ++index;
95             OsmPlacemarkData &innerRingData = osmData.memberReference( index );
96             if (innerRingData.isNull()) {
97                 innerRingData.setId(--m_minId);
98             }
99 
100             // Inner boundary nodes
101             QVector<GeoDataCoordinates>::const_iterator it =  innerRing.constBegin();
102             QVector<GeoDataCoordinates>::ConstIterator const end = innerRing.constEnd();
103 
104             for ( ; it != end; ++it ) {
105                 if (innerRingData.nodeReference(*it).isNull()) {
106                     innerRingData.nodeReference(*it).setId(--m_minId);
107                 }
108             }
109         }
110     }
111 }
112 
registerId(qint64 id)113 void OsmObjectManager::registerId( qint64 id )
114 {
115     m_minId = qMin( id, m_minId );
116 }
117 
118 }
119 
120