38 #define _CRT_SECURE_NO_DEPRECATE
54 #include "linkedlist.hpp"
74 va_start( list, fmt );
75 vfprintf( stderr, fmt, list );
82 va_start( list, fmt );
83 vfprintf( stdout, fmt, list );
98 fnIsCancelledContext = 0;
113 searchMethod =
CHAIN;
126 std::cout.precision( 12 );
127 std::cerr.precision( 12 );
141 if ( strcmp(( *it )->name, lyrName ) == 0 )
157 layers->removeOne( layer );
168 while ( layers->size() > 0 )
170 delete layers->front();
182 Layer *
Pal::addLayer(
const char *lyrName,
double min_scale,
double max_scale,
Arrangement arrangement,
Units label_unit,
double defaultPriority,
bool obstacle,
bool active,
bool toLabel,
bool displayAll )
188 std::cout <<
"Pal::addLayer" << std::endl;
189 std::cout <<
"lyrName:" << lyrName << std::endl;
190 std::cout <<
"nbLayers:" << layers->size() << std::endl;
195 if ( strcmp(( *it )->name, lyrName ) == 0 )
204 lyr =
new Layer( lyrName, min_scale, max_scale, arrangement, label_unit, defaultPriority, obstacle, active, toLabel,
this, displayAll );
205 layers->push_back( lyr );
224 std::ofstream *svgmap;
237 double amin[2], amax[2];
248 std::cout <<
"extract feat : " << ft_ptr->
getLayer()->
getName() <<
"/" << ft_ptr->
getUID() << std::endl;
255 context->
obstacles->Insert( amin, amax, ft_ptr );
282 std::cout <<
"ERROR: SHOULD HAVE A PARENT!!!!!" << std::endl;
303 context->
fFeats->push_back( ft );
334 double amin[2], amax[2];
339 pruneContext.
scale = scale;
341 pruneContext.
pal = pal;
361 Problem* Pal::extract(
int nbLayers,
char **layersName,
double *layersFactor,
double lambda_min,
double phi_min,
double lambda_max,
double phi_max,
double scale, std::ofstream *svgmap )
365 RTree<PointSet*, double, 2, double> *obstacles =
new RTree<PointSet*, double, 2, double>();
381 bbx[0] = bbx[3] = amin[0] = prob->bbox[0] = lambda_min;
382 bby[0] = bby[1] = amin[1] = prob->bbox[1] = phi_min;
383 bbx[1] = bbx[2] = amax[0] = prob->bbox[2] = lambda_max;
384 bby[2] = bby[3] = amax[1] = prob->bbox[3] = phi_max;
390 LinkedList<Feats*> *fFeats =
new LinkedList<Feats*> (
ptrFeatsCompare );
393 context->fFeats = fFeats;
394 context->scale = scale;
395 context->obstacles = obstacles;
396 context->candidates = prob->candidates;
398 context->bbox_min[0] = amin[0];
399 context->bbox_min[1] = amin[1];
401 context->bbox_max[0] = amax[0];
402 context->bbox_max[1] = amax[1];
405 context->svgmap = svgmap;
409 std::cout << nbLayers <<
"/" << layers->size() <<
" layers to extract " << std::endl;
410 std::cout <<
"scale is 1:" << scale << std::endl << std::endl;
424 for ( i = 0; i < nbLayers; i++ )
431 && ( layer->obstacle || ( layer->toLabel && layer->isScaleValid( scale ) ) ) )
435 if ( strcmp( layersName[i], layer->name ) == 0 )
438 if ( layer->getMergeConnectedLines() )
439 layer->joinConnectedFeatures();
441 layer->chopFeaturesAtRepeatDistance();
444 context->layer = layer;
445 context->priority = layersFactor[i];
449 *svgmap <<
"<g inkscape:label=\"" << layer->name <<
"\"" << std::endl
450 <<
" inkscape:groupmode=\"layer\"" << std::endl
451 <<
" id=\"" << layer->name <<
"\">" << std::endl << std::endl;
454 context->layer->modMutex->lock();
456 context->layer->modMutex->unlock();
459 *svgmap <<
"</g>" << std::endl << std::endl;
463 std::cout <<
"Layer's name: " << layer->getName() << std::endl;
464 std::cout <<
" scale range: " << layer->getMinScale() <<
"->" << layer->getMaxScale() << std::endl;
465 std::cout <<
" active:" << layer->isToLabel() << std::endl;
466 std::cout <<
" obstacle:" << layer->isObstacle() << std::endl;
467 std::cout <<
" toLabel:" << layer->isToLabel() << std::endl;
468 std::cout <<
" # features: " << layer->getNbFeatures() << std::endl;
469 std::cout <<
" # extracted features: " << context->fFeats->size() - oldNbft << std::endl;
471 if ( context->fFeats->size() - oldNbft > 0 )
473 char *name =
new char[strlen( layer->getName() ) +1];
474 strcpy( name, layer->getName() );
477 oldNbft = context->fFeats->size();
488 prob->nbLabelledLayers = labLayers->
size();
489 prob->labelledLayersName =
new char*[prob->nbLabelledLayers];
490 for ( i = 0; i < prob->nbLabelledLayers; i++ )
492 prob->labelledLayersName[i] = labLayers->
front();
498 if ( fFeats->size() == 0 )
501 std::cout << std::endl <<
"Empty problem" << std::endl;
509 prob->nbft = fFeats->
size();
511 prob->featNbLp =
new int [prob->nbft];
512 prob->featStartId =
new int [prob->nbft];
513 prob->inactiveCost =
new double[prob->nbft];
518 std::cout <<
"FIRST NBFT : " << prob->nbft << std::endl;
522 amin[0] = amin[1] = -DBL_MAX;
523 amax[0] = amax[1] = DBL_MAX;
526 filterCtx.scale = prob->scale;
527 filterCtx.pal =
this;
539 for ( i = 0; i < prob->nbft; i++ )
541 feat = fFeats->pop_front();
543 std::cout <<
"Feature:" << feat->feature->getLayer()->getName() <<
"/" << feat->feature->getUID() <<
" candidates " << feat->nblp << std::endl;
545 prob->featStartId[i] = idlp;
546 prob->inactiveCost[i] = pow( 2, 10 - 10 * feat->priority );
548 switch ( feat->feature->getGeosType() )
553 case GEOS_LINESTRING:
565 std::cout <<
"All costs are set" << std::endl;
568 for ( j = max_p; j < feat->nblp; j++ )
571 feat->lPos[j]->removeFromIndex( prob->candidates );
572 delete feat->lPos[j];
577 prob->featNbLp[i] = feat->nblp;
578 prob->nblp += feat->nblp;
581 for ( j = 0; j < feat->nblp; j++, idlp++ )
585 lp->setProblemIds( i, idlp );
587 fFeats->push_back( feat );
591 std::cout <<
"Malloc problem...." << std::endl;
597 prob->labelpositions =
new LabelPosition*[prob->nblp];
601 std::cout <<
"problem malloc'd" << std::endl;
606 while ( fFeats->size() > 0 )
616 feat = fFeats->pop_front();
617 for ( i = 0; i < feat->nblp; i++, idlp++ )
620 lp->resetNumOverlaps();
625 prob->labelpositions[idlp] = lp;
628 lp->getBoundingBox( amin, amax );
633 nbOverlaps += lp->getNumOverlaps();
635 std::cout <<
"Nb overlap for " << idlp <<
"/" << prob->nblp - 1 <<
" : " << lp->getNumOverlaps() << std::endl;
649 prob->all_nblp = prob->nblp;
650 prob->nbOverlap = nbOverlaps;
654 std::cout <<
"nbOverlap: " << prob->nbOverlap << std::endl;
655 std::cerr << scale <<
"\t"
656 << prob->nbft <<
"\t"
657 << prob->nblp <<
"\t"
658 << prob->nbOverlap <<
"\t";
668 std::cout <<
"LABELLER (active)" << std::endl;
673 int nbLayers = layers->size();
675 char **layersName =
new char*[nbLayers];
676 double *priorities =
new double[nbLayers];
682 layersName[i] = layer->
name;
688 std::list<LabelPosition*> * solution =
labeller( nbLayers, layersName, priorities, scale, bbox, stats, displayAll );
699 std::list<LabelPosition*>*
Pal::labeller(
int nbLayers,
char **layersName,
double *layersFactor,
double scale,
double bbox[4],
PalStat **stats,
bool displayAll )
702 std::cout <<
"LABELLER (selection)" << std::endl;
715 clock_t start = clock();
717 std::cout << std::endl <<
"bbox: " << bbox[0] <<
" " << bbox[1] <<
" " << bbox[2] <<
" " << bbox[3] << std::endl;
722 std::ofstream svgmap(
"pal-map.svg" );
724 svgmap <<
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" << std::endl
725 <<
"<svg" << std::endl
726 <<
"xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" << std::endl
727 <<
"xmlns:cc=\"http://creativecommons.org/ns#\"" << std::endl
728 <<
"xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"" << std::endl
729 <<
"xmlns:svg=\"http://www.w3.org/2000/svg\"" << std::endl
730 <<
"xmlns=\"http://www.w3.org/2000/svg\"" << std::endl
731 <<
"xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"" << std::endl
732 <<
"xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"" << std::endl
733 <<
"width=\"" <<
convert2pt( bbox[2] - bbox[0], scale, dpi ) <<
"\"" << std::endl
734 <<
"height=\"" <<
convert2pt( bbox[3] - bbox[1], scale, dpi ) <<
"\">" << std::endl;
742 if ( scale < 1 || ( prob = extract( nbLayers, layersName, layersFactor, bbox[0], bbox[1], bbox[2], bbox[3], scale,
753 std::cout <<
"Scale is 1:" << scale << std::endl;
755 std::cout <<
"empty problem... finishing" << std::endl;
759 svgmap <<
"</svg>" << std::endl;
766 return new std::list<LabelPosition*>();
769 std::cout <<
"PAL EXTRACT: " << t.
elapsed() / 1000.0 <<
" s" << std::endl;
777 std::cerr << prob->nblp <<
"\t"
782 prob->displayAll = displayAll;
785 create_time = double( clock() - start ) / double( CLOCKS_PER_SEC );
787 std::cout << std::endl <<
"Problem : " << prob->nblp <<
" candidates for " << prob->nbft <<
" features makes " << prob->nbOverlap <<
" overlaps" << std::endl;
788 std::cout << std::endl <<
"Times:" << std::endl <<
" to create problem: " << create_time << std::endl;
792 if ( searchMethod ==
FALP )
794 else if ( searchMethod ==
CHAIN )
799 std::cout <<
"PAL SEARCH (" << searchMethod <<
"): " << t.
elapsed() / 1000.0 <<
" s" << std::endl;
806 std::list<LabelPosition*> * solution = prob->
getSolution( displayAll );
812 prob->drawLabels( svgmap );
813 svgmap <<
"</svg>" << std::endl;
818 clock_t total_time = clock() - start;
819 std::cout <<
" Total time: " << double( total_time ) / double( CLOCKS_PER_SEC ) << std::endl;
820 std::cerr <<
"\t" << create_time <<
"\t" << double( total_time ) / double( CLOCKS_PER_SEC ) << std::endl;
836 fnIsCancelled = fnCancelled;
837 fnIsCancelledContext = context;
844 int nbLayers = layers->size();
846 char **layersName =
new char*[nbLayers];
847 double *priorities =
new double[nbLayers];
853 layersName[i] = layer->
name;
859 Problem* prob = extract( nbLayers, layersName, priorities, bbox[0], bbox[1], bbox[2], bbox[3], scale, NULL );
870 return new std::list<LabelPosition*>();
874 if ( searchMethod ==
FALP )
876 else if ( searchMethod ==
CHAIN )
888 this->point_p = point_p;
894 this->line_p = line_p;
900 this->poly_p = poly_p;
904 void Pal::setMinIt(
int min_it )
910 void Pal::setMaxIt(
int max_it )
916 void Pal::setPopmusicR(
int r )
922 void Pal::setEjChainDeg(
int degree )
924 this->ejChainDeg = degree;
927 void Pal::setTenure(
int tenure )
929 this->tenure = tenure;
932 void Pal::setCandListSize(
double fact )
934 this->candListSize = fact;
946 this->showPartial = show;
994 searchMethod = method;
1003 searchMethod = method;
1007 searchMethod = method;
1016 searchMethod = method;
1025 searchMethod = method;
1028 std::cerr <<
"Unknown search method..." << std::endl;
1049 this->map_unit = map_unit;
void removeLayer(Layer *layer)
remove a layer
void convert2pt(int *x, double scale, int dpi)
PointSet * getHoleOf()
returns NULL if this isn't a hole.
std::list< LabelPosition * > * solveProblem(Problem *prob, bool displayAll)
RTree< PointSet *, double, 2, double > * obstacles
void push_back(const T &value)
bool isScaleValid(double scale)
check if the scal is in the scale range min_scale -> max_scale
double getLabelHeight() const
void setMapUnit(Units map_unit)
set map unit
int getNumSelfObstacles() const
static bool countOverlapCallback(LabelPosition *lp, void *ctx)
A layer of spacial entites.
void setPointP(int point_p)
set # candidates to generate for points features Higher the value is, longer Pal::labeller will spend...
RTree< LabelPosition *, double, 2, double > * cdtsIndex
LinkedList< Feats * > * fFeats
void setPolyP(int poly_p)
set maximum # candidates to generate for polygon features Higher the value is, longer Pal::labeller w...
void popmusic()
popmusic framework
bool isCancelled()
Check whether the job has been cancelled.
double getLabelWidth() const
QList< Layer * > * getLayers()
get all layers
Layer * getLayer()
return the layer that feature belongs to
Problem * extractProblem(double scale, double bbox[4])
int getLineP()
get maximum # candidates to generate for line features
std::list< LabelPosition * > * getSolution(bool returnInactive)
Try to access an unknown layer.
void chain_search()
Test with very-large scale neighborhood.
void setSearch(SearchMethod method)
Select the search method to use.
Layer * getLayer(const char *lyrName)
Look for a layer.
bool filteringCallback(PointSet *pset, void *ctx)
Layer * addLayer(const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel, bool displayAll=false)
add a new layer
int setPosition(double scale, LabelPosition ***lPos, double bbox_min[2], double bbox_max[2], PointSet *mapShape, RTree< LabelPosition *, double, 2, double > *candidates)
generic method to generate candidates This method will call either setPositionFromPoint(), setPositionFromLine or setPositionFromPolygon
int getPointP()
get # candidates to generate for point features
void setDpi(int dpi)
Set map resolution.
PointSet * getSelfObstacle(int i)
void geosNotice(const char *fmt,...)
GEOSContextHandle_t geosContext()
Get GEOS context handle to be used in all GEOS library calls with reentrant API.
For usage in problem solving algorithm.
static int finalizeCandidatesCosts(Feats *feat, int max_p, RTree< PointSet *, double, 2, double > *obstacles, double bbx[4], double bby[4])
sort candidates by costs, skip the worse ones, evaluate polygon candidates
const char * getUID()
get the unique id of the feature
Main class to handle feature.
static bool pruneCallback(LabelPosition *lp, void *ctx)
Check whether the candidate in ctx overlap with obstacle feat.
bool ptrFeatsCompare(Feats *a, Feats *b)
RTree< LabelPosition *, double, 2, double > * candidates
bool extractFeatCallback(FeaturePart *ft_ptr, void *ctx)
enum _searchMethod SearchMethod
Typedef for _Units enumeration.
void setShowPartial(bool show)
Set flag show partial label.
is slower and best than TABU, worse and faster than TABU_CHAIN
void getBoundingBox(double min[2], double max[2]) const
const char * getName()
get layer's name
bool getShowPartial()
Get flag show partial label.
enum _arrangement Arrangement
typedef for _arrangement enumeration
static GEOSContextHandle_t getGEOSHandler()
return GEOS context handle
struct pal::_filterContext FilterContext
Units getMapUnit()
get current map unit
LabelPosition is a candidate feature label position.
SearchMethod getSearch()
get the search method in use
std::list< LabelPosition * > * labeller(double scale, double bbox[4], PalStat **stats, bool displayAll)
the labeling machine Will extract all active layers
Pal()
Create an new pal instance.
void setLineP(int line_p)
set maximum # candidates to generate for lines features Higher the value is, longer Pal::labeller wil...
int getPolyP()
get maximum # candidates to generate for polygon features
enum _Units Units
Typedef for _Units enumeration.
struct pal::_featCbackCtx FeatCallBackCtx
is a little bit better than CHAIN but slower
int getDpi()
get map resolution
is the worst but fastest method
void registerCancellationCallback(FnIsCancelled fnCancelled, void *context)
Register a function that returns whether this job has been cancelled - PAL calls it during the comput...
void geosError(const char *fmt,...)