Skip to content

Commit

Permalink
Data defined properties for svg marker
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Mar 31, 2013
1 parent 9acdcb7 commit ef35c8b
Show file tree
Hide file tree
Showing 5 changed files with 416 additions and 68 deletions.
281 changes: 275 additions & 6 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Expand Up @@ -895,7 +895,9 @@ void QgsSimpleMarkerSymbolLayerV2::prepareExpressions( const QgsVectorLayer* vl
//////////


QgsSvgMarkerSymbolLayerV2::QgsSvgMarkerSymbolLayerV2( QString name, double size, double angle )
QgsSvgMarkerSymbolLayerV2::QgsSvgMarkerSymbolLayerV2( QString name, double size, double angle ): mSizeExpression( 0 ),
mOutlineWidthExpression( 0 ), mAngleExpression( 0 ), mOffsetExpression( 0 ), mNameExpression( 0 ), mFillExpression( 0 ),
mOutlineExpression( 0 )
{
mPath = QgsSymbolLayerV2Utils::symbolNameToPath( name );
mSize = size;
Expand Down Expand Up @@ -958,6 +960,36 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::create( const QgsStringMap& props )
m->setOutlineWidth( props["outline-width"].toDouble() );
if ( props.contains( "outline_width_unit" ) )
m->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( props["outline_width_unit"] ) );

//data defined properties
if ( props.contains( "size_expression" ) )
{
m->setDataDefinedProperty( "size", props["size_expression"] );
}
if ( props.contains( "outline-width_expression" ) )
{
m->setDataDefinedProperty( "outline-width", props["outline-width_expression"] );
}
if ( props.contains( "angle_expression" ) )
{
m->setDataDefinedProperty( "angle", props["angle_expression"] );
}
if ( props.contains( "offset_expression" ) )
{
m->setDataDefinedProperty( "offset", props["offset_expression"] );
}
if ( props.contains( "name_expression" ) )
{
m->setDataDefinedProperty( "name", props["name_expression"] );
}
if ( props.contains( "fill_expression" ) )
{
m->setDataDefinedProperty( "fill", props["fill_expression"] );
}
if ( props.contains( "outline_expression" ) )
{
m->setDataDefinedProperty( "outline", props["outline_expression"] );
}
return m;
}

Expand Down Expand Up @@ -992,6 +1024,7 @@ void QgsSvgMarkerSymbolLayerV2::startRender( QgsSymbolV2RenderContext& context )
{
mOrigSize = mSize; // save in case the size would be data defined
Q_UNUSED( context );
prepareExpressions( context.layer() );
}

void QgsSvgMarkerSymbolLayerV2::stopRender( QgsSymbolV2RenderContext& context )
Expand All @@ -1007,7 +1040,12 @@ void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Re
return;
}

double size = mSize * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit );
double size = mSize;
if ( mSizeExpression )
{
size = mSizeExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
}
size *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mSizeUnit );
//don't render symbols with size below one or above 10,000 pixels
if (( int )size < 1 || 10000.0 < size )
{
Expand All @@ -1019,14 +1057,19 @@ void QgsSvgMarkerSymbolLayerV2::renderPoint( const QPointF& point, QgsSymbolV2Re
double offsetY = mOffset.y() * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit );
QPointF outputOffset( offsetX, offsetY );

if ( mAngle )
outputOffset = _rotatedOffset( outputOffset, mAngle );
double angle = mAngle;
if ( mAngleExpression )
{
angle = mAngleExpression->evaluate( const_cast<QgsFeature*>( context.feature() ) ).toDouble();
}
if ( angle )
outputOffset = _rotatedOffset( outputOffset, angle );
p->translate( point + outputOffset );

bool rotated = !doubleNear( mAngle, 0 );
bool rotated = !doubleNear( angle, 0 );
bool drawOnScreen = doubleNear( context.renderContext().rasterScaleFactor(), 1.0, 0.1 );
if ( rotated )
p->rotate( mAngle );
p->rotate( angle );

bool fitsInCache = true;
bool usePict = true;
Expand Down Expand Up @@ -1102,6 +1145,36 @@ QgsStringMap QgsSvgMarkerSymbolLayerV2::properties() const
map["outline"] = mOutlineColor.name();
map["outline-width"] = QString::number( mOutlineWidth );
map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );

