⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qgswfsprovider.cpp

📁 一个非常好的GIS开源新版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************                              qgswfsprovider.cpp                                  -------------------  begin                : July 25, 2006  copyright            : (C) 2006 by Marco Hugentobler  email                : marco dot hugentobler at karto dot baug dot ethz dot ch ***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * ***************************************************************************/#include "qgsapplication.h"#include "qgsfeature.h"#include "qgsfield.h"#include "qgsgeometry.h"#include "qgshttptransaction.h"#include "qgsspatialrefsys.h"#include "qgswfsdata.h"#include "qgswfsprovider.h"#include "qgslogger.h"#include <QDomDocument>#include <QDomNodeList>#include <QFile>#include <cfloat>static const QString TEXT_PROVIDER_KEY = "WFS";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), mUseIntersect(false), mSelectedFeatures(0), mSourceSRS(0), mFeatureCount(0), mValid(true){  if(getFeature(uri) == 0)    {      mValid = true;            //set spatial filter to the whole extent      //select(mExtent, false); //MH TODO: fix this in provider0_9-branch    }  else    {      mValid = false;    }}QgsWFSProvider::~QgsWFSProvider(){  delete mSelectedFeatures;  for(std::list<std::pair<GEOS_GEOM::Envelope*, QgsFeature*> >::iterator it = mEnvelopesAndFeatures.begin();\      it != mEnvelopesAndFeatures.end(); ++it)    {      delete it->first;      delete it->second;    }}bool QgsWFSProvider::getNextFeature(QgsFeature& feature){  while(true) //go through the loop until we find a feature in the filter    {      if(!mSelectedFeatures || mFeatureIterator == mSelectedFeatures->end())	{	  return 0;	}      feature.setFeatureId(((QgsFeature*)(*mFeatureIterator))->featureId());      if(mFetchGeom)	{	  QgsGeometry* geometry = ((QgsFeature*)(*mFeatureIterator))->geometry();	  unsigned char* geom = geometry->wkbBuffer();	  int geomSize = geometry->wkbSize();      	  unsigned char* copiedGeom = new unsigned char[geomSize];	  memcpy(copiedGeom, geom, geomSize);	  feature.setGeometryAndOwnership(copiedGeom, geomSize);	}            const QgsAttributeMap& attributes = ((QgsFeature*)(*mFeatureIterator))->attributeMap();      for(QgsAttributeList::const_iterator it = mAttributesToFetch.begin(); it != mAttributesToFetch.end(); ++it)	{	  feature.addAttribute(*it, attributes[*it]);	}      ++mFeatureIterator;      if(mUseIntersect)	{	  if(feature.geometry()->intersects(mSpatialFilter))	    {	      return true;	    }	  else	    {	      continue; //go for the next feature	    }	}      else	{	  return true;	}    }}QGis::WKBTYPE QgsWFSProvider::geometryType() const{  return mWKBType;}long QgsWFSProvider::featureCount() const{  return mFeatureCount;}uint QgsWFSProvider::fieldCount() const{  return mFields.size();}const QgsFieldMap & QgsWFSProvider::fields() const{  return mFields;}void QgsWFSProvider::reset(){  if(mSelectedFeatures)    {      mFeatureIterator = mSelectedFeatures->begin();    }}QgsSpatialRefSys QgsWFSProvider::getSRS(){  return mSourceSRS;}QgsRect QgsWFSProvider::extent(){  return mExtent;}bool QgsWFSProvider::isValid(){  return mValid;}void QgsWFSProvider::select(QgsAttributeList fetchAttributes,                            QgsRect rect,                            bool fetchGeometry,                            bool useIntersect){  mUseIntersect = useIntersect;  mAttributesToFetch = fetchAttributes;  mFetchGeom = fetchGeometry;  delete mSelectedFeatures;  if(rect.isEmpty())    {      mSpatialFilter = mExtent;    }  else    {      mSpatialFilter = rect;    }  GEOS_GEOM::Envelope filter(mSpatialFilter.xMin(), mSpatialFilter.xMax(), mSpatialFilter.yMin(), mSpatialFilter.yMax());#if GEOS_VERSION_MAJOR < 3  mSelectedFeatures = mSpatialIndex.query(&filter);#else  mSelectedFeatures = new std::vector<void*>;  mSpatialIndex.query(&filter, *mSelectedFeatures);#endif  mFeatureIterator = mSelectedFeatures->begin();}int QgsWFSProvider::getFeature(const QString& uri){  QString geometryAttribute;  //Local url or HTTP?  if(uri.startsWith("http://"))    {      mEncoding = QgsWFSProvider::GET;    }  else    {      mEncoding = QgsWFSProvider::FILE;    }  if(mEncoding == QgsWFSProvider::FILE)    {      //guess geometry attribute and other attributes from schema or from .gml file      if(describeFeatureTypeFile(uri, geometryAttribute, mFields) != 0)	{	  return 1;	}    }  else //take schema with describeFeatureType request    {      QString describeFeatureUri = uri;      describeFeatureUri.replace(QString("GetFeature"), QString("DescribeFeatureType"));      if(describeFeatureType(describeFeatureUri, geometryAttribute, mFields) != 0)	{	  return 1;	}    }  if(mEncoding == QgsWFSProvider::GET)    {      return getFeatureGET(uri, geometryAttribute);    }  else//local file    {      return getFeatureFILE(uri, geometryAttribute); //read the features from disk    }  return 2;}int QgsWFSProvider::describeFeatureType(const QString& uri, QString& geometryAttribute, QgsFieldMap& fields){  switch(mEncoding)    {    case QgsWFSProvider::GET:      return describeFeatureTypeGET(uri, geometryAttribute, fields);    case QgsWFSProvider::POST:      return describeFeatureTypePOST(uri, geometryAttribute, fields);    case QgsWFSProvider::SOAP:      return describeFeatureTypeSOAP(uri, geometryAttribute, fields);    case QgsWFSProvider::FILE:      return describeFeatureTypeFile(uri, geometryAttribute, fields);    }  return 1;}int QgsWFSProvider::getFeatureGET(const QString& uri, const QString& geometryAttribute){#if 0  //assemble request string  QString request = uri /*+ "&OUTPUTFORMAT=gml3"*/; //use gml2 as it is supported by most wfs servers  QByteArray result;  QgsHttpTransaction http(request);  http.getSynchronously(result);    QDomDocument getFeatureDocument;  if(!getFeatureDocument.setContent(result, true))    {      return 1; //error    }  QDomElement featureCollectionElement = getFeatureDocument.documentElement();    //get and set Extent  if(getExtentFromGML2(&mExtent, featureCollectionElement) != 0)    {      return 3;    }  setSRSFromGML2(featureCollectionElement);    if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute) != 0)  {    return 4;  }  return 0;#endif  //the new and faster method with the expat parser  std::list<QgsFeature*> dataFeatures;  std::set<QString> thematicAttributes;  for(QgsFieldMap::const_iterator it = mFields.begin(); it != mFields.end(); ++it)    {      thematicAttributes.insert(it->name());    }    QgsWFSData dataReader(uri, &mExtent, &mSourceSRS, &dataFeatures, geometryAttribute, thematicAttributes, &mWKBType);  QObject::connect(dataReader.http(), SIGNAL(dataReadProgress(int, int)), this, SLOT(handleWFSProgressMessage(int, int)));  //also connect to setStatus signal of qgisapp (if it exists)  QWidget* mainWindow = 0;    QWidgetList topLevelWidgets = qApp->topLevelWidgets();  QWidgetList::iterator it = topLevelWidgets.begin();  for(; it != topLevelWidgets.end(); ++it)    {      if((*it)->objectName() == "QgisApp")	{	  mainWindow = *it;	  break;	}    }    if(mainWindow)    {      QObject::connect(this, SIGNAL(dataReadProgressMessage(QString)), mainWindow, SLOT(showStatusMessage(QString)));    }  if(dataReader.getWFSData() != 0)    {      qWarning("getWFSData returned with error");      return 1;    }  qWarning("feature count after request is:");  qWarning(QString::number(dataFeatures.size()).toLocal8Bit().data());  qWarning("mExtent after request is:");  qWarning(mExtent.stringRep().toLocal8Bit().data());  mFeatureCount = 0;  QgsRect featureBBox;  GEOS_GEOM::Envelope* geosBBox;  for(std::list<QgsFeature*>::const_iterator it = dataFeatures.begin(); it != dataFeatures.end(); ++it)    {      featureBBox = (*it)->geometry()->boundingBox();      geosBBox = new GEOS_GEOM::Envelope(featureBBox.xMin(), featureBBox.xMax(), featureBBox.yMin(), featureBBox.yMax());      mSpatialIndex.insert(geosBBox, (void*)(*it));      mEnvelopesAndFeatures.push_back(std::make_pair(geosBBox, (*it)));      ++mFeatureCount;    }  return 0;}int QgsWFSProvider::getFeaturePOST(const QString& uri, const QString& geometryAttribute){  return 1; //soon...}int QgsWFSProvider::getFeatureSOAP(const QString& uri, const QString& geometryAttribute){  return 1; //soon...}int QgsWFSProvider::getFeatureFILE(const QString& uri, const QString& geometryAttribute){  QFile gmlFile(uri);  if(!gmlFile.open(QIODevice::ReadOnly))    {      mValid = false;      return 1;    }  QDomDocument gmlDoc;  QString errorMsg;  int errorLine, errorColumn;  if(!gmlDoc.setContent(&gmlFile, true, &errorMsg, &errorLine, &errorColumn))    {      mValid = false;      return 2;    }  QDomElement featureCollectionElement = gmlDoc.documentElement();  //get and set Extent  if(getExtentFromGML2(&mExtent, featureCollectionElement) != 0)    {      return 3;    }  setSRSFromGML2(featureCollectionElement);    if(getFeaturesFromGML2(featureCollectionElement, geometryAttribute) != 0)  {    return 4;  }  return 0;}int QgsWFSProvider::describeFeatureTypeGET(const QString& uri, QString& geometryAttribute, QgsFieldMap& fields){  QByteArray result;  QgsHttpTransaction http(uri);  if(!http.getSynchronously(result))    {      return 1;    }  QDomDocument describeFeatureDocument;    if(!describeFeatureDocument.setContent(result, true))    {      return 2;    }  if(readAttributesFromSchema(describeFeatureDocument, geometryAttribute, fields) != 0)    {      return 3;    }  return 0;}int QgsWFSProvider::describeFeatureTypePOST(const QString& uri, QString& geometryAttribute, QgsFieldMap& fields){  return 1; //soon...}int QgsWFSProvider::describeFeatureTypeSOAP(const QString& uri, QString& geometryAttribute, QgsFieldMap& fields){  return 1; //soon...}int QgsWFSProvider::describeFeatureTypeFile(const QString& uri, QString& geometryAttribute, QgsFieldMap& fields){  //first look in the schema file  QString noExtension = uri;  noExtension.chop(3);  QString schemaUri = noExtension.append("xsd");  QFile schemaFile(schemaUri);    if(schemaFile.open(QIODevice::ReadOnly))    {      QDomDocument schemaDoc;      if(!schemaDoc.setContent(&schemaFile, true))	{	  return 1; //xml file not readable or not valid	}            if(readAttributesFromSchema(schemaDoc, geometryAttribute, fields) != 0)	{	  return 2;	}      return 0;    }   std::list<QString> thematicAttributes;  //if this fails (e.g. no schema file), try to guess the geometry attribute and the names of the thematic attributes from the .gml file  if(guessAttributesFromFile(uri, geometryAttribute, thematicAttributes) != 0)    {      return 1;    }  fields.clear();  int i = 0;  for(std::list<QString>::const_iterator it = thematicAttributes.begin(); it != thematicAttributes.end(); ++it, ++i)    {      // TODO: is this correct?      fields[i] = QgsField(*it, QVariant::String, "unknown");    }  return 0;}int QgsWFSProvider::readAttributesFromSchema(QDomDocument& schemaDoc, QString& geometryAttribute, QgsFieldMap& fields) const{  //get the <schema> root element  QDomNodeList schemaNodeList = schemaDoc.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "schema");  if(schemaNodeList.length() < 1)    {      return 1;    }  QDomElement schemaElement = schemaNodeList.at(0).toElement();  QDomElement complexTypeElement; //the <complexType> element corresponding to the feature type  //find out, on which lines the first <element> or the first <complexType> occur. If <element> occurs first (mapserver), read the type of the relevant <complexType> tag. If <complexType> occurs first (geoserver), search for information about the feature type directly under this first complexType element  int firstElementTagPos = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element").at(0).toElement().columnNumber();  int firstComplexTypeTagPos = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "complexType").at(0).toElement().columnNumber();  if(firstComplexTypeTagPos < firstElementTagPos)    {      //geoserver      complexTypeElement = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "complexType").at(0).toElement();    }  else    {      //UMN mapserver      QString complexTypeType;      QDomNodeList typeElementNodeList = schemaElement.elementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "element");      QDomElement typeElement = typeElementNodeList.at(0).toElement();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -