From e3d30af7358887616c2bc6616ae2e29facee7c79 Mon Sep 17 00:00:00 2001 From: Larry Shaffer Date: Wed, 14 Nov 2012 18:31:27 -0700 Subject: [PATCH] Update to limit of number of features sent to PAL - Distributes max number across total number of features registered in PAL - Caveat: PAL may not show label for every registered feature --- python/core/qgsmaprenderer.sip | 3 +++ python/core/qgspallabeling.sip | 2 -- src/core/qgsmaprenderer.h | 4 ++++ src/core/qgspallabeling.cpp | 44 +++++++++++++++++++++++++++------- src/core/qgspallabeling.h | 7 +++--- src/core/qgsvectorlayer.cpp | 15 ++++++++++++ src/ui/qgslabelingguibase.ui | 7 ++++-- 7 files changed, 67 insertions(+), 15 deletions(-) diff --git a/python/core/qgsmaprenderer.sip b/python/core/qgsmaprenderer.sip index 578c4198c8f3..2cd7e31c470f 100644 --- a/python/core/qgsmaprenderer.sip +++ b/python/core/qgsmaprenderer.sip @@ -40,6 +40,9 @@ class QgsLabelingEngineInterface //! called when starting rendering of a layer //! @note: this method was added in version 1.6 virtual int prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, QgsRenderContext& ctx ) = 0; + //! returns PAL layer settings for a registered layer + //! @note: this method was added in version 1.9 + virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0; //! adds a diagram layer to the labeling engine virtual int addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings* s ); //! called for every feature diff --git a/python/core/qgspallabeling.sip b/python/core/qgspallabeling.sip index bb785b729a11..9a6130e9d645 100644 --- a/python/core/qgspallabeling.sip +++ b/python/core/qgspallabeling.sip @@ -126,8 +126,6 @@ class QgsPalLayerSettings double minFeatureSize; // minimum feature size to be labelled (in mm) bool limitNumLabels; // whether to limit the number of labels to be drawn int maxNumLabels; // maximum number of labels to be drawn - //bool rndMaxNumLabels; // whether to take a randomized maxNumLabels subset of features to be labeled - // Adds '<' or '>', or user-defined symbol to the label string pointing to the // direction of the line / polygon ring // Works only if Placement == Line diff --git a/src/core/qgsmaprenderer.h b/src/core/qgsmaprenderer.h index df75b9193928..792b0c2b7fde 100644 --- a/src/core/qgsmaprenderer.h +++ b/src/core/qgsmaprenderer.h @@ -39,6 +39,7 @@ class QgsDistanceArea; class QgsOverlayObjectPositionManager; class QgsVectorLayer; +class QgsPalLayerSettings; class QgsDiagramLayerSettings; class CORE_EXPORT QgsLabelPosition @@ -75,6 +76,9 @@ class CORE_EXPORT QgsLabelingEngineInterface //! called when starting rendering of a layer //! @note: this method was added in version 1.6 virtual int prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, QgsRenderContext& ctx ) = 0; + //! returns PAL layer settings for a registered layer + //! @note: this method was added in version 1.9 + virtual QgsPalLayerSettings& layer( const QString& layerName ) = 0; //! adds a diagram layer to the labeling engine virtual int addDiagramLayer( QgsVectorLayer* layer, QgsDiagramLayerSettings* s ) { Q_UNUSED( layer ); Q_UNUSED( s ); return 0; } diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp index 76194f198843..e2e2e685d17e 100644 --- a/src/core/qgspallabeling.cpp +++ b/src/core/qgspallabeling.cpp @@ -177,7 +177,7 @@ class QgsPalGeometry : public PalGeometry // ------------- QgsPalLayerSettings::QgsPalLayerSettings() - : palLayer( NULL ), ct( NULL ), extentGeom( NULL ), expression( NULL ) + : palLayer( NULL ), ct( NULL ), extentGeom( NULL ), mFeaturesToLabel( 0 ), mFeatsSendingToPal( 0 ), mFeatsRegPal( 0 ), expression( NULL ) { placement = AroundPoint; placementFlags = 0; @@ -658,13 +658,6 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF* fm, QString t void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f, const QgsRenderContext& context ) { - - // check if max number of labels to draw (already registered features) has been reached - if ( limitNumLabels && ( maxNumLabels == 0 || palLayer->getNbFeatures() >= maxNumLabels ) ) - { - return; - } - // data defined show label? defaults to show label if not 0 QMap< DataDefinedProperties, int >::const_iterator showIt = dataDefinedProperties.find( QgsPalLayerSettings::Show ); if ( showIt != dataDefinedProperties.constEnd() ) @@ -822,6 +815,32 @@ void QgsPalLayerSettings::registerFeature( QgsVectorLayer* layer, QgsFeature& f if ( geos_geom == NULL ) return; // invalid geometry + // likelihood exists label will be registered with PAL and may be drawn + // check if max number of features to label (already registered with PAL) has been reached + // Debug output at end of QgsPalLabeling::drawLabeling(), when deleting temp geometries + if ( limitNumLabels ) + { + if ( !maxNumLabels ) + { + return; + } + mFeatsRegPal = palLayer->getNbFeatures(); + if ( mFeatsRegPal >= maxNumLabels ) + { + return; + } + + int divNum = ( int )(( mFeaturesToLabel / maxNumLabels ) + 0.5 ); + if ( divNum && ( mFeatsRegPal == ( int )( mFeatsSendingToPal / divNum ) ) ) + { + mFeatsSendingToPal += 1; + if ( divNum && mFeatsSendingToPal % divNum ) + { + return; + } + } + } + GEOSGeometry* geos_geom_clone = GEOSGeom_clone( geos_geom ); //data defined position / alignment / rotation? @@ -1259,6 +1278,8 @@ int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QSet& attrIndices, // rect for clipping lyr.extentGeom = QgsGeometry::fromRect( mMapRenderer->extent() ); + lyr.mFeatsSendingToPal = 0; + return 1; // init successful } @@ -1656,6 +1677,13 @@ void QgsPalLabeling::drawLabeling( QgsRenderContext& context ) QgsPalLayerSettings& lyr = lit.value(); for ( QList::iterator git = lyr.geometries.begin(); git != lyr.geometries.end(); ++git ) delete *git; + if ( lyr.limitNumLabels ) + { + QgsDebugMsg( QString( "mFeaturesToLabel: %1" ).arg( lyr.mFeaturesToLabel ) ); + QgsDebugMsg( QString( "maxNumLabels: %1" ).arg( lyr.maxNumLabels ) ); + QgsDebugMsg( QString( "mFeatsSendingToPal: %1" ).arg( lyr.mFeatsSendingToPal ) ); + QgsDebugMsg( QString( "mFeatsRegPal: %1" ).arg( lyr.geometries.count() ) ); + } lyr.geometries.clear(); } diff --git a/src/core/qgspallabeling.h b/src/core/qgspallabeling.h index 02e973f79fde..4081a1d95688 100644 --- a/src/core/qgspallabeling.h +++ b/src/core/qgspallabeling.h @@ -180,8 +180,6 @@ class CORE_EXPORT QgsPalLayerSettings double minFeatureSize; // minimum feature size to be labelled (in mm) bool limitNumLabels; // whether to limit the number of labels to be drawn int maxNumLabels; // maximum number of labels to be drawn - //bool rndMaxNumLabels; // whether to take a randomized maxNumLabels subset of features to be labeled - // Adds '<' or '>', or user-defined symbol to the label string pointing to the // direction of the line / polygon ring // Works only if Placement == Line @@ -228,7 +226,7 @@ class CORE_EXPORT QgsPalLayerSettings @return font pixel size*/ int sizeToPixel( double size, const QgsRenderContext& c , bool buffer = false ) const; - // temporary stuff: set when layer gets prepared + // temporary stuff: set when layer gets prepared or labeled pal::Layer* palLayer; int fieldIndex; const QgsMapToPixel* xform; @@ -236,6 +234,9 @@ class CORE_EXPORT QgsPalLayerSettings QgsPoint ptZero, ptOne; QList geometries; QgsGeometry* extentGeom; + int mFeaturesToLabel; // total features that will probably be labeled, may be less (figured before PAL) + int mFeatsSendingToPal; // total features tested for sending into PAL (relative to maxNumLabels) + int mFeatsRegPal; // number of features registered in PAL, when using limitNumLabels private: /**Checks if a feature is larger than a minimum size (in mm) diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index 886e1f6b8a07..9d7e8c5c226c 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -5699,6 +5699,21 @@ void QgsVectorLayer::prepareLabelingAndDiagrams( QgsRenderContext& rendererConte labeling = true; } + if ( labeling ) + { + // see if feature count limit is set for labeling + QgsPalLayerSettings& palyr = rendererContext.labelingEngine()->layer( this->id() ); + if ( palyr.limitNumLabels && palyr.maxNumLabels > 0 ) + { + select( QgsAttributeList(), rendererContext.extent() ); + // total number of features that may be labeled + QgsFeature ftr; + int nFeatsToLabel = 0; + while ( nextFeature( ftr ) ) { nFeatsToLabel += 1; } + palyr.mFeaturesToLabel = nFeatsToLabel; + } + } + //register diagram layers if ( mDiagramRenderer && mDiagramLayerSettings ) { diff --git a/src/ui/qgslabelingguibase.ui b/src/ui/qgslabelingguibase.ui index 545936a61a5c..bae1aa65b3a2 100644 --- a/src/ui/qgslabelingguibase.ui +++ b/src/ui/qgslabelingguibase.ui @@ -2780,7 +2780,7 @@ - Limit number of labels drawn to + Limit number of features to be labeled to @@ -2795,6 +2795,9 @@ 0 + + Number of features sent to labeling engine, though not all may be labeled + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -2855,7 +2858,7 @@ 0 0 - 686 + 488 981