~ubuntu-branches/ubuntu/trusty/qgis/trusty

« back to all changes in this revision

Viewing changes to src/providers/osm/osmhandler.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
    osmhandler.cpp - handler for parsing OSM data
 
3
    ------------------
 
4
    begin                : October 2008
 
5
    copyright            : (C) 2008 by Lukas Berka
 
6
 ***************************************************************************
 
7
 *                                                                         *
 
8
 *   This program is free software; you can redistribute it and/or modify  *
 
9
 *   it under the terms of the GNU General Public License as published by  *
 
10
 *   the Free Software Foundation; either version 2 of the License, or     *
 
11
 *   (at your option) any later version.                                   *
 
12
 *                                                                         *
 
13
 ***************************************************************************/
 
14
 
 
15
#include "osmhandler.h"
 
16
 
 
17
#include <iostream>
 
18
#include <cstring>
 
19
 
 
20
#include "qgslogger.h"
 
21
#include "qgsapplication.h"
 
22
#include "qgsgeometry.h"
 
23
 
 
24
#include <QtXml/QXmlSimpleReader>
 
25
#include <QtXml/QXmlInputSource>
 
26
#include <QtGui/QApplication>
 
27
#include <QtGui/QLabel>
 
28
#include <QtXml/QXmlAttributes>
 
29
#include <QtCore/QFile>
 
30
 
 
31
#define MAX_FEATURE_ID 99999999
 
32
#define COMMIT_AFTER_TAGS 300000
 
33
 
 
34
 
 
35
// object construction
 
36
OsmHandler::OsmHandler( QFile *f, sqlite3 *database )
 
37
{
 
38
  mDatabase = database;
 
39
  mCnt = 0;
 
40
  mPointCnt = mLineCnt = mPolygonCnt = 0;
 
41
  mPosId = 1;
 
42
  xMin = yMin = MAX_FEATURE_ID;
 
43
  xMax = yMax = -MAX_FEATURE_ID;
 
44
  firstWayMemberId = "";
 
45
  mFirstMemberAppeared = 0;
 
46
 
 
47
  char sqlInsertNode[] = "INSERT INTO node ( id, lat, lon, timestamp, user, usage ) VALUES (?,?,?,?,?,'0');";
 
48
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertNode, sizeof( sqlInsertNode ), &mStmtInsertNode, 0 ) != SQLITE_OK )
 
49
  {
 
50
    QgsDebugMsg( "failed to prepare sqlInsertNode!!!" );
 
51
  }
 
52
 
 
53
  char sqlInsertWay[] = "INSERT INTO way ( id, timestamp, user, closed ) VALUES (?,?,?,?);";
 
54
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertWay, sizeof( sqlInsertWay ), &mStmtInsertWay, 0 ) != SQLITE_OK )
 
55
  {
 
56
    QgsDebugMsg( "failed to prepare sqlInsertWay!!!" );
 
57
  }
 
58
 
 
59
  char sqlInsertTag[] = "INSERT INTO tag ( key, val, object_id, object_type ) VALUES (?,?,?,?);";
 
60
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertTag, sizeof( sqlInsertTag ), &mStmtInsertTag, 0 ) != SQLITE_OK )
 
61
  {
 
62
    QgsDebugMsg( "failed to prepare sqlInsertTag!!!" );
 
63
  }
 
64
 
 
65
  char sqlInsertWayMember[] = "INSERT INTO way_member ( way_id, pos_id, node_id ) VALUES (?,?,?);";
 
66
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertWayMember, sizeof( sqlInsertWayMember ), &mStmtInsertWayMember, 0 ) != SQLITE_OK )
 
67
  {
 
68
    QgsDebugMsg( "failed to prepare sqlInsertWayMember!!!" );
 
69
  }
 
70
 
 
71
  char sqlInsertRelation[] = "INSERT INTO relation ( id, timestamp, user, type ) VALUES (?,?,?,?);";
 
72
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertRelation, sizeof( sqlInsertRelation ), &mStmtInsertRelation, 0 ) != SQLITE_OK )
 
