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