diff --git a/python/core/qgsmaprenderer.sip b/python/core/qgsmaprenderer.sip
index c4aed0a191b..550d33be818 100644
--- a/python/core/qgsmaprenderer.sip
+++ b/python/core/qgsmaprenderer.sip
@@ -19,7 +19,7 @@ public:
//! called when starting rendering of a layer
virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) = 0;
//! called for every feature
- virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0;
+ virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0;
//! called when the map is drawn and labels should be placed
virtual void drawLabeling( QgsRenderContext& context ) = 0;
//! called when we're done with rendering
diff --git a/src/core/qgsmaprenderer.h b/src/core/qgsmaprenderer.h
index be1754c6bb2..806a7775207 100644
--- a/src/core/qgsmaprenderer.h
+++ b/src/core/qgsmaprenderer.h
@@ -53,7 +53,7 @@ class QgsLabelingEngineInterface
//! called when starting rendering of a layer
virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx ) = 0;
//! called for every feature
- virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0;
+ virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() ) = 0;
//! called when the map is drawn and labels should be placed
virtual void drawLabeling( QgsRenderContext& context ) = 0;
//! called when we're done with rendering
diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp
index 4e7f08a1a3f..4a5a8a64275 100644
--- a/src/core/qgsvectorlayer.cpp
+++ b/src/core/qgsvectorlayer.cpp
@@ -741,7 +741,7 @@ void QgsVectorLayer::drawRendererV2( QgsRenderContext& rendererContext, bool lab
// labeling - register feature
if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL )
- rendererContext.labelingEngine()->registerFeature( this, fet );
+ rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
if ( mEditable )
{
@@ -805,7 +805,7 @@ void QgsVectorLayer::drawRendererV2Levels( QgsRenderContext& rendererContext, bo
features[sym].append( fet );
if ( labeling && mRendererV2->symbolForFeature( fet ) != NULL )
- rendererContext.labelingEngine()->registerFeature( this, fet );
+ rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
if ( mEditable )
{
@@ -1052,7 +1052,7 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext )
if ( labeling && mRenderer->willRenderFeature( &fet ) )
{
- rendererContext.labelingEngine()->registerFeature( this, fet );
+ rendererContext.labelingEngine()->registerFeature( this, fet, rendererContext );
}
++featureCount;
diff --git a/src/plugins/labeling/labelinggui.cpp b/src/plugins/labeling/labelinggui.cpp
index e416f942cbc..2c7385859ea 100644
--- a/src/plugins/labeling/labelinggui.cpp
+++ b/src/plugins/labeling/labelinggui.cpp
@@ -117,6 +117,7 @@ LabelingGui::LabelingGui( PalLabeling* lbl, QgsVectorLayer* layer, QWidget* pare
chkNoObstacle->setChecked( !lyr.obstacle );
chkLabelPerFeaturePart->setChecked( lyr.labelPerPart );
chkMergeLines->setChecked( lyr.mergeLines );
+ mMinSizeSpinBox->setValue( lyr.minFeatureSize );
bool scaleBased = ( lyr.scaleMin != 0 && lyr.scaleMax != 0 );
chkScaleBasedVisibility->setChecked( scaleBased );
@@ -231,7 +232,7 @@ LayerSettings LabelingGui::layerSettings()
{
lyr.bufferSize = 0;
}
-
+ lyr.minFeatureSize = mMinSizeSpinBox->value();
return lyr;
}
diff --git a/src/plugins/labeling/labelingguibase.ui b/src/plugins/labeling/labelingguibase.ui
index 339584af626..f6e4c7cecb8 100644
--- a/src/plugins/labeling/labelingguibase.ui
+++ b/src/plugins/labeling/labelingguibase.ui
@@ -6,7 +6,7 @@
0
0
- 480
+ 448
610
@@ -18,15 +18,15 @@
-
- -
+
+
-
Label this layer
- -
+
-
-
@@ -56,7 +56,7 @@
- -
+
-
Placement
@@ -326,7 +326,7 @@
- -
+
-
-
@@ -648,21 +648,39 @@
- -
+
-
label every part of multi-part features
- -
+
-
merge connected lines to avoid duplicate labels
- -
+
-
+
+
-
+
+
+ Suppress labeling of features smaller than
+
+
+
+ -
+
+
+ mm
+
+
+
+
+
+ -
-
@@ -699,7 +717,7 @@
- -
+
-
Qt::Vertical
@@ -712,7 +730,7 @@
- -
+
-
Qt::Horizontal
diff --git a/src/plugins/labeling/pallabeling.cpp b/src/plugins/labeling/pallabeling.cpp
index 69c8c54cdcf..935949b11a5 100644
--- a/src/plugins/labeling/pallabeling.cpp
+++ b/src/plugins/labeling/pallabeling.cpp
@@ -105,6 +105,7 @@ LayerSettings::LayerSettings()
bufferColor = Qt::white;
labelPerPart = false;
mergeLines = false;
+ minFeatureSize = 0.0;
}
LayerSettings::LayerSettings( const LayerSettings& s )
@@ -125,6 +126,7 @@ LayerSettings::LayerSettings( const LayerSettings& s )
bufferColor = s.bufferColor;
labelPerPart = s.labelPerPart;
mergeLines = s.mergeLines;
+ minFeatureSize = s.minFeatureSize;
fontMetrics = NULL;
ct = NULL;
@@ -178,6 +180,7 @@ void LayerSettings::readFromLayer( QgsVectorLayer* layer )
bufferColor = _readColor( layer, "labeling/bufferColor" );
labelPerPart = layer->customProperty( "labeling/labelPerPart" ).toBool();
mergeLines = layer->customProperty( "labeling/mergeLines" ).toBool();
+ minFeatureSize = layer->customProperty( "labeling/minFeatureSize" ).toDouble();
}
void LayerSettings::writeToLayer( QgsVectorLayer* layer )
@@ -205,6 +208,51 @@ void LayerSettings::writeToLayer( QgsVectorLayer* layer )
_writeColor( layer, "labeling/bufferColor", bufferColor );
layer->setCustomProperty( "labeling/labelPerPart", labelPerPart );
layer->setCustomProperty( "labeling/mergeLines", mergeLines );
+ layer->setCustomProperty( "labeling/minFeatureSize", minFeatureSize );
+}
+
+bool LayerSettings::checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const
+{
+ if ( minSize <= 0 )
+ {
+ return true;
+ }
+
+ if ( !geom )
+ {
+ return false;
+ }
+
+ QGis::GeometryType featureType = geom->type();
+ if ( featureType == QGis::Point ) //minimum size does not apply to point features
+ {
+ return true;
+ }
+
+ GEOSGeometry* geosGeom = geom->asGeos();
+ if ( !geosGeom )
+ {
+ return true;
+ }
+
+ double mapUnitsPerMM = ct.mapToPixel().mapUnitsPerPixel() * ct.scaleFactor();
+ if ( featureType == QGis::Line )
+ {
+ double length;
+ if ( GEOSLength( geosGeom, &length ) )
+ {
+ return ( length >= ( minSize * mapUnitsPerMM ) );
+ }
+ }
+ else if ( featureType == QGis::Polygon )
+ {
+ double area;
+ if ( GEOSArea( geosGeom, &area ) )
+ {
+ return ( sqrt( area ) >= ( minSize * mapUnitsPerMM ) );
+ }
+ }
+ return true; //should never be reached. Return true in this case to label such geometries anyway.
}
void LayerSettings::calculateLabelSize( QString text, double& labelX, double& labelY )
@@ -219,7 +267,7 @@ void LayerSettings::calculateLabelSize( QString text, double& labelX, double& la
}
-void LayerSettings::registerFeature( QgsFeature& f )
+void LayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext& context )
{
QString labelText = f.attributeMap()[fieldIndex].toString();
double labelX, labelY; // will receive label size
@@ -229,6 +277,11 @@ void LayerSettings::registerFeature( QgsFeature& f )
if ( ct != NULL ) // reproject the geometry if necessary
geom->transform( *ct );
+ if ( !checkMinimumSizeMM( context, geom, minFeatureSize ) )
+ {
+ return;
+ }
+
MyLabel* lbl = new MyLabel( f.id(), labelText, GEOSGeom_clone( geom->asGeos() ) );
// record the created geometry - it will be deleted at the end.
@@ -375,9 +428,10 @@ int PalLabeling::prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderC
}
-void PalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f )
+void PalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f, const QgsRenderContext& context )
{
- mActiveLayers[layer].registerFeature( f );
+ LayerSettings& lyr = mActiveLayers[layer];
+ lyr.registerFeature( f, context );
}
diff --git a/src/plugins/labeling/pallabeling.h b/src/plugins/labeling/pallabeling.h
index bf86d74ecf4..c88bf476dde 100644
--- a/src/plugins/labeling/pallabeling.h
+++ b/src/plugins/labeling/pallabeling.h
@@ -66,12 +66,13 @@ class LayerSettings
QColor bufferColor;
bool labelPerPart; // whether to label every feature's part or only the biggest one
bool mergeLines;
+ double minFeatureSize; // minimum feature size to be labelled (in mm)
// called from register feature hook
void calculateLabelSize( QString text, double& labelX, double& labelY );
// implementation of register feature hook
- void registerFeature( QgsFeature& f );
+ void registerFeature( QgsFeature& f, const QgsRenderContext& context );
void readFromLayer( QgsVectorLayer* layer );
void writeToLayer( QgsVectorLayer* layer );
@@ -85,6 +86,11 @@ class LayerSettings
const QgsCoordinateTransform* ct;
QgsPoint ptZero, ptOne;
QList geometries;
+
+ private:
+ /**Checks if a feature is larger than a minimum size (in mm)
+ @return true if above size, false if below*/
+ bool checkMinimumSizeMM( const QgsRenderContext& ct, QgsGeometry* geom, double minSize ) const;
};
class LabelCandidate
@@ -128,7 +134,7 @@ class PalLabeling : public QgsLabelingEngineInterface
//! hook called when drawing layer before issuing select()
virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex, QgsRenderContext& ctx );
//! hook called when drawing for every feature in a layer
- virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat );
+ virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat, const QgsRenderContext& context = QgsRenderContext() );
//! called when the map is drawn and labels should be placed
virtual void drawLabeling( QgsRenderContext& context );
//! called when we're done with rendering
@@ -145,6 +151,7 @@ class PalLabeling : public QgsLabelingEngineInterface
void initPal();
+
protected:
// temporary hashtable of layer settings, being filled during labeling, cleared once labeling's done
QHash mActiveLayers;