73
  {
 
74
    QgsDebugMsg( "failed to prepare sqlInsertRelation!!!" );
 
75
  }
 
76
 
 
77
  char sqlInsertRelationMember[] = "INSERT INTO relation_member ( relation_id, pos_id, member_id, member_type, role ) VALUES (?,?,?,?,?);";
 
78
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertRelationMember, sizeof( sqlInsertRelationMember ), &mStmtInsertRelationMember, 0 ) != SQLITE_OK )
 
79
  {
 
80
    QgsDebugMsg( "failed to prepare sqlInsertRelationMember!!!" );
 
81
  }
 
82
 
 
83
  char sqlInsertVersion[] = "INSERT INTO version (object_id,object_type,version_id) VALUES (?,?,?);";
 
84
  if ( sqlite3_prepare_v2( mDatabase, sqlInsertVersion, sizeof( sqlInsertVersion ), &mStmtInsertVersion, 0 ) != SQLITE_OK )
 
85
  {
 
86
    QgsDebugMsg( "failed to prepare sqlInsertVersion!!!" );
 
87
  }
 
88
}
 
89
 
 
90
OsmHandler::~OsmHandler()
 
91
{
 
92
  sqlite3_finalize( mStmtInsertTag );
 
93
  sqlite3_finalize( mStmtInsertNode );
 
94
  sqlite3_finalize( mStmtInsertWay );
 
95
  sqlite3_finalize( mStmtInsertWayMember );
 
96
  sqlite3_finalize( mStmtInsertRelation );
 
97
  sqlite3_finalize( mStmtInsertRelationMember );
 
98
  sqlite3_finalize( mStmtInsertVersion );
 
99
}
 
100
 
 
101
 
 
102
bool OsmHandler::startDocument()
 
103
{
 
104
  sqlite3_exec( mDatabase, "BEGIN;", 0, 0, 0 );
 
105
  return true;
 
106
}
 
107
 
 
108
 
 
109
QString OsmHandler::errorString()
 
110
{
 
111
  return mError;
 
112
}
 
113
 
 
114
 
 
115
bool OsmHandler::startElement( const QString & pUri, const QString & pLocalName, const QString & pName, const QXmlAttributes & pAttrs )
 
