Skip to content

Commit 80084da

Browse files
author
mhugent
committed
Use str tree spatial index from geos for the wfsprovider
git-svn-id: http://svn.osgeo.org/qgis/trunk@5889 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 4e0db53 commit 80084da

File tree

3 files changed

+54
-36
lines changed

3 files changed

+54
-36
lines changed

src/core/qgsgeometry.cpp

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,9 +2489,6 @@ geos::Geometry* QgsGeometry::geosGeometry() const
24892489
ptr += sizeof(double);
24902490
y = (double *) ptr;
24912491
ptr += sizeof(double);
2492-
#ifdef QGISDEBUG
2493-
qWarning("QgsGeometry::geosGeometry: adding coordinate pair "+QString::number(*x)+"//"+QString::number(*y));
2494-
#endif
24952492
sequence->add(geos::Coordinate(*x,*y));
24962493
}
24972494
return geosGeometryFactory->createLineString(sequence);
@@ -2603,9 +2600,6 @@ geos::Geometry* QgsGeometry::geosGeometry() const
26032600
ptr += sizeof(double);
26042601
y = (double *) ptr;
26052602
ptr += sizeof(double);
2606-
#ifdef QGISDEBUG
2607-
//qWarning("adding coordinate pair "+QString::number(*x)+"//"+QString::number(*y));
2608-
#endif
26092603
sequence->add(geos::Coordinate(*x,*y));
26102604
}
26112605
geos::LinearRing* ring=geosGeometryFactory->createLinearRing(sequence);
@@ -2723,9 +2717,9 @@ bool QgsGeometry::exportGeosToWkb() const
27232717
for (int n = 0; n < numPoints; n++)
27242718
{
27252719
#ifdef QGISDEBUG
2726-
std::cout << "QgsGeometry::exportGeosToWkb: Adding "
2727-
<< sequence->getAt(n).x << ", "
2728-
<< sequence->getAt(n).y << "." << std::endl;
2720+
//std::cout << "QgsGeometry::exportGeosToWkb: Adding "
2721+
// << sequence->getAt(n).x << ", "
2722+
// << sequence->getAt(n).y << "." << std::endl;
27292723
#endif
27302724
// assign x
27312725
memcpy(ptr, &(sequence->getAt(n).x), sizeof(double));

src/providers/wfs/qgswfsprovider.cpp

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,8 @@ static const QString TEXT_PROVIDER_DESCRIPTION = "WFS data provider";
3636
static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs";
3737
static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
3838

39-
QgsWFSProvider::QgsWFSProvider(const QString& uri): QgsVectorDataProvider(uri), mFilter(0), mUseIntersect(false), mSourceSRS(0)
39+
QgsWFSProvider::QgsWFSProvider(const QString& uri): QgsVectorDataProvider(uri), mUseIntersect(false), mSourceSRS(0), mSelectedFeatures(0), mFeatureCount(0)
4040
{
41-
mFeatureIterator = mFeatures.begin();
4241
if(getFeature(uri) == 0)
4342
{
4443
//provider valid
@@ -47,16 +46,20 @@ QgsWFSProvider::QgsWFSProvider(const QString& uri): QgsVectorDataProvider(uri),
4746
{
4847
//provider invalid
4948
}
49+
//set spatial filter to the whole extent
50+
select(&mExtent, false);
5051
}
5152

5253
QgsWFSProvider::~QgsWFSProvider()
5354
{
54-
for(std::vector<QgsFeature*>::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it)
55+
delete mSelectedFeatures;
56+
delete mSourceSRS;
57+
for(std::list<std::pair<geos::Envelope*, QgsFeature*> >::iterator it = mEnvelopesAndFeatures.begin();\
58+
it != mEnvelopesAndFeatures.end(); ++it)
5559
{
56-
delete (*it);
60+
delete it->first;
61+
delete it->second;
5762
}
58-
mFeatures.clear();
59-
delete mFilter;
6063
}
6164

6265
QgsFeature* QgsWFSProvider::getFirstFeature(bool fetchAttributes)
@@ -80,29 +83,29 @@ QgsFeature* QgsWFSProvider::getNextFeature(std::list<int> const & attlist, int f
8083
{
8184
while(true) //go through the loop until we find a feature in the filter
8285
{
83-
if(mFeatureIterator == mFeatures.end())
86+
if(!mSelectedFeatures || mFeatureIterator == mSelectedFeatures->end())
8487
{
8588
return 0;
8689
}
8790

8891
QgsFeature* f = new QgsFeature();
89-
unsigned char* geom = (*mFeatureIterator)->getGeometry();
90-
int geomSize = (*mFeatureIterator)->getGeometrySize();
92+
unsigned char* geom = ((QgsFeature*)(*mFeatureIterator))->getGeometry();
93+
int geomSize = ((QgsFeature*)(*mFeatureIterator))->getGeometrySize();
9194

9295
unsigned char* copiedGeom = new unsigned char[geomSize];
9396
memcpy(copiedGeom, geom, geomSize);
9497
f->setGeometryAndOwnership(copiedGeom, geomSize);
95-
f->setFeatureId((*mFeatureIterator)->featureId());
98+
f->setFeatureId(((QgsFeature*)(*mFeatureIterator))->featureId());
9699

97-
const std::vector<QgsFeatureAttribute> attributes = (*mFeatureIterator)->attributeMap();
100+
const std::vector<QgsFeatureAttribute> attributes = ((QgsFeature*)(*mFeatureIterator))->attributeMap();
98101
for(std::list<int>::const_iterator it = attlist.begin(); it != attlist.end(); ++it)
99102
{
100103
f->addAttribute(attributes[*it].fieldName(), attributes[*it].fieldValue(), attributes[*it].isNumeric());
101104
}
102105
++mFeatureIterator;
103-
if(mFilter && mUseIntersect)
106+
if(mUseIntersect)
104107
{
105-
if(f->geometry()->fast_intersects(mFilter))
108+
if(f->geometry()->fast_intersects(&mSpatialFilter))
106109
{
107110
return f;
108111
}
@@ -130,7 +133,7 @@ int QgsWFSProvider::geometryType() const
130133

131134
long QgsWFSProvider::featureCount() const
132135
{
133-
return mFeatures.size();
136+
return mFeatureCount;
134137
}
135138

136139
int QgsWFSProvider::fieldCount() const
@@ -145,9 +148,13 @@ std::vector<QgsField> const & QgsWFSProvider::fields() const
145148

146149
void QgsWFSProvider::reset()
147150
{
148-
mFeatureIterator = mFeatures.begin();
149-
delete mFilter;
150-
mFilter = 0;
151+
geos::Envelope e(mExtent.xMin(), mExtent.xMax(), mExtent.yMin(), mExtent.yMax());
152+
delete mSelectedFeatures;
153+
mSelectedFeatures = mSpatialIndex.query(&e);
154+
if(mSelectedFeatures)
155+
{
156+
mFeatureIterator = mSelectedFeatures->begin();
157+
}
151158
}
152159

153160
QString QgsWFSProvider::minValue(int position)
@@ -231,9 +238,12 @@ bool QgsWFSProvider::isValid()
231238

232239
void QgsWFSProvider::select(QgsRect *mbr, bool useIntersect)
233240
{
234-
reset();
235-
mFilter = new QgsRect(*mbr);
236241
mUseIntersect = useIntersect;
242+
delete mSelectedFeatures;
243+
mSpatialFilter = *mbr;
244+
geos::Envelope filter(mbr->xMin(), mbr->xMax(), mbr->yMin(), mbr->yMax());
245+
mSelectedFeatures = mSpatialIndex.query(&filter);
246+
mFeatureIterator = mSelectedFeatures->begin();
237247
}
238248

239249
int QgsWFSProvider::getCapabilities(const QString& uri, QgsWFSProvider::REQUEST_ENCODING e, std::list<QString>& typenames, std::list< std::list<QString> >& crs)
@@ -404,7 +414,7 @@ int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAtt
404414

405415
setSRSFromGML2(featureCollectionElement);
406416

407-
if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute, mFeatures) != 0)
417+
if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute) != 0)
408418
{
409419
return 4;
410420
}
@@ -638,7 +648,7 @@ int QgsWFSProvider::setSRSFromGML2(const QDomElement& wfsCollectionElement)
638648
return 0;
639649
}
640650

641-
int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const
651+
int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute)
642652
{
643653
QDomNodeList featureTypeNodeList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember");
644654
QDomElement currentFeatureMemberElem;
@@ -650,6 +660,9 @@ int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement,
650660
unsigned char* wkb = 0;
651661
int wkbSize = 0;
652662
QGis::WKBTYPE currentType;
663+
QgsRect featureBBox;
664+
geos::Envelope* geosBBox;
665+
mFeatureCount = 0;
653666

654667
for(int i = 0; i < featureTypeNodeList.size(); ++i)
655668
{
@@ -679,7 +692,12 @@ int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement,
679692
}
680693
if(wkb && wkbSize > 0)
681694
{
682-
features.push_back(f);
695+
//insert bbox and pointer to feature into search tree
696+
featureBBox = f->boundingBox();
697+
geosBBox = new geos::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax());
698+
mSpatialIndex.insert(geosBBox, (void*)f);
699+
mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, f));
700+
++mFeatureCount;
683701
}
684702
++counter;
685703
}

