|
QGIS API Documentation
master-6164ace
|
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 }