//data defined properties
if ( mSizeExpression )
{
map["size_expression"] = mSizeExpression->dump();
}
if ( mOutlineWidthExpression )
{
map["outline-width_expression"] = mOutlineWidthExpression->dump();
}
if ( mAngleExpression )
{
map["angle_expression"] = mAngleExpression->dump();
}
if ( mOffsetExpression )
{
map["offset_expression"] = mOffsetExpression->dump();
}
if ( mNameExpression )
{
map["name_expression"] = mNameExpression->dump();
}
if ( mFillExpression )
{
map["fill_expression"] = mFillExpression->dump();
}
if ( mOutlineExpression )
{
map["outline_expression"] = mOutlineExpression->dump();
}
return map;
}

Expand All @@ -1115,9 +1188,205 @@ QgsSymbolLayerV2* QgsSvgMarkerSymbolLayerV2::clone() const
m->setOffset( mOffset );
m->setOffsetUnit( mOffsetUnit );
m->setSizeUnit( mSizeUnit );

//data defined properties
if ( mSizeExpression )
{
m->setDataDefinedProperty( "size", mSizeExpression->dump() );
}
if ( mOutlineWidthExpression )
{
m->setDataDefinedProperty( "outline-width", mOutlineWidthExpression->dump() );
}
if ( mAngleExpression )
{
m->setDataDefinedProperty( "angle", mAngleExpression->dump() );
}
if ( mOffsetExpression )
{
m->setDataDefinedProperty( "offset", mOffsetExpression->dump() );
}
if ( mNameExpression )
{
m->setDataDefinedProperty( "name", mNameExpression->dump() );
}
if ( mFillExpression )
{
m->setDataDefinedProperty( "fill", mFillExpression->dump() );
}
if ( mOutlineExpression )
{
m->setDataDefinedProperty( "outline", mOutlineExpression->dump() );
}

return m;
}

const QgsExpression* QgsSvgMarkerSymbolLayerV2::dataDefinedProperty( const QString& property ) const
{
if ( property == "size" )
{
return mSizeExpression;
}
else if ( property == "outline-width" )
{
return mOutlineWidthExpression;
}
else if ( property == "angle" )
{
return mAngleExpression;
}
else if ( property == "offset" )
{
return mOffsetExpression;
}
else if ( property == "name" )
{
return mNameExpression;
}
else if ( property == "fill" )
{
return mFillExpression;
}
else if ( property == "outline" )
{
return mOutlineExpression;
}
return 0;
}

QString QgsSvgMarkerSymbolLayerV2::dataDefinedPropertyString( const QString& property ) const
{
const QgsExpression* ex = dataDefinedProperty( property );
return ( ex ? ex->dump() : QString() );
}

void QgsSvgMarkerSymbolLayerV2::setDataDefinedProperty( const QString& property, const QString& expressionString )
{
if ( property == "size" )
{
delete mSizeExpression; mSizeExpression = new QgsExpression( expressionString );
}
else if ( property == "outline-width" )
{
delete mOutlineWidthExpression; mOutlineWidthExpression = new QgsExpression( expressionString );
}
else if ( property == "angle" )
{
delete mAngleExpression; mAngleExpression = new QgsExpression( expressionString );
}
else if ( property == "offset" )
{
delete mOffsetExpression; mOffsetExpression = new QgsExpression( expressionString );
}
else if ( property == "name" )
{
delete mNameExpression; mNameExpression = new QgsExpression( expressionString );
}
else if ( property == "fill" )
{
delete mFillExpression; mFillExpression = new QgsExpression( expressionString );
}
else if ( property == "outline" )
{
delete mOutlineExpression; mOutlineExpression = new QgsExpression( expressionString );
}
}

