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