1 /*************************************************************************** 2 qgspointdisplacementrenderer.cpp 3 -------------------------------- 4 begin : January 26, 2010 5 copyright : (C) 2010 by Marco Hugentobler 6 email : marco at hugis dot net 7 ***************************************************************************/ 8 9 /*************************************************************************** 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 ***************************************************************************/ 17 18 #ifndef QGSPOINTDISPLACEMENTRENDERER_H 19 #define QGSPOINTDISPLACEMENTRENDERER_H 20 21 #include "qgis_core.h" 22 #include "qgis.h" 23 #include "qgspointdistancerenderer.h" 24 25 /** 26 * \class QgsPointDisplacementRenderer 27 * \ingroup core 28 * \brief A renderer that automatically displaces points with the same geographic location. 29 */ 30 class CORE_EXPORT QgsPointDisplacementRenderer: public QgsPointDistanceRenderer 31 { 32 public: 33 34 /** 35 * Placement methods for dispersing points 36 */ 37 enum Placement 38 { 39 Ring, //!< Place points in a single ring around group 40 ConcentricRings, //!< Place points in concentric rings around group 41 Grid //!< Place points in a grid around group 42 }; 43 44 /** 45 * Constructor for QgsPointDisplacementRenderer. 46 * \param labelAttributeName optional attribute name for labeling points 47 */ 48 QgsPointDisplacementRenderer( const QString &labelAttributeName = QString() ); 49 50 QgsPointDisplacementRenderer *clone() const override SIP_FACTORY; 51 void startRender( QgsRenderContext &context, const QgsFields &fields ) override; 52 void stopRender( QgsRenderContext &context ) override; 53 QDomElement save( QDomDocument &doc, const QgsReadWriteContext &context ) override; 54 QSet<QString> usedAttributes( const QgsRenderContext &context ) const override; 55 bool accept( QgsStyleEntityVisitorInterface *visitor ) const override; 56 57 //! Create a renderer from XML element 58 static QgsFeatureRenderer *create( QDomElement &symbologyElem, const QgsReadWriteContext &context ) SIP_FACTORY; 59 60 /** 61 * Sets the line width for the displacement group circle. 62 * \param width line width in mm 63 * \see circleWidth() 64 * \see setCircleColor() 65 */ setCircleWidth(double width)66 void setCircleWidth( double width ) { mCircleWidth = width; } 67 68 /** 69 * Returns the line width for the displacement group circle in mm. 70 * \see setCircleWidth() 71 * \see circleColor() 72 */ circleWidth()73 double circleWidth() const { return mCircleWidth; } 74 75 /** 76 * Sets the color used for drawing the displacement group circle. 77 * \param color circle color 78 * \see circleColor() 79 * \see setCircleWidth() 80 */ setCircleColor(const QColor & color)81 void setCircleColor( const QColor &color ) { mCircleColor = color; } 82 83 /** 84 * Returns the color used for drawing the displacement group circle. 85 * \see setCircleColor() 86 * \see circleWidth() 87 */ circleColor()88 QColor circleColor() const { return mCircleColor; } 89 90 /** 91 * Sets a factor for increasing the ring size of displacement groups. 92 * \param distance addition factor 93 * \see circleRadiusAddition() 94 */ setCircleRadiusAddition(double distance)95 void setCircleRadiusAddition( double distance ) { mCircleRadiusAddition = distance; } 96 97 /** 98 * Returns the factor for increasing the ring size of displacement groups. 99 * \see setCircleRadiusAddition() 100 */ circleRadiusAddition()101 double circleRadiusAddition() const { return mCircleRadiusAddition; } 102 103 /** 104 * Sets a factor for increasing the label distances from the symbol. 105 * \param factor addition factor 106 * \see labelDistanceFactor() 107 * \since QGIS 3.8 108 */ setLabelDistanceFactor(double factor)109 void setLabelDistanceFactor( double factor ) { mLabelDistanceFactor = factor; } 110 111 /** 112 * Returns the factor for label distance from the symbol. 113 * \see setLabelDistanceFactor() 114 * \since QGIS 3.8 115 */ labelDistanceFactor()116 double labelDistanceFactor() const { return mLabelDistanceFactor; } 117 118 /** 119 * Returns the placement method used for dispersing the points. 120 * \see setPlacement() 121 * \since QGIS 2.12 122 */ placement()123 Placement placement() const { return mPlacement; } 124 125 /** 126 * Sets the placement method used for dispersing the points. 127 * \param placement placement method 128 * \see placement() 129 * \since QGIS 2.12 130 */ setPlacement(Placement placement)131 void setPlacement( Placement placement ) { mPlacement = placement; } 132 133 /** 134 * Returns the symbol for the center of a displacement group (but not ownership of the symbol). 135 * \see setCenterSymbol() 136 */ 137 QgsMarkerSymbol *centerSymbol(); 138 139 /** 140 * Sets the center symbol for a displacement group. 141 * \param symbol new center symbol. Ownership is transferred to the renderer. 142 * \see centerSymbol() 143 */ 144 void setCenterSymbol( QgsMarkerSymbol *symbol SIP_TRANSFER ); 145 146 /** 147 * Creates a QgsPointDisplacementRenderer from an existing renderer. 148 * \returns a new renderer if the conversion was possible, otherwise NULLPTR. 149 * \since QGIS 2.5 150 */ 151 static QgsPointDisplacementRenderer *convertFromRenderer( const QgsFeatureRenderer *renderer ) SIP_FACTORY; 152 153 private: 154 #ifdef SIP_RUN 155 QgsPointDisplacementRenderer( const QgsPointDisplacementRenderer & ); 156 QgsPointDisplacementRenderer &operator=( const QgsPointDisplacementRenderer & ); 157 #endif 158 159 //! Center symbol for a displacement group 160 std::unique_ptr< QgsMarkerSymbol > mCenterSymbol; 161 162 //! Displacement placement mode 163 Placement mPlacement = Ring; 164 165 //! Line width for the circle 166 double mCircleWidth = 0.4; 167 //! Color to draw the circle 168 QColor mCircleColor; 169 //! Addition to the default circle radius 170 double mCircleRadiusAddition = 0; 171 //! Factor for label distance 172 double mLabelDistanceFactor = 0.5; 173 174 void drawGroup( QPointF centerPoint, QgsRenderContext &context, const QgsPointDistanceRenderer::ClusteredGroup &group ) override SIP_FORCE; 175 176 //helper functions 177 void calculateSymbolAndLabelPositions( QgsSymbolRenderContext &symbolContext, QPointF centerPoint, int nPosition, double symbolDiagonal, QList<QPointF> &symbolPositions, QList<QPointF> &labelShifts, double &circleRadius, 178 double &gridRadius, int &gridSize, QVector<double> &diagonals ) const; 179 void drawCircle( double radiusPainterUnits, QgsSymbolRenderContext &context, QPointF centerPoint, int nSymbols ); 180 void drawSymbols( const ClusteredGroup &group, QgsRenderContext &context, const QList<QPointF> &symbolPositions ); 181 void drawGrid( int gridSizeUnits, QgsSymbolRenderContext &context, 182 QList<QPointF> pointSymbolPositions, int nSymbols ); 183 void centralizeGrid( QList<QPointF> &pointSymbolPositions, double radius, int size ) const; 184 }; 185 186 #endif // QGSPOINTDISPLACEMENTRENDERER_H 187