File indexing completed on 2025-01-19 12:41:34
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2011 Dennis Nienhüser <nienhueser@kde.org> 0004 // 0005 0006 #ifndef MARBLE_OSMPARSER_H 0007 #define MARBLE_OSMPARSER_H 0008 0009 #include "Writer.h" 0010 #include "OsmRegion.h" 0011 #include "OsmPlacemark.h" 0012 #include "OsmRegionTree.h" 0013 0014 #include <QObject> 0015 #include <QFileInfo> 0016 #include <QHash> 0017 #include <QList> 0018 #include <QPair> 0019 0020 namespace Marble 0021 { 0022 0023 class GeoDataLineString; 0024 0025 enum ElementType { 0026 NoType, 0027 NodeType, 0028 WayType, 0029 RelationType 0030 }; 0031 0032 enum RelationRole { 0033 None, 0034 Outer, 0035 Inner 0036 }; 0037 0038 struct OsmOsmRegion { 0039 OsmOsmRegion* parent; 0040 OsmRegion region; 0041 0042 OsmOsmRegion() : parent( nullptr ) {} 0043 }; 0044 0045 struct Element { 0046 bool save; 0047 QString name; 0048 QString street; 0049 QString houseNumber; 0050 QString city; 0051 OsmPlacemark::OsmCategory category; 0052 0053 Element() : save( false ), 0054 category( OsmPlacemark::UnknownCategory ) {} 0055 }; 0056 0057 struct Coordinate { 0058 float lon; 0059 float lat; 0060 0061 Coordinate(float lon=0.0, float lat=0.0); 0062 }; 0063 0064 struct Node : public Element { 0065 float lon; 0066 float lat; 0067 0068 operator OsmPlacemark() const; 0069 operator Coordinate() const; 0070 }; 0071 0072 struct Way : public Element { 0073 QList<int> nodes; 0074 bool isBuilding; 0075 0076 operator OsmPlacemark() const; 0077 void setPosition( const QHash<int, Coordinate> &database, OsmPlacemark &placemark ) const; 0078 void setRegion( const QHash<int, Node> &database, const OsmRegionTree & tree, QList<OsmOsmRegion> & osmOsmRegions, OsmPlacemark &placemark ) const; 0079 }; 0080 0081 struct WayMerger { 0082 public: 0083 QList<Way> ways; 0084 0085 WayMerger( const Way &way ) { 0086 ways << way; 0087 } 0088 0089 bool compatible( const Way &aWay ) const { 0090 for( const Way & way: ways ) { 0091 if ( way.nodes.first() == aWay.nodes.first() ) return true; 0092 if ( way.nodes.last() == aWay.nodes.first() ) return true; 0093 if ( way.nodes.first() == aWay.nodes.last() ) return true; 0094 if ( way.nodes.last() == aWay.nodes.last() ) return true; 0095 } 0096 0097 return false; 0098 } 0099 0100 bool compatible( const WayMerger &other ) const { 0101 for( const Way & way: ways ) { 0102 if ( other.compatible( way ) ) { 0103 return true; 0104 } 0105 } 0106 0107 return false; 0108 } 0109 0110 void merge( const WayMerger &other ) { 0111 ways << other.ways; 0112 } 0113 }; 0114 0115 struct Relation : public Element { 0116 QList<int> nodes; 0117 QList< QPair<int, RelationRole> > ways; 0118 QList<int> relations; 0119 QString name; 0120 bool isMultipolygon; 0121 bool isAdministrativeBoundary; 0122 int adminLevel; 0123 0124 Relation() : isMultipolygon( false ), 0125 isAdministrativeBoundary( false ), 0126 adminLevel( 0 ) 0127 { 0128 // nothing to do 0129 } 0130 }; 0131 0132 struct Statistic { 0133 unsigned int mergedWays; 0134 unsigned int uselessWays; 0135 0136 Statistic() : mergedWays( 0 ), 0137 uselessWays( 0 ) 0138 {} 0139 }; 0140 0141 class OsmParser : public QObject 0142 { 0143 Q_OBJECT 0144 public: 0145 explicit OsmParser( QObject *parent = nullptr ); 0146 0147 void addWriter( Writer* writer ); 0148 0149 void read( const QFileInfo &file, const QString &areaName ); 0150 0151 void writeKml( const QString &area, const QString &version, const QString &date, const QString &transport, const QString &payload, const QString &outputKml ) const; 0152 0153 protected: 0154 virtual bool parse( const QFileInfo &file, int pass, bool &needAnotherPass ) = 0; 0155 0156 bool shouldSave( ElementType type, const QString &key, const QString &value ); 0157 0158 void setCategory( Element &element, const QString &key, const QString &value ); 0159 0160 QHash<int, Coordinate> m_coordinates; 0161 0162 QHash<int, Node> m_nodes; 0163 0164 QHash<int, Way> m_ways; 0165 0166 QHash<int, Relation> m_relations; 0167 0168 private: 0169 GeoDataLinearRing *convexHull() const; 0170 0171 void importMultipolygon( const Relation &relation ); 0172 0173 void importWay( QVector<Marble::GeoDataLineString> &ways, int id ); 0174 0175 QList< QList<Way> > merge( const QList<Way> &ways ) const; 0176 0177 template<class T, class S> 0178 bool contains( const T &outer, const S &inner ) const { 0179 for ( int i = 0; i < inner.size(); ++i ) { 0180 if ( !outer.contains( inner[i] ) ) { 0181 bool onBorder = false; 0182 for ( int k=0; k<outer.size(); ++k ) { 0183 if ( inner[i] == outer[k] ) { 0184 onBorder = true; 0185 break; 0186 } 0187 } 0188 if ( !onBorder ) { 0189 return false; 0190 } 0191 } 0192 } 0193 0194 return true; 0195 } 0196 0197 QColor randomColor() const; 0198 0199 Marble::GeoDataLineString reverse( const Marble::GeoDataLineString & string ); 0200 0201 QList<Writer*> m_writers; 0202 0203 QList<OsmOsmRegion> m_osmOsmRegions; 0204 0205 QList<OsmPlacemark> m_placemarks; 0206 0207 QHash<QString, OsmPlacemark::OsmCategory> m_categoryMap; 0208 0209 mutable Statistic m_statistic; 0210 0211 GeoDataLinearRing* m_convexHull; 0212 }; 0213 0214 } 0215 0216 #endif // MARBLE_OSMPARSER_H