Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgslabelingengine.h 3 : : -------------------------------------- 4 : : Date : September 2015 5 : : Copyright : (C) 2015 by Martin Dobias 6 : : Email : wonder dot sk at gmail dot com 7 : : *************************************************************************** 8 : : * * 9 : : * This program is free software; you can redistribute it and/or modify * 10 : : * it under the terms of the GNU General Public License as published by * 11 : : * the Free Software Foundation; either version 2 of the License, or * 12 : : * (at your option) any later version. * 13 : : * * 14 : : ***************************************************************************/ 15 : : 16 : : #ifndef QGSLABELINGENGINE_H 17 : : #define QGSLABELINGENGINE_H 18 : : 19 : : #define SIP_NO_FILE 20 : : 21 : : #include "qgis_core.h" 22 : : #include "qgsmapsettings.h" 23 : : 24 : : #include "qgspallabeling.h" 25 : : #include "qgslabelingenginesettings.h" 26 : : #include "qgslabeling.h" 27 : : 28 : : class QgsLabelingEngine; 29 : : class QgsLabelingResults; 30 : : 31 : : namespace pal 32 : : { 33 : : class Problem; 34 : : } 35 : : 36 : : /** 37 : : * \ingroup core 38 : : * \brief The QgsAbstractLabelProvider class is an interface class. Implementations 39 : : * return list of labels and their associated geometries - these are used by 40 : : * QgsLabelingEngine to compute the final layout of labels. 41 : : * 42 : : * Implementations also take care of drawing the returned final label positions. 43 : : * 44 : : * \note this class is not a part of public API yet. See notes in QgsLabelingEngine 45 : : * \note not available in Python bindings 46 : : * \since QGIS 2.12 47 : : */ 48 : : class CORE_EXPORT QgsAbstractLabelProvider 49 : : { 50 : : 51 : : public: 52 : : //! Construct the provider with default values 53 : : QgsAbstractLabelProvider( QgsMapLayer *layer, const QString &providerId = QString() ); 54 : : 55 : 0 : virtual ~QgsAbstractLabelProvider() = default; 56 : : 57 : : //! Associate provider with a labeling engine (should be only called internally from QgsLabelingEngine) 58 : 0 : void setEngine( const QgsLabelingEngine *engine ) { mEngine = engine; } 59 : : 60 : : enum Flag 61 : : { 62 : : DrawLabels = 1 << 1, //!< Whether the labels should be rendered 63 : : DrawAllLabels = 1 << 2, //!< Whether all features will be labelled even though overlaps occur 64 : : MergeConnectedLines = 1 << 3, //!< Whether adjacent lines (with the same label text) should be merged 65 : : CentroidMustBeInside = 1 << 4, //!< Whether location of centroid must be inside of polygons 66 : : }; 67 : : Q_DECLARE_FLAGS( Flags, Flag ) 68 : : 69 : : //! Returns list of label features (they are owned by the provider and thus deleted on its destruction) 70 : : virtual QList<QgsLabelFeature *> labelFeatures( QgsRenderContext &context ) = 0; 71 : : 72 : : /** 73 : : * Draw this label at the position determined by the labeling engine. 74 : : * 75 : : * Before any calls to drawLabel(), a provider should be prepared for rendering by a call to 76 : : * startRender() and a corresponding call to stopRender(). 77 : : */ 78 : : virtual void drawLabel( QgsRenderContext &context, pal::LabelPosition *label ) const = 0; 79 : : 80 : : /** 81 : : * Draw an unplaced label. These correspond to features which were registered for labeling, 82 : : * but which could not be labeled (e.g. due to conflicting labels). 83 : : * 84 : : * The default behavior is to draw nothing for these labels. 85 : : * 86 : : * \note This method is only used if the QgsLabelingEngineSettings::DrawUnplacedLabels flag 87 : : * is set on the labeling engine. 88 : : * 89 : : * \since QGIS 3.10 90 : : */ 91 : : virtual void drawUnplacedLabel( QgsRenderContext &context, pal::LabelPosition *label ) const; 92 : : 93 : : /** 94 : : * Draw the background for the specified \a label. 95 : : * 96 : : * This is called in turn for each label provider before any actual labels are rendered, 97 : : * and allows the provider to render content which should be drawn below ALL map labels 98 : : * (such as background rectangles or callout lines). 99 : : * 100 : : * Before any calls to drawLabelBackground(), a provider should be prepared for rendering by a call to 101 : : * startRender() and a corresponding call to stopRender(). 102 : : * 103 : : * \since QGIS 3.10 104 : : */ 105 : : virtual void drawLabelBackground( QgsRenderContext &context, pal::LabelPosition *label ) const; 106 : : 107 : : /** 108 : : * To be called before rendering of labels begins. Must be accompanied by 109 : : * a corresponding call to stopRender() 110 : : * \since QGIS 3.10 111 : : */ 112 : : virtual void startRender( QgsRenderContext &context ); 113 : : 114 : : /** 115 : : * To be called after rendering is complete. 116 : : * \see startRender() 117 : : * \since QGIS 3.10 118 : : */ 119 : : virtual void stopRender( QgsRenderContext &context ); 120 : : 121 : : //! Returns list of child providers - useful if the provider needs to put labels into more layers with different configuration 122 : 0 : virtual QList<QgsAbstractLabelProvider *> subProviders() { return QList<QgsAbstractLabelProvider *>(); } 123 : : 124 : : //! Name of the layer (for statistics, debugging etc.) - does not need to be unique 125 : 0 : QString name() const { return mName; } 126 : : 127 : : //! Returns ID of associated layer, or empty string if no layer is associated with the provider. 128 : 0 : QString layerId() const { return mLayerId; } 129 : : 130 : : //! Returns the associated layer, or NULLPTR if no layer is associated with the provider. 131 : 0 : QgsMapLayer *layer() const { return mLayer.data(); } 132 : : 133 : : /** 134 : : * Returns provider ID - useful in case there is more than one label provider within a layer 135 : : * (e.g. in case of rule-based labeling - provider ID = rule's key). May be empty string if 136 : : * layer ID is sufficient for identification of provider's configuration. 137 : : */ 138 : 0 : QString providerId() const { return mProviderId; } 139 : : 140 : : //! Flags associated with the provider 141 : 0 : Flags flags() const { return mFlags; } 142 : : 143 : : //! What placement strategy to use for the labels 144 : 0 : QgsPalLayerSettings::Placement placement() const { return mPlacement; } 145 : : 146 : : //! Default priority of labels (may be overridden by individual labels) 147 : 0 : double priority() const { return mPriority; } 148 : : 149 : : //! How the feature geometries will work as obstacles 150 : 0 : QgsLabelObstacleSettings::ObstacleType obstacleType() const { return mObstacleType; } 151 : : 152 : : //! How to handle labels that would be upside down 153 : 0 : QgsPalLayerSettings::UpsideDownLabels upsidedownLabels() const { return mUpsidedownLabels; } 154 : : 155 : : protected: 156 : : //! Associated labeling engine 157 : : const QgsLabelingEngine *mEngine = nullptr; 158 : : 159 : : //! Name of the layer 160 : : QString mName; 161 : : //! Associated layer's ID, if applicable 162 : : QString mLayerId; 163 : : //! Weak pointer to source layer 164 : : QgsWeakMapLayerPointer mLayer; 165 : : //! Associated provider ID (one layer may have multiple providers, e.g. in rule-based labeling) 166 : : QString mProviderId; 167 : : //! Flags altering drawing and registration of features 168 : : Flags mFlags; 169 : : //! Placement strategy 170 : : QgsPalLayerSettings::Placement mPlacement; 171 : : //! Default priority of labels 172 : : double mPriority; 173 : : //! Type of the obstacle of feature geometries 174 : : QgsLabelObstacleSettings::ObstacleType mObstacleType = QgsLabelObstacleSettings::PolygonBoundary; 175 : : //! How to handle labels that would be upside down 176 : : QgsPalLayerSettings::UpsideDownLabels mUpsidedownLabels; 177 : : }; 178 : : 179 : : Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAbstractLabelProvider::Flags ) 180 : : 181 : : 182 : : /** 183 : : * \ingroup core 184 : : * \brief The QgsLabelingEngine class provides map labeling functionality. 185 : : * The input for the engine is a list of label provider objects and map settings. 186 : : * Based on the input, the engine computes layout of labels for the given map view 187 : : * with no collisions between the labels. Drawing of resulting labels is done 188 : : * again by label providers. 189 : : * 190 : : * The labeling engine is used for the map rendering in QgsMapRendererJob instances, 191 : : * individual map layer renderers may add label providers - for example, 192 : : * QgsVectorLayerRenderer may add text label provider and diagram provider 193 : : * (if labeling / diagrams were configured for such vector layer). 194 : : * 195 : : * The labeling engine may also be used independently from map rendering loop: 196 : : * \code{.cpp} 197 : : * QgsLabelingEngine engine; 198 : : * engine.setMapSettings( mapSettings ); 199 : : * // add one or more providers 200 : : * engine.addProvider( ... ); 201 : : * // compute the labeling and draw labels (using painter from the context) 202 : : * engine.run( context ); 203 : : * \endcode 204 : : * 205 : : * \note this class is not a part of public API yet. The provider's interface still 206 : : * uses pal::LabelPosition as an argument in drawLabels() method - this should be 207 : : * sorted out first (a class common to API and pal?). Also, the API may need more 208 : : * polishing to be easy to use - e.g. use concept of labeling layers in API 209 : : * (equivalent of pal::Layer) instead of subProviders(), label providers integrated 210 : : * into feature loop vs providers with independent feature loop), split labeling 211 : : * computation from drawing of labels, improved results class with label iterator). 212 : : * \note not available in Python bindings 213 : : * \since QGIS 2.12 214 : : */ 215 : : class CORE_EXPORT QgsLabelingEngine 216 : : { 217 : : public: 218 : : //! Construct the labeling engine with default settings 219 : : QgsLabelingEngine(); 220 : : //! Clean up everything (especially the registered providers) 221 : : virtual ~QgsLabelingEngine(); 222 : : 223 : : //! QgsLabelingEngine cannot be copied. 224 : : QgsLabelingEngine( const QgsLabelingEngine &rh ) = delete; 225 : : //! QgsLabelingEngine cannot be copied. 226 : : QgsLabelingEngine &operator=( const QgsLabelingEngine &rh ) = delete; 227 : : 228 : : //! Associate map settings instance 229 : : void setMapSettings( const QgsMapSettings &mapSettings ); 230 : : //! Gets associated map settings 231 : 0 : const QgsMapSettings &mapSettings() const { return mMapSettings; } 232 : : 233 : : //! Gets associated labeling engine settings 234 : 0 : const QgsLabelingEngineSettings &engineSettings() const { return mMapSettings.labelingEngineSettings(); } 235 : : 236 : : /** 237 : : * Returns a list of layers with providers in the engine. 238 : : * \since QGIS 3.0 239 : : */ 240 : : QList< QgsMapLayer * > participatingLayers() const; 241 : : 242 : : /** 243 : : * Returns a list of layer IDs for layers with providers in the engine. 244 : : * \since QGIS 3.10 245 : : */ 246 : : QStringList participatingLayerIds() const; 247 : : 248 : : //! Add provider of label features. Takes ownership of the provider 249 : : void addProvider( QgsAbstractLabelProvider *provider ); 250 : : 251 : : //! Remove provider if the provider's initialization failed. Provider instance is deleted. 252 : : void removeProvider( QgsAbstractLabelProvider *provider ); 253 : : 254 : : /** 255 : : * Runs the labeling job. 256 : : * 257 : : * Depending on the concrete labeling engine class, this will either run the whole 258 : : * labeling job, including rendering the labels themselves, OR possibly just run the labeling 259 : : * job but leave the rendering to a future, deferred stage. 260 : : */ 261 : : virtual void run( QgsRenderContext &context ) = 0; 262 : : 263 : : //! Returns pointer to recently computed results and pass the ownership of results to the caller 264 : : QgsLabelingResults *takeResults(); 265 : : 266 : : //! For internal use by the providers 267 : 0 : QgsLabelingResults *results() const { return mResults.get(); } 268 : : 269 : : protected: 270 : : void processProvider( QgsAbstractLabelProvider *provider, QgsRenderContext &context, pal::Pal &p ); 271 : : 272 : : protected: 273 : : 274 : : /** 275 : : * Runs the label registration step. 276 : : * 277 : : * Must be called by subclasses prior to solve() and drawLabels() 278 : : * 279 : : * \since QGIS 3.10 280 : : */ 281 : : void registerLabels( QgsRenderContext &context ); 282 : : 283 : : /** 284 : : * Solves the label problem. 285 : : * 286 : : * Must be called by subclasses prior to drawLabels(), and must be 287 : : * preceded by a call to registerLabels() 288 : : * 289 : : * \since QGIS 3.10 290 : : */ 291 : : void solve( QgsRenderContext &context ); 292 : : 293 : : /** 294 : : * Draws labels to the specified render \a context. 295 : : * 296 : : * If \a layerId is specified, only labels from the matching layer will 297 : : * be rendered. 298 : : * 299 : : * Must be preceded by a call to registerLabels() and solve() 300 : : * 301 : : * \since QGIS 3.10 302 : : */ 303 : : void drawLabels( QgsRenderContext &context, const QString &layerId = QString() ); 304 : : 305 : : /** 306 : : * Cleans up the engine following a call to registerLabels() or solve(). 307 : : * \since QGIS 3.10 308 : : */ 309 : : void cleanup(); 310 : : 311 : : //! Associated map settings instance 312 : : QgsMapSettings mMapSettings; 313 : : 314 : : //! List of providers (the are owned by the labeling engine) 315 : : QList<QgsAbstractLabelProvider *> mProviders; 316 : : QList<QgsAbstractLabelProvider *> mSubProviders; 317 : : 318 : : //! Resulting labeling layout 319 : : std::unique_ptr< QgsLabelingResults > mResults; 320 : : 321 : : std::unique_ptr< pal::Pal > mPal; 322 : : std::unique_ptr< pal::Problem > mProblem; 323 : : QList<pal::LabelPosition *> mUnlabeled; 324 : : QList<pal::LabelPosition *> mLabels; 325 : : 326 : : }; 327 : : 328 : : /** 329 : : * \ingroup core 330 : : * \class QgsDefaultLabelingEngine 331 : : * \brief Default QgsLabelingEngine implementation, which completes the whole 332 : : * labeling operation (including label rendering) in the run() method. 333 : : * \note this class is not a part of public API yet. See notes in QgsLabelingEngine 334 : : * \note not available in Python bindings 335 : : * \since QGIS 3.10 336 : : */ 337 : 0 : class CORE_EXPORT QgsDefaultLabelingEngine : public QgsLabelingEngine 338 : : { 339 : : public: 340 : : //! Construct the labeling engine with default settings 341 : : QgsDefaultLabelingEngine(); 342 : : 343 : : //! QgsDefaultLabelingEngine cannot be copied. 344 : : QgsDefaultLabelingEngine( const QgsDefaultLabelingEngine &rh ) = delete; 345 : : //! QgsDefaultLabelingEngine cannot be copied. 346 : : QgsDefaultLabelingEngine &operator=( const QgsDefaultLabelingEngine &rh ) = delete; 347 : : 348 : : void run( QgsRenderContext &context ) override; 349 : : 350 : : }; 351 : : 352 : : /** 353 : : * \ingroup core 354 : : * \class QgsStagedRenderLabelingEngine 355 : : * \brief A QgsLabelingEngine implementation, which only calculates 356 : : * the labeling solution during its run() method. The actual rendering 357 : : * of labels themselves is deferred to follow up calls to .... 358 : : * 359 : : * \note this class is not a part of public API yet. See notes in QgsLabelingEngine 360 : : * \note not available in Python bindings 361 : : * \since QGIS 3.10 362 : : */ 363 : 0 : class CORE_EXPORT QgsStagedRenderLabelingEngine : public QgsLabelingEngine 364 : : { 365 : : public: 366 : : //! Construct the labeling engine with default settings 367 : : QgsStagedRenderLabelingEngine(); 368 : : 369 : : //! QgsStagedRenderLabelingEngine cannot be copied. 370 : : QgsStagedRenderLabelingEngine( const QgsStagedRenderLabelingEngine &rh ) = delete; 371 : : //! QgsStagedRenderLabelingEngine cannot be copied. 372 : : QgsStagedRenderLabelingEngine &operator=( const QgsStagedRenderLabelingEngine &rh ) = delete; 373 : : 374 : : void run( QgsRenderContext &context ) override; 375 : : 376 : : /** 377 : : * Renders all the labels which belong only to the layer with matching \a layerId 378 : : * to the specified render \a context. 379 : : */ 380 : : void renderLabelsForLayer( QgsRenderContext &context, const QString &layerId ); 381 : : 382 : : /** 383 : : * Finalizes and cleans up the engine following the rendering of labels for the last layer 384 : : * to be labeled (via renderLabelsForLayer() ). 385 : : */ 386 : : void finalize(); 387 : : }; 388 : : 389 : : 390 : : /** 391 : : * \ingroup core 392 : : * \class QgsLabelingUtils 393 : : * \brief Contains helper utilities for working with QGIS' labeling engine. 394 : : * \note this class is not a part of public API yet. See notes in QgsLabelingEngine 395 : : * \note not available in Python bindings 396 : : * \since QGIS 2.14 397 : : */ 398 : : class CORE_EXPORT QgsLabelingUtils 399 : : { 400 : : public: 401 : : 402 : : /** 403 : : * Encodes an ordered list of predefined point label positions to a string. 404 : : * \param positions order list of positions 405 : : * \returns list encoded to string 406 : : * \see decodePredefinedPositionOrder() 407 : : */ 408 : : static QString encodePredefinedPositionOrder( const QVector< QgsPalLayerSettings::PredefinedPointPosition > &positions ); 409 : : 410 : : /** 411 : : * Decodes a string to an ordered list of predefined point label positions. 412 : : * \param positionString encoded string of positions 413 : : * \returns decoded list 414 : : * \see encodePredefinedPositionOrder() 415 : : */ 416 : : static QVector< QgsPalLayerSettings::PredefinedPointPosition > decodePredefinedPositionOrder( const QString &positionString ); 417 : : 418 : : /** 419 : : * Encodes line placement \a flags to a string. 420 : : * \see decodeLinePlacementFlags() 421 : : */ 422 : : static QString encodeLinePlacementFlags( QgsLabeling::LinePlacementFlags flags ); 423 : : 424 : : /** 425 : : * Decodes a \a string to set of line placement flags. 426 : : * \see encodeLinePlacementFlags() 427 : : */ 428 : : static QgsLabeling::LinePlacementFlags decodeLinePlacementFlags( const QString &string ); 429 : : 430 : : }; 431 : : 432 : : #endif // QGSLABELINGENGINE_H