diff --git a/providers/ogr/qgsshapefileprovider.cpp b/providers/ogr/qgsshapefileprovider.cpp index 4f4190e4be4..1a5655d0b9e 100644 --- a/providers/ogr/qgsshapefileprovider.cpp +++ b/providers/ogr/qgsshapefileprovider.cpp @@ -13,88 +13,93 @@ QgsShapeFileProvider::QgsShapeFileProvider(QString uri):dataSourceUri(uri), minmaxcachedirty(true) { - OGRRegisterAll(); - - // make connection to the data source - #ifdef QGISDEBUG - std::cerr << "Data source uri is " << uri << std::endl; - #endif - ogrDataSource = OGRSFDriverRegistrar::Open((const char *) uri); - if (ogrDataSource != NULL) { - #ifdef QGISDEBUG - std::cerr << "Data source is valid" << std::endl; - #endif - valid = true; - ogrLayer = ogrDataSource->GetLayer(0); - // get the extent_ (envelope) of the layer - #ifdef QGISDEBUG - std::cerr << "Starting get extent\n"; - #endif - extent_ = new OGREnvelope(); - ogrLayer->GetExtent(extent_); - #ifdef QGISDEBUG - std::cerr << "Finished get extent\n"; - #endif - // getting the total number of features in the layer - numberFeatures = ogrLayer->GetFeatureCount(); - // check the validity of the layer - #ifdef QGISDEBUG - std::cerr << "checking validity\n"; - #endif - OGRFeature *feat = ogrLayer->GetNextFeature(); - if (feat) { - OGRGeometry *geom = feat->GetGeometryRef(); - if (geom) { - geomType = geom->getGeometryType(); - - } else { - valid = false; - } - // Populate the field vector for this layer. The field vector contains - // field name, type, length, and precision (if numeric) - for (int i = 0; i < feat->GetFieldCount(); i++) { - OGRFieldDefn *fldDef = feat->GetFieldDefnRef(i); - attributeFields.push_back(QgsField( - fldDef->GetNameRef(), - fldDef->GetFieldTypeName(fldDef->GetType()), - fldDef->GetWidth(), - fldDef->GetPrecision())); - } + OGRRegisterAll(); - delete feat; - } else { - valid = false; - } - - ogrLayer->ResetReading(); - #ifdef QGISDEBUG - std::cerr << "Done checking validity\n"; - #endif - } else { - std::cerr << "Data source is invalid" << std::endl; - const char *er = CPLGetLastErrorMsg(); - #ifdef QGISDEBUG - std::cerr << er << std::endl; - #endif - valid = false; - } - - //resize the cache matrix - minmaxcache=new double*[fieldCount()]; - for(int i=0;iGetLayer(0); + // get the extent_ (envelope) of the layer +#ifdef QGISDEBUG + std::cerr << "Starting get extent\n"; +#endif + extent_ = new OGREnvelope(); + ogrLayer->GetExtent(extent_); +#ifdef QGISDEBUG + std::cerr << "Finished get extent\n"; +#endif + // getting the total number of features in the layer + numberFeatures = ogrLayer->GetFeatureCount(); + // check the validity of the layer +#ifdef QGISDEBUG + std::cerr << "checking validity\n"; +#endif + OGRFeature *feat = ogrLayer->GetNextFeature(); + if (feat) + { + OGRGeometry *geom = feat->GetGeometryRef(); + if (geom) + { + geomType = geom->getGeometryType(); + + } else + { + valid = false; + } + // Populate the field vector for this layer. The field vector contains + // field name, type, length, and precision (if numeric) + for (int i = 0; i < feat->GetFieldCount(); i++) + { + OGRFieldDefn *fldDef = feat->GetFieldDefnRef(i); + attributeFields.push_back(QgsField(fldDef->GetNameRef(), + fldDef->GetFieldTypeName(fldDef->GetType()), + fldDef->GetWidth(), fldDef->GetPrecision())); + } + + delete feat; + } else + { + valid = false; + } + + ogrLayer->ResetReading(); +#ifdef QGISDEBUG + std::cerr << "Done checking validity\n"; +#endif + } else + { + std::cerr << "Data source is invalid" << std::endl; + const char *er = CPLGetLastErrorMsg(); +#ifdef QGISDEBUG + std::cerr << er << std::endl; +#endif + valid = false; + } + + //resize the cache matrix + minmaxcache = new double *[fieldCount()]; + for (int i = 0; i < fieldCount(); i++) + { + minmaxcache[i] = new double[2]; + } } QgsShapeFileProvider::~QgsShapeFileProvider() { - for(int i=0;iResetReading(); - OGRFeature *feat = ogrLayer->GetNextFeature(); - if(feat){ - #ifdef QGISDEBUG - std::cerr << "First feature is not null\n"; - #endif - }else{ - #ifdef QGISDEBUG - std::cerr << "First feature is null\n"; - #endif - } - f = new QgsFeature(feat->GetFID()); - f->setGeometry(getGeometryPointer(feat)); - if(fetchAttributes){ - getFeatureAttributes(feat, f); - } - } - return f; + QgsFeature *f = 0; + if (valid) + { +#ifdef QGISDEBUG + std::cerr << "getting first feature\n"; +#endif + ogrLayer->ResetReading(); + OGRFeature *feat = ogrLayer->GetNextFeature(); + if (feat) + { +#ifdef QGISDEBUG + std::cerr << "First feature is not null\n"; +#endif + } else + { +#ifdef QGISDEBUG + std::cerr << "First feature is null\n"; +#endif + } + f = new QgsFeature(feat->GetFID()); + f->setGeometry(getGeometryPointer(feat)); + if (fetchAttributes) + { + getFeatureAttributes(feat, f); + } + } + return f; } - /** + /** * Get the next feature resutling from a select operation * Return 0 if there are no features in the selection set * @return QgsFeature */ QgsFeature *QgsShapeFileProvider::getNextFeature(bool fetchAttributes) { - - QgsFeature *f = 0; - if(valid){ - //std::cerr << "getting next feature\n"; - OGRFeature *fet = ogrLayer->GetNextFeature(); - if(fet){ - OGRGeometry *geom = fet->GetGeometryRef(); - - // get the wkb representation - unsigned char *feature = new unsigned char[geom->WkbSize()]; - geom->exportToWkb((OGRwkbByteOrder) endian(), feature); - f = new QgsFeature(fet->GetFID()); - f->setGeometry(feature); - if(fetchAttributes){ - getFeatureAttributes(fet, f); - } - /* char *wkt = new char[2 * geom->WkbSize()]; - geom->exportToWkt(&wkt); - f->setWellKnownText(wkt); - delete[] wkt; */ - delete fet; - }else{ - #ifdef QGISDEBUG - std::cerr << "Feature is null\n"; - #endif - // probably should reset reading here - ogrLayer->ResetReading(); - } - - - }else{ - #ifdef QGISDEBUG - std::cerr << "Read attempt on an invalid shapefile data source\n"; - #endif - } - return f; + + QgsFeature *f = 0; + if (valid) + { + //std::cerr << "getting next feature\n"; + OGRFeature *fet = ogrLayer->GetNextFeature(); + if (fet) + { + OGRGeometry *geom = fet->GetGeometryRef(); + + // get the wkb representation + unsigned char *feature = new unsigned char[geom->WkbSize()]; + geom->exportToWkb((OGRwkbByteOrder) endian(), feature); + f = new QgsFeature(fet->GetFID()); + f->setGeometry(feature); + if (fetchAttributes) + { + getFeatureAttributes(fet, f); + } + /* char *wkt = new char[2 * geom->WkbSize()]; + geom->exportToWkt(&wkt); + f->setWellKnownText(wkt); + delete[] wkt; */ + delete fet; + } else + { +#ifdef QGISDEBUG + std::cerr << "Feature is null\n"; +#endif + // probably should reset reading here + ogrLayer->ResetReading(); + } + + + } else + { +#ifdef QGISDEBUG + std::cerr << "Read attempt on an invalid shapefile data source\n"; +#endif + } + return f; } - /** + /** * Select features based on a bounding rectangle. Features can be retrieved * with calls to getFirstFeature and getNextFeature. * @param mbr QgsRect containing the extent to use in selecting features */ - void QgsShapeFileProvider::select(QgsRect *rect, bool useIntersect) - { - // spatial query to select features - // std::cerr << "Selection rectangle is " << *rect << std::endl; - OGRGeometry *filter = 0; - filter = new OGRPolygon(); - QString wktExtent = QString("POLYGON ((%1))").arg(rect->stringRep()); - const char *wktText = (const char *)wktExtent; - - OGRErr result = ((OGRPolygon *) filter)->importFromWkt((char **)&wktText); - //TODO - detect an error in setting the filter and figure out what to - //TODO about it. If setting the filter fails, all records will be returned - if (result == OGRERR_NONE) { +void QgsShapeFileProvider::select(QgsRect * rect, bool useIntersect) +{ + // spatial query to select features + // std::cerr << "Selection rectangle is " << *rect << std::endl; + OGRGeometry *filter = 0; + filter = new OGRPolygon(); + QString wktExtent = QString("POLYGON ((%1))").arg(rect->stringRep()); + const char *wktText = (const char *) wktExtent; + + OGRErr result = ((OGRPolygon *) filter)->importFromWkt((char **) &wktText); + //TODO - detect an error in setting the filter and figure out what to + //TODO about it. If setting the filter fails, all records will be returned + if (result == OGRERR_NONE) + { // std::cerr << "Setting spatial filter using " << wktExtent << std::endl; ogrLayer->SetSpatialFilter(filter); // std::cerr << "Feature count: " << ogrLayer->GetFeatureCount() << std::endl; - /* int featureCount = 0; - while (OGRFeature * fet = ogrLayer->GetNextFeature()) { - if (fet) { - select(fet->GetFID()); - if (tabledisplay) { - tabledisplay->table()->selectRowWithId(fet->GetFID()); - (*selected)[fet->GetFID()] = true; - } - } - } - ogrLayer->ResetReading();*/ - }else{ - #ifdef QGISDEBUG + /* int featureCount = 0; + while (OGRFeature * fet = ogrLayer->GetNextFeature()) { + if (fet) { + select(fet->GetFID()); + if (tabledisplay) { + tabledisplay->table()->selectRowWithId(fet->GetFID()); + (*selected)[fet->GetFID()] = true; + } + } + } + ogrLayer->ResetReading(); */ + } else + { +#ifdef QGISDEBUG std::cerr << "Setting spatial filter failed!" << std::endl; - #endif +#endif } - } +} - /** + /** * Set the data source specification. This may be a path or database * connection string * @uri data source specification */ void QgsShapeFileProvider::setDataSourceUri(QString uri) { - dataSourceUri = uri; + dataSourceUri = uri; } - /** + /** * Get the data source specification. This may be a path or database * connection string * @return data source specification */ QString QgsShapeFileProvider::getDataSourceUri() { - return dataSourceUri; + return dataSourceUri; } - /** + /** * Identify features within the search radius specified by rect * @param rect Bounding rectangle of search radius * @return std::vector containing QgsFeature objects that intersect rect */ -std::vector& QgsShapeFileProvider::identify(QgsRect * rect) +std::vector < QgsFeature > &QgsShapeFileProvider::identify(QgsRect * rect) { // select the features select(rect); } -unsigned char * QgsShapeFileProvider::getGeometryPointer(OGRFeature *fet){ - OGRGeometry *geom = fet->GetGeometryRef(); - unsigned char *gPtr=0; - // get the wkb representation - gPtr = new unsigned char[geom->WkbSize()]; - - geom->exportToWkb((OGRwkbByteOrder) endian(), gPtr); - return gPtr; +unsigned char *QgsShapeFileProvider::getGeometryPointer(OGRFeature * fet) +{ + OGRGeometry *geom = fet->GetGeometryRef(); + unsigned char *gPtr = 0; + // get the wkb representation + gPtr = new unsigned char[geom->WkbSize()]; + + geom->exportToWkb((OGRwkbByteOrder) endian(), gPtr); + return gPtr; } int QgsShapeFileProvider::endian() { - char *chkEndian = new char[4]; - memset(chkEndian, '\0', 4); - chkEndian[0] = 0xE8; + char *chkEndian = new char[4]; + memset(chkEndian, '\0', 4); + chkEndian[0] = 0xE8; - int *ce = (int *) chkEndian; - int retVal; - if (232 == *ce) - retVal = NDR; - else - retVal = XDR; - delete[]chkEndian; - return retVal; + int *ce = (int *) chkEndian; + int retVal; + if (232 == *ce) + retVal = NDR; + else + retVal = XDR; + delete[]chkEndian; + return retVal; } // TODO - make this function return the real extent_ @@ -279,132 +296,150 @@ QgsRect *QgsShapeFileProvider::extent() /** * Return the feature type */ -int QgsShapeFileProvider::geometryType(){ - return geomType; +int QgsShapeFileProvider::geometryType() +{ + return geomType; } + /** * Return the feature type */ -long QgsShapeFileProvider::featureCount(){ - return numberFeatures; +long QgsShapeFileProvider::featureCount() +{ + return numberFeatures; } /** * Return the number of fields */ -int QgsShapeFileProvider::fieldCount(){ +int QgsShapeFileProvider::fieldCount() +{ return attributeFields.size(); } + /** * Fetch attributes for a selected feature */ -void QgsShapeFileProvider::getFeatureAttributes(OGRFeature *ogrFet, QgsFeature *f){ - for (int i = 0; i < ogrFet->GetFieldCount(); i++) { +void QgsShapeFileProvider::getFeatureAttributes(OGRFeature * ogrFet, QgsFeature * f) +{ + for (int i = 0; i < ogrFet->GetFieldCount(); i++) + { - // add the feature attributes to the tree - OGRFieldDefn *fldDef = ogrFet->GetFieldDefnRef(i); - QString fld = fldDef->GetNameRef(); - // OGRFieldType fldType = fldDef->GetType(); - QString val; + // add the feature attributes to the tree + OGRFieldDefn *fldDef = ogrFet->GetFieldDefnRef(i); + QString fld = fldDef->GetNameRef(); + // OGRFieldType fldType = fldDef->GetType(); + QString val; - val = ogrFet->GetFieldAsString(i); - f->addAttribute(fld, val); -} + val = ogrFet->GetFieldAsString(i); + f->addAttribute(fld, val); + } } -std::vector& QgsShapeFileProvider::fields(){ +std::vector < QgsField > &QgsShapeFileProvider::fields() +{ return attributeFields; } -void QgsShapeFileProvider::reset(){ +void QgsShapeFileProvider::reset() +{ ogrLayer->SetSpatialFilter(0); ogrLayer->ResetReading(); } QString QgsShapeFileProvider::minValue(int position) { - if(position>=fieldCount()) + if (position >= fieldCount()) { - std::cerr << "Warning: access requested to invalid position in QgsShapeFileProvider::minValue(..)" << std::endl; + std::cerr << "Warning: access requested to invalid position in QgsShapeFileProvider::minValue(..)" << std::endl; } - if(minmaxcachedirty) + if (minmaxcachedirty) { - fillMinMaxCash(); + fillMinMaxCash(); } - return QString::number(minmaxcache[position][0],'f',2); + return QString::number(minmaxcache[position][0], 'f', 2); } - + QString QgsShapeFileProvider::maxValue(int position) { - if(position>=fieldCount()) + if (position >= fieldCount()) { - std::cerr << "Warning: access requested to invalid position in QgsShapeFileProvider::maxValue(..)" << std::endl; + std::cerr << "Warning: access requested to invalid position in QgsShapeFileProvider::maxValue(..)" << std::endl; } - if(minmaxcachedirty) + if (minmaxcachedirty) { - fillMinMaxCash(); + fillMinMaxCash(); } - return QString::number(minmaxcache[position][1],'f',2); + return QString::number(minmaxcache[position][1], 'f', 2); } void QgsShapeFileProvider::fillMinMaxCash() { - for(int i=0;iattributeMap())[i].fieldValue().toDouble(); - if(valueminmaxcache[i][1]) - { - minmaxcache[i][1]=value; - } - } - }while(f=getNextFeature(true)); + for (int i = 0; i < fieldCount(); i++) + { + double value = (f->attributeMap())[i].fieldValue().toDouble(); + if (value < minmaxcache[i][0]) + { + minmaxcache[i][0] = value; + } + if (value > minmaxcache[i][1]) + { + minmaxcache[i][1] = value; + } + } + } + while (f = getNextFeature(true)); - minmaxcachedirty=false; + minmaxcachedirty = false; } + //TODO - add sanity check for shape file layers, to include cheking to // see if the .shp, .dbf, .shx files are all present and the layer // actually has features -bool QgsShapeFileProvider::isValid(){ - return true; +bool QgsShapeFileProvider::isValid() +{ + return valid; } + /** * Class factory to return a pointer to a newly created * QgsShapeFileProvider object */ extern "C" QgsShapeFileProvider * classFactory(const char *uri) { - return new QgsShapeFileProvider(uri); + return new QgsShapeFileProvider(uri); } + /** Required key function (used to map the plugin to a data store type) */ -extern "C" QString providerKey(){ - return QString("ogr"); +extern "C" QString providerKey() +{ + return QString("ogr"); } + /** * Required description function */ -extern "C" QString description(){ - return QString("OGR data provider (shapefile and other formats)"); -} +extern "C" QString description() +{ + return QString("OGR data provider (shapefile and other formats)"); +} + /** * Required isProvider function. Used to determine if this shared library * is a data provider plugin */ -extern "C" bool isProvider(){ +extern "C" bool isProvider() +{ return true; } - diff --git a/providers/ogr/qgsshapefileprovider.h b/providers/ogr/qgsshapefileprovider.h index 2b0d083e007..b908a0e4b36 100644 --- a/providers/ogr/qgsshapefileprovider.h +++ b/providers/ogr/qgsshapefileprovider.h @@ -25,22 +25,23 @@ class OGRLayer; \class QgsShapeFileProvider \brief Data provider for ESRI shapefiles */ -class QgsShapeFileProvider : public QgsDataProvider { +class QgsShapeFileProvider:public QgsDataProvider +{ public: - QgsShapeFileProvider(QString uri=0); - virtual ~QgsShapeFileProvider(); + QgsShapeFileProvider(QString uri = 0); + virtual ~ QgsShapeFileProvider(); /** * Get the first feature resutling from a select operation * @return QgsFeature */ - QgsFeature * getFirstFeature(bool fetchAttributes=false); - /** + QgsFeature *getFirstFeature(bool fetchAttributes = false); + /** * Get the next feature resutling from a select operation * @return QgsFeature */ - QgsFeature * getNextFeature(bool fetchAttributes=false); - - /** Get the feature type. This corresponds to + QgsFeature *getNextFeature(bool fetchAttributes = false); + + /** Get the feature type. This corresponds to WKBPoint, WKBLineString, WKBPolygon, @@ -49,96 +50,96 @@ public: WKBMultiPolygon * as defined in qgis.h */ - int geometryType(); + int geometryType(); /** * Get the number of features in the layer */ - long featureCount(); + long featureCount(); /** * Get the number of fields in the layer */ - int fieldCount(); - /** + int fieldCount(); + /** * Select features based on a bounding rectangle. Features can be retrieved * with calls to getFirstFeature and getNextFeature. * @param mbr QgsRect containing the extent to use in selecting features */ - void select(QgsRect *mbr, bool useIntersect=false); - /** + void select(QgsRect * mbr, bool useIntersect = false); + /** * Set the data source specification. This may be a path or database * connection string * @uri data source specification */ - void setDataSourceUri(QString uri); - - /** + void setDataSourceUri(QString uri); + + /** * Get the data source specification. This may be a path or database * connection string * @return data source specification */ - QString getDataSourceUri(); - - /** + QString getDataSourceUri(); + + /** * Identify features within the search radius specified by rect * @param rect Bounding rectangle of search radius * @return std::vector containing QgsFeature objects that intersect rect */ - virtual std::vector& identify(QgsRect *rect); + virtual std::vector < QgsFeature > &identify(QgsRect * rect); /** Return endian-ness for this layer - */ - int endian(); + */ + int endian(); /** Return the extent for this data layer */ - virtual QgsRect * extent(); + virtual QgsRect *extent(); /** * Get the attributes associated with a feature */ - void getFeatureAttributes(OGRFeature *ogrFet, QgsFeature *f); + void getFeatureAttributes(OGRFeature * ogrFet, QgsFeature * f); /** * Get the field information for the layer */ - std::vector& fields(); - - /* Reset the layer - for an OGRLayer, this means clearing the - * spatial filter and calling ResetReading - */ - void reset(); + std::vector < QgsField > &fields(); + + /* Reset the layer - for an OGRLayer, this means clearing the + * spatial filter and calling ResetReading + */ + void reset(); /**Returns the minimum value of an attribut @param position the number of the attribute*/ - QString minValue(int position); + QString minValue(int position); /**Returns the maximum value of an attribut @param position the number of the attribute*/ - QString maxValue(int position); + QString maxValue(int position); /**Returns true if this is a valid shapefile */ - bool isValid(); - + bool isValid(); + private: - unsigned char *getGeometryPointer(OGRFeature *fet); - std::vector attributeFields; - QString dataSourceUri; - OGRDataSource *ogrDataSource; - OGREnvelope *extent_; - OGRLayer *ogrLayer; - bool valid; - int geomType; - long numberFeatures; - enum ENDIAN - { - NDR = 1, - XDR = 0 - }; - /**Flag indicating, if the minmaxcache should be renewed (true) or not (false)*/ - bool minmaxcachedirty; - /**Matrix storing the minimum and maximum values*/ - double** minmaxcache; - /**Fills the cash and sets minmaxcachedirty to false*/ - void fillMinMaxCash(); - - + unsigned char *getGeometryPointer(OGRFeature * fet); + std::vector < QgsField > attributeFields; + QString dataSourceUri; + OGRDataSource *ogrDataSource; + OGREnvelope *extent_; + OGRLayer *ogrLayer; + bool valid; + int geomType; + long numberFeatures; + enum ENDIAN + { + NDR = 1, + XDR = 0 + }; + /**Flag indicating, if the minmaxcache should be renewed (true) or not (false)*/ + bool minmaxcachedirty; + /**Matrix storing the minimum and maximum values*/ + double **minmaxcache; + /**Fills the cash and sets minmaxcachedirty to false*/ + void fillMinMaxCash(); + + };