Quantum GIS API Documentation  1.8
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   vlayer->select( attList, viewExtent, true, false );
00368   while ( vlayer->nextFeature( f ) )
00369   {
00370     intersectList.clear();
00371 
00372     //check, if there is already a point at that position
00373     if ( f.geometry() )
00374     {
00375       intersectList = spatialIndex.intersects( searchRect( f.geometry()->asPoint() ) );
00376       if ( intersectList.empty() )
00377       {
00378         spatialIndex.insertFeature( f );
00379       }
00380       else
00381       {
00382         //go through all the displacement group maps and search an entry where the id equals the result of the spatial search
00383         QgsFeatureId existingEntry = intersectList.at( 0 );
00384         bool found = false;
00385         QList< QMap<QgsFeatureId, QgsFeature> >::iterator it = mDisplacementGroups.begin();
00386         for ( ; it != mDisplacementGroups.end(); ++it )
00387         {
00388           if ( it->size() > 0 && it->contains( existingEntry ) )
00389           {
00390             found = true;
00391             QgsFeature feature;
00392             it->insert( f.id(), f );
00393             mDisplacementIds.insert( f.id() );
00394             break;
00395           }
00396         }
00397 
00398         if ( !found )//insert the already existing feature and the new one into a map
00399         {
00400           QMap<QgsFeatureId, QgsFeature> newMap;
00401           QgsFeature existingFeature;
00402           vlayer->featureAtId( existingEntry, existingFeature );
00403           newMap.insert( existingEntry, existingFeature );
00404           mDisplacementIds.insert( existingEntry );
00405           newMap.insert( f.id(), f );
00406           mDisplacementIds.insert( f.id() );
00407           mDisplacementGroups.push_back( newMap );
00408         }
00409       }
00410     }
00411   }
00412   //refresh the selection because the vector layer is going to step through all features now
00413   vlayer->select( attList, viewExtent, true, false );
00414 }
00415 
00416 QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p ) const
00417 {
00418   return QgsRectangle( p.x() - mTolerance, p.y() - mTolerance, p.x() + mTolerance, p.y() + mTolerance );
00419 }
00420 
00421 void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
00422 {
00423   int nGroups = mDisplacementGroups.size();
00424   QgsDebugMsg( "number of displacement groups:" + QString::number( nGroups ) );
00425   for ( int i = 0; i < nGroups; ++i )
00426   {
00427     QgsDebugMsg( "***************displacement group " + QString::number( i ) );
00428     QMap<QgsFeatureId, QgsFeature>::const_iterator it = mDisplacementGroups.at( i ).constBegin();
00429     for ( ; it != mDisplacementGroups.at( i ).constEnd(); ++it )
00430     {
00431       QgsDebugMsg( FID_TO_STRING( it.key() ) );
00432     }
00433   }
00434   QgsDebugMsg( "********all displacement ids*********" );
00435   QSet<QgsFeatureId>::const_iterator iIt = mDisplacementIds.constBegin();
00436   for ( ; iIt != mDisplacementIds.constEnd(); ++iIt )
00437   {
00438     QgsDebugMsg( FID_TO_STRING( *iIt ) );
00439   }
00440 }
00441 
00442 void QgsPointDisplacementRenderer::setDisplacementGroups( const QList< QMap<QgsFeatureId, QgsFeature> >& list )
00443 {
00444   mDisplacementGroups = list;
00445   mDisplacementIds.clear();
00446 
00447   QList<QMap<QgsFeatureId, QgsFeature> >::const_iterator list_it = mDisplacementGroups.constBegin();
00448   for ( ; list_it != mDisplacementGroups.constEnd(); ++list_it )
00449   {
00450     QMap<QgsFeatureId, QgsFeature>::const_iterator map_it = list_it->constBegin();
00451     for ( ; map_it != list_it->constEnd(); ++map_it )
00452     {
00453       mDisplacementIds.insert( map_it.key() );
00454     }
00455   }
00456 }
00457 
00458 QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f )
00459 {
00460   QString attribute;
00461   QgsAttributeMap attMap = f.attributeMap();
00462   if ( attMap.size() > 0 )
00463   {
00464     QgsAttributeMap::const_iterator valIt = attMap.find( mLabelIndex );
00465     if ( valIt != attMap.constEnd() )
00466     {
00467       attribute = valIt->toString();
00468     }
00469   }
00470   return attribute;
00471 }
00472 
00473 void QgsPointDisplacementRenderer::setCenterSymbol( QgsMarkerSymbolV2* symbol )
00474 {
00475   delete mCenterSymbol;
00476   mCenterSymbol = symbol;
00477 }
00478 
00479 
00480 
00481 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( const QPointF& centerPoint, int nPosition, double radius,
00482     double symbolDiagonal, QList<QPointF>& symbolPositions, QList<QPointF>& labelShifts ) const
00483 {
00484   symbolPositions.clear();
00485   labelShifts.clear();
00486 
00487   if ( nPosition < 1 )
00488   {
00489     return;
00490   }
00491   else if ( nPosition == 1 ) //If there is only one feature, draw it exactly at the center position
00492   {
00493     symbolPositions.append( centerPoint );
00494     labelShifts.append( QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
00495     return;
00496   }
00497 
00498   double fullPerimeter = 2 * M_PI;
00499   double angleStep = fullPerimeter / nPosition;
00500   double currentAngle;
00501 
00502   for ( currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
00503   {
00504     double sinusCurrentAngle = sin( currentAngle );
00505     double cosinusCurrentAngle = cos( currentAngle );
00506     QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
00507     QPointF labelShift(( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
00508     symbolPositions.append( centerPoint + positionShift );
00509     labelShifts.append( labelShift );
00510   }
00511 }
00512 
00513 void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolV2RenderContext& context, const QPointF& centerPoint, int nSymbols )
00514 {
00515   QPainter* p = context.renderContext().painter();
00516   if ( nSymbols < 2 || !p ) //draw circle only if multiple features
00517   {
00518     return;
00519   }
00520 
00521   //draw Circle
00522   QPen circlePen( mCircleColor );
00523   circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) );
00524   p->setPen( circlePen );
00525   p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
00526 }
00527 
00528 void QgsPointDisplacementRenderer::drawSymbols( QgsFeature& f, QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions, bool selected )
00529 {
00530   QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
00531   QList<QgsMarkerSymbolV2*>::const_iterator symbolIt = symbolList.constBegin();
00532   for ( ; symbolPosIt != symbolPositions.constEnd() && symbolIt != symbolList.constEnd(); ++symbolPosIt, ++symbolIt )
00533   {
00534     if ( *symbolIt )
00535     {
00536       ( *symbolIt )->renderPoint( *symbolPosIt, &f, context, -1, selected );
00537     }
00538   }
00539 }
00540 
00541 void QgsPointDisplacementRenderer::drawLabels( const QPointF& centerPoint, QgsSymbolV2RenderContext& context, const QList<QPointF>& labelShifts, const QStringList& labelList )
00542 {
00543   QPainter* p = context.renderContext().painter();
00544   if ( !p )
00545   {
00546     return;
00547   }
00548 
00549   QPen labelPen( mLabelColor );
00550   p->setPen( labelPen );
00551 
00552   //scale font (for printing)
00553   QFont pixelSizeFont = mLabelFont;
00554   pixelSizeFont.setPixelSize( context.outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) );
00555   QFont scaledFont = pixelSizeFont;
00556   scaledFont.setPixelSize( pixelSizeFont.pixelSize() * context.renderContext().rasterScaleFactor() );
00557   p->setFont( scaledFont );
00558 
00559   QFontMetricsF fontMetrics( pixelSizeFont );
00560   QPointF currentLabelShift; //considers the signs to determine the label position
00561 
00562   QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin();
00563   QStringList::const_iterator text_it = labelList.constBegin();
00564 
00565   for ( ; labelPosIt != labelShifts.constEnd() && text_it != labelList.constEnd(); ++labelPosIt, ++text_it )
00566   {
00567     currentLabelShift = *labelPosIt;
00568     if ( currentLabelShift.x() < 0 )
00569     {
00570       currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( *text_it ) );
00571     }
00572     if ( currentLabelShift.y() > 0 )
00573     {
00574       currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() );
00575     }
00576 
00577     QPointF drawingPoint( centerPoint + currentLabelShift );
00578     p->save();
00579     p->translate( drawingPoint.x(), drawingPoint.y() );
00580     p->scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
00581     p->drawText( QPointF( 0, 0 ), *text_it );
00582     p->restore();
00583   }
00584 }
00585 
00586 QgsSymbolV2* QgsPointDisplacementRenderer::firstSymbolForFeature( QgsFeatureRendererV2* r, QgsFeature& f )
00587 {
00588   if ( !r )
00589   {
00590     return 0;
00591   }
00592 
00593   QgsSymbolV2List symbolList = r->symbolsForFeature( f );
00594   if ( symbolList.size() < 1 )
00595   {
00596     return 0;
00597   }
00598 
00599   return symbolList.at( 0 );
00600 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines