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