void QgsSvgMarkerSymbolLayerV2::removeDataDefinedProperty( const QString& property )
{
if ( property == "size" )
{
delete mSizeExpression; mSizeExpression = 0;
}
else if ( property == "outline-width" )
{
delete mOutlineWidthExpression; mOutlineWidthExpression = 0;
}
else if ( property == "angle" )
{
delete mAngleExpression; mAngleExpression = 0;
}
else if ( property == "offset" )
{
delete mOffsetExpression; mOffsetExpression = 0;
}
else if ( property == "name" )
{
delete mNameExpression; mNameExpression = 0;
}
else if ( property == "fill" )
{
delete mFillExpression; mFillExpression = 0;
}
else if ( property == "outline" )
{
delete mOutlineExpression; mOutlineExpression = 0;
}
}

void QgsSvgMarkerSymbolLayerV2::removeDataDefinedProperties()
{
delete mSizeExpression; mSizeExpression = 0;
delete mOutlineWidthExpression; mOutlineWidthExpression = 0;
delete mAngleExpression; mAngleExpression = 0;
delete mOffsetExpression; mOffsetExpression = 0;
delete mNameExpression; mNameExpression = 0;
delete mFillExpression; mFillExpression = 0;
delete mOutlineExpression; mOutlineExpression = 0;
}

QSet<QString> QgsSvgMarkerSymbolLayerV2::usedAttributes() const
{
QSet<QString> attributes;

//add data defined attributes
QStringList columns;
if ( mSizeExpression )
columns.append( mSizeExpression->referencedColumns() );
if ( mOutlineWidthExpression )
columns.append( mOutlineWidthExpression->referencedColumns() );
if ( mAngleExpression )
columns.append( mAngleExpression->referencedColumns() );
if ( mOffsetExpression )
columns.append( mOffsetExpression->referencedColumns() );
if ( mNameExpression )
columns.append( mNameExpression->referencedColumns() );
if ( mFillExpression )
columns.append( mFillExpression->referencedColumns() );
if ( mOutlineExpression )
columns.append( mOutlineExpression->referencedColumns() );

QStringList::const_iterator it = columns.constBegin();
for ( ; it != columns.constEnd(); ++it )
{
attributes.insert( *it );
}
return attributes;
}

void QgsSvgMarkerSymbolLayerV2::prepareExpressions( const QgsVectorLayer* vl )
{
if ( !vl )
{
return;
}

const QgsFields& fields = vl->pendingFields();
if ( mSizeExpression )
mSizeExpression->prepare( fields );
if ( mOutlineWidthExpression )
mOutlineWidthExpression->prepare( fields );
if ( mAngleExpression )
mAngleExpression->prepare( fields );
if ( mOffsetExpression )
mOffsetExpression->prepare( fields );
if ( mNameExpression )
mNameExpression->prepare( fields );
if ( mFillExpression )
mFillExpression->prepare( fields );
}

void QgsSvgMarkerSymbolLayerV2::setOutputUnit( QgsSymbolV2::OutputUnit unit )
{
mSizeUnit = unit;
Expand Down
19 changes: 19 additions & 0 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.h
Expand Up @@ -166,6 +166,14 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
void setOutputUnit( QgsSymbolV2::OutputUnit unit );
QgsSymbolV2::OutputUnit outputUnit() const;

const QgsExpression* dataDefinedProperty( const QString& property ) const;
QString dataDefinedPropertyString( const QString& property ) const;
void setDataDefinedProperty( const QString& property, const QString& expressionString );
void removeDataDefinedProperty( const QString& property );
void removeDataDefinedProperties();

QSet<QString> usedAttributes() const;

protected:
QString mPath;

Expand All @@ -176,6 +184,17 @@ class CORE_EXPORT QgsSvgMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2
double mOutlineWidth;
QgsSymbolV2::OutputUnit mOutlineWidthUnit;
double mOrigSize;

QgsExpression* mSizeExpression;
QgsExpression* mOutlineWidthExpression;
QgsExpression* mAngleExpression;
QgsExpression* mOffsetExpression;
QgsExpression* mNameExpression;
QgsExpression* mFillExpression;
QgsExpression* mOutlineExpression;

private:
void prepareExpressions( const QgsVectorLayer* vl );
};


Expand Down

0 comments on commit ef35c8b

Please sign in to comment.