QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgssymbol.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbol.cpp
3  ---------------------
4  begin : November 2009
5  copyright : (C) 2009 by Martin Dobias
6  email : wonder dot sk at gmail dot com
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  ***************************************************************************/
15 
16 #include <QColor>
17 #include <QImage>
18 #include <QPainter>
19 #include <QSize>
20 #include <QSvgGenerator>
21 
22 #include <cmath>
23 #include <map>
24 #include <random>
25 
26 #include "qgssymbol.h"
27 #include "qgssymbollayer.h"
28 
29 #include "qgslinesymbollayer.h"
30 #include "qgsmarkersymbollayer.h"
31 #include "qgsfillsymbollayer.h"
34 #include "qgslogger.h"
35 #include "qgsrendercontext.h" // for bigSymbolPreview
36 #include "qgsproject.h"
37 #include "qgsstyle.h"
38 #include "qgspainteffect.h"
39 #include "qgseffectstack.h"
40 #include "qgsvectorlayer.h"
41 #include "qgsfeature.h"
42 #include "qgsgeometry.h"
43 #include "qgsmultipoint.h"
44 #include "qgsgeometrycollection.h"
45 #include "qgslinestring.h"
46 #include "qgspolygon.h"
47 #include "qgsclipper.h"
48 #include "qgsproperty.h"
49 #include "qgscolorschemeregistry.h"
50 #include "qgsapplication.h"
52 
53 inline
54 QgsProperty rotateWholeSymbol( double additionalRotation, const QgsProperty &property )
55 {
56  QString exprString = property.asExpression();
57  return QgsProperty::fromExpression( QString::number( additionalRotation ) + " + (" + exprString + ')' );
58 }
59 
60 inline
61 QgsProperty scaleWholeSymbol( double scaleFactor, const QgsProperty &property )
62 {
63  QString exprString = property.asExpression();
64  return QgsProperty::fromExpression( QString::number( scaleFactor ) + "*(" + exprString + ')' );
65 }
66 
67 inline
68 QgsProperty scaleWholeSymbol( double scaleFactorX, double scaleFactorY, const QgsProperty &property )
69 {
70  QString exprString = property.asExpression();
72  ( !qgsDoubleNear( scaleFactorX, 0.0 ) ? "tostring(" + QString::number( scaleFactorX ) + "*(" + exprString + "))" : QStringLiteral( "'0'" ) ) +
73  "|| ',' || " +
74  ( !qgsDoubleNear( scaleFactorY, 0.0 ) ? "tostring(" + QString::number( scaleFactorY ) + "*(" + exprString + "))" : QStringLiteral( "'0'" ) ) );
75 }
76 
77 
79 
80 Q_NOWARN_DEPRECATED_PUSH // because of deprecated mLayer
82  : mType( type )
83  , mLayers( layers )
84 {
85 
86  // check they're all correct symbol layers
87  for ( int i = 0; i < mLayers.count(); i++ )
88  {
89  if ( !mLayers.at( i ) )
90  {
91  mLayers.removeAt( i-- );
92  }
93  else if ( !mLayers.at( i )->isCompatibleWithSymbol( this ) )
94  {
95  delete mLayers.at( i );
96  mLayers.removeAt( i-- );
97  }
98  }
99 }
101 
102 QPolygonF QgsSymbol::_getLineString( QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent )
103 {
104  const unsigned int nPoints = curve.numPoints();
105 
107  const QgsMapToPixel &mtp = context.mapToPixel();
108  QPolygonF pts;
109 
110  //apply clipping for large lines to achieve a better rendering performance
111  if ( clipToExtent && nPoints > 1 )
112  {
113  const QgsRectangle &e = context.extent();
114  const double cw = e.width() / 10;
115  const double ch = e.height() / 10;
116  const QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
117  pts = QgsClipper::clippedLine( curve, clipRect );
118  }
119  else
120  {
121  pts = curve.asQPolygonF();
122  }
123 
124  //transform the QPolygonF to screen coordinates
125  if ( ct.isValid() )
126  {
127  try
128  {
129  ct.transformPolygon( pts );
130  }
131  catch ( QgsCsException & )
132  {
133  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
134  }
135  }
136 
137  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
138  pts.erase( std::remove_if( pts.begin(), pts.end(),
139  []( const QPointF point )
140  {
141  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
142  } ), pts.end() );
143 
144  QPointF *ptr = pts.data();
145  for ( int i = 0; i < pts.size(); ++i, ++ptr )
146  {
147  mtp.transformInPlace( ptr->rx(), ptr->ry() );
148  }
149 
150  return pts;
151 }
152 
153 QPolygonF QgsSymbol::_getPolygonRing( QgsRenderContext &context, const QgsCurve &curve, const bool clipToExtent, const bool isExteriorRing, const bool correctRingOrientation )
154 {
155  const QgsCoordinateTransform ct = context.coordinateTransform();
156  const QgsMapToPixel &mtp = context.mapToPixel();
157  const QgsRectangle &e = context.extent();
158  const double cw = e.width() / 10;
159  const double ch = e.height() / 10;
160  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
161 
162  QPolygonF poly = curve.asQPolygonF();
163 
164  if ( curve.numPoints() < 1 )
165  return QPolygonF();
166 
167  if ( correctRingOrientation )
168  {
169  // ensure consistent polygon ring orientation
170  if ( isExteriorRing && curve.orientation() != QgsCurve::Clockwise )
171  std::reverse( poly.begin(), poly.end() );
172  else if ( !isExteriorRing && curve.orientation() != QgsCurve::CounterClockwise )
173  std::reverse( poly.begin(), poly.end() );
174  }
175 
176  //clip close to view extent, if needed
177  const QRectF ptsRect = poly.boundingRect();
178  if ( clipToExtent && !context.extent().contains( ptsRect ) )
179  {
180  QgsClipper::trimPolygon( poly, clipRect );
181  }
182 
183  //transform the QPolygonF to screen coordinates
184  if ( ct.isValid() )
185  {
186  try
187  {
188  ct.transformPolygon( poly );
189  }
190  catch ( QgsCsException & )
191  {
192  // we don't abort the rendering here, instead we remove any invalid points and just plot those which ARE valid
193  }
194  }
195 
196  // remove non-finite points, e.g. infinite or NaN points caused by reprojecting errors
197  poly.erase( std::remove_if( poly.begin(), poly.end(),
198  []( const QPointF point )
199  {
200  return !std::isfinite( point.x() ) || !std::isfinite( point.y() );
201  } ), poly.end() );
202 
203  QPointF *ptr = poly.data();
204  for ( int i = 0; i < poly.size(); ++i, ++ptr )
205  {
206  mtp.transformInPlace( ptr->rx(), ptr->ry() );
207  }
208 
209  return poly;
210 }
211 
212 void QgsSymbol::_getPolygon( QPolygonF &pts, QList<QPolygonF> &holes, QgsRenderContext &context, const QgsPolygon &polygon, const bool clipToExtent, const bool correctRingOrientation )
213 {
214  holes.clear();
215 
216  pts = _getPolygonRing( context, *polygon.exteriorRing(), clipToExtent, true, correctRingOrientation );
217  for ( int idx = 0; idx < polygon.numInteriorRings(); idx++ )
218  {
219  const QPolygonF hole = _getPolygonRing( context, *( polygon.interiorRing( idx ) ), clipToExtent, false, correctRingOrientation );
220  if ( !hole.isEmpty() ) holes.append( hole );
221  }
222 }
223 
225 {
226  // delete all symbol layers (we own them, so it's okay)
227  qDeleteAll( mLayers );
228 }
229 
231 {
232  if ( mLayers.empty() )
233  {
235  }
236 
237  QgsSymbolLayerList::const_iterator it = mLayers.constBegin();
238 
239  QgsUnitTypes::RenderUnit unit = ( *it )->outputUnit();
240 
241  for ( ; it != mLayers.constEnd(); ++it )
242  {
243  if ( ( *it )->outputUnit() != unit )
244  {
246  }
247  }
248  return unit;
249 }
250 
252 {
253  if ( mLayers.empty() )
254  {
255  return QgsMapUnitScale();
256  }
257 
258  QgsSymbolLayerList::const_iterator it = mLayers.constBegin();
259  if ( it == mLayers.constEnd() )
260  return QgsMapUnitScale();
261 
262  QgsMapUnitScale scale = ( *it )->mapUnitScale();
263  ++it;
264 
265  for ( ; it != mLayers.constEnd(); ++it )
266  {
267  if ( ( *it )->mapUnitScale() != scale )
268  {
269  return QgsMapUnitScale();
270  }
271  }
272  return scale;
273 }
274 
276 {
277  const auto constMLayers = mLayers;
278  for ( QgsSymbolLayer *layer : constMLayers )
279  {
280  layer->setOutputUnit( u );
281  }
282 }
283 
285 {
286  const auto constMLayers = mLayers;
287  for ( QgsSymbolLayer *layer : constMLayers )
288  {
289  layer->setMapUnitScale( scale );
290  }
291 }
292 
294 {
295  std::unique_ptr< QgsSymbol > s;
296 
297  // override global default if project has a default for this type
298  QString defaultSymbol;
299  switch ( geomType )
300  {
302  defaultSymbol = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Marker" ) );
303  break;
305  defaultSymbol = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Line" ) );
306  break;
308  defaultSymbol = QgsProject::instance()->readEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Fill" ) );
309  break;
310  default:
311  break;
312  }
313  if ( !defaultSymbol.isEmpty() )
314  s.reset( QgsStyle::defaultStyle()->symbol( defaultSymbol ) );
315 
316  // if no default found for this type, get global default (as previously)
317  if ( !s )
318  {
319  switch ( geomType )
320  {
322  s = qgis::make_unique< QgsMarkerSymbol >();
323  break;
325  s = qgis::make_unique< QgsLineSymbol >();
326  break;
328  s = qgis::make_unique< QgsFillSymbol >();
329  break;
330  default:
331  QgsDebugMsg( QStringLiteral( "unknown layer's geometry type" ) );
332  return nullptr;
333  }
334  }
335 
336  // set opacity
337  double opacity = 1.0;
338  bool ok = false;
339  // upgrade old setting
340  double alpha = QgsProject::instance()->readDoubleEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/AlphaInt" ), 255, &ok );
341  if ( ok )
342  opacity = alpha / 255.0;
343  double newOpacity = QgsProject::instance()->readDoubleEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/Opacity" ), 1.0, &ok );
344  if ( ok )
345  opacity = newOpacity;
346  s->setOpacity( opacity );
347 
348  // set random color, it project prefs allow
349  if ( defaultSymbol.isEmpty() ||
350  QgsProject::instance()->readBoolEntry( QStringLiteral( "DefaultStyles" ), QStringLiteral( "/RandomColors" ), true ) )
351  {
352  s->setColor( QgsApplication::colorSchemeRegistry()->fetchRandomStyleColor() );
353  }
354 
355  return s.release();
356 }
357 
359 {
360  return mLayers.value( layer );
361 }
362 
364 {
365  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
366  return false;
367 
368  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
369  return false;
370 
371  mLayers.insert( index, layer );
372  return true;
373 }
374 
375 
377 {
378  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
379  return false;
380 
381  mLayers.append( layer );
382  return true;
383 }
384 
385 
387 {
388  if ( index < 0 || index >= mLayers.count() )
389  return false;
390 
391  delete mLayers.at( index );
392  mLayers.removeAt( index );
393  return true;
394 }
395 
396 
398 {
399  if ( index < 0 || index >= mLayers.count() )
400  return nullptr;
401 
402  return mLayers.takeAt( index );
403 }
404 
405 
407 {
408  QgsSymbolLayer *oldLayer = mLayers.value( index );
409 
410  if ( oldLayer == layer )
411  return false;
412 
413  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
414  return false;
415 
416  delete oldLayer; // first delete the original layer
417  mLayers[index] = layer; // set new layer
418  return true;
419 }
420 
421 
422 void QgsSymbol::startRender( QgsRenderContext &context, const QgsFields &fields )
423 {
424  Q_ASSERT_X( !mStarted, "startRender", "Rendering has already been started for this symbol instance!" );
425  mStarted = true;
426 
427  mSymbolRenderContext.reset( new QgsSymbolRenderContext( context, outputUnit(), mOpacity, false, mRenderHints, nullptr, fields, mapUnitScale() ) );
428 
429  QgsSymbolRenderContext symbolContext( context, outputUnit(), mOpacity, false, mRenderHints, nullptr, fields, mapUnitScale() );
430 
431  std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::updateSymbolScope( this, new QgsExpressionContextScope() ) );
432  mSymbolRenderContext->setExpressionContextScope( scope.release() );
433 
434  const auto constMLayers = mLayers;
435  for ( QgsSymbolLayer *layer : constMLayers )
436  {
437  if ( !layer->enabled() )
438  continue;
439 
440  layer->prepareExpressions( symbolContext );
441  layer->startRender( symbolContext );
442  }
443 }
444 
446 {
447  Q_ASSERT_X( mStarted, "startRender", "startRender was not called for this symbol instance!" );
448  mStarted = false;
449 
450  Q_UNUSED( context )
451  if ( mSymbolRenderContext )
452  {
453  const auto constMLayers = mLayers;
454  for ( QgsSymbolLayer *layer : constMLayers )
455  {
456  if ( !layer->enabled() )
457  continue;
458 
459  layer->stopRender( *mSymbolRenderContext );
460  }
461  }
462 
463  mSymbolRenderContext.reset( nullptr );
464 
466  mLayer = nullptr;
468 }
469 
470 void QgsSymbol::setColor( const QColor &color )
471 {
472  const auto constMLayers = mLayers;
473  for ( QgsSymbolLayer *layer : constMLayers )
474  {
475  if ( !layer->isLocked() )
476  layer->setColor( color );
477  }
478 }
479 
480 QColor QgsSymbol::color() const
481 {
482  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
483  {
484  // return color of the first unlocked layer
485  if ( !( *it )->isLocked() )
486  return ( *it )->color();
487  }
488  return QColor( 0, 0, 0 );
489 }
490 
491 void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext )
492 {
493  QgsRenderContext context = customContext ? *customContext : QgsRenderContext::fromQPainter( painter );
494  context.setForceVectorOutput( true );
495  QgsSymbolRenderContext symbolContext( context, outputUnit(), mOpacity, false, mRenderHints, nullptr, QgsFields(), mapUnitScale() );
497 
498  if ( !customContext )
499  {
500  // if no render context was passed, build a minimal expression context
501  QgsExpressionContext expContext;
503  context.setExpressionContext( expContext );
504  }
505 
506  const auto constMLayers = mLayers;
507  for ( QgsSymbolLayer *layer : constMLayers )
508  {
509  if ( !layer->enabled() )
510  continue;
511 
512  if ( mType == Fill && layer->type() == Line )
513  {
514  // line symbol layer would normally draw just a line
515  // so we override this case to force it to draw a polygon stroke
516  QgsLineSymbolLayer *lsl = dynamic_cast<QgsLineSymbolLayer *>( layer );
517 
518  if ( lsl )
519  {
520  // from QgsFillSymbolLayer::drawPreviewIcon()
521  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
522  lsl->startRender( symbolContext );
523  lsl->renderPolygonStroke( poly, nullptr, symbolContext );
524  lsl->stopRender( symbolContext );
525  }
526  }
527  else
528  layer->drawPreviewIcon( symbolContext, size );
529  }
530 }
531 
532 void QgsSymbol::exportImage( const QString &path, const QString &format, QSize size )
533 {
534  if ( format.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
535  {
536  QSvgGenerator generator;
537  generator.setFileName( path );
538  generator.setSize( size );
539  generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) );
540 
541  QPainter painter( &generator );
542  drawPreviewIcon( &painter, size );
543  painter.end();
544  }
545  else
546  {
547  QImage image = asImage( size );
548  image.save( path );
549  }
550 }
551 
552 QImage QgsSymbol::asImage( QSize size, QgsRenderContext *customContext )
553 {
554  QImage image( size, QImage::Format_ARGB32_Premultiplied );
555  image.fill( 0 );
556 
557  QPainter p( &image );
558  p.setRenderHint( QPainter::Antialiasing );
559 
560  drawPreviewIcon( &p, size, customContext );
561 
562  return image;
563 }
564 
565 
567 {
568  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
569  preview.fill( 0 );
570 
571  QPainter p( &preview );
572  p.setRenderHint( QPainter::Antialiasing );
573  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising
574 
575  if ( mType == QgsSymbol::Marker )
576  {
577  p.setPen( QPen( Qt::gray ) );
578  p.drawLine( 0, 50, 100, 50 );
579  p.drawLine( 50, 0, 50, 100 );
580  }
581 
583  if ( expressionContext )
584  context.setExpressionContext( *expressionContext );
585 
586  startRender( context );
587 
588  if ( mType == QgsSymbol::Line )
589  {
590  QPolygonF poly;
591  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
592  static_cast<QgsLineSymbol *>( this )->renderPolyline( poly, nullptr, context );
593  }
594  else if ( mType == QgsSymbol::Fill )
595  {
596  QPolygonF polygon;
597  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
598  static_cast<QgsFillSymbol *>( this )->renderPolygon( polygon, nullptr, nullptr, context );
599  }
600  else // marker
601  {
602  static_cast<QgsMarkerSymbol *>( this )->renderPoint( QPointF( 50, 50 ), nullptr, context );
603  }
604 
605  stopRender( context );
606  return preview;
607 }
608 
609 
610 QString QgsSymbol::dump() const
611 {
612  QString t;
613  switch ( type() )
614  {
615  case QgsSymbol::Marker:
616  t = QStringLiteral( "MARKER" );
617  break;
618  case QgsSymbol::Line:
619  t = QStringLiteral( "LINE" );
620  break;
621  case QgsSymbol::Fill:
622  t = QStringLiteral( "FILL" );
623  break;
624  default:
625  Q_ASSERT( false && "unknown symbol type" );
626  }
627  QString s = QStringLiteral( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerUtils::encodeColor( color() ) );
628 
629  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
630  {
631  // TODO:
632  }
633  return s;
634 }
635 
636 void QgsSymbol::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
637 {
638  props[ QStringLiteral( "alpha" )] = QString::number( opacity() );
639  double scaleFactor = 1.0;
640  props[ QStringLiteral( "uom" )] = QgsSymbolLayerUtils::encodeSldUom( outputUnit(), &scaleFactor );
641  props[ QStringLiteral( "uomScale" )] = ( !qgsDoubleNear( scaleFactor, 1.0 ) ? qgsDoubleToString( scaleFactor ) : QString() );
642 
643  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
644  {
645  ( *it )->toSld( doc, element, props );
646  }
647 }
648 
650 {
651  QgsSymbolLayerList lst;
652  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
653  {
654  QgsSymbolLayer *layer = ( *it )->clone();
655  layer->setLocked( ( *it )->isLocked() );
656  layer->setRenderingPass( ( *it )->renderingPass() );
657  layer->setEnabled( ( *it )->enabled() );
658  lst.append( layer );
659  }
660  return lst;
661 }
662 
664 {
665  Q_ASSERT( layer->type() == Hybrid );
666 
668  return;
669 
670  QgsGeometryGeneratorSymbolLayer *generatorLayer = static_cast<QgsGeometryGeneratorSymbolLayer *>( layer );
671 
672  QgsPaintEffect *effect = generatorLayer->paintEffect();
673  if ( effect && effect->enabled() )
674  {
675  QgsEffectPainter p( context.renderContext(), effect );
676  generatorLayer->render( context );
677  }
678  else
679  {
680  generatorLayer->render( context );
681  }
682 }
683 
684 QSet<QString> QgsSymbol::usedAttributes( const QgsRenderContext &context ) const
685 {
686  QSet<QString> attributes;
687  QgsSymbolLayerList::const_iterator sIt = mLayers.constBegin();
688  for ( ; sIt != mLayers.constEnd(); ++sIt )
689  {
690  if ( *sIt )
691  {
692  attributes.unite( ( *sIt )->usedAttributes( context ) );
693  }
694  }
695  return attributes;
696 }
697 
699 {
700  const auto constMLayers = mLayers;
701  for ( QgsSymbolLayer *layer : constMLayers )
702  {
703  if ( layer->hasDataDefinedProperties() )
704  return true;
705  }
706  return false;
707 }
708 
710 {
712  mLayer = layer;
714 }
715 
717 {
719  return mLayer;
721 }
722 
724 
728 class ExpressionContextScopePopper
729 {
730  public:
731 
732  ExpressionContextScopePopper() = default;
733 
734  ~ExpressionContextScopePopper()
735  {
736  if ( context )
737  context->popScope();
738  }
739 
740  QgsExpressionContext *context = nullptr;
741 };
742 
746 class GeometryRestorer
747 {
748  public:
749  GeometryRestorer( QgsRenderContext &context )
750  : mContext( context ),
751  mGeometry( context.geometry() )
752  {}
753 
754  ~GeometryRestorer()
755  {
756  mContext.setGeometry( mGeometry );
757  }
758 
759  private:
760  QgsRenderContext &mContext;
761  const QgsAbstractGeometry *mGeometry;
762 };
764 
765 void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, double currentVertexMarkerSize )
766 {
767  if ( context.renderingStopped() )
768  return;
769 
770  const QgsGeometry geom = feature.geometry();
771  if ( geom.isNull() )
772  {
773  return;
774  }
775 
776  GeometryRestorer geomRestorer( context );
777  QgsGeometry segmentizedGeometry = geom;
778  bool usingSegmentizedGeometry = false;
779  context.setGeometry( geom.constGet() );
780 
781  bool tileMapRendering = context.testFlag( QgsRenderContext::RenderMapTile );
782 
783  //convert curve types to normal point/line/polygon ones
784  if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) )
785  {
787  if ( !g )
788  {
789  return;
790  }
791  segmentizedGeometry = QgsGeometry( g );
792  usingSegmentizedGeometry = true;
793  }
794 
795  mSymbolRenderContext->setGeometryPartCount( segmentizedGeometry.constGet()->partCount() );
796  mSymbolRenderContext->setGeometryPartNum( 1 );
797 
798  bool needsExpressionContext = hasDataDefinedProperties();
799  ExpressionContextScopePopper scopePopper;
800  if ( mSymbolRenderContext->expressionContextScope() )
801  {
802  if ( needsExpressionContext )
803  {
804  // this is somewhat nasty - by appending this scope here it's now owned
805  // by both mSymbolRenderContext AND context.expressionContext()
806  // the RAII scopePopper is required to make sure it always has ownership transferred back
807  // from context.expressionContext(), even if exceptions of other early exits occur in this
808  // function
809  context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
810  scopePopper.context = &context.expressionContext();
811 
812  QgsExpressionContextUtils::updateSymbolScope( this, mSymbolRenderContext->expressionContextScope() );
813  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext->geometryPartCount(), true ) );
814  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, 1, true ) );
815  }
816  }
817 
818  // Collection of markers to paint, only used for no curve types.
819  QPolygonF markers;
820 
821  // Simplify the geometry, if needed.
823  {
824  const int simplifyHints = context.vectorSimplifyMethod().simplifyHints();
825  const QgsMapToPixelSimplifier simplifier( simplifyHints, context.vectorSimplifyMethod().tolerance(),
827  segmentizedGeometry = simplifier.simplify( segmentizedGeometry );
828  }
829 
830  switch ( QgsWkbTypes::flatType( segmentizedGeometry.constGet()->wkbType() ) )
831  {
832  case QgsWkbTypes::Point:
833  {
834  if ( mType != QgsSymbol::Marker )
835  {
836  QgsDebugMsg( QStringLiteral( "point can be drawn only with marker symbol!" ) );
837  break;
838  }
839 
840  const QgsPoint *point = static_cast< const QgsPoint * >( segmentizedGeometry.constGet() );
841  const QPointF pt = _getPoint( context, *point );
842  static_cast<QgsMarkerSymbol *>( this )->renderPoint( pt, &feature, context, layer, selected );
843 
845  {
846  //draw debugging rect
847  context.painter()->setPen( Qt::red );
848  context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
849  context.painter()->drawRect( static_cast<QgsMarkerSymbol *>( this )->bounds( pt, context, feature ) );
850  }
851 
852  if ( drawVertexMarker && !usingSegmentizedGeometry )
853  {
854  markers << pt;
855  }
856  }
857  break;
859  {
860  if ( mType != QgsSymbol::Line )
861  {
862  QgsDebugMsg( QStringLiteral( "linestring can be drawn only with line symbol!" ) );
863  break;
864  }
865  const QgsCurve &curve = dynamic_cast<const QgsCurve &>( *segmentizedGeometry.constGet() );
866  const QPolygonF pts = _getLineString( context, curve, !tileMapRendering && clipFeaturesToExtent() );
867  static_cast<QgsLineSymbol *>( this )->renderPolyline( pts, &feature, context, layer, selected );
868 
869  if ( drawVertexMarker && !usingSegmentizedGeometry )
870  {
871  markers = pts;
872  }
873  }
874  break;
877  {
878  QPolygonF pts;
879  QList<QPolygonF> holes;
880  if ( mType != QgsSymbol::Fill )
881  {
882  QgsDebugMsg( QStringLiteral( "polygon can be drawn only with fill symbol!" ) );
883  break;
884  }
885  const QgsPolygon &polygon = dynamic_cast<const QgsPolygon &>( *segmentizedGeometry.constGet() );
886  if ( !polygon.exteriorRing() )
887  {
888  QgsDebugMsg( QStringLiteral( "cannot render polygon with no exterior ring" ) );
889  break;
890  }
891  _getPolygon( pts, holes, context, polygon, !tileMapRendering && clipFeaturesToExtent(), mForceRHR );
892  static_cast<QgsFillSymbol *>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
893 
894  if ( drawVertexMarker && !usingSegmentizedGeometry )
895  {
896  markers = pts;
897 
898  const auto constHoles = holes;
899  for ( const QPolygonF &hole : constHoles )
900  {
901  markers << hole;
902  }
903  }
904  }
905  break;
906 
908  {
909  if ( mType != QgsSymbol::Marker )
910  {
911  QgsDebugMsg( QStringLiteral( "multi-point can be drawn only with marker symbol!" ) );
912  break;
913  }
914 
915  const QgsMultiPoint &mp = static_cast< const QgsMultiPoint & >( *segmentizedGeometry.constGet() );
916 
917  if ( drawVertexMarker && !usingSegmentizedGeometry )
918  {
919  markers.reserve( mp.numGeometries() );
920  }
921 
922  for ( int i = 0; i < mp.numGeometries(); ++i )
923  {
924  if ( context.renderingStopped() )
925  break;
926 
927  mSymbolRenderContext->setGeometryPartNum( i + 1 );
928  if ( needsExpressionContext )
929  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, i + 1, true ) );
930 
931  const QgsPoint &point = static_cast< const QgsPoint & >( *mp.geometryN( i ) );
932  const QPointF pt = _getPoint( context, point );
933  static_cast<QgsMarkerSymbol *>( this )->renderPoint( pt, &feature, context, layer, selected );
934 
935  if ( drawVertexMarker && !usingSegmentizedGeometry )
936  {
937  markers.append( pt );
938  }
939  }
940  }
941  break;
942 
945  {
946  if ( mType != QgsSymbol::Line )
947  {
948  QgsDebugMsg( QStringLiteral( "multi-linestring can be drawn only with line symbol!" ) );
949  break;
950  }
951 
952  const QgsGeometryCollection &geomCollection = dynamic_cast<const QgsGeometryCollection &>( *segmentizedGeometry.constGet() );
953 
954  const unsigned int num = geomCollection.numGeometries();
955  for ( unsigned int i = 0; i < num; ++i )
956  {
957  if ( context.renderingStopped() )
958  break;
959 
960  mSymbolRenderContext->setGeometryPartNum( i + 1 );
961  if ( needsExpressionContext )
962  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, i + 1, true ) );
963 
964  context.setGeometry( geomCollection.geometryN( i ) );
965  const QgsCurve &curve = dynamic_cast<const QgsCurve &>( *geomCollection.geometryN( i ) );
966  const QPolygonF pts = _getLineString( context, curve, !tileMapRendering && clipFeaturesToExtent() );
967  static_cast<QgsLineSymbol *>( this )->renderPolyline( pts, &feature, context, layer, selected );
968 
969  if ( drawVertexMarker && !usingSegmentizedGeometry )
970  {
971  markers << pts;
972  }
973  }
974  }
975  break;
976 
979  {
980  if ( mType != QgsSymbol::Fill )
981  {
982  QgsDebugMsg( QStringLiteral( "multi-polygon can be drawn only with fill symbol!" ) );
983  break;
984  }
985 
986  QPolygonF pts;
987  QList<QPolygonF> holes;
988 
989  const QgsGeometryCollection &geomCollection = dynamic_cast<const QgsGeometryCollection &>( *segmentizedGeometry.constGet() );
990  const unsigned int num = geomCollection.numGeometries();
991 
992  // Sort components by approximate area (probably a bit faster than using
993  // area() )
994  std::map<double, QList<unsigned int> > mapAreaToPartNum;
995  for ( unsigned int i = 0; i < num; ++i )
996  {
997  const QgsPolygon &polygon = dynamic_cast<const QgsPolygon &>( *geomCollection.geometryN( i ) );
998  const QgsRectangle r( polygon.boundingBox() );
999  mapAreaToPartNum[ r.width() * r.height()] << i;
1000  }
1001 
1002  // Draw starting with larger parts down to smaller parts, so that in
1003  // case of a part being incorrectly inside another part, it is drawn
1004  // on top of it (#15419)
1005  std::map<double, QList<unsigned int> >::const_reverse_iterator iter = mapAreaToPartNum.rbegin();
1006  for ( ; iter != mapAreaToPartNum.rend(); ++iter )
1007  {
1008  const QList<unsigned int> &listPartIndex = iter->second;
1009  for ( int idx = 0; idx < listPartIndex.size(); ++idx )
1010  {
1011  if ( context.renderingStopped() )
1012  break;
1013 
1014  const unsigned i = listPartIndex[idx];
1015  mSymbolRenderContext->setGeometryPartNum( i + 1 );
1016  if ( needsExpressionContext )
1017  mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, i + 1, true ) );
1018 
1019  context.setGeometry( geomCollection.geometryN( i ) );
1020  const QgsPolygon &polygon = dynamic_cast<const QgsPolygon &>( *geomCollection.geometryN( i ) );
1021  if ( !polygon.exteriorRing() )
1022  break;
1023 
1024  _getPolygon( pts, holes, context, polygon, !tileMapRendering && clipFeaturesToExtent(), mForceRHR );
1025  static_cast<QgsFillSymbol *>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
1026 
1027  if ( drawVertexMarker && !usingSegmentizedGeometry )
1028  {
1029  markers << pts;
1030 
1031  const auto constHoles = holes;
1032  for ( const QPolygonF &hole : constHoles )
1033  {
1034  markers << hole;
1035  }
1036  }
1037  }
1038  }
1039  break;
1040  }
1042  {
1043  const QgsGeometryCollection &geomCollection = dynamic_cast<const QgsGeometryCollection &>( *segmentizedGeometry.constGet() );
1044  if ( geomCollection.numGeometries() == 0 )
1045  {
1046  // skip noise from empty geometry collections from simplification
1047  break;
1048  }
1049 
1050  FALLTHROUGH
1051  }
1052  default:
1053  QgsDebugMsg( QStringLiteral( "feature %1: unsupported wkb type %2/%3 for rendering" )
1054  .arg( feature.id() )
1055  .arg( QgsWkbTypes::displayString( geom.constGet()->wkbType() ) )
1056  .arg( geom.wkbType(), 0, 16 ) );
1057  }
1058 
1059  if ( drawVertexMarker )
1060  {
1061  if ( !markers.isEmpty() && !context.renderingStopped() )
1062  {
1063  const auto constMarkers = markers;
1064  for ( QPointF marker : constMarkers )
1065  {
1066  renderVertexMarker( marker, context, currentVertexMarkerType, currentVertexMarkerSize );
1067  }
1068  }
1069  else
1070  {
1072  const QgsMapToPixel &mtp = context.mapToPixel();
1073 
1074  QgsPoint vertexPoint;
1075  QgsVertexId vertexId;
1076  double x, y, z;
1077  QPointF mapPoint;
1078  while ( geom.constGet()->nextVertex( vertexId, vertexPoint ) )
1079  {
1080  //transform
1081  x = vertexPoint.x();
1082  y = vertexPoint.y();
1083  z = 0.0;
1084  if ( ct.isValid() )
1085  {
1086  ct.transformInPlace( x, y, z );
1087  }
1088  mapPoint.setX( x );
1089  mapPoint.setY( y );
1090  mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
1091  renderVertexMarker( mapPoint, context, currentVertexMarkerType, currentVertexMarkerSize );
1092  }
1093  }
1094  }
1095 }
1096 
1098 {
1099  return mSymbolRenderContext.get();
1100 }
1101 
1102 void QgsSymbol::renderVertexMarker( QPointF pt, QgsRenderContext &context, int currentVertexMarkerType, double currentVertexMarkerSize )
1103 {
1104  int markerSize = context.convertToPainterUnits( currentVertexMarkerSize, QgsUnitTypes::RenderMillimeters );
1105  QgsSymbolLayerUtils::drawVertexMarker( pt.x(), pt.y(), *context.painter(), static_cast< QgsSymbolLayerUtils::VertexMarkerType >( currentVertexMarkerType ), markerSize );
1106 }
1107 
1109 
1110 
1112  : mRenderContext( c )
1113  , mOutputUnit( u )
1114  , mMapUnitScale( mapUnitScale )
1115  , mOpacity( opacity )
1116  , mSelected( selected )
1117  , mRenderHints( renderHints )
1118  , mFeature( f )
1119  , mFields( fields )
1120  , mGeometryPartCount( 0 )
1121  , mGeometryPartNum( 0 )
1122 {
1123 }
1124 
1126 {
1127  mRenderContext.expressionContext().setOriginalValueVariable( value );
1128 }
1129 
1130 double QgsSymbolRenderContext::outputLineWidth( double width ) const
1131 {
1132  return mRenderContext.convertToPainterUnits( width, mOutputUnit, mMapUnitScale );
1133 }
1134 
1135 double QgsSymbolRenderContext::outputPixelSize( double size ) const
1136 {
1137  return mRenderContext.convertToPainterUnits( size, mOutputUnit, mMapUnitScale );
1138 }
1139 
1141 {
1142  // This is just a dummy implementation of assignment.
1143  // sip 4.7 generates a piece of code that needs this function to exist.
1144  // It's not generated automatically by the compiler because of
1145  // mRenderContext member which is a reference (and thus can't be changed).
1146  Q_ASSERT( false );
1147  return *this;
1148 }
1149 
1151 {
1152  return mExpressionContextScope.get();
1153 }
1154 
1156 {
1157  mExpressionContextScope.reset( contextScope );
1158 }
1159 
1161 
1163 {
1165  if ( !sl )
1166  return nullptr;
1167 
1168  QgsSymbolLayerList layers;
1169  layers.append( sl );
1170  return new QgsMarkerSymbol( layers );
1171 }
1172 
1174 {
1176  if ( !sl )
1177  return nullptr;
1178 
1179  QgsSymbolLayerList layers;
1180  layers.append( sl );
1181  return new QgsLineSymbol( layers );
1182 }
1183 
1185 {
1187  if ( !sl )
1188  return nullptr;
1189 
1190  QgsSymbolLayerList layers;
1191  layers.append( sl );
1192  return new QgsFillSymbol( layers );
1193 }
1194 
1196 
1198  : QgsSymbol( Marker, layers )
1199 {
1200  if ( mLayers.isEmpty() )
1201  mLayers.append( new QgsSimpleMarkerSymbolLayer() );
1202 }
1203 
1204 void QgsMarkerSymbol::setAngle( double symbolAngle )
1205 {
1206  double origAngle = angle();
1207  double angleDiff = symbolAngle - origAngle;
1208  const auto constMLayers = mLayers;
1209  for ( QgsSymbolLayer *layer : constMLayers )
1210  {
1211  QgsMarkerSymbolLayer *markerLayer = dynamic_cast<QgsMarkerSymbolLayer *>( layer );
1212  if ( markerLayer )
1213  markerLayer->setAngle( markerLayer->angle() + angleDiff );
1214  }
1215 }
1216 
1218 {
1219  const auto constMLayers = mLayers;
1220  for ( QgsSymbolLayer *layer : constMLayers )
1221  {
1222  if ( layer->type() != QgsSymbol::Marker )
1223  continue;
1224  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1225  return markerLayer->angle();
1226  }
1227  return 0;
1228 }
1229 
1230 void QgsMarkerSymbol::setLineAngle( double lineAng )
1231 {
1232  const auto constMLayers = mLayers;
1233  for ( QgsSymbolLayer *layer : constMLayers )
1234  {
1235  if ( layer->type() != QgsSymbol::Marker )
1236  continue;
1237  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1238  markerLayer->setLineAngle( lineAng );
1239  }
1240 }
1241 
1243 {
1244  const double symbolRotation = angle();
1245 
1246  const auto constMLayers = mLayers;
1247  for ( QgsSymbolLayer *layer : constMLayers )
1248  {
1249  if ( layer->type() != QgsSymbol::Marker )
1250  continue;
1251  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1252  if ( !property )
1253  {
1254  layer->setDataDefinedProperty( QgsSymbolLayer::PropertyAngle, QgsProperty() );
1255  }
1256  else
1257  {
1258  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1259  {
1260  layer->setDataDefinedProperty( QgsSymbolLayer::PropertyAngle, property );
1261  }
1262  else
1263  {
1264  QgsProperty rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, property );
1265  layer->setDataDefinedProperty( QgsSymbolLayer::PropertyAngle, rotatedDD );
1266  }
1267  }
1268  }
1269 }
1270 
1272 {
1273  const double symbolRotation = angle();
1274  QgsProperty symbolDD;
1275 
1276  // find the base of the "en masse" pattern
1277  const auto layers = mLayers;
1278  for ( QgsSymbolLayer *layer : layers )
1279  {
1280  if ( layer->type() != QgsSymbol::Marker )
1281  continue;
1282  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1283  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) && markerLayer->dataDefinedProperties().isActive( QgsSymbolLayer::PropertyAngle ) )
1284  {
1285  symbolDD = markerLayer->dataDefinedProperties().property( QgsSymbolLayer::PropertyAngle );
1286  break;
1287  }
1288  }
1289 
1290  if ( !symbolDD )
1291  return QgsProperty();
1292 
1293  // check that all layer's angle expressions match the "en masse" pattern
1294  for ( QgsSymbolLayer *layer : layers )
1295  {
1296  if ( layer->type() != QgsSymbol::Marker )
1297  continue;
1298  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1299 
1301 
1302  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1303  {
1304  if ( !layerAngleDD || layerAngleDD != symbolDD )
1305  return QgsProperty();
1306  }
1307  else
1308  {
1309  QgsProperty rotatedDD( rotateWholeSymbol( markerLayer->angle() - symbolRotation, symbolDD ) );
1310  if ( !layerAngleDD || layerAngleDD != rotatedDD )
1311  return QgsProperty();
1312  }
1313  }
1314  return symbolDD;
1315 }
1316 
1317 
1319 {
1320  double origSize = size();
1321 
1322  const auto constMLayers = mLayers;
1323  for ( QgsSymbolLayer *layer : constMLayers )
1324  {
1325  if ( layer->type() != QgsSymbol::Marker )
1326  continue;
1327  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1328  if ( qgsDoubleNear( markerLayer->size(), origSize ) )
1329  markerLayer->setSize( s );
1330  else if ( !qgsDoubleNear( origSize, 0.0 ) )
1331  {
1332  // proportionally scale size
1333  markerLayer->setSize( markerLayer->size() * s / origSize );
1334  }
1335  // also scale offset to maintain relative position
1336  if ( !qgsDoubleNear( origSize, 0.0 ) && ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) ) )
1337  markerLayer->setOffset( QPointF( markerLayer->offset().x() * s / origSize,
1338  markerLayer->offset().y() * s / origSize ) );
1339  }
1340 }
1341 
1343 {
1344  // return size of the largest symbol
1345  double maxSize = 0;
1346  const auto constMLayers = mLayers;
1347  for ( QgsSymbolLayer *layer : constMLayers )
1348  {
1349  if ( layer->type() != QgsSymbol::Marker )
1350  continue;
1351  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1352  double lsize = markerLayer->size();
1353  if ( lsize > maxSize )
1354  maxSize = lsize;
1355  }
1356  return maxSize;
1357 }
1358 
1359 double QgsMarkerSymbol::size( const QgsRenderContext &context ) const
1360 {
1361  // return size of the largest symbol
1362  double maxSize = 0;
1363  for ( QgsSymbolLayer *layer : mLayers )
1364  {
1365  if ( layer->type() != QgsSymbol::Marker )
1366  continue;
1367  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1368  const double layerSize = context.convertToPainterUnits( markerLayer->size(), markerLayer->sizeUnit(), markerLayer->sizeMapUnitScale() );
1369  maxSize = std::max( maxSize, layerSize );
1370  }
1371  return maxSize;
1372 }
1373 
1375 {
1376  const auto constMLayers = mLayers;
1377  for ( QgsSymbolLayer *layer : constMLayers )
1378  {
1379  if ( layer->type() != QgsSymbol::Marker )
1380  continue;
1381 
1382  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1383  markerLayer->setSizeUnit( unit );
1384  }
1385 }
1386 
1388 {
1389  bool first = true;
1391 
1392  const auto constMLayers = mLayers;
1393  for ( QgsSymbolLayer *layer : constMLayers )
1394  {
1395  if ( layer->type() != QgsSymbol::Marker )
1396  continue;
1397  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1398 
1399  if ( first )
1400  unit = markerLayer->sizeUnit();
1401  else
1402  {
1403  if ( unit != markerLayer->sizeUnit() )
1405  }
1406 
1407  first = false;
1408  }
1409  return unit;
1410 }
1411 
1413 {
1414  const auto constMLayers = mLayers;
1415  for ( QgsSymbolLayer *layer : constMLayers )
1416  {
1417  if ( layer->type() != QgsSymbol::Marker )
1418  continue;
1419 
1420  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1421  markerLayer->setSizeMapUnitScale( scale );
1422  }
1423 }
1424 
1426 {
1427  const auto constMLayers = mLayers;
1428  for ( QgsSymbolLayer *layer : constMLayers )
1429  {
1430  if ( layer->type() != QgsSymbol::Marker )
1431  continue;
1432 
1433  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1434  return markerLayer->sizeMapUnitScale();
1435  }
1436  return QgsMapUnitScale();
1437 }
1438 
1440 {
1441  const double symbolSize = size();
1442 
1443  const auto constMLayers = mLayers;
1444  for ( QgsSymbolLayer *layer : constMLayers )
1445  {
1446  if ( layer->type() != QgsSymbol::Marker )
1447  continue;
1448  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1449 
1450  if ( !property )
1451  {
1454  }
1455  else
1456  {
1457  if ( qgsDoubleNear( symbolSize, 0.0 ) || qgsDoubleNear( markerLayer->size(), symbolSize ) )
1458  {
1459  markerLayer->setDataDefinedProperty( QgsSymbolLayer::PropertySize, property );
1460  }
1461  else
1462  {
1463  markerLayer->setDataDefinedProperty( QgsSymbolLayer::PropertySize, scaleWholeSymbol( markerLayer->size() / symbolSize, property ) );
1464  }
1465 
1466  if ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) )
1467  {
1469  markerLayer->offset().x() / symbolSize,
1470  markerLayer->offset().y() / symbolSize, property ) );
1471  }
1472  }
1473  }
1474 }
1475 
1477 {
1478  const double symbolSize = size();
1479 
1480  QgsProperty symbolDD;
1481 
1482  // find the base of the "en masse" pattern
1483  const auto layers = mLayers;
1484  for ( QgsSymbolLayer *layer : layers )
1485  {
1486  if ( layer->type() != QgsSymbol::Marker )
1487  continue;
1488  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1489  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) && markerLayer->dataDefinedProperties().isActive( QgsSymbolLayer::PropertySize ) )
1490  {
1491  symbolDD = markerLayer->dataDefinedProperties().property( QgsSymbolLayer::PropertySize );
1492  break;
1493  }
1494  }
1495 
1496  if ( !symbolDD )
1497  return QgsProperty();
1498 
1499  // check that all layers size expressions match the "en masse" pattern
1500  for ( QgsSymbolLayer *layer : layers )
1501  {
1502  if ( layer->type() != QgsSymbol::Marker )
1503  continue;
1504  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1505 
1508 
1509  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
1510  {
1511  if ( !layerSizeDD || layerSizeDD != symbolDD )
1512  return QgsProperty();
1513  }
1514  else
1515  {
1516  if ( qgsDoubleNear( symbolSize, 0.0 ) )
1517  return QgsProperty();
1518 
1519  QgsProperty scaledDD( scaleWholeSymbol( markerLayer->size() / symbolSize, symbolDD ) );
1520  if ( !layerSizeDD || layerSizeDD != scaledDD )
1521  return QgsProperty();
1522  }
1523 
1524  QgsProperty scaledOffsetDD( scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, symbolDD ) );
1525  if ( layerOffsetDD && layerOffsetDD != scaledOffsetDD )
1526  return QgsProperty();
1527  }
1528 
1529  return symbolDD;
1530 }
1531 
1533 {
1534  const auto constMLayers = mLayers;
1535  for ( QgsSymbolLayer *layer : constMLayers )
1536  {
1537  if ( layer->type() != QgsSymbol::Marker )
1538  continue;
1539  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( layer );
1540  markerLayer->setScaleMethod( scaleMethod );
1541  }
1542 }
1543 
1545 {
1546  const auto constMLayers = mLayers;
1547  for ( QgsSymbolLayer *layer : constMLayers )
1548  {
1549  if ( layer->type() != QgsSymbol::Marker )
1550  continue;
1551  const QgsMarkerSymbolLayer *markerLayer = static_cast<const QgsMarkerSymbolLayer *>( layer );
1552  // return scale method of the first symbol layer
1553  return markerLayer->scaleMethod();
1554  }
1555 
1556  return DEFAULT_SCALE_METHOD;
1557 }
1558 
1559 void QgsMarkerSymbol::renderPointUsingLayer( QgsMarkerSymbolLayer *layer, QPointF point, QgsSymbolRenderContext &context )
1560 {
1561  static QPointF nullPoint( 0, 0 );
1562 
1564  return;
1565 
1566  QgsPaintEffect *effect = layer->paintEffect();
1567  if ( effect && effect->enabled() )
1568  {
1569  QgsEffectPainter p( context.renderContext() );
1570  p->translate( point );
1571  p.setEffect( effect );
1572  layer->renderPoint( nullPoint, context );
1573  }
1574  else
1575  {
1576  layer->renderPoint( point, context );
1577  }
1578 }
1579 
1580 void QgsMarkerSymbol::renderPoint( QPointF point, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
1581 {
1582  QgsSymbolRenderContext symbolContext( context, outputUnit(), mOpacity, selected, mRenderHints, f, QgsFields(), mapUnitScale() );
1583  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1584  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1585 
1586  if ( layerIdx != -1 )
1587  {
1588  QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
1589  if ( symbolLayer && symbolLayer->enabled() )
1590  {
1591  if ( symbolLayer->type() == QgsSymbol::Marker )
1592  {
1593  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( symbolLayer );
1594  renderPointUsingLayer( markerLayer, point, symbolContext );
1595  }
1596  else
1597  renderUsingLayer( symbolLayer, symbolContext );
1598  }
1599  return;
1600  }
1601 
1602  const auto constMLayers = mLayers;
1603  for ( QgsSymbolLayer *symbolLayer : constMLayers )
1604  {
1605  if ( context.renderingStopped() )
1606  break;
1607 
1608  if ( !symbolLayer->enabled() )
1609  continue;
1610 
1611  if ( symbolLayer->type() == QgsSymbol::Marker )
1612  {
1613  QgsMarkerSymbolLayer *markerLayer = static_cast<QgsMarkerSymbolLayer *>( symbolLayer );
1614  renderPointUsingLayer( markerLayer, point, symbolContext );
1615  }
1616  else
1617  renderUsingLayer( symbolLayer, symbolContext );
1618  }
1619 }
1620 
1621 QRectF QgsMarkerSymbol::bounds( QPointF point, QgsRenderContext &context, const QgsFeature &feature ) const
1622 {
1623  QgsSymbolRenderContext symbolContext( context, outputUnit(), mOpacity, false, mRenderHints, &feature, feature.fields(), mapUnitScale() );
1624 
1625  QRectF bound;
1626  const auto constMLayers = mLayers;
1627  for ( QgsSymbolLayer *layer : constMLayers )
1628  {
1629  if ( layer->type() == QgsSymbol::Marker )
1630  {
1632  if ( bound.isNull() )
1633  bound = symbolLayer->bounds( point, symbolContext );
1634  else
1635  bound = bound.united( symbolLayer->bounds( point, symbolContext ) );
1636  }
1637  }
1638  return bound;
1639 }
1640 
1642 {
1643  QgsMarkerSymbol *cloneSymbol = new QgsMarkerSymbol( cloneLayers() );
1644  cloneSymbol->setOpacity( mOpacity );
1646  cloneSymbol->setLayer( mLayer );
1649  cloneSymbol->setForceRHR( mForceRHR );
1650  return cloneSymbol;
1651 }
1652 
1653 
1655 // LINE
1656 
1658  : QgsSymbol( Line, layers )
1659 {
1660  if ( mLayers.isEmpty() )
1661  mLayers.append( new QgsSimpleLineSymbolLayer() );
1662 }
1663 
1664 void QgsLineSymbol::setWidth( double w )
1665 {
1666  double origWidth = width();
1667 
1668  const auto constMLayers = mLayers;
1669  for ( QgsSymbolLayer *layer : constMLayers )
1670  {
1671  QgsLineSymbolLayer *lineLayer = dynamic_cast<QgsLineSymbolLayer *>( layer );
1672 
1673  if ( lineLayer )
1674  {
1675  if ( qgsDoubleNear( lineLayer->width(), origWidth ) )
1676  {
1677  lineLayer->setWidth( w );
1678  }
1679  else if ( !qgsDoubleNear( origWidth, 0.0 ) )
1680  {
1681  // proportionally scale the width
1682  lineLayer->setWidth( lineLayer->width() * w / origWidth );
1683  }
1684  // also scale offset to maintain relative position
1685  if ( !qgsDoubleNear( origWidth, 0.0 ) && !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1686  lineLayer->setOffset( lineLayer->offset() * w / origWidth );
1687  }
1688  }
1689 }
1690 
1691 double QgsLineSymbol::width() const
1692 {
1693  double maxWidth = 0;
1694  if ( mLayers.isEmpty() )
1695  return maxWidth;
1696 
1697  const auto constMLayers = mLayers;
1698  for ( QgsSymbolLayer *symbolLayer : constMLayers )
1699  {
1700  const QgsLineSymbolLayer *lineLayer = dynamic_cast<QgsLineSymbolLayer *>( symbolLayer );
1701  if ( lineLayer )
1702  {
1703  double width = lineLayer->width();
1704  if ( width > maxWidth )
1705  maxWidth = width;
1706  }
1707  }
1708  return maxWidth;
1709 }
1710 
1711 double QgsLineSymbol::width( const QgsRenderContext &context ) const
1712 {
1713  // return width of the largest symbol
1714  double maxWidth = 0;
1715  for ( QgsSymbolLayer *layer : mLayers )
1716  {
1717  if ( layer->type() != QgsSymbol::Line )
1718  continue;
1719  const QgsLineSymbolLayer *lineLayer = static_cast<const QgsLineSymbolLayer *>( layer );
1720  const double layerWidth = lineLayer->width( context );
1721  maxWidth = std::max( maxWidth, layerWidth );
1722  }
1723  return maxWidth;
1724 }
1725 
1727 {
1728  const double symbolWidth = width();
1729 
1730  const auto constMLayers = mLayers;
1731  for ( QgsSymbolLayer *layer : constMLayers )
1732  {
1733  QgsLineSymbolLayer *lineLayer = dynamic_cast<QgsLineSymbolLayer *>( layer );
1734 
1735  if ( lineLayer )
1736  {
1737  if ( !property )
1738  {
1741  }
1742  else
1743  {
1744  if ( qgsDoubleNear( symbolWidth, 0.0 ) || qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1745  {
1747  }
1748  else
1749  {
1750  lineLayer->setDataDefinedProperty( QgsSymbolLayer::PropertyStrokeWidth, scaleWholeSymbol( lineLayer->width() / symbolWidth, property ) );
1751  }
1752 
1753  if ( !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1754  {
1755  lineLayer->setDataDefinedProperty( QgsSymbolLayer::PropertyOffset, scaleWholeSymbol( lineLayer->offset() / symbolWidth, property ) );
1756  }
1757  }
1758  }
1759  }
1760 }
1761 
1763 {
1764  const double symbolWidth = width();
1765 
1766  QgsProperty symbolDD;
1767 
1768  // find the base of the "en masse" pattern
1769  for ( QgsSymbolLayerList::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1770  {
1771  const QgsLineSymbolLayer *layer = dynamic_cast<const QgsLineSymbolLayer *>( *it );
1772  if ( layer && qgsDoubleNear( layer->width(), symbolWidth ) && layer->dataDefinedProperties().isActive( QgsSymbolLayer::PropertyStrokeWidth ) )
1773  {
1775  break;
1776  }
1777  }
1778 
1779  if ( !symbolDD )
1780  return QgsProperty();
1781 
1782  // check that all layers width expressions match the "en masse" pattern
1783  const auto constMLayers = mLayers;
1784  for ( QgsSymbolLayer *layer : constMLayers )
1785  {
1786  if ( layer->type() != QgsSymbol::Line )
1787  continue;
1788  const QgsLineSymbolLayer *lineLayer = static_cast<const QgsLineSymbolLayer *>( layer );
1789 
1792 
1793  if ( qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1794  {
1795  if ( !layerWidthDD || layerWidthDD != symbolDD )
1796  return QgsProperty();
1797  }
1798  else
1799  {
1800  if ( qgsDoubleNear( symbolWidth, 0.0 ) )
1801  return QgsProperty();
1802 
1803  QgsProperty scaledDD( scaleWholeSymbol( lineLayer->width() / symbolWidth, symbolDD ) );
1804  if ( !layerWidthDD || layerWidthDD != scaledDD )
1805  return QgsProperty();
1806  }
1807 
1808  QgsProperty scaledOffsetDD( scaleWholeSymbol( lineLayer->offset() / symbolWidth, symbolDD ) );
1809  if ( layerOffsetDD && layerOffsetDD != scaledOffsetDD )
1810  return QgsProperty();
1811  }
1812 
1813  return symbolDD;
1814 }
1815 
1816 void QgsLineSymbol::renderPolyline( const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
1817 {
1818  //save old painter
1819  QPainter *renderPainter = context.painter();
1820  QgsSymbolRenderContext symbolContext( context, outputUnit(), mOpacity, selected, mRenderHints, f, QgsFields(), mapUnitScale() );
1822  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1823  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1824 
1825  if ( layerIdx != -1 )
1826  {
1827  QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
1828  if ( symbolLayer && symbolLayer->enabled() )
1829  {
1830  if ( symbolLayer->type() == QgsSymbol::Line )
1831  {
1832  QgsLineSymbolLayer *lineLayer = static_cast<QgsLineSymbolLayer *>( symbolLayer );
1833  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1834  }
1835  else
1836  renderUsingLayer( symbolLayer, symbolContext );
1837  }
1838  return;
1839  }
1840 
1841  const auto constMLayers = mLayers;
1842  for ( QgsSymbolLayer *symbolLayer : constMLayers )
1843  {
1844  if ( context.renderingStopped() )
1845  break;;
1846 
1847  if ( !symbolLayer->enabled() )
1848  continue;
1849 
1850  if ( symbolLayer->type() == QgsSymbol::Line )
1851  {
1852  QgsLineSymbolLayer *lineLayer = static_cast<QgsLineSymbolLayer *>( symbolLayer );
1853  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1854  }
1855  else
1856  {
1857  renderUsingLayer( symbolLayer, symbolContext );
1858  }
1859  }
1860 
1861  context.setPainter( renderPainter );
1862 }
1863 
1864 void QgsLineSymbol::renderPolylineUsingLayer( QgsLineSymbolLayer *layer, const QPolygonF &points, QgsSymbolRenderContext &context )
1865 {
1867  return;
1868 
1869  QgsPaintEffect *effect = layer->paintEffect();
1870  if ( effect && effect->enabled() )
1871  {
1872  QgsEffectPainter p( context.renderContext() );
1873  p->translate( points.boundingRect().topLeft() );
1874  p.setEffect( effect );
1875  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
1876  }
1877  else
1878  {
1879  layer->renderPolyline( points, context );
1880  }
1881 }
1882 
1883 
1885 {
1886  QgsLineSymbol *cloneSymbol = new QgsLineSymbol( cloneLayers() );
1887  cloneSymbol->setOpacity( mOpacity );
1889  cloneSymbol->setLayer( mLayer );
1892  cloneSymbol->setForceRHR( mForceRHR );
1893  return cloneSymbol;
1894 }
1895 
1897 // FILL
1898 
1900  : QgsSymbol( Fill, layers )
1901 {
1902  if ( mLayers.isEmpty() )
1903  mLayers.append( new QgsSimpleFillSymbolLayer() );
1904 }
1905 
1906 void QgsFillSymbol::renderPolygon( const QPolygonF &points, QList<QPolygonF> *rings, const QgsFeature *f, QgsRenderContext &context, int layerIdx, bool selected )
1907 {
1908  QgsSymbolRenderContext symbolContext( context, outputUnit(), mOpacity, selected, mRenderHints, f, QgsFields(), mapUnitScale() );
1910  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1911  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1912 
1913  if ( layerIdx != -1 )
1914  {
1915  QgsSymbolLayer *symbolLayer = mLayers.value( layerIdx );
1916  if ( symbolLayer && symbolLayer->enabled() )
1917  {
1918  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1919  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1920  else
1921  renderUsingLayer( symbolLayer, symbolContext );
1922  }
1923  return;
1924  }
1925 
1926  const auto constMLayers = mLayers;
1927  for ( QgsSymbolLayer *symbolLayer : constMLayers )
1928  {
1929  if ( context.renderingStopped() )
1930  break;
1931 
1932  if ( !symbolLayer->enabled() )
1933  continue;
1934 
1935  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1936  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1937  else
1938  renderUsingLayer( symbolLayer, symbolContext );
1939  }
1940 }
1941 
1942 void QgsFillSymbol::renderPolygonUsingLayer( QgsSymbolLayer *layer, const QPolygonF &points, QList<QPolygonF> *rings, QgsSymbolRenderContext &context )
1943 {
1945  return;
1946 
1947  QgsSymbol::SymbolType layertype = layer->type();
1948 
1949  QgsPaintEffect *effect = layer->paintEffect();
1950  if ( effect && effect->enabled() )
1951  {
1952  QRectF bounds = polygonBounds( points, rings );
1953  QList<QPolygonF> *translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
1954 
1955  QgsEffectPainter p( context.renderContext() );
1956  p->translate( bounds.topLeft() );
1957  p.setEffect( effect );
1958  if ( layertype == QgsSymbol::Fill )
1959  {
1960  ( static_cast<QgsFillSymbolLayer *>( layer ) )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
1961  }
1962  else if ( layertype == QgsSymbol::Line )
1963  {
1964  ( static_cast<QgsLineSymbolLayer *>( layer ) )->renderPolygonStroke( points.translated( -bounds.topLeft() ), translatedRings, context );
1965  }
1966  delete translatedRings;
1967  }
1968  else
1969  {
1970  if ( layertype == QgsSymbol::Fill )
1971  {
1972  ( static_cast<QgsFillSymbolLayer *>( layer ) )->renderPolygon( points, rings, context );
1973  }
1974  else if ( layertype == QgsSymbol::Line )
1975  {
1976  ( static_cast<QgsLineSymbolLayer *>( layer ) )->renderPolygonStroke( points, rings, context );
1977  }
1978  }
1979 }
1980 
1981 QRectF QgsFillSymbol::polygonBounds( const QPolygonF &points, const QList<QPolygonF> *rings ) const
1982 {
1983  QRectF bounds = points.boundingRect();
1984  if ( rings )
1985  {
1986  QList<QPolygonF>::const_iterator it = rings->constBegin();
1987  for ( ; it != rings->constEnd(); ++it )
1988  {
1989  bounds = bounds.united( ( *it ).boundingRect() );
1990  }
1991  }
1992  return bounds;
1993 }
1994 
1995 QList<QPolygonF> *QgsFillSymbol::translateRings( const QList<QPolygonF> *rings, double dx, double dy ) const
1996 {
1997  if ( !rings )
1998  return nullptr;
1999 
2000  QList<QPolygonF> *translatedRings = new QList<QPolygonF>;
2001  QList<QPolygonF>::const_iterator it = rings->constBegin();
2002  for ( ; it != rings->constEnd(); ++it )
2003  {
2004  translatedRings->append( ( *it ).translated( dx, dy ) );
2005  }
2006  return translatedRings;
2007 }
2008 
2010 {
2011  QgsFillSymbol *cloneSymbol = new QgsFillSymbol( cloneLayers() );
2012  cloneSymbol->setOpacity( mOpacity );
2014  cloneSymbol->setLayer( mLayer );
2017  cloneSymbol->setForceRHR( mForceRHR );
2018  return cloneSymbol;
2019 }
2020 
2022 {
2023  const auto constMLayers = mLayers;
2024  for ( QgsSymbolLayer *layer : constMLayers )
2025  {
2026  if ( layer->type() != QgsSymbol::Fill )
2027  continue;
2028 
2029  QgsFillSymbolLayer *fillLayer = static_cast<QgsFillSymbolLayer *>( layer );
2030 
2031  if ( fillLayer )
2032  fillLayer->setAngle( angle );
2033  }
2034 }
2035 
2036 
void setOffset(QPointF offset)
Sets the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered marker...
bool insertSymbolLayer(int index, QgsSymbolLayer *layer)
Inserts a symbol layer to specified index.
Definition: qgssymbol.cpp:363
QgsSymbolRenderContext(QgsRenderContext &c, QgsUnitTypes::RenderUnit u, qreal opacity=1.0, bool selected=false, QgsSymbol::RenderHints renderHints=nullptr, const QgsFeature *f=nullptr, const QgsFields &fields=QgsFields(), const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
Constructor for QgsSymbolRenderContext.
Definition: qgssymbol.cpp:1111
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
QgsFeatureId id
Definition: qgsfeature.h:64
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbol *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbol to an expression context.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:342
Single variable definition for use within a QgsExpressionContextScope.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QString asExpression() const
Returns an expression string representing the state of the property, or an empty string if the proper...
double y
Definition: qgspoint.h:42
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol&#39;s angle.
void setRenderingPass(int renderingPass)
Specifies the rendering pass in which this symbol layer should be rendered.
void setLocked(bool locked)
const QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Added in QGIS v2.4.
QgsMapLayerType type() const
Returns the type of the layer.
static QPolygonF _getPolygonRing(QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent, bool isExteriorRing=false, bool correctRingOrientation=false)
Creates a polygon ring in screen coordinates from a QgsCurve in map coordinates.
Definition: qgssymbol.cpp:153
void setMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol.
Definition: qgssymbol.cpp:284
QString readEntry(const QString &scope, const QString &key, const QString &def=QString(), bool *ok=nullptr) const
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:61
void renderVertexMarker(QPointF pt, QgsRenderContext &context, int currentVertexMarkerType, double currentVertexMarkerSize)
Render editing vertex marker at specified point.
Definition: qgssymbol.cpp:1102
bool readBoolEntry(const QString &scope, const QString &key, bool def=false, bool *ok=nullptr) const
Multi point geometry collection.
Definition: qgsmultipoint.h:29
bool appendSymbolLayer(QgsSymbolLayer *layer)
Appends a symbol layer at the end of the current symbol layer list.
Definition: qgssymbol.cpp:376
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an stroke...
virtual void setWidth(double width)
Sets the width of the line symbol layer.
SimplifyAlgorithm simplifyAlgorithm() const
Gets the local simplification algorithm of the vector layer managed.
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
Definition: qgssymbol.cpp:1173
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
ScaleMethod scaleMethod()
Definition: qgssymbol.cpp:1544
const QgsMapUnitScale & sizeMapUnitScale() const
Returns the map unit scale for the symbol&#39;s size.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsFillSymbol * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
Definition: qgssymbol.cpp:1184
QgsMapUnitScale mapUnitScale() const
Returns the map unit scale for the symbol.
Definition: qgssymbol.cpp:251
A simple line symbol layer, which renders lines using a line in a variety of styles (e...
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:265
void setExpressionContextScope(QgsExpressionContextScope *contextScope)
Set an expression scope for this symbol.
Definition: qgssymbol.cpp:1155
void setAngle(double angle)
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol along the line joining points, using the given render context. ...
Definition: qgssymbol.cpp:1816
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
Converts the symbol to a SLD representation.
Definition: qgssymbol.cpp:636
static QPointF _getPoint(QgsRenderContext &context, const QgsPoint &point)
Creates a point in screen coordinates from a QgsPoint in map coordinates.
Definition: qgssymbol.h:447
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:624
void setSize(double size)
Sets the size for the whole symbol.
Definition: qgssymbol.cpp:1318
Base class for visual effects which can be applied to QPicture drawings.
static QgsProperty fromExpression(const QString &expression, bool isActive=true)
Returns a new ExpressionBasedProperty created from the specified expression.
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the size map unit scale for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1412
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context&#39;s extent...
Definition: qgssymbol.h:380
Q_DECL_DEPRECATED double outputLineWidth(double width) const
Definition: qgssymbol.cpp:1130
bool mClipFeaturesToExtent
Definition: qgssymbol.h:518
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
Mixed or unknown units.
Definition: qgsunittypes.h:119
virtual void render(QgsSymbolRenderContext &context)
Will render this symbol layer using the context.
void setGeometryPartCount(int count)
Sets the part count of current geometry.
Definition: qgssymbol.h:692
bool deleteSymbolLayer(int index)
Removes and deletes the symbol layer at the specified index.
Definition: qgssymbol.cpp:386
void setDataDefinedAngle(const QgsProperty &property)
Set data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1242
Line symbol.
Definition: qgssymbol.h:86
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
virtual bool nextVertex(QgsVertexId &id, QgsPoint &vertex) const =0
Returns next vertex id and coordinates.
void setAngle(double symbolAngle)
Sets the angle for the whole symbol.
Definition: qgssymbol.cpp:1204
QgsFields fields
Definition: qgsfeature.h:66
SimplifyAlgorithm
Types of simplification algorithms that can be used.
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Sets the method to use for scaling the marker&#39;s size.
QgsAbstractGeometry::SegmentationToleranceType segmentationToleranceType() const
Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
QMap< QString, QString > QgsStringMap
Definition: qgis.h:587
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
void addVariable(const QgsExpressionContextScope::StaticVariable &variable)
Adds a variable into the context scope.
virtual double width() const
Returns the estimated width for the line symbol layer.
A marker symbol type, for rendering Point and MultiPoint geometries.
Definition: qgssymbol.h:766
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
A line symbol type, for rendering LineString and MultiLineString geometries.
Definition: qgssymbol.h:966
void startRender(QgsRenderContext &context, const QgsFields &fields=QgsFields())
Begins the rendering process for the symbol.
Definition: qgssymbol.cpp:422
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:46
virtual void renderPolyline(const QPolygonF &points, QgsSymbolRenderContext &context)=0
Renders the line symbol layer along the line joining points, using the given render context...
void transformPolygon(QPolygonF &polygon, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transforms a polygon to the destination coordinate system.
Q_DECL_DEPRECATED const QgsVectorLayer * mLayer
Definition: qgssymbol.h:521
bool isActive(int key) const override
Returns true if the collection contains an active property with the specified key.
static QString encodeColor(const QColor &color)
QgsUnitTypes::RenderUnit outputUnit() const
Returns the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:230
void setOutputUnit(QgsUnitTypes::RenderUnit unit)
Sets the units to use for sizes and widths within the symbol.
Definition: qgssymbol.cpp:275
QgsSymbolRenderContext & operator=(const QgsSymbolRenderContext &)
Definition: qgssymbol.cpp:1140
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
SymbolType
Type of the symbol.
Definition: qgssymbol.h:83
void renderPoint(QPointF point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol at the specified point, using the given render context.
Definition: qgssymbol.cpp:1580
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
Definition: qgssymbol.cpp:1125
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
QgsProperty dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1271
SymbolType mType
Definition: qgssymbol.h:511
virtual QPolygonF asQPolygonF() const
Returns a QPolygonF representing the points.
Definition: qgscurve.cpp:211
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleMarkerSymbolLayer.
QgsSymbolLayerList mLayers
Definition: qgssymbol.h:512
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
bool mForceRHR
Definition: qgssymbol.h:519
virtual QRectF bounds(QPointF point, QgsSymbolRenderContext &context)=0
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
QImage asImage(QSize size, QgsRenderContext *customContext=nullptr)
Returns an image of the symbol at the specified size.
Definition: qgssymbol.cpp:552
void exportImage(const QString &path, const QString &format, QSize size)
Export the symbol as an image format, to the specified path and with the given size.
Definition: qgssymbol.cpp:532
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
Definition: qgssymbol.cpp:293
void setOriginalGeometryType(QgsWkbTypes::GeometryType type)
Sets the geometry type for the original feature geometry being rendered.
Definition: qgssymbol.h:662
#define FALLTHROUGH
Definition: qgis.h:656
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
QString dump() const
Returns a string dump of the symbol&#39;s properties.
Definition: qgssymbol.cpp:610
Utility class for identifying a unique vertex within a geometry.
double tolerance() const
Gets the tolerance of simplification in map units. Represents the maximum distance in map units betwe...
void setGeometry(const QgsAbstractGeometry *geometry)
Sets pointer to original (unsegmentized) geometry.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
Geometry collection.
#define DEFAULT_SCALE_METHOD
QRectF bounds(QPointF point, QgsRenderContext &context, const QgsFeature &feature=QgsFeature()) const
Returns the approximate bounding box of the marker symbol, which includes the bounding box of all sym...
Definition: qgssymbol.cpp:1621
void renderPolygon(const QPolygonF &points, QList< QPolygonF > *rings, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
Renders the symbol using the given render context.
Definition: qgssymbol.cpp:1906
Q_DECL_DEPRECATED double outputPixelSize(double size) const
Definition: qgssymbol.cpp:1135
void renderUsingLayer(QgsSymbolLayer *layer, QgsSymbolRenderContext &context)
Renders a context using a particular symbol layer without passing in a geometry.
Definition: qgssymbol.cpp:663
void setOpacity(qreal opacity)
Sets the opacity for the symbol.
Definition: qgssymbol.h:346
QgsFillSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:2009
void setGeometryPartNum(int num)
Sets the part number of current geometry.
Definition: qgssymbol.h:704
void setWidth(double width)
Sets the width for the whole line symbol.
Definition: qgssymbol.cpp:1664
double width() const
Returns the estimated width for the whole symbol, which is the maximum width of all marker symbol lay...
Definition: qgssymbol.cpp:1691
const QgsAbstractGeometry * geometry() const
Returns pointer to the unsegmentized geometry.
double size() const
Returns the symbol size.
virtual void renderPoint(QPointF point, QgsSymbolRenderContext &context)=0
Renders a marker at the specified point.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:202
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:225
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsPropertyCollection & dataDefinedProperties()
Returns a reference to the symbol layer&#39;s property collection, used for data defined overrides...
QgsProperty scaleWholeSymbol(double scaleFactor, const QgsProperty &property)
Definition: qgssymbol.cpp:61
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s size.
static QgsRenderContext fromQPainter(QPainter *painter)
Creates a default render context given a pixel based QPainter destination.
QgsMapUnitScale sizeMapUnitScale() const
Returns the size map unit scale for the whole symbol.
Definition: qgssymbol.cpp:1425
Draw bounds of symbols (for debugging/testing)
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draws an icon of the symbol that occupies an area given by size using the specified painter...
Definition: qgssymbol.cpp:491
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition: qgssymbol.h:51
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgssurface.h:42
static QString encodeSldUom(QgsUnitTypes::RenderUnit unit, double *scaleFactor)
Encodes a render unit into an SLD unit of measure string.
QColor color() const
Returns the symbol&#39;s color.
Definition: qgssymbol.cpp:480
QgsSymbolRenderContext * symbolRenderContext()
Returns the symbol render context.
Definition: qgssymbol.cpp:1097
QgsSymbol::SymbolType type() const
void setScaleMethod(QgsSymbol::ScaleMethod scaleMethod)
Definition: qgssymbol.cpp:1532
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer&#39;s project and layer.
bool enabled() const
Returns whether the effect is enabled.
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
double offset() const
Returns the line&#39;s offset.
ScaleMethod
Scale method.
Definition: qgssymbol.h:94
Single scope for storing variables and functions for use within a QgsExpressionContext.
Abstract base class for all geometries.
void setEnabled(bool enabled)
Sets whether symbol layer is enabled and should be drawn.
void setAngle(double angle)
Definition: qgssymbol.cpp:2021
A store for object properties.
Definition: qgsproperty.h:229
QgsMarkerSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsMarkerSymbol, with the specified list of initial symbol layers.
Definition: qgssymbol.cpp:1197
QgsRenderContext & renderContext()
Returns a reference to the context&#39;s render context.
Definition: qgssymbol.h:574
Implementation of GeometrySimplifier using the "MapToPixel" algorithm.
QgsSymbolLayer * symbolLayer(int layer)
Returns a specific symbol layer contained in the symbol.
Definition: qgssymbol.cpp:358
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Counter-clockwise orientation.
Definition: qgscurve.h:237
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
void setEffect(QgsPaintEffect *effect)
Sets the effect to be painted.
static QPolygonF clippedLine(const QgsCurve &curve, const QgsRectangle &clipExtent)
Takes a linestring and clips it to clipExtent.
Definition: qgsclipper.cpp:41
void setDataDefinedWidth(const QgsProperty &property)
Set data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1726
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the size units for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1374
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleLineSymbolLayer, using the settings serialized in the properties map (correspo...
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsSymbol::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker&#39;s size.
Clockwise orientation.
Definition: qgscurve.h:236
Orientation orientation() const
Returns the curve&#39;s orientation, e.g.
Definition: qgscurve.cpp:237
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the size units for the whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1387
QgsExpressionContext & expressionContext()
Gets the expression context.
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
static QPolygonF _getLineString(QgsRenderContext &context, const QgsCurve &curve, bool clipToExtent=true)
Creates a line string in screen coordinates from a QgsCurve in map coordinates.
Definition: qgssymbol.cpp:102
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1476
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
virtual bool isCompatibleWithSymbol(QgsSymbol *symbol) const
Returns if the layer can be used below the specified symbol.
bool valueAsBool(int key, const QgsExpressionContext &context, bool defaultValue=false, bool *ok=nullptr) const
Calculates the current value of the property with the specified key and interprets it as an boolean...
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:139
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:625
VertexMarkerType
Editing vertex markers.
static void drawVertexMarker(double x, double y, QPainter &p, QgsSymbolLayerUtils::VertexMarkerType type, int markerSize)
Draws a vertex symbol at (painter) coordinates x, y.
bool changeSymbolLayer(int index, QgsSymbolLayer *layer)
Deletes the current layer at the specified index and replaces it with layer.
Definition: qgssymbol.cpp:406
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the symbol&#39;s size.
Marker symbol.
Definition: qgssymbol.h:85
static QgsColorSchemeRegistry * colorSchemeRegistry()
Returns the application&#39;s color scheme registry, used for managing color schemes. ...
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
Definition: qgssymbol.cpp:684
Fill symbol.
Definition: qgssymbol.h:87
Contains information about the context of a rendering operation.
Abstract base class for marker symbol layers.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
double segmentationTolerance() const
Gets the segmentation tolerance applied when rendering curved geometries.
QPainter * painter()
Returns the destination QPainter for the render operation.
const QgsMapToPixel & mapToPixel() const
Returns the context&#39;s map to pixel transform, which transforms between map coordinates and device coo...
virtual ~QgsSymbol()
Definition: qgssymbol.cpp:224
QgsSymbolLayerList cloneLayers() const
Retrieve a cloned list of all layers that make up this symbol.
Definition: qgssymbol.cpp:649
QgsGeometry simplify(const QgsGeometry &geometry) const override
Returns a simplified version the specified geometry.
bool hasDataDefinedProperties() const
Returns whether the symbol utilizes any data defined properties.
Definition: qgssymbol.cpp:698
bool enabled() const
Returns true if symbol layer is enabled and will be drawn.
static QgsSymbolLayer * create(const QgsStringMap &properties=QgsStringMap())
SymbolType type() const
Returns the symbol&#39;s type.
Definition: qgssymbol.h:120
virtual void stopRender(QgsSymbolRenderContext &context)=0
Struct for storing maximum and minimum scales for measurements in map units.
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, double currentVertexMarkerSize=0.0) SIP_THROW(QgsCsException)
Render a feature.
Definition: qgssymbol.cpp:765
QgsUnitTypes::RenderUnit sizeUnit() const
Returns the units for the symbol&#39;s size.
RenderHints mRenderHints
Definition: qgssymbol.h:517
QgsProperty rotateWholeSymbol(double additionalRotation, const QgsProperty &property)
Definition: qgssymbol.cpp:54
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:609
Q_DECL_DEPRECATED void setLayer(const QgsVectorLayer *layer)
Definition: qgssymbol.cpp:709
double size() const
Returns the estimated size for the whole symbol, which is the maximum size of all marker symbol layer...
Definition: qgssymbol.cpp:1342
bool forceLocalOptimization() const
Gets where the simplification executes, after fetch the geometries from provider, or when supported...
static void _getPolygon(QPolygonF &pts, QList< QPolygonF > &holes, QgsRenderContext &context, const QgsPolygon &polygon, bool clipToExtent=true, bool correctRingOrientation=false)
Creates a polygon in screen coordinates from a QgsPolygonXYin map coordinates.
Definition: qgssymbol.cpp:212
RenderHints renderHints() const
Returns the rendering hint flags for the symbol.
Definition: qgssymbol.h:358
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:438
QgsSymbol(SymbolType type, const QgsSymbolLayerList &layers)
Definition: qgssymbol.cpp:81
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
virtual void setSize(double size)
Sets the symbol size.
SimplifyHints simplifyHints() const
Gets the simplification hints of the vector layer managed.
Class for doing transforms between two map coordinate systems.
static QString displayString(Type type)
Returns a display string type for a WKB type, e.g., the geometry name used in WKT geometry representa...
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
virtual void renderPolygonStroke(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolRenderContext &context)
Renders the line symbol layer along the outline of polygon, using the given render context...
void setAngle(double angle)
Sets the rotation angle for the marker.
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol&#39;s angle.
Definition: qgssymbol.cpp:1230
QgsLineSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsLineSymbol, with the specified list of initial symbol layers.
Definition: qgssymbol.cpp:1657
double readDoubleEntry(const QString &scope, const QString &key, double def=0, bool *ok=nullptr) const
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
bool hasActiveProperties() const override
Returns true if the collection has any active properties, or false if all properties within the colle...
QgsSymbolLayer * takeSymbolLayer(int index)
Removes a symbol layer from the list and returns a pointer to it.
Definition: qgssymbol.cpp:397
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
Definition: qgssymbol.h:1061
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
QgsSymbol * symbol(const QString &name)
Returns a NEW copy of symbol.
Definition: qgsstyle.cpp:175
QgsGeometry geometry
Definition: qgsfeature.h:67
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
Definition: qgssymbol.cpp:1162
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
void setDataDefinedSize(const QgsProperty &property)
Set data defined size for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1439
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context&#39;s extent...
Definition: qgssymbol.h:369
qreal opacity() const
Returns the opacity for the symbol.
Definition: qgssymbol.h:339
Polygon geometry type.
Definition: qgspolygon.h:31
void setForceRHR(bool force)
Sets whether polygon features drawn by the symbol should be reoriented to follow the standard right-h...
Definition: qgssymbol.h:391
Draw map such that there are no problems between adjacent tiles.
const QgsCurve * exteriorRing() const
Returns the curve polygon&#39;s exterior ring.
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
Definition: qgsclipper.h:202
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
QImage bigSymbolPreviewImage(QgsExpressionContext *expressionContext=nullptr)
Returns a large (roughly 100x100 pixel) preview image for the symbol.
Definition: qgssymbol.cpp:566
QPointF offset() const
Returns the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered mar...
Q_DECL_DEPRECATED const QgsVectorLayer * layer() const
Definition: qgssymbol.cpp:716
Represents a vector layer which manages a vector based data sets.
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:430
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
Whether symbol layer is enabled.
virtual QgsAbstractGeometry * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
void stopRender(QgsRenderContext &context)
Ends the rendering process.
Definition: qgssymbol.cpp:445
virtual int numPoints() const =0
Returns the number of points in the curve.
qreal mOpacity
Symbol opacity (in the range 0 - 1)
Definition: qgssymbol.h:515
Hybrid symbol.
Definition: qgssymbol.h:88
QgsProperty dataDefinedWidth() const
Returns data defined width for whole symbol (including all symbol layers).
Definition: qgssymbol.cpp:1762
A class to manager painter saving and restoring required for effect drawing.
double angle() const
Returns the marker angle for the whole symbol.
Definition: qgssymbol.cpp:1217
QgsFillSymbol(const QgsSymbolLayerList &layers=QgsSymbolLayerList())
Constructor for QgsFillSymbol, with the specified list of initial symbol layers.
Definition: qgssymbol.cpp:1899
QgsMarkerSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1641
QgsProperty property(int key) const override
Returns a matching property from the collection, if one exists.
QgsVectorLayer * clone() const override
Returns a new instance equivalent to this one.
RenderUnit
Rendering size units.
Definition: qgsunittypes.h:111
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
virtual void setDataDefinedProperty(Property key, const QgsProperty &property)
Sets a data defined property for the layer.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:209
void setOffset(double offset)
Sets the line&#39;s offset.
virtual void startRender(QgsSymbolRenderContext &context)=0
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.
Definition: qgssymbol.cpp:1884
void setColor(const QColor &color)
Sets the color for the symbol.
Definition: qgssymbol.cpp:470
double x
Definition: qgspoint.h:41
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
Definition: qgssymbol.cpp:1150