Skip to content

Commit

Permalink
Merge pull request #1075 from Oslandia/expressions_in_symbol_rotation…
Browse files Browse the repository at this point in the history
…_and_scale_for_pr

[FEATURE] allow for expressions in symbol rotation and scale
  • Loading branch information
wonder-sk committed Jan 23, 2014
2 parents 467f978 + c7ccdc9 commit 3568fe7
Show file tree
Hide file tree
Showing 19 changed files with 340 additions and 314 deletions.
4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgscategorizedsymbolrendererv2.sip
Expand Up @@ -123,5 +123,9 @@ class QgsCategorizedSymbolRendererV2 : QgsFeatureRendererV2
void rebuildHash();

QgsSymbolV2* symbolForValue( QVariant value );

private:
QgsCategorizedSymbolRendererV2( const QgsCategorizedSymbolRendererV2 & );
QgsCategorizedSymbolRendererV2 & operator=( const QgsCategorizedSymbolRendererV2 & );
};

4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgsgraduatedsymbolrendererv2.sip
Expand Up @@ -147,4 +147,8 @@ class QgsGraduatedSymbolRendererV2 : QgsFeatureRendererV2

protected:
QgsSymbolV2* symbolForValue( double value );

private:
QgsGraduatedSymbolRendererV2( const QgsGraduatedSymbolRendererV2 & );
QgsGraduatedSymbolRendererV2 & operator=( const QgsGraduatedSymbolRendererV2 & );
};
4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgspointdisplacementrenderer.sip
Expand Up @@ -65,4 +65,8 @@ class QgsPointDisplacementRenderer : QgsFeatureRendererV2

void setTolerance( double t );
double tolerance() const;

private:
QgsPointDisplacementRenderer( const QgsPointDisplacementRenderer & );
QgsPointDisplacementRenderer & operator=( const QgsPointDisplacementRenderer & );
};
4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgsrendererv2.sip
Expand Up @@ -170,4 +170,8 @@ class QgsFeatureRendererV2
static const unsigned char* _getPolygon( QPolygonF& pts, QList<QPolygonF>& holes, QgsRenderContext& context, const unsigned char* wkb );

void setScaleMethodToSymbol( QgsSymbolV2* symbol, int scaleMethod );
private:
QgsFeatureRendererV2( const QgsFeatureRendererV2 & );
QgsFeatureRendererV2 & operator=( const QgsFeatureRendererV2 & );

};
4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgsrulebasedrendererv2.sip
Expand Up @@ -201,4 +201,8 @@ class QgsRuleBasedRendererV2 : QgsFeatureRendererV2
static void refineRuleRanges( QgsRuleBasedRendererV2::Rule* initialRule, QgsGraduatedSymbolRendererV2* r );
//! take a rule and create a list of new rules with intervals of scales given by the passed scale denominators
static void refineRuleScales( QgsRuleBasedRendererV2::Rule* initialRule, QList<int> scales );

private:
QgsRuleBasedRendererV2( const QgsRuleBasedRendererV2 & );
QgsRuleBasedRendererV2 & operator=( const QgsRuleBasedRendererV2 & );
};
4 changes: 4 additions & 0 deletions python/core/symbology-ng/qgssinglesymbolrendererv2.sip
Expand Up @@ -60,4 +60,8 @@ class QgsSingleSymbolRendererV2 : QgsFeatureRendererV2
//! return a list of item text / symbol
//! @note: this method was added in version 1.5
// virtual QgsLegendSymbolList legendSymbolItems();

private:
QgsSingleSymbolRendererV2( const QgsSingleSymbolRendererV2 & );
QgsSingleSymbolRendererV2 & operator=( const QgsSingleSymbolRendererV2 & );
};
1 change: 0 additions & 1 deletion src/core/qgis.h
Expand Up @@ -415,5 +415,4 @@ typedef unsigned long long qgssize;
# define QGISEXTERN extern "C"
#endif
#endif

#endif
145 changes: 55 additions & 90 deletions src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
Expand Up @@ -29,39 +29,35 @@
#include <QSettings> // for legend

QgsRendererCategoryV2::QgsRendererCategoryV2()
: mValue(), mSymbol( 0 ), mLabel()
{
}

QgsRendererCategoryV2::QgsRendererCategoryV2( QVariant value, QgsSymbolV2* symbol, QString label )
: mValue( value ), mSymbol( symbol ), mLabel( label )
: mValue( value )
, mSymbol( symbol )
, mLabel( label )
{
}

