[QGIS Commit] r11284 - in trunk/qgis: python/plugins/osm src/providers/osm

svn_qgis at osgeo.org svn_qgis at osgeo.org
Thu Aug 6 10:12:49 EDT 2009


Author: wonder
Date: 2009-08-06 10:12:49 -0400 (Thu, 06 Aug 2009)
New Revision: 11284

Modified:
   trunk/qgis/python/plugins/osm/DlgLoadOSM.py
   trunk/qgis/src/providers/osm/osmprovider.cpp
   trunk/qgis/src/providers/osm/osmprovider.h
Log:
Update to OSM provider+plugin from Lukas Berka:
-osm provider code documentation; refactoring


Modified: trunk/qgis/python/plugins/osm/DlgLoadOSM.py
===================================================================
--- trunk/qgis/python/plugins/osm/DlgLoadOSM.py	2009-08-06 14:09:40 UTC (rev 11283)
+++ trunk/qgis/python/plugins/osm/DlgLoadOSM.py	2009-08-06 14:12:49 UTC (rev 11284)
@@ -135,8 +135,6 @@
             # remove layers of current data first 
             QgsMapLayerRegistry.instance().removeMapLayer(self.canvas.currentLayer().getLayerID(),True)
 
-        tags = "&tags=yes"
-
         if self.chkCustomRenderer.isChecked():
             styleFile=self.styleFiles[self.styleCombo.currentIndex()]
             style="&style="+styleFile
@@ -160,7 +158,7 @@
         self.setProperty("osm_stop_parsing",QVariant(0))
 
         # add polygon layer
-        polygonLayer = QgsVectorLayer(self.fname+"?type=polygon"+observer + tags + tag + style, basename+" polygons", "osm")
+        polygonLayer = QgsVectorLayer(self.fname+"?type=polygon"+observer + tag + style, basename+" polygons", "osm")
 
         if self.loadingCanceled:
             polygonLayer=None
@@ -174,7 +172,7 @@
         QgsMapLayerRegistry.instance().addMapLayer(polygonLayer)
 
         # add line layer
-        lineLayer = QgsVectorLayer(self.fname+"?type=line"+observer + tags + tag + style, basename+" lines", "osm")
+        lineLayer = QgsVectorLayer(self.fname+"?type=line"+observer + tag + style, basename+" lines", "osm")
 
         if self.loadingCanceled:
             lineLayer=None
@@ -188,7 +186,7 @@
         QgsMapLayerRegistry.instance().addMapLayer(lineLayer)
 
         # add point layer
-        pointLayer = QgsVectorLayer(self.fname+"?type=point"+observer + tags + tag + style, basename+" points", "osm")
+        pointLayer = QgsVectorLayer(self.fname+"?type=point"+observer + tag + style, basename+" points", "osm")
 
         if self.loadingCanceled:
             pointLayer=None

Modified: trunk/qgis/src/providers/osm/osmprovider.cpp
===================================================================
--- trunk/qgis/src/providers/osm/osmprovider.cpp	2009-08-06 14:09:40 UTC (rev 11283)
+++ trunk/qgis/src/providers/osm/osmprovider.cpp	2009-08-06 14:12:49 UTC (rev 11284)
@@ -56,7 +56,7 @@
   mDatabase = NULL;
   mInitObserver = NULL;
   mFeatureType = PointType; // default
-  mTagsRetrieval = false;
+
   // set default boundaries
   xMin = -DEFAULT_EXTENT;
   xMax = DEFAULT_EXTENT;
@@ -102,10 +102,6 @@
       mInitObserver = ( QObject* ) observerAddr;
       mInitObserver->setProperty( "osm_state", QVariant( 1 ) );
     }
