Skip to content
Permalink
Browse files

creation of a convertToRuleBasedRenderer() function

  • Loading branch information
leyan committed Sep 9, 2014
1 parent 5c5deec commit 85172491f341720d5387924a4bec39e07b7cc82e
@@ -19,6 +19,7 @@
#include "qgssymbolv2.h"
#include "qgssymbollayerv2utils.h"
#include "qgsvectorcolorrampv2.h"
#include "qgsrulebasedrendererv2.h"

#include "qgsfeature.h"
#include "qgsvectorlayer.h"
@@ -758,3 +759,94 @@ void QgsCategorizedSymbolRendererV2::checkLegendSymbolItem( QString key, bool st
}

QgsMarkerSymbolV2 QgsCategorizedSymbolRendererV2::sSkipRender;

QgsRuleBasedRendererV2* QgsCategorizedSymbolRendererV2::convertToRuleBasedRenderer()
{
QgsRuleBasedRendererV2::Rule* rootrule = new QgsRuleBasedRendererV2::Rule( NULL );

QString expression;
QString sizeExpression;
QString value;
for ( int i = 0; i < mCategories.size();++i )
{
QgsRuleBasedRendererV2::Rule* rule = new QgsRuleBasedRendererV2::Rule( NULL );

rule->setLabel( mCategories[i].label() );

//We first define the rule corresponding to the category
//If the value is a number, we can use it directly, otherwise we need to quote it in the rule
if ( QVariant( mCategories[i].value() ).convert( QVariant::Double ) )
{
value = mCategories[i].value().toString();
}
else
{
value = "'" + mCategories[i].value().toString() + "'";
}

//An empty category is equivalent to the ELSE keyword
if ( value == "''" )
expression = "ELSE";
else
expression = classAttribute() + " = " + value;
rule->setFilterExpression( expression );

//Then we construct an equivalent symbol.
//Ideally we could simply copy the symbol, but the categorized renderer allows a separate interface to specify
//data dependent area and rotation, so we need to convert these to obtain the same rendering

QgsSymbolV2* origSymbol = mCategories[i].symbol()->clone();

switch ( origSymbol->type() )
{
case QgsSymbolV2::Marker:
for ( int j = 0; j < origSymbol->symbolLayerCount();++j )
{
QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( origSymbol->symbolLayer( j ) );
if ( mSizeScale.data() )
{
sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField() );
msl->setDataDefinedProperty( "size", sizeExpression );
}
if ( mRotation.data() )
{
msl->setDataDefinedProperty( "angle", rotationField() );
}
}
break;
case QgsSymbolV2::Line:
if ( mSizeScale.data() )
{
for ( int j = 0; j < origSymbol->symbolLayerCount();++j )
{
if ( origSymbol->symbolLayer( j )->layerType() == "SimpleLine" )
{
QgsLineSymbolLayerV2* lsl = static_cast<QgsLineSymbolLayerV2*>( origSymbol->symbolLayer( j ) );
sizeExpression = QString( "%1*(%2)" ).arg( lsl->width() ).arg( sizeScaleField() );
lsl->setDataDefinedProperty( "width", sizeExpression );
}
if ( origSymbol->symbolLayer( j )->layerType() == "MarkerLine" )
{
QgsSymbolV2* marker = origSymbol->symbolLayer( j )->subSymbol();
for ( int k = 0; k < marker->symbolLayerCount();++k )
{
QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( marker->symbolLayer( k ) );
sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField() );
msl->setDataDefinedProperty( "size", sizeExpression );
}
}
}
}
break;
default:
break;
}

rule->setSymbol( origSymbol );

rootrule->appendChild( rule );
}

return new QgsRuleBasedRendererV2( rootrule );

}
@@ -24,6 +24,7 @@

class QgsVectorColorRampV2;
class QgsVectorLayer;
class QgsRuleBasedRendererV2;

/* \brief categorized renderer */
class CORE_EXPORT QgsRendererCategoryV2
@@ -165,6 +166,7 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
//! @note added in 2.0
QgsSymbolV2::ScaleMethod scaleMethod() const { return mScaleMethod; }


//! items of symbology items in legend should be checkable
// @note added in 2.5
virtual bool legendSymbolItemsCheckable() const;
@@ -181,6 +183,10 @@ class CORE_EXPORT QgsCategorizedSymbolRendererV2 : public QgsFeatureRendererV2
//! @note added in 2.6
virtual QString legendClassificationAttribute() const { return classAttribute(); }

//! convert the renderer to a rule based renderer with equivalent rules
//! @note added in 2.5
virtual QgsRuleBasedRendererV2* convertToRuleBasedRenderer();

protected:
QString mAttrName;
QgsCategoryList mCategories;
@@ -17,6 +17,7 @@
#include "qgssymbolv2.h"
#include "qgssymbollayerv2utils.h"
#include "qgsvectorcolorrampv2.h"
#include "qgsrulebasedrendererv2.h"

