QGIS API Documentation  2.12.0-Lyon
pal.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 //#define _VERBOSE_
31 
32 #define _CRT_SECURE_NO_DEPRECATE
33 
34 #include "qgsgeometry.h"
35 #include "pal.h"
36 #include "layer.h"
37 #include "palexception.h"
38 #include "palstat.h"
39 #include "rtree.hpp"
40 #include "costcalculator.h"
41 #include "feature.h"
42 #include "geomfunction.h"
43 #include "labelposition.h"
44 #include "problem.h"
45 #include "pointset.h"
46 #include "internalexception.h"
47 #include "util.h"
48 #include <QTime>
49 #include <cstdarg>
50 #include <iostream>
51 #include <fstream>
52 #include <cfloat>
53 #include <list>
54 
55 namespace pal
56 {
57  GEOSContextHandle_t geosContext()
58  {
60  }
61 
63  {
64  // do not init and exit GEOS - we do it inside QGIS
65  //initGEOS( geosNotice, geosError );
66 
67  fnIsCancelled = 0;
68  fnIsCancelledContext = 0;
69 
70  ejChainDeg = 50;
71  tenure = 10;
72  candListSize = 0.2;
73 
74  tabuMinIt = 3;
75  tabuMaxIt = 4;
76  searchMethod = POPMUSIC_CHAIN;
77  popmusic_r = 30;
78 
79  searchMethod = CHAIN;
80 
81  setSearch( CHAIN );
82 
83  point_p = 8;
84  line_p = 8;
85  poly_p = 8;
86 
87  showPartial = true;
88 
89  std::cout.precision( 12 );
90  std::cerr.precision( 12 );
91 
92  }
93 
94  void Pal::removeLayer( Layer *layer )
95  {
96  if ( !layer )
97  return;
98 
99  mMutex.lock();
100  if ( QgsAbstractLabelProvider* key = mLayers.key( layer, 0 ) )
101  {
102  mLayers.remove( key );
103  delete layer;
104  }
105  mMutex.unlock();
106  }
107 
109  {
110 
111  mMutex.lock();
112 
113  qDeleteAll( mLayers );
114  mLayers.clear();
115  mMutex.unlock();
116 
117  // do not init and exit GEOS - we do it inside QGIS
118  //finishGEOS();
119  }
120 
121  Layer* Pal::addLayer( QgsAbstractLabelProvider* provider, const QString& layerName, Arrangement arrangement, double defaultPriority, bool active, bool toLabel, bool displayAll )
122  {
123  mMutex.lock();
124 
125  Q_ASSERT( !mLayers.contains( provider ) );
126 
127  Layer* layer = new Layer( provider, layerName, arrangement, defaultPriority, active, toLabel, this, displayAll );
128  mLayers.insert( provider, layer );
129  mMutex.unlock();
130 
131  return layer;
132  }
133 
134  typedef struct _featCbackCtx
135  {
140  double bbox_min[2];
141  double bbox_max[2];
142  } FeatCallBackCtx;
143 
144 
145 
146  /*
147  * Callback function
148  *
149  * Extract a specific shape from indexes
150  */
151  bool extractFeatCallback( FeaturePart *ft_ptr, void *ctx )
152  {
153  double amin[2], amax[2];
154 
155  FeatCallBackCtx *context = ( FeatCallBackCtx* ) ctx;
156 
157 #ifdef _DEBUG_FULL_
158  std::cout << "extract feat : " << ft_ptr->getLayer()->getName() << "/" << ft_ptr->getUID() << std::endl;
159 #endif
160 
161  // all feature which are obstacle will be inserted into obstacles
162  if ( ft_ptr->isObstacle() )
163  {
164  ft_ptr->getBoundingBox( amin, amax );
165  context->obstacles->Insert( amin, amax, ft_ptr );
166  }
167 
168  // first do some checks whether to extract candidates or not
169 
170  // feature has to be labeled?
171  if ( !context->layer->labelLayer() )
172  return true;
173 
174  // is the feature well defined? TODO Check epsilon
175  if ( ft_ptr->getLabelWidth() < 0.0000001 || ft_ptr->getLabelHeight() < 0.0000001 )
176  return true;
177 
178  // OK, everything's fine, let's process the feature part
179 
180  // Holes of the feature are obstacles
181  for ( int i = 0; i < ft_ptr->getNumSelfObstacles(); i++ )
182  {
183  ft_ptr->getSelfObstacle( i )->getBoundingBox( amin, amax );
184  context->obstacles->Insert( amin, amax, ft_ptr->getSelfObstacle( i ) );
185 
186  if ( !ft_ptr->getSelfObstacle( i )->getHoleOf() )
187  {
188  std::cout << "ERROR: SHOULD HAVE A PARENT!!!!!" << std::endl;
189  }
190  }
191 
192  // generate candidates for the feature part
194  if ( ft_ptr->setPosition( lPos, context->bbox_min, context->bbox_max, ft_ptr, context->candidates ) )
195  {
196  // valid features are added to fFeats
197  Feats *ft = new Feats();
198  ft->feature = ft_ptr;
199  ft->shape = NULL;
200  ft->lPos = lPos;
201  ft->priority = ft_ptr->calculatePriority();
202  context->fFeats->append( ft );
203  }
204  else
205  {
206  // Others are deleted
207  qDeleteAll( lPos );
208  }
209 
210  return true;
211  }
212 
213 
214 
215 
216  typedef struct _filterContext
217  {
220  } FilterContext;
221 
222  bool filteringCallback( FeaturePart *featurePart, void *ctx )
223  {
224 
225  RTree<LabelPosition*, double, 2, double> *cdtsIndex = (( FilterContext* ) ctx )->cdtsIndex;
226  Pal* pal = (( FilterContext* )ctx )->pal;
227 
228  if ( pal->isCancelled() )
229  return false; // do not continue searching
230 
231  double amin[2], amax[2];
232  featurePart->getBoundingBox( amin, amax );
233 
234  LabelPosition::PruneCtx pruneContext;
235  pruneContext.obstacle = featurePart;
236  pruneContext.pal = pal;
237  cdtsIndex->Search( amin, amax, LabelPosition::pruneCallback, ( void* ) &pruneContext );
238 
239  return true;
240  }
241 
242  Problem* Pal::extract( double lambda_min, double phi_min, double lambda_max, double phi_max )
243  {
244  // to store obstacles
245  RTree<FeaturePart*, double, 2, double> *obstacles = new RTree<FeaturePart*, double, 2, double>();
246 
247  Problem *prob = new Problem();
248 
249  int i, j;
250 
251  double bbx[4];
252  double bby[4];
253 
254  double amin[2];
255  double amax[2];
256 
257  int max_p = 0;
258 
259  LabelPosition* lp;
260 
261  bbx[0] = bbx[3] = amin[0] = prob->bbox[0] = lambda_min;
262  bby[0] = bby[1] = amin[1] = prob->bbox[1] = phi_min;
263  bbx[1] = bbx[2] = amax[0] = prob->bbox[2] = lambda_max;
264  bby[2] = bby[3] = amax[1] = prob->bbox[3] = phi_max;
265 
266  prob->pal = this;
267 
269 
270  FeatCallBackCtx *context = new FeatCallBackCtx();
271  context->fFeats = fFeats;
272  context->obstacles = obstacles;
273  context->candidates = prob->candidates;
274 
275  context->bbox_min[0] = amin[0];
276  context->bbox_min[1] = amin[1];
277 
278  context->bbox_max[0] = amax[0];
279  context->bbox_max[1] = amax[1];
280 
281  // first step : extract features from layers
282 
283  int previousFeatureCount = 0;
284 
285  QStringList layersWithFeaturesInBBox;
286 
287  mMutex.lock();
288  Q_FOREACH ( Layer* layer, mLayers.values() )
289  {
290  if ( !layer )
291  {
292  // invalid layer name
293  continue;
294  }
295 
296  // only select those who are active
297  if ( !layer->active() )
298  continue;
299 
300  // check for connected features with the same label text and join them
301  if ( layer->mergeConnectedLines() )
302  layer->joinConnectedFeatures();
303 
304  layer->chopFeaturesAtRepeatDistance();
305 
306  // find features within bounding box and generate candidates list
307  context->layer = layer;
308  context->layer->mMutex.lock();
309  context->layer->rtree->Search( amin, amax, extractFeatCallback, ( void* ) context );
310  context->layer->mMutex.unlock();
311 
312  if ( context->fFeats->size() - previousFeatureCount > 0 )
313  {
314  layersWithFeaturesInBBox << layer->name();
315  }
316  previousFeatureCount = context->fFeats->size();
317  }
318  delete context;
319  mMutex.unlock();
320 
321  prob->nbLabelledLayers = layersWithFeaturesInBBox.size();
322  prob->labelledLayersName = layersWithFeaturesInBBox;
323 
324  if ( fFeats->size() == 0 )
325  {
326 #ifdef _VERBOSE_
327  std::cout << std::endl << "Empty problem" << std::endl;
328 #endif
329  delete fFeats;
330  delete prob;
331  delete obstacles;
332  return NULL;
333  }
334 
335  prob->nbft = fFeats->size();
336  prob->nblp = 0;
337  prob->featNbLp = new int [prob->nbft];
338  prob->featStartId = new int [prob->nbft];
339  prob->inactiveCost = new double[prob->nbft];
340 
341  Feats *feat;
342 
343 #ifdef _VERBOSE_
344  std::cout << "FIRST NBFT : " << prob->nbft << std::endl;
345 #endif
346 
347  // Filtering label positions against obstacles
348  amin[0] = amin[1] = -DBL_MAX;
349  amax[0] = amax[1] = DBL_MAX;
350  FilterContext filterCtx;
351  filterCtx.cdtsIndex = prob->candidates;
352  filterCtx.pal = this;
353  obstacles->Search( amin, amax, filteringCallback, ( void* ) &filterCtx );
354 
355  if ( isCancelled() )
356  {
357  Q_FOREACH ( Feats* feat, *fFeats )
358  {
359  qDeleteAll( feat->lPos );
360  feat->lPos.clear();
361  }
362 
363  qDeleteAll( *fFeats );
364  delete fFeats;
365  delete prob;
366  delete obstacles;
367  return 0;
368  }
369 
370  int idlp = 0;
371  for ( i = 0; i < prob->nbft; i++ ) /* foreach feature into prob */
372  {
373  feat = fFeats->takeFirst();
374 
375  prob->featStartId[i] = idlp;
376  prob->inactiveCost[i] = pow( 2, 10 - 10 * feat->priority );
377 
378  switch ( feat->feature->getGeosType() )
379  {
380  case GEOS_POINT:
381  max_p = point_p;
382  break;
383  case GEOS_LINESTRING:
384  max_p = line_p;
385  break;
386  case GEOS_POLYGON:
387  max_p = poly_p;
388  break;
389  }
390 
391  // sort candidates by cost, skip less interesting ones, calculate polygon costs (if using polygons)
392  max_p = CostCalculator::finalizeCandidatesCosts( feat, max_p, obstacles, bbx, bby );
393 
394  // only keep the 'max_p' best candidates
395  while ( feat->lPos.count() > max_p )
396  {
397  // TODO remove from index
398  feat->lPos.last()->removeFromIndex( prob->candidates );
399  delete feat->lPos.takeLast();
400  }
401 
402  // update problem's # candidate
403  prob->featNbLp[i] = feat->lPos.count();
404  prob->nblp += feat->lPos.count();
405 
406  // add all candidates into a rtree (to speed up conflicts searching)
407  for ( j = 0; j < feat->lPos.count(); j++, idlp++ )
408  {
409  lp = feat->lPos[j];
410  //lp->insertIntoIndex(prob->candidates);
411  lp->setProblemIds( i, idlp ); // bugfix #1 (maxence 10/23/2008)
412  }
413  fFeats->append( feat );
414  }
415 
416  int nbOverlaps = 0;
417 
418  while ( fFeats->size() > 0 ) // foreach feature
419  {
420  if ( isCancelled() )
421  {
422  Q_FOREACH ( Feats* feat, *fFeats )
423  {
424  qDeleteAll( feat->lPos );
425  feat->lPos.clear();
426  }
427 
428  qDeleteAll( *fFeats );
429  delete fFeats;
430  delete prob;
431  delete obstacles;
432  return 0;
433  }
434 
435  feat = fFeats->takeFirst();
436  while ( !feat->lPos.isEmpty() ) // foreach label candidate
437  {
438  lp = feat->lPos.takeFirst();
439  lp->resetNumOverlaps();
440 
441  // make sure that candidate's cost is less than 1
442  lp->validateCost();
443 
444  prob->addCandidatePosition( lp );
445  //prob->feat[idlp] = j;
446 
447  lp->getBoundingBox( amin, amax );
448 
449  // lookup for overlapping candidate
450  prob->candidates->Search( amin, amax, LabelPosition::countOverlapCallback, ( void* ) lp );
451 
452  nbOverlaps += lp->getNumOverlaps();
453  }
454  delete feat;
455  }
456  delete fFeats;
457 
458  //delete candidates;
459  delete obstacles;
460 
461 
462  nbOverlaps /= 2;
463  prob->all_nblp = prob->nblp;
464  prob->nbOverlap = nbOverlaps;
465 
466 
467 #ifdef _VERBOSE_
468  std::cout << "nbOverlap: " << prob->nbOverlap << std::endl;
469  std::cerr << prob->nbft << "\t"
470  << prob->nblp << "\t"
471  << prob->nbOverlap << "\t";
472 #endif
473 
474  return prob;
475  }
476 
477  /*
478  * BIG MACHINE
479  */
480  std::list<LabelPosition*>* Pal::labeller( double bbox[4], PalStat **stats, bool displayAll )
481  {
482 #ifdef _DEBUG_
483  std::cout << "LABELLER (selection)" << std::endl;
484 #endif
485 
486  Problem *prob;
487 
488  SearchMethod old_searchMethod = searchMethod;
489 
490  if ( displayAll )
491  {
493  }
494 
495 #ifdef _VERBOSE_
496  clock_t start = clock();
497  double create_time;
498  std::cout << std::endl << "bbox: " << bbox[0] << " " << bbox[1] << " " << bbox[2] << " " << bbox[3] << std::endl;
499 #endif
500 
501  QTime t;
502  t.start();
503 
504  // First, extract the problem
505  if (( prob = extract( bbox[0], bbox[1], bbox[2], bbox[3] ) ) == NULL )
506  {
507  // nothing to be done => return an empty result set
508  if ( stats )
509  ( *stats ) = new PalStat();
510  return new std::list<LabelPosition*>();
511  }
512 
513  std::cout << "PAL EXTRACT: " << t.elapsed() / 1000.0 << " s" << std::endl;
514  t.restart();
515 
516  // reduce number of candidates
517  // (remove candidates which surely won't be used)
518  prob->reduce();
519 
520 #ifdef _VERBOSE_
521  std::cerr << prob->nblp << "\t"
522  << prob->nbOverlap;
523 #endif
524 
525 
526  prob->displayAll = displayAll;
527 
528 #ifdef _VERBOSE_
529  create_time = double( clock() - start ) / double( CLOCKS_PER_SEC );
530 
531  std::cout << std::endl << "Problem : " << prob->nblp << " candidates for " << prob->nbft << " features makes " << prob->nbOverlap << " overlaps" << std::endl;
532  std::cout << std::endl << "Times:" << std::endl << " to create problem: " << create_time << std::endl;
533 #endif
534 
535  // search a solution
536  if ( searchMethod == FALP )
537  prob->init_sol_falp();
538  else if ( searchMethod == CHAIN )
539  prob->chain_search();
540  else
541  prob->popmusic();
542 
543  std::cout << "PAL SEARCH (" << searchMethod << "): " << t.elapsed() / 1000.0 << " s" << std::endl;
544  t.restart();
545 
546  // Post-Optimization
547  //prob->post_optimization();
548 
549 
550  std::list<LabelPosition*> * solution = prob->getSolution( displayAll );
551 
552  if ( stats )
553  *stats = prob->getStats();
554 
555 #ifdef _VERBOSE_
556  clock_t total_time = clock() - start;
557  std::cout << " Total time: " << double( total_time ) / double( CLOCKS_PER_SEC ) << std::endl;
558  std::cerr << "\t" << create_time << "\t" << double( total_time ) / double( CLOCKS_PER_SEC ) << std::endl;
559 #endif
560 
561  delete prob;
562 
563 
564  if ( displayAll )
565  {
566  setSearch( old_searchMethod );
567  }
568 
569  return solution;
570  }
571 
572  void Pal::registerCancellationCallback( Pal::FnIsCancelled fnCancelled, void *context )
573  {
574  fnIsCancelled = fnCancelled;
575  fnIsCancelledContext = context;
576  }
577 
578  Problem* Pal::extractProblem( double bbox[4] )
579  {
580  return extract( bbox[0], bbox[1], bbox[2], bbox[3] );
581  }
582 
583  std::list<LabelPosition*>* Pal::solveProblem( Problem* prob, bool displayAll )
584  {
585  if ( prob == NULL )
586  return new std::list<LabelPosition*>();
587 
588  prob->reduce();
589 
590  try
591  {
592  if ( searchMethod == FALP )
593  prob->init_sol_falp();
594  else if ( searchMethod == CHAIN )
595  prob->chain_search();
596  else
597  prob->popmusic();
598  }
599  catch ( InternalException::Empty )
600  {
601  return new std::list<LabelPosition*>();
602  }
603 
604  return prob->getSolution( displayAll );
605  }
606 
607 
608  void Pal::setPointP( int point_p )
609  {
610  if ( point_p > 0 )
611  this->point_p = point_p;
612  }
613 
614  void Pal::setLineP( int line_p )
615  {
616  if ( line_p > 0 )
617  this->line_p = line_p;
618  }
619 
620  void Pal::setPolyP( int poly_p )
621  {
622  if ( poly_p > 0 )
623  this->poly_p = poly_p;
624  }
625 
626 
627  void Pal::setMinIt( int min_it )
628  {
629  if ( min_it >= 0 )
630  tabuMinIt = min_it;
631  }
632 
633  void Pal::setMaxIt( int max_it )
634  {
635  if ( max_it > 0 )
636  tabuMaxIt = max_it;
637  }
638 
639  void Pal::setPopmusicR( int r )
640  {
641  if ( r > 0 )
642  popmusic_r = r;
643  }
644 
645  void Pal::setEjChainDeg( int degree )
646  {
647  this->ejChainDeg = degree;
648  }
649 
650  void Pal::setTenure( int tenure )
651  {
652  this->tenure = tenure;
653  }
654 
655  void Pal::setCandListSize( double fact )
656  {
657  this->candListSize = fact;
658  }
659 
660  void Pal::setShowPartial( bool show )
661  {
662  this->showPartial = show;
663  }
664 
666  {
667  return point_p;
668  }
669 
671  {
672  return line_p;
673  }
674 
676  {
677  return poly_p;
678  }
679 
680  int Pal::getMinIt()
681  {
682  return tabuMaxIt;
683  }
684 
685  int Pal::getMaxIt()
686  {
687  return tabuMinIt;
688  }
689 
691  {
692  return showPartial;
693  }
694 
696  {
697  return searchMethod;
698  }
699 
701  {
702  switch ( method )
703  {
704  case POPMUSIC_CHAIN:
705  searchMethod = method;
706  popmusic_r = 30;
707  tabuMinIt = 2;
708  tabuMaxIt = 4;
709  tenure = 10;
710  ejChainDeg = 50;
711  candListSize = 0.2;
712  break;
713  case CHAIN:
714  searchMethod = method;
715  ejChainDeg = 50;
716  break;
717  case POPMUSIC_TABU:
718  searchMethod = method;
719  popmusic_r = 25;
720  tabuMinIt = 2;
721  tabuMaxIt = 4;
722  tenure = 10;
723  ejChainDeg = 50;
724  candListSize = 0.2;
725  break;
726  case POPMUSIC_TABU_CHAIN:
727  searchMethod = method;
728  popmusic_r = 25;
729  tabuMinIt = 2;
730  tabuMaxIt = 4;
731  tenure = 10;
732  ejChainDeg = 50;
733  candListSize = 0.2;
734  break;
735  case FALP:
736  searchMethod = method;
737  break;
738  default:
739  std::cerr << "Unknown search method..." << std::endl;
740  }
741  }
742 
743 } // namespace pal
744 
void removeLayer(Layer *layer)
remove a layer
Definition: pal.cpp:94
PointSet * getHoleOf()
Returns NULL if this isn't a hole.
Definition: pointset.h:121
std::list< LabelPosition * > * solveProblem(Problem *prob, bool displayAll)
Definition: pal.cpp:583
FeaturePart * feature
Definition: util.h:59
Definition: pal.h:70
double getLabelHeight() const
Definition: feature.h:171
double calculatePriority() const
Calculates the priority for the feature.
Definition: feature.cpp:1433
bool labelLayer() const
Returns whether the layer will be labeled or not.
Definition: layer.h:141
int getNumSelfObstacles() const
Get number of holes (inner rings) - they are considered as obstacles.
Definition: feature.h:183
friend class Problem
Definition: pal.h:113
static bool countOverlapCallback(LabelPosition *lp, void *ctx)
A layer of spacial entites.
Definition: layer.h:57
void setPointP(int point_p)
set # candidates to generate for points features Higher the value is, longer Pal::labeller will spend...
Definition: pal.cpp:608
RTree< LabelPosition *, double, 2, double > * cdtsIndex
Definition: pal.cpp:218
void setPolyP(int poly_p)
set maximum # candidates to generate for polygon features Higher the value is, longer Pal::labeller w...
Definition: pal.cpp:620
Layer * layer
Definition: pal.cpp:136
void popmusic()
popmusic framework
Definition: problem.cpp:427
Pal main class.
Definition: pal.h:111
bool isCancelled()
Check whether the job has been cancelled.
Definition: pal.h:171
is slower and best than TABU, worse and faster than TABU_CHAIN
Definition: pal.h:69
double getLabelWidth() const
Definition: feature.h:170
QLinkedList< Feats * > * fFeats
Definition: pal.cpp:137
void unlock()
double bbox_min[2]
Definition: pal.cpp:140
int getLineP()
get maximum # candidates to generate for line features
Definition: pal.cpp:670
std::list< LabelPosition * > * getSolution(bool returnInactive)
Definition: problem.cpp:2619
PointSet * shape
Definition: util.h:60
is a little bit better than CHAIN but slower
Definition: pal.h:68
int size() const
bool(* FnIsCancelled)(void *ctx)
Definition: pal.h:165
int elapsed() const
int setPosition(QList< LabelPosition * > &lPos, double bbox_min[2], double bbox_max[2], PointSet *mapShape, RTree< LabelPosition *, double, 2, double > *candidates)
Generic method to generate candidates.
Definition: feature.cpp:1234
void chain_search()
Test with very-large scale neighborhood.
Definition: problem.cpp:2456
void setSearch(SearchMethod method)
Select the search method to use.
Definition: pal.cpp:700
RTree< FeaturePart *, double, 2, double > * obstacles
Definition: pal.cpp:138
is the best but slowest
Definition: pal.h:67
int getPointP()
get # candidates to generate for point features
Definition: pal.cpp:665
int restart()
Problem * extractProblem(double bbox[4])
Definition: pal.cpp:578
GEOSContextHandle_t geosContext()
Get GEOS context handle to be used in all GEOS library calls with reentrant API.
Definition: pal.cpp:57
For usage in problem solving algorithm.
Definition: util.h:50
double priority
Definition: util.h:61
Main class to handle feature.
Definition: feature.h:79
The QgsAbstractLabelProvider class is an interface class.
friend class Layer
Definition: pal.h:115
static bool pruneCallback(LabelPosition *lp, void *ctx)
Check whether the candidate in ctx overlap with obstacle feat.
RTree< LabelPosition *, double, 2, double > * candidates
Definition: pal.cpp:139
bool extractFeatCallback(FeaturePart *ft_ptr, void *ctx)
Definition: pal.cpp:151
void lock()
void setShowPartial(bool show)
Set flag show partial label.
Definition: pal.cpp:660
void getBoundingBox(double min[2], double max[2]) const
Definition: pointset.h:114
PalStat * getStats()
Definition: problem.cpp:2653
std::list< LabelPosition * > * labeller(double bbox[4], PalStat **stats, bool displayAll)
the labeling machine Will extract all active layers
Definition: pal.cpp:480
bool getShowPartial()
Get flag show partial label.
Definition: pal.cpp:690
Arrangement
The way to arrange labels against spatial entities.
Definition: pal.h:77
double bbox_max[2]
Definition: pal.cpp:141
static GEOSContextHandle_t getGEOSHandler()
Return GEOS context handle.
~Pal()
delete an instance
Definition: pal.cpp:108
struct pal::_filterContext FilterContext
void init_sol_falp()
Definition: problem.cpp:305
FeaturePart * getSelfObstacle(int i)
Get hole (inner ring) - considered as obstacle.
Definition: feature.h:185
Summury of problem.
Definition: palstat.h:41
Layer * addLayer(QgsAbstractLabelProvider *provider, const QString &layerName, Arrangement arrangement, double defaultPriority, bool active, bool toLabel, bool displayAll=false)
add a new layer
Definition: pal.cpp:121
SearchMethod getSearch()
get the search method in use
Definition: pal.cpp:695
Pal()
Create an new pal instance.
Definition: pal.cpp:62
Represent a problem.
Definition: problem.h:93
bool filteringCallback(FeaturePart *featurePart, void *ctx)
Definition: pal.cpp:222
void start()
void setLineP(int line_p)
set maximum # candidates to generate for lines features Higher the value is, longer Pal::labeller wil...
Definition: pal.cpp:614
static int finalizeCandidatesCosts(Feats *feat, int max_p, RTree< pal::FeaturePart *, double, 2, double > *obstacles, double bbx[4], double bby[4])
Sort candidates by costs, skip the worse ones, evaluate polygon candidates.
void reduce()
Definition: problem.cpp:150
int getPolyP()
get maximum # candidates to generate for polygon features
Definition: pal.cpp:675
SearchMethod
Search method to use.
Definition: pal.h:64
struct pal::_featCbackCtx FeatCallBackCtx
bool isObstacle()
Definition: feature.h:178
is the worst but fastest method
Definition: pal.h:66
QList< LabelPosition * > lPos
Definition: util.h:62
Thrown when trying to access an empty dada set.
int size() const
void registerCancellationCallback(FnIsCancelled fnCancelled, void *context)
Register a function that returns whether this job has been cancelled - PAL calls it during the comput...
Definition: pal.cpp:572
void append(const T &value)