116
{
 
117
  QString name = pLocalName;
 
118
 
 
119
  if ( name == "osm" )
 
120
  {
 
121
    if ( pAttrs.value( "version" ) != "0.6" )
 
122
    {
 
123
      mError = "Invalid OSM version. Only files of v0.6 are supported.";
 
124
      return false;
 
125
    }
 
126
  }
 
127
  else if ( name == "node" )
 
128
  {
 
129
    //todo: test if pAttrs.value("visible").toUtf8() is "true" -> if not, node has to be ignored!
 
130
 
 
131
    mObjectId = pAttrs.value( "id" );
 
132
    mObjectType = "node";
 
133
 
 
134
    double id = pAttrs.value( "id" ).toInt();
 
135
    double lat = pAttrs.value( "lat" ).toDouble();
 
136
    double lon = pAttrs.value( "lon" ).toDouble();
 
137
    QString timestamp = pAttrs.value( "timestamp" );
 
138
    QString user = pAttrs.value( "user" );
 
139
 
 
140
    if ( lat < yMin ) yMin = lat;
 
141
    if ( lat > yMax ) yMax = lat;
 
142
    if ( lon < xMin ) xMin = lon;
 
143
    if ( lon > xMax ) xMax = lon;
 
144
 
 
145
    sqlite3_bind_int( mStmtInsertNode, 1, id );
 
146
    sqlite3_bind_double( mStmtInsertNode, 2, lat );
 
147
    sqlite3_bind_double( mStmtInsertNode, 3, lon );
 
148
    sqlite3_bind_text( mStmtInsertNode, 4, timestamp.toUtf8(), -1, SQLITE_TRANSIENT ); // TODO: maybe static?
 
149
    sqlite3_bind_text( mStmtInsertNode, 5, user.toUtf8(), -1, SQLITE_TRANSIENT ); // TODO: maybe static?
 
150
 
 
151
    if ( sqlite3_step( mStmtInsertNode ) != SQLITE_DONE )
 
152
    {
 
153
      QgsDebugMsg( "Storing node information into database failed." );
 
154
      return false;
 
155
    }
 
156
 
 
157
    sqlite3_reset( mStmtInsertNode ); // make ready for next insert
 
158
 
 
159
    // store version number of this object
 
160
    sqlite3_bind_text( mStmtInsertVersion, 1, pAttrs.value( "id" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
161
    sqlite3_bind_text( mStmtInsertVersion, 2, mObjectType.toUtf8(), -1, SQLITE_TRANSIENT );
 
162
    sqlite3_bind_text( mStmtInsertVersion, 3, pAttrs.value( "version" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
163
 
 
164
    if ( sqlite3_step( mStmtInsertVersion ) != SQLITE_DONE )
 
165
    {
 
166
      QgsDebugMsg( "Storing version information into database failed." );
 
167
      return false;
 
168
    }
 
169
    sqlite3_reset( mStmtInsertVersion ); // make ready for next insert
 
170
 
 
171
    // increase node counter
 
172
    mPointCnt++;
 
173
  }
 
174
  else if ( name == "way" )
 
175
  {
 
176
    mObjectId = pAttrs.value( "id" );
 
177
    mObjectType = "way";
 
178
    mPosId = 1;
 
179
    mFirstMemberAppeared = 0;
 
180
 
 
181
    //todo: test if pAttrs.value("visible").toUtf8() is "true" -> if not, way has to be ignored!
 
182
 
 
183
    sqlite3_bind_text( mStmtInsertWay, 1, mObjectId.toUtf8(), -1, SQLITE_TRANSIENT );
 
184
    sqlite3_bind_text( mStmtInsertWay, 2, pAttrs.value( "timestamp" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
185
    sqlite3_bind_text( mStmtInsertWay, 3, pAttrs.value( "user" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
186
 
 
187
    // store version number of this object
 
188
    sqlite3_bind_text( mStmtInsertVersion, 1, pAttrs.value( "id" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
189
    sqlite3_bind_text( mStmtInsertVersion, 2, mObjectType.toUtf8(), -1, SQLITE_TRANSIENT );
 
190
    sqlite3_bind_text( mStmtInsertVersion, 3, pAttrs.value( "version" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
191
 
 
192
    if ( sqlite3_step( mStmtInsertVersion ) != SQLITE_DONE )
 
193
    {
 
194
      QgsDebugMsg( "Storing version information into database failed." );
 
195
      return false;
 
196
    }
 
197
    sqlite3_reset( mStmtInsertVersion ); // make ready for next insert
 
198
  }
 
199
  else if ( name == "nd" )
 
200
  {
 
201
    // store id of the first and last way member to be able to decide if the way is closed (polygon) or not
 
202
    if ( firstWayMemberId == "" )
 
203
    {
 
204
      firstWayMemberId = pAttrs.value( "ref" );
 
205
    }
 
206
    lastWayMemberId = pAttrs.value( "ref" );
 
207
 
 
208
    if ( firstWayMemberId == lastWayMemberId )
 
209
      mFirstMemberAppeared++;
 
210
 
 
211
    if (( firstWayMemberId != lastWayMemberId ) || ( mFirstMemberAppeared < 2 ) )
 
212
    {
 
213
      sqlite3_bind_text( mStmtInsertWayMember, 1, mObjectId.toUtf8(), -1, SQLITE_TRANSIENT ); // TODO: maybe static?
 
214
      sqlite3_bind_int( mStmtInsertWayMember, 2, mPosId );
 
215
      sqlite3_bind_text( mStmtInsertWayMember, 3, pAttrs.value( "ref" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
216
 
 
217
      if ( sqlite3_step( mStmtInsertWayMember ) != SQLITE_DONE )
 
218
      {
 
219
        QgsDebugMsg( "Storing way-node relationship into database failed." );
 
220
        return false;
 
221
      };
 
222
      sqlite3_reset( mStmtInsertWayMember );
 
223
    }
 
224
    mPosId++;
 
225
  }
 
226
  else if ( name == "relation" )
 
227
  {
 
228
    mObjectId = pAttrs.value( "id" );
 
229
    mRelationType = "";
 
230
    mObjectType = "relation";
 
231
    mPosId = 1;
 
232
 
 
233
    //todo: test if pAttrs.value("visible").toUtf8() is "true" -> if not, relation has to be ignored!
 
234
 
 
235
    sqlite3_bind_text( mStmtInsertRelation, 1, mObjectId.toUtf8(), -1, SQLITE_TRANSIENT );
 
236
    sqlite3_bind_text( mStmtInsertRelation, 2, pAttrs.value( "timestamp" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
237
    sqlite3_bind_text( mStmtInsertRelation, 3, pAttrs.value( "user" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
238
 
 
239
    // store version number of this object
 
240
    sqlite3_bind_text( mStmtInsertVersion, 1, pAttrs.value( "id" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
241
    sqlite3_bind_text( mStmtInsertVersion, 2, mObjectType.toUtf8(), -1, SQLITE_TRANSIENT );
 
242
    sqlite3_bind_text( mStmtInsertVersion, 3, pAttrs.value( "version" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
243
 
 
244
    if ( sqlite3_step( mStmtInsertVersion ) != SQLITE_DONE )
 
245
    {
 
246
      QgsDebugMsg( "Storing version information into database failed." );
 
247
      return false;
 
248
    }
 
249
    sqlite3_reset( mStmtInsertVersion ); // make ready for next insert
 
250
  }
 
251
  else if ( name == "member" )
 
252
  {
 
253
    sqlite3_bind_text( mStmtInsertRelationMember, 1, mObjectId.toUtf8(), -1, SQLITE_TRANSIENT );
 
254
    sqlite3_bind_int( mStmtInsertRelationMember, 2, mPosId );
 
255
    sqlite3_bind_text( mStmtInsertRelationMember, 3, pAttrs.value( "ref" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
256
    sqlite3_bind_text( mStmtInsertRelationMember, 4, pAttrs.value( "type" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
257
    sqlite3_bind_text( mStmtInsertRelationMember, 5, pAttrs.value( "role" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
258
 
 
259
    if ( sqlite3_step( mStmtInsertRelationMember ) != SQLITE_DONE )
 
260
    {
 
261
      QgsDebugMsg( "Storing relation-feature relationship into database failed." );
 
262
      return false;
 
263
    };
 
264
 
 
265
    sqlite3_reset( mStmtInsertRelationMember );
 
266
    mPosId++;
 
267
  }
 
268
  else if ( name == "tag" )
 
269
  {
 
270
    if ( mCnt == COMMIT_AFTER_TAGS )
 
271
    {
 
272
      sqlite3_exec( mDatabase, "COMMIT;", 0, 0, 0 );
 
273
      sqlite3_exec( mDatabase, "BEGIN;", 0, 0, 0 );
 
274
      mCnt = 0;
 
275
    }
 
276
    mCnt++;
 
277
 
 
278
    sqlite3_bind_text( mStmtInsertTag, 1, pAttrs.value( "k" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
279
    sqlite3_bind_text( mStmtInsertTag, 2, pAttrs.value( "v" ).toUtf8(), -1, SQLITE_TRANSIENT );
 
280
    sqlite3_bind_text( mStmtInsertTag, 3, mObjectId.toUtf8(), -1, SQLITE_TRANSIENT );
 
281
    sqlite3_bind_text( mStmtInsertTag, 4, mObjectType.toUtf8(), -1, SQLITE_TRANSIENT );
 
282
 
 
283
    // we've got node parameters -> let's create new database record
 
284
    if ( sqlite3_step( mStmtInsertTag ) != SQLITE_DONE )
 
285
    {
 
286
      QgsDebugMsg( QString( "Storing tag into database failed. K:%1, V:%2." ).arg( pAttrs.value( "k" ) ).arg( pAttrs.value( "v" ) ) );
 
287
      return false;
 
288
    }
 
289
    sqlite3_reset( mStmtInsertTag );
 
290
 
 
291
    // if we are under xml tag <relation> and we reach xml tag <tag k="type" v="...">, lets insert prepared relation into DB
 
292
    if (( mObjectType == "relation" ) && ( pAttrs.value( "k" ) == "type" ) )
 
293
    {
 
294
      mRelationType = pAttrs.value( "v" );
 
295
    }
 
296
  }
 
297
  else if ( name == "bounds" )
 
298
  {
 
299
    // e.g. <bounds minlat="41.388625" minlon="2.15426" maxlat="41.391732" maxlon="2.158192"/>
 
300
 
 
301
    // xMin = pAttrs.value("minlon").toDouble();
 
302
    // xMax = pAttrs.value("maxlon").toDouble();
 
303
    // yMin = pAttrs.value("minlat").toDouble();
 
304
    // yMax = pAttrs.value("maxlat").toDouble();
 
305
  }
 
306
  return true;
 
307
}
 
308
 
 
309
 
 
310
bool OsmHandler::endElement( const QString & pURI, const QString & pLocalName, const QString & pName )
 
311
{
 
312
  QString name = pLocalName;
 
313
  if ( name == "way" )
 
314
  {
 
315
    int isPolygon = false;
 
316
    int cntMembers = mPosId - 1;
 
317
 
 
318
    if ( firstWayMemberId == lastWayMemberId )
 
319
      isPolygon = true;
 
320
 
 
321
    // test if polygon is correct; it should have >2 member points
 
322
    if (( isPolygon ) && ( cntMembers < 4 ) )
 
323
    {
 
324
      sqlite3_reset( mStmtInsertWay );
 
325
      return true;
 
326
    }
 
327
 
 
328
    // test if way is correct; it should have more then 1 member point
 
329
    if ( cntMembers < 2 )
 
330
    {
 
331
      sqlite3_reset( mStmtInsertWay );
 
332
      return true;
 
333
    }
 
334
 
 
335
    // we should bind the last information needed for way insertion -> if the way is closed (polygon) or not
 
336
    sqlite3_bind_int( mStmtInsertWay, 4, ( isPolygon ? 1 : 0 ) );
 
337
 
 
338
    // well, insert new way
 
339
    if ( sqlite3_step( mStmtInsertWay ) != SQLITE_DONE )
 
340
    {
 
341
      QgsDebugMsg( "Storing way information into database failed." );
 
342
      return false;
 
343
    };
 
344
 
 
345
    // make statement ready for next insert
 
346
    sqlite3_reset( mStmtInsertWay );
 
347
 
 
348
    if ( isPolygon )
 
349
      mPolygonCnt++;
 
350
    else
 
351
      mLineCnt++;
 
352
 
 
353
    // make variables ready for next way parsing
 
354
    firstWayMemberId = "";
 
355
  }
 
356
  else if ( name == "relation" )
 
357
  {
 
358
    sqlite3_bind_text( mStmtInsertRelation, 4, mRelationType.toUtf8(), -1, SQLITE_TRANSIENT );
 
359
 
 
360
    if ( sqlite3_step( mStmtInsertRelation ) != SQLITE_DONE )
 
361
    {
 
362
      QgsDebugMsg( QString( "Storing relation into database failed." ) );
 
363
      return false;
 
364
    }
 
365
    sqlite3_reset( mStmtInsertRelation );
 
366
  }
 
367
  return true;
 
368
}
 
369
 
 
370
 
 
371
bool OsmHandler::endDocument()
 
372
{
 
373
  // first commit all database actions connected to xml parsing
 
374
  sqlite3_exec( mDatabase, "COMMIT;", 0, 0, 0 );
 
375
  return true;
 
376
}
 
377