QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
layer.cpp
Go to the documentation of this file.
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 #include "pal.h"
31 #include "layer.h"
32 #include "palexception.h"
33 #include "internalexception.h"
34 #include "feature.h"
35 #include "geomfunction.h"
36 #include "util.h"
37 #include "qgslabelingengine.h"
38 #include "qgslogger.h"
39 
40 #include <cmath>
41 #include <vector>
42 
43 using namespace pal;
44 
45 Layer::Layer( QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal, bool displayAll )
46  : mProvider( provider )
47  , mName( name )
48  , mPal( pal )
49  , mActive( active )
50  , mLabelLayer( toLabel )
51  , mDisplayAll( displayAll )
52  , mCentroidInside( false )
53  , mArrangement( arrangement )
54  , mMergeLines( false )
55  , mUpsidedownLabels( Upright )
56 {
57  if ( defaultPriority < 0.0001 )
58  mDefaultPriority = 0.0001;
59  else if ( defaultPriority > 1.0 )
60  mDefaultPriority = 1.0;
61  else
62  mDefaultPriority = defaultPriority;
63 }
64 
66 {
67  mMutex.lock();
68 
69  qDeleteAll( mFeatureParts );
70  qDeleteAll( mObstacleParts );
71 
72  mMutex.unlock();
73 }
74 
75 void Layer::setPriority( double priority )
76 {
77  if ( priority >= 1.0 ) // low priority
78  mDefaultPriority = 1.0;
79  else if ( priority <= 0.0001 )
80  mDefaultPriority = 0.0001; // high priority
81  else
83 }
84 
86 {
87  if ( lf->size().width() < 0 || lf->size().height() < 0 )
88  return false;
89 
90  QMutexLocker locker( &mMutex );
91 
92  if ( mHashtable.contains( lf->id() ) )
93  {
94  //A feature with this id already exists. Don't throw an exception as sometimes,
95  //the same feature is added twice (dateline split with otf-reprojection)
96  return false;
97  }
98 
99  // assign label feature to this PAL layer
100  lf->setLayer( this );
101 
102  // Split MULTI GEOM and Collection in simple geometries
103 
104  bool addedFeature = false;
105 
106  double geom_size = -1, biggest_size = -1;
107  std::unique_ptr<FeaturePart> biggest_part;
108 
109  // break the (possibly multi-part) geometry into simple geometries
110  std::unique_ptr<QLinkedList<const GEOSGeometry *>> simpleGeometries( Util::unmulti( lf->geometry() ) );
111  if ( !simpleGeometries ) // unmulti() failed?
112  {
114  }
115 
116  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
117 
118  bool featureGeomIsObstacleGeom = lf->obstacleSettings().obstacleGeometry().isNull();
119 
120  while ( !simpleGeometries->isEmpty() )
121  {
122  const GEOSGeometry *geom = simpleGeometries->takeFirst();
123 
124  // ignore invalid geometries (e.g. polygons with self-intersecting rings)
125  if ( GEOSisValid_r( geosctxt, geom ) != 1 ) // 0=invalid, 1=valid, 2=exception
126  {
127  continue;
128  }
129 
130  int type = GEOSGeomTypeId_r( geosctxt, geom );
131 
132  if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
133  {
135  }
136 
137  std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom );
138 
139  // ignore invalid geometries
140  if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
141  ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
142  {
143  continue;
144  }
145 
146  // polygons: reorder coordinates
147  if ( type == GEOS_POLYGON && GeomFunction::reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
148  {
149  continue;
150  }
151 
152  // is the feature well defined? TODO Check epsilon
153  bool labelWellDefined = ( lf->size().width() > 0.0000001 && lf->size().height() > 0.0000001 );
154 
155  if ( lf->obstacleSettings().isObstacle() && featureGeomIsObstacleGeom )
156  {
157  //if we are not labeling the layer, only insert it into the obstacle list and avoid an
158  //unnecessary copy
159  if ( mLabelLayer && labelWellDefined )
160  {
161  addObstaclePart( new FeaturePart( *fpart ) );
162  }
163  else
164  {
165  addObstaclePart( fpart.release() );
166  }
167  }
168 
169  // feature has to be labeled?
170  if ( !mLabelLayer || !labelWellDefined )
171  {
172  //nothing more to do for this part
173  continue;
174  }
175 
176  if ( !lf->labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
177  {
178  if ( type == GEOS_LINESTRING )
179  geom_size = fpart->length();
180  else if ( type == GEOS_POLYGON )
181  geom_size = fpart->area();
182 
183  if ( geom_size > biggest_size )
184  {
185  biggest_size = geom_size;
186  biggest_part.reset( fpart.release() );
187  }
188  // don't add the feature part now, do it later
189  }
190  else
191  {
192  // feature part is ready!
193  addFeaturePart( fpart.release(), lf->labelText() );
194  addedFeature = true;
195  }
196  }
197 
198  if ( lf->obstacleSettings().isObstacle() && !featureGeomIsObstacleGeom )
199  {
200  //do the same for the obstacle geometry
201  const QgsGeometry obstacleGeometry = lf->obstacleSettings().obstacleGeometry();
202  for ( auto it = obstacleGeometry.const_parts_begin(); it != obstacleGeometry.const_parts_end(); ++it )
203  {
204  geos::unique_ptr geom = QgsGeos::asGeos( *it );
205 
206  if ( !geom )
207  {
208  QgsDebugMsg( QStringLiteral( "Obstacle geometry passed to PAL labeling engine could not be converted to GEOS! %1" ).arg( ( *it )->asWkt() ) );
209  continue;
210  }
211 
212  // ignore invalid geometries (e.g. polygons with self-intersecting rings)
213  if ( GEOSisValid_r( geosctxt, geom.get() ) != 1 ) // 0=invalid, 1=valid, 2=exception
214  {
215  // this shouldn't happen -- we have already checked this while registering the feature
216  QgsDebugMsg( QStringLiteral( "Obstacle geometry passed to PAL labeling engine is not valid! %1" ).arg( ( *it )->asWkt() ) );
217  continue;
218  }
219 
220  int type = GEOSGeomTypeId_r( geosctxt, geom.get() );
221 
222  if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
223  {
225  }
226 
227  std::unique_ptr<FeaturePart> fpart = qgis::make_unique<FeaturePart>( lf, geom.get() );
228 
229  // ignore invalid geometries
230  if ( ( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
231  ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
232  {
233  continue;
234  }
235 
236  // polygons: reorder coordinates
237  if ( type == GEOS_POLYGON && GeomFunction::reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
238  {
239  continue;
240  }
241 
242  mGeosObstacleGeometries.emplace_back( std::move( geom ) );
243 
244  // feature part is ready!
245  addObstaclePart( fpart.release() );
246  }
247  }
248 
249  locker.unlock();
250 
251  // if using only biggest parts...
252  if ( ( !lf->labelAllParts() || lf->hasFixedPosition() ) && biggest_part )
253  {
254  addFeaturePart( biggest_part.release(), lf->labelText() );
255  addedFeature = true;
256  }
257 
258  // add feature to layer if we have added something
259  if ( addedFeature )
260  {
261  mHashtable.insert( lf->id(), lf );
262  }
263 
264  return addedFeature; // true if we've added something
265 }
266 
267 
268 void Layer::addFeaturePart( FeaturePart *fpart, const QString &labelText )
269 {
270  // add to list of layer's feature parts
271  mFeatureParts << fpart;
272 
273  // add to hashtable with equally named feature parts
274  if ( mMergeLines && !labelText.isEmpty() )
275  {
276  mConnectedHashtable[ labelText ].append( fpart );
277  }
278 }
279 
281 {
282  // add to list of layer's feature parts
283  mObstacleParts.append( fpart );
284 }
285 
286 static FeaturePart *_findConnectedPart( FeaturePart *partCheck, const QVector<FeaturePart *> &otherParts )
287 {
288  // iterate in the rest of the parts with the same label
289  auto it = otherParts.constBegin();
290  while ( it != otherParts.constEnd() )
291  {
292  if ( partCheck->isConnected( *it ) )
293  {
294  // stop checking for other connected parts
295  return *it;
296  }
297  ++it;
298  }
299 
300  return nullptr; // no connected part found...
301 }
302 
304 {
305  // go through all label texts
306  int connectedFeaturesId = 0;
307  for ( auto it = mConnectedHashtable.constBegin(); it != mConnectedHashtable.constEnd(); ++it )
308  {
309  QVector<FeaturePart *> parts = it.value();
310  connectedFeaturesId++;
311 
312  // need to start with biggest parts first, to avoid merging in side branches before we've
313  // merged the whole of the longest parts of the joined network
314  std::sort( parts.begin(), parts.end(), []( FeaturePart * a, FeaturePart * b )
315  {
316  return a->length() > b->length();
317  } );
318 
319  // go one-by-one part, try to merge
320  while ( parts.count() > 1 )
321  {
322  // part we'll be checking against other in this round
323  FeaturePart *partCheck = parts.takeFirst();
324 
325  FeaturePart *otherPart = _findConnectedPart( partCheck, parts );
326  if ( otherPart )
327  {
328  // merge points from partCheck to p->item
329  if ( otherPart->mergeWithFeaturePart( partCheck ) )
330  {
331  mConnectedFeaturesIds.insert( partCheck->featureId(), connectedFeaturesId );
332  mConnectedFeaturesIds.insert( otherPart->featureId(), connectedFeaturesId );
333 
334  mFeatureParts.removeOne( partCheck );
335  delete partCheck;
336  }
337  }
338  }
339  }
340  mConnectedHashtable.clear();
341 }
342 
344 {
345  return mConnectedFeaturesIds.value( featureId, -1 );
346 }
347 
349 {
350  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
351  QLinkedList<FeaturePart *> newFeatureParts;
352  while ( !mFeatureParts.isEmpty() )
353  {
354  std::unique_ptr< FeaturePart > fpart( mFeatureParts.takeFirst() );
355  const GEOSGeometry *geom = fpart->geos();
356  double chopInterval = fpart->repeatDistance();
357 
358  // whether we CAN chop
359  bool canChop = false;
360  double featureLen = 0;
361  if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
362  {
363  featureLen = fpart->length();
364  if ( featureLen > chopInterval )
365  canChop = true;
366  }
367 
368  // whether we SHOULD chop
369  bool shouldChop = canChop;
370  int possibleSegments = 0;
371  if ( canChop )
372  {
373  // never chop into segments smaller than required for the actual label text
374  chopInterval *= std::ceil( fpart->getLabelWidth() / fpart->repeatDistance() );
375 
376  // now work out how many full segments we could chop this line into
377  possibleSegments = static_cast< int >( std::floor( featureLen / chopInterval ) );
378 
379  // ... and use this to work out the actual chop distance for this line. Otherwise, we risk the
380  // situation of:
381  // 1. Line length of 3cm
382  // 2. Repeat distance of 2cm
383  // 3. Label size is 1.5 cm
384  //
385  // 2cm 1cm
386  // /--Label--/----/
387  //
388  // i.e. the labels would be off center and gravitate toward line starts
389  chopInterval = featureLen / possibleSegments;
390 
391  shouldChop = possibleSegments > 1;
392  }
393 
394  if ( shouldChop )
395  {
396  const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( geosctxt, geom );
397 
398  // get number of points
399  unsigned int n;
400  GEOSCoordSeq_getSize_r( geosctxt, cs, &n );
401 
402  // Read points
403  std::vector<Point> points( n );
404  for ( unsigned int i = 0; i < n; ++i )
405  {
406 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
407  GEOSCoordSeq_getXY_r( geosctxt, cs, i, &points[i].x, &points[i].y );
408 #else
409  GEOSCoordSeq_getX_r( geosctxt, cs, i, &points[i].x );
410  GEOSCoordSeq_getY_r( geosctxt, cs, i, &points[i].y );
411 #endif
412  }
413 
414  // Cumulative length vector
415  std::vector<double> len( n, 0 );
416  for ( unsigned int i = 1; i < n; ++i )
417  {
418  double dx = points[i].x - points[i - 1].x;
419  double dy = points[i].y - points[i - 1].y;
420  len[i] = len[i - 1] + std::sqrt( dx * dx + dy * dy );
421  }
422 
423  // Walk along line
424  unsigned int cur = 0;
425  double lambda = 0;
426  std::vector<Point> part;
427 
428  QList<FeaturePart *> repeatParts;
429  repeatParts.reserve( possibleSegments );
430 
431  for ( int segment = 0; segment < possibleSegments; segment++ )
432  {
433  lambda += chopInterval;
434  for ( ; cur < n && lambda > len[cur]; ++cur )
435  {
436  part.push_back( points[cur] );
437  }
438  if ( cur >= n )
439  {
440  // Create final part
441  GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, static_cast< unsigned int >( part.size() ), 2 );
442  for ( unsigned int i = 0; i < part.size(); ++i )
443  {
444 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
445  GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
446 #else
447  GEOSCoordSeq_setX_r( geosctxt, cooSeq, i, part[i].x );
448  GEOSCoordSeq_setY_r( geosctxt, cooSeq, i, part[i].y );
449 #endif
450  }
451  GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
452  FeaturePart *newfpart = new FeaturePart( fpart->feature(), newgeom );
453  newFeatureParts.append( newfpart );
454  repeatParts.push_back( newfpart );
455 
456  break;
457  }
458  double c = ( lambda - len[cur - 1] ) / ( len[cur] - len[cur - 1] );
459  Point p;
460  p.x = points[cur - 1].x + c * ( points[cur].x - points[cur - 1].x );
461  p.y = points[cur - 1].y + c * ( points[cur].y - points[cur - 1].y );
462  part.push_back( p );
463  GEOSCoordSequence *cooSeq = GEOSCoordSeq_create_r( geosctxt, static_cast< unsigned int >( part.size() ), 2 );
464  for ( std::size_t i = 0; i < part.size(); ++i )
465  {
466 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
467  GEOSCoordSeq_setXY_r( geosctxt, cooSeq, i, part[i].x, part[i].y );
468 #else
469  GEOSCoordSeq_setX_r( geosctxt, cooSeq, static_cast< unsigned int >( i ), part[i].x );
470  GEOSCoordSeq_setY_r( geosctxt, cooSeq, static_cast< unsigned int >( i ), part[i].y );
471 #endif
472  }
473 
474  GEOSGeometry *newgeom = GEOSGeom_createLineString_r( geosctxt, cooSeq );
475  FeaturePart *newfpart = new FeaturePart( fpart->feature(), newgeom );
476  newFeatureParts.append( newfpart );
477  part.clear();
478  part.push_back( p );
479  repeatParts.push_back( newfpart );
480  }
481 
482  for ( FeaturePart *partPtr : repeatParts )
483  partPtr->setTotalRepeats( repeatParts.count() );
484  }
485  else
486  {
487  newFeatureParts.append( fpart.release() );
488  }
489  }
490 
491  mFeatureParts = newFeatureParts;
492 }
493 
494 
pal::Layer::mMutex
QMutex mMutex
Definition: layer.h:355
QgsLabelFeature::id
QgsFeatureId id() const
Identifier of the label (unique within the parent label provider)
Definition: qgslabelfeature.h:66
pal::FeaturePart::mergeWithFeaturePart
bool mergeWithFeaturePart(FeaturePart *other)
Merge other (connected) part with this one and save the result in this part (other is unchanged).
Definition: feature.cpp:2226
pal::Layer::mObstacleParts
QList< FeaturePart * > mObstacleParts
List of obstacle parts.
Definition: layer.h:328
pal::Layer::FeaturePart
friend class FeaturePart
Definition: layer.h:64
pal::Layer::addFeaturePart
void addFeaturePart(FeaturePart *fpart, const QString &labelText=QString())
Add newly created feature part into r tree and to the list.
Definition: layer.cpp:268
pal::Layer::connectedFeatureId
int connectedFeatureId(QgsFeatureId featureId) const
Returns the connected feature ID for a label feature ID, which is unique for all features which have ...
Definition: layer.cpp:343
pal::Point::y
double y
Definition: util.h:75
pal::Util::unmulti
static QLinkedList< const GEOSGeometry * > * unmulti(const GEOSGeometry *the_geom)
Definition: util.cpp:40
QgsGeometry::const_parts_end
QgsAbstractGeometry::const_part_iterator const_parts_end() const
Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
Definition: qgsgeometry.cpp:1880
QgsGeometry::isNull
Q_GADGET bool isNull
Definition: qgsgeometry.h:126
pal::Layer::mGeosObstacleGeometries
std::vector< geos::unique_ptr > mGeosObstacleGeometries
Definition: layer.h:330
QgsLabelObstacleSettings::obstacleGeometry
QgsGeometry obstacleGeometry() const
Returns the label's obstacle geometry, if different to the feature geometry.
Definition: qgslabelobstaclesettings.cpp:26
pal::Layer::mHashtable
QHash< QgsFeatureId, QgsLabelFeature * > mHashtable
Lookup table of label features (owned by the label feature provider that created them)
Definition: layer.h:350
QgsGeometry::const_parts_begin
QgsAbstractGeometry::const_part_iterator const_parts_begin() const
Returns STL-style const iterator pointing to the first part of the geometry.
Definition: qgsgeometry.cpp:1873
layer.h
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
pal
Definition: qgsdiagramrenderer.h:49
geos::unique_ptr
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
Definition: qgsgeos.h:79
pal::GeomFunction::reorderPolygon
static int reorderPolygon(int nbPoints, std::vector< double > &x, std::vector< double > &y)
Reorder points to have cross prod ((x,y)[i], (x,y)[i+1), point) > 0 when point is outside.
Definition: geomfunction.cpp:267
QgsGenericSpatialIndex
A generic rtree spatial index based on a libspatialindex backend.
Definition: qgsgenericspatialindex.h:45
pal::Point
Definition: util.h:74
feature.h
QgsLabelFeature::obstacleSettings
const QgsLabelObstacleSettings & obstacleSettings() const
Returns the label's obstacle settings.
Definition: qgslabelfeature.cpp:103
QgsPalLayerSettings::Placement
Placement
Placement modes which determine how label candidates are generated for a feature.
Definition: qgspallabeling.h:222
QgsGeos::asGeos
static geos::unique_ptr asGeos(const QgsGeometry &geometry, double precision=0)
Returns a geos geometry - caller takes ownership of the object (should be deleted with GEOSGeom_destr...
Definition: qgsgeos.cpp:163
QgsLabelFeature::hasFixedPosition
bool hasFixedPosition() const
Whether the label should use a fixed position instead of being automatically placed.
Definition: qgslabelfeature.h:173
pal::FeaturePart::isConnected
bool isConnected(FeaturePart *p2)
Check whether this part is connected with some other part.
Definition: feature.cpp:2209
QgsAbstractLabelProvider
The QgsAbstractLabelProvider class is an interface class.
Definition: qgslabelingengine.h:48
QgsLabelFeature::labelAllParts
bool labelAllParts() const
Returns true if all parts of the feature should be labeled.
Definition: qgslabelfeature.h:485
pal::Layer::mDefaultPriority
double mDefaultPriority
Definition: layer.h:334
pal::Layer::priority
double priority() const
Returns the layer's priority, between 0 and 1.
Definition: layer.h:252
palexception.h
pal::Layer::mConnectedHashtable
QHash< QString, QVector< FeaturePart * > > mConnectedHashtable
Definition: layer.h:352
pal::Layer::mConnectedFeaturesIds
QHash< QgsFeatureId, int > mConnectedFeaturesIds
Definition: layer.h:353
pal::Layer::mFeatureParts
QLinkedList< FeaturePart * > mFeatureParts
List of feature parts.
Definition: layer.h:325
geomfunction.h
pal::FeaturePart
Main class to handle feature.
Definition: feature.h:96
pal::Layer::Layer
Layer(QgsAbstractLabelProvider *provider, const QString &name, QgsPalLayerSettings::Placement arrangement, double defaultPriority, bool active, bool toLabel, Pal *pal, bool displayAll=false)
Create a new layer.
Definition: layer.cpp:45
pal::Layer::joinConnectedFeatures
void joinConnectedFeatures()
Join connected features with the same label text.
Definition: layer.cpp:303
QgsGeos::getGEOSHandler
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:2888
QgsLabelObstacleSettings::isObstacle
bool isObstacle() const
Returns true if the features are obstacles to labels of other layers.
Definition: qgslabelobstaclesettings.h:60
QgsLabelFeature::size
QSizeF size(double angle=0.0) const
Size of the label (in map units)
Definition: qgslabelfeature.cpp:64
QgsLabelFeature::geometry
GEOSGeometry * geometry() const
Gets access to the associated geometry.
Definition: qgslabelfeature.h:69
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
pal::Layer::mMergeLines
bool mMergeLines
Definition: layer.h:345
internalexception.h
QgsLabelFeature::setLayer
void setLayer(pal::Layer *layer)
Assign PAL layer to the label feature. Should be only used internally in PAL.
Definition: qgslabelfeature.h:355
pal::Pal
Main Pal labeling class.
Definition: pal.h:80
pal::InternalException::UnknownGeometry
Thrown when a geometry type is not like expected.
Definition: internalexception.h:87
pal::Layer::chopFeaturesAtRepeatDistance
void chopFeaturesAtRepeatDistance()
Chop layer features at the repeat distance.
Definition: layer.cpp:348
pal::Point::x
double x
Definition: util.h:75
pal.h
pal::Layer::~Layer
virtual ~Layer()
Definition: layer.cpp:65
QgsLabelFeature
The QgsLabelFeature class describes a feature that should be used within the labeling engine.
Definition: qgslabelfeature.h:57
qgslogger.h
pal::Layer::setPriority
void setPriority(double priority)
Sets the layer's priority.
Definition: layer.cpp:75
pal::FeaturePart::featureId
QgsFeatureId featureId() const
Returns the unique ID of the feature.
Definition: feature.cpp:157
pal::Layer::mLabelLayer
bool mLabelLayer
Definition: layer.h:338
pal::Layer::addObstaclePart
void addObstaclePart(FeaturePart *fpart)
Add newly created obstacle part into r tree and to the list.
Definition: layer.cpp:280
util.h
QgsLabelFeature::labelText
QString labelText() const
Text of the label.
Definition: qgslabelfeature.h:343
qgslabelingengine.h
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
pal::Layer::registerFeature
bool registerFeature(QgsLabelFeature *label)
Register a feature in the layer.
Definition: layer.cpp:85