Skip to content

Commit

Permalink
[pal] Cache geos area and length calculation results
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 29, 2019
1 parent e0197fe commit 92f232c
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 70 deletions.
86 changes: 30 additions & 56 deletions src/core/pal/feature.cpp
Expand Up @@ -167,25 +167,20 @@ std::size_t FeaturePart::maximumLineCandidates() const
if ( mCachedMaxLineCandidates > 0 ) if ( mCachedMaxLineCandidates > 0 )
return mCachedMaxLineCandidates; return mCachedMaxLineCandidates;


GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler(); const double l = length();
try if ( l > 0 )
{ {
double length = 0; const std::size_t candidatesForLineLength = static_cast< std::size_t >( std::ceil( mLF->layer()->mPal->maximumLineCandidatesPerMapUnit() * l ) );
if ( GEOSLength_r( geosctxt, geos(), &length ) == 1 ) const std::size_t maxForLayer = mLF->layer()->maximumLineLabelCandidates();
{ if ( maxForLayer == 0 )
const std::size_t candidatesForLineLength = static_cast< std::size_t >( std::ceil( mLF->layer()->mPal->maximumLineCandidatesPerMapUnit() * length ) ); mCachedMaxLineCandidates = candidatesForLineLength;
const std::size_t maxForLayer = mLF->layer()->maximumLineLabelCandidates(); else
if ( maxForLayer == 0 ) mCachedMaxLineCandidates = std::min( candidatesForLineLength, maxForLayer );
mCachedMaxLineCandidates = candidatesForLineLength;
else
mCachedMaxLineCandidates = std::min( candidatesForLineLength, maxForLayer );
return mCachedMaxLineCandidates;
}
} }
catch ( GEOSException & ) else
{ {
mCachedMaxLineCandidates = 1;
} }
mCachedMaxLineCandidates = 1;
return mCachedMaxLineCandidates; return mCachedMaxLineCandidates;
} }


Expand All @@ -194,25 +189,20 @@ std::size_t FeaturePart::maximumPolygonCandidates() const
if ( mCachedMaxPolygonCandidates > 0 ) if ( mCachedMaxPolygonCandidates > 0 )
return mCachedMaxPolygonCandidates; return mCachedMaxPolygonCandidates;


GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler(); const double a = area();
try if ( a > 0 )
{ {
double area = 0; const std::size_t candidatesForArea = static_cast< std::size_t >( std::ceil( mLF->layer()->mPal->maximumPolygonCandidatesPerMapUnitSquared() * a ) );
if ( GEOSArea_r( geosctxt, geos(), &area ) == 1 ) const std::size_t maxForLayer = mLF->layer()->maximumPolygonLabelCandidates();
{ if ( maxForLayer == 0 )
const std::size_t candidatesForArea = static_cast< std::size_t >( std::ceil( mLF->layer()->mPal->maximumPolygonCandidatesPerMapUnitSquared() * area ) ); mCachedMaxPolygonCandidates = candidatesForArea;
const std::size_t maxForLayer = mLF->layer()->maximumPolygonLabelCandidates(); else
if ( maxForLayer == 0 ) mCachedMaxPolygonCandidates = std::min( candidatesForArea, maxForLayer );
mCachedMaxPolygonCandidates = candidatesForArea;
else
mCachedMaxPolygonCandidates = std::min( candidatesForArea, maxForLayer );
return mCachedMaxPolygonCandidates;
}
} }
catch ( GEOSException & ) else
{ {
mCachedMaxPolygonCandidates = 1;
} }
mCachedMaxPolygonCandidates = 1;
return mCachedMaxPolygonCandidates; return mCachedMaxPolygonCandidates;
} }


