[QGIS Commit] r13929 - in branches/threading-branch/src: core
plugins/grass providers/grass
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sun Jul 18 08:03:00 EDT 2010
Author: wonder
Date: 2010-07-18 12:03:00 +0000 (Sun, 18 Jul 2010)
New Revision: 13929
Added:
branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp
branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h
Modified:
branches/threading-branch/src/core/qgsvectordataprovider.cpp
branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp
branches/threading-branch/src/providers/grass/CMakeLists.txt
branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp
branches/threading-branch/src/providers/grass/qgsgrassprovider.h
Log:
Adapted GRASS provider for the new read API.
Modified: branches/threading-branch/src/core/qgsvectordataprovider.cpp
===================================================================
--- branches/threading-branch/src/core/qgsvectordataprovider.cpp 2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/core/qgsvectordataprovider.cpp 2010-07-18 12:03:00 UTC (rev 13929)
@@ -167,9 +167,9 @@
bool fetchGeometry,
QgsAttributeList fetchAttributes )
{
- select( fetchAttributes, QgsRectangle(), fetchGeometry );
+ QgsFeatureIterator fi = getFeatures( fetchAttributes, QgsRectangle(), fetchGeometry );
- while ( nextFeature( feature ) )
+ while ( fi.nextFeature( feature ) )
{
if ( feature.id() == featureId )
return true;
Modified: branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp
===================================================================
--- branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp 2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/plugins/grass/qgsgrassedittools.cpp 2010-07-18 12:03:00 UTC (rev 13929)
@@ -18,6 +18,7 @@
#include "qgsgrassattributes.h"
#include "qgsgrassedit.h"
#include "qgsgrassprovider.h"
+#include "qgsvectorlayer.h"
#include "qgisinterface.h"
#include "qgslogger.h"
Modified: branches/threading-branch/src/providers/grass/CMakeLists.txt
===================================================================
--- branches/threading-branch/src/providers/grass/CMakeLists.txt 2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/providers/grass/CMakeLists.txt 2010-07-18 12:03:00 UTC (rev 13929)
@@ -7,7 +7,7 @@
SET(GRASS_RASTER_PROVIDER_SRCS qgsgrassrasterprovider.cpp)
-SET(GRASS_LIB_SRCS qgsgrassprovider.cpp qgsgrass.cpp)
+SET(GRASS_LIB_SRCS qgsgrassprovider.cpp qgsgrass.cpp qgsgrassfeatureiterator.cpp)
SET(QGIS_D_RAST_SRCS qgis.d.rast.c)
Added: branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp (rev 0)
+++ branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.cpp 2010-07-18 12:03:00 UTC (rev 13929)
@@ -0,0 +1,358 @@
+#include "qgsgrassfeatureiterator.h"
+
+#include "qgsgrassprovider.h"
+#include "qgsapplication.h"
+#include "qgslogger.h"
+
+extern "C"
+{
+#include <grass/Vect.h>
+}
+
+// from provider:
+// - isEdited(), isFrozen()
+// - mLayers, mLayerId, mLayerType
+// - mapOutdated(), updateMap(), update()
+// - mMapVersion, mMaps, mMap
+// - attributesOutdated(), loadAttributes()
+
+QgsGrassFeatureIterator::QgsGrassFeatureIterator( QgsGrassProvider* p,
+ QgsAttributeList fetchAttributes,
+ QgsRectangle rect,
+ bool fetchGeometry,
+ bool useIntersect )
+: QgsVectorDataProviderIterator( fetchAttributes, rect, fetchGeometry, useIntersect ),
+ P(p)
+{
+
+ if ( P->isEdited() || P->isFrozen() || !P->mValid )
+ {
+ mClosed = true;
+ return;
+ }
+
+ P->mMapMutex.lock();
+
+ // Init structures
+ mPoints = Vect_new_line_struct();
+ mCats = Vect_new_cats_struct();
+ mList = Vect_new_list();
+
+ // check if outdated and update if necessary
+ int mapId = P->mLayers[P->mLayerId].mapId;
+ if ( P->mapOutdated( mapId ) )
+ {
+ P->updateMap( mapId );
+ }
+ if ( P->mMapVersion < P->mMaps[mapId].version )
+ {
+ P->update();
+ }
+ if ( P->attributesOutdated( mapId ) )
+ {
+ P->loadAttributes( P->mLayers[P->mLayerId] );
+ }
+
+ mNextCidx = 0;
+
+ // Create selection array
+ allocateSelection();
+
+ //no selection rectangle - use all features
+ if ( rect.isEmpty() )
+ {
+ resetSelection( 1 );
+ return;
+ }
+
+ //apply selection rectangle
+ resetSelection( 0 );
+
+ if ( !useIntersect )
+ { // select by bounding boxes only
+ BOUND_BOX box;
+ box.N = rect.yMaximum(); box.S = rect.yMinimum();
+ box.E = rect.xMaximum(); box.W = rect.xMinimum();
+ box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX;
+ if ( P->mLayerType == QgsGrassProvider::POINT ||
+ P->mLayerType == QgsGrassProvider::CENTROID ||
+ P->mLayerType == QgsGrassProvider::LINE ||
+ P->mLayerType == QgsGrassProvider::BOUNDARY )
+ {
+ Vect_select_lines_by_box( P->mMap, &box, P->mGrassType, mList );
+ }
+ else if ( P->mLayerType == QgsGrassProvider::POLYGON )
+ {
+ Vect_select_areas_by_box( P->mMap, &box, mList );
+ }
+
+ }
+ else
+ { // check intersection
+ struct line_pnts *Polygon;
+
+ Polygon = Vect_new_line_struct();
+
+ // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
+ // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon
+ // should clarify better how 2D/3D is treated
+ Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX );
+ Vect_append_point( Polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX );
+ Vect_append_point( Polygon, rect.xMaximum(), rect.yMaximum(), 0 );
+ Vect_append_point( Polygon, rect.xMinimum(), rect.yMaximum(), 0 );
+ Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), 0 );
+
+ if ( P->mLayerType == QgsGrassProvider::POINT ||
+ P->mLayerType == QgsGrassProvider::CENTROID ||
+ P->mLayerType == QgsGrassProvider::LINE ||
+ P->mLayerType == QgsGrassProvider::BOUNDARY )
+ {
+ Vect_select_lines_by_polygon( P->mMap, Polygon, 0, NULL, P->mGrassType, mList );
+ }
+ else if ( P->mLayerType == QgsGrassProvider::POLYGON )
+ {
+ Vect_select_areas_by_polygon( P->mMap, Polygon, 0, NULL, mList );
+ }
+
+ Vect_destroy_line_struct( Polygon );
+ }
+
+ for ( int i = 0; i < mList->n_values; i++ )
+ {
+ if ( mList->value[i] <= mSelectionSize )
+ {
+ mSelection[mList->value[i]] = 1;
+ }
+ else
+ {
+ QgsDebugMsg( "Selected element out of range" );
+ }
+ }
+
+}
+
+void QgsGrassFeatureIterator::allocateSelection()
+{
+ //int size;
+ QgsDebugMsg( "entered." );
+
+ int nlines = Vect_get_num_lines( P->mMap );
+ int nareas = Vect_get_num_areas( P->mMap );
+
+ if ( nlines > nareas )
+ {
+ mSelectionSize = nlines + 1;
+ }
+ else
+ {
+ mSelectionSize = nareas + 1;
+ }
+ QgsDebugMsg( QString( "nlines = %1 nareas = %2 size = %3" ).arg( nlines ).arg( nareas ).arg( mSelectionSize ) );
+
+ mSelection = ( char * ) malloc( mSelectionSize );
+}
+
+
+void QgsGrassFeatureIterator::resetSelection( bool sel )
+{
+ QgsDebugMsg( "entered." );
+ if ( !P->mValid ) return;
+ memset( mSelection, ( int ) sel, mSelectionSize );
+ mNextCidx = 0;
+}
+
+
+
+QgsGrassFeatureIterator::~QgsGrassFeatureIterator()
+{
+ close();
+}
+
+bool QgsGrassFeatureIterator::nextFeature(QgsFeature& feature)
+{
+ if (mClosed)
+ return false;
+
+ feature.setValid( false );
+ int cat = -1, type = -1, id = -1;
+ unsigned char *wkb;
+ int wkbsize;
+
+ QgsDebugMsgLevel( "entered.", 3 );
+
+ if ( P->isEdited() || P->isFrozen() || !P->mValid )
+ return false;
+
+ if ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats )
+ return false; // No features, no features in this layer
+
+ // Get next line/area id
+ int found = 0;
+ while ( mNextCidx < P->mCidxFieldNumCats )
+ {
+ Vect_cidx_get_cat_by_index( P->mMap, P->mCidxFieldIndex, mNextCidx++, &cat, &type, &id );
+ // Warning: selection array is only of type line/area of current layer -> check type first
+
+ if ( !( type & P->mGrassType ) )
+ continue;
+
+ if ( !mSelection[id] )
+ continue;
+
+ found = 1;
+ break;
+ }
+
+ if ( !found )
+ return false; // No more features
+
+#if QGISDEBUG > 3
+ QgsDebugMsg( QString( "cat = %1 type = %2 id = %3" ).arg( cat ).arg( type ).arg( id ) );
+#endif
+
+ feature.setFeatureId( id );
+ feature.clearAttributeMap();
+
+ // TODO int may be 64 bits (memcpy)
+ if ( type & ( GV_POINTS | GV_LINES ) ) /* points or lines */
+ {
+ Vect_read_line( P->mMap, mPoints, mCats, id );
+ int npoints = mPoints->n_points;
+
+ if ( type & GV_POINTS )
+ {
+ wkbsize = 1 + 4 + 2 * 8;
+ }
+ else // GV_LINES
+ {
+ wkbsize = 1 + 4 + 4 + npoints * 2 * 8;
+ }
+ wkb = new unsigned char[wkbsize];
+ unsigned char *wkbp = wkb;
+ wkbp[0] = ( unsigned char ) QgsApplication::endian();
+ wkbp += 1;
+
+ /* WKB type */
+ memcpy( wkbp, &P->mQgisType, 4 );
+ wkbp += 4;
+
+ /* number of points */
+ if ( type & GV_LINES )
+ {
+ memcpy( wkbp, &npoints, 4 );
+ wkbp += 4;
+ }
+
+ for ( int i = 0; i < npoints; i++ )
+ {
+ memcpy( wkbp, &( mPoints->x[i] ), 8 );
+ memcpy( wkbp + 8, &( mPoints->y[i] ), 8 );
+ wkbp += 16;
+ }
+ }
+ else // GV_AREA
+ {
+ Vect_get_area_points( P->mMap, id, mPoints );
+ int npoints = mPoints->n_points;
+
+ wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8; // size without islands
+ wkb = new unsigned char[wkbsize];
+ wkb[0] = ( unsigned char ) QgsApplication::endian();
+ int offset = 1;
+
+ /* WKB type */
+ memcpy( wkb + offset, &P->mQgisType, 4 );
+ offset += 4;
+
+ /* Number of rings */
+ int nisles = Vect_get_area_num_isles( P->mMap, id );
+ int nrings = 1 + nisles;
+ memcpy( wkb + offset, &nrings, 4 );
+ offset += 4;
+
+ /* Outer ring */
+ memcpy( wkb + offset, &npoints, 4 );
+ offset += 4;
+ for ( int i = 0; i < npoints; i++ )
+ {
+ memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
+ memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
+ offset += 16;
+ }
+
+ /* Isles */
+ for ( int i = 0; i < nisles; i++ )
+ {
+ Vect_get_isle_points( P->mMap, Vect_get_area_isle( P->mMap, id, i ), mPoints );
+ npoints = mPoints->n_points;
+
+ // add space
+ wkbsize += 4 + npoints * 2 * 8;
+ wkb = ( unsigned char * ) realloc( wkb, wkbsize );
+
+ memcpy( wkb + offset, &npoints, 4 );
+ offset += 4;
+ for ( int i = 0; i < npoints; i++ )
+ {
+ memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
+ memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
+ offset += 16;
+ }
+ }
+ }
+
+ feature.setGeometryAndOwnership( wkb, wkbsize );
+
+ P->setFeatureAttributes( P->mLayerId, cat, &feature, mFetchAttributes );
+
+ feature.setValid( true );
+
+ return true;
+}
+
+bool QgsGrassFeatureIterator::rewind()
+{
+ if (mClosed)
+ return false;
+
+ if ( P->isEdited() || P->isFrozen() || !P->mValid )
+ return false;
+
+ int mapId = P->mLayers[P->mLayerId].mapId;
+ if ( P->mapOutdated( mapId ) )
+ {
+ P->updateMap( mapId );
+ }
+ if ( P->mMapVersion < P->mMaps[mapId].version )
+ {
+ P->update();
+
+ // Create selection array
+ free(mSelection);
+ allocateSelection();
+
+ }
+ if ( P->attributesOutdated( mapId ) )
+ {
+ P->loadAttributes( P->mLayers[P->mLayerId] );
+ }
+
+ mNextCidx = 0;
+ return true;
+}
+
+bool QgsGrassFeatureIterator::close()
+{
+ if (mClosed)
+ return false;
+
+ // finalization
+ Vect_destroy_line_struct( mPoints );
+ Vect_destroy_cats_struct( mCats );
+ Vect_destroy_list( mList );
+
+ P->mMapMutex.unlock();
+
+ mClosed = true;
+ return true;
+}
Added: branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h (rev 0)
+++ branches/threading-branch/src/providers/grass/qgsgrassfeatureiterator.h 2010-07-18 12:03:00 UTC (rev 13929)
@@ -0,0 +1,59 @@
+#ifndef QGSGRASSFEATUREITERATOR_H
+#define QGSGRASSFEATUREITERATOR_H
+
+#include "qgsvectordataprovider.h"
+
+class QgsGrassProvider;
+
+struct ilist;
+
+class QgsGrassFeatureIterator : public QgsVectorDataProviderIterator
+{
+public:
+ QgsGrassFeatureIterator( QgsGrassProvider* p,
+ QgsAttributeList fetchAttributes,
+ QgsRectangle rect,
+ bool fetchGeometry,
+ bool useIntersect );
+
+ ~QgsGrassFeatureIterator();
+
+ //! fetch next feature, return true on success
+ virtual bool nextFeature(QgsFeature& f);
+
+ //! reset the iterator to the starting position
+ virtual bool rewind();
+
+ //! end of iterating: free the resources / lock
+ virtual bool close();
+
+protected:
+ QgsGrassProvider* P;
+
+ struct ilist *mList;
+ struct line_pnts *mPoints; // points structure
+ struct line_cats *mCats; // cats structure
+
+ int mNextCidx; // !UPDATE! Next index in cidxFieldIndex to be read, used to find nextFeature
+
+ // selection: array of size nlines or nareas + 1, set to 1 - selected or 0 - not selected, 2 - read
+ // Code 2 means that the line was already read in this cycle, all 2 must be reset to 1
+ // if getFirstFeature() or select() is calles.
+ // Distinction between 1 and 2 is used if attribute table exists, in that case attributes are
+ // read from the table and geometry is append and selection set to 2.
+ // In the end the selection array is scanned for 1 (attributes missing), and the geometry
+ // is returned without attributes
+ char *mSelection; // !UPDATE!
+ int mSelectionSize; // !UPDATE! Size of selection array
+
+ /*! Allocate sellection array for given map id. The array is large enough for lines or areas
+ * (bigger from num lines and num areas)
+ * Possible old selection array is not released.
+ */
+ void allocateSelection();
+
+ void resetSelection( bool sel ); // reset selection
+
+};
+
+#endif // QGSGRASSFEATUREITERATOR_H
Modified: branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp 2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/providers/grass/qgsgrassprovider.cpp 2010-07-18 12:03:00 UTC (rev 13929)
@@ -17,6 +17,7 @@
#include "qgsgrassprovider.h"
#include "qgsgrass.h"
+#include "qgsgrassfeatureiterator.h"
#include "qgsapplication.h"
#include "qgscoordinatereferencesystem.h"
@@ -191,22 +192,11 @@
mNumberFeatures = 0;
mCidxFieldNumCats = 0;
}
- mNextCidx = 0;
QgsDebugMsg( QString( "mNumberFeatures = %1 mCidxFieldIndex = %2 mCidxFieldNumCats = %3" ).arg( mNumberFeatures ).arg( mCidxFieldIndex ).arg( mCidxFieldNumCats ) );
-
- // Create selection array
- mSelectionSize = allocateSelection( mMap, &mSelection );
- resetSelection( 1 ); // TODO ? - where what reset
-
mMapVersion = mMaps[mLayers[mLayerId].mapId].version;
- // Init structures
- mPoints = Vect_new_line_struct();
- mCats = Vect_new_cats_struct();
- mList = Vect_new_list();
-
mValid = true;
QgsDebugMsg( QString( "New GRASS layer opened, time (ms): %1" ).arg( time.elapsed() ) );
@@ -240,43 +230,14 @@
mNumberFeatures = 0;
mCidxFieldNumCats = 0;
}
- mNextCidx = 0;
QgsDebugMsg( QString( "mNumberFeatures = %1 mCidxFieldIndex = %2 mCidxFieldNumCats = %3" ).arg( mNumberFeatures ).arg( mCidxFieldIndex ).arg( mCidxFieldNumCats ) );
- // Create selection array
- if ( mSelection ) free( mSelection );
- mSelectionSize = allocateSelection( mMap, &mSelection );
- resetSelection( 1 );
-
mMapVersion = mMaps[mLayers[mLayerId].mapId].version;
mValid = true;
}
-int QgsGrassProvider::allocateSelection( struct Map_info *map, char **selection )
-{
- int size;
- QgsDebugMsg( "entered." );
-
- int nlines = Vect_get_num_lines( map );
- int nareas = Vect_get_num_areas( map );
-
- if ( nlines > nareas )
- {
- size = nlines + 1;
- }
- else
- {
- size = nareas + 1;
- }
- QgsDebugMsg( QString( "nlines = %1 nareas = %2 size = %3" ).arg( nlines ).arg( nareas ).arg( size ) );
-
- *selection = ( char * ) malloc( size );
-
- return size;
-}
-
QgsGrassProvider::~QgsGrassProvider()
{
QgsDebugMsg( "entered." );
@@ -289,244 +250,40 @@
return "GRASS (Geographic Resources Analysis and Support System) file";
}
-bool QgsGrassProvider::nextFeature( QgsFeature& feature )
+QgsFeatureIterator QgsGrassProvider::getFeatures( QgsAttributeList fetchAttributes,
+ QgsRectangle rect,
+ bool fetchGeometry,
+ bool useIntersect )
{
- feature.setValid( false );
- int cat = -1, type = -1, id = -1;
- unsigned char *wkb;
- int wkbsize;
-
- QgsDebugMsgLevel( "entered.", 3 );
-
- if ( isEdited() || isFrozen() || !mValid )
- return false;
-
- if ( mCidxFieldIndex < 0 || mNextCidx >= mCidxFieldNumCats )
- return false; // No features, no features in this layer
-
- // Get next line/area id
- int found = 0;
- while ( mNextCidx < mCidxFieldNumCats )
- {
- Vect_cidx_get_cat_by_index( mMap, mCidxFieldIndex, mNextCidx++, &cat, &type, &id );
- // Warning: selection array is only of type line/area of current layer -> check type first
-
- if ( !( type & mGrassType ) )
- continue;
-
- if ( !mSelection[id] )
- continue;
-
- found = 1;
- break;
- }
- if ( !found )
- return false; // No more features
-#if QGISDEBUG > 3
- QgsDebugMsg( QString( "cat = %1 type = %2 id = %3" ).arg( cat ).arg( type ).arg( id ) );
-#endif
-
- feature.setFeatureId( id );
- feature.clearAttributeMap();
-
- // TODO int may be 64 bits (memcpy)
- if ( type & ( GV_POINTS | GV_LINES ) ) /* points or lines */
- {
- Vect_read_line( mMap, mPoints, mCats, id );
- int npoints = mPoints->n_points;
-
- if ( type & GV_POINTS )
- {
- wkbsize = 1 + 4 + 2 * 8;
- }
- else // GV_LINES
- {
- wkbsize = 1 + 4 + 4 + npoints * 2 * 8;
- }
- wkb = new unsigned char[wkbsize];
- unsigned char *wkbp = wkb;
- wkbp[0] = ( unsigned char ) QgsApplication::endian();
- wkbp += 1;
-
- /* WKB type */
- memcpy( wkbp, &mQgisType, 4 );
- wkbp += 4;
-
- /* number of points */
- if ( type & GV_LINES )
- {
- memcpy( wkbp, &npoints, 4 );
- wkbp += 4;
- }
-
- for ( int i = 0; i < npoints; i++ )
- {
- memcpy( wkbp, &( mPoints->x[i] ), 8 );
- memcpy( wkbp + 8, &( mPoints->y[i] ), 8 );
- wkbp += 16;
- }
- }
- else // GV_AREA
- {
- Vect_get_area_points( mMap, id, mPoints );
- int npoints = mPoints->n_points;
-
- wkbsize = 1 + 4 + 4 + 4 + npoints * 2 * 8; // size without islands
- wkb = new unsigned char[wkbsize];
- wkb[0] = ( unsigned char ) QgsApplication::endian();
- int offset = 1;
-
- /* WKB type */
- memcpy( wkb + offset, &mQgisType, 4 );
- offset += 4;
-
- /* Number of rings */
- int nisles = Vect_get_area_num_isles( mMap, id );
- int nrings = 1 + nisles;
- memcpy( wkb + offset, &nrings, 4 );
- offset += 4;
-
- /* Outer ring */
- memcpy( wkb + offset, &npoints, 4 );
- offset += 4;
- for ( int i = 0; i < npoints; i++ )
- {
- memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
- memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
- offset += 16;
- }
-
- /* Isles */
- for ( int i = 0; i < nisles; i++ )
- {
- Vect_get_isle_points( mMap, Vect_get_area_isle( mMap, id, i ), mPoints );
- npoints = mPoints->n_points;
-
- // add space
- wkbsize += 4 + npoints * 2 * 8;
- wkb = ( unsigned char * ) realloc( wkb, wkbsize );
-
- memcpy( wkb + offset, &npoints, 4 );
- offset += 4;
- for ( int i = 0; i < npoints; i++ )
- {
- memcpy( wkb + offset, &( mPoints->x[i] ), 8 );
- memcpy( wkb + offset + 8, &( mPoints->y[i] ), 8 );
- offset += 16;
- }
- }
- }
-
- feature.setGeometryAndOwnership( wkb, wkbsize );
-
- setFeatureAttributes( mLayerId, cat, &feature, mAttributesToFetch );
-
- feature.setValid( true );
-
- return true;
+ return QgsFeatureIterator( new QgsGrassFeatureIterator(this, fetchAttributes, rect, fetchGeometry, useIntersect) );
}
-void QgsGrassProvider::resetSelection( bool sel )
-{
- QgsDebugMsg( "entered." );
- if ( !mValid ) return;
- memset( mSelection, ( int ) sel, mSelectionSize );
- mNextCidx = 0;
-}
-
void QgsGrassProvider::select( QgsAttributeList fetchAttributes,
QgsRectangle rect,
bool fetchGeometry,
bool useIntersect )
{
- mAttributesToFetch = fetchAttributes;
- mFetchGeom = fetchGeometry;
+ mOldApiIter = getFeatures( fetchAttributes, rect, fetchGeometry, useIntersect );
+}
- if ( isEdited() || isFrozen() || !mValid )
- return;
-
- // check if outdated and update if necessary
- int mapId = mLayers[mLayerId].mapId;
- if ( mapOutdated( mapId ) )
- {
- updateMap( mapId );
- }
- if ( mMapVersion < mMaps[mapId].version )
- {
- update();
- }
- if ( attributesOutdated( mapId ) )
- {
- loadAttributes( mLayers[mLayerId] );
- }
-
- //no selection rectangle - use all features
- if ( rect.isEmpty() )
- {
- resetSelection( 1 );
- return;
- }
-
- //apply selection rectangle
- resetSelection( 0 );
-
- if ( !useIntersect )
- { // select by bounding boxes only
- BOUND_BOX box;
- box.N = rect.yMaximum(); box.S = rect.yMinimum();
- box.E = rect.xMaximum(); box.W = rect.xMinimum();
- box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX;
- if ( mLayerType == POINT || mLayerType == CENTROID || mLayerType == LINE || mLayerType == BOUNDARY )
- {
- Vect_select_lines_by_box( mMap, &box, mGrassType, mList );
- }
- else if ( mLayerType == POLYGON )
- {
- Vect_select_areas_by_box( mMap, &box, mList );
- }
-
- }
+bool QgsGrassProvider::nextFeature( QgsFeature& feature )
+{
+ if (mOldApiIter.nextFeature(feature))
+ return true;
else
- { // check intersection
- struct line_pnts *Polygon;
-
- Polygon = Vect_new_line_struct();
-
- // Using z coor -PORT_DOUBLE_MAX/PORT_DOUBLE_MAX we cover 3D, Vect_select_lines_by_polygon is
- // using dig_line_box to get the box, it is not perfect, Vect_select_lines_by_polygon
- // should clarify better how 2D/3D is treated
- Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), -PORT_DOUBLE_MAX );
- Vect_append_point( Polygon, rect.xMaximum(), rect.yMinimum(), PORT_DOUBLE_MAX );
- Vect_append_point( Polygon, rect.xMaximum(), rect.yMaximum(), 0 );
- Vect_append_point( Polygon, rect.xMinimum(), rect.yMaximum(), 0 );
- Vect_append_point( Polygon, rect.xMinimum(), rect.yMinimum(), 0 );
-
- if ( mLayerType == POINT || mLayerType == CENTROID || mLayerType == LINE || mLayerType == BOUNDARY )
- {
- Vect_select_lines_by_polygon( mMap, Polygon, 0, NULL, mGrassType, mList );
- }
- else if ( mLayerType == POLYGON )
- {
- Vect_select_areas_by_polygon( mMap, Polygon, 0, NULL, mList );
- }
-
- Vect_destroy_line_struct( Polygon );
- }
- for ( int i = 0; i < mList->n_values; i++ )
{
- if ( mList->value[i] <= mSelectionSize )
- {
- mSelection[mList->value[i]] = 1;
- }
- else
- {
- QgsDebugMsg( "Selected element out of range" );
- }
+ mOldApiIter.close(); // make sure to unlock the layer
+ return false;
}
}
+void QgsGrassProvider::rewind()
+{
+ mOldApiIter.rewind();
+}
+
QgsRectangle QgsGrassProvider::extent()
{
BOUND_BOX box;
@@ -572,28 +329,7 @@
return mLayers[mLayerId].keyColumn;
}
-void QgsGrassProvider::rewind()
-{
- if ( isEdited() || isFrozen() || !mValid )
- return;
- int mapId = mLayers[mLayerId].mapId;
- if ( mapOutdated( mapId ) )
- {
- updateMap( mapId );
- }
- if ( mMapVersion < mMaps[mapId].version )
- {
- update();
- }
- if ( attributesOutdated( mapId ) )
- {
- loadAttributes( mLayers[mLayerId] );
- }
-
- mNextCidx = 0;
-}
-
QVariant QgsGrassProvider::minimumValue( int index )
{
if ( !fields().contains( index ) )
Modified: branches/threading-branch/src/providers/grass/qgsgrassprovider.h
===================================================================
--- branches/threading-branch/src/providers/grass/qgsgrassprovider.h 2010-07-18 11:48:34 UTC (rev 13928)
+++ branches/threading-branch/src/providers/grass/qgsgrassprovider.h 2010-07-18 12:03:00 UTC (rev 13929)
@@ -20,8 +20,11 @@
class QgsField;
#include <QDateTime>
+#include <QMutex>
#include "qgsvectordataprovider.h"
+#include <vector>
+
/* Update.
* Vectors are updated (reloaded) if:
* 1) Vector was find to be outdated on some occasion. Currently the only occasion is the beginning
@@ -145,7 +148,12 @@
*/
virtual bool nextFeature( QgsFeature& feature );
+ virtual QgsFeatureIterator getFeatures( QgsAttributeList fetchAttributes = QgsAttributeList(),
+ QgsRectangle rect = QgsRectangle(),
+ bool fetchGeometry = true,
+ bool useIntersect = false );
+
/**
* Get the feature type as defined in WkbType (qgis.h).
* @return int representing the feature type
@@ -535,28 +543,17 @@
struct Map_info *mMap; // vector header pointer
int mMapVersion; // The version of the map for which the instance was last time updated
- struct line_pnts *mPoints; // points structure
- struct line_cats *mCats; // cats structure
- struct ilist *mList;
int mCidxFieldIndex; // !UPDATE! Index for layerField in category index or -1 if no such field
int mCidxFieldNumCats; // !UPDATE! Number of records in field index
- int mNextCidx; // !UPDATE! Next index in cidxFieldIndex to be read, used to find nextFeature
- // selection: array of size nlines or nareas + 1, set to 1 - selected or 0 - not selected, 2 - read
- // Code 2 means that the line was already read in this cycle, all 2 must be reset to 1
- // if getFirstFeature() or select() is calles.
- // Distinction between 1 and 2 is used if attribute table exists, in that case attributes are
- // read from the table and geometry is append and selection set to 2.
- // In the end the selection array is scanned for 1 (attributes missing), and the geometry
- // is returned without attributes
- char *mSelection; // !UPDATE!
- int mSelectionSize; // !UPDATE! Size of selection array
-
bool mValid; // !UPDATE!
long mNumberFeatures; // !UPDATE!
- void resetSelection( bool sel ); // reset selection
+ QgsFeatureIterator mOldApiIter;
+ friend class QgsGrassFeatureIterator;
+ QMutex mMapMutex;
+
// Reopen map after edit or freeze
bool reopenMap();
@@ -641,15 +638,6 @@
*/
static bool attributesOutdated( int mapId );
- /*! Allocate sellection array for given map id. The array is large enough for lines or areas
- * (bigger from num lines and num areas)
- * Possible old selection array is not released.
- * @param map pointer to map structure
- * @param selection pointer to pointer to char array
- * @return selection size
- */
- static int allocateSelection( struct Map_info *map, char **selection );
-
/*! Get layer map.
* @param layerId
* @return pointer to Map_info structure
More information about the QGIS-commit
mailing list