QgsRendererCategoryV2::QgsRendererCategoryV2( const QgsRendererCategoryV2& cat )
: mValue( cat.mValue ), mSymbol( 0 ), mLabel( cat.mLabel )
: mValue( cat.mValue )
, mSymbol( cat.mSymbol.data() ? cat.mSymbol->clone() : NULL )
, mLabel( cat.mLabel )
{
if ( cat.mSymbol )
{
mSymbol = cat.mSymbol->clone();
}
}

QgsRendererCategoryV2::~QgsRendererCategoryV2()
// copy+swap idion, the copy is done through the 'pass by value'
QgsRendererCategoryV2& QgsRendererCategoryV2::operator=( QgsRendererCategoryV2 cat )
{
delete mSymbol;
swap( cat );
return *this;
}

QgsRendererCategoryV2& QgsRendererCategoryV2::operator=( const QgsRendererCategoryV2 & cat )
void QgsRendererCategoryV2::swap( QgsRendererCategoryV2 & cat )
{
mValue = cat.mValue;
mLabel = cat.mLabel;
mSymbol = 0;
if ( cat.mSymbol )
{
mSymbol = cat.mSymbol->clone();
}
return *this;
std::swap( mValue, cat.mValue );
std::swap( mSymbol, cat.mSymbol );
std::swap( mLabel, cat.mLabel );
}

QVariant QgsRendererCategoryV2::value() const
Expand All @@ -71,7 +67,7 @@ QVariant QgsRendererCategoryV2::value() const

QgsSymbolV2* QgsRendererCategoryV2::symbol() const
{
return mSymbol;
return mSymbol.data();
}

QString QgsRendererCategoryV2::label() const
Expand All @@ -86,10 +82,7 @@ void QgsRendererCategoryV2::setValue( const QVariant &value )

void QgsRendererCategoryV2::setSymbol( QgsSymbolV2* s )
{
if ( mSymbol == s )
return;
delete mSymbol;
mSymbol = s;
if ( mSymbol.data() != s ) mSymbol.reset( s );
}

void QgsRendererCategoryV2::setLabel( const QString &label )
Expand All @@ -104,7 +97,7 @@ QString QgsRendererCategoryV2::dump() const

