Skip to content
Permalink
Browse files

Fix many leaks in PAL and simplify code

  • Loading branch information
nyalldawson committed Aug 31, 2015
1 parent 30407c3 commit 0b15d8bc182b5bfdeba78773d03dd0cfd284e95a
@@ -28,6 +28,16 @@
namespace pal
{

bool CostCalculator::candidateSortGrow( const LabelPosition *c1, const LabelPosition *c2 )
{
return c1->cost() < c2->cost();
}

bool CostCalculator::candidateSortShrink( const LabelPosition *c1, const LabelPosition *c2 )
{
return c1->cost() > c2->cost();
}

void CostCalculator::addObstacleCostPenalty( LabelPosition* lp, FeaturePart* obstacle )
{
int n = 0;
@@ -85,7 +95,7 @@ namespace pal

////////

void CostCalculator::setPolygonCandidatesCost( int nblp, LabelPosition **lPos, int max_p, RTree<FeaturePart*, double, 2, double> *obstacles, double bbx[4], double bby[4] )
void CostCalculator::setPolygonCandidatesCost( int nblp, QList< LabelPosition* >& lPos, int max_p, RTree<FeaturePart*, double, 2, double> *obstacles, double bbx[4], double bby[4] )
{
int i;

@@ -98,14 +108,13 @@ namespace pal
for ( i = 0; i < nblp; i++ )
setCandidateCostFromPolygon( lPos[i], obstacles, bbx, bby );

// lPos with big values came fisrts (value = min distance from label to Polygon's Perimeter)
//sort ( (void**) lPos, nblp, costGrow);
sort(( void** ) lPos, nblp, LabelPosition::costShrink );
// lPos with big values came first (value = min distance from label to Polygon's Perimeter)
qSort( lPos.begin(), lPos.end(), candidateSortShrink );


// define the value's range
double cost_max = lPos[0]->cost();
double cost_min = lPos[max_p-1]->cost();
double cost_max = lPos.at( 0 )->cost();
double cost_min = lPos.at( max_p - 1 )->cost();

cost_max -= cost_min;

@@ -128,7 +137,7 @@ namespace pal
//if (cost_max - cost_min < EPSILON)
if ( cost_max > EPSILON )
{
lPos[i]->mCost = 0.0021 - ( lPos[i]->cost() - cost_min ) * normalizer;
lPos[i]->mCost = 0.0021 - ( lPos.at( i )->cost() - cost_min ) * normalizer;
}
else
{
@@ -174,22 +183,22 @@ namespace pal
int CostCalculator::finalizeCandidatesCosts( Feats* feat, int max_p, RTree <FeaturePart*, double, 2, double> *obstacles, double bbx[4], double bby[4] )
{
// If candidates list is smaller than expected
if ( max_p > feat->nblp )
max_p = feat->nblp;
if ( max_p > feat->lPos.count() )
max_p = feat->lPos.count();
//
// sort candidates list, best label to worst
sort(( void** ) feat->lPos, feat->nblp, LabelPosition::costGrow );
qSort( feat->lPos.begin(), feat->lPos.end(), candidateSortGrow );

// try to exclude all conflitual labels (good ones have cost < 1 by pruning)
double discrim = 0.0;
int stop;
do
{
discrim += 1.0;
for ( stop = 0; stop < feat->nblp && feat->lPos[stop]->cost() < discrim; stop++ )
for ( stop = 0; stop < feat->lPos.count() && feat->lPos[stop]->cost() < discrim; stop++ )
;
}
while ( stop == 0 && discrim < feat->lPos[feat->nblp-1]->cost() + 2.0 );
while ( stop == 0 && discrim < feat->lPos.last()->cost() + 2.0 );

if ( discrim > 1.5 )
{
@@ -211,7 +220,7 @@ namespace pal
{
int arrangement = feat->feature->layer()->arrangement();
if ( arrangement == P_FREE || arrangement == P_HORIZ )
setPolygonCandidatesCost( stop, ( LabelPosition** ) feat->lPos, max_p, obstacles, bbx, bby );
setPolygonCandidatesCost( stop, feat->lPos, max_p, obstacles, bbx, bby );
}

// add size penalty (small lines/polygons get higher cost)
@@ -15,6 +15,7 @@
#ifndef COSTCALCULATOR_H
#define COSTCALCULATOR_H

#include <QList>
#include "rtree.hpp"

namespace pal
@@ -27,13 +28,21 @@ namespace pal
/** Increase candidate's cost according to its collision with passed feature */
static void addObstacleCostPenalty( LabelPosition* lp, pal::FeaturePart *obstacle );

static void setPolygonCandidatesCost( int nblp, LabelPosition **lPos, int max_p, RTree<pal::FeaturePart*, double, 2, double> *obstacles, double bbx[4], double bby[4] );
static void setPolygonCandidatesCost( int nblp, QList< LabelPosition* >& lPos, int max_p, RTree<pal::FeaturePart*, double, 2, double> *obstacles, double bbx[4], double bby[4] );

/** Set cost to the smallest distance between lPos's centroid and a polygon stored in geoetry field */
static void setCandidateCostFromPolygon( LabelPosition* lp, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );

/** Sort candidates by costs, skip the worse ones, evaluate polygon candidates */
static int finalizeCandidatesCosts( Feats* feat, int max_p, RTree<pal::FeaturePart *, double, 2, double> *obstacles, double bbx[4], double bby[4] );

/** Sorts label candidates in ascending order of cost
*/
static bool candidateSortGrow( const LabelPosition *c1, const LabelPosition *c2 );

/** Sorts label candidates in descending order of cost
*/
static bool candidateSortShrink( const LabelPosition *c1, const LabelPosition *c2 );
};

/**
@@ -45,6 +45,7 @@
#include "qgis.h"
#include "qgsgeos.h"
#include "qgsmessagelog.h"
#include "costcalculator.h"
#include <QLinkedList>
#include <cmath>
#include <cfloat>
@@ -242,10 +243,9 @@ namespace pal
}
}

int FeaturePart::setPositionOverPoint( double x, double y, LabelPosition ***lPos, double angle, PointSet *mapShape )
int FeaturePart::setPositionOverPoint( double x, double y, QList< LabelPosition*>& lPos, double angle, PointSet *mapShape )
{
int nbp = 1;
*lPos = new LabelPosition *[nbp];

// get from feature
double labelW = mFeature->label_x;
@@ -317,17 +317,15 @@ namespace pal
{
if ( !mapShape->containsLabelCandidate( lx, ly, labelW, labelH, angle ) )
{
delete[] *lPos;
*lPos = 0;
return 0;
}
}

( *lPos )[0] = new LabelPosition( id, lx, ly, labelW, labelH, angle, cost, this, false, quadrantFromOffset() );
lPos << new LabelPosition( id, lx, ly, labelW, labelH, angle, cost, this, false, quadrantFromOffset() );
return nbp;
}

int FeaturePart::setPositionForPoint( double x, double y, LabelPosition ***lPos, double angle, PointSet *mapShape )
int FeaturePart::setPositionForPoint( double x, double y, QList< LabelPosition* >& lPos, double angle, PointSet *mapShape )
{

#ifdef _DEBUG_
@@ -483,18 +481,17 @@ namespace pal

if ( !candidates.isEmpty() )
{
*lPos = new LabelPosition *[candidates.count()];
for ( int i = 0; i < candidates.count(); ++i )
{
( *lPos )[i] = candidates.at( i );
lPos << candidates.at( i );
}
}

return candidates.count();
}

// TODO work with squared distance by removing call to sqrt or dist_euc2d
int FeaturePart::setPositionForLine( LabelPosition ***lPos, PointSet *mapShape )
int FeaturePart::setPositionForLine( QList< LabelPosition* >& lPos, PointSet *mapShape )
{
#ifdef _DEBUG_
std::cout << "SetPosition (line) : " << layer->name << "/" << uid << std::endl;
@@ -669,12 +666,9 @@ namespace pal
delete[] ad;

int nbp = positions.size();
*lPos = new LabelPosition *[nbp];
i = 0;
while ( positions.size() > 0 )
{
( *lPos )[i] = positions.takeFirst();
i++;
lPos << positions.takeFirst();
}

return nbp;
@@ -885,7 +879,7 @@ namespace pal
return newLp;
}

int FeaturePart::setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape )
int FeaturePart::setPositionForLineCurved( QList< LabelPosition* >& lPos, PointSet* mapShape )
{
// label info must be present
if ( mFeature->labelInfo == NULL || mFeature->labelInfo->char_num == 0 )
@@ -976,11 +970,11 @@ namespace pal


int nbp = positions.size();
( *lPos ) = new LabelPosition*[nbp];
for ( int i = 0; i < nbp; i++ )
{
( *lPos )[i] = positions.takeFirst();
lPos << positions.takeFirst();
}

delete[] path_distances;

return nbp;
@@ -1001,7 +995,7 @@ namespace pal
*
*/

int FeaturePart::setPositionForPolygon( LabelPosition ***lPos, PointSet *mapShape )
int FeaturePart::setPositionForPolygon( QList< LabelPosition*>& lPos, PointSet *mapShape )
{

#ifdef _DEBUG_
@@ -1207,10 +1201,9 @@ namespace pal

nbp = positions.size();

( *lPos ) = new LabelPosition*[nbp];
for ( i = 0; i < nbp; i++ )
{
( *lPos )[i] = positions.takeFirst();
lPos << positions.takeFirst();
}

for ( bbid = 0; bbid < j; bbid++ )
@@ -1256,12 +1249,10 @@ namespace pal
}
#endif

int FeaturePart::setPosition( LabelPosition ***lPos,
int FeaturePart::setPosition( QList< LabelPosition*>& lPos,
double bbox_min[2], double bbox_max[2],
PointSet *mapShape, RTree<LabelPosition*, double, 2, double> *candidates )
{
int nbp = 0;
int i;
double bbox[4];

bbox[0] = bbox_min[0];
@@ -1273,25 +1264,23 @@ namespace pal

if ( mFeature->fixedPosition() )
{
nbp = 1;
*lPos = new LabelPosition *[nbp];
( *lPos )[0] = new LabelPosition( 0, mFeature->fixedPosX, mFeature->fixedPosY, mFeature->label_x, mFeature->label_y, angle, 0.0, this );
lPos << new LabelPosition( 0, mFeature->fixedPosX, mFeature->fixedPosY, mFeature->label_x, mFeature->label_y, angle, 0.0, this );
}
else
{
switch ( type )
{
case GEOS_POINT:
if ( mFeature->layer->arrangement() == P_POINT_OVER || mFeature->fixedQuadrant() )
nbp = setPositionOverPoint( x[0], y[0], lPos, angle );
setPositionOverPoint( x[0], y[0], lPos, angle );
else
nbp = setPositionForPoint( x[0], y[0], lPos, angle );
setPositionForPoint( x[0], y[0], lPos, angle );
break;
case GEOS_LINESTRING:
if ( mFeature->layer->arrangement() == P_CURVED )
nbp = setPositionForLineCurved( lPos, mapShape );
setPositionForLineCurved( lPos, mapShape );
else
nbp = setPositionForLine( lPos, mapShape );
setPositionForLine( lPos, mapShape );
break;

case GEOS_POLYGON:
@@ -1302,52 +1291,47 @@ namespace pal
double cx, cy;
mapShape->getCentroid( cx, cy, mFeature->layer->centroidInside() );
if ( mFeature->layer->arrangement() == P_POINT_OVER )
nbp = setPositionOverPoint( cx, cy, lPos, angle, mapShape );
setPositionOverPoint( cx, cy, lPos, angle, mapShape );
else
nbp = setPositionForPoint( cx, cy, lPos, angle, mapShape );
setPositionForPoint( cx, cy, lPos, angle, mapShape );
break;
case P_LINE:
nbp = setPositionForLine( lPos, mapShape );
setPositionForLine( lPos, mapShape );
break;
default:
nbp = setPositionForPolygon( lPos, mapShape );
setPositionForPolygon( lPos, mapShape );
break;
}
}
}

int rnbp = nbp;

// purge candidates that are outside the bbox
for ( i = 0; i < nbp; i++ )

QMutableListIterator< LabelPosition*> i( lPos );
while ( i.hasNext() )
{
LabelPosition* pos = i.next();
bool outside = false;
if ( mFeature->layer->pal->getShowPartial() )
outside = !( *lPos )[i]->isIntersect( bbox );
outside = !pos->isIntersect( bbox );
else
outside = !( *lPos )[i]->isInside( bbox );
outside = !pos->isInside( bbox );
if ( outside )
{
rnbp--;
( *lPos )[i]->setCost( DBL_MAX ); // infinite cost => do not use
i.remove();
delete pos;
}
else // this one is OK
{
( *lPos )[i]->insertIntoIndex( candidates );
pos->insertIntoIndex( candidates );
}
}

sort(( void** )( *lPos ), nbp, LabelPosition::costGrow );

for ( i = rnbp; i < nbp; i++ )
{
delete( *lPos )[i];
}

return rnbp;
qSort( lPos.begin(), lPos.end(), CostCalculator::candidateSortGrow );
return lPos.count();
}

void FeaturePart::addSizePenalty( int nbp, LabelPosition** lPos, double bbx[4], double bby[4] )
void FeaturePart::addSizePenalty( int nbp, QList< LabelPosition* >& lPos, double bbx[4], double bby[4] )
{
if ( !mGeos )
createGeosGeom();
@@ -1402,7 +1386,7 @@ namespace pal
// apply the penalty
for ( int i = 0; i < nbp; i++ )
{
lPos[i]->setCost( lPos[i]->cost() + sizeCost / 100 );
lPos.at( i )->setCost( lPos.at( i )->cost() + sizeCost / 100 );
}
}

0 comments on commit 0b15d8b

Please sign in to comment.
You can’t perform that action at this time.