QGIS API Documentation  2.17.0-Master (973e4b0)
qgsellipsesymbollayerv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsellipsesymbollayerv2.cpp
3  ---------------------
4  begin : June 2011
5  copyright : (C) 2011 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
16 #include "qgsdxfexport.h"
17 #include "qgsexpression.h"
18 #include "qgsfeature.h"
19 #include "qgsrendercontext.h"
20 #include "qgsvectorlayer.h"
21 #include "qgsdatadefined.h"
22 #include "qgslogger.h"
23 #include "qgsunittypes.h"
24 
25 #include <QPainter>
26 #include <QSet>
27 #include <QDomDocument>
28 #include <QDomElement>
29 
32  , mSymbolName( "circle" )
33  , mSymbolWidth( 4 )
34  , mSymbolWidthUnit( QgsSymbolV2::MM )
35  , mSymbolHeight( 3 )
36  , mSymbolHeightUnit( QgsSymbolV2::MM )
37  , mOutlineColor( Qt::black )
38  , mOutlineStyle( Qt::SolidLine )
39  , mPenJoinStyle( DEFAULT_ELLIPSE_JOINSTYLE )
40  , mOutlineWidth( 0 )
41  , mOutlineWidthUnit( QgsSymbolV2::MM )
42 {
43  mColor = Qt::white;
44  mPen.setColor( mOutlineColor );
45  mPen.setStyle( mOutlineStyle );
46  mPen.setJoinStyle( mPenJoinStyle );
47  mPen.setWidth( 1.0 );
48  mBrush.setColor( mColor );
49  mBrush.setStyle( Qt::SolidPattern );
50  mOffset = QPointF( 0, 0 );
51  mAngle = 0;
52 }
53 
55 {
56 }
57 
59 {
61  if ( properties.contains( "symbol_name" ) )
62  {
63  layer->setSymbolName( properties[ "symbol_name" ] );
64  }
65  if ( properties.contains( "symbol_width" ) )
66  {
67  layer->setSymbolWidth( properties["symbol_width"].toDouble() );
68  }
69  if ( properties.contains( "symbol_width_unit" ) )
70  {
71  layer->setSymbolWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["symbol_width_unit"] ) );
72  }
73  if ( properties.contains( "symbol_width_map_unit_scale" ) )
74  {
75  layer->setSymbolWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["symbol_width_map_unit_scale"] ) );
76  }
77  if ( properties.contains( "symbol_height" ) )
78  {
79  layer->setSymbolHeight( properties["symbol_height"].toDouble() );
80  }
81  if ( properties.contains( "symbol_height_unit" ) )
82  {
83  layer->setSymbolHeightUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["symbol_height_unit"] ) );
84  }
85  if ( properties.contains( "symbol_height_map_unit_scale" ) )
86  {
87  layer->setSymbolHeightMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["symbol_height_map_unit_scale"] ) );
88  }
89  if ( properties.contains( "angle" ) )
90  {
91  layer->setAngle( properties["angle"].toDouble() );
92  }
93  if ( properties.contains( "outline_style" ) )
94  {
95  layer->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( properties["outline_style"] ) );
96  }
97  else if ( properties.contains( "line_style" ) )
98  {
99  layer->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( properties["line_style"] ) );
100  }
101  if ( properties.contains( "joinstyle" ) )
102  {
103  layer->setPenJoinStyle( QgsSymbolLayerV2Utils::decodePenJoinStyle( properties["joinstyle"] ) );
104  }
105  if ( properties.contains( "outline_width" ) )
106  {
107  layer->setOutlineWidth( properties["outline_width"].toDouble() );
108  }
109  else if ( properties.contains( "line_width" ) )
110  {
111  layer->setOutlineWidth( properties["line_width"].toDouble() );
112  }
113  if ( properties.contains( "outline_width_unit" ) )
114  {
115  layer->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["outline_width_unit"] ) );
116  }
117  else if ( properties.contains( "line_width_unit" ) )
118  {
119  layer->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["line_width_unit"] ) );
120  }
121  if ( properties.contains( "outline_width_map_unit_scale" ) )
122  {
123  layer->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["outline_width_map_unit_scale"] ) );
124  }
125  if ( properties.contains( "fill_color" ) )
126  {
127  //pre 2.5 projects used "fill_color"
128  layer->setFillColor( QgsSymbolLayerV2Utils::decodeColor( properties["fill_color"] ) );
129  }
130  else if ( properties.contains( "color" ) )
131  {
132  layer->setFillColor( QgsSymbolLayerV2Utils::decodeColor( properties["color"] ) );
133  }
134  if ( properties.contains( "outline_color" ) )
135  {
136  layer->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( properties["outline_color"] ) );
137  }
138  else if ( properties.contains( "line_color" ) )
139  {
140  layer->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( properties["line_color"] ) );
141  }
142  if ( properties.contains( "size" ) )
143  {
144  layer->setSize( properties["size"].toDouble() );
145  }
146  if ( properties.contains( "size_unit" ) )
147  {
148  layer->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["size_unit"] ) );
149  }
150  if ( properties.contains( "size_map_unit_scale" ) )
151  {
152  layer->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["size_map_unit_scale"] ) );
153  }
154  if ( properties.contains( "offset" ) )
155  {
156  layer->setOffset( QgsSymbolLayerV2Utils::decodePoint( properties["offset"] ) );
157  }
158  if ( properties.contains( "offset_unit" ) )
159  {
160  layer->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["offset_unit"] ) );
161  }
162  if ( properties.contains( "offset_map_unit_scale" ) )
163  {
164  layer->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["offset_map_unit_scale"] ) );
165  }
166  if ( properties.contains( "horizontal_anchor_point" ) )
167  {
168  layer->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( properties[ "horizontal_anchor_point" ].toInt() ) );
169  }
170  if ( properties.contains( "vertical_anchor_point" ) )
171  {
172  layer->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( properties[ "vertical_anchor_point" ].toInt() ) );
173  }
174 
175  //data defined properties
176  layer->restoreDataDefinedProperties( properties );
177 
178  //compatibility with old project file format
179  if ( !properties["width_field"].isEmpty() )
180  {
181  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, new QgsDataDefined( properties["width_field"] ) );
182  }
183  if ( !properties["height_field"].isEmpty() )
184  {
185  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, new QgsDataDefined( properties["height_field"] ) );
186  }
187  if ( !properties["rotation_field"].isEmpty() )
188  {
189  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, new QgsDataDefined( properties["rotation_field"] ) );
190  }
191  if ( !properties["outline_width_field"].isEmpty() )
192  {
193  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, new QgsDataDefined( properties[ "outline_width_field" ] ) );
194  }
195  if ( !properties["fill_color_field"].isEmpty() )
196  {
197  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, new QgsDataDefined( properties["fill_color_field"] ) );
198  }
199  if ( !properties["outline_color_field"].isEmpty() )
200  {
201  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, new QgsDataDefined( properties["outline_color_field"] ) );
202  }
203  if ( !properties["symbol_name_field"].isEmpty() )
204  {
205  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, new QgsDataDefined( properties["symbol_name_field"] ) );
206  }
207 
208  return layer;
209 }
210 
212 {
213  bool ok;
215  {
216  context.setOriginalValueVariable( mOutlineWidth );
217  double width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, mOutlineWidth ).toDouble();
218  width = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), width, mOutlineWidthUnit, mOutlineWidthMapUnitScale );
219  mPen.setWidthF( width );
220  }
222  {
225  if ( ok )
226  {
227  Qt::PenStyle style = QgsSymbolLayerV2Utils::decodePenStyle( styleString );
228  mPen.setStyle( style );
229  }
230  }
232  {
235  if ( ok )
236  {
238  }
239  }
241  {
244  if ( ok )
245  mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
246  }
248  {
251  if ( ok )
252  mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
253  }
254  double scaledWidth = mSymbolWidth;
255  double scaledHeight = mSymbolHeight;
257  {
258  QString symbolName = mSymbolName;
260  {
261  context.setOriginalValueVariable( mSymbolName );
262  symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context, mSymbolName ).toString();
263  }
264  preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() );
265  }
266 
267  //offset and rotation
268  bool hasDataDefinedRotation = false;
269  QPointF offset;
270  double angle = 0;
271  calculateOffsetAndRotation( context, scaledWidth, scaledHeight, hasDataDefinedRotation, offset, angle );
272 
273  QPainter* p = context.renderContext().painter();
274  if ( !p )
275  {
276  return;
277  }
278 
279  QMatrix transform;
280  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
281  if ( !qgsDoubleNear( angle, 0.0 ) )
282  {
283  transform.rotate( angle );
284  }
285 
286  p->setPen( mPen );
287  p->setBrush( mBrush );
288  p->drawPath( transform.map( mPainterPath ) );
289 }
290 
291 
292 void QgsEllipseSymbolLayerV2::calculateOffsetAndRotation( QgsSymbolV2RenderContext& context,
293  double scaledWidth,
294  double scaledHeight,
295  bool& hasDataDefinedRotation,
296  QPointF& offset,
297  double& angle ) const
298 {
299  double offsetX = 0;
300  double offsetY = 0;
301  markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale );
302  offset = QPointF( offsetX, offsetY );
303 
304 //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
305  bool ok = true;
306  angle = mAngle + mLineAngle;
307  bool usingDataDefinedRotation = false;
309  {
310  context.setOriginalValueVariable( angle );
312  usingDataDefinedRotation = ok;
313  }
314 
315  hasDataDefinedRotation = context.renderHints() & QgsSymbolV2::DataDefinedRotation || usingDataDefinedRotation;
316  if ( hasDataDefinedRotation )
317  {
318  // For non-point markers, "dataDefinedRotation" means following the
319  // shape (shape-data defined). For them, "field-data defined" does
320  // not work at all. TODO: if "field-data defined" ever gets implemented
321  // we'll need a way to distinguish here between the two, possibly
322  // using another flag in renderHints()
323  const QgsFeature* f = context.feature();
324  if ( f )
325  {
326  const QgsGeometry *g = f->constGeometry();
327  if ( g && g->type() == QGis::Point )
328  {
329  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
330  angle += m2p.mapRotation();
331  }
332  }
333  }
334 
335  if ( angle )
336  offset = _rotatedOffset( offset, angle );
337 }
338 
340 {
341  return "EllipseMarker";
342 }
343 
345 {
346  QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions
347  if ( !context.feature() || !hasDataDefinedProperties() )
348  {
349  preparePath( mSymbolName, context );
350  }
351  mPen.setColor( mOutlineColor );
352  mPen.setStyle( mOutlineStyle );
353  mPen.setJoinStyle( mPenJoinStyle );
354  mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) );
355  mBrush.setColor( mColor );
356  prepareExpressions( context );
357 }
358 
360 {
361 }
362 
364 {
366  m->setSymbolName( mSymbolName );
367  m->setSymbolWidth( mSymbolWidth );
368  m->setSymbolHeight( mSymbolHeight );
369  m->setOutlineStyle( mOutlineStyle );
370  m->setOffset( mOffset );
373  m->setOutlineStyle( mOutlineStyle );
374  m->setPenJoinStyle( mPenJoinStyle );
375  m->setOutlineWidth( mOutlineWidth );
376  m->setColor( color() );
377  m->setOutlineColor( mOutlineColor );
378  m->setSymbolWidthUnit( mSymbolWidthUnit );
379  m->setSymbolWidthMapUnitScale( mSymbolWidthMapUnitScale );
380  m->setSymbolHeightUnit( mSymbolHeightUnit );
381  m->setSymbolHeightMapUnitScale( mSymbolHeightMapUnitScale );
382  m->setOutlineWidthUnit( mOutlineWidthUnit );
383  m->setOutlineWidthMapUnitScale( mOutlineWidthMapUnitScale );
384  m->setAngle( mAngle );
387 
389  copyPaintEffect( m );
390  return m;
391 }
392 
393 void QgsEllipseSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const
394 {
395  QDomElement symbolizerElem = doc.createElement( "se:PointSymbolizer" );
396  if ( !props.value( "uom", "" ).isEmpty() )
397  symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) );
398  element.appendChild( symbolizerElem );
399 
400  // <Geometry>
401  QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) );
402 
403  writeSldMarker( doc, symbolizerElem, props );
404 }
405 
407 {
408  // <Graphic>
409  QDomElement graphicElem = doc.createElement( "se:Graphic" );
410  element.appendChild( graphicElem );
411 
412  QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, mSymbolName, mColor, mOutlineColor, mOutlineStyle, mOutlineWidth, mSymbolWidth );
413 
414  // store w/h factor in a <VendorOption>
415  double widthHeightFactor = mSymbolWidth / mSymbolHeight;
416  QDomElement factorElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "widthHeightFactor", QString::number( widthHeightFactor ) );
417  graphicElem.appendChild( factorElem );
418 
419  // <Rotation>
421 
422  QString angleFunc = props.value( "angle", "" );
423  if ( angleFunc.isEmpty() ) // symbol has no angle set
424  {
425  if ( ddRotation && ddRotation->isActive() )
426  {
427  angleFunc = ddRotation->useExpression() ? ddRotation->expressionString() : ddRotation->field();
428  }
429  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
430  angleFunc = QString::number( mAngle );
431  }
432  else if ( ddRotation && ddRotation->isActive() )
433  {
434  // the symbol has an angle and the symbol layer have a rotation
435  // property set
436  angleFunc = QString( "%1 + %2" ).arg( angleFunc, ddRotation->useExpression() ? ddRotation->expressionString() : ddRotation->field() );
437  }
438  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
439  {
440  // both the symbol and the symbol layer have angle value set
441  bool ok;
442  double angle = angleFunc.toDouble( &ok );
443  if ( !ok )
444  {
445  // its a string (probably a property name or a function)
446  angleFunc = QString( "%1 + %2" ).arg( angleFunc ).arg( mAngle );
447  }
448  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
449  {
450  // it's a double value
451  angleFunc = QString::number( angle + mAngle );
452  }
453  }
454  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
455 }
456 
458 {
459  QgsDebugMsg( "Entered." );
460 
461  QDomElement graphicElem = element.firstChildElement( "Graphic" );
462  if ( graphicElem.isNull() )
463  return nullptr;
464 
465  QString name = "circle";
466  QColor fillColor, borderColor;
467  double borderWidth, size;
468  double widthHeightFactor = 1.0;
469  Qt::PenStyle borderStyle;
470 
471  QgsStringMap vendorOptions = QgsSymbolLayerV2Utils::getVendorOptionList( graphicElem );
472  for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
473  {
474  if ( it.key() == "widthHeightFactor" )
475  {
476  bool ok;
477  double v = it.value().toDouble( &ok );
478  if ( ok && !qgsDoubleNear( v, 0.0 ) && v > 0 )
479  widthHeightFactor = v;
480  }
481  }
482 
483  if ( !QgsSymbolLayerV2Utils::wellKnownMarkerFromSld( graphicElem, name, fillColor, borderColor, borderStyle, borderWidth, size ) )
484  return nullptr;
485 
486  double angle = 0.0;
487  QString angleFunc;
488  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
489  {
490  bool ok;
491  double d = angleFunc.toDouble( &ok );
492  if ( ok )
493  angle = d;
494  }
495 
497  m->setSymbolName( name );
498  m->setFillColor( fillColor );
499  m->setOutlineColor( borderColor );
500  m->setOutlineStyle( borderStyle );
501  m->setOutlineWidth( borderWidth );
502  m->setSymbolWidth( size );
503  m->setSymbolHeight( size / widthHeightFactor );
504  m->setAngle( angle );
505  return m;
506 }
507 
509 {
510  QgsStringMap map;
511  map["symbol_name"] = mSymbolName;
512  map["symbol_width"] = QString::number( mSymbolWidth );
513  map["symbol_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSymbolWidthUnit );
514  map["symbol_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSymbolWidthMapUnitScale );
515  map["symbol_height"] = QString::number( mSymbolHeight );
516  map["symbol_height_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSymbolHeightUnit );
517  map["symbol_height_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSymbolHeightMapUnitScale );
518  map["angle"] = QString::number( mAngle );
519  map["outline_style"] = QgsSymbolLayerV2Utils::encodePenStyle( mOutlineStyle );
520  map["outline_width"] = QString::number( mOutlineWidth );
521  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
522  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
523  map["joinstyle"] = QgsSymbolLayerV2Utils::encodePenJoinStyle( mPenJoinStyle );
524  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mColor );
525  map["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mOutlineColor );
526  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
528  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
529  map["size"] = QString::number( mSize );
531  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
532  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
533  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
535  return map;
536 }
537 
538 QSizeF QgsEllipseSymbolLayerV2::calculateSize( QgsSymbolV2RenderContext& context, double* scaledWidth, double* scaledHeight )
539 {
540  double width = 0;
541 
542  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
543  {
544  context.setOriginalValueVariable( mSymbolWidth );
545  width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mSymbolWidth ).toDouble();
546  }
547  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
548  {
549  width = mSize;
550  }
551  else //3. priority: global width setting
552  {
553  width = mSymbolWidth;
554  }
555  if ( scaledWidth )
556  {
557  *scaledWidth = width;
558  }
559  width = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), width, mSymbolWidthUnit, mSymbolHeightMapUnitScale );
560 
561  double height = 0;
562  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
563  {
564  context.setOriginalValueVariable( mSymbolHeight );
565  height = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, context, mSymbolHeight ).toDouble();
566  }
567  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
568  {
569  height = mSize;
570  }
571  else //3. priority: global height setting
572  {
573  height = mSymbolHeight;
574  }
575  if ( scaledHeight )
576  {
577  *scaledHeight = height;
578  }
579  height = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), height, mSymbolHeightUnit, mSymbolHeightMapUnitScale );
580  return QSizeF( width, height );
581 }
582 
583 void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV2RenderContext& context, double* scaledWidth, double* scaledHeight, const QgsFeature* )
584 {
585  mPainterPath = QPainterPath();
586 
587  QSizeF size = calculateSize( context, scaledWidth, scaledHeight );
588 
589  if ( symbolName == "circle" )
590  {
591  mPainterPath.addEllipse( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
592  }
593  else if ( symbolName == "semi_circle" )
594  {
595  mPainterPath.arcTo( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height(), 0, 180 );
596  mPainterPath.lineTo( 0, 0 );
597  }
598  else if ( symbolName == "rectangle" )
599  {
600  mPainterPath.addRect( QRectF( -size.width() / 2.0, -size.height() / 2.0, size.width(), size.height() ) );
601  }
602  else if ( symbolName == "diamond" )
603  {
604  mPainterPath.moveTo( -size.width() / 2.0, 0 );
605  mPainterPath.lineTo( 0, size.height() / 2.0 );
606  mPainterPath.lineTo( size.width() / 2.0, 0 );
607  mPainterPath.lineTo( 0, -size.height() / 2.0 );
608  mPainterPath.lineTo( -size.width() / 2.0, 0 );
609  }
610  else if ( symbolName == "cross" )
611  {
612  mPainterPath.moveTo( 0, -size.height() / 2.0 );
613  mPainterPath.lineTo( 0, size.height() / 2.0 );
614  mPainterPath.moveTo( -size.width() / 2.0, 0 );
615  mPainterPath.lineTo( size.width() / 2.0, 0 );
616  }
617  else if ( symbolName == "triangle" )
618  {
619  mPainterPath.moveTo( 0, -size.height() / 2.0 );
620  mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
621  mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
622  mPainterPath.lineTo( 0, -size.height() / 2.0 );
623  }
624  else if ( symbolName == "left_half_triangle" )
625  {
626  mPainterPath.moveTo( 0, size.height() / 2.0 );
627  mPainterPath.lineTo( size.width() / 2.0, size.height() / 2.0 );
628  mPainterPath.lineTo( 0, -size.height() / 2.0 );
629  mPainterPath.lineTo( 0, size.height() / 2.0 );
630  }
631  else if ( symbolName == "right_half_triangle" )
632  {
633  mPainterPath.moveTo( -size.width() / 2.0, size.height() / 2.0 );
634  mPainterPath.lineTo( 0, size.height() / 2.0 );
635  mPainterPath.lineTo( 0, -size.height() / 2.0 );
636  mPainterPath.lineTo( -size.width() / 2.0, size.height() / 2.0 );
637  }
638 }
639 
641 {
643  mSymbolWidthUnit = unit;
644  mSymbolHeightUnit = unit;
645  mOutlineWidthUnit = unit;
646 }
647 
649 {
651  if ( mSymbolWidthUnit != unit || mSymbolHeightUnit != unit || mOutlineWidthUnit != unit )
652  {
653  return QgsSymbolV2::Mixed;
654  }
655  return unit;
656 }
657 
659 {
661  mSymbolWidthMapUnitScale = scale;
662  mSymbolHeightMapUnitScale = scale;
663  mOutlineWidthMapUnitScale = scale;
664 }
665 
667 {
668  if ( QgsMarkerSymbolLayerV2::mapUnitScale() == mSymbolWidthMapUnitScale &&
669  mSymbolWidthMapUnitScale == mSymbolHeightMapUnitScale &&
670  mSymbolHeightMapUnitScale == mOutlineWidthMapUnitScale )
671  {
672  return mSymbolWidthMapUnitScale;
673  }
674  return QgsMapUnitScale();
675 }
676 
678 {
679  QSizeF size = calculateSize( context );
680 
681  bool hasDataDefinedRotation = false;
682  QPointF offset;
683  double angle = 0;
684  calculateOffsetAndRotation( context, size.width(), size.height(), hasDataDefinedRotation, offset, angle );
685 
686  double pixelSize = 1.0 / context.renderContext().rasterScaleFactor();
687 
688  QMatrix transform;
689 
690  // move to the desired position
691  transform.translate( point.x() + offset.x(), point.y() + offset.y() );
692 
693  if ( !qgsDoubleNear( angle, 0.0 ) )
694  transform.rotate( angle );
695 
696  double penWidth = 0.0;
697  bool ok = true;
699  {
700  context.setOriginalValueVariable( mOutlineWidth );
702  if ( ok )
703  {
704  penWidth = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), outlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale );
705  }
706  }
708  {
711  if ( ok && outlineStyle == "no" )
712  {
713  penWidth = 0.0;
714  }
715  }
716 
717  //antialiasing
718  penWidth += pixelSize;
719 
720  QRectF symbolBounds = transform.mapRect( QRectF( -size.width() / 2.0,
721  -size.height() / 2.0,
722  size.width(),
723  size.height() ) );
724 
725  //extend bounds by pen width / 2.0
726  symbolBounds.adjust( -penWidth / 2.0, -penWidth / 2.0,
727  penWidth / 2.0, penWidth / 2.0 );
728 
729  return symbolBounds;
730 }
731 
732 bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext &context, QPointF shift ) const
733 {
734  //width
735  double symbolWidth = mSymbolWidth;
736 
737  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
738  {
739  context.setOriginalValueVariable( mSymbolWidth );
740  symbolWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mSymbolWidth ).toDouble();
741  }
742  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
743  {
744  symbolWidth = mSize;
745  }
746  if ( mSymbolWidthUnit == QgsSymbolV2::MM )
747  {
748  symbolWidth *= mmMapUnitScaleFactor;
749  }
750 
751  //height
752  double symbolHeight = mSymbolHeight;
753  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
754  {
755  context.setOriginalValueVariable( mSymbolHeight );
756  symbolHeight = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, context, mSymbolHeight ).toDouble();
757  }
758  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
759  {
760  symbolHeight = mSize;
761  }
762  if ( mSymbolHeightUnit == QgsSymbolV2::MM )
763  {
764  symbolHeight *= mmMapUnitScaleFactor;
765  }
766 
767  //outline width
768  double outlineWidth = mOutlineWidth;
769 
771  {
772  context.setOriginalValueVariable( mOutlineWidth );
773  outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, mOutlineWidth ).toDouble();
774  }
775  if ( mOutlineWidthUnit == QgsSymbolV2::MM )
776  {
777  outlineWidth *= outlineWidth;
778  }
779 
780  //fill color
781  bool ok;
782  QColor fc = mColor;
784  {
787  if ( ok )
788  fc = QgsSymbolLayerV2Utils::decodeColor( colorString );
789  }
790 
791  //outline color
792  QColor oc = mOutlineColor;
794  {
797  if ( ok )
798  oc = QgsSymbolLayerV2Utils::decodeColor( colorString );
799  }
800 
801  //symbol name
802  QString symbolName = mSymbolName;
804  {
805  context.setOriginalValueVariable( mSymbolName );
806  symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context, mSymbolName ).toString();
807  }
808 
809  //offset
810  double offsetX = 0;
811  double offsetY = 0;
812  markerOffset( context, offsetX, offsetY );
813  QPointF off( offsetX, offsetY );
814 
815  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
816  double rotation = 0.0;
818  {
819  context.setOriginalValueVariable( mAngle );
821  }
822  else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
823  {
824  rotation = mAngle + mLineAngle;
825  }
826  rotation = -rotation; //rotation in Qt is counterclockwise
827  if ( rotation )
828  off = _rotatedOffset( off, rotation );
829 
830  QTransform t;
831  t.translate( shift.x() + offsetX, shift.y() + offsetY );
832 
833  if ( !qgsDoubleNear( rotation, 0.0 ) )
834  t.rotate( rotation );
835 
836  double halfWidth = symbolWidth / 2.0;
837  double halfHeight = symbolHeight / 2.0;
838 
839  if ( symbolName == "circle" )
840  {
841  if ( qgsDoubleNear( halfWidth, halfHeight ) )
842  {
843  QgsPointV2 pt( t.map( QPointF( 0, 0 ) ) );
844  e.writeFilledCircle( layerName, oc, pt, halfWidth );
845  }
846  else
847  {
848  QgsPointSequenceV2 line;
849 
850  double stepsize = 2 * M_PI / 40;
851  for ( int i = 0; i < 39; ++i )
852  {
853  double angle = stepsize * i;
854  double x = halfWidth * cos( angle );
855  double y = halfHeight * sin( angle );
856  line << QgsPointV2( t.map( QPointF( x, y ) ) );
857  }
858  //close ellipse with first point
859  line << line.at( 0 );
860 
861  if ( mBrush.style() != Qt::NoBrush )
862  e.writePolygon( QgsRingSequenceV2() << line, layerName, "SOLID", fc );
863  if ( mPen.style() != Qt::NoPen )
864  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
865  }
866  }
867  else if ( symbolName == "rectangle" )
868  {
870  p << QgsPointV2( t.map( QPointF( -halfWidth, -halfHeight ) ) )
871  << QgsPointV2( t.map( QPointF( halfWidth, -halfHeight ) ) )
872  << QgsPointV2( t.map( QPointF( halfWidth, halfHeight ) ) )
873  << QgsPointV2( t.map( QPointF( -halfWidth, halfHeight ) ) );
874  p << p[0];
875 
876  if ( mBrush.style() != Qt::NoBrush )
877  e.writePolygon( QgsRingSequenceV2() << p, layerName, "SOLID", fc );
878  if ( mPen.style() != Qt::NoPen )
879  e.writePolyline( p, layerName, "CONTINUOUS", oc, outlineWidth );
880  return true;
881  }
882  else if ( symbolName == "cross" && mPen.style() != Qt::NoPen )
883  {
885  << QgsPointV2( t.map( QPointF( -halfWidth, 0 ) ) )
886  << QgsPointV2( t.map( QPointF( halfWidth, 0 ) ) ),
887  layerName, "CONTINUOUS", oc, outlineWidth );
889  << QgsPointV2( t.map( QPointF( 0, halfHeight ) ) )
890  << QgsPointV2( t.map( QPointF( 0, -halfHeight ) ) ),
891  layerName, "CONTINUOUS", oc, outlineWidth );
892  return true;
893  }
894  else if ( symbolName == "triangle" )
895  {
897  p << QgsPointV2( t.map( QPointF( -halfWidth, -halfHeight ) ) )
898  << QgsPointV2( t.map( QPointF( halfWidth, -halfHeight ) ) )
899  << QgsPointV2( t.map( QPointF( 0, halfHeight ) ) );
900  p << p[0];
901  if ( mBrush.style() != Qt::NoBrush )
902  e.writePolygon( QgsRingSequenceV2() << p, layerName, "SOLID", fc );
903  if ( mPen.style() != Qt::NoPen )
904  e.writePolyline( p, layerName, "CONTINUOUS", oc, outlineWidth );
905  return true;
906  }
907 
908  return false; //soon...
909 }
910 
911 
void addEllipse(const QRectF &boundingRectangle)
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
static const QString EXPR_OUTLINE_COLOR
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
Writes the symbol layer definition as a SLD XML element.
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
Qt::PenStyle style() const
void setSymbolWidthUnit(QgsSymbolV2::OutputUnit unit)
QColor fillColor() const override
Get fill color.
QgsSymbolV2::OutputUnit outputUnit() const override
void setStyle(Qt::PenStyle style)
static QPointF _rotatedOffset(QPointF offset, double angle)
Adjusts a marker offset to account for rotation.
void renderPoint(QPointF point, QgsSymbolV2RenderContext &context) override
Renders a marker at the specified point.
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:65
int renderHints() const
Definition: qgssymbolv2.h:379
QgsMapUnitScale mSizeMapUnitScale
Marker size map unit scale.
A container class for data source field mapping or expression.
bool contains(const Key &key) const
static Q_DECL_DEPRECATED bool wellKnownMarkerFromSld(QDomElement &element, QString &name, QColor &color, QColor &borderColor, double &borderWidth, double &size)
void startRender(QgsSymbolV2RenderContext &context) override
QDomNode appendChild(const QDomNode &newChild)
static QDomElement createVendorOptionElement(QDomDocument &doc, const QString &name, const QString &value)
Qt::BrushStyle style() const
static void createGeometryElement(QDomDocument &doc, QDomElement &element, const QString &geomFunc)
QString field() const
Get the field which this QgsDataDefined represents.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QPoint map(const QPoint &point) const
static QString encodeColor(const QColor &color)
static const QString EXPR_WIDTH
static QgsStringMap getVendorOptionList(QDomElement &element)
const T & at(int i) const
void setOffset(QPointF offset)
Sets the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered marker...
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit unit)
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
Sets the horizontal anchor point for positioning the symbol.
QGis::GeometryType type() const
Returns type of the geometry as a QGis::GeometryType.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
void setVerticalAnchorPoint(VerticalAnchorPoint v)
Sets the vertical anchor point for positioning the symbol.
QgsEllipseSymbolLayerV2 * clone() const override
Shall be reimplemented by subclasses to create a deep copy of the instance.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setJoinStyle(Qt::PenJoinStyle style)
void moveTo(const QPointF &point)
static QPointF decodePoint(const QString &str)
QString expressionString() const
Returns the expression string of this QgsDataDefined.
static Qt::PenJoinStyle decodePenJoinStyle(const QString &str)
void copyPaintEffect(QgsSymbolLayerV2 *destLayer) const
Copies paint effect of this layer to another symbol layer.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
virtual bool hasDataDefinedProperty(const QString &property) const
Checks whether the layer has a matching data defined property and if that property is currently activ...
QRectF bounds(QPointF point, QgsSymbolV2RenderContext &context) override
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
QgsSymbolV2::OutputUnit outputUnit() const override
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s offset.
double toDouble(bool *ok) const
void setStyle(Qt::BrushStyle style)
A symbol layer for rendering objects with major and minor axis (e.g.
QgsStringMap properties() const override
Should be reimplemented by subclasses to return a string map that contains the configuration informat...
double mapRotation() const
Return current map rotation in degrees.
void adjust(qreal dx1, qreal dy1, qreal dx2, qreal dy2)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
Sets the units for the symbol&#39;s offset.
void setMapUnitScale(const QgsMapUnitScale &scale) override
static const QString EXPR_JOIN_STYLE
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
static QString encodePenStyle(Qt::PenStyle style)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
Mixed units in symbol layers.
Definition: qgssymbolv2.h:69
void setSymbolHeightMapUnitScale(const QgsMapUnitScale &scale)
QTransform & translate(qreal dx, qreal dy)
The output shall be in millimeters.
Definition: qgssymbolv2.h:67
QString number(int n, int base)
static const QString EXPR_FILL_COLOR
void markerOffset(QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY) const
Calculates the required marker offset, including both the symbol offset and any displacement required...
qreal x() const
qreal y() const
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:384
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
static QString encodePoint(QPointF point)
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsSymbolV2::OutputUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
void setPen(const QColor &color)
void lineTo(const QPointF &endPoint)
void setAttribute(const QString &name, const QString &value)
QMatrix & translate(qreal dx, qreal dy)
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
bool isEmpty() const
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
void addRect(const QRectF &rectangle)
#define M_PI
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
Sets the units for the symbol&#39;s size.
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolV2RenderContext &context, QPointF shift=QPointF(0.0, 0.0)) const override
write as DXF
void setWidthF(qreal width)
void setBrush(const QBrush &brush)
double rasterScaleFactor() const
Q_DECL_DEPRECATED void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
virtual QColor color() const
The fill color.
HorizontalAnchorPoint mHorizontalAnchorPoint
Horizontal anchor point.
iterator end()
void setOutlineStyle(Qt::PenStyle outlineStyle)
void setColor(const QColor &color)
void setSymbolName(const QString &name)
virtual Q_DECL_DEPRECATED void prepareExpressions(const QgsFields *fields, double scale=-1.0)
Prepares all data defined property expressions for evaluation.
virtual bool hasDataDefinedProperties() const
Checks whether the layer has any associated data defined properties.
double mAngle
Marker rotation angle, in degrees clockwise from north.
iterator begin()
static Qt::PenStyle decodePenStyle(const QString &str)
double mLineAngle
Line rotation angle (see setLineAngle() for details)
static const QString EXPR_OUTLINE_STYLE
Q_DECL_DEPRECATED void writePolyline(const QgsPolyline &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
double size() const
Returns the symbol size.
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
bool useExpression() const
Returns if the field or the expression part is active.
QRect mapRect(const QRect &rectangle) const
bool isNull() const
void startRender(QgsSymbolV2RenderContext &context) override
static const QString EXPR_OUTLINE_WIDTH
QTransform & rotate(qreal angle, Qt::Axis axis)
QMatrix & rotate(qreal degrees)
VerticalAnchorPoint
Symbol vertical anchor points.
QPainter * painter()
void drawPath(const QPainterPath &path)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void setWidth(int width)
Struct for storing maximum and minimum scales for measurements in map units.
QgsMapUnitScale mapUnitScale() const override
void setSymbolWidthMapUnitScale(const QgsMapUnitScale &scale)
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:355
virtual QgsDataDefined * getDataDefinedProperty(const QString &property) const
Returns the data defined property corresponding to the specified property key.
QDomElement firstChildElement(const QString &tagName) const
void setOutlineColor(const QColor &c) override
Set outline color.
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
Q_DECL_DEPRECATED void writePolygon(const QgsPolygon &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf filled polygon (HATCH)
static const QString EXPR_ROTATION
const QgsMapToPixel & mapToPixel() const
Qt::PenStyle outlineStyle() const
QgsSymbolV2::OutputUnit mOffsetUnit
Offset units.
virtual void setColor(const QColor &color)
The fill color.
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
double toDouble(bool *ok) const
static QColor decodeColor(const QString &str)
Abstract base class for marker symbol layers.
VerticalAnchorPoint mVerticalAnchorPoint
Vertical anchor point.
void stopRender(QgsSymbolV2RenderContext &context) override
QgsSymbolV2::OutputUnit mSizeUnit
Marker size unit.
QgsMapUnitScale mOffsetMapUnitScale
Offset map unit scale.
HorizontalAnchorPoint
Symbol horizontal anchor points.
void setPenJoinStyle(Qt::PenJoinStyle style)
Set outline join style.
void restoreDataDefinedProperties(const QgsStringMap &stringMap)
Restores all data defined properties from string map.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
QString layerType() const override
Returns a string that represents this layer type.
double mSize
Marker size.
QDomElement createElement(const QString &tagName)
static const QString EXPR_SYMBOL_NAME
qreal height() const
QgsMapUnitScale mapUnitScale() const override
void setSize(double size)
Sets the symbol size.
void map(int x, int y, int *tx, int *ty) const
void setAngle(double angle)
Sets the rotation angle for the marker.
QPointF offset() const
Returns the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered mar...
void arcTo(const QRectF &rectangle, qreal startAngle, qreal sweepLength)
void setColor(const QColor &color)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
void saveDataDefinedProperties(QgsStringMap &stringMap) const
Saves all data defined properties to a string map.
QPointF mOffset
Marker offset.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s size.
void setFillColor(const QColor &c) override
Set fill color.
bool isActive() const
void setSymbolHeightUnit(QgsSymbolV2::OutputUnit unit)
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
qreal width() const
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
#define DEFAULT_ELLIPSE_JOINSTYLE
void copyDataDefinedProperties(QgsSymbolLayerV2 *destLayer) const
Copies all data defined properties of this layer to another symbol layer.
QList< QgsPointV2 > QgsPointSequenceV2
static const QString EXPR_HEIGHT
const T value(const Key &key) const
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, const QString &name, const QColor &color, const QColor &borderColor=QColor(), double borderWidth=-1, double size=-1)
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.
virtual Q_DECL_DEPRECATED QVariant evaluateDataDefinedProperty(const QString &property, const QgsFeature *feature, const QVariant &defaultVal=QVariant(), bool *ok=nullptr) const
Evaluates the matching data defined property and returns the calculated value.