QGIS API Documentation  2.15.0-Master (af20121)
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"
38 #include "qgsclipper.h"
39 
40 #include <QColor>
41 #include <QImage>
42 #include <QPainter>
43 #include <QSize>
44 #include <QSvgGenerator>
45 
46 #include <cmath>
47 
48 inline
49 QgsDataDefined* rotateWholeSymbol( double additionalRotation, const QgsDataDefined& dd )
50 {
51  QgsDataDefined* rotatedDD = new QgsDataDefined( dd );
52  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
53  rotatedDD->setExpressionString( QString::number( additionalRotation ) + " + (" + exprString + ')' );
54  rotatedDD->setUseExpression( true );
55  return rotatedDD;
56 }
57 
58 inline
59 QgsDataDefined* scaleWholeSymbol( double scaleFactor, const QgsDataDefined& dd )
60 {
61  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
62  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
63  scaledDD->setExpressionString( QString::number( scaleFactor ) + "*(" + exprString + ')' );
64  scaledDD->setUseExpression( true );
65  return scaledDD;
66 }
67 
68 inline
69 QgsDataDefined* scaleWholeSymbol( double scaleFactorX, double scaleFactorY, const QgsDataDefined& dd )
70 {
71  QgsDataDefined* scaledDD = new QgsDataDefined( dd );
72  QString exprString = dd.useExpression() ? dd.expressionString() : dd.field();
73  scaledDD->setExpressionString(
74  ( !qgsDoubleNear( scaleFactorX, 0.0 ) ? "tostring(" + QString::number( scaleFactorX ) + "*(" + exprString + "))" : "'0'" ) +
75  "|| ',' || " +
76  ( !qgsDoubleNear( scaleFactorY, 0.0 ) ? "tostring(" + QString::number( scaleFactorY ) + "*(" + exprString + "))" : "'0'" ) );
77  scaledDD->setUseExpression( true );
78  return scaledDD;
79 }
80 
81 
83 
85  : mType( type )
86  , mLayers( layers )
87  , mAlpha( 1.0 )
88  , mRenderHints( 0 )
89  , mClipFeaturesToExtent( true )
90  , mLayer( nullptr )
91  , mSymbolRenderContext( nullptr )
92 {
93 
94  // check they're all correct symbol layers
95  for ( int i = 0; i < mLayers.count(); i++ )
96  {
97  if ( !mLayers.at( i ) )
98  {
99  mLayers.removeAt( i-- );
100  }
101  else if ( !mLayers.at( i )->isCompatibleWithSymbol( this ) )
102  {
103  delete mLayers.at( i );
104  mLayers.removeAt( i-- );
105  }
106  }
107 }
108 
110 {
111  QgsWKBTypes::Type type = wkbPtr.readHeader();
112  wkbPtr >> pt.rx() >> pt.ry();
113  wkbPtr += ( QgsWKBTypes::coordDimensions( type ) - 2 ) * sizeof( double );
114 
115  if ( context.coordinateTransform() )
116  {
117  double z = 0; // dummy variable for coordiante transform
118  context.coordinateTransform()->transformInPlace( pt.rx(), pt.ry(), z );
119  }
120 
121  context.mapToPixel().transformInPlace( pt.rx(), pt.ry() );
122 
123  return wkbPtr;
124 }
125 
127 {
128  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
129  unsigned int nPoints;
130  wkbPtr >> nPoints;
131 
132  const QgsCoordinateTransform* ct = context.coordinateTransform();
133  const QgsMapToPixel& mtp = context.mapToPixel();
134 
135  //apply clipping for large lines to achieve a better rendering performance
136  if ( clipToExtent && nPoints > 1 )
137  {
138  const QgsRectangle& e = context.extent();
139  double cw = e.width() / 10;
140  double ch = e.height() / 10;
141  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
142  wkbPtr -= 1 + 2 * sizeof( int );
143  wkbPtr = QgsClipper::clippedLineWKB( wkbPtr, clipRect, pts );
144  }
145  else
146  {
147  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
148  Q_ASSERT( skipZM >= 0 );
149 
150  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
151  {
152  QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
153  return QgsConstWkbPtr( nullptr, 0 );
154  }
155 
156  pts.resize( nPoints );
157 
158  QPointF *ptr = pts.data();
159  for ( unsigned int i = 0; i < nPoints; ++i, ++ptr )
160  {
161  wkbPtr >> ptr->rx() >> ptr->ry();
162  wkbPtr += skipZM;
163  }
164  }
165 
166  //transform the QPolygonF to screen coordinates
167  if ( ct )
168  {
169  ct->transformPolygon( pts );
170  }
171 
172  QPointF *ptr = pts.data();
173  for ( int i = 0; i < pts.size(); ++i, ++ptr )
174  {
175  mtp.transformInPlace( ptr->rx(), ptr->ry() );
176  }
177 
178  return wkbPtr;
179 }
180 
182 {
183  QgsWKBTypes::Type wkbType = wkbPtr.readHeader();
184  unsigned int numRings;
185  wkbPtr >> numRings;
186 
187  if ( numRings == 0 ) // sanity check for zero rings in polygon
188  return wkbPtr;
189 
190  holes.clear();
191 
192  const QgsCoordinateTransform* ct = context.coordinateTransform();
193  const QgsMapToPixel& mtp = context.mapToPixel();
194  const QgsRectangle& e = context.extent();
195  double cw = e.width() / 10;
196  double ch = e.height() / 10;
197  QgsRectangle clipRect( e.xMinimum() - cw, e.yMinimum() - ch, e.xMaximum() + cw, e.yMaximum() + ch );
198 
199  int skipZM = ( QgsWKBTypes::coordDimensions( wkbType ) - 2 ) * sizeof( double );
200  Q_ASSERT( skipZM >= 0 );
201 
202  for ( unsigned int idx = 0; idx < numRings; idx++ )
203  {
204  unsigned int nPoints;
205  wkbPtr >> nPoints;
206 
207  if ( static_cast<int>( nPoints * ( 2 * sizeof( double ) + skipZM ) ) > wkbPtr.remaining() )
208  {
209  QgsDebugMsg( QString( "%1 points exceed wkb length (%2>%3)" ).arg( nPoints ).arg( nPoints * ( 2 * sizeof( double ) + skipZM ) ).arg( wkbPtr.remaining() ) );
210  return QgsConstWkbPtr( nullptr, 0 );
211  }
212 
213  QPolygonF poly( nPoints );
214 
215  // Extract the points from the WKB and store in a pair of vectors.
216  QPointF *ptr = poly.data();
217  for ( unsigned int jdx = 0; jdx < nPoints; ++jdx, ++ptr )
218  {
219  wkbPtr >> ptr->rx() >> ptr->ry();
220  wkbPtr += skipZM;
221  }
222 
223  if ( nPoints < 1 )
224  continue;
225 
226  //clip close to view extent, if needed
227  QRectF ptsRect = poly.boundingRect();
228  if ( clipToExtent && !context.extent().contains( ptsRect ) )
229  {
230  QgsClipper::trimPolygon( poly, clipRect );
231  }
232 
233  //transform the QPolygonF to screen coordinates
234  if ( ct )
235  {
236  ct->transformPolygon( poly );
237  }
238 
239  ptr = poly.data();
240  for ( int i = 0; i < poly.size(); ++i, ++ptr )
241  {
242  mtp.transformInPlace( ptr->rx(), ptr->ry() );
243  }
244 
245  if ( idx == 0 )
246  pts = poly;
247  else
248  holes.append( poly );
249  }
250 
251  return wkbPtr;
252 }
253 
255 {
256  delete mSymbolRenderContext;
257  // delete all symbol layers (we own them, so it's okay)
258  qDeleteAll( mLayers );
259 }
260 
262 {
263  if ( mLayers.empty() )
264  {
265  return QgsSymbolV2::Mixed;
266  }
267 
269 
270  QgsSymbolV2::OutputUnit unit = ( *it )->outputUnit();
271 
272  for ( ; it != mLayers.constEnd(); ++it )
273  {
274  if (( *it )->outputUnit() != unit )
275  {
276  return QgsSymbolV2::Mixed;
277  }
278  }
279  return unit;
280 }
281 
283 {
284  if ( mLayers.empty() )
285  {
286  return QgsMapUnitScale();
287  }
288 
290  if ( it == mLayers.constEnd() )
291  return QgsMapUnitScale();
292 
293  QgsMapUnitScale scale = ( *it )->mapUnitScale();
294  ++it;
295 
296  for ( ; it != mLayers.constEnd(); ++it )
297  {
298  if (( *it )->mapUnitScale() != scale )
299  {
300  return QgsMapUnitScale();
301  }
302  }
303  return scale;
304 }
305 
307 {
308  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
309  {
310  layer->setOutputUnit( u );
311  }
312 }
313 
315 {
316  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
317  {
318  layer->setMapUnitScale( scale );
319  }
320 }
321 
323 {
324  QgsSymbolV2* s = nullptr;
325 
326  // override global default if project has a default for this type
328  switch ( geomType )
329  {
330  case QGis::Point :
331  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Marker", "" );
332  break;
333  case QGis::Line :
334  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Line", "" );
335  break;
336  case QGis::Polygon :
337  defaultSymbol = QgsProject::instance()->readEntry( "DefaultStyles", "/Fill", "" );
338  break;
339  default:
340  defaultSymbol = "";
341  break;
342  }
343  if ( defaultSymbol != "" )
344  s = QgsStyleV2::defaultStyle()->symbol( defaultSymbol );
345 
346  // if no default found for this type, get global default (as previously)
347  if ( ! s )
348  {
349  switch ( geomType )
350  {
351  case QGis::Point:
352  s = new QgsMarkerSymbolV2();
353  break;
354  case QGis::Line:
355  s = new QgsLineSymbolV2();
356  break;
357  case QGis::Polygon:
358  s = new QgsFillSymbolV2();
359  break;
360  default:
361  QgsDebugMsg( "unknown layer's geometry type" );
362  return nullptr;
363  }
364  }
365 
366  // set alpha transparency
367  s->setAlpha( QgsProject::instance()->readDoubleEntry( "DefaultStyles", "/AlphaInt", 255 ) / 255.0 );
368 
369  // set random color, it project prefs allow
370  if ( defaultSymbol == "" ||
371  QgsProject::instance()->readBoolEntry( "DefaultStyles", "/RandomColors", true ) )
372  {
373  s->setColor( QColor::fromHsv( qrand() % 360, 64 + qrand() % 192, 128 + qrand() % 128 ) );
374  }
375 
376  return s;
377 }
378 
380 {
381  return mLayers.value( layer );
382 }
383 
384 
386 {
387  // fill symbol can contain also line symbol layers for drawing of outlines
388  if ( mType == Fill && layerType == Line )
389  return true;
390 
391  return mType == layerType;
392 }
393 
394 
396 {
397  if ( index < 0 || index > mLayers.count() ) // can be added also after the last index
398  return false;
399 
400  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
401  return false;
402 
403  mLayers.insert( index, layer );
404  return true;
405 }
406 
407 
409 {
410  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
411  return false;
412 
413  mLayers.append( layer );
414  return true;
415 }
416 
417 
419 {
420  if ( index < 0 || index >= mLayers.count() )
421  return false;
422 
423  delete mLayers.at( index );
424  mLayers.removeAt( index );
425  return true;
426 }
427 
428 
430 {
431  if ( index < 0 || index >= mLayers.count() )
432  return nullptr;
433 
434  return mLayers.takeAt( index );
435 }
436 
437 
439 {
440  QgsSymbolLayerV2* oldLayer = mLayers.value( index );
441 
442  if ( oldLayer == layer )
443  return false;
444 
445  if ( !layer || !layer->isCompatibleWithSymbol( this ) )
446  return false;
447 
448  delete oldLayer; // first delete the original layer
449  mLayers[index] = layer; // set new layer
450  return true;
451 }
452 
453 
454 void QgsSymbolV2::startRender( QgsRenderContext& context, const QgsFields* fields )
455 {
456  delete mSymbolRenderContext;
457  mSymbolRenderContext = new QgsSymbolV2RenderContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, fields, mapUnitScale() );
458 
459  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, fields, mapUnitScale() );
460 
462 
463  mSymbolRenderContext->setExpressionContextScope( scope );
464 
465  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
466  layer->startRender( symbolContext );
467 }
468 
470 {
471  Q_UNUSED( context )
472  if ( mSymbolRenderContext )
473  {
474  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
475  layer->stopRender( *mSymbolRenderContext );
476  }
477 
478  delete mSymbolRenderContext;
479  mSymbolRenderContext = nullptr;
480 
481  mLayer = nullptr;
482 }
483 
485 {
486  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
487  {
488  if ( !layer->isLocked() )
489  layer->setColor( color );
490  }
491 }
492 
494 {
495  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
496  {
497  // return color of the first unlocked layer
498  if ( !( *it )->isLocked() )
499  return ( *it )->color();
500  }
501  return QColor( 0, 0, 0 );
502 }
503 
504 void QgsSymbolV2::drawPreviewIcon( QPainter* painter, QSize size, QgsRenderContext* customContext )
505 {
506  QgsRenderContext context = customContext ? *customContext : QgsSymbolLayerV2Utils::createRenderContext( painter );
507  context.setForceVectorOutput( true );
508  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, nullptr, nullptr, mapUnitScale() );
509 
510  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
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 outline
516  QgsLineSymbolLayerV2* lsl = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
517 
518  if ( lsl )
519  {
520  // from QgsFillSymbolLayerV2::drawPreviewIcon()
521  QPolygonF poly = QRectF( QPointF( 0, 0 ), QPointF( size.width() - 1, size.height() - 1 ) );
522  lsl->startRender( symbolContext );
523  lsl->renderPolygonOutline( poly, nullptr, symbolContext );
524  lsl->stopRender( symbolContext );
525  }
526  }
527  else
528  layer->drawPreviewIcon( symbolContext, size );
529  }
530 }
531 
532 void QgsSymbolV2::exportImage( const QString& path, const QString& format, QSize size )
533 {
534  if ( format.toLower() == "svg" )
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 
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 == QgsSymbolV2::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 == QgsSymbolV2::Line )
589  {
590  QPolygonF poly;
591  poly << QPointF( 0, 50 ) << QPointF( 99, 50 );
592  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( poly, nullptr, context );
593  }
594  else if ( mType == QgsSymbolV2::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<QgsFillSymbolV2*>( this )->renderPolygon( polygon, nullptr, nullptr, context );
599  }
600  else // marker
601  {
602  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( QPointF( 50, 50 ), nullptr, context );
603  }
604 
605  stopRender( context );
606  return preview;
607 }
608 
609 
611 {
612  QString t;
613  switch ( type() )
614  {
615  case QgsSymbolV2::Marker:
616  t = "MARKER";
617  break;
618  case QgsSymbolV2::Line:
619  t = "LINE";
620  break;
621  case QgsSymbolV2::Fill:
622  t = "FILL";
623  break;
624  default:
625  Q_ASSERT( 0 && "unknown symbol type" );
626  }
627  QString s = QString( "%1 SYMBOL (%2 layers) color %3" ).arg( t ).arg( mLayers.count() ).arg( QgsSymbolLayerV2Utils::encodeColor( color() ) );
628 
629  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
630  {
631  // TODO:
632  }
633  return s;
634 }
635 
636 void QgsSymbolV2::toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
637 {
638  props[ "alpha" ] = QString::number( alpha() );
639  double scaleFactor = 1.0;
640  props[ "uom" ] = QgsSymbolLayerV2Utils::encodeSldUom( outputUnit(), &scaleFactor );
641  props[ "uomScale" ] = ( !qgsDoubleNear( scaleFactor, 1.0 ) ? QString::number( scaleFactor ) : "" );
642 
643  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
644  {
645  ( *it )->toSld( doc, element, props );
646  }
647 }
648 
650 {
652  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
653  {
654  QgsSymbolLayerV2* layer = ( *it )->clone();
655  layer->setLocked(( *it )->isLocked() );
656  layer->setRenderingPass(( *it )->renderingPass() );
657  lst.append( layer );
658  }
659  return lst;
660 }
661 
663 {
664  Q_ASSERT( layer->type() == Hybrid );
665 
667 
668  QgsPaintEffect* effect = generatorLayer->paintEffect();
669  if ( effect && effect->enabled() )
670  {
671  QPainter* p = context.renderContext().painter();
672  p->save();
673 
674  effect->begin( context.renderContext() );
675  generatorLayer->render( context );
676  effect->end( context.renderContext() );
677 
678  p->restore();
679  }
680  else
681  {
682  generatorLayer->render( context );
683  }
684 }
685 
687 {
688  QSet<QString> attributes;
690  for ( ; sIt != mLayers.constEnd(); ++sIt )
691  {
692  if ( *sIt )
693  {
694  attributes.unite(( *sIt )->usedAttributes() );
695  }
696  }
697  return attributes;
698 }
699 
701 {
702  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
703  {
704  if ( layer->hasDataDefinedProperties() )
705  return true;
706  }
707  return false;
708 }
709 
710 void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker, int currentVertexMarkerType, int currentVertexMarkerSize )
711 {
712  const QgsGeometry* geom = feature.constGeometry();
713  if ( !geom || !geom->geometry() )
714  {
715  return;
716  }
717 
718  const QgsGeometry *segmentizedGeometry = geom;
719  bool deleteSegmentizedGeometry = false;
720  context.setGeometry( geom->geometry() );
721 
722  bool tileMapRendering = context.testFlag( QgsRenderContext::RenderMapTile );
723 
724  //convert curve types to normal point/line/polygon ones
725  if ( QgsWKBTypes::isCurvedType( geom->geometry()->wkbType() ) )
726  {
728  if ( !g )
729  {
730  return;
731  }
732  segmentizedGeometry = new QgsGeometry( g );
733  deleteSegmentizedGeometry = true;
734  }
735 
736  mSymbolRenderContext->setGeometryPartCount( segmentizedGeometry->geometry()->partCount() );
737  mSymbolRenderContext->setGeometryPartNum( 1 );
738 
739  if ( mSymbolRenderContext->expressionContextScope() )
740  {
741  context.expressionContext().appendScope( mSymbolRenderContext->expressionContextScope() );
743  mSymbolRenderContext->expressionContextScope()->setVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_COUNT, mSymbolRenderContext->geometryPartCount() );
745  }
746 
747  switch ( QgsWKBTypes::flatType( segmentizedGeometry->geometry()->wkbType() ) )
748  {
749  case QgsWKBTypes::Point:
750  {
751  QPointF pt;
752  if ( mType != QgsSymbolV2::Marker )
753  {
754  QgsDebugMsg( "point can be drawn only with marker symbol!" );
755  break;
756  }
757 
758  const QgsPointV2* point = static_cast< const QgsPointV2* >( segmentizedGeometry->geometry() );
759  _getPoint( pt, context, point );
760  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( pt, &feature, context, layer, selected );
761 
763  {
764  //draw debugging rect
765  context.painter()->setPen( Qt::red );
766  context.painter()->setBrush( QColor( 255, 0, 0, 100 ) );
767  context.painter()->drawRect( static_cast<QgsMarkerSymbolV2*>( this )->bounds( pt, context, feature ) );
768  }
769  }
770  break;
772  {
773  QPolygonF pts;
774  if ( mType != QgsSymbolV2::Line )
775  {
776  QgsDebugMsg( "linestring can be drawn only with line symbol!" );
777  break;
778  }
779  _getLineString( pts, context, QgsConstWkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() ), !tileMapRendering && clipFeaturesToExtent() );
780  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
781  }
782  break;
784  {
785  QPolygonF pts;
786  QList<QPolygonF> holes;
787  if ( mType != QgsSymbolV2::Fill )
788  {
789  QgsDebugMsg( "polygon can be drawn only with fill symbol!" );
790  break;
791  }
792  _getPolygon( pts, holes, context, QgsConstWkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() ), !tileMapRendering && clipFeaturesToExtent() );
793  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
794  }
795  break;
796 
798  {
799  QPointF pt;
800 
801  if ( mType != QgsSymbolV2::Marker )
802  {
803  QgsDebugMsg( "multi-point can be drawn only with marker symbol!" );
804  break;
805  }
806 
807  QgsMultiPointV2* mp = static_cast< QgsMultiPointV2* >( segmentizedGeometry->geometry() );
808 
809  for ( int i = 0; i < mp->numGeometries(); ++i )
810  {
811  mSymbolRenderContext->setGeometryPartNum( i + 1 );
813 
814  const QgsPointV2* point = static_cast< const QgsPointV2* >( mp->geometryN( i ) );
815  _getPoint( pt, context, point );
816  static_cast<QgsMarkerSymbolV2*>( this )->renderPoint( pt, &feature, context, layer, selected );
817  }
818  }
819  break;
820 
823  {
824  QPolygonF pts;
825 
826  if ( mType != QgsSymbolV2::Line )
827  {
828  QgsDebugMsg( "multi-linestring can be drawn only with line symbol!" );
829  break;
830  }
831 
832  QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() );
833  wkbPtr.readHeader();
834 
835  unsigned int num;
836  wkbPtr >> num;
837 
838  const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
839 
840  for ( unsigned int i = 0; i < num && wkbPtr; ++i )
841  {
842  mSymbolRenderContext->setGeometryPartNum( i + 1 );
844 
845  if ( geomCollection )
846  {
847  context.setGeometry( geomCollection->geometryN( i ) );
848  }
849  wkbPtr = _getLineString( pts, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() );
850  static_cast<QgsLineSymbolV2*>( this )->renderPolyline( pts, &feature, context, layer, selected );
851  }
852  }
853  break;
854 
857  {
858  if ( mType != QgsSymbolV2::Fill )
859  {
860  QgsDebugMsg( "multi-polygon can be drawn only with fill symbol!" );
861  break;
862  }
863 
864  QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() );
865  wkbPtr.readHeader();
866 
867  unsigned int num;
868  wkbPtr >> num;
869 
870  QPolygonF pts;
871  QList<QPolygonF> holes;
872 
873  const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );
874 
875  for ( unsigned int i = 0; i < num && wkbPtr; ++i )
876  {
877  mSymbolRenderContext->setGeometryPartNum( i + 1 );
879 
880  if ( geomCollection )
881  {
882  context.setGeometry( geomCollection->geometryN( i ) );
883  }
884 
885  wkbPtr = _getPolygon( pts, holes, context, wkbPtr, !tileMapRendering && clipFeaturesToExtent() );
886  static_cast<QgsFillSymbolV2*>( this )->renderPolygon( pts, ( !holes.isEmpty() ? &holes : nullptr ), &feature, context, layer, selected );
887  }
888  break;
889  }
891  {
892  QgsConstWkbPtr wkbPtr( segmentizedGeometry->asWkb(), segmentizedGeometry->wkbSize() );
893  wkbPtr.readHeader();
894 
895  int nGeometries;
896  wkbPtr >> nGeometries;
897 
898  if ( nGeometries == 0 )
899  {
900  // skip noise from empty geometry collections from simplification
901  break;
902  }
903 
904  FALLTHROUGH;
905  }
906  default:
907  QgsDebugMsg( QString( "feature %1: unsupported wkb type %2/%3 for rendering" )
908  .arg( feature.id() )
909  .arg( QgsWKBTypes::displayString( geom->geometry()->wkbType() ) )
910  .arg( geom->wkbType(), 0, 16 ) );
911  }
912 
913  if ( drawVertexMarker )
914  {
915  const QgsCoordinateTransform* ct = context.coordinateTransform();
916  const QgsMapToPixel& mtp = context.mapToPixel();
917 
918  QgsPointV2 vertexPoint;
919  QgsVertexId vertexId;
920  double x, y, z;
921  QPointF mapPoint;
922  while ( geom->geometry()->nextVertex( vertexId, vertexPoint ) )
923  {
924  //transform
925  x = vertexPoint.x();
926  y = vertexPoint.y();
927  z = vertexPoint.z();
928  if ( ct )
929  {
930  ct->transformInPlace( x, y, z );
931  }
932  mapPoint.setX( x );
933  mapPoint.setY( y );
934  mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
935  renderVertexMarker( mapPoint, context, currentVertexMarkerType, currentVertexMarkerSize );
936  }
937  }
938 
939  if ( deleteSegmentizedGeometry )
940  {
941  delete segmentizedGeometry;
942  }
943 
944  if ( mSymbolRenderContext->expressionContextScope() )
945  context.expressionContext().popScope();
946 }
947 
949 {
950  return mSymbolRenderContext;
951 }
952 
953 void QgsSymbolV2::renderVertexMarker( QPointF pt, QgsRenderContext& context, int currentVertexMarkerType, int currentVertexMarkerSize )
954 {
955  QgsVectorLayer::drawVertexMarker( pt.x(), pt.y(), *context.painter(), static_cast< QgsVectorLayer::VertexMarkerType >( currentVertexMarkerType ), currentVertexMarkerSize );
956 }
957 
959 
960 
962  : mRenderContext( c )
963  , mExpressionContextScope( nullptr )
964  , mOutputUnit( u )
965  , mMapUnitScale( mapUnitScale )
966  , mAlpha( alpha )
967  , mSelected( selected )
968  , mRenderHints( renderHints )
969  , mFeature( f )
970  , mFields( fields )
971  , mGeometryPartCount( 0 )
972  , mGeometryPartNum( 0 )
973 {
974 }
975 
977 {
978  delete mExpressionContextScope;
979 }
980 
982 {
983  mRenderContext.expressionContext().setOriginalValueVariable( value );
984 }
985 
986 double QgsSymbolV2RenderContext::outputLineWidth( double width ) const
987 {
988  return QgsSymbolLayerV2Utils::convertToPainterUnits( mRenderContext, width, mOutputUnit, mMapUnitScale );
989 }
990 
991 double QgsSymbolV2RenderContext::outputPixelSize( double size ) const
992 {
993  return size * QgsSymbolLayerV2Utils::pixelSizeScaleFactor( mRenderContext, mOutputUnit, mMapUnitScale );
994 }
995 
997 {
998  // This is just a dummy implementation of assignment.
999  // sip 4.7 generates a piece of code that needs this function to exist.
1000  // It's not generated automatically by the compiler because of
1001  // mRenderContext member which is a reference (and thus can't be changed).
1002  Q_ASSERT( false );
1003  return *this;
1004 }
1005 
1007 {
1008  return mExpressionContextScope;
1009 }
1010 
1012 {
1013  mExpressionContextScope = contextScope;
1014 }
1015 
1017 
1019 {
1021  if ( !sl )
1022  return nullptr;
1023 
1024  QgsSymbolLayerV2List layers;
1025  layers.append( sl );
1026  return new QgsMarkerSymbolV2( layers );
1027 }
1028 
1030 {
1032  if ( !sl )
1033  return nullptr;
1034 
1035  QgsSymbolLayerV2List layers;
1036  layers.append( sl );
1037  return new QgsLineSymbolV2( layers );
1038 }
1039 
1041 {
1043  if ( !sl )
1044  return nullptr;
1045 
1046  QgsSymbolLayerV2List layers;
1047  layers.append( sl );
1048  return new QgsFillSymbolV2( layers );
1049 }
1050 
1052 
1054  : QgsSymbolV2( Marker, layers )
1055 {
1056  if ( mLayers.isEmpty() )
1058 }
1059 
1061 {
1062  double origAngle = angle();
1063  double angleDiff = ang - origAngle;
1064  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1065  {
1066  QgsMarkerSymbolLayerV2* markerLayer = dynamic_cast<QgsMarkerSymbolLayerV2*>( layer );
1067  if ( markerLayer )
1068  markerLayer->setAngle( markerLayer->angle() + angleDiff );
1069  }
1070 }
1071 
1073 {
1074  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1075  {
1076  if ( layer->type() != QgsSymbolV2::Marker )
1077  continue;
1078  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1079  return markerLayer->angle();
1080  }
1081  return 0;
1082 }
1083 
1084 void QgsMarkerSymbolV2::setLineAngle( double lineAng )
1085 {
1086  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1087  {
1088  if ( layer->type() != QgsSymbolV2::Marker )
1089  continue;
1090  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1091  markerLayer->setLineAngle( lineAng );
1092  }
1093 }
1094 
1096 {
1097  const double symbolRotation = angle();
1098 
1099  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1100  {
1101  if ( layer->type() != QgsSymbolV2::Marker )
1102  continue;
1103  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1104  if ( dd.hasDefaultValues() )
1105  {
1106  layer->removeDataDefinedProperty( "angle" );
1107  }
1108  else
1109  {
1110  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1111  {
1112  layer->setDataDefinedProperty( "angle", new QgsDataDefined( dd ) );
1113  }
1114  else
1115  {
1116  QgsDataDefined* rotatedDD = rotateWholeSymbol( markerLayer->angle() - symbolRotation, dd );
1117  layer->setDataDefinedProperty( "angle", rotatedDD );
1118  }
1119  }
1120  }
1121 }
1122 
1124 {
1125  const double symbolRotation = angle();
1126  QgsDataDefined* symbolDD = nullptr;
1127 
1128  // find the base of the "en masse" pattern
1129  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1130  {
1131  if ( layer->type() != QgsSymbolV2::Marker )
1132  continue;
1133  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1134  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) && markerLayer->getDataDefinedProperty( "angle" ) )
1135  {
1136  symbolDD = markerLayer->getDataDefinedProperty( "angle" );
1137  break;
1138  }
1139  }
1140 
1141  if ( !symbolDD )
1142  return QgsDataDefined();
1143 
1144  // check that all layer's angle expressions match the "en masse" pattern
1145  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1146  {
1147  if ( layer->type() != QgsSymbolV2::Marker )
1148  continue;
1149  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1150  QgsDataDefined* layerAngleDD = markerLayer->getDataDefinedProperty( "angle" );
1151 
1152  if ( qgsDoubleNear( markerLayer->angle(), symbolRotation ) )
1153  {
1154  if ( !layerAngleDD || *layerAngleDD != *symbolDD )
1155  return QgsDataDefined();
1156  }
1157  else
1158  {
1159  QScopedPointer< QgsDataDefined > rotatedDD( rotateWholeSymbol( markerLayer->angle() - symbolRotation, *symbolDD ) );
1160  if ( !layerAngleDD || *layerAngleDD != *( rotatedDD.data() ) )
1161  return QgsDataDefined();
1162  }
1163  }
1164  return QgsDataDefined( *symbolDD );
1165 }
1166 
1167 
1169 {
1170  double origSize = size();
1171 
1172  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1173  {
1174  if ( layer->type() != QgsSymbolV2::Marker )
1175  continue;
1176  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1177  if ( qgsDoubleNear( markerLayer->size(), origSize ) )
1178  markerLayer->setSize( s );
1179  else if ( !qgsDoubleNear( origSize, 0.0 ) )
1180  {
1181  // proportionally scale size
1182  markerLayer->setSize( markerLayer->size() * s / origSize );
1183  }
1184  // also scale offset to maintain relative position
1185  if ( !qgsDoubleNear( origSize, 0.0 ) && ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) ) )
1186  markerLayer->setOffset( QPointF( markerLayer->offset().x() * s / origSize,
1187  markerLayer->offset().y() * s / origSize ) );
1188  }
1189 }
1190 
1192 {
1193  // return size of the largest symbol
1194  double maxSize = 0;
1195  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1196  {
1197  if ( layer->type() != QgsSymbolV2::Marker )
1198  continue;
1199  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1200  double lsize = markerLayer->size();
1201  if ( lsize > maxSize )
1202  maxSize = lsize;
1203  }
1204  return maxSize;
1205 }
1206 
1208 {
1209  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1210  {
1211  if ( layer->type() != QgsSymbolV2::Marker )
1212  continue;
1213 
1214  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1215  markerLayer->setSizeUnit( unit );
1216  }
1217 }
1218 
1220 {
1221  bool first = true;
1222  OutputUnit unit = Mixed;
1223 
1224  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1225  {
1226  if ( layer->type() != QgsSymbolV2::Marker )
1227  continue;
1228  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1229 
1230  if ( first )
1231  unit = markerLayer->sizeUnit();
1232  else
1233  {
1234  if ( unit != markerLayer->sizeUnit() )
1235  return Mixed;
1236  }
1237 
1238  first = false;
1239  }
1240  return unit;
1241 }
1242 
1244 {
1245  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1246  {
1247  if ( layer->type() != QgsSymbolV2::Marker )
1248  continue;
1249 
1250  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1251  markerLayer->setSizeMapUnitScale( scale );
1252  }
1253 }
1254 
1256 {
1257  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1258  {
1259  if ( layer->type() != QgsSymbolV2::Marker )
1260  continue;
1261 
1262  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1263  return markerLayer->sizeMapUnitScale();
1264  }
1265  return QgsMapUnitScale();
1266 }
1267 
1269 {
1270  const double symbolSize = size();
1271 
1272  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1273  {
1274  if ( layer->type() != QgsSymbolV2::Marker )
1275  continue;
1276  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1277 
1278  if ( dd.hasDefaultValues() )
1279  {
1280  markerLayer->removeDataDefinedProperty( "size" );
1281  markerLayer->removeDataDefinedProperty( "offset" );
1282  }
1283  else
1284  {
1285  if ( qgsDoubleNear( symbolSize, 0.0 ) || qgsDoubleNear( markerLayer->size(), symbolSize ) )
1286  {
1287  markerLayer->setDataDefinedProperty( "size", new QgsDataDefined( dd ) );
1288  }
1289  else
1290  {
1291  markerLayer->setDataDefinedProperty( "size", scaleWholeSymbol( markerLayer->size() / symbolSize, dd ) );
1292  }
1293 
1294  if ( !qgsDoubleNear( markerLayer->offset().x(), 0.0 ) || !qgsDoubleNear( markerLayer->offset().y(), 0.0 ) )
1295  {
1296  markerLayer->setDataDefinedProperty( "offset", scaleWholeSymbol(
1297  markerLayer->offset().x() / symbolSize,
1298  markerLayer->offset().y() / symbolSize, dd ) );
1299  }
1300  }
1301  }
1302 }
1303 
1305 {
1306  const double symbolSize = size();
1307 
1308  QgsDataDefined* symbolDD = nullptr;
1309 
1310  // find the base of the "en masse" pattern
1311  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1312  {
1313  if ( layer->type() != QgsSymbolV2::Marker )
1314  continue;
1315  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1316  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) && markerLayer->getDataDefinedProperty( "size" ) )
1317  {
1318  symbolDD = markerLayer->getDataDefinedProperty( "size" );
1319  break;
1320  }
1321  }
1322 
1323  if ( !symbolDD )
1324  return QgsDataDefined();
1325 
1326  // check that all layers size expressions match the "en masse" pattern
1327  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1328  {
1329  if ( layer->type() != QgsSymbolV2::Marker )
1330  continue;
1331  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1332 
1333  QgsDataDefined* layerSizeDD = markerLayer->getDataDefinedProperty( "size" );
1334  QgsDataDefined* layerOffsetDD = markerLayer->getDataDefinedProperty( "offset" );
1335 
1336  if ( qgsDoubleNear( markerLayer->size(), symbolSize ) )
1337  {
1338  if ( !layerSizeDD || *layerSizeDD != *symbolDD )
1339  return QgsDataDefined();
1340  }
1341  else
1342  {
1343  if ( qgsDoubleNear( symbolSize, 0.0 ) )
1344  return QgsDataDefined();
1345 
1346  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( markerLayer->size() / symbolSize, *symbolDD ) );
1347  if ( !layerSizeDD || *layerSizeDD != *( scaledDD.data() ) )
1348  return QgsDataDefined();
1349  }
1350 
1351  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( markerLayer->offset().x() / symbolSize, markerLayer->offset().y() / symbolSize, *symbolDD ) );
1352  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
1353  return QgsDataDefined();
1354  }
1355 
1356  return QgsDataDefined( *symbolDD );
1357 }
1358 
1360 {
1361  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1362  {
1363  if ( layer->type() != QgsSymbolV2::Marker )
1364  continue;
1365  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( layer );
1366  markerLayer->setScaleMethod( scaleMethod );
1367  }
1368 }
1369 
1371 {
1372  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1373  {
1374  if ( layer->type() != QgsSymbolV2::Marker )
1375  continue;
1376  const QgsMarkerSymbolLayerV2* markerLayer = static_cast<const QgsMarkerSymbolLayerV2*>( layer );
1377  // return scale method of the first symbol layer
1378  return markerLayer->scaleMethod();
1379  }
1380 
1381  return DEFAULT_SCALE_METHOD;
1382 }
1383 
1384 void QgsMarkerSymbolV2::renderPointUsingLayer( QgsMarkerSymbolLayerV2* layer, QPointF point, QgsSymbolV2RenderContext& context )
1385 {
1386  static QPointF nullPoint( 0, 0 );
1387 
1388  QgsPaintEffect* effect = layer->paintEffect();
1389  if ( effect && effect->enabled() )
1390  {
1391  QPainter* p = context.renderContext().painter();
1392  p->save();
1393  p->translate( point );
1394 
1395  effect->begin( context.renderContext() );
1396  layer->renderPoint( nullPoint, context );
1397  effect->end( context.renderContext() );
1398 
1399  p->restore();
1400  }
1401  else
1402  {
1403  layer->renderPoint( point, context );
1404  }
1405 }
1406 
1407 void QgsMarkerSymbolV2::renderPoint( QPointF point, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1408 {
1409  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1410  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1411  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1412 
1413  if ( layerIdx != -1 )
1414  {
1415  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1416  if ( symbolLayer )
1417  {
1418  if ( symbolLayer->type() == QgsSymbolV2::Marker )
1419  {
1420  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( symbolLayer );
1421  renderPointUsingLayer( markerLayer, point, symbolContext );
1422  }
1423  else
1424  renderUsingLayer( symbolLayer, symbolContext );
1425  }
1426  return;
1427  }
1428 
1429  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1430  {
1431  if ( symbolLayer->type() == QgsSymbolV2::Marker )
1432  {
1433  QgsMarkerSymbolLayerV2* markerLayer = static_cast<QgsMarkerSymbolLayerV2*>( symbolLayer );
1434  renderPointUsingLayer( markerLayer, point, symbolContext );
1435  }
1436  else
1437  renderUsingLayer( symbolLayer, symbolContext );
1438  }
1439 }
1440 
1441 QRectF QgsMarkerSymbolV2::bounds( QPointF point, QgsRenderContext& context, const QgsFeature& feature ) const
1442 {
1443  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, false, mRenderHints, &feature, feature.fields(), mapUnitScale() );
1444 
1445  QRectF bound;
1446  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1447  {
1448  if ( layer->type() == QgsSymbolV2::Marker )
1449  {
1451  if ( bound.isNull() )
1452  bound = symbolLayer->bounds( point, symbolContext );
1453  else
1454  bound = bound.united( symbolLayer->bounds( point, symbolContext ) );
1455  }
1456  }
1457  return bound;
1458 }
1459 
1461 {
1462  QgsMarkerSymbolV2* cloneSymbol = new QgsMarkerSymbolV2( cloneLayers() );
1463  cloneSymbol->setAlpha( mAlpha );
1464  cloneSymbol->setLayer( mLayer );
1466  return cloneSymbol;
1467 }
1468 
1469 
1471 // LINE
1472 
1474  : QgsSymbolV2( Line, layers )
1475 {
1476  if ( mLayers.isEmpty() )
1478 }
1479 
1481 {
1482  double origWidth = width();
1483 
1484  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1485  {
1486  QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
1487 
1488  if ( lineLayer )
1489  {
1490  if ( qgsDoubleNear( lineLayer->width(), origWidth ) )
1491  {
1492  lineLayer->setWidth( w );
1493  }
1494  else if ( !qgsDoubleNear( origWidth, 0.0 ) )
1495  {
1496  // proportionally scale the width
1497  lineLayer->setWidth( lineLayer->width() * w / origWidth );
1498  }
1499  // also scale offset to maintain relative position
1500  if ( !qgsDoubleNear( origWidth, 0.0 ) && !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1501  lineLayer->setOffset( lineLayer->offset() * w / origWidth );
1502  }
1503  }
1504 }
1505 
1507 {
1508  double maxWidth = 0;
1509  if ( mLayers.isEmpty() )
1510  return maxWidth;
1511 
1512  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1513  {
1514  const QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1515  if ( lineLayer )
1516  {
1517  double width = lineLayer->width();
1518  if ( width > maxWidth )
1519  maxWidth = width;
1520  }
1521  }
1522  return maxWidth;
1523 }
1524 
1526 {
1527  const double symbolWidth = width();
1528 
1529  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1530  {
1531  QgsLineSymbolLayerV2* lineLayer = dynamic_cast<QgsLineSymbolLayerV2*>( layer );
1532 
1533  if ( lineLayer )
1534  {
1535  if ( dd.hasDefaultValues() )
1536  {
1537  lineLayer->removeDataDefinedProperty( "width" );
1538  lineLayer->removeDataDefinedProperty( "offset" );
1539  }
1540  else
1541  {
1542  if ( qgsDoubleNear( symbolWidth, 0.0 ) || qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1543  {
1544  lineLayer->setDataDefinedProperty( "width", new QgsDataDefined( dd ) );
1545  }
1546  else
1547  {
1548  lineLayer->setDataDefinedProperty( "width", scaleWholeSymbol( lineLayer->width() / symbolWidth, dd ) );
1549  }
1550 
1551  if ( !qgsDoubleNear( lineLayer->offset(), 0.0 ) )
1552  {
1553  lineLayer->setDataDefinedProperty( "offset", scaleWholeSymbol( lineLayer->offset() / symbolWidth, dd ) );
1554  }
1555  }
1556  }
1557  }
1558 }
1559 
1561 {
1562  const double symbolWidth = width();
1563 
1564  QgsDataDefined* symbolDD = nullptr;
1565 
1566  // find the base of the "en masse" pattern
1567  for ( QgsSymbolLayerV2List::const_iterator it = mLayers.begin(); it != mLayers.end(); ++it )
1568  {
1569  const QgsLineSymbolLayerV2* layer = dynamic_cast<const QgsLineSymbolLayerV2*>( *it );
1570  if ( layer && qgsDoubleNear( layer->width(), symbolWidth ) && layer->getDataDefinedProperty( "width" ) )
1571  {
1572  symbolDD = layer->getDataDefinedProperty( "width" );
1573  break;
1574  }
1575  }
1576 
1577  if ( !symbolDD )
1578  return QgsDataDefined();
1579 
1580  // check that all layers width expressions match the "en masse" pattern
1581  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1582  {
1583  if ( layer->type() != QgsSymbolV2::Line )
1584  continue;
1585  const QgsLineSymbolLayerV2* lineLayer = static_cast<const QgsLineSymbolLayerV2*>( layer );
1586 
1587  QgsDataDefined* layerWidthDD = lineLayer->getDataDefinedProperty( "width" );
1588  QgsDataDefined* layerOffsetDD = lineLayer->getDataDefinedProperty( "offset" );
1589 
1590  if ( qgsDoubleNear( lineLayer->width(), symbolWidth ) )
1591  {
1592  if ( !layerWidthDD || *layerWidthDD != *symbolDD )
1593  return QgsDataDefined();
1594  }
1595  else
1596  {
1597  if ( qgsDoubleNear( symbolWidth, 0.0 ) )
1598  return QgsDataDefined();
1599 
1600  QScopedPointer< QgsDataDefined > scaledDD( scaleWholeSymbol( lineLayer->width() / symbolWidth, *symbolDD ) );
1601  if ( !layerWidthDD || *layerWidthDD != *( scaledDD.data() ) )
1602  return QgsDataDefined();
1603  }
1604 
1605  QScopedPointer< QgsDataDefined > scaledOffsetDD( scaleWholeSymbol( lineLayer->offset() / symbolWidth, *symbolDD ) );
1606  if ( layerOffsetDD && *layerOffsetDD != *( scaledOffsetDD.data() ) )
1607  return QgsDataDefined();
1608  }
1609 
1610  return QgsDataDefined( *symbolDD );
1611 }
1612 
1613 void QgsLineSymbolV2::renderPolyline( const QPolygonF& points, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1614 {
1615  //save old painter
1616  QPainter* renderPainter = context.painter();
1617  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1618  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1619  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1620 
1621  if ( layerIdx != -1 )
1622  {
1623  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1624  if ( symbolLayer )
1625  {
1626  if ( symbolLayer->type() == QgsSymbolV2::Line )
1627  {
1628  QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1629  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1630  }
1631  else
1632  renderUsingLayer( symbolLayer, symbolContext );
1633  }
1634  return;
1635  }
1636 
1637  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1638  {
1639  if ( symbolLayer->type() == QgsSymbolV2::Line )
1640  {
1641  QgsLineSymbolLayerV2* lineLayer = static_cast<QgsLineSymbolLayerV2*>( symbolLayer );
1642  renderPolylineUsingLayer( lineLayer, points, symbolContext );
1643  }
1644  else
1645  {
1646  renderUsingLayer( symbolLayer, symbolContext );
1647  }
1648  }
1649 
1650  context.setPainter( renderPainter );
1651 }
1652 
1653 void QgsLineSymbolV2::renderPolylineUsingLayer( QgsLineSymbolLayerV2 *layer, const QPolygonF &points, QgsSymbolV2RenderContext &context )
1654 {
1655  QgsPaintEffect* effect = layer->paintEffect();
1656  if ( effect && effect->enabled() )
1657  {
1658  QPainter* p = context.renderContext().painter();
1659  p->save();
1660  p->translate( points.boundingRect().topLeft() );
1661 
1662  effect->begin( context.renderContext() );
1663  layer->renderPolyline( points.translated( -points.boundingRect().topLeft() ), context );
1664  effect->end( context.renderContext() );
1665 
1666  p->restore();
1667  }
1668  else
1669  {
1670  layer->renderPolyline( points, context );
1671  }
1672 }
1673 
1674 
1676 {
1677  QgsLineSymbolV2* cloneSymbol = new QgsLineSymbolV2( cloneLayers() );
1678  cloneSymbol->setAlpha( mAlpha );
1679  cloneSymbol->setLayer( mLayer );
1681  return cloneSymbol;
1682 }
1683 
1685 // FILL
1686 
1688  : QgsSymbolV2( Fill, layers )
1689 {
1690  if ( mLayers.isEmpty() )
1692 }
1693 
1694 void QgsFillSymbolV2::renderPolygon( const QPolygonF& points, QList<QPolygonF>* rings, const QgsFeature* f, QgsRenderContext& context, int layerIdx, bool selected )
1695 {
1696  QgsSymbolV2RenderContext symbolContext( context, outputUnit(), mAlpha, selected, mRenderHints, f, nullptr, mapUnitScale() );
1697  symbolContext.setGeometryPartCount( symbolRenderContext()->geometryPartCount() );
1698  symbolContext.setGeometryPartNum( symbolRenderContext()->geometryPartNum() );
1699 
1700  if ( layerIdx != -1 )
1701  {
1702  QgsSymbolLayerV2* symbolLayer = mLayers.value( layerIdx );
1703  if ( symbolLayer )
1704  {
1705  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1706  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1707  else
1708  renderUsingLayer( symbolLayer, symbolContext );
1709  }
1710  return;
1711  }
1712 
1713  Q_FOREACH ( QgsSymbolLayerV2* symbolLayer, mLayers )
1714  {
1715  if ( symbolLayer->type() == Fill || symbolLayer->type() == Line )
1716  renderPolygonUsingLayer( symbolLayer, points, rings, symbolContext );
1717  else
1718  renderUsingLayer( symbolLayer, symbolContext );
1719  }
1720 }
1721 
1722 void QgsFillSymbolV2::renderPolygonUsingLayer( QgsSymbolLayerV2* layer, const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
1723 {
1724  QgsSymbolV2::SymbolType layertype = layer->type();
1725 
1726  QgsPaintEffect* effect = layer->paintEffect();
1727  if ( effect && effect->enabled() )
1728  {
1729  QRectF bounds = polygonBounds( points, rings );
1730  QList<QPolygonF>* translatedRings = translateRings( rings, -bounds.left(), -bounds.top() );
1731 
1732  QPainter* p = context.renderContext().painter();
1733  p->save();
1734  p->translate( bounds.topLeft() );
1735 
1736  effect->begin( context.renderContext() );
1737  if ( layertype == QgsSymbolV2::Fill )
1738  {
1739  ( static_cast<QgsFillSymbolLayerV2*>( layer ) )->renderPolygon( points.translated( -bounds.topLeft() ), translatedRings, context );
1740  }
1741  else if ( layertype == QgsSymbolV2::Line )
1742  {
1743  ( static_cast<QgsLineSymbolLayerV2*>( layer ) )->renderPolygonOutline( points.translated( -bounds.topLeft() ), translatedRings, context );
1744  }
1745  delete translatedRings;
1746 
1747  effect->end( context.renderContext() );
1748  p->restore();
1749  }
1750  else
1751  {
1752  if ( layertype == QgsSymbolV2::Fill )
1753  {
1754  ( static_cast<QgsFillSymbolLayerV2*>( layer ) )->renderPolygon( points, rings, context );
1755  }
1756  else if ( layertype == QgsSymbolV2::Line )
1757  {
1758  ( static_cast<QgsLineSymbolLayerV2*>( layer ) )->renderPolygonOutline( points, rings, context );
1759  }
1760  }
1761 }
1762 
1763 QRectF QgsFillSymbolV2::polygonBounds( const QPolygonF& points, const QList<QPolygonF>* rings ) const
1764 {
1765  QRectF bounds = points.boundingRect();
1766  if ( rings )
1767  {
1769  for ( ; it != rings->constEnd(); ++it )
1770  {
1771  bounds = bounds.united(( *it ).boundingRect() );
1772  }
1773  }
1774  return bounds;
1775 }
1776 
1777 QList<QPolygonF>* QgsFillSymbolV2::translateRings( const QList<QPolygonF>* rings, double dx, double dy ) const
1778 {
1779  if ( !rings )
1780  return nullptr;
1781 
1782  QList<QPolygonF>* translatedRings = new QList<QPolygonF>;
1784  for ( ; it != rings->constEnd(); ++it )
1785  {
1786  translatedRings->append(( *it ).translated( dx, dy ) );
1787  }
1788  return translatedRings;
1789 }
1790 
1792 {
1793  QgsFillSymbolV2* cloneSymbol = new QgsFillSymbolV2( cloneLayers() );
1794  cloneSymbol->setAlpha( mAlpha );
1795  cloneSymbol->setLayer( mLayer );
1797  return cloneSymbol;
1798 }
1799 
1801 {
1802  Q_FOREACH ( QgsSymbolLayerV2* layer, mLayers )
1803  {
1804  if ( layer->type() != QgsSymbolV2::Fill )
1805  continue;
1806 
1807  QgsFillSymbolLayerV2* fillLayer = static_cast<QgsFillSymbolLayerV2*>( layer );
1808 
1809  if ( fillLayer )
1810  fillLayer->setAngle( angle );
1811  }
1812 }
1813 
1814 
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:562
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:215
OutputUnit
The unit of the output.
Definition: qgssymbolv2.h:62
virtual void setOutputUnit(QgsSymbolV2::OutputUnit unit)
int width() const
bool mClipFeaturesToExtent
Definition: qgssymbolv2.h:329
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:393
virtual QgsLineSymbolV2 * clone() const override
int remaining() const
Definition: qgswkbptr.h:121
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 setRenderHint(RenderHint hint, bool on)
const QgsVectorLayer * mLayer
Definition: qgssymbolv2.h:331
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:104
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.
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:261
Abstract base class for all geometries.
QgsMapUnitScale mapUnitScale() const
Container of fields for a vector layer.
Definition: qgsfield.h:193
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
qreal top() const
Line symbol.
Definition: qgssymbolv2.h:79
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:322
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:352
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:59
Marker symbol.
Definition: qgssymbolv2.h:78
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)
void setAngle(double angle)
const QgsVectorLayer * layer() const
Definition: qgssymbolv2.h:241
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:37
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:66
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:323
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:528
void resize(int size)
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.
double z() const
Returns the point&#39;s z-coordinate.
Definition: qgspointv2.h:80
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
Definition: qgssymbolv2.h:200
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:520
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:240
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
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:326
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:84
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:49
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()
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:76
void restore()
void setDataDefinedWidth(const QgsDataDefined &dd)
Set data defined width for whole symbol (including all symbol layers).
Hybrid symbol.
Definition: qgssymbolv2.h:81
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)
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. ...
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:87
Struct for storing maximum and minimum scales for measurements in map units.
bool isLocked() const
void insert(int i, const T &value)
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.
QImage asImage(QSize size, QgsRenderContext *customContext=nullptr)
Generate symbol as image.
double offset() const
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:349
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()
access to canonical QgsProject instance
Definition: qgsproject.cpp:388
int height() const
Fill symbol.
Definition: qgssymbolv2.h:80
QgsSymbolV2::OutputUnit outputUnit() const
int geometryPartCount() const
Part count of current geometry.
Definition: qgssymbolv2.h:389
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
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:402
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:225
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:202
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
QColor color() const
int mRenderHints
Definition: qgssymbolv2.h:328
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:205