Branch data Line data Source code
1 : : /* 2 : : * libpal - Automated Placement of Labels Library 3 : : * 4 : : * Copyright (C) 2008 Maxence Laurent, MIS-TIC, HEIG-VD 5 : : * University of Applied Sciences, Western Switzerland 6 : : * http://www.hes-so.ch 7 : : * 8 : : * Contact: 9 : : * maxence.laurent <at> heig-vd <dot> ch 10 : : * or 11 : : * eric.taillard <at> heig-vd <dot> ch 12 : : * 13 : : * This file is part of libpal. 14 : : * 15 : : * libpal is free software: you can redistribute it and/or modify 16 : : * it under the terms of the GNU General Public License as published by 17 : : * the Free Software Foundation, either version 3 of the License, or 18 : : * (at your option) any later version. 19 : : * 20 : : * libpal is distributed in the hope that it will be useful, 21 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 : : * GNU General Public License for more details. 24 : : * 25 : : * You should have received a copy of the GNU General Public License 26 : : * along with libpal. If not, see <http://www.gnu.org/licenses/>. 27 : : * 28 : : */ 29 : : 30 : : #ifndef PAL_H 31 : : #define PAL_H 32 : : 33 : : #define SIP_NO_FILE 34 : : 35 : : 36 : : #include "qgis_core.h" 37 : : #include "qgsgeometry.h" 38 : : #include "qgsgeos.h" 39 : : #include "qgspallabeling.h" 40 : : #include "qgslabelingenginesettings.h" 41 : : #include <QList> 42 : : #include <iostream> 43 : : #include <ctime> 44 : : #include <QMutex> 45 : : #include <QStringList> 46 : : #include <unordered_map> 47 : : 48 : : // TODO ${MAJOR} ${MINOR} etc instead of 0.2 49 : : 50 : : class QgsAbstractLabelProvider; 51 : : 52 : : namespace pal 53 : : { 54 : : class Layer; 55 : : class LabelPosition; 56 : : class PalStat; 57 : : class Problem; 58 : : class PointSet; 59 : : 60 : : //! Search method to use 61 : : enum SearchMethod 62 : : { 63 : : CHAIN = 0, //!< Is the worst but fastest method 64 : : POPMUSIC_TABU_CHAIN = 1, //!< Is the best but slowest 65 : : POPMUSIC_TABU = 2, //!< Is a little bit better than CHAIN but slower 66 : : POPMUSIC_CHAIN = 3, //!< Is slower and best than TABU, worse and faster than TABU_CHAIN 67 : : FALP = 4 //!< Only initial solution 68 : : }; 69 : : 70 : : /** 71 : : * \ingroup core 72 : : * \brief Main Pal labeling class 73 : : * 74 : : * A pal object will contains layers and global information such as which search method 75 : : * will be used. 76 : : * \class pal::Pal 77 : : * \note not available in Python bindings 78 : : */ 79 : : class CORE_EXPORT Pal 80 : : { 81 : : friend class Problem; 82 : : friend class FeaturePart; 83 : : friend class Layer; 84 : : 85 : : public: 86 : : 87 : : /** 88 : : * \brief Create an new pal instance 89 : : */ 90 : : Pal(); 91 : : 92 : : ~Pal(); 93 : : 94 : : //! Pal cannot be copied. 95 : : Pal( const Pal &other ) = delete; 96 : : //! Pal cannot be copied. 97 : : Pal &operator=( const Pal &other ) = delete; 98 : : 99 : : /** 100 : : * \brief add a new layer 101 : : * 102 : : * \param provider Provider associated with the layer 103 : : * \param layerName layer's name 104 : : * \param arrangement Howto place candidates 105 : : * \param defaultPriority layer's prioriry (0 is the best, 1 the worst) 106 : : * \param active is the layer is active (currently displayed) 107 : : * \param toLabel the layer will be labeled only if toLablel is TRUE 108 : : * \param displayAll if TRUE, all features will be labelled even though overlaps occur 109 : : * 110 : : * \throws PalException::LayerExists 111 : : */ 112 : : Layer *addLayer( QgsAbstractLabelProvider *provider, const QString &layerName, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, bool displayAll = false ); 113 : : 114 : : /** 115 : : * \brief remove a layer 116 : : * 117 : : * \param layer layer to remove 118 : : */ 119 : : void removeLayer( Layer *layer ); 120 : : 121 : : typedef bool ( *FnIsCanceled )( void *ctx ); 122 : : 123 : : //! Register a function that returns whether this job has been canceled - PAL calls it during the computation 124 : : void registerCancellationCallback( FnIsCanceled fnCanceled, void *context ); 125 : : 126 : : //! Check whether the job has been canceled 127 : 0 : inline bool isCanceled() { return fnIsCanceled ? fnIsCanceled( fnIsCanceledContext ) : false; } 128 : : 129 : : /** 130 : : * Extracts the labeling problem for the specified map \a extent - only features within this 131 : : * extent will be considered. The \a mapBoundary argument specifies the actual geometry of the map 132 : : * boundary, which will be used to detect whether a label is visible (or partially visible) in 133 : : * the rendered map. This may differ from \a extent in the case of rotated or non-rectangular 134 : : * maps. 135 : : */ 136 : : std::unique_ptr< Problem > extractProblem( const QgsRectangle &extent, const QgsGeometry &mapBoundary ); 137 : : 138 : : /** 139 : : * Solves the labeling problem, selecting the best candidate locations for all labels and returns a list of these 140 : : * calculated label positions. 141 : : * 142 : : * If \a displayAll is TRUE, then the best positions for ALL labels will be returned, regardless of whether these 143 : : * labels overlap other labels. 144 : : * 145 : : * If the optional \a unlabeled list is specified, it will be filled with a list of all feature labels which could 146 : : * not be placed in the returned solution (e.g. due to overlaps or other constraints). 147 : : * 148 : : * Ownership of the returned labels is not transferred - it resides with the pal object. 149 : : */ 150 : : QList<LabelPosition *> solveProblem( Problem *prob, bool displayAll, QList<pal::LabelPosition *> *unlabeled = nullptr ); 151 : : 152 : : /** 153 : : * Sets whether partial labels show be allowed. 154 : : * 155 : : * \see showPartialLabels() 156 : : */ 157 : : void setShowPartialLabels( bool show ); 158 : : 159 : : /** 160 : : * Returns whether partial labels should be allowed. 161 : : * 162 : : * \see setShowPartialLabels() 163 : : */ 164 : : bool showPartialLabels() const; 165 : : 166 : : /** 167 : : * Returns the maximum number of line label candidate positions per map unit. 168 : : * 169 : : * \see setMaximumLineCandidatesPerMapUnit() 170 : : */ 171 : 0 : double maximumLineCandidatesPerMapUnit() const { return mMaxLineCandidatesPerMapUnit; } 172 : : 173 : : /** 174 : : * Sets the maximum number of line label \a candidates per map unit. 175 : : * 176 : : * \see maximumLineCandidatesPerMapUnit() 177 : : */ 178 : 0 : void setMaximumLineCandidatesPerMapUnit( double candidates ) { mMaxLineCandidatesPerMapUnit = candidates; } 179 : : 180 : : /** 181 : : * Returns the maximum number of polygon label candidate positions per map unit squared. 182 : : * 183 : : * \see setMaximumPolygonCandidatesPerMapUnitSquared() 184 : : */ 185 : 0 : double maximumPolygonCandidatesPerMapUnitSquared() const { return mMaxPolygonCandidatesPerMapUnitSquared; } 186 : : 187 : : /** 188 : : * Sets the maximum number of polygon label \a candidates per map unit squared. 189 : : * 190 : : * \see maximumPolygonCandidatesPerMapUnitSquared() 191 : : */ 192 : 0 : void setMaximumPolygonCandidatesPerMapUnitSquared( double candidates ) { mMaxPolygonCandidatesPerMapUnitSquared = candidates; } 193 : : 194 : : /** 195 : : * Returns the placement engine version, which dictates how the label placement problem is solved. 196 : : * 197 : : * \see setPlacementVersion() 198 : : */ 199 : : QgsLabelingEngineSettings::PlacementEngineVersion placementVersion() const; 200 : : 201 : : /** 202 : : * Sets the placement engine \a version, which dictates how the label placement problem is solved. 203 : : * 204 : : * \see placementVersion() 205 : : */ 206 : : void setPlacementVersion( QgsLabelingEngineSettings::PlacementEngineVersion placementVersion ); 207 : : 208 : : /** 209 : : * Returns the global candidates limit for point features, or 0 if no global limit is in effect. 210 : : * 211 : : * This is an installation-wide setting which applies to all projects, and is set via QSettings. It can 212 : : * be used to place global limits on the number of candidates generated for point features in order 213 : : * to optimise map rendering speeds. 214 : : * 215 : : * \see globalCandidatesLimitLine() 216 : : * \see globalCandidatesLimitPolygon() 217 : : */ 218 : 0 : int globalCandidatesLimitPoint() const { return mGlobalCandidatesLimitPoint; } 219 : : 220 : : /** 221 : : * Returns the global candidates limit for line features, or 0 if no global limit is in effect. 222 : : * 223 : : * This is an installation-wide setting which applies to all projects, and is set via QSettings. It can 224 : : * be used to place global limits on the number of candidates generated for line features in order 225 : : * to optimise map rendering speeds. 226 : : * 227 : : * \see globalCandidatesLimitPolygon() 228 : : * \see globalCandidatesLimitPoint() 229 : : */ 230 : 0 : int globalCandidatesLimitLine() const { return mGlobalCandidatesLimitLine; } 231 : : 232 : : /** 233 : : * Returns the global candidates limit for polygon features, or 0 if no global limit is in effect. 234 : : * 235 : : * This is an installation-wide setting which applies to all projects, and is set via QSettings. It can 236 : : * be used to place global limits on the number of candidates generated for polygon features in order 237 : : * to optimise map rendering speeds. 238 : : * 239 : : * \see globalCandidatesLimitLine() 240 : : * \see globalCandidatesLimitPoint() 241 : : */ 242 : 0 : int globalCandidatesLimitPolygon() const { return mGlobalCandidatesLimitPolygon; } 243 : : 244 : : private: 245 : : 246 : : std::unordered_map< QgsAbstractLabelProvider *, std::unique_ptr< Layer > > mLayers; 247 : : 248 : : QMutex mMutex; 249 : : 250 : : /* 251 : : * POPMUSIC Tuning 252 : : */ 253 : : int mPopmusicR = 30; 254 : : 255 : : int mTabuMaxIt = 4; 256 : : int mTabuMinIt = 2; 257 : : 258 : : int mEjChainDeg = 50; 259 : : int mTenure = 10; 260 : : double mCandListSize = 0.2; 261 : : 262 : : /** 263 : : * \brief show partial labels (cut-off by the map canvas) or not 264 : : */ 265 : : bool mShowPartialLabels = true; 266 : : 267 : : double mMaxLineCandidatesPerMapUnit = 0; 268 : : double mMaxPolygonCandidatesPerMapUnitSquared = 0; 269 : : 270 : : int mGlobalCandidatesLimitPoint = 0; 271 : : int mGlobalCandidatesLimitLine = 0; 272 : : int mGlobalCandidatesLimitPolygon = 0; 273 : : 274 : : QgsLabelingEngineSettings::PlacementEngineVersion mPlacementVersion = QgsLabelingEngineSettings::PlacementEngineVersion2; 275 : : 276 : : //! Callback that may be called from PAL to check whether the job has not been canceled in meanwhile 277 : : FnIsCanceled fnIsCanceled = nullptr; 278 : : //! Application-specific context for the cancellation check function 279 : : void *fnIsCanceledContext = nullptr; 280 : : 281 : : /** 282 : : * Creates a Problem, by extracting labels and generating candidates from the given \a extent. 283 : : * The \a mapBoundary geometry specifies the actual visible region of the map, and is used 284 : : * for pruning candidates which fall outside the visible region. 285 : : */ 286 : : std::unique_ptr< Problem > extract( const QgsRectangle &extent, const QgsGeometry &mapBoundary ); 287 : : 288 : : /** 289 : : * \brief Choose the size of popmusic subpart's 290 : : * \param r subpart size 291 : : */ 292 : : void setPopmusicR( int r ); 293 : : 294 : : /** 295 : : * \brief minimum # of iteration for search method POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN 296 : : * \param min_it Sub part optimization min # of iteration 297 : : */ 298 : : void setMinIt( int min_it ); 299 : : 300 : : /** 301 : : * \brief maximum \# of iteration for search method POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN 302 : : * \param max_it Sub part optimization max # of iteration 303 : : */ 304 : : void setMaxIt( int max_it ); 305 : : 306 : : /** 307 : : * \brief For tabu search : how many iteration a feature will be tabu 308 : : * \param tenure consiser a feature as tabu for tenure iteration after updating feature in solution 309 : : */ 310 : : void setTenure( int tenure ); 311 : : 312 : : /** 313 : : * \brief For *CHAIN, select the max size of a transformation chain 314 : : * \param degree maximum soze of a transformation chain 315 : : */ 316 : : void setEjChainDeg( int degree ); 317 : : 318 : : /** 319 : : * \brief How many candidates will be tested by a tabu iteration 320 : : * \param fact the ration (0..1) of candidates to test 321 : : */ 322 : : void setCandListSize( double fact ); 323 : : 324 : : 325 : : /** 326 : : * Returns the minimum number of iterations used for POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN. 327 : : * \see getMaxIt() 328 : : */ 329 : : int getMinIt(); 330 : : 331 : : /** 332 : : * Returns the maximum number of iterations allowed for POPMUSIC_TABU, POPMUSIC_CHAIN and POPMUSIC_TABU_CHAIN. 333 : : * \see getMinIt() 334 : : */ 335 : : int getMaxIt(); 336 : : 337 : : }; 338 : : 339 : : } // end namespace pal 340 : : 341 : : #endif