-    if ( propName == "tags" )
-    {
-      mTagsRetrieval = ( propValue == "yes" );
-    }
     if ( propName == "tag" )
     {
       mCustomTagsList = propValue.split( "+" );
@@ -265,7 +261,7 @@
 {
   QFile osmFile( mFileName );
   QFileInfo osmFileInfo( osmFile );
-  mOsmFileLastModif = osmFileInfo.lastModified();
+  QDateTime mOsmFileLastModif = osmFileInfo.lastModified();
 
   QString cmd = QString( "SELECT val FROM meta WHERE key='osm-file-last-modified';" );
   QByteArray cmd_bytes = cmd.toAscii();
@@ -522,7 +518,7 @@
     geo[geo[0] == QgsApplication::NDR ? 1 : 4] = QGis::WKBPoint;
     std::memcpy( geo + 5, &selLon, sizeof( double ) );
     std::memcpy( geo + 13, &selLat, sizeof( double ) );
-    feature.setGeometryAndOwnership(( unsigned char * )geo, sizeof( wkbPoint ) );
+    feature.setGeometryAndOwnership(( unsigned char * )geo, 24 );    // 24 is size of wkb point structure!
   }
 
   // fetch attributes
@@ -536,10 +532,7 @@
       case UserAttr:
         feature.addAttribute( UserAttr, QString::fromUtf8( selUser ) ); break;
       case TagAttr:
-        if ( mTagsRetrieval )
-          feature.addAttribute( TagAttr, tagsForObject( "node", selId ) );
-        else
-          feature.addAttribute( TagAttr, QString() );
+        feature.addAttribute(TagAttr, tagsForObject("node",selId));
         break;
 
       default: // suppose it's a custom tag
@@ -652,10 +645,7 @@
         feature.addAttribute( UserAttr, QString::fromUtf8( selUser ) );
         break;
       case TagAttr:
-        if ( mTagsRetrieval )
-          feature.addAttribute( TagAttr, tagsForObject( "way", selId ) );
-        else
-          feature.addAttribute( TagAttr, QString() );
+        feature.addAttribute(TagAttr, tagsForObject("way",selId));
         break;
       default: // suppose it's a custom tag
         if ( *iter >= CustomTagAttr && *iter < CustomTagAttr + mCustomTagsList.count() )
@@ -670,33 +660,7 @@
 }
 
 
-int QgsOSMDataProvider::relationMemberCount( int relId )
-{
-  const char *zSql = "select count(*) from relation_member rm, way_member wm, node n where rm.relation_id=? and rm.member_type='way' and rm.member_id=wm.way_id and wm.node_id=n.id and wm.u=1 and n.u=1 and rm.u=1;";
-  sqlite3_stmt *pStmt;
-  int rc = sqlite3_prepare_v2( mDatabase, zSql, -1, &pStmt, 0 );
 
-  if ( rc != SQLITE_OK )
-  {
-    QgsDebugMsg( QString( "Failed (1)." ) );
-    return 0;
-  }
-
-  sqlite3_bind_int( pStmt, 1, relId );
-
-  rc = sqlite3_step( pStmt );
-  if ( rc != SQLITE_ROW )
-  {
-    QgsDebugMsg( QString( "Failed (2)." ) );
-    return 0;
-  }
-
-  int memberCnt = sqlite3_column_int( pStmt, 0 );
-  sqlite3_finalize( pStmt );
-  return memberCnt;
-}
-
-
 QString QgsOSMDataProvider::tagForObject( const char* type, int id, QString tagKey )
 {
   sqlite3_bind_int( mCustomTagsStmt, 1, id );
@@ -945,54 +909,6 @@
 }
 
 
