QGIS API Documentation  2.17.0-Master (6f7b933)
qgssymbolv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgssymbolv2.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 "qgssymbolv2.h"
17 #include "qgssymbollayerv2.h"
18 
19 #include "qgslinesymbollayerv2.h"
20 #include "qgsmarkersymbollayerv2.h"
21 #include "qgsfillsymbollayerv2.h"
23 
24 #include "qgslogger.h"
25 #include "qgsrendercontext.h" // for bigSymbolPreview
26 
27 #include "qgsproject.h"
28 #include "qgsstylev2.h"
29 #include "qgspainteffect.h"
30 #include "qgseffectstack.h"
31 
32 #include "qgsdatadefined.h"
33 
34 #include "qgsgeometry.h"
35 #include "qgsmultipointv2.h"
36 #include "qgswkbptr.h"
37 #include "qgswkbsimplifierptr.h"
39 #include "qgsclipper.h"
40 
41 #include <QColor>
42 #include <QImage>
43 #include <QPainter>
44 #include <QSize>
45 #include <QSvgGenerator>
46 
47 #include <cmath>
48 
49 inline
50 QgsDataDefined* rotateWholeSymbol( double additionalRotation, const QgsDataDefined& dd )
51 {
52  QgsDataDefined* rotatedDD = new QgsDataDefined( dd );
53  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
54  rotatedDD->setExpressionString( QString::number( additionalRotation ) + " + (" + exprString + ')' );
55  rotatedDD->setUseExpression( true );
56  return rotatedDD;
57 }
58 
59 inline
60 QgsDataDefined* scaleWholeSymbol( double scaleFactor, const QgsDataDefined& dd )
61 {
62  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
63  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
64  scaledDD->setExpressionString( QString::number( scaleFactor ) + "*(" + exprString + ')' );
65  scaledDD->setUseExpression( true );
66  return scaledDD;
67 }
68 
69 inline
70 QgsDataDefined* scaleWholeSymbol( double scaleFactorX, double scaleFactorY, const QgsDataDefined& dd )
71 {
72  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
73  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
74  scaledDD->setExpressionString(
75  ( !qgsDoubleNear( scaleFactorX, 0.0 ) ? "tostring(" + QString::number( scaleFactorX ) + "*(" + exprString + "))" : "'0'" ) +
76  "|| ',' || " +
77  ( !qgsDoubleNear( scaleFactorY, 0.0 ) ? "tostring(" + QString::number( scaleFactorY ) + "*(" + exprString + "))" : "'0'" ) );
78  scaledDD->setUseExpression( true );
79  return scaledDD;
80 }
81 
82 
84 
86  : mType( type )
87  , mLayers( layers )
88  , mAlpha( 1.0 )
89  , mRenderHints( 0 )
90  , mClipFeaturesToExtent( true )
91  , mLayer( nullptr )
92  , mSymbolRenderContext( nullptr )
93 {
94 
95  // check they're all correct symbol layers
96  for ( int i = 0; i < mLayers.count(); i++ )
97  {
98  if ( !mLayers.at( i ) )
99  {
100  mLayers.removeAt( i-- );
101  }
102  else if ( !mLayers.at( i )->isCompatibleWithSymbol( this ) )
103  {
104  delete mLayers.at( i );
105  mLayers.removeAt( i-- );
106  }
107  }
108 }
109 
111 {
112  QgsWKBTypes::Type type = wkbPtr.readHeader();
113  wkbPtr >> pt.rx() >> pt.ry();
114  wkbPtr += ( QgsWKBTypes::coordDimensions( type ) - 2 ) * sizeof( double );
115 
116  if ( context.coordinateTransform() )
117  {
118  double z = 0; // dummy variable for coordinate transform
119  context.coordinateTransform()->transformInPlace( pt.rx(), pt.ry(), z );
120  }
121 
122  context.mapToPixel().transformInPlace( pt.rx(), pt.ry() );
123 
124  return wkbPtr;
125 }
126 
128 {
129  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
130  unsigned int nPoints;
131  wkbPtr >> nPoints;
132 
133  const QgsCoordinateTransform* ct = context.coordinateTransform();
134  const QgsMapToPixel& mtp = context.mapToPixel();
135 
136  //apply clipping for large lines to achieve a better rendering performance
137  if ( clipToExtent && nPoints > 1 )
138  {
139  const QgsRectangle& e = context.extent();
140  double cw = e.width() / 10;
141  double ch = e.height() / 10;
142  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
143  wkbPtr -= 1 + 2 * sizeof( int );
144  wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts );
145  }
146  else
147  {
148  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
149  Q_ASSERT( skipZM >= 0 );
150 
151  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
152  {
153  QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
154  return QgsConstWkbPtr( nullptr, 0 );
155  }
156 
157  wkbPtr -= sizeof( unsigned int );
158  wkbPtr >> pts;
159  nPoints = pts.size();
160  }
161 
162  //transform the QPolygonF to screen coordinates
163  if ( ct )
164  {
165  ct->transformPolygon( pts );
166  }
167 
168  QPointF *ptr = pts.data();
169  for ( int i = 0; i < pts.size(); ++i, ++ptr )
170  {
171  mtp.transformInPlace( ptr->rx(), ptr->ry() );
172  }
173 
174  return wkbPtr;
175 }
176 
178 {
179  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
180  unsigned int numRings;
181  wkbPtr >> numRings;
182 
183  if ( numRings == 0 ) // sanity check for zero rings in polygon
184  return wkbPtr;
185 
186  holes.clear();
187 
188  const QgsCoordinateTransform* ct = context.coordinateTransform();
189  const QgsMapToPixel& mtp = context.mapToPixel();
190  const QgsRectangle& e = context.extent();
191  double cw = e.width() / 10;
192  double ch = e.height() / 10;
193  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
194 
195  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
196  Q_ASSERT( skipZM >= 0 );
197 
198  for ( unsigned int idx = 0; idx < numRings; idx++ )
199  {
200  unsigned int nPoints;
201  wkbPtr >> nPoints;
202 
203  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
204  {
205  QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
206  return QgsConstWkbPtr( nullptr, 0 );
207  }
208 
209  QPolygonF poly;
210  wkbPtr -= sizeof( unsigned int );
211  wkbPtr >> poly;
212  nPoints = poly.size();
213 
214  if ( nPoints < 1 )
215  continue;
216 
217  //clip close to view extent, if needed
218  QRectF ptsRect = poly.boundingRect();
219  if ( clipToExtent && !context.extent().contains( ptsRect ) )
220  {
221  QgsClipper::trimPolygon( poly, clipRect );
222  }
223 
224  //transform the QPolygonF to screen coordinates
225  if ( ct )
226  {
227  ct->transformPolygon( poly );
228  }
229 
230  QPointF *ptr = poly.data();
231  for ( int i = 0; i < poly.size(); ++i, ++ptr )
232  {
233  mtp.transformInPlace( ptr->rx(), ptr->ry() );
234  }
235 
236  if ( idx == 0 )
237  pts = poly;
238  else
239  holes.append( poly );
240  }
241 
242  return wkbPtr;
243 }
244 
246 {
247  delete mSymbolRenderContext;
248  // delete all symbol layers (we own them, so it's okay)
249  qDeleteAll( mLayers );
250 }
251 
253 {
254  if ( mLayers.empty() )
255  {
256  return QgsSymbolV2::Mixed;
257  }
258 
260 
261  QgsSymbolV2::OutputUnit unit = ( *it )->outputUnit();
262 
263  for ( ; it != mLayers.constEnd(); ++it )
264  {
265  if (( *it )->outputUnit() != unit )
266  {
267  return QgsSymbolV2::Mixed;
268  }
269  }
270  return unit;
271 }
272 
274 {
275  if ( mLayers.empty() )
276  {
277  return QgsMapUnitScale();
278  }
279 
281  if ( it == mLayers.constEnd() )
282  return QgsMapUnitScale();
283 
284  QgsMapUnitScale scale = ( *it )->mapUnitScale();
285  ++it;
286 
287  for ( ; it != mLayers.constEnd(); ++it )
288  {
289  if (( *it )->mapUnitScale() != scale )
290  {
291  return QgsMapUnitScale();
292  }
293  }
294  return scale;
295 }
296 
298 {
299  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
300  {
301  layer->setOutputUnit( u );
302  }
303 }
304 
306 {
307  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
308  {
309  layer->setMapUnitScale( scale );
310  }
311 }
312 
314 {
315  QgsSymbolV2* s = nullptr;
316 
317  // override global default if project has a default for this type
319  switch ( geomType )
320  {
321  case QGis::Point :
322  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Marker", "" );
323  break;
324  case QGis::Line :
325  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Line", "" );
326  break;
327  case QGis::Polygon :
328  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Fill", "" );
329  break;
330  default:
331  defaultSymbol = "";
332  break;
333  }
334  if ( defaultSymbol != "" )
335  s = QgsStyleV2::defaultStyle()->symbol( defaultSymbol );
336 
337  // if no default found for this type, get global default (as previously)
338  if ( ! s )
339  {
340  switch ( geomType )
341  {
342  case QGis::Point:
343  s = new QgsMarkerSymbolV2();
344  break;
345  case QGis::Line:
346  s = new QgsLineSymbolV2();
347  break;
348  case QGis::Polygon:
349  s = new QgsFillSymbolV2();
350  break;
351  default:
352  QgsDebugMsg( "unknown layer's geometry type" );
353  return nullptr;
354  }
355  }
356 
357  // set alpha transparency
358  s->setAlpha( QgsProject::instance()->readDoubleEntry( "DefaultStyles", "/AlphaInt", 255 ) / 255.0 );
359 
360  // set random color, it project prefs allow
361  if ( defaultSymbol == "" ||
362  QgsProject::instance()->readBoolEntry( "DefaultStyles", "/RandomColors", true ) )
363  {
364  s->setColor( QColor::fromHsv( qrand() % 360, 64 + qrand() % 192, 128 + qrand() % 128 ) );
365  }
366 
367  return s;
368 }
369 
371 {
372  return mLayers.value( layer );
373 }
374 
375 
377 {
378  // fill symbol can contain also line symbol layers for drawing of outlines
379  if ( mType == Fill && layerType == Line )
380  return true;
381 
382  return mType == layerType;
383 }
384 
385 
387 {
388  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
389  return false;
390 
391  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
392  return false;
393 
394  mLayers.insert( index, layer );
395  return true;
396 }
397 
398 
400 {
401  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
402  return false;
403 
404  mLayers.append( layer );
405  return true;
406 }
407 
408 
410 {
411  if ( index < 0 || index >= mLayers.count() )
412  return false;
413 
414  delete mLayers.at( index );
415  mLayers.removeAt( index );
416  return true;
417 }
418 
419 
421 {
422  if ( index < 0 || index >= mLayers.count() )
423  return nullptr;
424 
425  return mLayers.takeAt( index );
426 }
427 
428 
430 {
431  QgsSymbolLayerV2* oldLayer = mLayers.value( index );
432 
433  if ( oldLayer == layer )
434  return false;
435 
436  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
437  return false;
438 
439  delete oldLayer; // first delete the original layer
440  mLayers[index] = layer; // set new layer
441  return true;
442 }
443 
444 
445 void QgsSymbolV2::startRender( QgsRenderContext& context, const QgsFields* fields )
446 {
447  delete mSymbolRenderContext;
448  mSymbolRenderContext = new QgsSymbolV2RenderContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, fields, mapUnitScale() );
449 
450  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, fields, mapUnitScale() );
451 
453 
454  mSymbolRenderContext->setExpressionContextScope( scope );
455 
456  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
457  layer->startRender( symbolContext );
458 }
459 
461 {
462  Q_UNUSED( context )
463  if ( mSymbolRenderContext )
464  {
465  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
466  layer->stopRender( *mSymbolRenderContext );
467  }
468 
469  delete mSymbolRenderContext;
470  mSymbolRenderContext = nullptr;
471 
472  mLayer = nullptr;
473 }
474 
476 {
477  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
478  {
479  if ( !layer->isLocked() )
480  layer->setColor( color );
481  }
482 }
483 
485 {
486  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
487  {
488  // return color of the first unlocked layer
489  if ( !( *it )->isLocked() )
490  return ( *it )->color();
491  }
492  return QColor( 0, 0, 0 );
493 }
494 
495 void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
496 {
497  QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerV2Utils::createRenderContext( painter );
498  context.setForceVectorOutput( true );
499  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, nullptr, mapUnitScale() );
500 
501  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
502  {
503  if ( mType == Fill && layer->type() == Line )
504  {
505  // line symbol layer would normally draw just a line
506  // so we override this case to force it to draw a polygon outline
507  QgsLineSymbolLayerV2* lsl = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
508 
509  if ( lsl )
510  {
511  // from QgsFillSymbolLayerV2::drawPreviewIcon()
512  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
513  lsl->startRender( symbolContext );
514  lsl->renderPolygonOutline( poly, nullptr, symbolContext );
515  lsl->stopRender( symbolContext );
516  }
517  }
518  else
519  layer->drawPreviewIcon( symbolContext, size );
520  }
521 }
522 
523 void QgsSymbolV2::exportImage( const QString& path, const QString& format, QSize size )
524 {
525  if ( format.toLower() == "svg" )
526  {
527  QSvgGenerator generator;
528  generator.setFileName( path );
529  generator.setSize( size );
530  generator.setViewBox( QRect( 0, 0, size.height(), size.height() ) );
531 
532  QPainter painter( &generator );
533  drawPreviewIcon( &painter, size );
534  painter.end();
535  }
536  else
537  {
538  QImage image = asImage( size );
539  image.save( path );
540  }
541 }
542 
544 {
545  QImage image( size, QImage::Format_ARGB32_Premultiplied );
546  image.fill( 0 );
547 
548  QPainter p( &image );
549  p.setRenderHint( QPainter::Antialiasing );
550 
551  drawPreviewIcon( &p, size, customContext );
552 
553  return image;
554 }
555 
556 
558 {
559  QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
560  preview.fill( 0 );
561 
562  QPainter p( &preview );
563  p.setRenderHint( QPainter::Antialiasing );
564  p.translate( 0.5, 0.5 ); // shift by half a pixel to avoid blurring due antialising
565 
566  if ( mType == QgsSymbolV2::Marker )
567  {
568  p.setPen( QPen( Qt::gray ) );
569  p.drawLine( 0, 50, 100, 50 );
570  p.drawLine( 50, 0, 50, 100 );
571  }
572 
574  if ( expressionContext )
575  context.setExpressionContext( *expressionContext );
576 
577  startRender( context );
578 
579  if ( mType == QgsSymbolV2::Line )
580  {
581  QPolygonF poly;
582  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
583  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, nullptr, context );
584  }
585  else if ( mType == QgsSymbolV2::Fill )
586  {
587  QPolygonF polygon;
588  polygon << QPointF( 20, 20 ) << QPointF( 80, 20 ) << QPointF( 80, 80 ) << QPointF( 20, 80 ) << QPointF( 20, 20 );
589  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( polygon, nullptr, nullptr, context );
590  }
591  else // marker
592  {
593  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), nullptr, context );
594  }
595 
596  stopRender( context );
597  return preview;
598 }
599 
600 
602 {
603  QString t;
604  switch ( type() )
605  {
606  case QgsSymbolV2::Marker:
607  t = "MARKER";
608  break;
609  case QgsSymbolV2::Line:
610  t = "LINE";
611  break;
612  case QgsSymbolV2::Fill:
613  t = "FILL";
614  break;
615  default:
616  Q_ASSERT( 0 && "unknown symbol type" );
617  }
618  QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) );
619 
620  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
621  {
622  // TODO:
623  }
624  return s;
625 }
626 
627 void QgsSymbolV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
628 {
629  props[ "alpha" ] = QString::number( alpha() );
630  double scaleFactor = 1.0;
631  props[ "uom" ] = QgsSymbolLayerV2Utils::encodeSldUom( outputUnit(), &scaleFactor );
632  props[ "uomScale" ] = ( !qgsDoubleNear( scaleFactor, 1.0 ) ? qgsDoubleToString( scaleFactor ) : "" );
633 
634  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
635  {
636  ( *it )->toSld( doc, element, props );
637  }
638 }
639 
641 {
643  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
644  {
645  QgsSymbolLayerV2* layer = ( *it )->clone();
646  layer->setLocked(( *it )->isLocked() );
647  layer->setRenderingPass(( *it )->renderingPass() );
648  lst.append( layer );
649  }
650  return lst;
651 }
652 
654 {
655  Q_ASSERT( layer->type() == Hybrid );
656 
658 
659  QgsPaintEffect* effect = generatorLayer->paintEffect();
660  if ( effect && effect->enabled() )
661  {
662  QPainter* p = context.renderContext().painter();
663  p->save();
664 
665  effect->begin( context.renderContext() );
666  generatorLayer->render( context );
667  effect->end( context.renderContext() );
668 
669  p->restore();
670  }
671  else
672  {
673  generatorLayer->render( context );
674  }
675 }
676 
678 {
679  QSet<QString> attributes;
681  for ( ; sIt != mLayers.constEnd(); ++sIt )
682  {
683  if ( *sIt )
684  {
685  attributes.unite(( *sIt )->usedAttributes() );
686  }
687  }
688  return attributes;
689 }
690 
692 {
693  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
694  {
695  if ( layer->hasDataDefinedProperties() )
696  return true;
697  }
698  return false;
699 }
700 
701 void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, int currentVertexMarkerSize )
702 {
703  const QgsGeometry* geom = feature.constGeometry();
704  if ( !geom || !geom->geometry() )
705  {
706  return;
707  }
708 
709  const QgsGeometry *segmentizedGeometry = geom;
710  bool deleteSegmentizedGeometry = false;
711  context.setGeometry( geom->geometry() );
712 
713  bool tileMapRendering = context.testFlag( QgsRenderContext::RenderMapTile );
714 
715  //convert curve types to normal point/line/polygon ones
716  if ( QgsWKBTypes::isCurvedType( geom->geometry()->wkbType() ) )
717  {
719  if ( !g )
720  {
721  return;
722  }
723  segmentizedGeometry = new QgsGeometry( g );
724  deleteSegmentizedGeometry = true;
725  }
726 
727  mSymbolRenderContext->setGeometryPartCount( segmentizedGeometry->geometry()->partCount() );
728  mSymbolRenderContext->setGeometryPartNum( 1 );
729 
730  if ( mSymbolRenderContext->expressionContextScope() )
731  {
732  context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
734  mSymbolRenderContext->expressionContextScope()->setVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext->geometryPartCount() );
736  }
737 
738  // Collection of markers to paint, only used for no curve types.
739  QPolygonF markers;
740 
741  switch ( QgsWKBTypes::flatType( segmentizedGeometry->geometry()->wkbType() ) )
742  {
743  case QgsWKBTypes::Point:
744  {
745  QPointF pt;
746  if ( mType != QgsSymbolV2::Marker )
747  {
748  QgsDebugMsg( "point can be drawn only with marker symbol!" );
749  break;
750  }
751 
752  const QgsPointV2* point = static_cast< const QgsPointV2* >( segmentizedGeometry->geometry() );
753  _getPoint( pt, context, point );
754  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( pt, &feature, context, layer, selected );
755 
757  {
758  //draw debugging rect
759  context.painter()->setPen( Qt::red );
760  context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
761  context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context, feature ) );
762  }
763 
764  if ( drawVertexMarker && !deleteSegmentizedGeometry )
765  {
766  markers << pt;
767  }
768  }
769  break;
771  {
772  QPolygonF pts;
773  if ( mType != QgsSymbolV2::Line )
774  {
775  QgsDebugMsg( "linestring can be drawn only with line symbol!" );
776  break;
777  }
778  QgsConstWkbSimplifierPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize(), context.vectorSimplifyMethod() );
779  _getLineString( pts, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() );
780  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
781 
782  if ( drawVertexMarker && !deleteSegmentizedGeometry )
783  {
784  markers = pts;
785  }
786  }
787  break;
789  {
790  QPolygonF pts;
791  QList<QPolygonF> holes;
792  if ( mType != QgsSymbolV2::Fill )
793  {
794  QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
795  break;
796  }
797  QgsConstWkbSimplifierPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize(), context.vectorSimplifyMethod() );
798  _getPolygon( pts, holes, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() );
799  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
800 
801  if ( drawVertexMarker && !deleteSegmentizedGeometry )
802  {
803  markers = pts;
804 
805  Q_FOREACH ( const QPolygonF& hole, holes )
806  {
807  markers << hole;
808  }
809  }
810  }
811  break;
812 
814  {
815  QPointF pt;
816 
817  if ( mType != QgsSymbolV2::Marker )
818  {
819  QgsDebugMsg( "multi-point can be drawn only with marker symbol!" );
820  break;
821  }
822 
823  QgsMultiPointV2* mp = static_cast< QgsMultiPointV2* >( segmentizedGeometry->geometry() );
824 
825  if ( drawVertexMarker && !deleteSegmentizedGeometry )
826  {
827  markers.reserve( mp->numGeometries() );
828  }
829 
830  for ( int i = 0; i < mp->numGeometries(); ++i )
831  {
832  mSymbolRenderContext->setGeometryPartNum( i + 1 );
834 
835  const QgsPointV2* point = static_cast< const QgsPointV2* >( mp->geometryN( i ) );
836  _getPoint( pt, context, point );
837  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( pt, &feature, context, layer, selected );
838 
839  if ( drawVertexMarker && !deleteSegmentizedGeometry )
840  {
841  markers.append( pt );
842  }
843  }
844  }
845  break;
846 
849  {
850  QPolygonF pts;
851 
852  if ( mType != QgsSymbolV2::Line )
853  {
854  QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" );
855  break;
856  }
857 
858  QgsConstWkbSimplifierPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize(), context.vectorSimplifyMethod() );
859  wkbPtr.readHeader();
860 
861  unsigned int num;
862  wkbPtr >> num;
863 
864  const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
865 
866  for ( unsigned int i = 0; i < num && wkbPtr; ++i )
867  {
868  mSymbolRenderContext->setGeometryPartNum( i + 1 );
870 
871  if ( geomCollection )
872  {
873  context.setGeometry( geomCollection->geometryN( i ) );
874  }
875  if ( _getLineString( pts, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() ) == nullptr )
876  {
877  break;
878  }
879  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
880 
881  if ( drawVertexMarker && !deleteSegmentizedGeometry )
882  {
883  if ( i == 0 )
884  {
885  markers = pts;
886  }
887  else
888  {
889  markers << pts;
890  }
891  }
892  }
893  }
894  break;
895 
898  {
899  if ( mType != QgsSymbolV2::Fill )
900  {
901  QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" );
902  break;
903  }
904 
905  QgsConstWkbSimplifierPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize(), context.vectorSimplifyMethod() );
906  wkbPtr.readHeader();
907 
908  unsigned int num;
909  wkbPtr >> num;
910 
911  QPolygonF pts;
912  QList<QPolygonF> holes;
913 
914  const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
915 
916  for ( unsigned int i = 0; i < num && wkbPtr; ++i )
917  {
918  mSymbolRenderContext->setGeometryPartNum( i + 1 );
920 
921  if ( geomCollection )
922  {
923  context.setGeometry( geomCollection->geometryN( i ) );
924  }
925  if ( _getPolygon( pts, holes, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() ) == nullptr )
926  {
927  break;
928  }
929  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
930 
931  if ( drawVertexMarker && !deleteSegmentizedGeometry )
932  {
933  if ( i == 0 )
934  {
935  markers = pts;
936  }
937  else
938  {
939  markers << pts;
940  }
941 
942  Q_FOREACH ( const QPolygonF& hole, holes )
943  {
944  markers << hole;
945  }
946  }
947  }
948  break;
949  }
951  {
952  QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() );
953  wkbPtr.readHeader();
954 
955  int nGeometries;
956  wkbPtr >> nGeometries;
957 
958  if ( nGeometries == 0 )
959  {
960  // skip noise from empty geometry collections from simplification
961  break;
962  }
963 
964  FALLTHROUGH;
965  }
966  default:
967  QgsDebugMsg( QString( "feature %1: unsupported wkb type %2/%3 for rendering" )
968  .arg( feature.id() )
969  .arg( QgsWKBTypes::displayString( geom->geometry()->wkbType() ) )
970  .arg( geom->wkbType(), 0, 16 ) );
971  }
972 
973  if ( drawVertexMarker )
974  {
975  if ( markers.size() > 0 )
976  {
977  Q_FOREACH ( QPointF marker, markers )
978  {
979  renderVertexMarker( marker, context, currentVertexMarkerType, currentVertexMarkerSize );
980  }
981  }
982  else
983  {
984  const QgsCoordinateTransform* ct = context.coordinateTransform();
985  const QgsMapToPixel& mtp = context.mapToPixel();
986 
987  QgsPointV2 vertexPoint;
988  QgsVertexId vertexId;
989  double x, y, z;
990  QPointF mapPoint;
991  while ( geom->geometry()->nextVertex( vertexId, vertexPoint ) )
992  {
993  //transform
994  x = vertexPoint.x();
995  y = vertexPoint.y();
996  z = 0.0;
997  if ( ct )
998  {
999  ct->transformInPlace( x, y, z );
1000  }
1001  mapPoint.setX( x );
1002  mapPoint.setY( y );
1003  mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
1004  renderVertexMarker( mapPoint, context, currentVertexMarkerType, currentVertexMarkerSize );
1005  }
1006  }
1007  }
1008 
1009  if ( deleteSegmentizedGeometry )
1010  {
1011  delete segmentizedGeometry;
1012  }
1013 
1014  if ( mSymbolRenderContext->expressionContextScope() )
1015  context.expressionContext().popScope();
1016 }
1017 
1019 {
1020  return mSymbolRenderContext;
1021 }
1022 
1023 void QgsSymbolV2::renderVertexMarker( QPointF pt, QgsRenderContext& context, int currentVertexMarkerType, int currentVertexMarkerSize )
1024 {
1025  QgsVectorLayer::drawVertexMarker( pt.x(), pt.y(), *context.painter(), static_cast< QgsVectorLayer::VertexMarkerType >( currentVertexMarkerType ), currentVertexMarkerSize );
1026 }
1027 
1029 
1030 
1032  : mRenderContext( c )
1033  , mExpressionContextScope( nullptr )
1034  , mOutputUnit( u )
1035  , mMapUnitScale( mapUnitScale )
1036  , mAlpha( alpha )
1037  , mSelected( selected )
1038  , mRenderHints( renderHints )
1039  , mFeature( f )
1040  , mFields( fields )
1041  , mGeometryPartCount( 0 )
1042  , mGeometryPartNum( 0 )
1043 {
1044 }
1045 
1047 {
1048  delete mExpressionContextScope;
1049 }
1050 
1052 {
1053  mRenderContext.expressionContext().setOriginalValueVariable( value );
1054 }
1055 
1056 double QgsSymbolV2RenderContext::outputLineWidth( double width ) const
1057 {
1058  return QgsSymbolLayerV2Utils::convertToPainterUnits( mRenderContext, width, mOutputUnit, mMapUnitScale );
1059 }
1060 
1062 {
1063  return size * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
1064 }
1065 
1067 {
1068  // This is just a dummy implementation of assignment.
1069  // sip 4.7 generates a piece of code that needs this function to exist.
1070  // It's not generated automatically by the compiler because of
1071  // mRenderContext member which is a reference (and thus can't be changed).
1072  Q_ASSERT( false );
1073  return *this;
1074 }
1075 
1077 {
1078  return mExpressionContextScope;
1079 }
1080 
1082 {
1083  mExpressionContextScope = contextScope;
1084 }
1085 
1087 
1089 {
1091  if ( !sl )
1092  return nullptr;
1093 
1094  QgsSymbolLayerV2List layers;
1095  layers.append( sl );
1096  return new QgsMarkerSymbolV2( layers );
1097 }
1098 
1100 {
1102  if ( !sl )
1103  return nullptr;
1104 
1105  QgsSymbolLayerV2List layers;
1106  layers.append( sl );
1107  return new QgsLineSymbolV2( layers );
1108 }
1109 
1111 {
1113  if ( !sl )
1114  return nullptr;
1115 
1116  QgsSymbolLayerV2List layers;
1117  layers.append( sl );
1118  return new QgsFillSymbolV2( layers );
1119 }
1120 
1122 
1124  : QgsSymbolV2( Marker, layers )
1125 {
1126  if ( mLayers.isEmpty() )
1128 }
1129 
1131 {
1132  double origAngle = angle();
1133  double angleDiff = ang - origAngle;
1134  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1135  {
1136  QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
1137  if ( markerLayer )
1138  markerLayer->setAngle( markerLayer->angle() + angleDiff );
1139  }
1140 }
1141 
1143 {
1144  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1145  {
1146  if ( layer->type() != QgsSymbolV2::Marker )
1147  continue;
1148  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1149  return markerLayer->angle();
1150  }
1151  return 0;
1152 }
1153 
1154 void QgsMarkerSymbolV2::setLineAngle( double lineAng )
1155 {
1156  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1157  {
1158  if ( layer->type() != QgsSymbolV2::Marker )
1159  continue;
1160  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1161  markerLayer->setLineAngle( lineAng );
1162  }
1163 }
1164 
1166 {
1167  const double symbolRotation = angle();
1168 
1169  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1170  {
1171  if ( layer->type() != QgsSymbolV2::Marker )
1172  continue;
1173  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1174  if ( dd.hasDefaultValues() )
1175  {
1176  layer->removeDataDefinedProperty( "angle" );
1177  }
1178  else
1179  {
1180  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1181  {
1182  layer->setDataDefinedProperty( "angle", new QgsDataDefined( dd ) );
1183  }
1184  else
1185  {
1186  QgsDataDefined* rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, dd );
1187  layer->setDataDefinedProperty( "angle", rotatedDD );
1188  }
1189  }
1190  }
1191 }
1192 
1194 {
1195  const double symbolRotation = angle();
1196  QgsDataDefined* symbolDD = nullptr;
1197 
1198  // find the base of the "en masse" pattern
1199  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1200  {
1201  if ( layer->type() != QgsSymbolV2::Marker )
1202  continue;
1203  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1204  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) && markerLayer->getDataDefinedProperty( "angle" ) )
1205  {
1206  symbolDD = markerLayer->getDataDefinedProperty( "angle" );
1207  break;
1208  }
1209  }
1210 
1211  if ( !symbolDD )
1212  return QgsDataDefined();
1213 
1214  // check that all layer's angle expressions match the "en masse" pattern
1215  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1216  {
1217  if ( layer->type() != QgsSymbolV2::Marker )
1218  continue;
1219  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1220  QgsDataDefined* layerAngleDD = markerLayer->getDataDefinedProperty( "angle" );
1221 
1222  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1223  {
1224  if ( !layerAngleDD || *layerAngleDD != *symbolDD )
1225  return QgsDataDefined();
1226  }
1227  else
1228  {
1229  QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( markerLayer->angle() - symbolRotation, *symbolDD ) );
1230  if ( !layerAngleDD || *layerAngleDD != *( rotatedDD.data() ) )
1231  return QgsDataDefined();
1232  }
1233  }
1234  return QgsDataDefined( *symbolDD );
1235 }
1236 
1237 
1239 {
1240  double origSize = size();
1241 
1242  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1243  {
1244  if ( layer->type() != QgsSymbolV2::Marker )
1245  continue;
1246  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1247  if ( qgsDoubleNear( markerLayer->size(), origSize ) )
1248  markerLayer->setSize( s );
1249  else if ( !qgsDoubleNear( origSize, 0.0 ) )
1250  {
1251  // proportionally scale size
1252  markerLayer->setSize( markerLayer->size() * s / origSize );
1253  }
1254  // also scale offset to maintain relative position
1255  if ( !qgsDoubleNear( origSize, 0.0 ) && ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) ) )
1256  markerLayer->setOffset( QPointF( markerLayer->offset().x() * s / origSize,
1257  markerLayer->offset().y() * s / origSize ) );
1258  }
1259 }
1260 
1262 {
1263  // return size of the largest symbol
1264  double maxSize = 0;
1265  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1266  {
1267  if ( layer->type() != QgsSymbolV2::Marker )
1268  continue;
1269  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1270  double lsize = markerLayer->size();
1271  if ( lsize > maxSize )
1272  maxSize = lsize;
1273  }
1274  return maxSize;
1275 }
1276 
1278 {
1279  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1280  {
1281  if ( layer->type() != QgsSymbolV2::Marker )
1282  continue;
1283 
1284  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1285  markerLayer->setSizeUnit( unit );
1286  }
1287 }
1288 
1290 {
1291  bool first = true;
1292  OutputUnit unit = Mixed;
1293 
1294  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1295  {
1296  if ( layer->type() != QgsSymbolV2::Marker )
1297  continue;
1298  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1299 
1300  if ( first )
1301  unit = markerLayer->sizeUnit();
1302  else
1303  {
1304  if ( unit != markerLayer->sizeUnit() )
1305  return Mixed;
1306  }
1307 
1308  first = false;
1309  }
1310  return unit;
1311 }
1312 
1314 {
1315  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1316  {
1317  if ( layer->type() != QgsSymbolV2::Marker )
1318  continue;
1319 
1320  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1321  markerLayer->setSizeMapUnitScale( scale );
1322  }
1323 }
1324 
1326 {
1327  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1328  {
1329  if ( layer->type() != QgsSymbolV2::Marker )
1330  continue;
1331 
1332  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1333  return markerLayer->sizeMapUnitScale();
1334  }
1335  return QgsMapUnitScale();
1336 }
1337 
1339 {
1340  const double symbolSize = size();
1341 
1342  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1343  {
1344  if ( layer->type() != QgsSymbolV2::Marker )
1345  continue;
1346  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1347 
1348  if ( dd.hasDefaultValues() )
1349  {
1350  markerLayer->removeDataDefinedProperty( "size" );
1351  markerLayer->removeDataDefinedProperty( "offset" );
1352  }
1353  else
1354  {
1355  if ( qgsDoubleNear( symbolSize, 0.0 ) || qgsDoubleNear( markerLayer->size(), symbolSize ) )
1356  {
1357  markerLayer->setDataDefinedProperty( "size", new QgsDataDefined( dd ) );
1358  }
1359  else
1360  {
1361  markerLayer->setDataDefinedProperty( "size", scaleWholeSymbol( markerLayer->size() / symbolSize, dd ) );
1362  }
1363 
1364  if ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) )
1365  {
1366  markerLayer->setDataDefinedProperty( "offset", scaleWholeSymbol(
1367  markerLayer->offset().x() / symbolSize,
1368  markerLayer->offset().y() / symbolSize, dd ) );
1369  }
1370  }
1371  }
1372 }
1373 
1375 {
1376  const double symbolSize = size();
1377 
1378  QgsDataDefined* symbolDD = nullptr;
1379 
1380  // find the base of the "en masse" pattern
1381  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1382  {
1383  if ( layer->type() != QgsSymbolV2::Marker )
1384  continue;
1385  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1386  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) && markerLayer->getDataDefinedProperty( "size" ) )
1387  {
1388  symbolDD = markerLayer->getDataDefinedProperty( "size" );
1389  break;
1390  }
1391  }
1392 
1393  if ( !symbolDD )
1394  return QgsDataDefined();
1395 
1396  // check that all layers size expressions match the "en masse" pattern
1397  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1398  {
1399  if ( layer->type() != QgsSymbolV2::Marker )
1400  continue;
1401  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1402 
1403  QgsDataDefined* layerSizeDD = markerLayer->getDataDefinedProperty( "size" );
1404  QgsDataDefined* layerOffsetDD = markerLayer->getDataDefinedProperty( "offset" );
1405 
1406  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
1407  {
1408  if ( !layerSizeDD || *layerSizeDD != *symbolDD )
1409  return QgsDataDefined();
1410  }
1411  else
1412  {
1413  if ( qgsDoubleNear( symbolSize, 0.0 ) )
1414  return QgsDataDefined();
1415 
1416  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( markerLayer->size() / symbolSize, *symbolDD ) );
1417  if ( !layerSizeDD || *layerSizeDD != *( scaledDD.data() ) )
1418  return QgsDataDefined();
1419  }
1420 
1421  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, *symbolDD ) );
1422  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
1423  return QgsDataDefined();
1424  }
1425 
1426  return QgsDataDefined( *symbolDD );
1427 }
1428 
1430 {
1431  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1432  {
1433  if ( layer->type() != QgsSymbolV2::Marker )
1434  continue;
1435  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1436  markerLayer->setScaleMethod( scaleMethod );
1437  }
1438 }
1439 
1441 {
1442  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1443  {
1444  if ( layer->type() != QgsSymbolV2::Marker )
1445  continue;
1446  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1447  // return scale method of the first symbol layer
1448  return markerLayer->scaleMethod();
1449  }
1450 
1451  return DEFAULT_SCALE_METHOD;
1452 }
1453 
1454 void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, QPointF point, QgsSymbolV2RenderContext& context )
1455 {
1456  static QPointF nullPoint( 0, 0 );
1457 
1458  QgsPaintEffect* effect = layer->paintEffect();
1459  if ( effect && effect->enabled() )
1460  {
1461  QPainter* p = context.renderContext().painter();
1462  p->save();
1463  p->translate( point );
1464 
1465  effect->begin( context.renderContext() );
1466  layer->renderPoint( nullPoint, context );
1467  effect->end( context.renderContext() );
1468 
1469  p->restore();
1470  }
1471  else
1472  {
1473  layer->renderPoint( point, context );
1474  }
1475 }
1476 
1477 void QgsMarkerSymbolV2::renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1478 {
1479  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1480  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1481  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1482 
1483  if ( layerIdx != -1 )
1484  {
1485  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1486  if ( symbolLayer )
1487  {
1488  if ( symbolLayer->type() == QgsSymbolV2::Marker )
1489  {
1490  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( symbolLayer );
1491  renderPointUsingLayer( markerLayer, point, symbolContext );
1492  }
1493  else
1494  renderUsingLayer( symbolLayer, symbolContext );
1495  }
1496  return;
1497  }
1498 
1499  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1500  {
1501  if ( symbolLayer->type() == QgsSymbolV2::Marker )
1502  {
1503  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( symbolLayer );
1504  renderPointUsingLayer( markerLayer, point, symbolContext );
1505  }
1506  else
1507  renderUsingLayer( symbolLayer, symbolContext );
1508  }
1509 }
1510 
1511 QRectF QgsMarkerSymbolV2::bounds( QPointF point, QgsRenderContext& context, const QgsFeature& feature ) const
1512 {
1513  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, &feature, feature.fields(), mapUnitScale() );
1514 
1515  QRectF bound;
1516  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1517  {
1518  if ( layer->type() == QgsSymbolV2::Marker )
1519  {
1521  if ( bound.isNull() )
1522  bound = symbolLayer->bounds( point, symbolContext );
1523  else
1524  bound = bound.united( symbolLayer->bounds( point, symbolContext ) );
1525  }
1526  }
1527  return bound;
1528 }
1529 
1531 {
1532  QgsMarkerSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
1533  cloneSymbol->setAlpha( mAlpha );
1534  cloneSymbol->setLayer( mLayer );
1536  return cloneSymbol;
1537 }
1538 
1539 
1541 // LINE
1542 
1544  : QgsSymbolV2( Line, layers )
1545 {
1546  if ( mLayers.isEmpty() )
1548 }
1549 
1551 {
1552  double origWidth = width();
1553 
1554  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1555  {
1556  QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
1557 
1558  if ( lineLayer )
1559  {
1560  if ( qgsDoubleNear( lineLayer->width(), origWidth ) )
1561  {
1562  lineLayer->setWidth( w );
1563  }
1564  else if ( !qgsDoubleNear( origWidth, 0.0 ) )
1565  {
1566  // proportionally scale the width
1567  lineLayer->setWidth( lineLayer->width() * w / origWidth );
1568  }
1569  // also scale offset to maintain relative position
1570  if ( !qgsDoubleNear( origWidth, 0.0 ) && !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1571  lineLayer->setOffset( lineLayer->offset() * w / origWidth );
1572  }
1573  }
1574 }
1575 
1577 {
1578  double maxWidth = 0;
1579  if ( mLayers.isEmpty() )
1580  return maxWidth;
1581 
1582  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1583  {
1584  const QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1585  if ( lineLayer )
1586  {
1587  double width = lineLayer->width();
1588  if ( width > maxWidth )
1589  maxWidth = width;
1590  }
1591  }
1592  return maxWidth;
1593 }
1594 
1596 {
1597  const double symbolWidth = width();
1598 
1599  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1600  {
1601  QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
1602 
1603  if ( lineLayer )
1604  {
1605  if ( dd.hasDefaultValues() )
1606  {
1607  lineLayer->removeDataDefinedProperty( "width" );
1608  lineLayer->removeDataDefinedProperty( "offset" );
1609  }
1610  else
1611  {
1612  if ( qgsDoubleNear( symbolWidth, 0.0 ) || qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1613  {
1614  lineLayer->setDataDefinedProperty( "width", new QgsDataDefined( dd ) );
1615  }
1616  else
1617  {
1618  lineLayer->setDataDefinedProperty( "width", scaleWholeSymbol( lineLayer->width() / symbolWidth, dd ) );
1619  }
1620 
1621  if ( !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1622  {
1623  lineLayer->setDataDefinedProperty( "offset", scaleWholeSymbol( lineLayer->offset() / symbolWidth, dd ) );
1624  }
1625  }
1626  }
1627  }
1628 }
1629 
1631 {
1632  const double symbolWidth = width();
1633 
1634  QgsDataDefined* symbolDD = nullptr;
1635 
1636  // find the base of the "en masse" pattern
1637  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1638  {
1639  const QgsLineSymbolLayerV2* layer = dynamic_cast<const QgsLineSymbolLayerV2*>( *it );
1640  if ( layer && qgsDoubleNear( layer->width(), symbolWidth ) && layer->getDataDefinedProperty( "width" ) )
1641  {
1642  symbolDD = layer->getDataDefinedProperty( "width" );
1643  break;
1644  }
1645  }
1646 
1647  if ( !symbolDD )
1648  return QgsDataDefined();
1649 
1650  // check that all layers width expressions match the "en masse" pattern
1651  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1652  {
1653  if ( layer->type() != QgsSymbolV2::Line )
1654  continue;
1655  const QgsLineSymbolLayerV2* lineLayer = static_cast<const QgsLineSymbolLayerV2*>( layer );
1656 
1657  QgsDataDefined* layerWidthDD = lineLayer->getDataDefinedProperty( "width" );
1658  QgsDataDefined* layerOffsetDD = lineLayer->getDataDefinedProperty( "offset" );
1659 
1660  if ( qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1661  {
1662  if ( !layerWidthDD || *layerWidthDD != *symbolDD )
1663  return QgsDataDefined();
1664  }
1665  else
1666  {
1667  if ( qgsDoubleNear( symbolWidth, 0.0 ) )
1668  return QgsDataDefined();
1669 
1670  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( lineLayer->width() / symbolWidth, *symbolDD ) );
1671  if ( !layerWidthDD || *layerWidthDD != *( scaledDD.data() ) )
1672  return QgsDataDefined();
1673  }
1674 
1675  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( lineLayer->offset() / symbolWidth, *symbolDD ) );
1676  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
1677  return QgsDataDefined();
1678  }
1679 
1680  return QgsDataDefined( *symbolDD );
1681 }
1682 
1683 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1684 {
1685  //save old painter
1686  QPainter* renderPainter = context.painter();
1687  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1688  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1689  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1690 
1691  if ( layerIdx != -1 )
1692  {
1693  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1694  if ( symbolLayer )
1695  {
1696  if ( symbolLayer->type() == QgsSymbolV2::Line )
1697  {
1698  QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1699  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1700  }
1701  else
1702  renderUsingLayer( symbolLayer, symbolContext );
1703  }
1704  return;
1705  }
1706 
1707  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1708  {
1709  if ( symbolLayer->type() == QgsSymbolV2::Line )
1710  {
1711  QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1712  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1713  }
1714  else
1715  {
1716  renderUsingLayer( symbolLayer, symbolContext );
1717  }
1718  }
1719 
1720  context.setPainter( renderPainter );
1721 }
1722 
1723 void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context )
1724 {
1725  QgsPaintEffect* effect = layer->paintEffect();
1726  if ( effect && effect->enabled() )
1727  {
1728  QPainter* p = context.renderContext().painter();
1729  p->save();
1730  p->translate( points.boundingRect().topLeft() );
1731 
1732  effect->begin( context.renderContext() );
1733  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
1734  effect->end( context.renderContext() );
1735 
1736  p->restore();
1737  }
1738  else
1739  {
1740  layer->renderPolyline( points, context );
1741  }
1742 }
1743 
1744 
1746 {
1747  QgsLineSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
1748  cloneSymbol->setAlpha( mAlpha );
1749  cloneSymbol->setLayer( mLayer );
1751  return cloneSymbol;
1752 }
1753 
1755 // FILL
1756 
1758  : QgsSymbolV2( Fill, layers )
1759 {
1760  if ( mLayers.isEmpty() )
1762 }
1763 
1764 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1765 {
1766  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1767  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1768  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1769 
1770  if ( layerIdx != -1 )
1771  {
1772  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1773  if ( symbolLayer )
1774  {
1775  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1776  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1777  else
1778  renderUsingLayer( symbolLayer, symbolContext );
1779  }
1780  return;
1781  }
1782 
1783  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1784  {
1785  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1786  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1787  else
1788  renderUsingLayer( symbolLayer, symbolContext );
1789  }
1790 }
1791 
1792 void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
1793 {
1794  QgsSymbolV2::SymbolType layertype = layer->type();
1795 
1796  QgsPaintEffect* effect = layer->paintEffect();
1797  if ( effect && effect->enabled() )
1798  {
1799  QRectF bounds = polygonBounds( points, rings );
1800  QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
1801 
1802  QPainter* p = context.renderContext().painter();
1803  p->save();
1804  p->translate( bounds.topLeft() );
1805 
1806  effect->begin( context.renderContext() );
1807  if ( layertype == QgsSymbolV2::Fill )
1808  {
1809  ( static_cast<QgsFillSymbolLayerV2*>( layer ) )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
1810  }
1811  else if ( layertype == QgsSymbolV2::Line )
1812  {
1813  ( static_cast<QgsLineSymbolLayerV2*>( layer ) )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context );
1814  }
1815  delete translatedRings;
1816 
1817  effect->end( context.renderContext() );
1818  p->restore();
1819  }
1820  else
1821  {
1822  if ( layertype == QgsSymbolV2::Fill )
1823  {
1824  ( static_cast<QgsFillSymbolLayerV2*>( layer ) )->renderPolygon( points, rings, context );
1825  }
1826  else if ( layertype == QgsSymbolV2::Line )
1827  {
1828  ( static_cast<QgsLineSymbolLayerV2*>( layer ) )->renderPolygonOutline( points, rings, context );
1829  }
1830  }
1831 }
1832 
1833 QRectF QgsFillSymbolV2::polygonBounds( const QPolygonF& points, const QList<QPolygonF>* rings ) const
1834 {
1835  QRectF bounds = points.boundingRect();
1836  if ( rings )
1837  {
1839  for ( ; it != rings->constEnd(); ++it )
1840  {
1841  bounds = bounds.united(( *it ).boundingRect() );
1842  }
1843  }
1844  return bounds;
1845 }
1846 
1847 QList<QPolygonF>* QgsFillSymbolV2::translateRings( const QList<QPolygonF>* rings, double dx, double dy ) const
1848 {
1849  if ( !rings )
1850  return nullptr;
1851 
1852  QList<QPolygonF>* translatedRings = new QList<QPolygonF>;
1854  for ( ; it != rings->constEnd(); ++it )
1855  {
1856  translatedRings->append(( *it ).translated( dx, dy ) );
1857  }
1858  return translatedRings;
1859 }
1860 
1862 {
1863  QgsFillSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
1864  cloneSymbol->setAlpha( mAlpha );
1865  cloneSymbol->setLayer( mLayer );
1867  return cloneSymbol;
1868 }
1869 
1871 {
1872  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1873  {
1874  if ( layer->type() != QgsSymbolV2::Fill )
1875  continue;
1876 
1877  QgsFillSymbolLayerV2* fillLayer = static_cast<QgsFillSymbolLayerV2*>( layer );
1878 
1879  if ( fillLayer )
1880  fillLayer->setAngle( angle );
1881  }
1882 }
1883 
1884 
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
double angle() const
Returns the rotation angle for the marker, in degrees clockwise from north.
virtual void renderPoint(QPointF point, QgsSymbolV2RenderContext &context)=0
Renders a marker at the specified point.
virtual void setMapUnitScale(const QgsMapUnitScale &scale)
QgsFillSymbolV2(const QgsSymbolLayerV2List &layers=QgsSymbolLayerV2List())
void setForceVectorOutput(bool force)
void clear()
void setLocked(bool locked)
static int coordDimensions(Type type)
Returns the coordinate dimension of the geometry type as an integer.
Definition: qgswkbtypes.h:573
bool deleteSymbolLayer(int index)
delete symbol layer at specified index
static unsigned index
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
void setViewBox(const QRect &viewBox)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
void renderPolygon(const QPolygonF &points, QList< QPolygonF > *rings, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
static QgsMarkerSymbolV2 * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
void setClipFeaturesToExtent(bool clipFeaturesToExtent)
Sets whether features drawn by the symbol should be clipped to the render context&#39;s extent...
Definition: qgssymbolv2.h:218
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:65
virtual void setOutputUnit(QgsSymbolV2::OutputUnit unit)
int width() const
bool mClipFeaturesToExtent
Definition: qgssymbolv2.h:332
void setDataDefinedAngle(const QgsDataDefined &dd)
Set data defined angle for whole symbol (including all symbol layers).
A container class for data source field mapping or expression.
bool end()
QgsMapUnitScale sizeMapUnitScale() const
Returns the size map unit scale for the whole symbol.
GeometryType
Definition: qgis.h:115
void setSize(const QSize &size)
virtual double width() const
void setGeometryPartCount(int count)
Sets the part count of current geometry.
Definition: qgssymbolv2.h:399
virtual QgsLineSymbolV2 * clone() const override
int remaining() const
Definition: qgswkbptr.h:133
void setRenderHint(RenderHint hint, bool on)
const QgsVectorLayer * mLayer
Definition: qgssymbolv2.h:334
void append(const T &value)
double x() const
Returns the point&#39;s x-coordinate.
Definition: qgspointv2.h:68
OutputUnit sizeUnit() const
Returns the size units for the whole symbol (including all symbol layers).
SymbolType type() const
Definition: qgssymbolv2.h:107
void transformPolygon(QPolygonF &poly, TransformDirection direction=ForwardTransform) const
virtual bool isCompatibleWithSymbol(QgsSymbolV2 *symbol) const
Returns if the layer can be used below the specified symbol.
QSet< QString > usedAttributes() const
Return a list of attributes required to render this feature.
const QgsVectorSimplifyMethod & vectorSimplifyMethod() const
Added in QGIS v2.4.
QString field() const
Get the field which this QgsDataDefined represents.
virtual QRectF bounds(QPointF point, QgsSymbolV2RenderContext &context)
Returns the approximate bounding box of the marker symbol layer, taking into account any data defined...
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setDataDefinedSize(const QgsDataDefined &dd)
Set data defined size for whole symbol (including all symbol layers).
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
bool save(const QString &fileName, const char *format, int quality) const
static QString encodeColor(const QColor &color)
static QString encodeSldUom(QgsSymbolV2::OutputUnit unit, double *scaleFactor)
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
Sets the method to use for scaling the marker&#39;s size.
double size() const
Returns the size for the whole symbol, which is the maximum size of all marker symbol layers in the s...
QgsDataDefined dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
static QgsFillSymbolV2 * createSimple(const QgsStringMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties. ...
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
const T & at(int i) const
VertexMarkerType
Editing vertex markers.
void setOffset(QPointF offset)
Sets the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered marker...
void removeAt(int i)
QPolygonF translated(qreal dx, qreal dy) const
bool enabled() const
Returns whether the effect is enabled.
Base class for visual effects which can be applied to QPicture drawings.
bool changeSymbolLayer(int index, QgsSymbolLayerV2 *layer)
delete layer at specified index and set a new one
QgsSymbolV2RenderContext(QgsRenderContext &c, QgsSymbolV2::OutputUnit u, qreal alpha=1.0, bool selected=false, int renderHints=0, const QgsFeature *f=nullptr, const QgsFields *fields=nullptr, const QgsMapUnitScale &mapUnitScale=QgsMapUnitScale())
ScaleMethod scaleMethod()
void save()
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for data defined symbology.
static void _getPoint(QPointF &pt, QgsRenderContext &context, const QgsPointV2 *point)
Creates a point in screen coordinates from a QgsPointV2 in map coordinates.
Definition: qgssymbolv2.h:264
Abstract base class for all geometries.
QgsMapUnitScale mapUnitScale() const
Container of fields for a vector layer.
Definition: qgsfield.h:209
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
qreal top() const
Line symbol.
Definition: qgssymbolv2.h:82
QString expressionString() const
Returns the expression string of this QgsDataDefined.
T takeAt(int i)
const QgsRectangle & extent() const
QgsSymbolV2::OutputUnit sizeUnit() const
Returns the units for the symbol&#39;s size.
Multi point geometry collection.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
void drawLine(const QLineF &line)
void renderFeature(const QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false, int currentVertexMarkerType=0, int currentVertexMarkerSize=0)
Render a feature.
const QgsCoordinateTransform * coordinateTransform() const
void setExpressionContextScope(QgsExpressionContextScope *contextScope)
Set an expression scope for this symbol.
SymbolType mType
Definition: qgssymbolv2.h:325
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
Creates a new QgsSimpleMarkerSymbolLayerV2.
virtual void removeDataDefinedProperty(const QString &property)
Removes a data defined property from the layer.
void drawPreviewIcon(QPainter *painter, QSize size, QgsRenderContext *customContext=nullptr)
Draw icon of the symbol that occupyies area given by size using the painter.
qreal left() const
void setVariable(const QString &name, const QVariant &value)
Convenience method for setting a variable in the context scope by name and value. ...
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:353
void setSizeUnit(OutputUnit unit)
Sets the size units for the whole symbol (including all symbol layers).
static double pixelSizeScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns scale factor painter units -> pixel dimensions.
void setWidth(double width)
QgsDataDefined * scaleWholeSymbol(double scaleFactor, const QgsDataDefined &dd)
Definition: qgssymbolv2.cpp:60
Marker symbol.
Definition: qgssymbolv2.h:81
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the size map unit scale for the whole symbol (including all symbol layers).
QgsDataDefined dataDefinedWidth() const
Returns data defined size for whole symbol (including all symbol layers).
void setMapUnitScale(const QgsMapUnitScale &scale)
static QgsConstWkbPtr clippedLineWKB(QgsConstWkbPtr &wkb, const QgsRectangle &clipExtent, QPolygonF &line)
Reads a polyline from WKB and clips it to clipExtent.
Definition: qgsclipper.cpp:41
void setAngle(double angle)
const QgsVectorLayer * layer() const
Definition: qgssymbolv2.h:244
virtual void startRender(QgsSymbolV2RenderContext &context)=0
T value(int i) const
double y() const
Returns the point&#39;s y-coordinate.
Definition: qgspointv2.h:74
QColor fromHsv(int h, int s, int v, int a)
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
T * data()
void drawRect(const QRectF &rectangle)
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
void setUseExpression(bool use)
Controls if the field or the expression part is active.
void setColor(const QColor &color)
Mixed units in symbol layers.
Definition: qgssymbolv2.h:69
void transformInPlace(double &x, double &y, double &z, TransformDirection direction=ForwardTransform) const
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
static QgsRenderContext createRenderContext(QPainter *p)
Creates a render context for a pixel based device.
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=nullptr) const
QString number(int n, int base)
QgsSymbolLayerV2List mLayers
Definition: qgssymbolv2.h:326
int count(const T &value) const
qreal x() const
qreal y() const
void append(const T &value)
double width() const
QgsSymbolLayerV2List cloneLayers() const
Retrieve a cloned list of all layers that make up this symbol.
void setOffset(double offset)
bool appendSymbolLayer(QgsSymbolLayerV2 *layer)
Append symbol layer at the end of the list Ownership will be transferred.
#define FALLTHROUGH
Definition: qgis.h:539
bool empty() const
void startRender(QgsRenderContext &context, const QgsFields *fields=nullptr)
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
void fill(uint pixelValue)
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
static double convertToPainterUnits(const QgsRenderContext &c, double size, QgsSymbolV2::OutputUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale())
Converts a size from the specied units to painter units.
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol&#39;s angle.
Utility class for identifying a unique vertex within a geometry.
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:203
static QgsLineSymbolV2 * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
static bool isCurvedType(Type type)
Returns true if the WKB type is a curved type or can contain curved geometries.
Definition: qgswkbtypes.h:531
void setPen(const QColor &color)
Q_DECL_DEPRECATED bool isSymbolLayerCompatible(SymbolType layerType)
check whether a symbol layer type can be used within the symbol (marker-marker, line-line, fill-fill/line)
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
void setRenderingPass(int renderingPass)
#define DEFAULT_SCALE_METHOD
void setLayer(const QgsVectorLayer *layer)
Definition: qgssymbolv2.h:243
const QgsFields * fields() const
Returns the field map associated with the feature.
Definition: qgsfeature.cpp:188
Point geometry type, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:341
bool isEmpty() const
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
virtual void setWidth(double width)
static QgsStyleV2 * defaultStyle()
return default application-wide style
Definition: qgsstylev2.cpp:51
QPointF topLeft() const
double segmentationTolerance() const
Gets the segmentation tolerance applied when rendering curved geometries.
void renderPolyline(const QPolygonF &points, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
QgsMarkerSymbolV2(const QgsSymbolLayerV2List &layers=QgsSymbolLayerV2List())
void setAngle(double angle)
double angle() const
Returns the marker angle for the whole symbol.
void setAngle(double angle)
Sets the angle for the whole symbol.
void setSizeUnit(QgsSymbolV2::OutputUnit unit)
Sets the units for the symbol&#39;s size.
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...
Draw bounds of symbols (for debugging/testing)
const QgsMapUnitScale & sizeMapUnitScale() const
Returns the map unit scale for the symbol&#39;s size.
void setBrush(const QBrush &brush)
void setPainter(QPainter *p)
void setSize(double size)
Sets the size for the whole symbol.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
qreal mAlpha
Symbol opacity (in the range 0 - 1)
Definition: qgssymbolv2.h:329
virtual int partCount() const =0
Returns count of parts contained in the geometry.
QgsSymbolV2RenderContext & operator=(const QgsSymbolV2RenderContext &)
QRectF united(const QRectF &rectangle) const
virtual void renderPolygonOutline(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)
QgsSymbolV2(SymbolType type, const QgsSymbolLayerV2List &layers)
Definition: qgssymbolv2.cpp:85
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const =0
Returns next vertex id and coordinates.
QgsDataDefined * rotateWholeSymbol(double additionalRotation, const QgsDataDefined &dd)
Definition: qgssymbolv2.cpp:50
Single scope for storing variables and functions for use within a QgsExpressionContext.
virtual bool hasDataDefinedProperties() const
Checks whether the layer has any associated data defined properties.
static void drawVertexMarker(double x, double y, QPainter &p, QgsVectorLayer::VertexMarkerType type, int vertexSize)
Draws a vertex symbol at (screen) coordinates x, y.
void setLineAngle(double lineAngle)
Sets the line angle modification for the symbol&#39;s angle.
QgsSymbolV2::ScaleMethod scaleMethod() const
Returns the method to use for scaling the marker&#39;s size.
double size() const
Returns the symbol size.
QgsSymbolV2::SymbolType type() const
bool useExpression() const
Returns if the field or the expression part is active.
T * data() const
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
iterator end()
QString toLower() const
virtual ~QgsSymbolV2()
void reserve(int size)
virtual void renderPolyline(const QPolygonF &points, QgsSymbolV2RenderContext &context)=0
QgsSymbolV2 * symbol(const QString &name)
return a NEW copy of symbol
Definition: qgsstylev2.cpp:164
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const
Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation...
virtual QgsFillSymbolV2 * clone() const override
QImage bigSymbolPreviewImage(QgsExpressionContext *expressionContext=nullptr)
Returns a large (roughly 100x100 pixel) preview image for the symbol.
void setFileName(const QString &fileName)
void exportImage(const QString &path, const QString &format, QSize size)
export symbol as image format. PNG and SVG supported
QgsExpressionContext & expressionContext()
Gets the expression context.
void renderUsingLayer(QgsSymbolLayerV2 *layer, QgsSymbolV2RenderContext &context)
Renders a context using a particular symbol layer without passing in a geometry.
SymbolType
Type of the symbol.
Definition: qgssymbolv2.h:79
void restore()
void setDataDefinedWidth(const QgsDataDefined &dd)
Set data defined width for whole symbol (including all symbol layers).
Hybrid symbol.
Definition: qgssymbolv2.h:84
int numGeometries() const
Returns the number of geometries within the collection.
QgsExpressionContextScope * expressionContextScope()
This scope is always available when a symbol of this type is being rendered.
Contains information about the context of a rendering operation.
QRectF boundingRect() const
QPainter * painter()
QgsDataDefined dataDefinedAngle() const
Returns data defined angle for whole symbol (including all symbol layers).
int wkbSize() const
Returns the size of the WKB in asWkb().
void stopRender(QgsRenderContext &context)
bool insertSymbolLayer(int index, QgsSymbolLayerV2 *layer)
Insert symbol layer to specified index Ownership will be transferred.
QSet< T > & unite(const QSet< T > &other)
static QgsSymbolV2 * defaultSymbol(QGis::GeometryType geomType)
return new default symbol for specified geometry type
ScaleMethod
Scale method.
Definition: qgssymbolv2.h:90
Struct for storing maximum and minimum scales for measurements in map units.
bool isLocked() const
void insert(int i, const T &value)
QImage asImage(QSize size, QgsRenderContext *customContext=nullptr)
Generate symbol as image.
double offset() const
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:355
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
virtual QgsDataDefined * getDataDefinedProperty(const QString &property) const
Returns the data defined property corresponding to the specified property key.
void setX(qreal x)
void setY(qreal y)
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
int height() const
Fill symbol.
Definition: qgssymbolv2.h:83
QgsSymbolV2::OutputUnit outputUnit() const
int geometryPartCount() const
Part count of current geometry.
Definition: qgssymbolv2.h:395
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
static QgsConstWkbPtr _getPolygon(QPolygonF &pts, QList< QPolygonF > &holes, QgsRenderContext &context, QgsConstWkbPtr &wkb, bool clipToExtent=true)
Creates a polygon in screen coordinates from a wkb string in map coordinates.
qreal & rx()
qreal & ry()
Class for doing transforms between two map coordinate systems.
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
void renderPoint(QPointF point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
void translate(const QPointF &offset)
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
const QgsMapToPixel & mapToPixel() const
virtual void setColor(const QColor &color)
The fill color.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
void setGeometryPartNum(int num)
Sets the part number of current geometry.
Definition: qgssymbolv2.h:408
Abstract base class for marker symbol layers.
QgsSymbolLayerV2 * takeSymbolLayer(int index)
Remove symbol layer from the list and return pointer to it.
bool hasDefaultValues() const
Returns whether the data defined container is set to all the default values, ie, disabled, with empty expression and no assigned field.
double outputPixelSize(double size) const
double outputLineWidth(double width) const
QgsSymbolLayerV2 * symbolLayer(int layer)
Returns a specific symbol layers contained in the symbol.
QgsExpressionContextScope * popScope()
Removes the last scope from the expression context and return it.
const_iterator constEnd() const
QString dump() const
virtual void drawPreviewIcon(QgsSymbolV2RenderContext &context, QSize size)=0
const_iterator constBegin() const
static QString displayString(Type type)
Returns a display string type for a WKB type, eg the geometry name used in WKT geometry representatio...
Definition: qgswkbtypes.cpp:48
Draw map such that there are no problems between adjacent tiles.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
Definition: qgsclipper.h:181
static const QString EXPR_GEOMETRY_PART_NUM
Inbuilt variable name for geometry part number variable.
void setSize(double size)
Sets the symbol size.
int size() const
void setAngle(double angle)
Sets the rotation angle for the marker.
bool clipFeaturesToExtent() const
Returns whether features drawn by the symbol will be clipped to the render context&#39;s extent...
Definition: qgssymbolv2.h:228
QPointF offset() const
Returns the marker&#39;s offset, which is the horizontal and vertical displacement which the rendered mar...
static const QString EXPR_GEOMETRY_PART_COUNT
Inbuilt variable name for geometry part count variable.
void setOriginalValueVariable(const QVariant &value)
Sets the original value variable value for the context.
virtual void end(QgsRenderContext &context)
Ends interception of paint operations to a render context, and draws the result to the render context...
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
static QgsExpressionContextScope * updateSymbolScope(const QgsSymbolV2 *symbol, QgsExpressionContextScope *symbolScope=nullptr)
Updates a symbol scope related to a QgsSymbolV2 to an expression context.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
virtual void stopRender(QgsSymbolV2RenderContext &context)=0
void setSizeMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale for the symbol&#39;s size.
void renderVertexMarker(QPointF pt, QgsRenderContext &context, int currentVertexMarkerType, int currentVertexMarkerSize)
Render editing vertex marker at specified point.
void setExpressionString(const QString &expr)
Sets the expression for this QgsDataDefined.
void setOutputUnit(QgsSymbolV2::OutputUnit u)
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:205
iterator begin()
bool hasDataDefinedProperties() const
Returns whether the symbol utilises any data defined properties.
void setScaleMethod(QgsSymbolV2::ScaleMethod scaleMethod)
void setGeometry(const QgsAbstractGeometryV2 *geometry)
Sets pointer to original (unsegmentized) geometry.
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
virtual void begin(QgsRenderContext &context)
Begins intercepting paint operations to a render context.
virtual QgsAbstractGeometryV2 * segmentize(double tolerance=M_PI/180., SegmentationToleranceType toleranceType=MaximumAngle) const
Returns a version of the geometry without curves.
Simple marker symbol layer, consisting of a rendered shape with solid fill color and an outline...
QgsSymbolV2RenderContext * symbolRenderContext()
Returns the symbol render context.
QgsLineSymbolV2(const QgsSymbolLayerV2List &layers=QgsSymbolLayerV2List())
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
virtual QgsMarkerSymbolV2 * clone() const override
QgsPaintEffect * paintEffect() const
Returns the current paint effect for the layer.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
static QgsConstWkbPtr _getLineString(QPolygonF &pts, QgsRenderContext &context, QgsConstWkbPtr &wkb, bool clipToExtent=true)
Creates a line string in screen coordinates from a wkb string in map coordinates. ...
QColor color() const
int mRenderHints
Definition: qgssymbolv2.h:331
virtual Q_DECL_DEPRECATED void setDataDefinedProperty(const QString &property, const QString &expressionString)
Sets a data defined expression for a property.
int renderHints() const
Definition: qgssymbolv2.h:208