- ran files through GNU indent to make it easier to read code

- isValid() was always returning true when, in fact, occasionally the
  provider was not in a valid state


git-svn-id: http://svn.osgeo.org/qgis/trunk@978 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
mcoletti 2004-03-04 20:35:14 +00:00
parent 7d1631703c
commit ab3b85fdbb
2 changed files with 338 additions and 302 deletions

View File

@ -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;i<fieldCount();i++)
{
minmaxcache[i]=new double[2];
}
// 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()));
}
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;i<fieldCount();i++)
for (int i = 0; i < fieldCount(); i++)
{
delete minmaxcache[i];
delete minmaxcache[i];
}
delete[] minmaxcache;
delete[]minmaxcache;
}
/**
@ -103,171 +108,183 @@ QgsShapeFileProvider::~QgsShapeFileProvider()
*/
QgsFeature *QgsShapeFileProvider::getFirstFeature(bool fetchAttributes)
{
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;
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<QgsFeature>& 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<QgsField>& 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;i<fieldCount();i++)
for (int i = 0; i < fieldCount(); i++)
{
minmaxcache[i][0]=DBL_MAX;
minmaxcache[i][1]=-DBL_MAX;
minmaxcache[i][0] = DBL_MAX;
minmaxcache[i][1] = -DBL_MAX;
}
QgsFeature* f=getFirstFeature(true);
do
QgsFeature *f = getFirstFeature(true);
do
{
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));
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;
}

View File

@ -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<QgsFeature>& 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<QgsField>& 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<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();
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();
};