Skip to content

Commit

Permalink
Use str tree spatial index from geos for the wfsprovider
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@5889 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Sep 30, 2006
1 parent c733461 commit 985d3d0
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 36 deletions.
12 changes: 3 additions & 9 deletions src/core/qgsgeometry.cpp
Expand Up @@ -2489,9 +2489,6 @@ geos::Geometry* QgsGeometry::geosGeometry() const
ptr += sizeof(double);
y = (double *) ptr;
ptr += sizeof(double);
#ifdef QGISDEBUG
qWarning("QgsGeometry::geosGeometry: adding coordinate pair "+QString::number(*x)+"//"+QString::number(*y));
#endif
sequence->add(geos::Coordinate(*x,*y));
}
return geosGeometryFactory->createLineString(sequence);
Expand Down Expand Up @@ -2603,9 +2600,6 @@ geos::Geometry* QgsGeometry::geosGeometry() const
ptr += sizeof(double);
y = (double *) ptr;
ptr += sizeof(double);
#ifdef QGISDEBUG
//qWarning("adding coordinate pair "+QString::number(*x)+"//"+QString::number(*y));
#endif
sequence->add(geos::Coordinate(*x,*y));
}
geos::LinearRing* ring=geosGeometryFactory->createLinearRing(sequence);
Expand Down Expand Up @@ -2723,9 +2717,9 @@ bool QgsGeometry::exportGeosToWkb() const
for (int n = 0; n < numPoints; n++)
{
#ifdef QGISDEBUG
std::cout << "QgsGeometry::exportGeosToWkb: Adding "
<< sequence->getAt(n).x << ", "
<< sequence->getAt(n).y << "." << std::endl;
//std::cout << "QgsGeometry::exportGeosToWkb: Adding "
// << sequence->getAt(n).x << ", "
// << sequence->getAt(n).y << "." << std::endl;
#endif
// assign x
memcpy(ptr, &(sequence->getAt(n).x), sizeof(double));
Expand Down
62 changes: 40 additions & 22 deletions src/providers/wfs/qgswfsprovider.cpp
Expand Up @@ -36,9 +36,8 @@ static const QString TEXT_PROVIDER_DESCRIPTION = "WFS data provider";
static const QString WFS_NAMESPACE = "http://www.opengis.net/wfs";
static const QString GML_NAMESPACE = "http://www.opengis.net/gml";

QgsWFSProvider::QgsWFSProvider(const QString& uri): QgsVectorDataProvider(uri), mFilter(0), mUseIntersect(false), mSourceSRS(0)
QgsWFSProvider::QgsWFSProvider(const QString& uri): QgsVectorDataProvider(uri), mUseIntersect(false), mSourceSRS(0), mSelectedFeatures(0), mFeatureCount(0)
{
mFeatureIterator = mFeatures.begin();
if(getFeature(uri) == 0)
{
//provider valid
Expand All @@ -47,16 +46,20 @@ QgsWFSProvider::QgsWFSProvider(const QString& uri): QgsVectorDataProvider(uri),
{
//provider invalid
}
//set spatial filter to the whole extent
select(&mExtent, false);
}

QgsWFSProvider::~QgsWFSProvider()
{
for(std::vector<QgsFeature*>::iterator it = mFeatures.begin(); it != mFeatures.end(); ++it)
delete mSelectedFeatures;
delete mSourceSRS;
for(std::list<std::pair<geos::Envelope*, QgsFeature*> >::iterator it = mEnvelopesAndFeatures.begin();\
it != mEnvelopesAndFeatures.end(); ++it)
{
delete (*it);
delete it->first;
delete it->second;
}
mFeatures.clear();
delete mFilter;
}

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

QgsFeature* f = new QgsFeature();
unsigned char* geom = (*mFeatureIterator)->getGeometry();
int geomSize = (*mFeatureIterator)->getGeometrySize();
unsigned char* geom = ((QgsFeature*)(*mFeatureIterator))->getGeometry();
int geomSize = ((QgsFeature*)(*mFeatureIterator))->getGeometrySize();

unsigned char* copiedGeom = new unsigned char[geomSize];
memcpy(copiedGeom, geom, geomSize);
f->setGeometryAndOwnership(copiedGeom, geomSize);
f->setFeatureId((*mFeatureIterator)->featureId());
f->setFeatureId(((QgsFeature*)(*mFeatureIterator))->featureId());

const std::vector<QgsFeatureAttribute> attributes = (*mFeatureIterator)->attributeMap();
const std::vector<QgsFeatureAttribute> attributes = ((QgsFeature*)(*mFeatureIterator))->attributeMap();
for(std::list<int>::const_iterator it = attlist.begin(); it != attlist.end(); ++it)
{
f->addAttribute(attributes[*it].fieldName(), attributes[*it].fieldValue(), attributes[*it].isNumeric());
}
++mFeatureIterator;
if(mFilter && mUseIntersect)
if(mUseIntersect)
{
if(f->geometry()->fast_intersects(mFilter))
if(f->geometry()->fast_intersects(&mSpatialFilter))
{
return f;
}
Expand Down Expand Up @@ -130,7 +133,7 @@ int QgsWFSProvider::geometryType() const

long QgsWFSProvider::featureCount() const
{
return mFeatures.size();
return mFeatureCount;
}

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

void QgsWFSProvider::reset()
{
mFeatureIterator = mFeatures.begin();
delete mFilter;
mFilter = 0;
geos::Envelope e(mExtent.xMin(), mExtent.xMax(), mExtent.yMin(), mExtent.yMax());
delete mSelectedFeatures;
mSelectedFeatures = mSpatialIndex.query(&e);
if(mSelectedFeatures)
{
mFeatureIterator = mSelectedFeatures->begin();
}
}

QString QgsWFSProvider::minValue(int position)
Expand Down Expand Up @@ -231,9 +238,12 @@ bool QgsWFSProvider::isValid()

void QgsWFSProvider::select(QgsRect *mbr, bool useIntersect)
{
reset();
mFilter = new QgsRect(*mbr);
mUseIntersect = useIntersect;
delete mSelectedFeatures;
mSpatialFilter = *mbr;
geos::Envelope filter(mbr->xMin(), mbr->xMax(), mbr->yMin(), mbr->yMax());
mSelectedFeatures = mSpatialIndex.query(&filter);
mFeatureIterator = mSelectedFeatures->begin();
}

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

setSRSFromGML2(featureCollectionElement);

if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute, mFeatures) != 0)
if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute) != 0)
{
return 4;
}
Expand Down Expand Up @@ -638,7 +648,7 @@ int QgsWFSProvider::setSRSFromGML2(const QDomElement& wfsCollectionElement)
return 0;
}