src/providers/wfs/qgswfsprovider.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgis.h"
2323
#include "qgsrect.h"
2424
#include "qgsvectordataprovider.h"
25+
#include <indexStrtree.h>
2526

2627
class QgsRect;
2728

@@ -86,20 +87,25 @@ class QgsWFSProvider: public QgsVectorDataProvider
8687
/**Bounding box for the layer*/
8788
QgsRect mExtent;
8889
/**Spatial filter for the layer*/
89-
QgsRect* mFilter;
90+
QgsRect mSpatialFilter;
9091
/**Flag if precise intersection test is needed. Otherwise, every feature is returned (even if a filter is set)*/
9192
bool mUseIntersect;
92-
/**Stores all the features*/
93-
std::vector<QgsFeature*> mFeatures;
93+
/**A spatial index for fast access to a feature subset*/
94+
geos::STRtree mSpatialIndex;
95+
/**Stores all the inserted rectangles and features. This is used to clean up the memory in the destructor*/
96+
std::list< std::pair<geos::Envelope*, QgsFeature*> > mEnvelopesAndFeatures;
97+
/**Vector where the QgsFeature* of a query are inserted*/
98+
std::vector<void*>* mSelectedFeatures;
9499
/**Iterator on the feature vector for use in reset(), getNextFeature(), etc...*/
95-
std::vector<QgsFeature*>::iterator mFeatureIterator;
100+
std::vector<void*>::iterator mFeatureIterator;
96101
/**Geometry type of the features in this layer*/
97102
mutable QGis::WKBTYPE mWKBType;
98103
/**Source SRS*/
99104
QgsSpatialRefSys* mSourceSRS;
100105
/**Stores the minimum/maximum values for each attribute
101106
The position in the vector is equal to the position of an attribute in the layers attribute vector*/
102107
std::vector< std::pair<QString, QString> > mMinMaxCash;
108+
int mFeatureCount;
103109

104110
/**Goes through all the features and their attributes and populates mMinMaxCash with entries*/
105111
void fillMinMaxCash();
@@ -123,7 +129,7 @@ class QgsWFSProvider: public QgsVectorDataProvider
123129
//GML2 specific methods
124130
int getExtentFromGML2(QgsRect* extent, const QDomElement& wfsCollectionElement) const;
125131

126-
int getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const;
132+
int getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute);
127133

128134
int getWkbFromGML2(const QDomNode& geometryElement, unsigned char** wkb, int* wkbSize, QGis::WKBTYPE* type) const;
129135
/**Creates WKB from a <Point> element*/

0 commit comments

Comments
 (0)