More memory management fixes in pal, stack allocation rather than heap

This commit is contained in:
Nyall Dawson 2019-11-29 09:50:00 +10:00
parent 6fdc99be1e
commit 4351c30fa5
3 changed files with 51 additions and 59 deletions

View File

@ -1404,8 +1404,6 @@ std::size_t FeaturePart::createCurvedCandidatesAlongLine( std::vector< std::uniq
std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape ) std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_ptr< LabelPosition > > &lPos, PointSet *mapShape )
{ {
int j;
double labelWidth = getLabelWidth(); double labelWidth = getLabelWidth();
double labelHeight = getLabelHeight(); double labelHeight = getLabelHeight();
@ -1428,23 +1426,20 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
double px, py; double px, py;
double dx; double dx;
double dy; double dy;
int bbid;
double beta; double beta;
double diago = std::sqrt( labelWidth * labelWidth / 4.0 + labelHeight * labelHeight / 4 ); double diago = std::sqrt( labelWidth * labelWidth / 4.0 + labelHeight * labelHeight / 4 );
double rx, ry; double rx, ry;
CHullBox **boxes = new CHullBox*[shapes_final.size()]; std::vector< CHullBox > boxes;
j = 0; boxes.reserve( shapes_final.size() );
// Compute bounding box foreach finalShape // Compute bounding box foreach finalShape
while ( !shapes_final.isEmpty() ) while ( !shapes_final.isEmpty() )
{ {
PointSet *shape = shapes_final.takeFirst(); PointSet *shape = shapes_final.takeFirst();
boxes[j] = shape->compute_chull_bbox(); boxes.emplace_back( shape->compute_chull_bbox() );
if ( shape->parent ) if ( shape->parent )
delete shape; delete shape;
j++;
} }
//dx = dy = min( yrm, xrm ) / 2; //dx = dy = min( yrm, xrm ) / 2;
@ -1461,11 +1456,9 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
do do
{ {
for ( bbid = 0; bbid < j; bbid++ ) for ( CHullBox &box : boxes )
{ {
CHullBox *box = boxes[bbid]; if ( ( box.length * box.width ) > ( xmax - xmin ) * ( ymax - ymin ) * 5 )
if ( ( box->length * box->width ) > ( xmax - xmin ) * ( ymax - ymin ) * 5 )
{ {
// Very Large BBOX (should never occur) // Very Large BBOX (should never occur)
continue; continue;
@ -1486,8 +1479,8 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Free ) if ( mLF->layer()->arrangement() == QgsPalLayerSettings::Free )
{ {
enoughPlace = true; enoughPlace = true;
px = ( box->x[0] + box->x[2] ) / 2 - labelWidth; px = ( box.x[0] + box.x[2] ) / 2 - labelWidth;
py = ( box->y[0] + box->y[2] ) / 2 - labelHeight; py = ( box.y[0] + box.y[2] ) / 2 - labelHeight;
int i, j; int i, j;
// Virtual label: center on bbox center, label size = 2x original size // Virtual label: center on bbox center, label size = 2x original size
@ -1515,24 +1508,24 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
{ {
alpha = 0.0; // HORIZ alpha = 0.0; // HORIZ
} }
else if ( box->length > 1.5 * labelWidth && box->width > 1.5 * labelWidth ) else if ( box.length > 1.5 * labelWidth && box.width > 1.5 * labelWidth )
{ {
if ( box->alpha <= M_PI_4 ) if ( box.alpha <= M_PI_4 )
{ {
alpha = box->alpha; alpha = box.alpha;
} }
else else
{ {
alpha = box->alpha - M_PI_2; alpha = box.alpha - M_PI_2;
} }
} }
else if ( box->length > box->width ) else if ( box.length > box.width )
{ {
alpha = box->alpha - M_PI_2; alpha = box.alpha - M_PI_2;
} }
else else
{ {
alpha = box->alpha; alpha = box.alpha;
} }
beta = std::atan2( labelHeight, labelWidth ) + alpha; beta = std::atan2( labelHeight, labelWidth ) + alpha;
@ -1546,22 +1539,22 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
double px0, py0; double px0, py0;
px0 = box->width / 2.0; px0 = box.width / 2.0;
py0 = box->length / 2.0; py0 = box.length / 2.0;
px0 -= std::ceil( px0 / dx ) * dx; px0 -= std::ceil( px0 / dx ) * dx;
py0 -= std::ceil( py0 / dy ) * dy; py0 -= std::ceil( py0 / dy ) * dy;
for ( px = px0; px <= box->width; px += dx ) for ( px = px0; px <= box.width; px += dx )
{ {
for ( py = py0; py <= box->length; py += dy ) for ( py = py0; py <= box.length; py += dy )
{ {
rx = std::cos( box->alpha ) * px + std::cos( box->alpha - M_PI_2 ) * py; rx = std::cos( box.alpha ) * px + std::cos( box.alpha - M_PI_2 ) * py;
ry = std::sin( box->alpha ) * px + std::sin( box->alpha - M_PI_2 ) * py; ry = std::sin( box.alpha ) * px + std::sin( box.alpha - M_PI_2 ) * py;
rx += box->x[0]; rx += box.x[0];
ry += box->y[0]; ry += box.y[0];
bool candidateAcceptable = ( mLF->permissibleZonePrepared() bool candidateAcceptable = ( mLF->permissibleZonePrepared()
? GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), rx - dlx, ry - dly, labelWidth, labelHeight, alpha ) ? GeomFunction::containsCandidate( mLF->permissibleZonePrepared(), rx - dlx, ry - dly, labelWidth, labelHeight, alpha )
@ -1587,13 +1580,6 @@ std::size_t FeaturePart::createCandidatesForPolygon( std::vector< std::unique_pt
while ( nbp == 0 && numTry < maxTry ); while ( nbp == 0 && numTry < maxTry );
nbp = numberCandidatesGenerated; nbp = numberCandidatesGenerated;
for ( bbid = 0; bbid < j; bbid++ )
{
delete boxes[bbid];
}
delete[] boxes;
} }
else else
{ {

View File

@ -209,12 +209,11 @@ void PointSet::deleteCoords()
y.clear(); y.clear();
} }
PointSet *PointSet::extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty ) std::unique_ptr<PointSet> PointSet::extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty )
{ {
int i, j; int i, j;
PointSet *newShape = new PointSet(); std::unique_ptr<PointSet> newShape = qgis::make_unique< PointSet >();
newShape->type = GEOS_POLYGON; newShape->type = GEOS_POLYGON;
newShape->nbPoints = nbPtSh; newShape->nbPoints = nbPtSh;
newShape->x.resize( newShape->nbPoints ); newShape->x.resize( newShape->nbPoints );
@ -272,8 +271,8 @@ bool PointSet::containsLabelCandidate( double x, double y, double width, double
return GeomFunction::containsCandidate( preparedGeom(), x, y, width, height, alpha ); return GeomFunction::containsCandidate( preparedGeom(), x, y, width, height, alpha );
} }
void PointSet::splitPolygons( QLinkedList<PointSet *> &shapes_toProcess, void PointSet::splitPolygons( QLinkedList<PointSet *> &inputShapes,
QLinkedList<PointSet *> &shapes_final, QLinkedList<PointSet *> &outputShapes,
double xrm, double yrm ) double xrm, double yrm )
{ {
int i, j; int i, j;
@ -313,9 +312,9 @@ void PointSet::splitPolygons( QLinkedList<PointSet *> &shapes_toProcess,
PointSet *shape = nullptr; PointSet *shape = nullptr;
while ( !shapes_toProcess.isEmpty() ) while ( !inputShapes.isEmpty() )
{ {
shape = shapes_toProcess.takeFirst(); shape = inputShapes.takeFirst();
x = shape->x; x = shape->x;
y = shape->y; y = shape->y;
@ -509,33 +508,33 @@ void PointSet::splitPolygons( QLinkedList<PointSet *> &shapes_toProcess,
// check for useless splitting // check for useless splitting
else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp ) else if ( imax == imin || nbPtSh1 <= 2 || nbPtSh2 <= 2 || nbPtSh1 == nbp || nbPtSh2 == nbp )
{ {
shapes_final.append( shape ); outputShapes.append( shape );
} }
else else
{ {
PointSet *newShape = shape->extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ); PointSet *newShape = shape->extractShape( nbPtSh1, imin, imax, fps, fpe, fptx, fpty ).release();
if ( shape->parent ) if ( shape->parent )
newShape->parent = shape->parent; newShape->parent = shape->parent;
else else
newShape->parent = shape; newShape->parent = shape;
shapes_toProcess.append( newShape ); inputShapes.append( newShape );
if ( imax == fps ) if ( imax == fps )
imax = fpe; imax = fpe;
else else
imax = fps; imax = fps;
newShape = shape->extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ); newShape = shape->extractShape( nbPtSh2, imax, imin, fps, fpe, fptx, fpty ).release();
if ( shape->parent ) if ( shape->parent )
newShape->parent = shape->parent; newShape->parent = shape->parent;
else else
newShape->parent = shape; newShape->parent = shape;
shapes_toProcess.append( newShape ); inputShapes.append( newShape );
if ( shape->parent ) if ( shape->parent )
delete shape; delete shape;
@ -543,7 +542,7 @@ void PointSet::splitPolygons( QLinkedList<PointSet *> &shapes_toProcess,
} }
else else
{ {
shapes_final.append( shape ); outputShapes.append( shape );
} }
delete[] pts; delete[] pts;
} }
@ -636,7 +635,7 @@ void PointSet::extendLineByDistance( double startDistance, double endDistance, d
invalidateGeos(); invalidateGeos();
} }
CHullBox *PointSet::compute_chull_bbox() CHullBox PointSet::compute_chull_bbox()
{ {
int i; int i;
int j; int j;
@ -768,18 +767,18 @@ CHullBox *PointSet::compute_chull_bbox()
// best bbox is defined // best bbox is defined
CHullBox *finalBb = new CHullBox(); CHullBox finalBb;
for ( i = 0; i < 16; i = i + 4 ) for ( i = 0; i < 16; i = i + 4 )
{ {
GeomFunction::computeLineIntersection( best_bb[i], best_bb[i + 1], best_bb[i + 2], best_bb[i + 3], GeomFunction::computeLineIntersection( best_bb[i], best_bb[i + 1], best_bb[i + 2], best_bb[i + 3],
best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16], best_bb[( i + 4 ) % 16], best_bb[( i + 5 ) % 16], best_bb[( i + 6 ) % 16], best_bb[( i + 7 ) % 16],
&finalBb->x[int ( i / 4 )], &finalBb->y[int ( i / 4 )] ); &finalBb.x[int ( i / 4 )], &finalBb.y[int ( i / 4 )] );
} }
finalBb->alpha = best_alpha; finalBb.alpha = best_alpha;
finalBb->width = best_width; finalBb.width = best_width;
finalBb->length = best_length; finalBb.length = best_length;
return finalBb; return finalBb;
} }

View File

@ -80,7 +80,10 @@ namespace pal
PointSet( int nbPoints, double *x, double *y ); PointSet( int nbPoints, double *x, double *y );
virtual ~PointSet(); virtual ~PointSet();
PointSet *extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty ); /**
* Does... something completely inscrutable.
*/
std::unique_ptr< PointSet > extractShape( int nbPtSh, int imin, int imax, int fps, int fpe, double fptx, double fpty );
/** /**
* Returns a copy of the point set. * Returns a copy of the point set.
@ -106,13 +109,17 @@ namespace pal
*/ */
bool containsLabelCandidate( double x, double y, double width, double height, double alpha = 0 ) const; bool containsLabelCandidate( double x, double y, double width, double height, double alpha = 0 ) const;
CHullBox *compute_chull_bbox(); /**
* Computes a con???? hull. Maybe convex, maybe concave. The person who wrote this
* had no care for anyone else ever reading their code.
*/
CHullBox compute_chull_bbox();
/** /**
* Split a concave shape into several convex shapes. * Split a concave shape into several convex shapes.
*/ */
static void splitPolygons( QLinkedList<PointSet *> &shapes_toProcess, static void splitPolygons( QLinkedList<PointSet *> &inputShapes,
QLinkedList<PointSet *> &shapes_final, QLinkedList<PointSet *> &outputShapes,
double xrm, double yrm ); double xrm, double yrm );
/** /**