#include "qgsfeature.h"
#include "qgsvectorlayer.h"
@@ -1311,3 +1312,85 @@ void QgsGraduatedSymbolRendererV2::sortByLabel( Qt::SortOrder order )
}
}

QgsRuleBasedRendererV2* QgsGraduatedSymbolRendererV2::convertToRuleBasedRenderer()
{
QgsRuleBasedRendererV2::Rule* rootrule = new QgsRuleBasedRendererV2::Rule( NULL );

QString sizeExpression;
QString expression;
for ( int i = 0; i < mRanges.size();++i )
{
QgsRuleBasedRendererV2::Rule* rule = new QgsRuleBasedRendererV2::Rule( NULL );
rule->setSymbol( mRanges[i].symbol() );
rule->setLabel( mRanges[i].label() );
if ( i == 0 )//The lower boundary of the first range is included, while it is excluded for the others
{
expression = classAttribute() + " >= " + QString::number( mRanges[i].lowerValue(), 'f' ) + " AND " + \
classAttribute() + " <= " + QString::number( mRanges[i].upperValue(), 'f' );
}
else
{
expression = classAttribute() + " > " + QString::number( mRanges[i].lowerValue(), 'f' ) + " AND " + \
classAttribute() + " <= " + QString::number( mRanges[i].upperValue(), 'f' );
}
rule->setFilterExpression( expression );

//Then we construct an equivalent symbol.
//Ideally we could simply copy the symbol, but the graduated renderer allows a separate interface to specify
//data dependent area and rotation, so we need to convert these to obtain the same rendering

QgsSymbolV2* origSymbol = mRanges[i].symbol()->clone();

switch ( origSymbol->type() )
{
case QgsSymbolV2::Marker:
for ( int j = 0; j < origSymbol->symbolLayerCount();++j )
{
QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( origSymbol->symbolLayer( j ) );
if ( mSizeScale.data() )
{
sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField() );
msl->setDataDefinedProperty( "size", sizeExpression );
if ( mRotation.data() )
{
msl->setDataDefinedProperty( "angle", rotationField() );
}
}
}
break;
case QgsSymbolV2::Line:
if ( mSizeScale.data() )
{
for ( int j = 0; j < origSymbol->symbolLayerCount();++j )
{
if ( origSymbol->symbolLayer( j )->layerType() == "SimpleLine" )
{
QgsLineSymbolLayerV2* lsl = static_cast<QgsLineSymbolLayerV2*>( origSymbol->symbolLayer( j ) );
sizeExpression = QString( "%1*(%2)" ).arg( lsl->width() ).arg( sizeScaleField() );
lsl->setDataDefinedProperty( "width", sizeExpression );
}
if ( origSymbol->symbolLayer( j )->layerType() == "MarkerLine" )
{
QgsSymbolV2* marker = origSymbol->symbolLayer( j )->subSymbol();
for ( int k = 0; k < marker->symbolLayerCount();++k )
{
QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( marker->symbolLayer( k ) );
sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField() );
msl->setDataDefinedProperty( "size", sizeExpression );
}
}
}
}
break;
default:
break;
}

rule->setSymbol( origSymbol );

rootrule->appendChild( rule );
}

return new QgsRuleBasedRendererV2( rootrule );

}
@@ -64,6 +64,7 @@ typedef QList<QgsRendererRangeV2> QgsRangeList;

class QgsVectorLayer;
class QgsVectorColorRampV2;
class QgsRuleBasedRenderedV2;

class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
{
@@ -202,6 +203,10 @@ class CORE_EXPORT QgsGraduatedSymbolRendererV2 : public QgsFeatureRendererV2
//! @note added in 2.6
virtual QString legendClassificationAttribute() const { return classAttribute(); }

//! convert the renderer to a rule based renderer with equivalent rules
//! @note added in 2.5
virtual QgsRuleBasedRendererV2* convertToRuleBasedRenderer();

protected:
QString mAttrName;
QgsRangeList mRanges;
@@ -16,6 +16,7 @@
#include "qgsrendererv2.h"
#include "qgssymbolv2.h"
#include "qgssymbollayerv2utils.h"
#include "qgsrulebasedrendererv2.h"

#include "qgssinglesymbolrendererv2.h" // for default renderer

@@ -585,3 +586,8 @@ QgsSymbolV2List QgsFeatureRendererV2::symbolsForFeature( QgsFeature& feat )
if ( s ) lst.append( s );
return lst;
}

QgsRuleBasedRendererV2* QgsFeatureRendererV2::convertToRuleBasedRenderer()
{
return 0;
}
@@ -31,6 +31,7 @@ class QgsRenderContext;
class QgsFeature;
class QgsFields;
class QgsVectorLayer;
class QgsRuleBasedRendererV2;

typedef QMap<QString, QString> QgsStringMap;

@@ -201,6 +202,10 @@ class CORE_EXPORT QgsFeatureRendererV2
//! @note added in 1.9
virtual QgsSymbolV2List symbolsForFeature( QgsFeature& feat );

