Skip to content

Commit

Permalink
Fix graduated classifications for joined fields
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk@15389 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Mar 8, 2011
1 parent caa0cae commit 3717e57
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 41 deletions.
8 changes: 8 additions & 0 deletions python/core/qgsvectorlayer.sip
Expand Up @@ -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() */
Expand Down
62 changes: 26 additions & 36 deletions src/app/qgsgraduatedsymboldialog.cpp
Expand Up @@ -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;

Expand All @@ -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
Expand Down Expand Up @@ -500,30 +495,25 @@ int QgsGraduatedSymbolDialog::quantilesFromVectorLayer( std::list<double>& resul
{
if ( mVectorLayer )
{
QgsVectorDataProvider* provider = mVectorLayer->dataProvider();

if ( provider )
std::vector<double> attributeValues( mVectorLayer->featureCount() );
QgsAttributeList attList;
attList.push_back( attributeIndex );
QgsFeature currentFeature;
QgsAttributeMap currentAttributeMap;
double currentValue;
int index = 0;

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;
}
Expand Down
108 changes: 108 additions & 0 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -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 );
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsvectorlayer.h
Expand Up @@ -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() */
Expand Down
9 changes: 4 additions & 5 deletions src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
Expand Up @@ -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;
Expand All @@ -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 )
Expand Down

0 comments on commit 3717e57

Please sign in to comment.