📄 qgsogrprovider.cpp
字号:
/*************************************************************************** qgsogrprovider.cpp Data provider for OGR supported formats Formerly known as qgsshapefileprovider.cpp begin : Oct 29, 2003copyright : (C) 2003 by Gary E.Shermanemail : sherman at mrcc.com ***************************************************************************//*************************************************************************** * * * 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. * * * ***************************************************************************//* $Id: qgsogrprovider.cpp 8355 2008-04-17 02:08:49Z jef $ */#include "qgsogrprovider.h"#include "qgslogger.h"#include <iostream>#include <cassert>#define CPL_SUPRESS_CPLUSPLUS#include <gdal.h> // to collect version information#include <ogr_api.h>#include <ogr_srs_api.h>#include <cpl_error.h>#include <QtDebug>#include <QFile>#include <QDir>#include <QFileInfo>#include <QMap>#include <QString>//TODO Following ifndef can be removed once WIN32 GEOS support// is fixed#ifndef NOWIN32GEOSXXX//XXX GEOS support on windows is broken until we can get VC++ to// tolerate geos.h without throwing a bunch of type errors. It// appears that the windows version of GEOS may be compiled with // MINGW rather than VC++.#endif #include "qgsapplication.h"#include "qgsdataprovider.h"#include "qgsfeature.h"#include "qgsfield.h"#include "qgsgeometry.h"#include "qgslogger.h"#include "qgsspatialrefsys.h"static const QString TEXT_PROVIDER_KEY = "ogr";static const QString TEXT_PROVIDER_DESCRIPTION = QString("OGR data provider") + " (compiled against GDAL/OGR library version " + GDAL_RELEASE_NAME + ", running against GDAL/OGR library version " + GDALVersionInfo("RELEASE_NAME") + ")";QgsOgrProvider::QgsOgrProvider(QString const & uri) : QgsVectorDataProvider(uri), ogrDataSource(0), extent_(0), ogrLayer(0), ogrDriver(0){ OGRRegisterAll(); // set the selection rectangle pointer to 0 mSelectionRectangle = 0; // make connection to the data source QgsDebugMsg("Data source uri is " + uri); // try to open for update, but disable error messages to avoid a // message if the file is read only, because we cope with that // ourselves. CPLPushErrorHandler(CPLQuietErrorHandler); ogrDataSource = OGROpen(QFile::encodeName(uri).constData(), TRUE, &ogrDriver); CPLPopErrorHandler(); if(ogrDataSource == NULL) { // try to open read-only ogrDataSource = OGROpen(QFile::encodeName(uri).constData(), FALSE, &ogrDriver); //TODO Need to set a flag or something to indicate that the layer //TODO is in read-only mode, otherwise edit ops will fail //TODO: capabilities() should now reflect this; need to test. } if (ogrDataSource != NULL) { QgsDebugMsg("Data source is valid"); QgsDebugMsg("OGR Driver was " + QString(OGR_Dr_GetName(ogrDriver))); valid = true; ogrDriverName = OGR_Dr_GetName(ogrDriver); ogrLayer = OGR_DS_GetLayer(ogrDataSource,0); // get the extent_ (envelope) of the layer QgsDebugMsg("Starting get extent\n"); // TODO: This can be expensive, do we really need it! extent_ = calloc(sizeof(OGREnvelope),1); OGR_L_GetExtent(ogrLayer,(OGREnvelope *) extent_, TRUE ); QgsDebugMsg("Finished get extent\n"); // getting the total number of features in the layer // TODO: This can be expensive, do we really need it! numberFeatures = OGR_L_GetFeatureCount(ogrLayer, TRUE); // check the validity of the layer QgsDebugMsg("checking validity\n"); loadFields(); QgsDebugMsg("Done checking validity\n"); } else { QgsLogger::critical("Data source is invalid"); const char *er = CPLGetLastErrorMsg(); QgsLogger::critical(er); valid = false; } // create the geos objects geometryFactory = new GEOS_GEOM::GeometryFactory(); assert(geometryFactory!=0); mSupportedNativeTypes.insert("Integer"); mSupportedNativeTypes.insert("Real"); mSupportedNativeTypes.insert("String");}QgsOgrProvider::~QgsOgrProvider(){ OGR_DS_Destroy(ogrDataSource); ogrDataSource = 0; free(extent_); extent_ = 0; delete geometryFactory; if( mSelectionRectangle ) { OGR_G_DestroyGeometry( mSelectionRectangle ); mSelectionRectangle = 0; }}void QgsOgrProvider::setEncoding(const QString& e){ QgsVectorDataProvider::setEncoding(e); loadFields();}void QgsOgrProvider::loadFields(){ //the attribute fields need to be read again when the encoding changes mAttributeFields.clear(); OGRFeatureDefnH fdef = OGR_L_GetLayerDefn(ogrLayer); if(fdef) { geomType = OGR_FD_GetGeomType(fdef); //Some ogr drivers (e.g. GML) are not able to determine the geometry type of a layer like this. //In such cases, we examine the first feature if(geomType == wkbUnknown) { OGR_L_ResetReading(ogrLayer); OGRFeatureH firstFeature = OGR_L_GetNextFeature(ogrLayer); if(firstFeature) { OGRGeometryH firstGeometry = OGR_F_GetGeometryRef(firstFeature); if(firstGeometry) { geomType = OGR_G_GetGeometryType(firstGeometry); } OGR_F_Destroy( firstFeature ); } OGR_L_ResetReading(ogrLayer); } for(int i=0;i<OGR_FD_GetFieldCount(fdef);++i) { OGRFieldDefnH fldDef = OGR_FD_GetFieldDefn(fdef,i); OGRFieldType ogrType = OGR_Fld_GetType(fldDef); QVariant::Type varType; switch (ogrType) { case OFTInteger: varType = QVariant::Int; break; case OFTReal: varType = QVariant::Double; break; // unsupported in OGR 1.3 //case OFTDateTime: varType = QVariant::DateTime; break;#if GDAL_VERSION_NUM >= 1400 case OFTString: varType = QVariant::String; break;#endif default: varType = QVariant::String; // other unsupported, leave it as a string } mAttributeFields.insert( i, QgsField( mEncoding->toUnicode(OGR_Fld_GetNameRef(fldDef)), varType, mEncoding->toUnicode(OGR_GetFieldTypeName(ogrType)), OGR_Fld_GetWidth(fldDef), OGR_Fld_GetPrecision(fldDef) )); } }}QString QgsOgrProvider::storageType() const{ // Delegate to the driver loaded in by OGR return ogrDriverName;}bool QgsOgrProvider::getFeatureAtId(int featureId, QgsFeature& feature, bool fetchGeometry, QgsAttributeList fetchAttributes){ OGRFeatureH fet = OGR_L_GetFeature(ogrLayer,featureId); if (fet == NULL) return false; feature.setFeatureId(OGR_F_GetFID(fet)); /* fetch geometry */ if (fetchGeometry) { OGRGeometryH geom = OGR_F_GetGeometryRef(fet); // get the wkb representation unsigned char *wkb = new unsigned char[OGR_G_WkbSize(geom)]; OGR_G_ExportToWkb(geom,(OGRwkbByteOrder) QgsApplication::endian(), wkb); feature.setGeometryAndOwnership(wkb, OGR_G_WkbSize(geom)); } /* fetch attributes */ for(QgsAttributeList::iterator it = fetchAttributes.begin(); it != fetchAttributes.end(); ++it) { getFeatureAttribute(fet,feature,*it); } return true;}bool QgsOgrProvider::getNextFeature(QgsFeature& feature){ if (!valid) { QgsLogger::warning("Read attempt on an invalid shapefile data source"); return false; } OGRFeatureH fet; QgsRect selectionRect; while ((fet = OGR_L_GetNextFeature(ogrLayer)) != NULL) { // skip features without geometry if (OGR_F_GetGeometryRef(fet) == NULL && !mFetchFeaturesWithoutGeom) { OGR_F_Destroy( fet ); continue; } OGRFeatureDefnH featureDefinition = OGR_F_GetDefnRef(fet); QString featureTypeName = featureDefinition ? QString(OGR_FD_GetName(featureDefinition)) : QString(""); feature.setFeatureId(OGR_F_GetFID(fet)); feature.setTypeName(featureTypeName); /* fetch geometry */ if (mFetchGeom) { OGRGeometryH geom = OGR_F_GetGeometryRef(fet); // get the wkb representation unsigned char *wkb = new unsigned char[OGR_G_WkbSize(geom)]; OGR_G_ExportToWkb(geom,(OGRwkbByteOrder) QgsApplication::endian(), wkb); feature.setGeometryAndOwnership(wkb, OGR_G_WkbSize(geom)); if (mUseIntersect) { //precise test for intersection with search rectangle //first make QgsRect from OGRPolygon OGREnvelope env; memset( &env, 0, sizeof(env) ); if(mSelectionRectangle) OGR_G_GetEnvelope(mSelectionRectangle,&env); if(env.MinX != 0 || env.MinY != 0 || env.MaxX != 0 || env.MaxY != 0 ) //if envelope is invalid, skip the precise intersection test { selectionRect.set(env.MinX, env.MinY, env.MaxX, env.MaxY); if(!feature.geometry()->intersects(selectionRect)) { OGR_F_Destroy( fet ); continue; } } } } /* fetch attributes */ for(QgsAttributeList::iterator it = mAttributesToFetch.begin(); it != mAttributesToFetch.end(); ++it) { getFeatureAttribute(fet,feature,*it); } /* we have a feature, end this cycle */ break; } /* while */ if (fet) { OGR_F_Destroy( fet ); return true; } else { QgsDebugMsg("Feature is null"); // probably should reset reading here OGR_L_ResetReading(ogrLayer); return false; }}void QgsOgrProvider::select(QgsAttributeList fetchAttributes, QgsRect rect, bool fetchGeometry, \ bool useIntersect){ mUseIntersect = useIntersect; mAttributesToFetch = fetchAttributes; mFetchGeom = fetchGeometry; // spatial query to select features if(rect.isEmpty()) { OGR_L_SetSpatialFilter(ogrLayer,0); } else { OGRGeometryH filter = 0; QString wktExtent = QString("POLYGON ((%1))").arg(rect.asPolygon()); const char *wktText = (const char *)wktExtent; if(useIntersect) { // store the selection rectangle for use in filtering features during // an identify and display attributes if( mSelectionRectangle ) OGR_G_DestroyGeometry( mSelectionRectangle ); OGR_G_CreateFromWkt( (char **)&wktText, NULL, &mSelectionRectangle); } wktText = (const char *) wktExtent; OGR_G_CreateFromWkt( (char **)&wktText, NULL, &filter ); QgsDebugMsg("Setting spatial filter using " + wktExtent); OGR_L_SetSpatialFilter( ogrLayer, filter ); OGR_G_DestroyGeometry( filter ); } }unsigned char * QgsOgrProvider::getGeometryPointer(OGRFeatureH fet){ OGRGeometryH geom = OGR_F_GetGeometryRef(fet); unsigned char *gPtr=0; if( geom == NULL ) return NULL; // get the wkb representation gPtr = new unsigned char[OGR_G_WkbSize(geom)]; OGR_G_ExportToWkb(geom,(OGRwkbByteOrder) QgsApplication::endian(), gPtr); return gPtr;}QgsRect QgsOgrProvider::extent(){ OGREnvelope *ext = (OGREnvelope *) extent_; mExtentRect.set(ext->MinX, ext->MinY, ext->MaxX, ext->MaxY); return mExtentRect;}size_t QgsOgrProvider::layerCount() const{ return OGR_DS_GetLayerCount(ogrDataSource);} // QgsOgrProvider::layerCount()/** * Return the feature type */QGis::WKBTYPE QgsOgrProvider::geometryType() const{ return (QGis::WKBTYPE) geomType;}/** * Return the feature type */long QgsOgrProvider::featureCount() const{ return numberFeatures;}/** * Return the number of fields */uint QgsOgrProvider::fieldCount() const{ return mAttributeFields.size();}void QgsOgrProvider::getFeatureAttribute(OGRFeatureH ogrFet, QgsFeature & f, int attindex){ OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef(ogrFet, attindex); if ( ! fldDef ) { QgsDebugMsg("ogrFet->GetFieldDefnRef(attindex) returns NULL"); return; } QVariant value; if( OGR_F_IsFieldSet(ogrFet, attindex) ) { switch (mAttributeFields[attindex].type()) { case QVariant::String: value = QVariant( mEncoding->toUnicode( OGR_F_GetFieldAsString(ogrFet,attindex) ) ); break; case QVariant::Int: value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attindex ) ); break; case QVariant::Double: value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attindex ) ); break; //case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break; default: assert(NULL && "unsupported field type"); } } else { value = QVariant( QString::null );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -