QGIS API Documentation  master-6164ace
src/core/symbology-ng/qgspointdisplacementrenderer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                               qgspointdisplacementrenderer.cpp
00003                               --------------------------------
00004   begin                : January 26, 2010
00005   copyright            : (C) 2010 by Marco Hugentobler
00006   email                : marco at hugis dot net
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgspointdisplacementrenderer.h"
00019 #include "qgsgeometry.h"
00020 #include "qgslogger.h"
00021 #include "qgsspatialindex.h"
00022 #include "qgssymbolv2.h"
00023 #include "qgssymbollayerv2utils.h"
00024 #include "qgsvectorlayer.h"
00025 
00026 #include <QDomElement>
00027 #include <QPainter>
00028 
00029 #include <cmath>
00030 
00031 QgsPointDisplacementRenderer::QgsPointDisplacementRenderer( const QString& labelAttributeName )
00032     : QgsFeatureRendererV2( "pointDisplacement" )
00033     , mLabelAttributeName( labelAttributeName )
00034     , mLabelIndex( -1 )
00035     , mTolerance( 0.00001 )
00036     , mCircleWidth( 0.4 )
00037     , mCircleColor( QColor( 125, 125, 125 ) )
00038     , mCircleRadiusAddition( 0 )
00039     , mMaxLabelScaleDenominator( -1 )
00040 {
00041   mRenderer = QgsFeatureRendererV2::defaultRenderer( QGis::Point );
00042   mCenterSymbol = new QgsMarkerSymbolV2(); //the symbol for the center of a displacement group
00043   mDrawLabels = true;
00044 }
00045 
00046 QgsPointDisplacementRenderer::~QgsPointDisplacementRenderer()
00047 {
00048   delete mCenterSymbol;
00049   delete mRenderer;
00050 }
00051 
00052 QgsFeatureRendererV2* QgsPointDisplacementRenderer::clone()
00053 {
00054   QgsPointDisplacementRenderer* r = new QgsPointDisplacementRenderer( mLabelAttributeName );
00055   r->setEmbeddedRenderer( mRenderer->clone() );
00056   r->setDisplacementGroups( mDisplacementGroups );
00057   r->setCircleWidth( mCircleWidth );
00058   r->setCircleColor( mCircleColor );
00059   r->setLabelFont( mLabelFont );
00060   r->setLabelColor( mLabelColor );
00061   r->setCircleRadiusAddition( mCircleRadiusAddition );
00062   r->setMaxLabelScaleDenominator( mMaxLabelScaleDenominator );
00063   r->setTolerance( mTolerance );
00064   if ( mCenterSymbol )
00065   {
00066     r->setCenterSymbol( dynamic_cast<QgsMarkerSymbolV2*>( mCenterSymbol->clone() ) );
00067   }
00068   return r;
00069 }
00070 
00071 void QgsPointDisplacementRenderer::toSld( QDomDocument& doc, QDomElement &element ) const
00072 {
00073   mRenderer->toSld( doc, element );
00074 }
00075 
00076 
00077 bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker )
00078 {
00079   Q_UNUSED( drawVertexMarker );
00080   //point position in screen coords
00081   QgsGeometry* geom = feature.geometry();
00082   QGis::WkbType geomType = geom->wkbType();
00083   if ( geomType != QGis::WKBPoint && geomType != QGis::WKBPoint25D )
00084   {
00085     //can only render point type
00086     return false;
00087   }
00088   QPointF pt;
00089   _getPoint( pt, context, geom->asWkb() );
00090 
00091 
00092   //get list of labels and symbols
00093   QStringList labelAttributeList;
00094   QList<QgsMarkerSymbolV2*> symbolList;
00095 
00096   if ( mDisplacementIds.contains( feature.id() ) )
00097   {
00098     //create the symbol for the whole display group if the id is the first entry in a display group
00099     QList<QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin();
00100     for ( ; it != mDisplacementGroups.end(); ++it )
00101     {
00102       //create the symbol for the whole display group if the id is the first entry in a display group
00103       if ( feature.id() == it->begin().key() )
00104       {
00105         QMap<QgsFeatureId, QgsFeature>::iterator attIt = it->begin();
00106         for ( ; attIt != it->end(); ++attIt )
00107         {
00108           if ( mDrawLabels )
00109           {
00110             labelAttributeList << getLabel( attIt.value() );
00111           }
00112           else
00113           {
00114             labelAttributeList << QString();
00115           }
00116           symbolList << dynamic_cast<QgsMarkerSymbolV2*>( firstSymbolForFeature( mRenderer, attIt.value() ) );
00117         }
00118       }
00119     }
00120   }
00121   else //only one feature
00122   {
00123     symbolList << dynamic_cast<QgsMarkerSymbolV2*>( firstSymbolForFeature( mRenderer, feature ) );
00124     if ( mDrawLabels )
00125     {
00126       labelAttributeList << getLabel( feature );
00127     }
00128     else
00129     {
00130       labelAttributeList << QString();
00131     }
00132   }
00133 
00134   if ( symbolList.isEmpty() && labelAttributeList.isEmpty() )
00135   {
00136     return true; //display all point symbols for one posi
00137   }
00138 
00139 
00140   //draw symbol
00141   double diagonal = 0;
00142   double currentWidthFactor; //scale symbol size to map unit and output resolution
00143 
00144   QList<QgsMarkerSymbolV2*>::const_iterator it = symbolList.constBegin();
00145   for ( ; it != symbolList.constEnd(); ++it )
00146   {
00147     if ( *it )
00148     {
00149       currentWidthFactor = QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, ( *it )->outputUnit() );
00150       double currentDiagonal = sqrt( 2 * (( *it )->size() * ( *it )->size() ) ) * currentWidthFactor;
00151       if ( currentDiagonal > diagonal )
00152       {
00153         diagonal = currentDiagonal;
00154       }
00155     }
00156   }
00157 
00158 
00159   QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected );
00160   double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition );
00161   double radius = qMax(( diagonal / 2 ), labelAttributeList.size() * diagonal / 2 / M_PI ) + circleAdditionPainterUnits;
00162 
00163   //draw Circle
00164   drawCircle( radius, symbolContext, pt, symbolList.size() );
00165 
00166   QList<QPointF> symbolPositions;
00167   QList<QPointF> labelPositions;
00168   calculateSymbolAndLabelPositions( pt, labelAttributeList.size(), radius, diagonal, symbolPositions, labelPositions );
00169 
00170   //draw mid point
00171   if ( labelAttributeList.size() > 1 )
00172   {
00173     if ( mCenterSymbol )
00174     {
00175       mCenterSymbol->renderPoint( pt, &feature, context, layer, selected );
00176     }
00177     else
00178     {
00179       context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
00180     }
00181   }
00182 
00183   //draw symbols on the circle
00184   drawSymbols( feature, context, symbolList, symbolPositions, selected );
00185   //and also the labels
00186   drawLabels( pt, symbolContext, labelPositions, labelAttributeList );
00187   return true;
00188 }
00189 
00190 void QgsPointDisplacementRenderer::setEmbeddedRenderer( QgsFeatureRendererV2* r )
00191 {
00192   delete mRenderer;
00193   mRenderer = r;
00194 }
00195 
00196 QgsSymbolV2* QgsPointDisplacementRenderer::symbolForFeature( QgsFeature& feature )
00197 {
00198   Q_UNUSED( feature );
00199   return 0; //not used any more
00200 }
00201 
00202 void QgsPointDisplacementRenderer::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
00203 {
00204   mRenderer->startRender( context, vlayer );
00205 
00206   //create groups with features that have the same position
00207   createDisplacementGroups( const_cast<QgsVectorLayer*>( vlayer ), context.extent() );
00208   printInfoDisplacementGroups(); //just for debugging
00209 
00210   if ( mLabelAttributeName.isEmpty() )
00211   {
00212     mLabelIndex = -1;
00213   }
00214   else
00215   {
00216     mLabelIndex = vlayer->fieldNameIndex( mLabelAttributeName );
00217   }
00218 
00219   if ( mMaxLabelScaleDenominator > 0 && context.rendererScale() > mMaxLabelScaleDenominator )
00220   {
00221     mDrawLabels = false;
00222   }
00223   else
00224   {
00225     mDrawLabels = true;
00226   }
00227 
00228   if ( mCenterSymbol )
00229   {
00230     mCenterSymbol->startRender( context, vlayer );
00231   }
00232 }
00233 
00234 void QgsPointDisplacementRenderer::stopRender( QgsRenderContext& context )
00235 {
00236   QgsDebugMsg( "QgsPointDisplacementRenderer::stopRender" );
00237   mRenderer->stopRender( context );
00238   if ( mCenterSymbol )
00239   {
00240     mCenterSymbol->stopRender( context );
00241   }
00242 }
00243 
00244 QList<QString> QgsPointDisplacementRenderer::usedAttributes()
00245 {
00246   QList<QString> attributeList;
00247   if ( !mLabelAttributeName.isEmpty() )
00248   {
00249     attributeList.push_back( mLabelAttributeName );
00250   }
00251   if ( mRenderer )
00252   {
00253     attributeList += mRenderer->usedAttributes();
00254   }
00255   return attributeList;
00256 }
00257 
00258 QgsSymbolV2List QgsPointDisplacementRenderer::symbols()
00259 {
00260   if ( mRenderer )
00261   {
00262     return mRenderer->symbols();
00263   }
00264   else
00265   {
00266     return QgsSymbolV2List();
00267   }
00268 }
00269 
00270 QgsFeatureRendererV2* QgsPointDisplacementRenderer::create( QDomElement& symbologyElem )
00271 {
00272   QgsPointDisplacementRenderer* r = new QgsPointDisplacementRenderer();
00273   r->setLabelAttributeName( symbologyElem.attribute( "labelAttributeName" ) );
00274   QFont labelFont;
00275   labelFont.fromString( symbologyElem.attribute( "labelFont", "" ) );
00276   r->setLabelFont( labelFont );
00277   r->setCircleWidth( symbologyElem.attribute( "circleWidth", "0.4" ).toDouble() );
00278   r->setCircleColor( QgsSymbolLayerV2Utils::decodeColor( symbologyElem.attribute( "circleColor", "" ) ) );
00279   r->setLabelColor( QgsSymbolLayerV2Utils::decodeColor( symbologyElem.attribute( "labelColor", "" ) ) );
00280   r->setCircleRadiusAddition( symbologyElem.attribute( "circleRadiusAddition", "0.0" ).toDouble() );
00281   r->setMaxLabelScaleDenominator( symbologyElem.attribute( "maxLabelScaleDenominator", "-1" ).toDouble() );
00282 
00283   //look for an embedded renderer <renderer-v2>
00284   QDomElement embeddedRendererElem = symbologyElem.firstChildElement( "renderer-v2" );
00285   if ( !embeddedRendererElem.isNull() )
00286   {
00287     r->setEmbeddedRenderer( QgsFeatureRendererV2::load( embeddedRendererElem ) );
00288   }
00289 
00290   //center symbol
00291   QDomElement centerSymbolElem = symbologyElem.firstChildElement( "symbol" );
00292   if ( !centerSymbolElem.isNull() )
00293   {
00294     r->setCenterSymbol( dynamic_cast<QgsMarkerSymbolV2*>( QgsSymbolLayerV2Utils::loadSymbol( centerSymbolElem ) ) );
00295   }
00296   return r;
00297 }
00298 
00299 QDomElement QgsPointDisplacementRenderer::save( QDomDocument& doc )
00300 {
00301   QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
00302   rendererElement.setAttribute( "type", "pointDisplacement" );
00303   rendererElement.setAttribute( "labelAttributeName", mLabelAttributeName );
00304   rendererElement.setAttribute( "labelFont", mLabelFont.toString() );
00305   rendererElement.setAttribute( "circleWidth", QString::number( mCircleWidth ) );
00306   rendererElement.setAttribute( "circleColor", QgsSymbolLayerV2Utils::encodeColor( mCircleColor ) );
00307   rendererElement.setAttribute( "labelColor", QgsSymbolLayerV2Utils::encodeColor( mLabelColor ) );
00308   rendererElement.setAttribute( "circleRadiusAddition", QString::number( mCircleRadiusAddition ) );
00309   rendererElement.setAttribute( "maxLabelScaleDenominator", QString::number( mMaxLabelScaleDenominator ) );
00310 
00311   if ( mRenderer )
00312   {
00313     QDomElement embeddedRendererElem = mRenderer->save( doc );
00314     rendererElement.appendChild( embeddedRendererElem );
00315   }
00316   if ( mCenterSymbol )
00317   {
00318     QDomElement centerSymbolElem = QgsSymbolLayerV2Utils::saveSymbol( "centerSymbol", mCenterSymbol, doc );
00319     rendererElement.appendChild( centerSymbolElem );
00320   }
00321   return rendererElement;
00322 }
00323 
00324 QgsLegendSymbologyList QgsPointDisplacementRenderer::legendSymbologyItems( QSize iconSize )
00325 {
00326   if ( mRenderer )
00327   {
00328     return mRenderer->legendSymbologyItems( iconSize );
00329   }
00330   return QgsLegendSymbologyList();
00331 }
00332 
00333 QgsLegendSymbolList QgsPointDisplacementRenderer::legendSymbolItems()
00334 {
00335   if ( mRenderer )
00336   {
00337     return mRenderer->legendSymbolItems();
00338   }
00339   return QgsLegendSymbolList();
00340 }
00341 
00342 void QgsPointDisplacementRenderer::createDisplacementGroups( QgsVectorLayer* vlayer, const QgsRectangle& viewExtent )
00343 {
00344   if ( !vlayer || ( vlayer->wkbType() != QGis::WKBPoint && vlayer->wkbType() != QGis::WKBPoint25D ) )
00345   {
00346     return;
00347   }
00348 
00349   mDisplacementGroups.clear();
00350   mDisplacementIds.clear();
00351 
00352   //use a spatial index to check if there is already a point at a position
00353   QgsSpatialIndex spatialIndex;
00354 
00355   //attributes
00356   QgsAttributeList attList;
00357   QList<QString> attributeStrings = usedAttributes();
00358   QList<QString>::const_iterator attStringIt = attributeStrings.constBegin();
00359   for ( ; attStringIt != attributeStrings.constEnd(); ++attStringIt )
00360   {
00361     attList.push_back( vlayer->fieldNameIndex( *attStringIt ) );
00362   }
00363 
00364   QgsFeature f;
00365   QList<QgsFeatureId> intersectList;
00366 
00367   //Because the new vector api does not allow querying features by id within a nextFeature loop, default constructed QgsFeature() is
00368   //inserted first and the real features are created in a second loop
00369 
00370   QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( viewExtent ).setSubsetOfAttributes( attList ) );
00371   while ( fit.nextFeature( f ) )
00372   {
00373     intersectList.clear();
00374 
00375     //check, if there is already a point at that position
00376     if ( f.geometry() )
00377     {
00378       intersectList = spatialIndex.intersects( searchRect( f.geometry()->asPoint() ) );
00379       if ( intersectList.empty() )
00380       {
00381         spatialIndex.insertFeature( f );
00382       }
00383       else
00384       {
00385         //go through all the displacement group maps and search an entry where the id equals the result of the spatial search
00386         QgsFeatureId existingEntry = intersectList.at( 0 );
00387         bool found = false;
00388         QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin();
00389         for ( ; it != mDisplacementGroups.end(); ++it )
00390         {
00391           if ( it->size() > 0 && it->contains( existingEntry ) )
00392           {
00393             found = true;
00394             QgsFeature feature;
00395             it->insert( f.id(), QgsFeature() );
00396             mDisplacementIds.insert( f.id() );
00397             break;
00398           }
00399         }
00400 
00401         if ( !found )//insert the already existing feature and the new one into a map
00402         {
00403           QMap<QgsFeatureId, QgsFeature> newMap;
00404           newMap.insert( existingEntry, QgsFeature() );
00405           mDisplacementIds.insert( existingEntry );
00406           newMap.insert( f.id(), QgsFeature() );
00407           mDisplacementIds.insert( f.id() );
00408           mDisplacementGroups.push_back( newMap );
00409         }
00410       }
00411     }
00412   }
00413 
00414   //insert the real features into mDisplacementGroups
00415   QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin();
00416   for ( ; it != mDisplacementGroups.end(); ++it )
00417   {
00418     QMap<QgsFeatureId, QgsFeature>::iterator mapIt = it->begin();
00419     for ( ; mapIt != it->end(); ++mapIt )
00420     {
00421       QgsFeature fet;
00422       vlayer->getFeatures( QgsFeatureRequest().setFilterFid( mapIt.key() ) ).nextFeature( fet );
00423       mapIt.value() = fet;
00424     }
00425   }
00426 
00427 }
00428 
00429 QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p ) const
00430 {
00431   return QgsRectangle( p.x() - mTolerance, p.y() - mTolerance, p.x() + mTolerance, p.y() + mTolerance );
00432 }
00433 
00434 void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
00435 {
00436   int nGroups = mDisplacementGroups.size();
00437   QgsDebugMsg( "number of displacement groups:" + QString::number( nGroups ) );
00438   for ( int i = 0; i < nGroups; ++i )
00439   {
00440     QgsDebugMsg( "***************displacement group " + QString::number( i ) );
00441     QMap<QgsFeatureId, QgsFeature>::const_iterator it = mDisplacementGroups.at( i ).constBegin();
00442     for ( ; it != mDisplacementGroups.at( i ).constEnd(); ++it )
00443     {
00444       QgsDebugMsg( FID_TO_STRING( it.key() ) );
00445     }
00446   }
00447   QgsDebugMsg( "********all displacement ids*********" );
00448   QSet<QgsFeatureId>::const_iterator iIt = mDisplacementIds.constBegin();
00449   for ( ; iIt != mDisplacementIds.constEnd(); ++iIt )
00450   {
00451     QgsDebugMsg( FID_TO_STRING( *iIt ) );
00452   }
00453 }
00454 
00455 void QgsPointDisplacementRenderer::setDisplacementGroups( const QList< QMap<QgsFeatureId, QgsFeature> >& list )
00456 {
00457   mDisplacementGroups = list;
00458   mDisplacementIds.clear();
00459 
00460   QList<QMap<QgsFeatureId, QgsFeature> >::const_iterator list_it = mDisplacementGroups.constBegin();
00461   for ( ; list_it != mDisplacementGroups.constEnd(); ++list_it )
00462   {
00463     QMap<QgsFeatureId, QgsFeature>::const_iterator map_it = list_it->constBegin();
00464     for ( ; map_it != list_it->constEnd(); ++map_it )
00465     {
00466       mDisplacementIds.insert( map_it.key() );
00467     }
00468   }
00469 }
00470 
00471 QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f )
00472 {
00473   QString attribute;
00474   const QgsAttributes& attrs = f.attributes();
00475   if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() )
00476   {
00477     attribute = attrs[mLabelIndex].toString();
00478   }
00479   return attribute;
00480 }
00481 
00482 void QgsPointDisplacementRenderer::setCenterSymbol( QgsMarkerSymbolV2* symbol )
00483 {
00484   delete mCenterSymbol;
00485   mCenterSymbol = symbol;
00486 }
00487 
00488 
00489 
00490 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( const QPointF& centerPoint, int nPosition, double radius,
00491     double symbolDiagonal, QList<QPointF>& symbolPositions, QList<QPointF>& labelShifts ) const
00492 {
00493   symbolPositions.clear();
00494   labelShifts.clear();
00495 
00496   if ( nPosition < 1 )
00497   {
00498     return;
00499   }
00500   else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
00501   {
00502     symbolPositions.append( centerPoint );
00503     labelShifts.append( QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
00504     return;
00505   }
00506 
00507   double fullPerimeter = 2 * M_PI;
00508   double angleStep = fullPerimeter / nPosition;
00509   double currentAngle;
00510 
00511   for ( currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
00512   {
00513     double sinusCurrentAngle = sin( currentAngle );
00514     double cosinusCurrentAngle = cos( currentAngle );
00515     QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
00516     QPointF labelShift(( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
00517     symbolPositions.append( centerPoint + positionShift );
00518     labelShifts.append( labelShift );
00519   }
00520 }
00521 
00522 void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolV2RenderContext& context, const QPointF& centerPoint, int nSymbols )
00523 {
00524   QPainter* p = context.renderContext().painter();
00525   if ( nSymbols < 2 || !p ) //draw circle only if multiple features
00526   {
00527     return;
00528   }
00529 
00530   //draw Circle
00531   QPen circlePen( mCircleColor );
00532   circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) );
00533   p->setPen( circlePen );
00534   p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
00535 }
00536 
00537 void QgsPointDisplacementRenderer::drawSymbols( QgsFeature& f, QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions, bool selected )
00538 {
00539   QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
00540   QList<QgsMarkerSymbolV2*>::const_iterator symbolIt = symbolList.constBegin();
00541   for ( ; symbolPosIt != symbolPositions.constEnd() && symbolIt != symbolList.constEnd(); ++symbolPosIt, ++symbolIt )
00542   {
00543     if ( *symbolIt )
00544     {
00545       ( *symbolIt )->renderPoint( *symbolPosIt, &f, context, -1, selected );
00546     }
00547   }
00548 }
00549 
00550 void QgsPointDisplacementRenderer::drawLabels( const QPointF& centerPoint, QgsSymbolV2RenderContext& context, const QList<QPointF>& labelShifts, const QStringList& labelList )
00551 {
00552   QPainter* p = context.renderContext().painter();
00553   if ( !p )
00554   {
00555     return;
00556   }
00557 
00558   QPen labelPen( mLabelColor );
00559   p->setPen( labelPen );
00560 
00561   //scale font (for printing)
00562   QFont pixelSizeFont = mLabelFont;
00563   pixelSizeFont.setPixelSize( context.outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) );
00564   QFont scaledFont = pixelSizeFont;
00565   scaledFont.setPixelSize( pixelSizeFont.pixelSize() * context.renderContext().rasterScaleFactor() );
00566   p->setFont( scaledFont );
00567 
00568   QFontMetricsF fontMetrics( pixelSizeFont );
00569   QPointF currentLabelShift; //considers the signs to determine the label position
00570 
00571   QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin();
00572   QStringList::const_iterator text_it = labelList.constBegin();
00573 
00574   for ( ; labelPosIt != labelShifts.constEnd() && text_it != labelList.constEnd(); ++labelPosIt, ++text_it )
00575   {
00576     currentLabelShift = *labelPosIt;
00577     if ( currentLabelShift.x() < 0 )
00578     {
00579       currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( *text_it ) );
00580     }
00581     if ( currentLabelShift.y() > 0 )
00582     {
00583       currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() );
00584     }
00585 
00586     QPointF drawingPoint( centerPoint + currentLabelShift );
00587     p->save();
00588     p->translate( drawingPoint.x(), drawingPoint.y() );
00589     p->scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
00590     p->drawText( QPointF( 0, 0 ), *text_it );
00591     p->restore();
00592   }
00593 }
00594 
00595 QgsSymbolV2* QgsPointDisplacementRenderer::firstSymbolForFeature( QgsFeatureRendererV2* r, QgsFeature& f )
00596 {
00597   if ( !r )
00598   {
00599     return 0;
00600   }
00601 
00602   QgsSymbolV2List symbolList = r->symbolsForFeature( f );
00603   if ( symbolList.size() < 1 )
00604   {
00605     return 0;
00606   }
00607 
00608   return symbolList.at( 0 );
00609 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines