QGIS API Documentation  2.12.0-Lyon
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 
24 #include <QPainter>
25 #include <QSet>
26 #include <QDomDocument>
27 #include <QDomElement>
28 
30  : mSymbolName( "circle" )
31  , mSymbolWidth( 4 )
32  , mSymbolWidthUnit( QgsSymbolV2::MM )
33  , mSymbolHeight( 3 )
34  , mSymbolHeightUnit( QgsSymbolV2::MM )
35  , mFillColor( Qt::white )
36  , mOutlineColor( Qt::black )
37  , mOutlineStyle( Qt::SolidLine )
38  , mOutlineWidth( 0 )
39  , mOutlineWidthUnit( QgsSymbolV2::MM )
40 {
41  mPen.setColor( mOutlineColor );
42  mPen.setStyle( mOutlineStyle );
43  mPen.setWidth( 1.0 );
44  mPen.setJoinStyle( Qt::MiterJoin );
45  mBrush.setColor( mFillColor );
46  mBrush.setStyle( Qt::SolidPattern );
47  mOffset = QPointF( 0, 0 );
48 
49  mAngle = 0;
50 }
51 
53 {
54 }
55 
57 {
59  if ( properties.contains( "symbol_name" ) )
60  {
61  layer->setSymbolName( properties[ "symbol_name" ] );
62  }
63  if ( properties.contains( "symbol_width" ) )
64  {
65  layer->setSymbolWidth( properties["symbol_width"].toDouble() );
66  }
67  if ( properties.contains( "symbol_width_unit" ) )
68  {
69  layer->setSymbolWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["symbol_width_unit"] ) );
70  }
71  if ( properties.contains( "symbol_width_map_unit_scale" ) )
72  {
73  layer->setSymbolWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["symbol_width_map_unit_scale"] ) );
74  }
75  if ( properties.contains( "symbol_height" ) )
76  {
77  layer->setSymbolHeight( properties["symbol_height"].toDouble() );
78  }
79  if ( properties.contains( "symbol_height_unit" ) )
80  {
81  layer->setSymbolHeightUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["symbol_height_unit"] ) );
82  }
83  if ( properties.contains( "symbol_height_map_unit_scale" ) )
84  {
85  layer->setSymbolHeightMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["symbol_height_map_unit_scale"] ) );
86  }
87  if ( properties.contains( "angle" ) )
88  {
89  layer->setAngle( properties["angle"].toDouble() );
90  }
91  if ( properties.contains( "outline_style" ) )
92  {
93  layer->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( properties["outline_style"] ) );
94  }
95  else if ( properties.contains( "line_style" ) )
96  {
97  layer->setOutlineStyle( QgsSymbolLayerV2Utils::decodePenStyle( properties["line_style"] ) );
98  }
99  if ( properties.contains( "outline_width" ) )
100  {
101  layer->setOutlineWidth( properties["outline_width"].toDouble() );
102  }
103  else if ( properties.contains( "line_width" ) )
104  {
105  layer->setOutlineWidth( properties["line_width"].toDouble() );
106  }
107  if ( properties.contains( "outline_width_unit" ) )
108  {
109  layer->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["outline_width_unit"] ) );
110  }
111  else if ( properties.contains( "line_width_unit" ) )
112  {
113  layer->setOutlineWidthUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["line_width_unit"] ) );
114  }
115  if ( properties.contains( "outline_width_map_unit_scale" ) )
116  {
117  layer->setOutlineWidthMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["outline_width_map_unit_scale"] ) );
118  }
119  if ( properties.contains( "fill_color" ) )
120  {
121  //pre 2.5 projects used "fill_color"
122  layer->setFillColor( QgsSymbolLayerV2Utils::decodeColor( properties["fill_color"] ) );
123  }
124  else if ( properties.contains( "color" ) )
125  {
126  layer->setFillColor( QgsSymbolLayerV2Utils::decodeColor( properties["color"] ) );
127  }
128  if ( properties.contains( "outline_color" ) )
129  {
130  layer->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( properties["outline_color"] ) );
131  }
132  else if ( properties.contains( "line_color" ) )
133  {
134  layer->setOutlineColor( QgsSymbolLayerV2Utils::decodeColor( properties["line_color"] ) );
135  }
136  if ( properties.contains( "size" ) )
137  {
138  layer->setSize( properties["size"].toDouble() );
139  }
140  if ( properties.contains( "size_unit" ) )
141  {
142  layer->setSizeUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["size_unit"] ) );
143  }
144  if ( properties.contains( "size_map_unit_scale" ) )
145  {
146  layer->setSizeMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["size_map_unit_scale"] ) );
147  }
148  if ( properties.contains( "offset" ) )
149  {
150  layer->setOffset( QgsSymbolLayerV2Utils::decodePoint( properties["offset"] ) );
151  }
152  if ( properties.contains( "offset_unit" ) )
153  {
154  layer->setOffsetUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( properties["offset_unit"] ) );
155  }
156  if ( properties.contains( "offset_map_unit_scale" ) )
157  {
158  layer->setOffsetMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( properties["offset_map_unit_scale"] ) );
159  }
160  if ( properties.contains( "horizontal_anchor_point" ) )
161  {
162  layer->setHorizontalAnchorPoint( QgsMarkerSymbolLayerV2::HorizontalAnchorPoint( properties[ "horizontal_anchor_point" ].toInt() ) );
163  }
164  if ( properties.contains( "vertical_anchor_point" ) )
165  {
166  layer->setVerticalAnchorPoint( QgsMarkerSymbolLayerV2::VerticalAnchorPoint( properties[ "vertical_anchor_point" ].toInt() ) );
167  }
168 
169  //data defined properties
170  layer->restoreDataDefinedProperties( properties );
171 
172  //compatibility with old project file format
173  if ( !properties["width_field"].isEmpty() )
174  {
175  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, new QgsDataDefined( properties["width_field"] ) );
176  }
177  if ( !properties["height_field"].isEmpty() )
178  {
179  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, new QgsDataDefined( properties["height_field"] ) );
180  }
181  if ( !properties["rotation_field"].isEmpty() )
182  {
183  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, new QgsDataDefined( properties["rotation_field"] ) );
184  }
185  if ( !properties["outline_width_field"].isEmpty() )
186  {
187  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, new QgsDataDefined( properties[ "outline_width_field" ] ) );
188  }
189  if ( !properties["fill_color_field"].isEmpty() )
190  {
191  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, new QgsDataDefined( properties["fill_color_field"] ) );
192  }
193  if ( !properties["outline_color_field"].isEmpty() )
194  {
195  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, new QgsDataDefined( properties["outline_color_field"] ) );
196  }
197  if ( !properties["symbol_name_field"].isEmpty() )
198  {
199  layer->setDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, new QgsDataDefined( properties["symbol_name_field"] ) );
200  }
201 
202  return layer;
203 }
204 
206 {
207  bool ok;
209  {
210  context.setOriginalValueVariable( mOutlineWidth );
211  double width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context, mOutlineWidth ).toDouble();
212  width = QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), width, mOutlineWidthUnit, mOutlineWidthMapUnitScale );
213  mPen.setWidthF( width );
214  }
216  {
219  if ( ok )
220  {
221  Qt::PenStyle style = QgsSymbolLayerV2Utils::decodePenStyle( styleString );
222  mPen.setStyle( style );
223  }
224  }
226  {
229  if ( ok )
230  mBrush.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
231  }
233  {
236  if ( ok )
237  mPen.setColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) );
238  }
239  double scaledWidth = mSymbolWidth;
240  double scaledHeight = mSymbolHeight;
242  {
243  QString symbolName = mSymbolName;
245  {
246  context.setOriginalValueVariable( mSymbolName );
247  symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context, mSymbolName ).toString();
248  }
249  preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() );
250  }
251 
252  //offset
253  double offsetX = 0;
254  double offsetY = 0;
255  markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale );
256  QPointF off( offsetX, offsetY );
257 
258  QPainter* p = context.renderContext().painter();
259  if ( !p )
260  {
261  return;
262  }
263 
264  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
265  double rotation = 0.0;
266 
268  {
269  context.setOriginalValueVariable( mAngle );
271 
272  const QgsMapToPixel& m2p = context.renderContext().mapToPixel();
273  rotation += m2p.mapRotation();
274  }
275  else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
276  {
277  rotation = mAngle + mLineAngle;
278  }
279 
280  if ( rotation )
281  off = _rotatedOffset( off, rotation );
282 
283  QMatrix transform;
284  transform.translate( point.x() + off.x(), point.y() + off.y() );
285  if ( !qgsDoubleNear( rotation, 0.0 ) )
286  {
287  transform.rotate( rotation );
288  }
289 
290  p->setPen( mPen );
291  p->setBrush( mBrush );
292  p->drawPath( transform.map( mPainterPath ) );
293 }
294 
296 {
297  return "EllipseMarker";
298 }
299 
301 {
302  QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions
303  if ( !context.feature() || !hasDataDefinedProperties() )
304  {
305  preparePath( mSymbolName, context );
306  }
307  mPen.setColor( mOutlineColor );
308  mPen.setStyle( mOutlineStyle );
309  mPen.setWidthF( QgsSymbolLayerV2Utils::convertToPainterUnits( context.renderContext(), mOutlineWidth, mOutlineWidthUnit, mOutlineWidthMapUnitScale ) );
310  mBrush.setColor( mFillColor );
311  prepareExpressions( context );
312 }
313 
315 {
316 }
317 
319 {
321 }
322 
323 void QgsEllipseSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element, const QgsStringMap& props ) const
324 {
325  QDomElement symbolizerElem = doc.createElement( "se:PointSymbolizer" );
326  if ( !props.value( "uom", "" ).isEmpty() )
327  symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) );
328  element.appendChild( symbolizerElem );
329 
330  // <Geometry>
331  QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) );
332 
333  writeSldMarker( doc, symbolizerElem, props );
334 }
335 
337 {
338  // <Graphic>
339  QDomElement graphicElem = doc.createElement( "se:Graphic" );
340  element.appendChild( graphicElem );
341 
342  QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, mSymbolName, mFillColor, mOutlineColor, mOutlineStyle, mOutlineWidth, mSymbolWidth );
343 
344  // store w/h factor in a <VendorOption>
345  double widthHeightFactor = mSymbolWidth / mSymbolHeight;
346  QDomElement factorElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "widthHeightFactor", QString::number( widthHeightFactor ) );
347  graphicElem.appendChild( factorElem );
348 
349  // <Rotation>
351 
352  QString angleFunc = props.value( "angle", "" );
353  if ( angleFunc.isEmpty() ) // symbol has no angle set
354  {
355  if ( ddRotation && ddRotation->isActive() )
356  {
357  angleFunc = ddRotation->useExpression() ? ddRotation->expressionString() : ddRotation->field();
358  }
359  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
360  angleFunc = QString::number( mAngle );
361  }
362  else if ( ddRotation && ddRotation->isActive() )
363  {
364  // the symbol has an angle and the symbol layer have a rotation
365  // property set
366  angleFunc = QString( "%1 + %2" ).arg( angleFunc, ddRotation->useExpression() ? ddRotation->expressionString() : ddRotation->field() );
367  }
368  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
369  {
370  // both the symbol and the symbol layer have angle value set
371  bool ok;
372  double angle = angleFunc.toDouble( &ok );
373  if ( !ok )
374  {
375  // its a string (probably a property name or a function)
376  angleFunc = QString( "%1 + %2" ).arg( angleFunc ).arg( mAngle );
377  }
378  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
379  {
380  // it's a double value
381  angleFunc = QString::number( angle + mAngle );
382  }
383  }
384  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
385 }
386 
388 {
389  QgsDebugMsg( "Entered." );
390 
391  QDomElement graphicElem = element.firstChildElement( "Graphic" );
392  if ( graphicElem.isNull() )
393  return NULL;
394 
395  QString name = "circle";
396  QColor fillColor, borderColor;
397  double borderWidth, size;
398  double widthHeightFactor = 1.0;
399  Qt::PenStyle borderStyle;
400 
401  QgsStringMap vendorOptions = QgsSymbolLayerV2Utils::getVendorOptionList( graphicElem );
402  for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
403  {
404  if ( it.key() == "widthHeightFactor" )
405  {
406  bool ok;
407  double v = it.value().toDouble( &ok );
408  if ( ok && !qgsDoubleNear( v, 0.0 ) && v > 0 )
409  widthHeightFactor = v;
410  }
411  }
412 
413  if ( !QgsSymbolLayerV2Utils::wellKnownMarkerFromSld( graphicElem, name, fillColor, borderColor, borderStyle, borderWidth, size ) )
414  return NULL;
415 
416  double angle = 0.0;
417  QString angleFunc;
418  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
419  {
420  bool ok;
421  double d = angleFunc.toDouble( &ok );
422  if ( ok )
423  angle = d;
424  }
425 
427  m->setSymbolName( name );
428  m->setFillColor( fillColor );
429  m->setOutlineColor( borderColor );
430  m->setOutlineStyle( borderStyle );
431  m->setOutlineWidth( borderWidth );
432  m->setSymbolWidth( size );
433  m->setSymbolHeight( size / widthHeightFactor );
434  m->setAngle( angle );
435  return m;
436 }
437 
439 {
440  QgsStringMap map;
441  map["symbol_name"] = mSymbolName;
442  map["symbol_width"] = QString::number( mSymbolWidth );
443  map["symbol_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSymbolWidthUnit );
444  map["symbol_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSymbolWidthMapUnitScale );
445  map["symbol_height"] = QString::number( mSymbolHeight );
446  map["symbol_height_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSymbolHeightUnit );
447  map["symbol_height_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSymbolHeightMapUnitScale );
448  map["angle"] = QString::number( mAngle );
449  map["outline_style"] = QgsSymbolLayerV2Utils::encodePenStyle( mOutlineStyle );
450  map["outline_width"] = QString::number( mOutlineWidth );
451  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
452  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
453  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mFillColor );
454  map["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mOutlineColor );
455  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
457  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
458  map["size"] = QString::number( mSize );
460  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
461  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
462  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
464  return map;
465 }
466 
467 void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV2RenderContext& context, double* scaledWidth, double* scaledHeight, const QgsFeature* )
468 {
469  mPainterPath = QPainterPath();
470  const QgsRenderContext& ct = context.renderContext();
471 
472  double width = 0;
473 
474  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
475  {
476  context.setOriginalValueVariable( mSymbolWidth );
477  width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, context, mSymbolWidth ).toDouble();
478  }
479  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
480  {
481  width = mSize;
482  }
483  else //3. priority: global width setting
484  {
485  width = mSymbolWidth;
486  }
487  if ( scaledWidth )
488  {
489  *scaledWidth = width;
490  }
491  width = QgsSymbolLayerV2Utils::convertToPainterUnits( ct, width, mSymbolWidthUnit, mSymbolHeightMapUnitScale );
492 
493  double height = 0;
494  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
495  {
496  context.setOriginalValueVariable( mSymbolHeight );
497  height = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, context, mSymbolHeight ).toDouble();
498  }
499  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
500  {
501  height = mSize;
502  }
503  else //3. priority: global height setting
504  {
505  height = mSymbolHeight;
506  }
507  if ( scaledHeight )
508  {
509  *scaledHeight = height;
510  }
511  height = QgsSymbolLayerV2Utils::convertToPainterUnits( ct, height, mSymbolHeightUnit, mSymbolHeightMapUnitScale );
512 
513  if ( symbolName == "circle" )
514  {
515  mPainterPath.addEllipse( QRectF( -width / 2.0, -height / 2.0, width, height ) );
516  }
517  else if ( symbolName == "rectangle" )
518  {
519  mPainterPath.addRect( QRectF( -width / 2.0, -height / 2.0, width, height ) );
520  }
521  else if ( symbolName == "cross" )
522  {
523  mPainterPath.moveTo( 0, -height / 2.0 );
524  mPainterPath.lineTo( 0, height / 2.0 );
525  mPainterPath.moveTo( -width / 2.0, 0 );
526  mPainterPath.lineTo( width / 2.0, 0 );
527  }
528  else if ( symbolName == "triangle" )
529  {
530  mPainterPath.moveTo( 0, -height / 2.0 );
531  mPainterPath.lineTo( -width / 2.0, height / 2.0 );
532  mPainterPath.lineTo( width / 2.0, height / 2.0 );
533  mPainterPath.lineTo( 0, -height / 2.0 );
534  }
535 }
536 
538 {
540  mSymbolWidthUnit = unit;
541  mSymbolHeightUnit = unit;
542  mOutlineWidthUnit = unit;
543 }
544 
546 {
548  if ( mSymbolWidthUnit != unit || mSymbolHeightUnit != unit || mOutlineWidthUnit != unit )
549  {
550  return QgsSymbolV2::Mixed;
551  }
552  return unit;
553 }
554 
556 {
558  mSymbolWidthMapUnitScale = scale;
559  mSymbolHeightMapUnitScale = scale;
560  mOutlineWidthMapUnitScale = scale;
561 }
562 
564 {
565  if ( QgsMarkerSymbolLayerV2::mapUnitScale() == mSymbolWidthMapUnitScale &&
566  mSymbolWidthMapUnitScale == mSymbolHeightMapUnitScale &&
567  mSymbolHeightMapUnitScale == mOutlineWidthMapUnitScale )
568  {
569  return mSymbolWidthMapUnitScale;
570  }
571  return QgsMapUnitScale();
572 }
573 
574 bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext *context, const QgsFeature*, const QPointF& shift ) const
575 {
576  //width
577  double symbolWidth = mSymbolWidth;
578 
579  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
580  {
581  context->setOriginalValueVariable( mSymbolWidth );
582  symbolWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, *context, mSymbolWidth ).toDouble();
583  }
584  else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
585  {
586  symbolWidth = mSize;
587  }
588  if ( mSymbolWidthUnit == QgsSymbolV2::MM )
589  {
590  symbolWidth *= mmMapUnitScaleFactor;
591  }
592 
593  //height
594  double symbolHeight = mSymbolHeight;
595  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
596  {
597  context->setOriginalValueVariable( mSymbolHeight );
598  symbolHeight = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, *context, mSymbolHeight ).toDouble();
599  }
600  else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
601  {
602  symbolHeight = mSize;
603  }
604  if ( mSymbolHeightUnit == QgsSymbolV2::MM )
605  {
606  symbolHeight *= mmMapUnitScaleFactor;
607  }
608 
609  //outline width
610  double outlineWidth = mOutlineWidth;
611 
613  {
614  context->setOriginalValueVariable( mOutlineWidth );
615  outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, *context, mOutlineWidth ).toDouble();
616  }
617  if ( mOutlineWidthUnit == QgsSymbolV2::MM )
618  {
619  outlineWidth *= outlineWidth;
620  }
621 
622  //fill color
623  bool ok;
624  QColor fc = mFillColor;
626  {
629  if ( ok )
630  fc = QgsSymbolLayerV2Utils::decodeColor( colorString );
631  }
632 
633  //outline color
634  QColor oc = mOutlineColor;
636  {
639  if ( ok )
640  oc = QgsSymbolLayerV2Utils::decodeColor( colorString );
641  }
642 
643  //symbol name
644  QString symbolName = mSymbolName;
646  {
647  context->setOriginalValueVariable( mSymbolName );
648  symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, *context, mSymbolName ).toString();
649  }
650 
651  //offset
652  double offsetX = 0;
653  double offsetY = 0;
654  markerOffset( *context, offsetX, offsetY );
655  QPointF off( offsetX, offsetY );
656 
657  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
658  double rotation = 0.0;
660  {
661  context->setOriginalValueVariable( mAngle );
663  }
664  else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
665  {
666  rotation = mAngle + mLineAngle;
667  }
668  rotation = -rotation; //rotation in Qt is counterclockwise
669  if ( rotation )
670  off = _rotatedOffset( off, rotation );
671 
672  QTransform t;
673  t.translate( shift.x() + offsetX, shift.y() + offsetY );
674 
675  if ( rotation != 0 )
676  t.rotate( rotation );
677 
678  double halfWidth = symbolWidth / 2.0;
679  double halfHeight = symbolHeight / 2.0;
680 
681  if ( symbolName == "circle" )
682  {
683  if ( qgsDoubleNear( halfWidth, halfHeight ) )
684  {
685  QPointF pt( t.map( QPointF( 0, 0 ) ) );
686  e.writeFilledCircle( layerName, oc, pt, halfWidth );
687  }
688  else
689  {
690  QgsPolyline line;
691  line.reserve( 40 );
692  double stepsize = 2 * M_PI / 40;
693  for ( int i = 0; i < 39; ++i )
694  {
695  double angle = stepsize * i;
696  double x = halfWidth * cos( angle );
697  double y = halfHeight * sin( angle );
698  QPointF pt( t.map( QPointF( x, y ) ) );
699  line.push_back( pt );
700  }
701  //close ellipse with first point
702  line.push_back( line.at( 0 ) );
703  if ( mBrush.style() != Qt::NoBrush )
704  e.writePolygon( QgsPolygon() << line, layerName, "SOLID", fc );
705  if ( mPen.style() != Qt::NoPen )
706  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
707  }
708  }
709  else if ( symbolName == "rectangle" )
710  {
711  QgsPolygon p( 1 );
712  p[0].resize( 5 );
713  p[0][0] = t.map( QPointF( -halfWidth, -halfHeight ) );
714  p[0][1] = t.map( QPointF( halfWidth, -halfHeight ) );
715  p[0][2] = t.map( QPointF( halfWidth, halfHeight ) );
716  p[0][3] = t.map( QPointF( -halfWidth, halfHeight ) );
717  p[0][4] = p[0][0];
718  if ( mBrush.style() != Qt::NoBrush )
719  e.writePolygon( p, layerName, "SOLID", fc );
720  if ( mPen.style() != Qt::NoPen )
721  e.writePolyline( p[0], layerName, "CONTINUOUS", oc, outlineWidth );
722  return true;
723  }
724  else if ( symbolName == "cross" && mPen.style() != Qt::NoPen )
725  {
726  QgsPolyline line( 2 );
727  line[0] = t.map( QPointF( -halfWidth, 0 ) );
728  line[1] = t.map( QPointF( halfWidth, 0 ) );
729  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
730 
731  line[0] = t.map( QPointF( 0, halfHeight ) );
732  line[1] = t.map( QPointF( 0, -halfHeight ) );
733  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
734 
735  return true;
736  }
737  else if ( symbolName == "triangle" )
738  {
739  QgsPolygon p( 1 );
740  p[0].resize( 4 );
741  p[0][0] = QPointF( t.map( QPointF( -halfWidth, -halfHeight ) ) );
742  p[0][1] = QPointF( t.map( QPointF( halfWidth, -halfHeight ) ) );
743  p[0][2] = QPointF( t.map( QPointF( 0, halfHeight ) ) );
744  p[0][3] = p[0][0];
745  if ( mBrush.style() != Qt::NoBrush )
746  e.writePolygon( p, layerName, "SOLID", fc );
747  if ( mPen.style() != Qt::NoPen )
748  e.writePolyline( p[0], layerName, "CONTINUOUS", oc, outlineWidth );
749  return true;
750  }
751 
752  return false; //soon...
753 }
754 
755 
void addEllipse(const QRectF &boundingRectangle)
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
void renderPoint(const QPointF &point, QgsSymbolV2RenderContext &context) override
static const QString EXPR_OUTLINE_COLOR
void writeSldMarker(QDomDocument &doc, QDomElement &element, const QgsStringMap &props) const override
static void createRotationElement(QDomDocument &doc, QDomElement &element, const QString &rotationFunc)
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const override
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)
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:55
int renderHints() const
Definition: qgssymbolv2.h:278
QgsMapUnitScale mSizeMapUnitScale
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)
QgsSymbolLayerV2 * clone() const override
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)
void setOffset(QPointF offset)
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit unit)
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
void setVerticalAnchorPoint(VerticalAnchorPoint v)
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 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...
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:176
void setOffsetMapUnitScale(const QgsMapUnitScale &scale)
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
double mapRotation() const
Return current map rotation in degrees.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:268
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
void setMapUnitScale(const QgsMapUnitScale &scale) override
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
const QColor & color() const
static QString encodePenStyle(Qt::PenStyle style)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
QColor color() const
Mixed units in symbol layers.
Definition: qgssymbolv2.h:59
void setSymbolHeightMapUnitScale(const QgsMapUnitScale &scale)
QTransform & translate(qreal dx, qreal dy)
The output shall be in millimeters.
Definition: qgssymbolv2.h:57
QString number(int n, int base)
static const QString EXPR_FILL_COLOR
void markerOffset(QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY) const
qreal x() const
qreal y() const
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
void resize(int size)
const QgsFeature * feature() const
Current feature being rendered - may be null.
Definition: qgssymbolv2.h:283
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)
bool isEmpty() const
void addRect(const QRectF &rectangle)
#define M_PI
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
void setWidthF(qreal width)
void setBrush(const QBrush &brush)
void writeFilledCircle(const QString &layer, const QColor &color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
HorizontalAnchorPoint mHorizontalAnchorPoint
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.
iterator begin()
static Qt::PenStyle decodePenStyle(const QString &str)
static const QString EXPR_OUTLINE_STYLE
void writePolyline(const QgsPolyline &line, const QString &layer, const QString &lineStyleName, const QColor &color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
bool useExpression() const
Returns if the field or the expression part is active.
void reserve(int size)
bool isNull() const
void startRender(QgsSymbolV2RenderContext &context) override
static const QString EXPR_OUTLINE_WIDTH
QTransform & rotate(qreal angle, Qt::Axis axis)
const T & at(int i) const
QMatrix & rotate(qreal degrees)
Contains information about the context of a rendering operation.
QPainter * painter()
void drawPath(const QPainterPath &path)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void setWidth(int width)
virtual Q_DECL_DEPRECATED QVariant evaluateDataDefinedProperty(const QString &property, const QgsFeature *feature, const QVariant &defaultVal=QVariant(), bool *ok=0) const
Evaluates the matching data defined property and returns the calculated value.
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:254
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.
void writePolygon(const QgsPolygon &polygon, const QString &layer, const QString &hatchPattern, const QColor &color)
Draw dxf polygon (HATCH)
static const QString EXPR_ROTATION
const QgsMapToPixel & mapToPixel() const
void push_back(const T &value)
QgsSymbolV2::OutputUnit mOffsetUnit
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
double toDouble(bool *ok) const
static QColor decodeColor(const QString &str)
VerticalAnchorPoint mVerticalAnchorPoint
void stopRender(QgsSymbolV2RenderContext &context) override
QgsSymbolV2::OutputUnit mSizeUnit
QgsMapUnitScale mOffsetMapUnitScale
void restoreDataDefinedProperties(const QgsStringMap &stringMap)
Restores all data defined properties from string map.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
QString layerType() const override
QDomElement createElement(const QString &tagName)
static const QString EXPR_SYMBOL_NAME
QgsMapUnitScale mapUnitScale() const override
void setSize(double size)
void map(int x, int y, int *tx, int *ty) const
void setAngle(double angle)
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.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
void setFillColor(const QColor &c) override
Set fill color.
bool isActive() const
void setSymbolHeightUnit(QgsSymbolV2::OutputUnit unit)
void setOutputUnit(QgsSymbolV2::OutputUnit unit) override
void setOutlineWidthMapUnitScale(const QgsMapUnitScale &scale)
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.
static QPointF _rotatedOffset(const QPointF &offset, double angle)