Fix graduated classifications for joined fields

git-svn-id: http://svn.osgeo.org/qgis/trunk@15389 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
mhugent 2011-03-08 16:32:01 +00:00
parent caa0cae3b9
commit 3717e57e82
5 changed files with 152 additions and 40 deletions

View File

@ -598,6 +598,14 @@ public:
@note: this method was added in version 1.7*/
void uniqueValues( int index, QList<QVariant>& uniqueValues /Out/, int limit );
/**Returns minimum value for an attribute column or invalid variant in case of error
@note added in 1.7*/
QVariant minimumValue( int index );
/**Returns maximum value for an attribute column or invalid variant in case of error
@note added in 1.7*/
QVariant maximumValue( int index );
public slots:
/** Select feature by its ID, optionally emit signal selectionChanged() */

View File

@ -265,7 +265,6 @@ void QgsGraduatedSymbolDialog::adjustClassification()
{
mClassListWidget->clear();
QGis::GeometryType m_type = mVectorLayer->geometryType();
QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>( mVectorLayer->dataProvider() );
double minimum = 0;
double maximum = 0;
@ -288,20 +287,16 @@ void QgsGraduatedSymbolDialog::adjustClassification()
std::map < QString, int >::iterator iter = mFieldMap.find( fieldstring );
int field = iter->second;
if ( provider )
if ( modeComboBox->currentText() == tr( "Equal Interval" ) ||
modeComboBox->currentText() == tr( "Quantiles" ) )
{
if ( modeComboBox->currentText() == tr( "Equal Interval" ) ||
modeComboBox->currentText() == tr( "Quantiles" ) )
{
minimum = provider->minimumValue( field ).toDouble();
maximum = provider->maximumValue( field ).toDouble();
}
else //don't waste performance if mMode is QgsGraduatedSymbolDialog::EMPTY
{
minimum = 0;
maximum = 0;
}
minimum = mVectorLayer->minimumValue( field ).toDouble();
maximum = mVectorLayer->maximumValue( field ).toDouble();
}
else //don't waste performance if mMode is QgsGraduatedSymbolDialog::EMPTY
{
minimum = 0;
maximum = 0;
}
//todo: setup a data structure which holds the symbols
@ -500,30 +495,25 @@ int QgsGraduatedSymbolDialog::quantilesFromVectorLayer( std::list<double>& resul
{
if ( mVectorLayer )
{
QgsVectorDataProvider* provider = mVectorLayer->dataProvider();
std::vector<double> attributeValues( mVectorLayer->featureCount() );
QgsAttributeList attList;
attList.push_back( attributeIndex );
QgsFeature currentFeature;
QgsAttributeMap currentAttributeMap;
double currentValue;
int index = 0;
if ( provider )
mVectorLayer->select( attList, QgsRectangle(), false );
while ( mVectorLayer->nextFeature( currentFeature ) )
{
std::vector<double> attributeValues( provider->featureCount() );
QgsAttributeList attList;
attList.push_back( attributeIndex );
QgsFeature currentFeature;
QgsAttributeMap currentAttributeMap;
double currentValue;
int index = 0;
provider->select( attList, QgsRectangle(), false );
while ( provider->nextFeature( currentFeature ) )
{
currentAttributeMap = currentFeature.attributeMap();
currentValue = currentAttributeMap[attributeIndex].toDouble();
attributeValues[index] = currentValue;
++index;
}
sort( attributeValues.begin(), attributeValues.end() );
return calculateQuantiles( result, attributeValues, numQuantiles );
currentAttributeMap = currentFeature.attributeMap();
currentValue = currentAttributeMap[attributeIndex].toDouble();
attributeValues[index] = currentValue;
++index;
}
sort( attributeValues.begin(), attributeValues.end() );
return calculateQuantiles( result, attributeValues, numQuantiles );
}
return 1;
}

View File

@ -5003,6 +5003,114 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
uniqueValues = val.values();
}
QVariant QgsVectorLayer::minimumValue( int index )
{
if ( !mDataProvider )
{
return QVariant();
}
int maxProviderIndex;
QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), maxProviderIndex );
if ( index <= maxProviderIndex && !mEditable ) //a provider field
{
return mDataProvider->minimumValue( index );
}
else // a joined field?
{
int indexOffset; //offset between layer index and joined provider index
const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
if ( join )
{
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
if ( vl )
{
return vl->minimumValue( index );
}
}
}
//the layer is editable, but in certain cases it can still be avoided going through all features
if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
{
return mDataProvider->minimumValue( index );
}
//we need to go through each feature
QgsAttributeList attList;
attList << index;
select( attList, QgsRectangle(), false, false );
QgsFeature f;
double minimumValue = std::numeric_limits<double>::max();
double currentValue = 0;
while ( nextFeature( f ) )
{
currentValue = f.attributeMap()[index].toDouble();
if ( currentValue < minimumValue )
{
minimumValue = currentValue;
}
}
return QVariant( minimumValue );
}
QVariant QgsVectorLayer::maximumValue( int index )
{
if ( !mDataProvider )
{
return QVariant();
}
int maxProviderIndex;
QgsVectorLayerJoinBuffer::maximumIndex( mDataProvider->fields(), maxProviderIndex );
if ( index <= maxProviderIndex && !mEditable ) //a provider field
{
return mDataProvider->maximumValue( index );
}
else // a joined field?
{
int indexOffset; //offset between layer index and joined provider index
const QgsVectorJoinInfo* join = mJoinBuffer->joinForFieldIndex( index, maxProviderIndex, indexOffset );
if ( join )
{
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( join->joinLayerId ) );
if ( vl )
{
return vl->maximumValue( index );
}
}
}
//the layer is editable, but in certain cases it can still be avoided going through all features
if ( mDeletedFeatureIds.size() < 1 && mAddedFeatures.size() < 1 && !mDeletedAttributeIds.contains( index ) && mChangedAttributeValues.size() < 1 )
{
return mDataProvider->maximumValue( index );
}
//we need to go through each feature
QgsAttributeList attList;
attList << index;
select( attList, QgsRectangle(), false, false );
QgsFeature f;
double maximumValue = -std::numeric_limits<double>::max();
double currentValue = 0;
while ( nextFeature( f ) )
{
currentValue = f.attributeMap()[index].toDouble();
if ( currentValue > maximumValue )
{
maximumValue = currentValue;
}
}
return QVariant( maximumValue );
}
void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
{
mRendererV2->stopRender( rendererContext );

View File

@ -651,6 +651,13 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@note this method was added in version 1.7*/
void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 );
/**Returns minimum value for an attribute column or invalid variant in case of error
@note added in 1.7*/
QVariant minimumValue( int index );
/**Returns maximum value for an attribute column or invalid variant in case of error
@note added in 1.7*/
QVariant maximumValue( int index );
public slots:
/** Select feature by its ID, optionally emit signal selectionChanged() */

View File

@ -684,12 +684,11 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
QgsSymbolV2* symbol,
QgsVectorColorRampV2* ramp )
{
QgsVectorDataProvider* provider = vlayer->dataProvider();
int attrNum = vlayer->fieldNameIndex( attrName );
double minimum = provider->minimumValue( attrNum ).toDouble();
double maximum = provider->maximumValue( attrNum ).toDouble();
double minimum = vlayer->minimumValue( attrNum ).toDouble();
double maximum = vlayer->maximumValue( attrNum ).toDouble();
QgsDebugMsg( QString( "min %1 // max %2" ).arg( minimum ).arg( maximum ) );
QList<double> breaks;
@ -709,8 +708,8 @@ QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
QgsFeature f;
QgsAttributeList lst;
lst.append( attrNum );
provider->select( lst, QgsRectangle(), false );
while ( provider->nextFeature( f ) )
vlayer->select( lst, QgsRectangle(), false );
while ( vlayer->nextFeature( f ) )
values.append( f.attributeMap()[attrNum].toDouble() );
// calculate the breaks
if ( mode == Quantile )