32 #include <QDomElement>
38 #define M_SQRT2 1.41421356237309504880
43 , mLabelAttributeName( labelAttributeName )
49 , mCircleColor(
QColor( 125, 125, 125 ) )
50 , mCircleRadiusAddition( 0 )
51 , mMaxLabelScaleDenominator( -1 )
52 , mSpatialIndex( NULL )
89 mRenderer->
toSld( doc, element );
95 Q_UNUSED( drawVertexMarker );
103 QgsSymbolV2* symbol = firstSymbolForFeature( mRenderer, feature, context );
119 mSelectedFeatures.
insert( feature.
id() );
123 if ( intersectList.
empty() )
128 newGroup.
insert( feature.
id(), qMakePair( feature, symbol ) );
129 mDisplacementGroups.push_back( newGroup );
131 mGroupIndex.
insert( feature.
id(), mDisplacementGroups.count() - 1 );
138 int groupIdx = mGroupIndex[ existingEntry ];
142 group.
insert( feature.
id(), qMakePair( feature, symbol ) );
144 mGroupIndex.
insert( feature.
id(), groupIdx );
148 void QgsPointDisplacementRenderer::drawGroup(
const DisplacementGroup& group,
QgsRenderContext& context )
150 const QgsFeature& feature = group.begin().value().first;
151 bool selected = mSelectedFeatures.
contains( feature.
id() );
160 for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt )
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() );
190 double circleRadius = -1.0;
191 calculateSymbolAndLabelPositions( symbolContext, pt, symbolList.
size(), diagonal, symbolPositions, labelPositions, circleRadius );
194 if ( circleRadius > 0 )
195 drawCircle( circleRadius, symbolContext, pt, symbolList.
size() );
198 if ( labelAttributeList.
size() > 1 )
202 mCenterSymbol->
renderPoint( pt, &feature, context, -1, selected );
206 context.
painter()->
drawRect(
QRectF( pt.
x() - symbolContext.outputLineWidth( 1 ), pt.
y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
211 drawSymbols( feature, context, symbolList, symbolPositions, selected );
213 drawLabels( pt, symbolContext, labelPositions, labelAttributeList );
225 if ( !mLabelAttributeName.
isEmpty() )
227 attributeList.
push_back( mLabelAttributeName );
233 return attributeList;
251 return mRenderer->
symbols( context );
300 mDisplacementGroups.clear();
303 mSelectedFeatures.
clear();
305 if ( mLabelAttributeName.
isEmpty() )
314 if ( mMaxLabelScaleDenominator > 0 && context.
rendererScale() > mMaxLabelScaleDenominator )
332 QgsDebugMsg(
"QgsPointDisplacementRenderer::stopRender" );
337 drawGroup( *it, context );
339 mDisplacementGroups.clear();
341 delete mSpatialIndex;
343 mSelectedFeatures.
clear();
374 if ( !embeddedRendererElem.
isNull() )
381 if ( !centerSymbolElem.
isNull() )
383 r->
setCenterSymbol( QgsSymbolLayerV2Utils::loadSymbol<QgsMarkerSymbolV2>( centerSymbolElem ) );
392 rendererElement.
setAttribute(
"type",
"pointDisplacement" );
393 rendererElement.
setAttribute(
"labelAttributeName", mLabelAttributeName );
399 rendererElement.
setAttribute(
"placement", (
int )mPlacement );
408 rendererElement.
appendChild( embeddedRendererElem );
419 return rendererElement;
441 QgsRectangle QgsPointDisplacementRenderer::searchRect(
const QgsPoint& p,
double distance )
const
443 return QgsRectangle( p.
x() - distance, p.
y() - distance, p.
x() + distance, p.
y() + distance );
446 void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
448 int nGroups = mDisplacementGroups.size();
450 for (
int i = 0; i < nGroups; ++i )
453 DisplacementGroup::const_iterator it = mDisplacementGroups.at( i ).constBegin();
454 for ( ; it != mDisplacementGroups.at( i ).constEnd(); ++it )
465 if ( mLabelIndex >= 0 && mLabelIndex < attrs.
count() )
467 attribute = attrs.
at( mLabelIndex ).toString();
474 delete mCenterSymbol;
475 mCenterSymbol = symbol;
480 void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions(
QgsSymbolV2RenderContext& symbolContext,
const QPointF& centerPoint,
int nPosition,
483 symbolPositions.
clear();
490 else if ( nPosition == 1 )
492 symbolPositions.
append( centerPoint );
493 labelShifts.
append(
QPointF( symbolDiagonal / 2.0, -symbolDiagonal / 2.0 ) );
497 double circleAdditionPainterUnits = symbolContext.
outputLineWidth( mCircleRadiusAddition );
499 switch ( mPlacement )
503 double minDiameterToFitSymbols = nPosition * symbolDiagonal / ( 2.0 *
M_PI );
504 double radius = qMax( symbolDiagonal / 2, minDiameterToFitSymbols ) + circleAdditionPainterUnits;
506 double fullPerimeter = 2 *
M_PI;
507 double angleStep = fullPerimeter / nPosition;
508 for (
double currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
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 );
518 circleRadius = radius;
527 int pointsRemaining = nPosition;
529 double firstRingRadius = centerDiagonal / 2.0 + symbolDiagonal / 2.0;
530 while ( pointsRemaining > 0 )
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 );
536 double angleStep = 2 *
M_PI / actualPointsCurrentRing;
537 double currentAngle = 0.0;
538 for (
int i = 0; i < actualPointsCurrentRing; ++i )
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;
549 pointsRemaining -= actualPointsCurrentRing;
551 circleRadius = radiusCurrentRing;
558 void QgsPointDisplacementRenderer::drawCircle(
double radiusPainterUnits,
QgsSymbolV2RenderContext& context,
const QPointF& centerPoint,
int nSymbols )
561 if ( nSymbols < 2 || !p )
567 QPen circlePen( mCircleColor );
570 p->
drawArc(
QRectF( centerPoint.
x() - radiusPainterUnits, centerPoint.
y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
577 for ( ; symbolPosIt != symbolPositions.
constEnd() && symbolIt != symbolList.
constEnd(); ++symbolPosIt, ++symbolIt )
581 ( *symbolIt )->renderPoint( *symbolPosIt, &f, context, -1, selected );
594 QPen labelPen( mLabelColor );
598 QFont pixelSizeFont = mLabelFont;
600 QFont scaledFont = pixelSizeFont;
610 for ( ; labelPosIt != labelShifts.
constEnd() && text_it != labelList.
constEnd(); ++labelPosIt, ++text_it )
612 currentLabelShift = *labelPosIt;
613 if ( currentLabelShift.
x() < 0 )
615 currentLabelShift.
setX( currentLabelShift.
x() - fontMetrics.width( *text_it ) );
617 if ( currentLabelShift.
y() > 0 )
619 currentLabelShift.
setY( currentLabelShift.
y() + fontMetrics.ascent() );
622 QPointF drawingPoint( centerPoint + currentLabelShift );
624 p->
translate( drawingPoint.x(), drawingPoint.y() );
639 if ( symbolList.
size() < 1 )
644 return symbolList.
at( 0 );
649 if ( renderer->
type() ==
"pointDisplacement" )
654 if ( renderer->
type() ==
"singleSymbol" ||
655 renderer->
type() ==
"categorizedSymbol" ||
656 renderer->
type() ==
"graduatedSymbol" ||
657 renderer->
type() ==
"RuleRenderer" )
661 return pointRenderer;
QgsFeatureId id() const
Get the feature ID for this feature.
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
#define RENDERER_TAG_NAME
A rectangle specified with double values.
Placement
Placement methods for dispersing points.
~QgsPointDisplacementRenderer()
QList< QgsFeatureId > intersects(const QgsRectangle &rect) const
Returns features that intersect the specified rectangle.
QList< QgsSymbolV2 * > QgsSymbolV2List
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.
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...
double rendererScale() const
void setLabelFont(const QFont &f)
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)
static QDomElement saveSymbol(const QString &symbolName, QgsSymbolV2 *symbol, QDomDocument &doc)
void setMaxLabelScaleDenominator(double d)
QgsMapUnitScale mapUnitScale() const
Container of fields for a vector layer.
A geometry is the spatial representation of a feature.
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.
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...
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.
virtual QgsLegendSymbologyList legendSymbologyItems(QSize iconSize)
return a list of symbology items for the legend
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)
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.
QString number(int n, int base)
virtual Q_DECL_DEPRECATED QgsSymbolV2 * symbolForFeature(QgsFeature &feature)
To be overridden.
void append(const T &value)
virtual QgsSymbolV2List originalSymbolsForFeature(QgsFeature &feat, QgsRenderContext &context) override
Proxy that will call this method on the embedded renderer.
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.
void setPen(const QColor &color)
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const
virtual void toSld(QDomDocument &doc, QDomElement &element) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
void setLabelColor(const QColor &c)
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.
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 setCircleRadiusAddition(double d)
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
void setCircleWidth(double w)
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.
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
void setCircleColor(const QColor &c)
QgsRenderContext & renderContext()
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.
void translate(const QPointF &offset)
double y() const
Get the y value of the point.
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)
const_iterator constBegin() const
QgsPoint asPoint() const
Return contents of the geometry as a point if wkbType is WKBPoint, otherwise returns [0...
virtual QList< QString > usedAttributes() override
Partial proxy that will call this method on the embedded renderer.
QList< QPair< QString, QgsSymbolV2 * > > QgsLegendSymbolList
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.