void QgsRendererCategoryV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
{
if ( !mSymbol || props.value( "attribute", "" ).isEmpty() )
if ( !mSymbol.data() || props.value( "attribute", "" ).isEmpty() )
return;

QString attrName = props[ "attribute" ];
Expand Down Expand Up @@ -135,16 +128,11 @@ void QgsRendererCategoryV2::toSld( QDomDocument &doc, QDomElement &element, QgsS
///////////////////

QgsCategorizedSymbolRendererV2::QgsCategorizedSymbolRendererV2( QString attrName, QgsCategoryList categories )
: QgsFeatureRendererV2( "categorizedSymbol" ),
mAttrName( attrName ),
mCategories( categories ),
mSourceSymbol( NULL ),
mSourceColorRamp( NULL ),
mInvertedColorRamp( false ),
mScaleMethod( DEFAULT_SCALE_METHOD ),
mExpression( 0 ),
mRotationFieldIdx( -1 ),
mSizeScaleFieldIdx( -1 )
: QgsFeatureRendererV2( "categorizedSymbol" )
, mAttrName( attrName )
, mCategories( categories )
, mInvertedColorRamp( false )
, mScaleMethod( DEFAULT_SCALE_METHOD )
{
for ( int i = 0; i < mCategories.count(); ++i )
{
Expand All @@ -160,9 +148,6 @@ QgsCategorizedSymbolRendererV2::QgsCategorizedSymbolRendererV2( QString attrName

QgsCategorizedSymbolRendererV2::~QgsCategorizedSymbolRendererV2()
{
mCategories.clear(); // this should also call destructors of symbols
delete mSourceSymbol;
delete mSourceColorRamp;
}

void QgsCategorizedSymbolRendererV2::rebuildHash()
Expand Down Expand Up @@ -202,7 +187,7 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu
QVariant value;
if ( mAttrNum == -1 )
{
Q_ASSERT( mExpression );
Q_ASSERT( mExpression.data() );
value = mExpression->evaluate( &feature );
}
else
Expand All @@ -218,16 +203,12 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu
return symbolForValue( QVariant( "" ) );
}

if ( mRotationFieldIdx == -1 && mSizeScaleFieldIdx == -1 )
if ( !mRotation.data() && !mSizeScale.data() )
return symbol; // no data-defined rotation/scaling - just return the symbol

// find out rotation, size scale
double rotation = 0;
double sizeScale = 1;
if ( mRotationFieldIdx != -1 )
rotation = attrs[mRotationFieldIdx].toDouble();
if ( mSizeScaleFieldIdx != -1 )
sizeScale = attrs[mSizeScaleFieldIdx].toDouble();
const double rotation = mRotation.data() ? mRotation->evaluate( feature ).toDouble() : 0;
const double sizeScale = mSizeScale.data() ? mSizeScale->evaluate( feature ).toDouble() : 1.;

// take a temporary symbol (or create it if doesn't exist)
QgsSymbolV2* tempSymbol = mTempSymbols[attrs[mAttrNum].toString()];
Expand All @@ -236,17 +217,14 @@ QgsSymbolV2* QgsCategorizedSymbolRendererV2::symbolForFeature( QgsFeature& featu
if ( tempSymbol->type() == QgsSymbolV2::Marker )
{
QgsMarkerSymbolV2* markerSymbol = static_cast<QgsMarkerSymbolV2*>( tempSymbol );
if ( mRotationFieldIdx != -1 )
markerSymbol->setAngle( rotation );
if ( mSizeScaleFieldIdx != -1 )
markerSymbol->setSize( sizeScale * static_cast<QgsMarkerSymbolV2*>( symbol )->size() );
if ( mRotation.data() ) markerSymbol->setAngle( rotation );
markerSymbol->setSize( sizeScale * static_cast<QgsMarkerSymbolV2*>( symbol )->size() );
markerSymbol->setScaleMethod( mScaleMethod );
}
else if ( tempSymbol->type() == QgsSymbolV2::Line )
{
QgsLineSymbolV2* lineSymbol = static_cast<QgsLineSymbolV2*>( tempSymbol );
if ( mSizeScaleFieldIdx != -1 )
lineSymbol->setWidth( sizeScale * static_cast<QgsLineSymbolV2*>( symbol )->width() );
lineSymbol->setWidth( sizeScale * static_cast<QgsLineSymbolV2*>( symbol )->width() );
}

return tempSymbol;
Expand Down Expand Up @@ -370,23 +348,20 @@ void QgsCategorizedSymbolRendererV2::startRender( QgsRenderContext& context, con
mAttrNum = vlayer ? vlayer->fieldNameIndex( mAttrName ) : -1;
if ( mAttrNum == -1 )
{
mExpression = new QgsExpression( mAttrName );
mExpression.reset( new QgsExpression( mAttrName ) );
mExpression->prepare( vlayer->pendingFields() );
}

mRotationFieldIdx = ( mRotationField.isEmpty() ? -1 : vlayer->fieldNameIndex( mRotationField ) );
mSizeScaleFieldIdx = ( mSizeScaleField.isEmpty() ? -1 : vlayer->fieldNameIndex( mSizeScaleField ) );

QgsCategoryList::iterator it = mCategories.begin();
for ( ; it != mCategories.end(); ++it )
{
it->symbol()->startRender( context, vlayer );

if ( mRotationFieldIdx != -1 || mSizeScaleFieldIdx != -1 )
if ( mRotation.data() || mSizeScale.data() )
{
QgsSymbolV2* tempSymbol = it->symbol()->clone();
tempSymbol->setRenderHints(( mRotationFieldIdx != -1 ? QgsSymbolV2::DataDefinedRotation : 0 ) |
( mSizeScaleFieldIdx != -1 ? QgsSymbolV2::DataDefinedSizeScale : 0 ) );
tempSymbol->setRenderHints(( mRotation.data() ? QgsSymbolV2::DataDefinedRotation : 0 ) |
( mSizeScale.data() ? QgsSymbolV2::DataDefinedSizeScale : 0 ) );
tempSymbol->startRender( context, vlayer );
mTempSymbols[ it->value().toString()] = tempSymbol;
}
Expand All @@ -408,25 +383,15 @@ void QgsCategorizedSymbolRendererV2::stopRender( QgsRenderContext& context )
delete it2.value();
}
mTempSymbols.clear();
delete mExpression;
mExpression.reset();
}

QList<QString> QgsCategorizedSymbolRendererV2::usedAttributes()
{
QSet<QString> attributes;
QgsExpression exp( mAttrName );
foreach ( QString attr, exp.referencedColumns() )
{
attributes << attr;
}
if ( !mRotationField.isEmpty() )
{
attributes.insert( mRotationField );
}
if ( !mSizeScaleField.isEmpty() )
{
attributes.insert( mSizeScaleField );
}
QSet<QString> attributes( exp.referencedColumns().toSet() );
if ( mRotation.data() ) attributes.unite( mRotation->referencedColumns().toSet() );
if ( mSizeScale.data() ) attributes.unite( mSizeScale->referencedColumns().toSet() );

QgsCategoryList::const_iterator catIt = mCategories.constBegin();
for ( ; catIt != mCategories.constEnd(); ++catIt )
Expand All @@ -451,9 +416,9 @@ QString QgsCategorizedSymbolRendererV2::dump() const
QgsFeatureRendererV2* QgsCategorizedSymbolRendererV2::clone()
{
QgsCategorizedSymbolRendererV2* r = new QgsCategorizedSymbolRendererV2( mAttrName, mCategories );
if ( mSourceSymbol )
if ( mSourceSymbol.data() )
r->setSourceSymbol( mSourceSymbol->clone() );
if ( mSourceColorRamp )
if ( mSourceColorRamp.data() )
{
r->setSourceColorRamp( mSourceColorRamp->clone() );
r->setInvertedColorRamp( mInvertedColorRamp );
Expand All @@ -469,10 +434,10 @@ void QgsCategorizedSymbolRendererV2::toSld( QDomDocument &doc, QDomElement &elem
{
QgsStringMap props;
props[ "attribute" ] = mAttrName;
if ( !mRotationField.isEmpty() )
props[ "angle" ] = QString( mRotationField ).append( "\"" ).prepend( "\"" );
if ( !mSizeScaleField.isEmpty() )
props[ "scale" ] = QString( mSizeScaleField ).append( "\"" ).prepend( "\"" );
if ( mRotation.data() )
props[ "angle" ] = mRotation->expression();
if ( mSizeScale.data() )
props[ "scale" ] = mSizeScale->expression();

// create a Rule for each range
for ( QgsCategoryList::const_iterator it = mCategories.constBegin(); it != mCategories.constEnd(); ++it )
Expand Down Expand Up @@ -597,30 +562,32 @@ QDomElement QgsCategorizedSymbolRendererV2::save( QDomDocument& doc )
rendererElem.appendChild( symbolsElem );

// save source symbol
if ( mSourceSymbol )
if ( mSourceSymbol.data() )
{
QgsSymbolV2Map sourceSymbols;
sourceSymbols.insert( "0", mSourceSymbol );
sourceSymbols.insert( "0", mSourceSymbol.data() );
QDomElement sourceSymbolElem = QgsSymbolLayerV2Utils::saveSymbols( sourceSymbols, "source-symbol", doc );
rendererElem.appendChild( sourceSymbolElem );
}

// save source color ramp
if ( mSourceColorRamp )
if ( mSourceColorRamp.data() )
{
QDomElement colorRampElem = QgsSymbolLayerV2Utils::saveColorRamp( "[source]", mSourceColorRamp, doc );
QDomElement colorRampElem = QgsSymbolLayerV2Utils::saveColorRamp( "[source]", mSourceColorRamp.data(), doc );
rendererElem.appendChild( colorRampElem );
QDomElement invertedElem = doc.createElement( "invertedcolorramp" );
invertedElem.setAttribute( "value", mInvertedColorRamp );
rendererElem.appendChild( invertedElem );
}

QDomElement rotationElem = doc.createElement( "rotation" );
rotationElem.setAttribute( "field", mRotationField );
if ( mRotation.data() )
rotationElem.setAttribute( "field", mRotation->expression() );
rendererElem.appendChild( rotationElem );

QDomElement sizeScaleElem = doc.createElement( "sizescale" );
sizeScaleElem.setAttribute( "field", mSizeScaleField );
if ( mSizeScale.data() )
sizeScaleElem.setAttribute( "field", mSizeScale->expression() );
sizeScaleElem.setAttribute( "scalemethod", QgsSymbolLayerV2Utils::encodeScaleMethod( mScaleMethod ) );
rendererElem.appendChild( sizeScaleElem );

Expand Down Expand Up @@ -673,22 +640,20 @@ QgsLegendSymbolList QgsCategorizedSymbolRendererV2::legendSymbolItems( double sc

QgsSymbolV2* QgsCategorizedSymbolRendererV2::sourceSymbol()
{
return mSourceSymbol;
return mSourceSymbol.data();
}
void QgsCategorizedSymbolRendererV2::setSourceSymbol( QgsSymbolV2* sym )
{
delete mSourceSymbol;
mSourceSymbol = sym;
mSourceSymbol.reset( sym );
}

QgsVectorColorRampV2* QgsCategorizedSymbolRendererV2::sourceColorRamp()
{
return mSourceColorRamp;
return mSourceColorRamp.data();
}
void QgsCategorizedSymbolRendererV2::setSourceColorRamp( QgsVectorColorRampV2* ramp )
{
delete mSourceColorRamp;
mSourceColorRamp = ramp;
mSourceColorRamp.reset( ramp );
}

void QgsCategorizedSymbolRendererV2::updateSymbols( QgsSymbolV2 * sym )
Expand Down

0 comments on commit 3568fe7

Please sign in to comment.