QGIS API Documentation  2.11.0-Master
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  double width = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, context.feature(), mOutlineWidth ).toDouble();
211  width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit, mOutlineWidthMapUnitScale );
212  mPen.setWidthF( width );
213  }
215  {
216  QString styleString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_STYLE, context.feature(), QVariant(), &ok ).toString();
217  if ( ok )
218  {
219  Qt::PenStyle style = QgsSymbolLayerV2Utils::decodePenStyle( styleString );
220  mPen.setStyle( style );
221  }
222  }
224  {
225  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, context.feature(), QVariant(), &ok ).toString();
226  if ( ok )
227  mBrush.setColor( QColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) ) );
228  }
230  {
231  QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, context.feature(), QVariant(), &ok ).toString();
232  if ( ok )
233  mPen.setColor( QColor( QgsSymbolLayerV2Utils::decodeColor( colorString ) ) );
234  }
235  double scaledWidth = mSymbolWidth;
236  double scaledHeight = mSymbolHeight;
238  {
239  QString symbolName = mSymbolName;
241  {
242  symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, context.feature(), mSymbolName ).toString();
243  }
244  preparePath( symbolName, context, &scaledWidth, &scaledHeight, context.feature() );
245  }
246 
247  //offset
248  double offsetX = 0;
249  double offsetY = 0;
250  markerOffset( context, scaledWidth, scaledHeight, mSymbolWidthUnit, mSymbolHeightUnit, offsetX, offsetY, mSymbolWidthMapUnitScale, mSymbolHeightMapUnitScale );
251  QPointF off( offsetX, offsetY );
252 
253  QPainter* p = context.renderContext().painter();
254  if ( !p )
255  {
256  return;
257  }
258 
259  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
260  double rotation = 0.0;
262  {
264  }
265  else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
266  {
267  rotation = mAngle + mLineAngle;
268  }
269  if ( rotation )
270  off = _rotatedOffset( off, rotation );
271 
272  QMatrix transform;
273  transform.translate( point.x() + off.x(), point.y() + off.y() );
274  if ( !qgsDoubleNear( rotation, 0.0 ) )
275  {
276  transform.rotate( rotation );
277  }
278 
279  p->setPen( mPen );
280  p->setBrush( mBrush );
281  p->drawPath( transform.map( mPainterPath ) );
282 }
283 
285 {
286  return "EllipseMarker";
287 }
288 
290 {
291  QgsMarkerSymbolLayerV2::startRender( context ); // get anchor point expressions
292  if ( !context.feature() || !hasDataDefinedProperties() )
293  {
294  preparePath( mSymbolName, context );
295  }
296  mPen.setColor( mOutlineColor );
297  mPen.setStyle( mOutlineStyle );
298  mPen.setWidthF( mOutlineWidth * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOutlineWidthUnit, mOutlineWidthMapUnitScale ) );
299  mBrush.setColor( mFillColor );
300  prepareExpressions( context.fields(), context.renderContext().rendererScale() );
301 }
302 
304 {
305 }
306 
308 {
310 }
311 
313 {
314  QDomElement symbolizerElem = doc.createElement( "se:PointSymbolizer" );
315  if ( !props.value( "uom", "" ).isEmpty() )
316  symbolizerElem.setAttribute( "uom", props.value( "uom", "" ) );
317  element.appendChild( symbolizerElem );
318 
319  // <Geometry>
320  QgsSymbolLayerV2Utils::createGeometryElement( doc, symbolizerElem, props.value( "geom", "" ) );
321 
322  writeSldMarker( doc, symbolizerElem, props );
323 }
324 
326 {
327  // <Graphic>
328  QDomElement graphicElem = doc.createElement( "se:Graphic" );
329  element.appendChild( graphicElem );
330 
331  QgsSymbolLayerV2Utils::wellKnownMarkerToSld( doc, graphicElem, mSymbolName, mFillColor, mOutlineColor, mOutlineStyle, mOutlineWidth, mSymbolWidth );
332 
333  // store w/h factor in a <VendorOption>
334  double widthHeightFactor = mSymbolWidth / mSymbolHeight;
335  QDomElement factorElem = QgsSymbolLayerV2Utils::createVendorOptionElement( doc, "widthHeightFactor", QString::number( widthHeightFactor ) );
336  graphicElem.appendChild( factorElem );
337 
338  // <Rotation>
340 
341  QString angleFunc = props.value( "angle", "" );
342  if ( angleFunc.isEmpty() ) // symbol has no angle set
343  {
344  if ( ddRotation && ddRotation->isActive() )
345  {
346  angleFunc = ddRotation->useExpression() ? ddRotation->expressionString() : ddRotation->field();
347  }
348  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
349  angleFunc = QString::number( mAngle );
350  }
351  else if ( ddRotation && ddRotation->isActive() )
352  {
353  // the symbol has an angle and the symbol layer have a rotation
354  // property set
355  angleFunc = QString( "%1 + %2" ).arg( angleFunc ).arg( ddRotation->useExpression() ? ddRotation->expressionString() : ddRotation->field() );
356  }
357  else if ( !qgsDoubleNear( mAngle, 0.0 ) )
358  {
359  // both the symbol and the symbol layer have angle value set
360  bool ok;
361  double angle = angleFunc.toDouble( &ok );
362  if ( !ok )
363  {
364  // its a string (probably a property name or a function)
365  angleFunc = QString( "%1 + %2" ).arg( angleFunc ).arg( mAngle );
366  }
367  else if ( !qgsDoubleNear( angle + mAngle, 0.0 ) )
368  {
369  // it's a double value
370  angleFunc = QString::number( angle + mAngle );
371  }
372  }
373  QgsSymbolLayerV2Utils::createRotationElement( doc, graphicElem, angleFunc );
374 }
375 
377 {
378  QgsDebugMsg( "Entered." );
379 
380  QDomElement graphicElem = element.firstChildElement( "Graphic" );
381  if ( graphicElem.isNull() )
382  return NULL;
383 
384  QString name = "circle";
385  QColor fillColor, borderColor;
386  double borderWidth, size;
387  double widthHeightFactor = 1.0;
388  Qt::PenStyle borderStyle;
389 
390  QgsStringMap vendorOptions = QgsSymbolLayerV2Utils::getVendorOptionList( graphicElem );
391  for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
392  {
393  if ( it.key() == "widthHeightFactor" )
394  {
395  bool ok;
396  double v = it.value().toDouble( &ok );
397  if ( ok && !qgsDoubleNear( v, 0.0 ) && v > 0 )
398  widthHeightFactor = v;
399  }
400  }
401 
402  if ( !QgsSymbolLayerV2Utils::wellKnownMarkerFromSld( graphicElem, name, fillColor, borderColor, borderStyle, borderWidth, size ) )
403  return NULL;
404 
405  double angle = 0.0;
406  QString angleFunc;
407  if ( QgsSymbolLayerV2Utils::rotationFromSldElement( graphicElem, angleFunc ) )
408  {
409  bool ok;
410  double d = angleFunc.toDouble( &ok );
411  if ( ok )
412  angle = d;
413  }
414 
416  m->setSymbolName( name );
417  m->setFillColor( fillColor );
418  m->setOutlineColor( borderColor );
419  m->setOutlineStyle( borderStyle );
420  m->setOutlineWidth( borderWidth );
421  m->setSymbolWidth( size );
422  m->setSymbolHeight( size / widthHeightFactor );
423  m->setAngle( angle );
424  return m;
425 }
426 
428 {
429  QgsStringMap map;
430  map["symbol_name"] = mSymbolName;
431  map["symbol_width"] = QString::number( mSymbolWidth );
432  map["symbol_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSymbolWidthUnit );
433  map["symbol_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSymbolWidthMapUnitScale );
434  map["symbol_height"] = QString::number( mSymbolHeight );
435  map["symbol_height_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mSymbolHeightUnit );
436  map["symbol_height_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSymbolHeightMapUnitScale );
437  map["angle"] = QString::number( mAngle );
438  map["outline_style"] = QgsSymbolLayerV2Utils::encodePenStyle( mOutlineStyle );
439  map["outline_width"] = QString::number( mOutlineWidth );
440  map["outline_width_unit"] = QgsSymbolLayerV2Utils::encodeOutputUnit( mOutlineWidthUnit );
441  map["outline_width_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOutlineWidthMapUnitScale );
442  map["color"] = QgsSymbolLayerV2Utils::encodeColor( mFillColor );
443  map["outline_color"] = QgsSymbolLayerV2Utils::encodeColor( mOutlineColor );
444  map["offset"] = QgsSymbolLayerV2Utils::encodePoint( mOffset );
446  map["offset_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mOffsetMapUnitScale );
447  map["size"] = QString::number( mSize );
449  map["size_map_unit_scale"] = QgsSymbolLayerV2Utils::encodeMapUnitScale( mSizeMapUnitScale );
450  map["horizontal_anchor_point"] = QString::number( mHorizontalAnchorPoint );
451  map["vertical_anchor_point"] = QString::number( mVerticalAnchorPoint );
453  return map;
454 }
455 
456 void QgsEllipseSymbolLayerV2::preparePath( const QString& symbolName, QgsSymbolV2RenderContext& context, double* scaledWidth, double* scaledHeight, const QgsFeature* f )
457 {
458  mPainterPath = QPainterPath();
459  const QgsRenderContext& ct = context.renderContext();
460 
461  double width = 0;
462 
463  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
464  {
466  }
467  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
468  {
469  width = mSize;
470  }
471  else //3. priority: global width setting
472  {
473  width = mSymbolWidth;
474  }
475  if ( scaledWidth )
476  {
477  *scaledWidth = width;
478  }
479  width *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( ct, mSymbolWidthUnit, mSymbolHeightMapUnitScale );
480 
481  double height = 0;
482  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
483  {
485  }
486  else if ( context.renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
487  {
488  height = mSize;
489  }
490  else //3. priority: global height setting
491  {
492  height = mSymbolHeight;
493  }
494  if ( scaledHeight )
495  {
496  *scaledHeight = height;
497  }
498  height *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( ct, mSymbolHeightUnit, mSymbolHeightMapUnitScale );
499 
500  if ( symbolName == "circle" )
501  {
502  mPainterPath.addEllipse( QRectF( -width / 2.0, -height / 2.0, width, height ) );
503  }
504  else if ( symbolName == "rectangle" )
505  {
506  mPainterPath.addRect( QRectF( -width / 2.0, -height / 2.0, width, height ) );
507  }
508  else if ( symbolName == "cross" )
509  {
510  mPainterPath.moveTo( 0, -height / 2.0 );
511  mPainterPath.lineTo( 0, height / 2.0 );
512  mPainterPath.moveTo( -width / 2.0, 0 );
513  mPainterPath.lineTo( width / 2.0, 0 );
514  }
515  else if ( symbolName == "triangle" )
516  {
517  mPainterPath.moveTo( 0, -height / 2.0 );
518  mPainterPath.lineTo( -width / 2.0, height / 2.0 );
519  mPainterPath.lineTo( width / 2.0, height / 2.0 );
520  mPainterPath.lineTo( 0, -height / 2.0 );
521  }
522 }
523 
525 {
527  mSymbolWidthUnit = unit;
528  mSymbolHeightUnit = unit;
529  mOutlineWidthUnit = unit;
530 }
531 
533 {
535  if ( mSymbolWidthUnit != unit || mSymbolHeightUnit != unit || mOutlineWidthUnit != unit )
536  {
537  return QgsSymbolV2::Mixed;
538  }
539  return unit;
540 }
541 
543 {
545  mSymbolWidthMapUnitScale = scale;
546  mSymbolHeightMapUnitScale = scale;
547  mOutlineWidthMapUnitScale = scale;
548 }
549 
551 {
552  if ( QgsMarkerSymbolLayerV2::mapUnitScale() == mSymbolWidthMapUnitScale &&
553  mSymbolWidthMapUnitScale == mSymbolHeightMapUnitScale &&
554  mSymbolHeightMapUnitScale == mOutlineWidthMapUnitScale )
555  {
556  return mSymbolWidthMapUnitScale;
557  }
558  return QgsMapUnitScale();
559 }
560 
561 bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, const QgsSymbolV2RenderContext* context, const QgsFeature* f, const QPointF& shift ) const
562 {
563  //width
564  double symbolWidth = mSymbolWidth;
565 
566  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le
567  {
568  symbolWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, f, mSymbolWidth ).toDouble();
569  }
570  else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
571  {
572  symbolWidth = mSize;
573  }
574  if ( mSymbolWidthUnit == QgsSymbolV2::MM )
575  {
576  symbolWidth *= mmMapUnitScaleFactor;
577  }
578 
579  //height
580  double symbolHeight = mSymbolHeight;
581  if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level
582  {
583  symbolHeight = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, f, mSymbolHeight ).toDouble();
584  }
585  else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level
586  {
587  symbolHeight = mSize;
588  }
589  if ( mSymbolHeightUnit == QgsSymbolV2::MM )
590  {
591  symbolHeight *= mmMapUnitScaleFactor;
592  }
593 
594  //outline width
595  double outlineWidth = mOutlineWidth;
596 
598  {
599  outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, f, mOutlineWidth ).toDouble();
600  }
601  if ( mOutlineWidthUnit == QgsSymbolV2::MM )
602  {
603  outlineWidth *= outlineWidth;
604  }
605 
606  //fill color
607  bool ok;
608  QColor fc = mFillColor;
610  {
612  if ( ok )
613  fc = QColor( colorString );
614  }
615 
616  //outline color
617  QColor oc = mOutlineColor;
619  {
621  if ( ok )
622  oc = QColor( colorString );
623  }
624 
625  //symbol name
626  QString symbolName = mSymbolName;
628  {
630  }
631 
632  //offset
633  double offsetX = 0;
634  double offsetY = 0;
635  markerOffset( *context, offsetX, offsetY );
636  QPointF off( offsetX, offsetY );
637 
638  //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle)
639  double rotation = 0.0;
641  {
643  }
644  else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) )
645  {
646  rotation = mAngle + mLineAngle;
647  }
648  rotation = -rotation; //rotation in Qt is counterclockwise
649  if ( rotation )
650  off = _rotatedOffset( off, rotation );
651 
652  QTransform t;
653  t.translate( shift.x() + offsetX, shift.y() + offsetY );
654 
655  if ( rotation != 0 )
656  t.rotate( rotation );
657 
658  double halfWidth = symbolWidth / 2.0;
659  double halfHeight = symbolHeight / 2.0;
660 
661  if ( symbolName == "circle" )
662  {
663  if ( qgsDoubleNear( halfWidth, halfHeight ) )
664  {
665  QPointF pt( t.map( QPointF( 0, 0 ) ) );
666  e.writeFilledCircle( layerName, oc, pt, halfWidth );
667  }
668  else
669  {
670  QgsPolyline line;
671  double stepsize = 2 * M_PI / 40;
672  for ( int i = 0; i < 39; ++i )
673  {
674  double angle = stepsize * i;
675  double x = halfWidth * cos( angle );
676  double y = halfHeight * sin( angle );
677  QPointF pt( t.map( QPointF( x, y ) ) );
678  line.push_back( pt );
679  }
680  //close ellipse with first point
681  line.push_back( line.at( 0 ) );
682  if ( mBrush.style() != Qt::NoBrush )
683  e.writePolygon( QgsPolygon() << line, layerName, "SOLID", fc );
684  if ( mPen.style() != Qt::NoPen )
685  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
686  }
687  }
688  else if ( symbolName == "rectangle" )
689  {
690  QgsPolygon p( 1 );
691  p[0].resize( 5 );
692  p[0][0] = t.map( QPointF( -halfWidth, -halfHeight ) );
693  p[0][1] = t.map( QPointF( halfWidth, -halfHeight ) );
694  p[0][2] = t.map( QPointF( halfWidth, halfHeight ) );
695  p[0][3] = t.map( QPointF( -halfWidth, halfHeight ) );
696  p[0][4] = p[0][0];
697  if ( mBrush.style() != Qt::NoBrush )
698  e.writePolygon( p, layerName, "SOLID", fc );
699  if ( mPen.style() != Qt::NoPen )
700  e.writePolyline( p[0], layerName, "CONTINUOUS", oc, outlineWidth );
701  return true;
702  }
703  else if ( symbolName == "cross" && mPen.style() != Qt::NoPen )
704  {
705  QgsPolyline line( 2 );
706  line[0] = t.map( QPointF( -halfWidth, 0 ) );
707  line[1] = t.map( QPointF( halfWidth, 0 ) );
708  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
709 
710  line[0] = t.map( QPointF( 0, halfHeight ) );
711  line[1] = t.map( QPointF( 0, -halfHeight ) );
712  e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth );
713 
714  return true;
715  }
716  else if ( symbolName == "triangle" )
717  {
718  QgsPolygon p( 1 );
719  p[0].resize( 4 );
720  p[0][0] = QPointF( t.map( QPointF( -halfWidth, -halfHeight ) ) );
721  p[0][1] = QPointF( t.map( QPointF( halfWidth, -halfHeight ) ) );
722  p[0][2] = QPointF( t.map( QPointF( 0, halfHeight ) ) );
723  p[0][3] = p[0][0];
724  if ( mBrush.style() != Qt::NoBrush )
725  e.writePolygon( p, layerName, "SOLID", fc );
726  if ( mPen.style() != Qt::NoPen )
727  e.writePolyline( p[0], layerName, "CONTINUOUS", oc, outlineWidth );
728  return true;
729  }
730 
731  return false; //soon...
732 }
733 
734 
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 toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) 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)
int renderHints() const
Definition: qgssymbolv2.h:258
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)
Qt::BrushStyle style() const
QString field() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QPoint map(const QPoint &point) const
void writePolygon(const QgsPolygon &polygon, const QString &layer, const QString &hatchPattern, QColor color)
Draw dxf polygon (HATCH)
static void createRotationElement(QDomDocument &doc, QDomElement &element, QString rotationFunc)
double rendererScale() const
static const QString EXPR_WIDTH
static QgsStringMap getVendorOptionList(QDomElement &element)
void setOffset(QPointF offset)
void setOutlineWidthUnit(QgsSymbolV2::OutputUnit unit)
void setHorizontalAnchorPoint(HorizontalAnchorPoint h)
bool writeDxf(QgsDxfExport &e, double mmMapUnitScaleFactor, const QString &layerName, const QgsSymbolV2RenderContext *context, const QgsFeature *f, const QPointF &shift=QPointF(0.0, 0.0)) const override
static QPointF decodePoint(QString str)
void setVerticalAnchorPoint(VerticalAnchorPoint v)
void setJoinStyle(Qt::PenJoinStyle style)
void moveTo(const QPointF &point)
static QDomElement createVendorOptionElement(QDomDocument &doc, QString name, QString value)
static QColor decodeColor(QString str)
QString expressionString() const
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:162
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
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Definition: qgis.h:350
void setMapUnitScale(const QgsMapUnitScale &scale) override
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
static QString encodeColor(QColor color)
void setMapUnitScale(const QgsMapUnitScale &scale) override
static QString encodePenStyle(Qt::PenStyle style)
void setSymbolHeightMapUnitScale(const QgsMapUnitScale &scale)
QTransform & translate(qreal dx, qreal dy)
QString number(int n, int base)
static const QString EXPR_FILL_COLOR
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:263
static QString encodePoint(QPointF point)
static Qt::PenStyle decodePenStyle(QString str)
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)
HorizontalAnchorPoint mHorizontalAnchorPoint
iterator end()
void setOutlineStyle(Qt::PenStyle outlineStyle)
void setColor(const QColor &color)
void setSymbolName(const QString &name)
virtual 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 const QString EXPR_OUTLINE_STYLE
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
bool useExpression() const
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)
static void createGeometryElement(QDomDocument &doc, QDomElement &element, QString geomFunc)
Contains information about the context of a rendering operation.
QPainter * painter()
void drawPath(const QPainterPath &path)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
static double lineWidthScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns the line width scale factor depending on the unit and the paint device.
void setWidth(int width)
virtual 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.
QgsMapUnitScale mapUnitScale() const override
void setSymbolWidthMapUnitScale(const QgsMapUnitScale &scale)
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:241
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 writeFilledCircle(const QString &layer, QColor color, const QgsPoint &pt, double radius)
Write filled circle (as hatch)
static const QString EXPR_ROTATION
static Q_DECL_DEPRECATED void wellKnownMarkerToSld(QDomDocument &doc, QDomElement &element, QString name, QColor color, QColor borderColor=QColor(), double borderWidth=-1, double size=-1)
const QgsFields * fields() const
Fields of the layer.
Definition: qgssymbolv2.h:269
void push_back(const T &value)
QgsSymbolV2::OutputUnit mOffsetUnit
static bool rotationFromSldElement(QDomElement &element, QString &rotationFunc)
double toDouble(bool *ok) const
VerticalAnchorPoint mVerticalAnchorPoint
void stopRender(QgsSymbolV2RenderContext &context) override
QgsSymbolV2::OutputUnit mSizeUnit
QgsMapUnitScale mOffsetMapUnitScale
void markerOffset(const QgsSymbolV2RenderContext &context, double &offsetX, double &offsetY) const
void restoreDataDefinedProperties(const QgsStringMap &stringMap)
Restores all data defined properties from string map.
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
QString layerType() const override
void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) 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 writePolyline(const QgsPolyline &line, const QString &layer, const QString &lineStyleName, QColor color, double width=-1)
Draw dxf primitives (LWPOLYLINE)
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 QgsSymbolV2::OutputUnit decodeOutputUnit(QString str)
static const QString EXPR_HEIGHT
const T value(const Key &key) const
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)