Skip to content
Permalink
Browse files

[pal] Cache geos area and length calculation results

  • Loading branch information
nyalldawson committed Dec 26, 2019
1 parent e0197fe commit 92f232c7aa2448ad0d6c05e191dfec57d2bbd53c
Showing with 57 additions and 70 deletions.
  1. +30 −56 src/core/pal/feature.cpp
  2. +10 −8 src/core/pal/layer.cpp
  3. +13 −6 src/core/pal/pointset.cpp
  4. +4 −0 src/core/pal/pointset.h
@@ -167,25 +167,20 @@ std::size_t FeaturePart::maximumLineCandidates() const
if ( mCachedMaxLineCandidates > 0 )
return mCachedMaxLineCandidates;

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

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

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

@@ -1778,46 +1768,30 @@ void FeaturePart::addSizePenalty( std::vector< std::unique_ptr< LabelPosition >
double sizeCost = 0;
if ( geomType == GEOS_LINESTRING )
{
double length;
try
{
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;
}
const double l = length();
if ( l <= 0 )
return; // failed to calculate length
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

sizeCost = 1 - ( length / ( bbox_length / 4 ) ); // < 0,1 >
sizeCost = 1 - ( l / ( bbox_length / 4 ) ); // < 0,1 >
}
else if ( geomType == GEOS_POLYGON )
{
double area;
try
{
if ( GEOSArea_r( ctxt, mGeos, &area ) != 1 )
return;
}
catch ( GEOSException &e )
{
QgsMessageLog::logMessage( QObject::tr( "Exception: %1" ).arg( e.what() ), QObject::tr( "GEOS" ) );
const double a = area();
if ( a <= 0 )
return;
}
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

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

// apply the penalty
// apply the penalty
for ( std::unique_ptr< LabelPosition > &pos : lPos )
{
pos->setCost( pos->cost() + sizeCost / 100 );
@@ -175,21 +175,23 @@ bool Layer::registerFeature( QgsLabelFeature *lf )
if ( !lf->labelAllParts() && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
{
if ( type == GEOS_LINESTRING )
GEOSLength_r( geosctxt, geom, &geom_size );
geom_size = fpart->length();
else if ( type == GEOS_POLYGON )
GEOSArea_r( geosctxt, geom, &geom_size );
geom_size = fpart->area();

if ( geom_size > biggest_size )
{
biggest_size = geom_size;
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 )
@@ -349,7 +351,7 @@ void Layer::chopFeaturesAtRepeatDistance()
double featureLen = 0;
if ( chopInterval != 0. && GEOSGeomTypeId_r( geosctxt, geom ) == GEOS_LINESTRING )
{
( void )GEOSLength_r( geosctxt, geom, &featureLen );
featureLen = fpart->length();
if ( featureLen > chopInterval )
canChop = true;
}
@@ -185,6 +185,8 @@ void PointSet::invalidateGeos()
mOwnsGeom = false;
mGeos = nullptr;
mPreparedGeom = nullptr;
mLength = -1;
mArea = -1;
}

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

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

if ( !mGeos )
createGeosGeom();

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

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

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

if ( !mGeos )
createGeosGeom();

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

try
{
double area = 0;
( void )GEOSArea_r( geosctxt, mGeos, &area );
return area;
( void )GEOSArea_r( geosctxt, mGeos, &mArea );
mArea = std::fabs( mArea );
return mArea;
}
catch ( GEOSException &e )
{
@@ -213,6 +213,10 @@ namespace pal
PointSet *holeOf = nullptr;
PointSet *parent = nullptr;

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


PointSet( double x, double y );

PointSet( const PointSet &ps );

0 comments on commit 92f232c

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