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_PROBLEM_H 31 #define PAL_PROBLEM_H 32 33 #define SIP_NO_FILE 34 35 36 #include "qgis_core.h" 37 #include <list> 38 #include <QList> 39 #include "palrtree.h" 40 #include <memory> 41 #include <vector> 42 43 namespace pal 44 { 45 46 class LabelPosition; 47 class Label; 48 49 /** 50 * \class pal::Sol 51 * \ingroup core 52 * \brief Chain solution parameters. 53 * \note not available in Python bindings 54 */ 55 56 struct Chain 57 { 58 int degree; 59 double delta; 60 int *feat = nullptr; 61 int *label = nullptr; 62 }; 63 64 /** 65 * \ingroup core 66 * \brief Representation of a labeling problem 67 * \class pal::Problem 68 * \note not available in Python bindings 69 */ 70 class CORE_EXPORT Problem 71 { 72 friend class Pal; 73 74 public: 75 76 /** 77 * Constructor for Problem. 78 * 79 * The \a extent argument specifies the bounds of the incoming coordinates. 80 */ 81 Problem( const QgsRectangle &extent ); 82 83 //Problem(char *lorena_file, bool displayAll); 84 85 ~Problem(); 86 87 //! Problem cannot be copied 88 Problem( const Problem &other ) = delete; 89 //! Problem cannot be copied 90 Problem &operator=( const Problem &other ) = delete; 91 92 /** 93 * Adds a candidate label position to the problem. 94 * \param position label candidate position. Ownership is transferred to Problem. 95 * \since QGIS 2.12 96 */ addCandidatePosition(std::unique_ptr<LabelPosition> position)97 void addCandidatePosition( std::unique_ptr< LabelPosition > position ) { mLabelPositions.emplace_back( std::move( position ) ); } 98 99 /** 100 * Returns the total number of features considered during the labeling problem. 101 */ featureCount()102 std::size_t featureCount() const { return mFeatureCount; } 103 104 /** 105 * Returns the number of candidates generated for the \a feature at the specified index. 106 */ featureCandidateCount(int feature)107 int featureCandidateCount( int feature ) const { return mFeatNbLp[feature]; } 108 109 /** 110 * Returns the candidate corresponding to the specified \a feature and \a candidate index. 111 */ featureCandidate(int feature,int candidate)112 LabelPosition *featureCandidate( int feature, int candidate ) const { return mLabelPositions[ mFeatStartId[feature] + candidate ].get(); } 113 114 void reduce(); 115 116 /** 117 * \brief Test with very-large scale neighborhood 118 */ 119 void chain_search(); 120 121 /** 122 * Solves the labeling problem, selecting the best candidate locations for all labels and returns a list of these 123 * calculated label positions. 124 * 125 * If \a returnInactive is TRUE, then the best positions for ALL labels will be returned, regardless of whether these 126 * labels overlap other labels. 127 * 128 * If the optional \a unlabeled list is specified, it will be filled with a list of all feature labels which could 129 * not be placed in the returned solution (e.g. due to overlaps or other constraints). 130 * 131 * Ownership of the returned labels is not transferred - it resides with the pal object. 132 */ 133 QList<LabelPosition *> getSolution( bool returnInactive, QList<LabelPosition *> *unlabeled = nullptr ); 134 135 /* useful only for postscript post-conversion*/ 136 //void toFile(char *label_file); 137 138 void init_sol_falp(); 139 140 /** 141 * Returns a reference to the list of label positions which correspond to 142 * features with no candidates. 143 * 144 * Ownership of positions added to this list is transferred to the problem. 145 */ positionsWithNoCandidates()146 std::vector< std::unique_ptr< LabelPosition > > *positionsWithNoCandidates() 147 { 148 return &mPositionsWithNoCandidates; 149 } 150 151 /** 152 * Returns the index containing all label candidates. 153 */ allCandidatesIndex()154 PalRtree< LabelPosition > &allCandidatesIndex() { return mAllCandidatesIndex; } 155 156 private: 157 158 /** 159 * Total number of layers containing labels 160 */ 161 int mLayerCount = 0; 162 163 /** 164 * Names of the labelled layers 165 */ 166 QStringList labelledLayersName; 167 168 /** 169 * Total number of active candidates (remaining after reduce()) 170 */ 171 int mTotalCandidates = 0; 172 173 /** 174 * Number of candidates (all, including) 175 */ 176 int mAllNblp = 0; 177 178 /** 179 * Total number of features to label. 180 */ 181 std::size_t mFeatureCount = 0; 182 183 /** 184 * if TRUE, special value -1 is prohibited 185 */ 186 bool mDisplayAll = false; 187 188 /** 189 * Map extent (xmin, ymin, xmax, ymax) 190 */ 191 double mMapExtentBounds[4] = {0, 0, 0, 0}; 192 193 std::vector< std::unique_ptr< LabelPosition > > mLabelPositions; 194 195 PalRtree<LabelPosition> mAllCandidatesIndex; 196 PalRtree<LabelPosition> mActiveCandidatesIndex; 197 198 std::vector< std::unique_ptr< LabelPosition > > mPositionsWithNoCandidates; 199 200 std::vector< int > mFeatStartId; 201 std::vector< int > mFeatNbLp; 202 std::vector< double > mInactiveCost; 203 204 class Sol 205 { 206 public: 207 208 //! Placeholder list for active labels. Will contain label id for active labels, or -1 for empty positions in list 209 std::vector< int > activeLabelIds; 210 211 double totalCost = 0; 212 init(std::size_t featureCount)213 void init( std::size_t featureCount ) 214 { 215 activeLabelIds.resize( featureCount, -1 ); 216 totalCost = 0; 217 } 218 }; 219 220 Sol mSol; 221 double mNbOverlap = 0.0; 222 223 Chain *chain( int seed ); 224 225 Pal *pal = nullptr; 226 227 void solution_cost(); 228 }; 229 230 } // namespace 231 232 #endif 233