QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
labelposition.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 "layer.h"
31 #include "pal.h"
32 #include "costcalculator.h"
33 #include "feature.h"
34 #include "geomfunction.h"
35 #include "labelposition.h"
36 #include "qgsgeos.h"
37 #include "qgsmessagelog.h"
38 #include <cmath>
39 #include <cfloat>
40 
41 using namespace pal;
42 
43 LabelPosition::LabelPosition( int id, double x1, double y1, double w, double h, double alpha, double cost, FeaturePart *feature, bool isReversed, Quadrant quadrant )
44  : id( id )
45  , feature( feature )
46  , probFeat( 0 )
47  , nbOverlap( 0 )
48  , alpha( alpha )
49  , w( w )
50  , h( h )
51  , partId( -1 )
52  , reversed( isReversed )
53  , upsideDown( false )
54  , quadrant( quadrant )
55  , mCost( cost )
56  , mHasObstacleConflict( false )
57  , mUpsideDownCharCount( 0 )
58 {
59  type = GEOS_POLYGON;
60  nbPoints = 4;
61  x.resize( nbPoints );
62  y.resize( nbPoints );
63 
64  // alpha take his value bw 0 and 2*pi rad
65  while ( this->alpha > 2 * M_PI )
66  this->alpha -= 2 * M_PI;
67 
68  while ( this->alpha < 0 )
69  this->alpha += 2 * M_PI;
70 
71  const double beta = this->alpha + M_PI_2;
72 
73  double dx1, dx2, dy1, dy2;
74 
75  dx1 = std::cos( this->alpha ) * w;
76  dy1 = std::sin( this->alpha ) * w;
77 
78  dx2 = std::cos( beta ) * h;
79  dy2 = std::sin( beta ) * h;
80 
81  x[0] = x1;
82  y[0] = y1;
83 
84  x[1] = x1 + dx1;
85  y[1] = y1 + dy1;
86 
87  x[2] = x1 + dx1 + dx2;
88  y[2] = y1 + dy1 + dy2;
89 
90  x[3] = x1 + dx2;
91  y[3] = y1 + dy2;
92 
93  // upside down ? (curved labels are always correct)
94  if ( !feature->layer()->isCurved() &&
95  this->alpha > M_PI_2 && this->alpha <= 3 * M_PI_2 )
96  {
98  {
99  // Turn label upsidedown by inverting boundary points
100  double tx, ty;
101 
102  tx = x[0];
103  ty = y[0];
104 
105  x[0] = x[2];
106  y[0] = y[2];
107 
108  x[2] = tx;
109  y[2] = ty;
110 
111  tx = x[1];
112  ty = y[1];
113 
114  x[1] = x[3];
115  y[1] = y[3];
116 
117  x[3] = tx;
118  y[3] = ty;
119 
120  if ( this->alpha < M_PI )
121  this->alpha += M_PI;
122  else
123  this->alpha -= M_PI;
124 
125  // labels with text shown upside down are not classified as upsideDown,
126  // only those whose boundary points have been inverted
127  upsideDown = true;
128  }
129  }
130 
131  for ( int i = 0; i < nbPoints; ++i )
132  {
133  xmin = std::min( xmin, x[i] );
134  xmax = std::max( xmax, x[i] );
135  ymin = std::min( ymin, y[i] );
136  ymax = std::max( ymax, y[i] );
137  }
138 }
139 
141  : PointSet( other )
142 {
143  id = other.id;
144  mCost = other.mCost;
145  feature = other.feature;
146  probFeat = other.probFeat;
147  nbOverlap = other.nbOverlap;
148 
149  alpha = other.alpha;
150  w = other.w;
151  h = other.h;
152 
153  if ( other.mNextPart )
154  mNextPart = std::make_unique< LabelPosition >( *other.mNextPart );
155 
156  partId = other.partId;
157  upsideDown = other.upsideDown;
158  reversed = other.reversed;
159  quadrant = other.quadrant;
160  mHasObstacleConflict = other.mHasObstacleConflict;
161  mUpsideDownCharCount = other.mUpsideDownCharCount;
162 }
163 
164 bool LabelPosition::isIn( double *bbox )
165 {
166  int i;
167 
168  for ( i = 0; i < 4; i++ )
169  {
170  if ( x[i] >= bbox[0] && x[i] <= bbox[2] &&
171  y[i] >= bbox[1] && y[i] <= bbox[3] )
172  return true;
173  }
174 
175  if ( mNextPart )
176  return mNextPart->isIn( bbox );
177  else
178  return false;
179 }
180 
181 bool LabelPosition::isIntersect( double *bbox )
182 {
183  int i;
184 
185  for ( i = 0; i < 4; i++ )
186  {
187  if ( x[i] >= bbox[0] && x[i] <= bbox[2] &&
188  y[i] >= bbox[1] && y[i] <= bbox[3] )
189  return true;
190  }
191 
192  if ( mNextPart )
193  return mNextPart->isIntersect( bbox );
194  else
195  return false;
196 }
197 
198 bool LabelPosition::intersects( const GEOSPreparedGeometry *geometry )
199 {
200  if ( !mGeos )
201  createGeosGeom();
202 
203  try
204  {
205  if ( GEOSPreparedIntersects_r( QgsGeos::getGEOSHandler(), geometry, mGeos ) == 1 )
206  {
207  return true;
208  }
209  else if ( mNextPart )
210  {
211  return mNextPart->intersects( geometry );
212  }
213  }
214  catch ( GEOSException &e )
215  {
216  qWarning( "GEOS exception: %s", e.what() );
217  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
218  return false;
219  }
220 
221  return false;
222 }
223 
224 bool LabelPosition::within( const GEOSPreparedGeometry *geometry )
225 {
226  if ( !mGeos )
227  createGeosGeom();
228 
229  try
230  {
231  if ( GEOSPreparedContains_r( QgsGeos::getGEOSHandler(), geometry, mGeos ) != 1 )
232  {
233  return false;
234  }
235  else if ( mNextPart )
236  {
237  return mNextPart->within( geometry );
238  }
239  }
240  catch ( GEOSException &e )
241  {
242  qWarning( "GEOS exception: %s", e.what() );
243  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
244  return false;
245  }
246 
247  return true;
248 }
249 
250 bool LabelPosition::isInside( double *bbox )
251 {
252  for ( int i = 0; i < 4; i++ )
253  {
254  if ( !( x[i] >= bbox[0] && x[i] <= bbox[2] &&
255  y[i] >= bbox[1] && y[i] <= bbox[3] ) )
256  return false;
257  }
258 
259  if ( mNextPart )
260  return mNextPart->isInside( bbox );
261  else
262  return true;
263 }
264 
266 {
267  if ( this->probFeat == lp->probFeat ) // bugfix #1
268  return false; // always overlaping itself !
269 
270  // if either this label doesn't cause collisions, or the other one doesn't, then we don't conflict!
273  return false;
274 
275  if ( !nextPart() && !lp->nextPart() )
276  {
277  if ( qgsDoubleNear( alpha, 0 ) && qgsDoubleNear( lp->alpha, 0 ) )
278  {
279  // simple case -- both candidates are oriented to axis, so shortcut with easy calculation
280  return boundingBoxIntersects( lp );
281  }
282  }
283 
284  return isInConflictMultiPart( lp );
285 }
286 
287 bool LabelPosition::isInConflictMultiPart( const LabelPosition *lp ) const
288 {
289  if ( !mMultipartGeos )
290  createMultiPartGeosGeom();
291 
292  if ( !lp->mMultipartGeos )
293  lp->createMultiPartGeosGeom();
294 
295  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
296  try
297  {
298  const bool result = ( GEOSPreparedIntersects_r( geosctxt, preparedMultiPartGeom(), lp->mMultipartGeos ) == 1 );
299  return result;
300  }
301  catch ( GEOSException &e )
302  {
303  qWarning( "GEOS exception: %s", e.what() );
304  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
305  return false;
306  }
307 
308  return false;
309 }
310 
311 int LabelPosition::partCount() const
312 {
313  if ( mNextPart )
314  return mNextPart->partCount() + 1;
315  else
316  return 1;
317 }
318 
319 void LabelPosition::offsetPosition( double xOffset, double yOffset )
320 {
321  for ( int i = 0; i < 4; i++ )
322  {
323  x[i] += xOffset;
324  y[i] += yOffset;
325  }
326 
327  if ( mNextPart )
328  mNextPart->offsetPosition( xOffset, yOffset );
329 
330  invalidateGeos();
331 }
332 
334 {
335  return id;
336 }
337 
338 double LabelPosition::getX( int i ) const
339 {
340  return ( i >= 0 && i < 4 ? x[i] : -1 );
341 }
342 
343 double LabelPosition::getY( int i ) const
344 {
345  return ( i >= 0 && i < 4 ? y[i] : -1 );
346 }
347 
349 {
350  return alpha;
351 }
352 
354 {
355  if ( mCost >= 1 )
356  {
357  mCost -= int ( mCost ); // label cost up to 1
358  }
359 }
360 
362 {
363  return feature;
364 }
365 
366 void LabelPosition::getBoundingBox( double amin[2], double amax[2] ) const
367 {
368  if ( mNextPart )
369  {
370  mNextPart->getBoundingBox( amin, amax );
371  }
372  else
373  {
374  amin[0] = std::numeric_limits<double>::max();
375  amax[0] = std::numeric_limits<double>::lowest();
376  amin[1] = std::numeric_limits<double>::max();
377  amax[1] = std::numeric_limits<double>::lowest();
378  }
379  for ( int c = 0; c < 4; c++ )
380  {
381  if ( x[c] < amin[0] )
382  amin[0] = x[c];
383  if ( x[c] > amax[0] )
384  amax[0] = x[c];
385  if ( y[c] < amin[1] )
386  amin[1] = y[c];
387  if ( y[c] > amax[1] )
388  amax[1] = y[c];
389  }
390 }
391 
393 {
394  mHasObstacleConflict = conflicts;
395  if ( mNextPart )
396  mNextPart->setConflictsWithObstacle( conflicts );
397 }
398 
400 {
401  mHasHardConflict = conflicts;
402  if ( mNextPart )
403  mNextPart->setHasHardObstacleConflict( conflicts );
404 }
405 
407 {
408  double amin[2];
409  double amax[2];
410  getBoundingBox( amin, amax );
411  index.remove( this, QgsRectangle( amin[0], amin[1], amax[0], amax[1] ) );
412 }
413 
415 {
416  double amin[2];
417  double amax[2];
418  getBoundingBox( amin, amax );
419  index.insert( this, QgsRectangle( amin[0], amin[1], amax[0], amax[1] ) );
420 }
421 
422 
423 void LabelPosition::createMultiPartGeosGeom() const
424 {
425  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
426 
427  std::vector< const GEOSGeometry * > geometries;
428  const LabelPosition *tmp1 = this;
429  while ( tmp1 )
430  {
431  const GEOSGeometry *partGeos = tmp1->geos();
432  if ( !GEOSisEmpty_r( geosctxt, partGeos ) )
433  geometries.emplace_back( partGeos );
434  tmp1 = tmp1->nextPart();
435  }
436 
437  const std::size_t partCount = geometries.size();
438  GEOSGeometry **geomarr = new GEOSGeometry*[ partCount ];
439  for ( std::size_t i = 0; i < partCount; ++i )
440  {
441  geomarr[i ] = GEOSGeom_clone_r( geosctxt, geometries[i] );
442  }
443 
444  mMultipartGeos = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOLYGON, geomarr, partCount );
445  delete [] geomarr;
446 }
447 
448 const GEOSPreparedGeometry *LabelPosition::preparedMultiPartGeom() const
449 {
450  if ( !mMultipartGeos )
451  createMultiPartGeosGeom();
452 
453  if ( !mMultipartPreparedGeos )
454  {
455  mMultipartPreparedGeos = GEOSPrepare_r( QgsGeos::getGEOSHandler(), mMultipartGeos );
456  }
457  return mMultipartPreparedGeos;
458 }
459 
460 double LabelPosition::getDistanceToPoint( double xp, double yp ) const
461 {
462  //first check if inside, if so then distance is -1
463  bool contains = false;
464  if ( alpha == 0 )
465  {
466  // easy case -- horizontal label
467  contains = x[0] <= xp && x[1] >= xp && y[0] <= yp && y[2] >= yp;
468  }
469  else
470  {
471  contains = containsPoint( xp, yp );
472  }
473 
474  double distance = -1;
475  if ( !contains )
476  {
477  if ( alpha == 0 )
478  {
479  const double dx = std::max( std::max( x[0] - xp, 0.0 ), xp - x[1] );
480  const double dy = std::max( std::max( y[0] - yp, 0.0 ), yp - y[2] );
481  distance = std::sqrt( dx * dx + dy * dy );
482  }
483  else
484  {
485  distance = std::sqrt( minDistanceToPoint( xp, yp ) );
486  }
487  }
488 
489  if ( mNextPart && distance > 0 )
490  return std::min( distance, mNextPart->getDistanceToPoint( xp, yp ) );
491 
492  return distance;
493 }
494 
496 {
497  if ( !mGeos )
498  createGeosGeom();
499 
500  if ( !line->mGeos )
501  line->createGeosGeom();
502 
503  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
504  try
505  {
506  if ( GEOSPreparedIntersects_r( geosctxt, line->preparedGeom(), mGeos ) == 1 )
507  {
508  return true;
509  }
510  else if ( mNextPart )
511  {
512  return mNextPart->crossesLine( line );
513  }
514  }
515  catch ( GEOSException &e )
516  {
517  qWarning( "GEOS exception: %s", e.what() );
518  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
519  return false;
520  }
521 
522  return false;
523 }
524 
526 {
527  if ( !mGeos )
528  createGeosGeom();
529 
530  if ( !polygon->mGeos )
531  polygon->createGeosGeom();
532 
533  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
534  try
535  {
536  if ( GEOSPreparedIntersects_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1
537  && GEOSPreparedContains_r( geosctxt, polygon->preparedGeom(), mGeos ) != 1 )
538  {
539  return true;
540  }
541  else if ( mNextPart )
542  {
543  return mNextPart->crossesBoundary( polygon );
544  }
545  }
546  catch ( GEOSException &e )
547  {
548  qWarning( "GEOS exception: %s", e.what() );
549  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
550  return false;
551  }
552 
553  return false;
554 }
555 
557 {
558  //effectively take the average polygon intersection cost for all label parts
559  const double totalCost = polygonIntersectionCostForParts( polygon );
560  const int n = partCount();
561  return std::ceil( totalCost / n );
562 }
563 
565 {
566  if ( !mGeos )
567  createGeosGeom();
568 
569  if ( !polygon->mGeos )
570  polygon->createGeosGeom();
571 
572  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
573  try
574  {
575  if ( GEOSPreparedIntersects_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1 )
576  {
577  return true;
578  }
579  }
580  catch ( GEOSException &e )
581  {
582  qWarning( "GEOS exception: %s", e.what() );
583  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
584  }
585 
586  if ( mNextPart )
587  {
588  return mNextPart->intersectsWithPolygon( polygon );
589  }
590  else
591  {
592  return false;
593  }
594 }
595 
596 double LabelPosition::polygonIntersectionCostForParts( PointSet *polygon ) const
597 {
598  if ( !mGeos )
599  createGeosGeom();
600 
601  if ( !polygon->mGeos )
602  polygon->createGeosGeom();
603 
604  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
605  double cost = 0;
606  try
607  {
608  if ( GEOSPreparedIntersects_r( geosctxt, polygon->preparedGeom(), mGeos ) == 1 )
609  {
610  //at least a partial intersection
611  cost += 1;
612 
613  double px, py;
614 
615  // check each corner
616  for ( int i = 0; i < 4; ++i )
617  {
618  px = x[i];
619  py = y[i];
620 
621  for ( int a = 0; a < 2; ++a ) // and each middle of segment
622  {
623  if ( polygon->containsPoint( px, py ) )
624  cost++;
625  px = ( x[i] + x[( i + 1 ) % 4] ) / 2.0;
626  py = ( y[i] + y[( i + 1 ) % 4] ) / 2.0;
627  }
628  }
629 
630  px = ( x[0] + x[2] ) / 2.0;
631  py = ( y[0] + y[2] ) / 2.0;
632 
633  //check the label center. if covered by polygon, cost of 4
634  if ( polygon->containsPoint( px, py ) )
635  cost += 4;
636  }
637  }
638  catch ( GEOSException &e )
639  {
640  qWarning( "GEOS exception: %s", e.what() );
641  QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
642  }
643 
644  //maintain scaling from 0 -> 12
645  cost = 12.0 * cost / 13.0;
646 
647  if ( mNextPart )
648  {
649  cost += mNextPart->polygonIntersectionCostForParts( polygon );
650  }
651 
652  return cost;
653 }
654 
656 {
657  double angleDiff = 0.0;
658  double angleLast = 0.0;
659  LabelPosition *tmp = this;
660  while ( tmp )
661  {
662  if ( tmp != this ) // not first?
663  {
664  double diff = std::fabs( tmp->getAlpha() - angleLast );
665  if ( diff > 2 * M_PI )
666  diff -= 2 * M_PI;
667  diff = std::min( diff, 2 * M_PI - diff ); // difference 350 deg is actually just 10 deg...
668  angleDiff += diff;
669  }
670 
671  angleLast = tmp->getAlpha();
672  tmp = tmp->nextPart();
673  }
674  return angleDiff;
675 }
pal::LabelPosition::quadrant
LabelPosition::Quadrant quadrant
Definition: labelposition.h:368
pal::PointSet::xmax
double xmax
Definition: pointset.h:259
pal::LabelPosition::getY
double getY(int i=0) const
Returns the down-left y coordinate.
Definition: labelposition.cpp:343
pal::LabelPosition::crossesBoundary
bool crossesBoundary(PointSet *polygon) const
Returns true if this label crosses the boundary of the specified polygon.
Definition: labelposition.cpp:525
pal::LabelPosition::Quadrant
Quadrant
Position of label candidate relative to feature.
Definition: labelposition.h:65
pal::LabelPosition::isInConflict
bool isInConflict(const LabelPosition *ls) const
Check whether or not this overlap with another labelPosition.
Definition: labelposition.cpp:265
pal::Layer::isCurved
bool isCurved() const
Returns true if the layer has curved labels.
Definition: layer.h:173
pal::LabelPosition::crossesLine
bool crossesLine(PointSet *line) const
Returns true if this label crosses the specified line.
Definition: labelposition.cpp:495
pal::LabelPosition::partId
int partId
Definition: labelposition.h:359
pal::LabelPosition::isInside
bool isInside(double *bbox)
Is the labelposition inside the bounding-box ?
Definition: labelposition.cpp:250
pal::LabelPosition::within
bool within(const GEOSPreparedGeometry *geometry)
Returns true if the label position is within a geometry.
Definition: labelposition.cpp:224
labelposition.h
pal::LabelPosition::cost
double cost() const
Returns the candidate label position's geographical cost.
Definition: labelposition.h:206
pal::LabelPosition::intersects
bool intersects(const GEOSPreparedGeometry *geometry)
Returns true if the label position intersects a geometry.
Definition: labelposition.cpp:198
pal::LabelPosition
LabelPosition is a candidate feature label position.
Definition: labelposition.h:55
pal::LabelPosition::w
double w
Definition: labelposition.h:356
layer.h
pal::LabelPosition::nextPart
LabelPosition * nextPart() const
Returns the next part of this label position (i.e.
Definition: labelposition.h:277
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
pal::LabelPosition::getFeaturePart
FeaturePart * getFeaturePart() const
Returns the feature corresponding to this labelposition.
Definition: labelposition.cpp:361
pal
Definition: qgsdiagramrenderer.h:50
pal::PointSet::containsPoint
bool containsPoint(double x, double y) const
Tests whether point set contains a specified point.
Definition: pointset.cpp:265
pal::LabelPosition::nbOverlap
int nbOverlap
Definition: labelposition.h:353
pal::FeaturePart::layer
Layer * layer()
Returns the layer that feature belongs to.
Definition: feature.cpp:154
pal::LabelPosition::setHasHardObstacleConflict
void setHasHardObstacleConflict(bool conflicts)
Sets whether the position is marked as having a hard conflict with an obstacle feature.
Definition: labelposition.cpp:399
pal::PointSet::geos
const GEOSGeometry * geos() const
Returns the point set's GEOS geometry.
Definition: pointset.cpp:1084
pal::PointSet::ymin
double ymin
Definition: pointset.h:260
pal::LabelPosition::getBoundingBox
void getBoundingBox(double amin[2], double amax[2]) const
Returns bounding box - amin: xmin,ymin - amax: xmax,ymax.
Definition: labelposition.cpp:366
feature.h
pal::PointSet::minDistanceToPoint
double minDistanceToPoint(double px, double py, double *rx=nullptr, double *ry=nullptr) const
Returns the squared minimum distance between the point set geometry and the point (px,...
Definition: pointset.cpp:860
pal::LabelPosition::upsideDown
bool upsideDown
Definition: labelposition.h:366
pal::FeaturePart::onlyShowUprightLabels
bool onlyShowUprightLabels() const
Returns true if feature's label must be displayed upright.
Definition: feature.cpp:2381
costcalculator.h
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
pal::PointSet::boundingBoxIntersects
bool boundingBoxIntersects(const PointSet *other) const
Returns true if the bounding box of this pointset intersects the bounding box of another pointset.
Definition: pointset.cpp:996
pal::LabelPosition::reversed
bool reversed
Definition: labelposition.h:364
pal::LabelPosition::getId
int getId() const
Returns the id.
Definition: labelposition.cpp:333
pal::PointSet::x
std::vector< double > x
Definition: pointset.h:230
pal::LabelPosition::isIn
bool isIn(double *bbox)
Is the labelposition in the bounding-box ? (intersect or inside????)
Definition: labelposition.cpp:164
pal::PointSet::type
int type
Definition: pointset.h:239
pal::LabelPosition::polygonIntersectionCost
int polygonIntersectionCost(PointSet *polygon) const
Returns cost of position intersection with polygon (testing area of intersection and center).
Definition: labelposition.cpp:556
pal::PointSet::LabelPosition
friend class LabelPosition
Definition: pointset.h:79
geomfunction.h
pal::LabelPosition::h
double h
Definition: labelposition.h:357
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
pal::FeaturePart
Main class to handle feature.
Definition: feature.h:64
PalRtree::remove
void remove(T *data, const QgsRectangle &bounds)
Removes existing data from the spatial index, with the specified bounds.
Definition: palrtree.h:78
Qgis::LabelOverlapHandling::AllowOverlapAtNoCost
@ AllowOverlapAtNoCost
Labels may freely overlap other labels, at no cost.
pal::LabelPosition::preparedMultiPartGeom
const GEOSPreparedGeometry * preparedMultiPartGeom() const
Returns a prepared GEOS representation of all label parts as a multipolygon.
Definition: labelposition.cpp:448
QgsGeos::getGEOSHandler
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:3369
pal::PointSet::createGeosGeom
void createGeosGeom() const
Definition: pointset.cpp:99
pal::LabelPosition::id
int id
Definition: labelposition.h:346
pal::PointSet::mGeos
GEOSGeometry * mGeos
Definition: pointset.h:234
pal::PointSet::y
std::vector< double > y
Definition: pointset.h:231
pal::PointSet
The underlying raw pal geometry class.
Definition: pointset.h:76
pal::PointSet::xmin
double xmin
Definition: pointset.h:258
pal::PointSet::preparedGeom
const GEOSPreparedGeometry * preparedGeom() const
Definition: pointset.cpp:149
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
PalRtree
A rtree spatial index for use in the pal labeling engine.
Definition: palrtree.h:35
QgsLabelFeature::overlapHandling
Qgis::LabelOverlapHandling overlapHandling() const
Returns the technique to use for handling overlapping labels for the feature.
Definition: qgslabelfeature.h:572
pal::LabelPosition::getX
double getX(int i=0) const
Returns the down-left x coordinate.
Definition: labelposition.cpp:338
pal::LabelPosition::validateCost
void validateCost()
Make sure the cost is less than 1.
Definition: labelposition.cpp:353
pal::LabelPosition::removeFromIndex
void removeFromIndex(PalRtree< LabelPosition > &index)
Removes the label position from the specified index.
Definition: labelposition.cpp:406
pal::LabelPosition::setConflictsWithObstacle
void setConflictsWithObstacle(bool conflicts)
Sets whether the position is marked as conflicting with an obstacle feature.
Definition: labelposition.cpp:392
pal::LabelPosition::insertIntoIndex
void insertIntoIndex(PalRtree< LabelPosition > &index)
Inserts the label position into the specified index.
Definition: labelposition.cpp:414
pal.h
pal::PointSet::invalidateGeos
void invalidateGeos() const
Definition: pointset.cpp:161
pal::LabelPosition::feature
FeaturePart * feature
Definition: labelposition.h:348
pal::LabelPosition::getAlpha
double getAlpha() const
Returns the angle to rotate text (in rad).
Definition: labelposition.cpp:348
pal::LabelPosition::intersectsWithPolygon
bool intersectsWithPolygon(PointSet *polygon) const
Returns true if any intersection between polygon and position exists.
Definition: labelposition.cpp:564
pal::LabelPosition::getDistanceToPoint
double getDistanceToPoint(double xp, double yp) const
Gets distance from this label to a point. If point lies inside, returns negative number.
Definition: labelposition.cpp:460
pal::LabelPosition::alpha
double alpha
Definition: labelposition.h:355
pal::FeaturePart::feature
QgsLabelFeature * feature()
Returns the parent feature.
Definition: feature.h:94
pal::LabelPosition::offsetPosition
void offsetPosition(double xOffset, double yOffset)
Shift the label by specified offset.
Definition: labelposition.cpp:319
pal::PointSet::nbPoints
int nbPoints
Definition: pointset.h:229
PalRtree::insert
void insert(T *data, const QgsRectangle &bounds)
Inserts new data into the spatial index, with the specified bounds.
Definition: palrtree.h:59
pal::LabelPosition::probFeat
int probFeat
Definition: labelposition.h:351
pal::LabelPosition::isIntersect
bool isIntersect(double *bbox)
Is the labelposition intersect the bounding-box ?
Definition: labelposition.cpp:181
qgsgeos.h
qgsmessagelog.h
pal::LabelPosition::angleDifferential
double angleDifferential()
Returns the angle differential of all LabelPosition parts.
Definition: labelposition.cpp:655
pal::PointSet::ymax
double ymax
Definition: pointset.h:261