int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute, std::vector<QgsFeature*>& features) const
int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement, const QString& geometryAttribute)
{
QDomNodeList featureTypeNodeList = wfsCollectionElement.elementsByTagNameNS(GML_NAMESPACE, "featureMember");
QDomElement currentFeatureMemberElem;
Expand All @@ -650,6 +660,9 @@ int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement,
unsigned char* wkb = 0;
int wkbSize = 0;
QGis::WKBTYPE currentType;
QgsRect featureBBox;
geos::Envelope* geosBBox;
mFeatureCount = 0;

for(int i = 0; i < featureTypeNodeList.size(); ++i)
{
Expand Down Expand Up @@ -679,7 +692,12 @@ int QgsWFSProvider::getFeaturesFromGML2(const QDomElement& wfsCollectionElement,
}
if(wkb && wkbSize > 0)
{
features.push_back(f);
//insert bbox and pointer to feature into search tree
featureBBox = f->boundingBox();
geosBBox = new geos::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax());
mSpatialIndex.insert(geosBBox, (void*)f);
mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, f));
++mFeatureCount;
}
++counter;
}
Expand Down
16 changes: 11 additions & 5 deletions src/providers/wfs/qgswfsprovider.h
Expand Up @@ -22,6 +22,7 @@
#include "qgis.h"
#include "qgsrect.h"
#include "qgsvectordataprovider.h"
#include <indexStrtree.h>

class QgsRect;

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

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

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

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

0 comments on commit 985d3d0

Please sign in to comment.