QGIS API Documentation  2.12.0-Lyon
qgspointdisplacementrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointdisplacementrenderer.cpp
3  --------------------------------
4  begin : January 26, 2010
5  copyright : (C) 2010 by Marco Hugentobler
6  email : marco at hugis dot net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsgeometry.h"
20 #include "qgslogger.h"
21 #include "qgsspatialindex.h"
22 #include "qgssymbolv2.h"
23 #include "qgssymbollayerv2utils.h"
24 #include "qgsvectorlayer.h"
26 #include "qgspainteffect.h"
27 #include "qgspainteffectregistry.h"
28 #include "qgsfontutils.h"
29 #include "qgsmultipointv2.h"
30 #include "qgspointv2.h"
31 
32 #include <QDomElement>
33 #include <QPainter>
34 
35 #include <cmath>
36 
37 #ifndef M_SQRT2
38 #define M_SQRT2 1.41421356237309504880
39 #endif
40 
42  : QgsFeatureRendererV2( "pointDisplacement" )
43  , mLabelAttributeName( labelAttributeName )
44  , mLabelIndex( -1 )
45  , mTolerance( 3 )
46  , mToleranceUnit( QgsSymbolV2::MM )
47  , mPlacement( Ring )
48  , mCircleWidth( 0.4 )
49  , mCircleColor( QColor( 125, 125, 125 ) )
50  , mCircleRadiusAddition( 0 )
51  , mMaxLabelScaleDenominator( -1 )
52  , mSpatialIndex( NULL )
53 {
55  mCenterSymbol = new QgsMarkerSymbolV2(); //the symbol for the center of a displacement group
56  mDrawLabels = true;
57 }
58 
60 {
61  delete mCenterSymbol;
62  delete mRenderer;
63 }
64 
66 {
67  QgsPointDisplacementRenderer* r = new QgsPointDisplacementRenderer( mLabelAttributeName );
68  r->setEmbeddedRenderer( mRenderer->clone() );
69  r->setCircleWidth( mCircleWidth );
70  r->setCircleColor( mCircleColor );
71  r->setLabelFont( mLabelFont );
72  r->setLabelColor( mLabelColor );
73  r->setPlacement( mPlacement );
74  r->setCircleRadiusAddition( mCircleRadiusAddition );
75  r->setMaxLabelScaleDenominator( mMaxLabelScaleDenominator );
76  r->setTolerance( mTolerance );
77  r->setToleranceUnit( mToleranceUnit );
78  r->setToleranceMapUnitScale( mToleranceMapUnitScale );
79  if ( mCenterSymbol )
80  {
81  r->setCenterSymbol( dynamic_cast<QgsMarkerSymbolV2*>( mCenterSymbol->clone() ) );
82  }
83  copyPaintEffect( r );
84  return r;
85 }
86 
88 {
89  mRenderer->toSld( doc, element );
90 }
91 
92 
93 bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
94 {
95  Q_UNUSED( drawVertexMarker );
96  Q_UNUSED( context );
97  Q_UNUSED( layer );
98 
99  //check, if there is already a point at that position
100  if ( !feature.constGeometry() )
101  return false;
102 
103  QgsSymbolV2* symbol = firstSymbolForFeature( mRenderer, feature, context );
104 
105  //if the feature has no symbol (eg, no matching rule in a rule-based renderer), skip it
106  if ( !symbol )
107  return false;
108 
109  //point position in screen coords
110  const QgsGeometry* geom = feature.constGeometry();
111  QGis::WkbType geomType = geom->wkbType();
112  if ( geomType != QGis::WKBPoint && geomType != QGis::WKBPoint25D )
113  {
114  //can only render point type
115  return false;
116  }
117 
118  if ( selected )
119  mSelectedFeatures.insert( feature.id() );
120 
121  double searchDistance = mTolerance * QgsSymbolLayerV2Utils::mapUnitScaleFactor( context, mToleranceUnit, mToleranceMapUnitScale );
122  QList<QgsFeatureId> intersectList = mSpatialIndex->intersects( searchRect( feature.constGeometry()->asPoint(), searchDistance ) );
123  if ( intersectList.empty() )
124  {
125  mSpatialIndex->insertFeature( feature );
126  // create new group
127  DisplacementGroup newGroup;
128  newGroup.insert( feature.id(), qMakePair( feature, symbol ) );
129  mDisplacementGroups.push_back( newGroup );
130  // add to group index
131  mGroupIndex.insert( feature.id(), mDisplacementGroups.count() - 1 );
132  return true;
133  }
134 
135  //go through all the displacement group maps and search an entry where the id equals the result of the spatial search
136  QgsFeatureId existingEntry = intersectList.at( 0 );
137 
138  int groupIdx = mGroupIndex[ existingEntry ];
139  DisplacementGroup& group = mDisplacementGroups[groupIdx];
140 
141  // add to a group
142  group.insert( feature.id(), qMakePair( feature, symbol ) );
143  // add to group index
144  mGroupIndex.insert( feature.id(), groupIdx );
145  return true;
146 }
147 
148 void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, QgsRenderContext& context )
149 {
150  const QgsFeature& feature = group.begin().value().first;
151  bool selected = mSelectedFeatures.contains( feature.id() ); // maybe we should highlight individual features instead of the whole group?
152 
153 
154 
155  //get list of labels and symbols
156  QStringList labelAttributeList;
157  QList<QgsMarkerSymbolV2*> symbolList;
158 
159  QgsMultiPointV2* groupMultiPoint = new QgsMultiPointV2();
160  for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt )
161  {
162  labelAttributeList << ( mDrawLabels ? getLabel( attIt.value().first ) : QString() );
163  symbolList << dynamic_cast<QgsMarkerSymbolV2*>( attIt.value().second );
164  groupMultiPoint->addGeometry( attIt.value().first.constGeometry()->geometry()->clone() );
165  }
166 
167  //calculate centroid of all points, this will be center of group
168  QgsGeometry groupGeom( groupMultiPoint );
169  QgsGeometry* centroid = groupGeom.centroid();
170  QPointF pt;
171  _getPoint( pt, context, centroid->asWkb() );
172  delete centroid;
173 
174  //calculate max diagonal size from all symbols in group
175  double diagonal = 0;
176  Q_FOREACH ( QgsMarkerSymbolV2* symbol, symbolList )
177  {
178  if ( symbol )
179  {
180  diagonal = qMax( diagonal, QgsSymbolLayerV2Utils::convertToPainterUnits( context,
181  M_SQRT2 * symbol->size(),
182  symbol->outputUnit(), symbol->mapUnitScale() ) );
183  }
184  }
185 
186  QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected );
187 
188  QList<QPointF> symbolPositions;
189  QList<QPointF> labelPositions;
190  double circleRadius = -1.0;
191  calculateSymbolAndLabelPositions( symbolContext, pt, symbolList.size(), diagonal, symbolPositions, labelPositions, circleRadius );
192 
193  //draw Circle
194  if ( circleRadius > 0 )
195  drawCircle( circleRadius, symbolContext, pt, symbolList.size() );
196 
197  //draw mid point
198  if ( labelAttributeList.size() > 1 )
199  {
200  if ( mCenterSymbol )
201  {
202  mCenterSymbol->renderPoint( pt, &feature, context, -1, selected );
203  }
204  else
205  {
206  context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
207  }
208  }
209 
210  //draw symbols on the circle
211  drawSymbols( feature, context, symbolList, symbolPositions, selected );
212  //and also the labels
213  drawLabels( pt, symbolContext, labelPositions, labelAttributeList );
214 }
215 
217 {
218  delete mRenderer;
219  mRenderer = r;
220 }
221 
223 {
224  QList<QString> attributeList;
225  if ( !mLabelAttributeName.isEmpty() )
226  {
227  attributeList.push_back( mLabelAttributeName );
228  }
229  if ( mRenderer )
230  {
231  attributeList += mRenderer->usedAttributes();
232  }
233  return attributeList;
234 }
235 
237 {
238  if ( !mRenderer )
239  {
240  return 0;
241  }
242  return mRenderer->capabilities();
243 }
244 
246 {
247  if ( !mRenderer )
248  {
249  return QgsSymbolV2List();
250  }
251  return mRenderer->symbols( context );
252 }
253 
255 {
256  if ( !mRenderer )
257  {
258  return 0;
259  }
260  return mRenderer->symbolForFeature( feature, context );
261 }
262 
264 {
265  if ( !mRenderer )
266  return 0;
267  return mRenderer->originalSymbolForFeature( feat, context );
268 }
269 
271 {
272  if ( !mRenderer )
273  {
274  return QgsSymbolV2List();
275  }
276  return mRenderer->symbolsForFeature( feature, context );
277 }
278 
280 {
281  if ( !mRenderer )
282  return QgsSymbolV2List();
283  return mRenderer->originalSymbolsForFeature( feat, context );
284 }
285 
287 {
288  if ( !mRenderer )
289  {
290  return false;
291  }
292  return mRenderer->willRenderFeature( feat, context );
293 }
294 
295 
297 {
298  mRenderer->startRender( context, fields );
299 
300  mDisplacementGroups.clear();
301  mGroupIndex.clear();
302  mSpatialIndex = new QgsSpatialIndex;
303  mSelectedFeatures.clear();
304 
305  if ( mLabelAttributeName.isEmpty() )
306  {
307  mLabelIndex = -1;
308  }
309  else
310  {
311  mLabelIndex = fields.fieldNameIndex( mLabelAttributeName );
312  }
313 
314  if ( mMaxLabelScaleDenominator > 0 && context.rendererScale() > mMaxLabelScaleDenominator )
315  {
316  mDrawLabels = false;
317  }
318  else
319  {
320  mDrawLabels = true;
321  }
322 
323  if ( mCenterSymbol )
324  {
325  mCenterSymbol->startRender( context, &fields );
326  }
327  return;
328 }
329 
331 {
332  QgsDebugMsg( "QgsPointDisplacementRenderer::stopRender" );
333 
334  //printInfoDisplacementGroups(); //just for debugging
335 
336  for ( QList<DisplacementGroup>::const_iterator it = mDisplacementGroups.begin(); it != mDisplacementGroups.end(); ++it )
337  drawGroup( *it, context );
338 
339  mDisplacementGroups.clear();
340  mGroupIndex.clear();
341  delete mSpatialIndex;
342  mSpatialIndex = 0;
343  mSelectedFeatures.clear();
344 
345  mRenderer->stopRender( context );
346  if ( mCenterSymbol )
347  {
348  mCenterSymbol->stopRender( context );
349  }
350 }
351 
353 {
355  r->setLabelAttributeName( symbologyElem.attribute( "labelAttributeName" ) );
357  if ( !QgsFontUtils::setFromXmlChildNode( labelFont, symbologyElem, "labelFontProperties" ) )
358  {
359  labelFont.fromString( symbologyElem.attribute( "labelFont", "" ) );
360  }
361  r->setLabelFont( labelFont );
362  r->setPlacement(( Placement )symbologyElem.attribute( "placement", "0" ).toInt() );
363  r->setCircleWidth( symbologyElem.attribute( "circleWidth", "0.4" ).toDouble() );
364  r->setCircleColor( QgsSymbolLayerV2Utils::decodeColor( symbologyElem.attribute( "circleColor", "" ) ) );
365  r->setLabelColor( QgsSymbolLayerV2Utils::decodeColor( symbologyElem.attribute( "labelColor", "" ) ) );
366  r->setCircleRadiusAddition( symbologyElem.attribute( "circleRadiusAddition", "0.0" ).toDouble() );
367  r->setMaxLabelScaleDenominator( symbologyElem.attribute( "maxLabelScaleDenominator", "-1" ).toDouble() );
368  r->setTolerance( symbologyElem.attribute( "tolerance", "0.00001" ).toDouble() );
369  r->setToleranceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( symbologyElem.attribute( "toleranceUnit", "MapUnit" ) ) );
370  r->setToleranceMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( symbologyElem.attribute( "toleranceUnitScale" ) ) );
371 
372  //look for an embedded renderer <renderer-v2>
373  QDomElement embeddedRendererElem = symbologyElem.firstChildElement( "renderer-v2" );
374  if ( !embeddedRendererElem.isNull() )
375  {
376  r->setEmbeddedRenderer( QgsFeatureRendererV2::load( embeddedRendererElem ) );
377  }
378 
379  //center symbol
380  QDomElement centerSymbolElem = symbologyElem.firstChildElement( "symbol" );
381  if ( !centerSymbolElem.isNull() )
382  {
383  r->setCenterSymbol( QgsSymbolLayerV2Utils::loadSymbol<QgsMarkerSymbolV2>( centerSymbolElem ) );
384  }
385  return r;
386 }
387 
389 {
390  QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
391  rendererElement.setAttribute( "forceraster", ( mForceRaster ? "1" : "0" ) );
392  rendererElement.setAttribute( "type", "pointDisplacement" );
393  rendererElement.setAttribute( "labelAttributeName", mLabelAttributeName );
394  rendererElement.appendChild( QgsFontUtils::toXmlElement( mLabelFont, doc, "labelFontProperties" ) );
395  rendererElement.setAttribute( "circleWidth", QString::number( mCircleWidth ) );
396  rendererElement.setAttribute( "circleColor", QgsSymbolLayerV2Utils::encodeColor( mCircleColor ) );
397  rendererElement.setAttribute( "labelColor", QgsSymbolLayerV2Utils::encodeColor( mLabelColor ) );
398  rendererElement.setAttribute( "circleRadiusAddition", QString::number( mCircleRadiusAddition ) );
399  rendererElement.setAttribute( "placement", ( int )mPlacement );
400  rendererElement.setAttribute( "maxLabelScaleDenominator", QString::number( mMaxLabelScaleDenominator ) );
401  rendererElement.setAttribute( "tolerance", QString::number( mTolerance ) );
402  rendererElement.setAttribute( "toleranceUnit", QgsSymbolLayerV2Utils::encodeOutputUnit( mToleranceUnit ) );
403  rendererElement.setAttribute( "toleranceUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( mToleranceMapUnitScale ) );
404 
405  if ( mRenderer )
406  {
407  QDomElement embeddedRendererElem = mRenderer->save( doc );
408  rendererElement.appendChild( embeddedRendererElem );
409  }
410  if ( mCenterSymbol )
411  {
412  QDomElement centerSymbolElem = QgsSymbolLayerV2Utils::saveSymbol( "centerSymbol", mCenterSymbol, doc );
413  rendererElement.appendChild( centerSymbolElem );
414  }
415 
417  mPaintEffect->saveProperties( doc, rendererElement );
418 
419  return rendererElement;
420 }
421 
423 {
424  if ( mRenderer )
425  {
426  return mRenderer->legendSymbologyItems( iconSize );
427  }
428  return QgsLegendSymbologyList();
429 }
430 
432 {
433  if ( mRenderer )
434  {
435  return mRenderer->legendSymbolItems( scaleDenominator, rule );
436  }
437  return QgsLegendSymbolList();
438 }
439 
440 
441 QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p, double distance ) const
442 {
443  return QgsRectangle( p.x() - distance, p.y() - distance, p.x() + distance, p.y() + distance );
444 }
445 
446 void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
447 {
448  int nGroups = mDisplacementGroups.size();
449  QgsDebugMsg( "number of displacement groups:" + QString::number( nGroups ) );
450  for ( int i = 0; i < nGroups; ++i )
451  {
452  QgsDebugMsg( "***************displacement group " + QString::number( i ) );
453  DisplacementGroup::const_iterator it = mDisplacementGroups.at( i ).constBegin();
454  for ( ; it != mDisplacementGroups.at( i ).constEnd(); ++it )
455  {
456  QgsDebugMsg( FID_TO_STRING( it.key() ) );
457  }
458  }
459 }
460 
461 QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f )
462 {
463  QString attribute;
464  QgsAttributes attrs = f.attributes();
465  if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() )
466  {
467  attribute = attrs.at( mLabelIndex ).toString();
468  }
469  return attribute;
470 }
471 
473 {
474  delete mCenterSymbol;
475  mCenterSymbol = symbol;
476 }
477 
478 
479 
480 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( QgsSymbolV2RenderContext& symbolContext, const QPointF& centerPoint, int nPosition,
481  double symbolDiagonal, QList<QPointF>& symbolPositions, QList<QPointF>& labelShifts, double& circleRadius ) const
482 {
483  symbolPositions.clear();
484  labelShifts.clear();
485 
486  if ( nPosition < 1 )
487  {
488  return;
489  }
490  else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
491  {
492  symbolPositions.append( centerPoint );
493  labelShifts.append( QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
494  return;
495  }
496 
497  double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition );
498 
499  switch ( mPlacement )
500  {
501  case Ring:
502  {
503  double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 * M_PI );
504  double radius = qMax( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
505 
506  double fullPerimeter = 2 * M_PI;
507  double angleStep = fullPerimeter / nPosition;
508  for ( double currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
509  {
510  double sinusCurrentAngle = sin( currentAngle );
511  double cosinusCurrentAngle = cos( currentAngle );
512  QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
513  QPointF labelShift(( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
514  symbolPositions.append( centerPoint + positionShift );
515  labelShifts.append( labelShift );
516  }
517 
518  circleRadius = radius;
519  break;
520  }
521  case ConcentricRings:
522  {
523  double centerDiagonal = QgsSymbolLayerV2Utils::convertToPainterUnits( symbolContext.renderContext(),
524  M_SQRT2 * mCenterSymbol->size(),
525  mCenterSymbol->outputUnit(), mCenterSymbol->mapUnitScale() );
526 
527  int pointsRemaining = nPosition;
528  int ringNumber = 1;
529  double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
530  while ( pointsRemaining > 0 )
531  {
532  double radiusCurrentRing = qMax( firstRingRadius + ( ringNumber - 1 ) * symbolDiagonal + ringNumber * circleAdditionPainterUnits, 0.0 );
533  int maxPointsCurrentRing = qMax( floor( 2 * M_PI * radiusCurrentRing / symbolDiagonal ), 1.0 );
534  int actualPointsCurrentRing = qMin( maxPointsCurrentRing, pointsRemaining );
535 
536  double angleStep = 2 * M_PI / actualPointsCurrentRing;
537  double currentAngle = 0.0;
538  for ( int i = 0; i < actualPointsCurrentRing; ++i )
539  {
540  double sinusCurrentAngle = sin( currentAngle );
541  double cosinusCurrentAngle = cos( currentAngle );
542  QPointF positionShift( radiusCurrentRing * sinusCurrentAngle, radiusCurrentRing * cosinusCurrentAngle );
543  QPointF labelShift(( radiusCurrentRing + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radiusCurrentRing + symbolDiagonal / 2 ) * cosinusCurrentAngle );
544  symbolPositions.append( centerPoint + positionShift );
545  labelShifts.append( labelShift );
546  currentAngle += angleStep;
547  }
548 
549  pointsRemaining -= actualPointsCurrentRing;
550  ringNumber++;
551  circleRadius = radiusCurrentRing;
552  }
553  break;
554  }
555  }
556 }
557 
558 void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolV2RenderContext& context, const QPointF& centerPoint, int nSymbols )
559 {
560  QPainter* p = context.renderContext().painter();
561  if ( nSymbols < 2 || !p ) //draw circle only if multiple features
562  {
563  return;
564  }
565 
566  //draw Circle
567  QPen circlePen( mCircleColor );
568  circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) );
569  p->setPen( circlePen );
570  p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
571 }
572 
573 void QgsPointDisplacementRenderer::drawSymbols( const QgsFeature& f, QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions, bool selected )
574 {
575  QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
577  for ( ; symbolPosIt != symbolPositions.constEnd() && symbolIt != symbolList.constEnd(); ++symbolPosIt, ++symbolIt )
578  {
579  if ( *symbolIt )
580  {
581  ( *symbolIt )->renderPoint( *symbolPosIt, &f, context, -1, selected );
582  }
583  }
584 }
585 
586 void QgsPointDisplacementRenderer::drawLabels( const QPointF& centerPoint, QgsSymbolV2RenderContext& context, const QList<QPointF>& labelShifts, const QStringList& labelList )
587 {
588  QPainter* p = context.renderContext().painter();
589  if ( !p )
590  {
591  return;
592  }
593 
594  QPen labelPen( mLabelColor );
595  p->setPen( labelPen );
596 
597  //scale font (for printing)
598  QFont pixelSizeFont = mLabelFont;
599  pixelSizeFont.setPixelSize( context.outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) );
600  QFont scaledFont = pixelSizeFont;
601  scaledFont.setPixelSize( pixelSizeFont.pixelSize() * context.renderContext().rasterScaleFactor() );
602  p->setFont( scaledFont );
603 
604  QFontMetricsF fontMetrics( pixelSizeFont );
605  QPointF currentLabelShift; //considers the signs to determine the label position
606 
607  QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin();
608  QStringList::const_iterator text_it = labelList.constBegin();
609 
610  for ( ; labelPosIt != labelShifts.constEnd() && text_it != labelList.constEnd(); ++labelPosIt, ++text_it )
611  {
612  currentLabelShift = *labelPosIt;
613  if ( currentLabelShift.x() < 0 )
614  {
615  currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( *text_it ) );
616  }
617  if ( currentLabelShift.y() > 0 )
618  {
619  currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() );
620  }
621 
622  QPointF drawingPoint( centerPoint + currentLabelShift );
623  p->save();
624  p->translate( drawingPoint.x(), drawingPoint.y() );
625  p->scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
626  p->drawText( QPointF( 0, 0 ), *text_it );
627  p->restore();
628  }
629 }
630 
631 QgsSymbolV2* QgsPointDisplacementRenderer::firstSymbolForFeature( QgsFeatureRendererV2* r, QgsFeature& f, QgsRenderContext &context )
632 {
633  if ( !r )
634  {
635  return 0;
636  }
637 
638  QgsSymbolV2List symbolList = r->symbolsForFeature( f, context );
639  if ( symbolList.size() < 1 )
640  {
641  return 0;
642  }
643 
644  return symbolList.at( 0 );
645 }
646 
648 {
649  if ( renderer->type() == "pointDisplacement" )
650  {
651  return dynamic_cast<QgsPointDisplacementRenderer*>( renderer->clone() );
652  }
653 
654  if ( renderer->type() == "singleSymbol" ||
655  renderer->type() == "categorizedSymbol" ||
656  renderer->type() == "graduatedSymbol" ||
657  renderer->type() == "RuleRenderer" )
658  {
660  pointRenderer->setEmbeddedRenderer( renderer->clone() );
661  return pointRenderer;
662  }
663  return 0;
664 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:53
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
void clear()
#define RENDERER_TAG_NAME
Definition: qgsrendererv2.h:48
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Placement
Placement methods for dispersing points.
int pixelSize() const
QList< QgsFeatureId > intersects(const QgsRectangle &rect) const
Returns features that intersect the specified rectangle.
QList< QgsSymbolV2 * > QgsSymbolV2List
Definition: qgsrendererv2.h:39
QDomNode appendChild(const QDomNode &newChild)
void push_back(const T &value)
static const unsigned char * _getPoint(QPointF &pt, QgsRenderContext &context, const unsigned char *wkb)
QString attribute(const QString &name, const QString &defValue) const
static QgsFeatureRendererV2 * create(QDomElement &symbologyElem)
create a renderer from XML element
static double mapUnitScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale=QgsMapUnitScale())
Returns scale factor painter units -> map units.
qreal pointSizeF() const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
virtual Q_DECL_DEPRECATED QgsSymbolV2 * originalSymbolForFeature(QgsFeature &feature)
Return symbol for feature.
void setLabelAttributeName(const QString &name)
static QString encodeColor(const QColor &color)
int fieldNameIndex(const QString &fieldName) const
Look up field's index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:382
double size() const
double rendererScale() const
virtual QDomElement save(QDomDocument &doc)
store renderer info to XML element
void setCenterSymbol(QgsMarkerSymbolV2 *symbol)
Sets the center symbol (takes ownership)
void scale(qreal sx, qreal sy)
const T & at(int i) const
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
QgsLegendSymbologyList legendSymbologyItems(QSize iconSize) override
return a list of symbology items for the legend
#define FID_TO_STRING(fid)
Definition: qgsfeature.h:89
static QDomElement saveSymbol(const QString &symbolName, QgsSymbolV2 *symbol, QDomDocument &doc)
void save()
QgsMapUnitScale mapUnitScale() const
Container of fields for a vector layer.
Definition: qgsfield.h:177
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
static QgsPointDisplacementRenderer * convertFromRenderer(const QgsFeatureRendererV2 *renderer)
creates a QgsPointDisplacementRenderer from an existing renderer.
QDomElement save(QDomDocument &doc) override
store renderer info to XML element
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat, QgsRenderContext &context) override
Proxy that will call this method on the embedded renderer.
static QString encodeMapUnitScale(const QgsMapUnitScale &mapUnitScale)
virtual QList< QString > usedAttributes()=0
Multi point geometry collection.
WkbType
Used for symbology operations.
Definition: qgis.h:56
QgsPointDisplacementRenderer(const QString &labelAttributeName="")
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:176
void clear()
double toDouble(bool *ok) const
virtual void startRender(QgsRenderContext &context, const QgsFields &fields) override
Needs to be called when a new render cycle is started.
virtual Q_DECL_DEPRECATED bool willRenderFeature(QgsFeature &feat)
return whether the renderer will render a feature or not.
QgsPaintEffect * mPaintEffect
double x() const
Get the x value of the point.
Definition: qgspoint.h:126
virtual QgsLegendSymbologyList legendSymbologyItems(QSize iconSize)
return a list of symbology items for the legend
int size() const
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
Needs to be called when a new render cycle is started.
void setToleranceUnit(QgsSymbolV2::OutputUnit unit)
Sets the units for the tolerance distance.
virtual void stopRender(QgsRenderContext &context)=0
static QgsSymbolV2::OutputUnit decodeOutputUnit(const QString &str)
QString type() const
Definition: qgsrendererv2.h:82
virtual Q_DECL_DEPRECATED QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat)
Equivalent of originalSymbolsForFeature() call extended to support renderers that may use more symbol...
void drawRect(const QRectF &rectangle)
void setPixelSize(int pixelSize)
virtual QgsFeatureRendererV2 * clone() const =0
void setFont(const QFont &font)
The output shall be in millimeters.
Definition: qgssymbolv2.h:57
QString number(int n, int base)
virtual Q_DECL_DEPRECATED QgsSymbolV2 * symbolForFeature(QgsFeature &feature)
To be overridden.
qreal x() const
qreal y() const
void append(const T &value)
virtual QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat, QgsRenderContext &context) override
Proxy that will call this method on the embedded renderer.
bool empty() const
bool fromString(const QString &descrip)
void setEmbeddedRenderer(QgsFeatureRendererV2 *r)
Sets embedded renderer (takes ownership)
void drawArc(const QRectF &rectangle, int startAngle, int spanAngle)
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 startRender(QgsRenderContext &context, const QgsFields *fields=0)
virtual QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="")
return a list of item text / symbol
QgsAttributes attributes() const
Returns the feature's attributes.
Definition: qgsfeature.cpp:92
void setPen(const QColor &color)
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const
bool isEmpty() const
#define M_PI
virtual void toSld(QDomDocument &doc, QDomElement &element) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
virtual QgsSymbolV2 * clone() const override
virtual QgsSymbolV2 * originalSymbolForFeature(QgsFeature &feat, QgsRenderContext &context) override
Proxy that will call this method on the embedded renderer.
void drawText(const QPointF &position, const QString &text)
double rasterScaleFactor() const
static bool setFromXmlChildNode(QFont &font, const QDomElement &element, const QString &childNode)
Sets the properties of a font to match the properties stored in an XML child node.
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
void setPlacement(Placement placement)
Sets the placement method used for dispersing the points.
QgsGeometry * centroid() const
Returns the center of mass of a geometry.
static QgsFeatureRendererV2 * defaultRenderer(QGis::GeometryType geomType)
return a new renderer - used by default in vector layers
virtual Q_DECL_DEPRECATED QgsSymbolV2List symbols()
for symbol levels
void renderPoint(const QPointF &point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
A class to represent a point.
Definition: qgspoint.h:63
bool renderFeature(QgsFeature &feature, QgsRenderContext &context, int layer=-1, bool selected=false, bool drawVertexMarker=false) override
Reimplemented from QgsFeatureRendererV2.
virtual bool willRenderFeature(QgsFeature &feat, QgsRenderContext &context) override
Proxy that will call this method on the embedded renderer.
QList< QPair< QString, QPixmap > > QgsLegendSymbologyList
void stopRender(QgsRenderContext &context) override
virtual void toSld(QDomDocument &doc, QDomElement &element) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
A renderer that automatically displaces points with the same position.
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature, QgsRenderContext &context) override
Proxy that will call this method on the embedded renderer.
bool contains(const T &value) const
bool isNull() const
void restore()
const T & at(int i) const
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.
Contains information about the context of a rendering operation.
bool insertFeature(const QgsFeature &f)
Add feature to index.
QPainter * painter()
void stopRender(QgsRenderContext &context)
void copyPaintEffect(QgsFeatureRendererV2 *destRenderer) const
Copies paint effect of this renderer to another renderer.
QgsLegendSymbolList legendSymbolItems(double scaleDenominator=-1, const QString &rule="") override
virtual Q_DECL_DEPRECATED QgsSymbolV2List symbolsForFeature(QgsFeature &feat)
return list of symbols used for rendering the feature.
static QgsFeatureRendererV2 * load(QDomElement &symbologyElem)
create a renderer from XML element
QgsRenderContext & renderContext()
Definition: qgssymbolv2.h:254
void setX(qreal x)
void setY(qreal y)
QDomElement firstChildElement(const QString &tagName) const
int count(const T &value) const
QgsSymbolV2::OutputUnit outputUnit() const
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:70
void translate(const QPointF &offset)
qint64 QgsFeatureId
Definition: qgsfeature.h:31
double y() const
Get the y value of the point.
Definition: qgspoint.h:134
virtual int capabilities() override
Proxy that will call this method on the embedded renderer.
static QColor decodeColor(const QString &str)
iterator insert(const Key &key, const T &value)
void setToleranceMapUnitScale(const QgsMapUnitScale &scale)
Sets the map unit scale object for the distance tolerance.
static QDomElement toXmlElement(const QFont &font, QDomDocument &document, const QString &elementName)
Returns a DOM element containing the properties of the font.
double outputLineWidth(double width) const
static QgsMapUnitScale decodeMapUnitScale(const QString &str)
const_iterator constEnd() const
virtual int capabilities()
returns bitwise OR-ed capabilities of the renderer
QDomElement createElement(const QString &tagName)
void clear()
const_iterator constBegin() const
QgsPoint asPoint() const
Return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
A vector of attributes.
Definition: qgsfeature.h:109
virtual QList< QString > usedAttributes() override
Partial proxy that will call this method on the embedded renderer.
QList< QPair< QString, QgsSymbolV2 * > > QgsLegendSymbolList
Definition: qgsrendererv2.h:43
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
QgsFeatureRendererV2 * clone() const override
void setTolerance(double t)
Sets the tolerance distance for grouping points.