23 #include <netinet/in.h>
26 using namespace OSMPBF;
33 GOOGLE_PROTOBUF_VERIFY_VERSION;
39 needAnotherPass = pass < 2;
41 QFile file( fileInfo.absoluteFilePath() );
42 if ( !file.open( QFile::ReadOnly ) ) {
43 qCritical() <<
"Unable to open file " << fileInfo.absoluteFilePath() <<
" for reading.";
47 m_stream.setDevice( &file );
48 m_stream.setByteOrder( QDataStream::BigEndian );
50 if ( !parseBlobHeader() ) {
54 if ( m_blobHeader.type() !=
"OSMHeader" ) {
55 qCritical() <<
"Unable to parse blob header type " << m_blobHeader.type().c_str();
74 m_referencedWays.clear();
75 }
else if ( pass == 2 ) {
76 m_referencedNodes.clear();
104 bool PbfParser::parseBlobHeader()
110 qCritical() <<
"Invalid blob header size " << size;
114 m_buffer.resize( size );
115 int readBytes = m_stream.readRawData( m_buffer.data(), size );
116 if ( readBytes != size ) {
117 qCritical() <<
"Unable to read blob header";
121 if ( !m_blobHeader.ParseFromArray( m_buffer.constData(), size ) ) {
122 qCritical() <<
"Unable to parse blob header";
129 bool PbfParser::parseBlob()
131 int size = m_blobHeader.datasize();
133 qCritical() <<
"invalid blob size:" << size;
137 m_buffer.resize( size );
138 int readBytes = m_stream.readRawData( m_buffer.data(), size );
139 if ( readBytes != size ) {
140 qCritical() <<
"failed to read blob";
144 if ( !m_blob.ParseFromArray( m_buffer.constData(), size ) ) {
145 qCritical() <<
"failed to parse blob";
149 if ( m_blob.has_raw() ) {
150 const std::string& data = m_blob.raw();
151 m_buffer.resize( data.size() );
152 for (
unsigned int i = 0; i < data.size(); ++i ) {
153 m_buffer[i] = data[i];
155 }
else if ( m_blob.has_zlib_data() ) {
156 m_buffer.resize( m_blob.raw_size() );
158 zStream.next_in = (
unsigned char* ) m_blob.zlib_data().data();
159 zStream.avail_in = m_blob.zlib_data().size();
160 zStream.next_out = (
unsigned char* ) m_buffer.data();
161 zStream.avail_out = m_blob.raw_size();
162 zStream.zalloc = Z_NULL;
163 zStream.zfree = Z_NULL;
164 zStream.opaque = Z_NULL;
165 int result = inflateInit( &zStream );
166 if ( result != Z_OK ) {
167 qCritical() <<
"failed to open zlib m_stream";
170 result = inflate( &zStream, Z_FINISH );
171 if ( result != Z_STREAM_END ) {
172 qCritical() <<
"failed to inflate zlib m_stream";
175 result = inflateEnd( &zStream );
176 if ( result != Z_OK ) {
177 qCritical() <<
"failed to close zlib m_stream";
182 }
else if ( m_blob.has_lzma_data() ) {
183 qCritical() <<
"No support for lzma decryption implemented, sorry.";
186 qCritical() <<
"Blob contains no data";
193 bool PbfParser::parseData()
195 if ( !m_headerBlock.ParseFromArray( m_buffer.data(), m_buffer.size() ) ) {
196 qCritical() <<
"failed to parse header block";
200 for (
int i = 0; i < m_headerBlock.required_features_size(); ++i ) {
201 string const & feature = m_headerBlock.required_features( i );
202 if ( feature !=
"OsmSchema-V0.6" && feature !=
"DenseNodes" ) {
203 qCritical() <<
"Support for feature " << feature.c_str() <<
"not implemented";
211 bool PbfParser::readNext()
213 if ( !parseBlobHeader() )
216 if ( m_blobHeader.type() !=
"OSMData" ) {
217 qCritical() <<
"invalid block type, found" << m_blobHeader.type().data() <<
"instead of OSMData";
224 if ( !m_primitiveBlock.ParseFromArray( m_buffer.data(), m_buffer.size() ) ) {
225 qCritical() <<
"failed to parse PrimitiveBlock";
231 void PbfParser::loadGroup()
233 const PrimitiveGroup& group = m_primitiveBlock.primitivegroup( m_currentGroup );
234 if ( group.nodes_size() != 0 ) {
236 }
else if ( group.ways_size() != 0 ) {
238 }
else if ( group.relations_size() != 0 ) {
239 m_mode = ModeRelation;
240 }
else if ( group.has_dense() ) {
244 m_lastDenseLatitude = 0;
245 m_lastDenseLongitude = 0;
246 assert( group.dense().id_size() != 0 );
251 void PbfParser::loadBlock()
258 void PbfParser::parseNode()
261 const Node& inputNode = m_primitiveBlock.primitivegroup( m_currentGroup ).nodes( m_currentEntity );
263 node.
lat = ( ( double ) inputNode.lat() * m_primitiveBlock.granularity() + m_primitiveBlock.lat_offset() ) / ( 1000.0 * 1000.0 * 1000.0 );
264 node.
lon = ( ( double ) inputNode.lon() * m_primitiveBlock.granularity() + m_primitiveBlock.lon_offset() ) / ( 1000.0 * 1000.0 * 1000.0 );
266 for (
int tag = 0; tag < inputNode.keys_size(); tag++ ) {
268 QString key = QString::fromUtf8( m_primitiveBlock.stringtable().s( inputNode.keys( tag ) ).data() );
269 QString value = QString::fromUtf8( m_primitiveBlock.stringtable().s( inputNode.vals( tag ) ).data() );
271 if ( key ==
"name" ) {
272 node.
name = value.trimmed();
273 }
else if ( key ==
"addr:street" ) {
274 node.
street = value.trimmed();
276 }
else if ( key ==
"addr:housenumber" ) {
279 }
else if ( key ==
"addr:city" ) {
291 m_nodes[inputNode.id()] = node;
294 if ( m_referencedNodes.contains( inputNode.id() ) ) {
300 if ( m_currentEntity >= m_primitiveBlock.primitivegroup( m_currentGroup ).nodes_size() ) {
303 if ( m_currentGroup >= m_primitiveBlock.primitivegroup_size() )
310 void PbfParser::parseWay()
313 const Way& inputWay = m_primitiveBlock.primitivegroup( m_currentGroup ).ways( m_currentEntity );
317 for (
int tag = 0; tag < inputWay.keys_size(); tag++ ) {
318 QString key = QString::fromUtf8( m_primitiveBlock.stringtable().s( inputWay.keys( tag ) ).data() );
319 QString value = QString::fromUtf8( m_primitiveBlock.stringtable().s( inputWay.vals( tag ) ).data() );
321 if ( key ==
"name" ) {
322 way.
name = value.trimmed();
323 }
else if ( key ==
"addr:street" ) {
324 way.
street = value.trimmed();
326 }
else if ( key ==
"addr:housenumber" ) {
329 }
else if ( key ==
"addr:city" ) {
332 }
else if ( key ==
"building" && value ==
"yes" ) {
334 }
else if ( key ==
"boundary" && value ==
"administrative" ) {
336 }
else if ( key ==
"admin_level" ) {
346 long long lastRef = 0;
347 for (
int i = 0; i < inputWay.refs_size(); i++ ) {
348 lastRef += inputWay.refs( i );
349 way.
nodes.push_back( lastRef );
354 relation.
ways << QPair<int, Marble::RelationRole>( inputWay.id(),
Marble::Outer );
358 if ( way.
save || m_referencedWays.contains( inputWay.id() ) ) {
359 if ( !way.
isBuilding && way.
nodes.size() > 1 && !m_referencedWays.contains( inputWay.id() ) ) {
360 QList<int> nodes = way.
nodes;
362 way.
nodes << nodes.first();
363 if ( nodes.size() > 2 ) {
364 way.
nodes << nodes.at( nodes.size() / 2 );
366 way.
nodes << nodes.last();
369 foreach(
int node, way.
nodes ) {
370 m_referencedNodes << node;
373 m_ways[inputWay.id()] = way;
378 if ( m_currentEntity >= m_primitiveBlock.primitivegroup( m_currentGroup ).ways_size() ) {
381 if ( m_currentGroup >= m_primitiveBlock.primitivegroup_size() )
388 void PbfParser::parseRelation()
391 const Relation& inputRelation = m_primitiveBlock.primitivegroup( m_currentGroup ).relations( m_currentEntity );
394 for (
int tag = 0; tag < inputRelation.keys_size(); tag++ ) {
396 QString key = QString::fromUtf8( m_primitiveBlock.stringtable().s( inputRelation.keys( tag ) ).data() );
397 QString value = QString::fromUtf8( m_primitiveBlock.stringtable().s( inputRelation.vals( tag ) ).data() );
399 if ( key ==
"boundary" && value ==
"administrative" ) {
401 }
else if ( key ==
"admin_level" ) {
403 }
else if ( key ==
"name" ) {
404 relation.
name = value.trimmed();
405 }
else if ( key ==
"type" && value ==
"multipolygon" ) {
411 long long lastRef = 0;
412 for (
int i = 0; i < inputRelation.types_size(); i++ ) {
413 lastRef += inputRelation.memids( i );
414 switch ( inputRelation.types( i ) ) {
415 case OSMPBF::Relation::NODE:
416 relation.
nodes.push_back( lastRef );
418 case OSMPBF::Relation::WAY: {
419 string role = m_primitiveBlock.stringtable().s( inputRelation.roles_sid( i ) ).data();
423 m_referencedWays << lastRef;
424 relation.
ways.push_back( QPair<int, Marble::RelationRole>( lastRef, relationRole ) );
427 case OSMPBF::Relation::RELATION:
437 if ( m_currentEntity >= m_primitiveBlock.primitivegroup( m_currentGroup ).relations_size() ) {
440 if ( m_currentGroup >= m_primitiveBlock.primitivegroup_size() )
447 void PbfParser::parseDense()
449 const DenseNodes& dense = m_primitiveBlock.primitivegroup( m_currentGroup ).dense();
451 m_lastDenseID += dense.id( m_currentEntity );
452 m_lastDenseLatitude += dense.lat( m_currentEntity );
453 m_lastDenseLongitude += dense.lon( m_currentEntity );
456 node.
lat = ( ( double ) m_lastDenseLatitude * m_primitiveBlock.granularity() + m_primitiveBlock.lat_offset() ) / ( 1000.0 * 1000.0 * 1000.0 );
457 node.
lon = ( ( double ) m_lastDenseLongitude * m_primitiveBlock.granularity() + m_primitiveBlock.lon_offset() ) / ( 1000.0 * 1000.0 * 1000.0 );
460 if ( m_lastDenseTag >= dense.keys_vals_size() )
463 int tagValue = dense.keys_vals( m_lastDenseTag );
464 if ( tagValue == 0 ) {
469 QString key = QString::fromUtf8( m_primitiveBlock.stringtable().s( dense.keys_vals( m_lastDenseTag ) ).data() );
470 QString value = QString::fromUtf8( m_primitiveBlock.stringtable().s( dense.keys_vals( m_lastDenseTag + 1 ) ).data() );
472 if ( key ==
"name" ) {
473 node.
name = value.trimmed();
474 }
else if ( key ==
"addr:street" ) {
475 node.
street = value.trimmed();
477 }
else if ( key ==
"addr:housenumber" ) {
480 }
else if ( key ==
"addr:city" ) {
497 if ( m_referencedNodes.contains( m_lastDenseID ) ) {
503 if ( m_currentEntity >= dense.id_size() ) {
506 if ( m_currentGroup >= m_primitiveBlock.primitivegroup_size() ) {
QHash< int, Coordinate > m_coordinates
void setCategory(Element &element, const QString &key, const QString &value)
virtual bool parse(const QFileInfo &file, int pass, bool &needAnotherPass)
QHash< int, Relation > m_relations
QList< QPair< int, RelationRole > > ways
bool shouldSave(ElementType type, const QString &key, const QString &value)
QHash< int, Node > m_nodes
bool isAdministrativeBoundary