//! convert the renderer to a rule based renderer with equivalent rules, if possible
//! @note added in 2.5
virtual QgsRuleBasedRendererV2* convertToRuleBasedRenderer();

protected:
QgsFeatureRendererV2( QString type );

@@ -1043,3 +1043,8 @@ QgsSymbolV2List QgsRuleBasedRendererV2::symbolsForFeature( QgsFeature& feat )
{
return mRootRule->symbolsForFeature( feat );
}

QgsRuleBasedRendererV2* QgsRuleBasedRendererV2::convertToRuleBasedRenderer()
{
return this ;
}
@@ -293,6 +293,10 @@ class CORE_EXPORT QgsRuleBasedRendererV2 : public QgsFeatureRendererV2
//! take a rule and create a list of new rules with intervals of scales given by the passed scale denominators
static void refineRuleScales( Rule* initialRule, QList<int> scales );

//! convert the renderer to a rule based renderer with equivalent rules, if possible
//! @note added in 2.5
virtual QgsRuleBasedRendererV2* convertToRuleBasedRenderer();

protected:
//! the root node with hierarchical list of rules
Rule* mRootRule;
@@ -23,6 +23,7 @@
#include "qgsvectorlayer.h"
#include "qgssymbollayerv2.h"
#include "qgsogcutils.h"
#include "qgsrulebasedrendererv2.h"

#include <QDomDocument>
#include <QDomElement>
@@ -373,3 +374,60 @@ QgsLegendSymbolListV2 QgsSingleSymbolRendererV2::legendSymbolItemsV2() const
lst << QgsLegendSymbolItemV2( mSymbol.data(), QString(), 0 );
return lst;
}

QgsRuleBasedRendererV2* QgsSingleSymbolRendererV2::convertToRuleBasedRenderer()
{
//We construct an equivalent symbol for the rule based renderer.
//Ideally we could simply copy the symbol, but the single symbol renderer allows a separate interface to specify
//data dependent area and rotation, so we need to convert these to obtain the same rendering

QString sizeExpression;
QgsSymbolV2* origSymbol = symbol()->clone();

switch ( origSymbol->type() )
{
case QgsSymbolV2::Marker:
for ( int j = 0; j < origSymbol->symbolLayerCount();++j )
{
QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( origSymbol->symbolLayer( j ) );
if ( mSizeScale.data() )
{
sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField() );
msl->setDataDefinedProperty( "size", sizeExpression );
}
if ( mRotation.data() )
{
msl->setDataDefinedProperty( "angle", rotationField() );
}
}
break;
case QgsSymbolV2::Line:
if ( mSizeScale.data() )
{
for ( int j = 0; j < origSymbol->symbolLayerCount();++j )
{
if ( origSymbol->symbolLayer( j )->layerType() == "SimpleLine" )
{
QgsLineSymbolLayerV2* lsl = static_cast<QgsLineSymbolLayerV2*>( origSymbol->symbolLayer( j ) );
sizeExpression = QString( "%1*(%2)" ).arg( lsl->width() ).arg( sizeScaleField() );
lsl->setDataDefinedProperty( "width", sizeExpression );
}
if ( origSymbol->symbolLayer( j )->layerType() == "MarkerLine" )
{
QgsSymbolV2* marker = origSymbol->symbolLayer( j )->subSymbol();
for ( int k = 0; k < marker->symbolLayerCount();++k )
{
QgsMarkerSymbolLayerV2* msl = static_cast<QgsMarkerSymbolLayerV2*>( marker->symbolLayer( k ) );
sizeExpression = QString( "%1*(%2)" ).arg( msl->size() ).arg( sizeScaleField() );
msl->setDataDefinedProperty( "size", sizeExpression );
}
}
}
}
break;
default:
break;
}

return new QgsRuleBasedRendererV2( origSymbol );
}
@@ -21,6 +21,8 @@
#include "qgsexpression.h"
#include <QScopedPointer>

class QgsRuleBasedRenderedV2;

class CORE_EXPORT QgsSingleSymbolRendererV2 : public QgsFeatureRendererV2
{
public:
@@ -82,10 +84,16 @@ class CORE_EXPORT QgsSingleSymbolRendererV2 : public QgsFeatureRendererV2
//! @note not available in python bindings
virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = QString() );


//! Return a list of symbology items for the legend. Better choice than legendSymbolItems().
//! @note added in 2.6
virtual QgsLegendSymbolListV2 legendSymbolItemsV2() const;

//! convert the renderer to a rule based renderer with equivalent rules
//! @note added in 2.5
virtual QgsRuleBasedRendererV2* convertToRuleBasedRenderer();


protected:
QScopedPointer<QgsSymbolV2> mSymbol;
QScopedPointer<QgsExpression> mRotation;

0 comments on commit 8517249

Please sign in to comment.
You can’t perform that action at this time.