Skip to content

Commit add929a

Browse files

File tree

5 files changed

+137
-147
lines changed

5 files changed

+137
-147
lines changed
 

‎src/providers/wfs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ QT4_WRAP_CPP(WFS_MOC_SRCS ${WFS_MOC_HDRS})
2222

2323
INCLUDE_DIRECTORIES (
2424
../../core
25+
../../core/spatialindex
2526
${GEOS_INCLUDE_DIR}
2627
${GEOS_INCLUDE_DIR}/geos
2728
${EXPAT_INCLUDE_DIR}

‎src/providers/wfs/qgswfsdata.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,32 @@
1717
#include "qgsspatialrefsys.h"
1818
#include <QBuffer>
1919
#include <QUrl>
20+
#include <QList>
21+
#include <QSet>
2022

2123
//just for a test
2224
//#include <QProgressDialog>
2325

2426
const char NS_SEPARATOR = '?';
2527
const QString GML_NAMESPACE = "http://www.opengis.net/gml";
2628

27-
QgsWFSData::QgsWFSData(const QString& uri, QgsRect* extent, QgsSpatialRefSys* srs, std::list<QgsFeature*>* features, const QString& geometryAttribute, const std::set<QString>& thematicAttributes, QGis::WKBTYPE* wkbType): QObject(), mUri(uri), mExtent(extent), mSrs(srs), mFeatures(features), mGeometryAttribute(geometryAttribute), mThematicAttributes(thematicAttributes), mWkbType(wkbType), mFinished(false), mFeatureCount(0)
29+
QgsWFSData::QgsWFSData(
30+
const QString& uri, QgsRect* extent,
31+
QgsSpatialRefSys* srs,
32+
QList<QgsFeature*> &features,
33+
const QString& geometryAttribute,
34+
const QSet<QString>& thematicAttributes,
35+
QGis::WKBTYPE* wkbType)
36+
: QObject(),
37+
mUri(uri),
38+
mExtent(extent),
39+
mSrs(srs),
40+
mFeatures(features),
41+
mGeometryAttribute(geometryAttribute),
42+
mThematicAttributes(thematicAttributes),
43+
mWkbType(wkbType),
44+
mFinished(false),
45+
mFeatureCount(0)
2846
{
2947
//qWarning("Name of the geometry attribute is:");
3048
//qWarning(mGeometryAttribute.toLocal8Bit().data());
@@ -51,11 +69,6 @@ QgsWFSData::~QgsWFSData()
5169

5270
}
5371

54-
QgsWFSData::QgsWFSData()
55-
{
56-
57-
}
58-
5972
int QgsWFSData::getWFSData()
6073
{
6174
XML_Parser p = XML_ParserCreateNS(NULL, NS_SEPARATOR);
@@ -237,7 +250,7 @@ void QgsWFSData::endElement(const XML_Char* el)
237250
else if(elementName == GML_NAMESPACE + NS_SEPARATOR + "featureMember")
238251
{
239252
mCurrentFeature->setGeometryAndOwnership(mCurrentWKB, mCurrentWKBSize);
240-
mFeatures->push_back(mCurrentFeature);
253+
mFeatures << mCurrentFeature;
241254
++mFeatureCount;
242255
//qWarning("Removing featureMember from stack");
243256
mParseModeStack.pop();

‎src/providers/wfs/qgswfsdata.h

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,14 @@ class QgsWFSData: public QObject
3434
{
3535
Q_OBJECT
3636
public:
37-
QgsWFSData(const QString& uri, QgsRect* extent, QgsSpatialRefSys* srs, std::list<QgsFeature*>* features, const QString& geometryAttribute, const std::set<QString>& thematicAttributes, QGis::WKBTYPE* wkbType);
37+
QgsWFSData(
38+
const QString& uri,
39+
QgsRect* extent,
40+
QgsSpatialRefSys* srs,
41+
QList<QgsFeature*> &features,
42+
const QString& geometryAttribute,
43+
const QSet<QString>& thematicAttributes,
44+
QGis::WKBTYPE* wkbType);
3845
~QgsWFSData();
3946

4047
/**Does the Http GET request to the wfs server
@@ -74,17 +81,17 @@ class QgsWFSData: public QObject
7481
void endElement(const XML_Char* el);
7582
void characters(const XML_Char* chars, int len);
7683
static void start(void* data, const XML_Char* el, const XML_Char** attr)
77-
{
78-
static_cast<QgsWFSData*>(data)->startElement(el, attr);
79-
}
84+
{
85+
static_cast<QgsWFSData*>(data)->startElement(el, attr);
86+
}
8087
static void end(void* data, const XML_Char* el)
81-
{
82-
static_cast<QgsWFSData*>(data)->endElement(el);
83-
}
88+
{
89+
static_cast<QgsWFSData*>(data)->endElement(el);
90+
}
8491
static void chars(void* data, const XML_Char* chars, int len)
85-
{
86-
static_cast<QgsWFSData*>(data)->characters(chars, len);
87-
}
92+
{
93+
static_cast<QgsWFSData*>(data)->characters(chars, len);
94+
}
8895

8996
//helper routines
9097
/**Reads attribute srsName="EPSG:..."
@@ -126,10 +133,10 @@ class QgsWFSData: public QObject
126133
/**Source srs of the layer*/
127134
QgsSpatialRefSys* mSrs;
128135
/**The features of the layer*/
129-
std::list<QgsFeature*>* mFeatures;
136+
QList<QgsFeature*> &mFeatures;
130137
/**Name of geometry attribute*/
131138
QString mGeometryAttribute;
132-
std::set<QString> mThematicAttributes;
139+
const QSet<QString> &mThematicAttributes;
133140
QGis::WKBTYPE* mWkbType;
134141
/**True if the request is finished*/
135142
bool mFinished;

‎src/providers/wfs/qgswfsprovider.cpp

Lines changed: 90 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "qgsspatialrefsys.h"
2424
#include "qgswfsdata.h"
2525
#include "qgswfsprovider.h"
26+
#include "qgsspatialindex.h"
2627
#include "qgslogger.h"
2728
#include <QDomDocument>
2829
#include <QDomNodeList>
@@ -37,8 +38,9 @@ static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs";
3738
static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
3839

3940
QgsWFSProvider::QgsWFSProvider(const QString& uri)
40-
: QgsVectorDataProvider(uri), mUseIntersect(false), mSelectedFeatures(0), mSourceSRS(0), mFeatureCount(0), mValid(true)
41+
: QgsVectorDataProvider(uri), mUseIntersect(false), mSourceSRS(0), mFeatureCount(0), mValid(true)
4142
{
43+
mSpatialIndex = new QgsSpatialIndex;
4244
if(getFeature(uri) == 0)
4345
{
4446
mValid = true;
@@ -54,58 +56,56 @@ QgsWFSProvider::QgsWFSProvider(const QString& uri)
5456

5557
QgsWFSProvider::~QgsWFSProvider()
5658
{
57-
delete mSelectedFeatures;
58-
for(std::list<std::pair<GEOS_GEOM::Envelope*, QgsFeature*> >::iterator it = mEnvelopesAndFeatures.begin();\
59-
it != mEnvelopesAndFeatures.end(); ++it)
60-
{
61-
delete it->first;
62-
delete it->second;
63-
}
59+
mSelectedFeatures.clear();
60+
for(int i=0; i<mFeatures.size(); i++)
61+
delete mFeatures[i];
62+
mFeatures.clear();
63+
delete mSpatialIndex;
6464
}
6565

6666
bool QgsWFSProvider::getNextFeature(QgsFeature& feature)
6767
{
6868
while(true) //go through the loop until we find a feature in the filter
69+
{
70+
if(mSelectedFeatures.size()==0 || mFeatureIterator==mSelectedFeatures.end())
6971
{
70-
if(!mSelectedFeatures || mFeatureIterator == mSelectedFeatures->end())
71-
{
72-
return 0;
73-
}
72+
return 0;
73+
}
7474

75-
feature.setFeatureId(((QgsFeature*)(*mFeatureIterator))->featureId());
76-
if(mFetchGeom)
77-
{
78-
QgsGeometry* geometry = ((QgsFeature*)(*mFeatureIterator))->geometry();
79-
unsigned char* geom = geometry->wkbBuffer();
80-
int geomSize = geometry->wkbSize();
81-
82-
unsigned char* copiedGeom = new unsigned char[geomSize];
83-
memcpy(copiedGeom, geom, geomSize);
84-
feature.setGeometryAndOwnership(copiedGeom, geomSize);
85-
}
86-
87-
const QgsAttributeMap& attributes = ((QgsFeature*)(*mFeatureIterator))->attributeMap();
88-
for(QgsAttributeList::const_iterator it = mAttributesToFetch.begin(); it != mAttributesToFetch.end(); ++it)
89-
{
90-
feature.addAttribute(*it, attributes[*it]);
91-
}
92-
++mFeatureIterator;
93-
if(mUseIntersect)
94-
{
95-
if(feature.geometry()->intersects(mSpatialFilter))
96-
{
97-
return true;
98-
}
99-
else
100-
{
101-
continue; //go for the next feature
102-
}
103-
}
75+
feature.setFeatureId( mFeatures[*mFeatureIterator]->featureId() );
76+
if(mFetchGeom)
77+
{
78+
QgsGeometry* geometry = mFeatures[*mFeatureIterator]->geometry();
79+
unsigned char *geom = geometry->wkbBuffer();
80+
int geomSize = geometry->wkbSize();
81+
82+
unsigned char* copiedGeom = new unsigned char[geomSize];
83+
memcpy(copiedGeom, geom, geomSize);
84+
feature.setGeometryAndOwnership(copiedGeom, geomSize);
85+
}
86+
87+
const QgsAttributeMap& attributes = mFeatures[*mFeatureIterator]->attributeMap();
88+
for(QgsAttributeList::const_iterator it = mAttributesToFetch.begin(); it != mAttributesToFetch.end(); ++it)
89+
{
90+
feature.addAttribute(*it, attributes[*it]);
91+
}
92+
++mFeatureIterator;
93+
if(mUseIntersect)
94+
{
95+
if(feature.geometry()->intersects(mSpatialFilter))
96+
{
97+
return true;
98+
}
10499
else
105-
{
106-
return true;
107-
}
100+
{
101+
continue; //go for the next feature
102+
}
103+
}
104+
else
105+
{
106+
return true;
108107
}
108+
}
109109
}
110110

111111

@@ -132,10 +132,7 @@ const QgsFieldMap & QgsWFSProvider::fields() const
132132

133133
void QgsWFSProvider::reset()
134134
{
135-
if(mSelectedFeatures)
136-
{
137-
mFeatureIterator = mSelectedFeatures->begin();
138-
}
135+
mFeatureIterator = mSelectedFeatures.begin();
139136
}
140137

141138
QgsSpatialRefSys QgsWFSProvider::getSRS()
@@ -162,24 +159,17 @@ void QgsWFSProvider::select(QgsAttributeList fetchAttributes,
162159
mAttributesToFetch = fetchAttributes;
163160
mFetchGeom = fetchGeometry;
164161

165-
delete mSelectedFeatures;
166162
if(rect.isEmpty())
167-
{
168-
mSpatialFilter = mExtent;
169-
}
163+
{
164+
mSpatialFilter = mExtent;
165+
}
170166
else
171-
{
172-
mSpatialFilter = rect;
173-
}
167+
{
168+
mSpatialFilter = rect;
169+
}
174170

175-
GEOS_GEOM::Envelope filter(mSpatialFilter.xMin(), mSpatialFilter.xMax(), mSpatialFilter.yMin(), mSpatialFilter.yMax());
176-
#if GEOS_VERSION_MAJOR < 3
177-
mSelectedFeatures = mSpatialIndex.query(&filter);
178-
#else
179-
mSelectedFeatures = new std::vector<void*>;
180-
mSpatialIndex.query(&filter, *mSelectedFeatures);
181-
#endif
182-
mFeatureIterator = mSelectedFeatures->begin();
171+
mSelectedFeatures = mSpatialIndex->intersects(mSpatialFilter);
172+
mFeatureIterator = mSelectedFeatures.begin();
183173
}
184174

185175
int QgsWFSProvider::getFeature(const QString& uri)
@@ -249,20 +239,20 @@ int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAtt
249239
QByteArray result;
250240
QgsHttpTransaction http(request);
251241
http.getSynchronously(result);
252-
242+
253243
QDomDocument getFeatureDocument;
254244
if(!getFeatureDocument.setContent(result, true))
255-
{
256-
return 1; //error
257-
}
245+
{
246+
return 1; //error
247+
}
258248

259249
QDomElement featureCollectionElement = getFeatureDocument.documentElement();
260-
250+
261251
//get and set Extent
262252
if(getExtentFromGML2(&mExtent, featureCollectionElement) != 0)
263-
{
264-
return 3;
265-
}
253+
{
254+
return 3;
255+
}
266256

267257
setSRSFromGML2(featureCollectionElement);
268258

@@ -275,58 +265,52 @@ int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAtt
275265
#endif
276266

277267
//the new and faster method with the expat parser
278-
std::list<QgsFeature*> dataFeatures;
279-
std::set<QString> thematicAttributes;
268+
QSet<QString> thematicAttributes;
280269
for(QgsFieldMap::const_iterator it = mFields.begin(); it != mFields.end(); ++it)
281-
{
282-
thematicAttributes.insert(it->name());
283-
}
284-
285-
QgsWFSData dataReader(uri, &mExtent, &mSourceSRS, &dataFeatures, geometryAttribute, thematicAttributes, &mWKBType);
270+
{
271+
thematicAttributes << it->name();
272+
}
273+
274+
QgsWFSData dataReader(uri, &mExtent, &mSourceSRS, mFeatures, geometryAttribute, thematicAttributes, &mWKBType);
286275
QObject::connect(dataReader.http(), SIGNAL(dataReadProgress(int, int)), this, SLOT(handleWFSProgressMessage(int, int)));
287276

288277
//also connect to setStatus signal of qgisapp (if it exists)
289278
QWidget* mainWindow = 0;
290-
279+
291280
QWidgetList topLevelWidgets = qApp->topLevelWidgets();
292281
QWidgetList::iterator it = topLevelWidgets.begin();
293282
for(; it != topLevelWidgets.end(); ++it)
283+
{
284+
if((*it)->objectName() == "QgisApp")
294285
{
295-
if((*it)->objectName() == "QgisApp")
296-
{
297-
mainWindow = *it;
298-
break;
299-
}
286+
mainWindow = *it;
287+
break;
300288
}
301-
289+
}
290+
302291
if(mainWindow)
303-
{
304-
QObject::connect(this, SIGNAL(dataReadProgressMessage(QString)), mainWindow, SLOT(showStatusMessage(QString)));
305-
}
292+
{
293+
QObject::connect(this, SIGNAL(dataReadProgressMessage(QString)), mainWindow, SLOT(showStatusMessage(QString)));
294+
}
306295

307296
if(dataReader.getWFSData() != 0)
308-
{
309-
qWarning("getWFSData returned with error");
310-
return 1;
311-
}
297+
{
298+
qWarning("getWFSData returned with error");
299+
return 1;
300+
}
312301

313302
qWarning("feature count after request is:");
314-
qWarning(QString::number(dataFeatures.size()).toLocal8Bit().data());
303+
qWarning(QString::number(mFeatures.size()).toLocal8Bit().data());
315304
qWarning("mExtent after request is:");
316305
qWarning(mExtent.stringRep().toLocal8Bit().data());
317306

318-
mFeatureCount = 0;
307+
for(QList<QgsFeature*>::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it) {
308+
QgsDebugMsg("feature " + QString::number((*it)->featureId()));
309+
mSpatialIndex->insertFeature(**it);
310+
}
311+
312+
mFeatureCount = mFeatures.size();
319313

320-
QgsRect featureBBox;
321-
GEOS_GEOM::Envelope* geosBBox;
322-
for(std::list<QgsFeature*>::const_iterator it = dataFeatures.begin(); it != dataFeatures.end(); ++it)
323-
{
324-
featureBBox = (*it)->geometry()->boundingBox();
325-
geosBBox = new GEOS_GEOM::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax());
326-
mSpatialIndex.insert(geosBBox, (void*)(*it));
327-
mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, (*it)));
328-
++mFeatureCount;
329-
}
330314
return 0;
331315
}
332316

@@ -755,8 +739,6 @@ int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement,
755739
unsigned char* wkb = 0;
756740
int wkbSize = 0;
757741
QGis::WKBTYPE currentType;
758-
QgsRect featureBBox;
759-
GEOS_GEOM::Envelope* geosBBox;
760742
mFeatureCount = 0;
761743

762744
for(int i = 0; i < featureTypeNodeList.size(); ++i)
@@ -800,10 +782,8 @@ int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement,
800782
if(wkb && wkbSize > 0)
801783
{
802784
//insert bbox and pointer to feature into search tree
803-
featureBBox = f->geometry()->boundingBox();
804-
geosBBox = new GEOS_GEOM::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax());
805-
mSpatialIndex.insert(geosBBox, (void*)f);
806-
mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, f));
785+
mSpatialIndex->insertFeature(*f);
786+
mFeatures << f;
807787
++mFeatureCount;
808788
}
809789
++counter;