-bool QgsOSMDataProvider::changeGeometryValue( const int & featid, QgsGeometry & geom )
-{
-  if ( mFeatureType == PointType )
-  {
-    QgsDebugMsg( QString( "Changing geometry of point with id=%1." ).arg( featid ) );
-    QgsPoint point = geom.asPoint();
-
-    const char *zSql = "UPDATE node SET lat=?, lon=?, status='U' WHERE id=? AND u=1";
-    sqlite3_stmt *pStmt;
-    int rc;
-
-    rc = sqlite3_prepare_v2( mDatabase, zSql, -1, &pStmt, 0 );
-    if ( rc != SQLITE_OK )
-      return rc;
-
-    sqlite3_bind_double( pStmt, 1, point.y() );
-    sqlite3_bind_double( pStmt, 2, point.x() );
-    sqlite3_bind_int( pStmt, 3, featid );
-
-    rc = sqlite3_step( pStmt );
-    rc = sqlite3_finalize( pStmt );
-  }
-  else if ( mFeatureType == LineType )
-  {
-    QgsDebugMsg( QString( "Changing geometry of way with id=%1." ).arg( featid ) );
-    QgsPolyline way = geom.asPolyline();
-    unsigned char *wkb = geom.asWkb();
-
-    const char *zSql = "UPDATE way SET wkb=?, membercnt=?, status='U' WHERE id=? AND u=1";
-    sqlite3_stmt *pStmt;
-    int rc;
-
-    rc = sqlite3_prepare_v2( mDatabase, zSql, -1, &pStmt, 0 );
-    if ( rc != SQLITE_OK )
-      return rc;
-
-    sqlite3_bind_blob( pStmt, 1, wkb, 9 + 16 * way.size(), SQLITE_STATIC );
-    sqlite3_bind_int( pStmt, 2, way.size() );
-    sqlite3_bind_int( pStmt, 3, featid );
-
-    rc = sqlite3_step( pStmt );
-    rc = sqlite3_finalize( pStmt );
-
-  }
-  return true;
-}
-
-
 int QgsOSMDataProvider::capabilities() const
 {
   return QgsVectorDataProvider::SelectAtId | QgsVectorDataProvider::SelectGeometryAtId;

Modified: trunk/qgis/src/providers/osm/osmprovider.h
===================================================================
--- trunk/qgis/src/providers/osm/osmprovider.h	2009-08-06 14:09:40 UTC (rev 11283)
+++ trunk/qgis/src/providers/osm/osmprovider.h	2009-08-06 14:12:49 UTC (rev 11284)
@@ -16,24 +16,97 @@
 
 #include <sqlite3.h>
 #include <QFile>
-#include <QDateTime>
 
 
 
+class QgsOSMDataProvider: public QgsVectorDataProvider
+{
 
-typedef QMap<int, QgsFeature> QgsFeatureMap;
+  private:
 
+    //! provider can manage features with one of three geometry types; variable determines feature type of this provider
+    enum { PointType, LineType, PolygonType } mFeatureType;
 
+    //! supported feature attributes
+    enum Attribute { TimestampAttr=0, UserAttr=1, TagAttr, CustomTagAttr };
 
-class QgsOSMDataProvider: public QgsVectorDataProvider
-{
-  Q_OBJECT
+    //! supported feature attributes
+    static const char* attr[];
 
+    //! constant that helps to set default map extent
+    const static int DEFAULT_EXTENT=100;
+
+    //! absolute name of input OSM file
+    QString mFileName;
+
+    //! determines if this provider is in valid state (initialized correctly, etc.)
+    bool mValid;
+
+    //! holds information on error that occured in provider execution
+    char *mError;
+
+    //! object that receives notifications from init
+    QObject* mInitObserver;
+
+    //! boundary of all OSM data that provider manages
+    double xMin, xMax, yMin, yMax;
+
+    //! list of feature tags for which feature attributes are created
+    QStringList mCustomTagsList;
+
+    //! name of file with renderer style information
+    QString mStyleFileName;
+
+    //! determines style for rendering: one of "medium", "big", "small"
+    QString mStyle;
+
+    // sqlite3 database stuff:
+
+    //! absolute name of local database file with OSM data
+    QString mDatabaseFileName;
+
+    //! pointer to sqlite3 database that keeps OSM data
+    sqlite3 *mDatabase;
+
+    //! pointer to main sqlite3 database statement object; this statement serves to select OSM data
+    sqlite3_stmt *mDatabaseStmt;
+
+    //! sqlite3 database statement ready to select all feature tags
+    sqlite3_stmt *mTagsStmt;
+
+    //! sqlite3 database statement ready to select concrete feature tag
+    sqlite3_stmt *mCustomTagsStmt;
+
+    //! sqlite3 database statement for exact way selection
+    sqlite3_stmt *mWayStmt;
+
+    //! sqlite3 database statement for exact node selection
+    sqlite3_stmt *mNodeStmt;
+
+    // variables used to select OSM data; used mainly in select(), nextFeature() functions:
+
+    //! list of supported attribute fields
+    QgsFieldMap mAttributeFields;
+
+    //! which attributes should be fetched after calling of select() function
+    QgsAttributeList mAttributesToFetch;
+
+    //! features from which area should be fetched after calling of select() function?
+    QgsRectangle mSelectionRectangle;
+
+    //! geometry object of area from which features should be fetched after calling of select() function
+    QgsGeometry* mSelectionRectangleGeom;
+
+    //! determines if intersect should be used while selecting OSM data
+    bool mSelectUseIntersect;
+
+
+
   public:
 
     /**
-     * Constructor of the vector provider.
-     * @param uri  uniform resource locator (URI) for a dataset
+     * Constructor of vector provider.
+     * @param uri uniform resource locator (URI) for a dataset
      */
     QgsOSMDataProvider( QString uri );
 
@@ -43,7 +116,7 @@
     virtual ~QgsOSMDataProvider();
 
 
-    // Implementation of functions from QgsVectorDataProvider
+    // Implementation of QgsVectorDataProvider functions
 
     /**
      * Returns the permanent storage type for this layer as a friendly name.
@@ -126,7 +199,7 @@
     virtual int capabilities() const;
 
 
-    // Implementation of functions from QgsDataProvider
+    // Implementation of QgsDataProvider functions
 
     /**
      * Returns a provider name.
@@ -155,88 +228,56 @@
 
 
   private:
-    enum { PointType, LineType, PolygonType } mFeatureType;
-    enum Attribute { TimestampAttr = 0, UserAttr = 1, TagAttr, CustomTagAttr };
-    const static int DEFAULT_EXTENT = 100;
+    /**
+     * Finds out if database (provider is connected to) belongs to (was created from) specified input file.
+     * @param mFileName name of input OSM file
+     * @return answer to that question
+     */
+    bool isDatabaseCompatibleWithInput(QString mFileName);
 
-    static const char* attr[];
-
-    QString mFileName;
-    QString mDatabaseFileName;
-    QDateTime mOsmFileLastModif;
-    bool mValid;
-
-    sqlite3 *mDatabase;
-    sqlite3_stmt *mDatabaseStmt;
-
-    char *mError;
-
-    //! object that receives notifications from init
-    QObject* mInitObserver;
-
-    double xMin, xMax, yMin, yMax;   // boundary
-
-    // selection
-    QgsAttributeList mAttributesToFetch;
-    QgsFieldMap mAttributeFields;
-    QgsRectangle mSelectionRectangle;
-    QgsGeometry* mSelectionRectangleGeom;
-
-    // flags
-    bool mSelectUseIntersect;
-
-    // private methods
-    sqlite3_stmt *mTagsStmt;
-    bool mTagsRetrieval;
-    QString tagsForObject( const char* type, int id );
-
-    sqlite3_stmt *mCustomTagsStmt;
-    QStringList mCustomTagsList;
-    QString tagForObject( const char* type, int id, QString tagKey );
-
-    sqlite3_stmt *mWayStmt;
-    sqlite3_stmt *mNodeStmt;
-
-    QString mStyleFileName;
-    QString mStyle;
-
-    // manipulation with sqlite database
-
-    bool isDatabaseCompatibleWithInput( QString mFileName );
+    /**
+     * Finds out if database and provider versions are compatible.
+     * @return answer to that question
+     */
     bool isDatabaseCompatibleWithPlugin();
 
     /**
-     * Create Open Street Map database schema, using c++ library for attempt to sqlite database.
+     * Creates Open Street Map database schema, using c++ library for attempt to sqlite database.
      * @return true in case of success and false in case of failure
      */
     bool createDatabaseSchema();
 
     /**
-     * Create indexes for OSM database schema, using c++ library for attempt to sqlite database.
+     * Creates indexes for OSM database schema, using c++ library for attempt to sqlite database.
      * @return true in case of success and false in case of failure
      */
     bool createIndexes();
+
+    /**
+     * Creates triggers for OSM database schema, using c++ library for attempt to sqlite database.
+     * @return true in case of success and false in case of failure
+     */
     bool createTriggers();
 
     /**
-     * Drop the whole OSM database schema, using c++ library for attempt to sqlite database.
+     * Drops the whole OSM database schema, using c++ library for attempt to sqlite database.
      * @return true in case of success and false in case of failure
      */
     bool dropDatabaseSchema();
 
     /**
-     * Open sqlite3 database.
+     * Opens sqlite3 database.
      * @return true in case of success and false in case of failure
      */
     bool openDatabase();
 
     /**
-     * Close opened sqlite3 database.
+     * Closes opened sqlite3 database.
      */
     bool closeDatabase();
 
     /**
-     * Process Open Street Map file, parse it and store data in sqlite database.
+     * Processes Open Street Map file, parse it and store data in sqlite database.
      * Function doesn't require much memory: uses simple SAX XML parser
      * and stores data directly to database while processing OSM file.
      * @param osm_filename name of file with OSM data to parse into sqlite3 database
@@ -244,8 +285,25 @@
      */
     bool loadOsmFile( QString osm_filename );
 
+    /**
+     * Function computes WKB (well-known-binary) information on geometry of specified way
+     * and store it into database. Later this enables faster displaying of features.
+     * @param wayId way identifier
+     * @param isClosed is this way closed? closed=polygon X notClosed=line
+     * @param geo output; way geometry in wkb format
+     * @param geolen output; len of wkb geometry
+     */
     bool updateWayWKB( int wayId, int isClosed, char **geo, int *geolen );
+
+    /**
+     * Function performs all necessary postparsing manipulations with node records.
+     */
     bool updateNodes();
+
+    /**
+     * Function removes all ways that are not correct. This is called after parsing input file is completed.
+     * The main purpose is removing ways that contain nodes that are not included in loaded data.
+     */
     bool removeIncorrectWays();
 
 
@@ -261,9 +319,12 @@
     bool splitNodes();
 
     /**
-     * This function is postprocess after osm file parsing. Parsing stored all information into database, but
-     * such database schema is not optimal e.g. for way selection, that is called very often. It should be better
-     * to have way members (with their coordinates) store directly in way table - in WKB (well known binary) format
+     * This function performs postprocessing after OSM file parsing.
+     *
+     * Parsing has stored all information into database, but such database schema is not optimal e.g. for way selection,
+     * that must be done very often. It should be better to have way members (with their coordinates) stored directly
+     * in way table - in WKB (well known binary) format. Also some other redundant/cached information can be useful.
+     *
      * @return true in case of success and false in case of failure
      */
     bool postparsing();
@@ -276,30 +337,47 @@
     int freeFeatureId();
 
     /**
-     * Get number of members of specified way.
+     * Gets number of members of specified way.
      * @param wayId way identifier
      * @return number of way members
      */
     int wayMemberCount( int wayId );
 
-    int relationMemberCount( int relId );
-
-    // fetch node from current statement
+    /**
+     * Function fetches one node from current sqlite3 statement.
+     * @param feature output; feature representing fetched node
+     * @param stmt database statement to fetch node from
+     * @param fetchGeometry determines if node geometry should be fetched also
+     * @param fetchAttrs list of attributes to be fetched with node
+     * @return success of failure flag (true/false)
+     */
     bool fetchNode( QgsFeature& feature, sqlite3_stmt* stmt, bool fetchGeometry, QgsAttributeList& fetchAttrs );
 
-    // fetch way from current statement
+    /**
+     * Function fetches one way from current sqlite3 statement.
+     * @param feature output; feature representing fetched way
+     * @param stmt database statement to fetch way from
+     * @param fetchGeometry determines if way geometry should be fetched also
+     * @param fetchAttrs list of attributes to be fetched with way
+     * @return success of failure flag (true/false)
+     */
     bool fetchWay( QgsFeature& feature, sqlite3_stmt* stmt, bool fetchGeometry, QgsAttributeList& fetchAttrs );
 
-    // Change geometry of one feature (used by changeGeometryValues())
-    bool changeGeometryValue( const int & featid, QgsGeometry & geom );
+    /**
+     * Function returns string of concatenated tags of specified feature.
+     * @param type type of feature (one of "node","way","relation")
+     * @param id feature identifier
+     * @return string of tags concatenation
+     */
+    QString tagsForObject(const char* type, int id);
 
-    struct wkbPoint
-    {
-      char byteOrder;
-      unsigned wkbType;
-      double x;
-      double y;
-    };
-    wkbPoint mWKBpt;
+    /**
+     * Function returns one tag value of specified feature and specified key.
+     * @param type type of feature (one of "node","way","relation")
+     * @param id feature identifier
+     * @param tagKey tag key
+     * @return tag value
+     */
+    QString tagForObject(const char* type, int id, QString tagKey);
 };
 



More information about the QGIS-commit mailing list