Expand Down Expand Up @@ -1778,46 +1768,30 @@ void FeaturePart::addSizePenalty( std::vector< std::unique_ptr< LabelPosition >
double sizeCost = 0; double sizeCost = 0;
if ( geomType == GEOS_LINESTRING ) if ( geomType == GEOS_LINESTRING )
{ {
double length; const double l = length();
try if ( l <= 0 )
{ return; // failed to calculate length
if ( GEOSLength_r( ctxt, mGeos, &length ) != 1 )
return; // failed to calculate length
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return;
}
double bbox_length = std::max( bbx[2] - bbx[0], bby[2] - bby[0] ); double bbox_length = std::max( bbx[2] - bbx[0], bby[2] - bby[0] );
if ( length >= bbox_length / 4 ) if ( l >= bbox_length / 4 )
return; // the line is longer than quarter of height or width - don't penalize it return; // the line is longer than quarter of height or width - don't penalize it


sizeCost = 1 - ( length / ( bbox_length / 4 ) ); // < 0,1 > sizeCost = 1 - ( l / ( bbox_length / 4 ) ); // < 0,1 >
} }
else if ( geomType == GEOS_POLYGON ) else if ( geomType == GEOS_POLYGON )
{ {
double area; const double a = area();
try if ( a <= 0 )
{
if ( GEOSArea_r( ctxt, mGeos, &area ) != 1 )
return;
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
return; return;
}
double bbox_area = ( bbx[2] - bbx[0] ) * ( bby[2] - bby[0] ); double bbox_area = ( bbx[2] - bbx[0] ) * ( bby[2] - bby[0] );
if ( area >= bbox_area / 16 ) if ( a >= bbox_area / 16 )
return; // covers more than 1/16 of our view - don't penalize it return; // covers more than 1/16 of our view - don't penalize it


sizeCost = 1 - ( area / ( bbox_area / 16 ) ); // < 0, 1 > sizeCost = 1 - ( a / ( bbox_area / 16 ) ); // < 0, 1 >
} }
else else
return; // no size penalty for points return; // no size penalty for points


// apply the penalty // apply the penalty
for ( std::unique_ptr< LabelPosition > &pos : lPos ) for ( std::unique_ptr< LabelPosition > &pos : lPos )
{ {
pos->setCost( pos->cost() + sizeCost / 100 ); pos->setCost( pos->cost() + sizeCost / 100 );
Expand Down
18 changes: 10 additions & 8 deletions src/core/pal/layer.cpp
Expand Up @@ -175,21 +175,23 @@ bool Layer::registerFeature( QgsLabelFeature *lf )
if ( !lf->labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) ) if ( !lf->labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
{ {
if ( type == GEOS_LINESTRING ) if ( type == GEOS_LINESTRING )
GEOSLength_r( geosctxt, geom, &geom_size ); geom_size = fpart->length();
else if ( type == GEOS_POLYGON ) else if ( type == GEOS_POLYGON )
GEOSArea_r( geosctxt, geom, &geom_size ); geom_size = fpart->area();


if ( geom_size > biggest_size ) if ( geom_size > biggest_size )
{ {
biggest_size = geom_size; biggest_size = geom_size;
biggest_part.reset( fpart.release() ); biggest_part.reset( fpart.release() );
} }
continue; // don't add the feature part now, do it later // don't add the feature part now, do it later
}
else
{
// feature part is ready!
addFeaturePart( fpart.release(), lf->labelText() );
addedFeature = true;
} }

// feature part is ready!
addFeaturePart( fpart.release(), lf->labelText() );
addedFeature = true;
} }


if ( lf->obstacleSettings().isObstacle() && !featureGeomIsObstacleGeom ) if ( lf->obstacleSettings().isObstacle() && !featureGeomIsObstacleGeom )
Expand Down Expand Up @@ -349,7 +351,7 @@ void Layer::chopFeaturesAtRepeatDistance()
double featureLen = 0; double featureLen = 0;
if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING ) if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
{ {
( void )GEOSLength_r( geosctxt, geom, &featureLen ); featureLen = fpart->length();
if ( featureLen > chopInterval ) if ( featureLen > chopInterval )
canChop = true; canChop = true;
} }
Expand Down
19 changes: 13 additions & 6 deletions src/core/pal/pointset.cpp
Expand Up @@ -185,6 +185,8 @@ void PointSet::invalidateGeos()
mOwnsGeom = false; mOwnsGeom = false;
mGeos = nullptr; mGeos = nullptr;
mPreparedGeom = nullptr; mPreparedGeom = nullptr;
mLength = -1;
mArea = -1;
} }


PointSet::~PointSet() PointSet::~PointSet()
Expand Down Expand Up @@ -944,6 +946,9 @@ const GEOSGeometry *PointSet::geos() const


double PointSet::length() const double PointSet::length() const
{ {
if ( mLength >= 0 )
return mLength;

if ( !mGeos ) if ( !mGeos )
createGeosGeom(); createGeosGeom();


Expand All @@ -954,9 +959,8 @@ double PointSet::length() const


try try
{ {
double len = 0; ( void )GEOSLength_r( geosctxt, mGeos, &mLength );
( void )GEOSLength_r( geosctxt, mGeos, &len ); return mLength;
return len;
} }
catch ( GEOSException &e ) catch ( GEOSException &e )
{ {
Expand All @@ -967,6 +971,9 @@ double PointSet::length() const


double PointSet::area() const double PointSet::area() const
{ {
if ( mArea >= 0 )
return mArea;

if ( !mGeos ) if ( !mGeos )
createGeosGeom(); createGeosGeom();


Expand All @@ -977,9 +984,9 @@ double PointSet::area() const


try try
{ {
double area = 0; ( void )GEOSArea_r( geosctxt, mGeos, &mArea );
( void )GEOSArea_r( geosctxt, mGeos, &area ); mArea = std::fabs( mArea );
return area; return mArea;
} }
catch ( GEOSException &e ) catch ( GEOSException &e )
{ {
Expand Down
4 changes: 4 additions & 0 deletions src/core/pal/pointset.h
Expand Up @@ -213,6 +213,10 @@ namespace pal
PointSet *holeOf = nullptr; PointSet *holeOf = nullptr;
PointSet *parent = nullptr; PointSet *parent = nullptr;


mutable double mArea = -1;
mutable double mLength = -1;


PointSet( double x, double y ); PointSet( double x, double y );


PointSet( const PointSet &ps ); PointSet( const PointSet &ps );
Expand Down

0 comments on commit 92f232c

Please sign in to comment.