‎src/providers/wfs/qgswfsprovider.h

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,9 @@
2323
#include "qgsrect.h"
2424
#include "qgsspatialrefsys.h"
2525
#include "qgsvectordataprovider.h"
26-
#include <geos/version.h>
27-
#if GEOS_VERSION_MAJOR < 3
28-
#include <geos/geom.h>
29-
#include <geos/indexStrtree.h>
30-
#define GEOS_GEOM geos
31-
#define GEOS_INDEX_STRTREE geos
32-
#else
33-
#include <geos/geom/Envelope.h>
34-
#include <geos/index/strtree/STRtree.h>
35-
#define GEOS_GEOM geos::geom
36-
#define GEOS_INDEX_STRTREE geos::index::strtree
37-
#endif
3826

3927
class QgsRect;
28+
class QgsSpatialIndex;
4029

4130
/**A provider reading features from a WFS server*/
4231
class QgsWFSProvider: public QgsVectorDataProvider
@@ -122,13 +111,13 @@ class QgsWFSProvider: public QgsVectorDataProvider
122111
/**Flag if precise intersection test is needed. Otherwise, every feature is returned (even if a filter is set)*/
123112
bool mUseIntersect;
124113
/**A spatial index for fast access to a feature subset*/
125-
GEOS_INDEX_STRTREE::STRtree mSpatialIndex;
126-
/**Stores all the inserted rectangles and features. This is used to clean up the memory in the destructor*/
127-
std::list< std::pair<GEOS_GEOM::Envelope*, QgsFeature*> > mEnvelopesAndFeatures;
128-
/**Vector where the QgsFeature* of a query are inserted*/
129-
std::vector<void*>* mSelectedFeatures;
114+
QgsSpatialIndex *mSpatialIndex;
115+
/**Vector where the ids of the selected features are inserted*/
116+
QList<int> mSelectedFeatures;
130117
/**Iterator on the feature vector for use in reset(), getNextFeature(), etc...*/
131-
std::vector<void*>::iterator mFeatureIterator;
118+
QList<int>::iterator mFeatureIterator;
119+
/**Vector where the features are inserted*/
120+
QList<QgsFeature*> mFeatures;
132121
/**Geometry type of the features in this layer*/
133122
mutable QGis::WKBTYPE mWKBType;
134123
/**Source SRS*/

0 commit comments

Comments
 (0)
Please sign in to comment.