27 #include <QDomElement>
34 , mLabelAttributeName( labelAttributeName )
36 , mTolerance( 0.00001 )
38 , mCircleColor( QColor( 125, 125, 125 ) )
39 , mCircleRadiusAddition( 0 )
40 , mMaxLabelScaleDenominator( -1 )
41 , mSpatialIndex( NULL )
74 mRenderer->
toSld( doc, element );
80 Q_UNUSED( drawVertexMarker );
98 mSelectedFeatures.insert( feature.
id() );
101 if ( intersectList.empty() )
105 DisplacementGroup newGroup;
106 newGroup.insert( feature.
id(), feature );
107 mDisplacementGroups.push_back( newGroup );
109 mGroupIndex.insert( feature.
id(), mDisplacementGroups.count() - 1 );
116 int groupIdx = mGroupIndex[ existingEntry ];
117 DisplacementGroup& group = mDisplacementGroups[groupIdx];
120 group.insert( feature.
id(), feature );
122 mGroupIndex.insert( feature.
id(), groupIdx );
126 void QgsPointDisplacementRenderer::drawGroup(
const DisplacementGroup& group,
QgsRenderContext& context )
128 const QgsFeature& feature = group.begin().value();
129 bool selected = mSelectedFeatures.contains( feature.
id() );
135 QStringList labelAttributeList;
136 QList<QgsMarkerSymbolV2*> symbolList;
138 for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt )
140 labelAttributeList << ( mDrawLabels ? getLabel( attIt.value() ) : QString() );
142 symbolList << dynamic_cast<QgsMarkerSymbolV2*>( firstSymbolForFeature( mRenderer, f ) );
147 double currentWidthFactor;
149 QList<QgsMarkerSymbolV2*>::const_iterator it = symbolList.constBegin();
150 for ( ; it != symbolList.constEnd(); ++it )
155 double currentDiagonal = sqrt( 2 * (( *it )->size() * ( *it )->size() ) ) * currentWidthFactor;
156 if ( currentDiagonal > diagonal )
158 diagonal = currentDiagonal;
165 double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition );
166 double radius = qMax(( diagonal / 2 ), labelAttributeList.size() * diagonal / 2 /
M_PI ) + circleAdditionPainterUnits;
169 drawCircle( radius, symbolContext, pt, symbolList.size() );
171 QList<QPointF> symbolPositions;
172 QList<QPointF> labelPositions;
173 calculateSymbolAndLabelPositions( pt, labelAttributeList.size(), radius, diagonal, symbolPositions, labelPositions );
176 if ( labelAttributeList.size() > 1 )
180 mCenterSymbol->
renderPoint( pt, &feature, context, -1, selected );
184 context.
painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
189 drawSymbols( feature, context, symbolList, symbolPositions, selected );
191 drawLabels( pt, symbolContext, labelPositions, labelAttributeList );
202 QList<QString> attributeList;
203 if ( !mLabelAttributeName.isEmpty() )
205 attributeList.push_back( mLabelAttributeName );
211 return attributeList;
278 mDisplacementGroups.clear();
281 mSelectedFeatures.clear();
283 if ( mLabelAttributeName.isEmpty() )
292 if ( mMaxLabelScaleDenominator > 0 && context.
rendererScale() > mMaxLabelScaleDenominator )
309 QgsDebugMsg(
"QgsPointDisplacementRenderer::stopRender" );
313 for ( QList<DisplacementGroup>::const_iterator it = mDisplacementGroups.begin(); it != mDisplacementGroups.end(); ++it )
314 drawGroup( *it, context );
316 mDisplacementGroups.clear();
318 delete mSpatialIndex;
320 mSelectedFeatures.clear();
334 labelFont.fromString( symbologyElem.attribute(
"labelFont",
"" ) );
336 r->
setCircleWidth( symbologyElem.attribute(
"circleWidth",
"0.4" ).toDouble() );
341 r->
setTolerance( symbologyElem.attribute(
"tolerance",
"0.00001" ).toDouble() );
344 QDomElement embeddedRendererElem = symbologyElem.firstChildElement(
"renderer-v2" );
345 if ( !embeddedRendererElem.isNull() )
351 QDomElement centerSymbolElem = symbologyElem.firstChildElement(
"symbol" );
352 if ( !centerSymbolElem.isNull() )
354 r->
setCenterSymbol( QgsSymbolLayerV2Utils::loadSymbol<QgsMarkerSymbolV2>( centerSymbolElem ) );
362 rendererElement.setAttribute(
"type",
"pointDisplacement" );
363 rendererElement.setAttribute(
"labelAttributeName", mLabelAttributeName );
364 rendererElement.setAttribute(
"labelFont", mLabelFont.toString() );
365 rendererElement.setAttribute(
"circleWidth", QString::number( mCircleWidth ) );
368 rendererElement.setAttribute(
"circleRadiusAddition", QString::number( mCircleRadiusAddition ) );
369 rendererElement.setAttribute(
"maxLabelScaleDenominator", QString::number( mMaxLabelScaleDenominator ) );
370 rendererElement.setAttribute(
"tolerance", QString::number( mTolerance ) );
374 QDomElement embeddedRendererElem = mRenderer->
save( doc );
375 rendererElement.appendChild( embeddedRendererElem );
380 rendererElement.appendChild( centerSymbolElem );
382 return rendererElement;
406 return QgsRectangle( p.
x() - mTolerance, p.
y() - mTolerance, p.
x() + mTolerance, p.
y() + mTolerance );
409 void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
411 int nGroups = mDisplacementGroups.size();
412 QgsDebugMsg(
"number of displacement groups:" + QString::number( nGroups ) );
413 for (
int i = 0; i < nGroups; ++i )
415 QgsDebugMsg(
"***************displacement group " + QString::number( i ) );
416 QMap<QgsFeatureId, QgsFeature>::const_iterator it = mDisplacementGroups.at( i ).constBegin();
417 for ( ; it != mDisplacementGroups.at( i ).constEnd(); ++it )
424 QString QgsPointDisplacementRenderer::getLabel(
const QgsFeature& f )
428 if ( mLabelIndex >= 0 && mLabelIndex < attrs.count() )
430 attribute = attrs[mLabelIndex].toString();
437 delete mCenterSymbol;
438 mCenterSymbol = symbol;
443 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions(
const QPointF& centerPoint,
int nPosition,
double radius,
444 double symbolDiagonal, QList<QPointF>& symbolPositions, QList<QPointF>& labelShifts )
const
446 symbolPositions.clear();
453 else if ( nPosition == 1 )
455 symbolPositions.append( centerPoint );
456 labelShifts.append( QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
460 double fullPerimeter = 2 *
M_PI;
461 double angleStep = fullPerimeter / nPosition;
464 for ( currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
466 double sinusCurrentAngle = sin( currentAngle );
467 double cosinusCurrentAngle = cos( currentAngle );
468 QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
469 QPointF labelShift(( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
470 symbolPositions.append( centerPoint + positionShift );
471 labelShifts.append( labelShift );
475 void QgsPointDisplacementRenderer::drawCircle(
double radiusPainterUnits,
QgsSymbolV2RenderContext& context,
const QPointF& centerPoint,
int nSymbols )
478 if ( nSymbols < 2 || !p )
484 QPen circlePen( mCircleColor );
486 p->setPen( circlePen );
487 p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
490 void QgsPointDisplacementRenderer::drawSymbols(
const QgsFeature& f,
QgsRenderContext& context,
const QList<QgsMarkerSymbolV2*>& symbolList,
const QList<QPointF>& symbolPositions,
bool selected )
492 QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
493 QList<QgsMarkerSymbolV2*>::const_iterator symbolIt = symbolList.constBegin();
494 for ( ; symbolPosIt != symbolPositions.constEnd() && symbolIt != symbolList.constEnd(); ++symbolPosIt, ++symbolIt )
498 ( *symbolIt )->renderPoint( *symbolPosIt, &f, context, -1, selected );
503 void QgsPointDisplacementRenderer::drawLabels(
const QPointF& centerPoint,
QgsSymbolV2RenderContext& context,
const QList<QPointF>& labelShifts,
const QStringList& labelList )
511 QPen labelPen( mLabelColor );
512 p->setPen( labelPen );
515 QFont pixelSizeFont = mLabelFont;
516 pixelSizeFont.setPixelSize( context.
outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) );
517 QFont scaledFont = pixelSizeFont;
519 p->setFont( scaledFont );
521 QFontMetricsF fontMetrics( pixelSizeFont );
522 QPointF currentLabelShift;
524 QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin();
525 QStringList::const_iterator text_it = labelList.constBegin();
527 for ( ; labelPosIt != labelShifts.constEnd() && text_it != labelList.constEnd(); ++labelPosIt, ++text_it )
529 currentLabelShift = *labelPosIt;
530 if ( currentLabelShift.x() < 0 )
532 currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( *text_it ) );
534 if ( currentLabelShift.y() > 0 )
536 currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() );
539 QPointF drawingPoint( centerPoint + currentLabelShift );
541 p->translate( drawingPoint.x(), drawingPoint.y() );
543 p->drawText( QPointF( 0, 0 ), *text_it );
556 if ( symbolList.size() < 1 )
561 return symbolList.at( 0 );
566 if ( renderer->
type() ==
"pointDisplacement" )
571 if ( renderer->
type() ==
"singleSymbol" ||
572 renderer->
type() ==
"categorizedSymbol" ||
573 renderer->
type() ==
"graduatedSymbol" ||
574 renderer->
type() ==
"RuleRenderer" )
578 return pointRenderer;