Skip to content
Permalink
Browse files

[FEATURE] Allow tolerance in mm/pixels for displacement renderer

  • Loading branch information
nyalldawson committed Sep 16, 2015
1 parent 2f54208 commit 5a9d932d9c6b3b2331ea45260dfd7aa503a1ad96
@@ -78,9 +78,51 @@ class QgsPointDisplacementRenderer : QgsFeatureRendererV2
/** Sets the center symbol (takes ownership)*/
void setCenterSymbol( QgsMarkerSymbolV2* symbol /Transfer/ );

/** Sets the tolerance distance for grouping points. Units are specified using
* setToleranceUnit().
* @param t tolerance distance
* @see tolerance()
* @see setToleranceUnit()
*/
void setTolerance( double t );

/** Returns the tolerance distance for grouping points. Units are retrieved using
* toleranceUnit().
* @see setTolerance()
* @see toleranceUnit()
*/
double tolerance() const;

/** Sets the units for the tolerance distance.
* @param unit tolerance distance units
* @see setTolerance()
* @see toleranceUnit()
* @note added in QGIS 2.12
*/
void setToleranceUnit( QgsSymbolV2::OutputUnit unit );

/** Returns the units for the tolerance distance.
* @see tolerance()
* @see setToleranceUnit()
* @note added in QGIS 2.12
*/
QgsSymbolV2::OutputUnit toleranceUnit() const;

/** Sets the map unit scale object for the distance tolerance. This is only used if the
* toleranceUnit() is set to QgsSymbolV2::MapUnit.
* @param scale scale for distance tolerance
* @see toleranceMapUnitScale()
* @see setToleranceUnit()
*/
void setToleranceMapUnitScale( const QgsMapUnitScale& scale );

/** Returns the map unit scale object for the distance tolerance. This is only used if the
* toleranceUnit() is set to QgsSymbolV2::MapUnit.
* @see setToleranceMapUnitScale()
* @see toleranceUnit()
*/
const QgsMapUnitScale& toleranceMapUnitScale() const;

//! creates a QgsPointDisplacementRenderer from an existing renderer.
//! @note added in 2.5
//! @returns a new renderer if the conversion was possible, otherwise 0.
@@ -315,6 +315,8 @@ class QgsSymbolLayerV2Utils
static double lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Returns scale factor painter units -> map units*/
static double mapUnitScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Creates a render context for a pixel based device*/
static QgsRenderContext createRenderContext( QPainter* p );

@@ -36,6 +36,7 @@ QgsPointDisplacementRenderer::QgsPointDisplacementRenderer( const QString& label
, mLabelAttributeName( labelAttributeName )
, mLabelIndex( -1 )
, mTolerance( 0.00001 )
, mToleranceUnit( QgsSymbolV2::MapUnit )
, mCircleWidth( 0.4 )
, mCircleColor( QColor( 125, 125, 125 ) )
, mCircleRadiusAddition( 0 )
@@ -64,6 +65,8 @@ QgsFeatureRendererV2* QgsPointDisplacementRenderer::clone() const
r->setCircleRadiusAddition( mCircleRadiusAddition );
r->setMaxLabelScaleDenominator( mMaxLabelScaleDenominator );
r->setTolerance( mTolerance );
r->setToleranceUnit( mToleranceUnit );
r->setToleranceMapUnitScale( mToleranceMapUnitScale );
if ( mCenterSymbol )
{
r->setCenterSymbol( dynamic_cast<QgsMarkerSymbolV2*>( mCenterSymbol->clone() ) );
@@ -106,7 +109,8 @@ bool QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRender
if ( selected )
mSelectedFeatures.insert( feature.id() );

QList<QgsFeatureId> intersectList = mSpatialIndex->intersects( searchRect( feature.constGeometry()->asPoint() ) );
double searchDistance = mTolerance * QgsSymbolLayerV2Utils::mapUnitScaleFactor( context, mToleranceUnit, mToleranceMapUnitScale );
QList<QgsFeatureId> intersectList = mSpatialIndex->intersects( searchRect( feature.constGeometry()->asPoint(), searchDistance ) );
if ( intersectList.empty() )
{
mSpatialIndex->insertFeature( feature );
@@ -351,6 +355,8 @@ QgsFeatureRendererV2* QgsPointDisplacementRenderer::create( QDomElement& symbolo
r->setCircleRadiusAddition( symbologyElem.attribute( "circleRadiusAddition", "0.0" ).toDouble() );
r->setMaxLabelScaleDenominator( symbologyElem.attribute( "maxLabelScaleDenominator", "-1" ).toDouble() );
r->setTolerance( symbologyElem.attribute( "tolerance", "0.00001" ).toDouble() );
r->setToleranceUnit( QgsSymbolLayerV2Utils::decodeOutputUnit( symbologyElem.attribute( "toleranceUnit", "MapUnit" ) ) );
r->setToleranceMapUnitScale( QgsSymbolLayerV2Utils::decodeMapUnitScale( symbologyElem.attribute( "toleranceUnitScale" ) ) );

//look for an embedded renderer <renderer-v2>
QDomElement embeddedRendererElem = symbologyElem.firstChildElement( "renderer-v2" );
@@ -381,6 +387,8 @@ QDomElement QgsPointDisplacementRenderer::save( QDomDocument& doc )
rendererElement.setAttribute( "circleRadiusAddition", QString::number( mCircleRadiusAddition ) );
rendererElement.setAttribute( "maxLabelScaleDenominator", QString::number( mMaxLabelScaleDenominator ) );
rendererElement.setAttribute( "tolerance", QString::number( mTolerance ) );
rendererElement.setAttribute( "toleranceUnit", QgsSymbolLayerV2Utils::encodeOutputUnit( mToleranceUnit ) );
rendererElement.setAttribute( "toleranceUnitScale", QgsSymbolLayerV2Utils::encodeMapUnitScale( mToleranceMapUnitScale ) );

if ( mRenderer )
{
@@ -418,9 +426,9 @@ QgsLegendSymbolList QgsPointDisplacementRenderer::legendSymbolItems( double scal
}


QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p ) const
QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p, double distance ) const
{
return QgsRectangle( p.x() - mTolerance, p.y() - mTolerance, p.x() + mTolerance, p.y() + mTolerance );
return QgsRectangle( p.x() - distance, p.y() - distance, p.x() + distance, p.y() + distance );
}

void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
@@ -105,9 +105,51 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsFeatureRendererV2
/** Sets the center symbol (takes ownership)*/
void setCenterSymbol( QgsMarkerSymbolV2* symbol );

/** Sets the tolerance distance for grouping points. Units are specified using
* setToleranceUnit().
* @param t tolerance distance
* @see tolerance()
* @see setToleranceUnit()
*/
void setTolerance( double t ) { mTolerance = t; }

/** Returns the tolerance distance for grouping points. Units are retrieved using
* toleranceUnit().
* @see setTolerance()
* @see toleranceUnit()
*/
double tolerance() const { return mTolerance; }

/** Sets the units for the tolerance distance.
* @param unit tolerance distance units
* @see setTolerance()
* @see toleranceUnit()
* @note added in QGIS 2.12
*/
void setToleranceUnit( QgsSymbolV2::OutputUnit unit ) { mToleranceUnit = unit; }

/** Returns the units for the tolerance distance.
* @see tolerance()
* @see setToleranceUnit()
* @note added in QGIS 2.12
*/
QgsSymbolV2::OutputUnit toleranceUnit() const { return mToleranceUnit; }

/** Sets the map unit scale object for the distance tolerance. This is only used if the
* toleranceUnit() is set to QgsSymbolV2::MapUnit.
* @param scale scale for distance tolerance
* @see toleranceMapUnitScale()
* @see setToleranceUnit()
*/
void setToleranceMapUnitScale( const QgsMapUnitScale& scale ) { mToleranceMapUnitScale = scale; }

/** Returns the map unit scale object for the distance tolerance. This is only used if the
* toleranceUnit() is set to QgsSymbolV2::MapUnit.
* @see setToleranceMapUnitScale()
* @see toleranceUnit()
*/
const QgsMapUnitScale& toleranceMapUnitScale() const { return mToleranceMapUnitScale; }

//! creates a QgsPointDisplacementRenderer from an existing renderer.
//! @note added in 2.5
//! @returns a new renderer if the conversion was possible, otherwise 0.
@@ -128,6 +170,8 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsFeatureRendererV2

/** Tolerance. Points that are closer together are considered as equal*/
double mTolerance;
QgsSymbolV2::OutputUnit mToleranceUnit;
QgsMapUnitScale mToleranceMapUnitScale;

/** Font that is passed to the renderer*/
QFont mLabelFont;
@@ -153,8 +197,8 @@ class CORE_EXPORT QgsPointDisplacementRenderer: public QgsFeatureRendererV2
/** Keeps trask which features are selected */
QSet<QgsFeatureId> mSelectedFeatures;

/** Creates a search rectangle with mTolerance*/
QgsRectangle searchRect( const QgsPoint& p ) const;
/** Creates a search rectangle with specified distance tolerance */
QgsRectangle searchRect( const QgsPoint& p, double distance ) const;
/** This is a debugging function to check the entries in the displacement groups*/
void printInfoDisplacementGroups();

@@ -3310,6 +3310,22 @@ double QgsSymbolLayerV2Utils::pixelSizeScaleFactor( const QgsRenderContext& c, Q
}
}

double QgsSymbolLayerV2Utils::mapUnitScaleFactor( const QgsRenderContext &c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale &scale )
{
if ( u == QgsSymbolV2::MM )
{
return scale.computeMapUnitsPerPixel( c ) * c.scaleFactor() * c.rasterScaleFactor();
}
else if ( u == QgsSymbolV2::MapUnit )
{
return 1.0;
}
else //QgsSymbol::Pixel
{
return scale.computeMapUnitsPerPixel( c );
}
}

QgsRenderContext QgsSymbolLayerV2Utils::createRenderContext( QPainter* p )
{
QgsRenderContext context;
@@ -367,6 +367,8 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
static double lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Returns scale factor painter units -> map units*/
static double mapUnitScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u, const QgsMapUnitScale& scale = QgsMapUnitScale() );
/** Creates a render context for a pixel based device*/
static QgsRenderContext createRenderContext( QPainter* p );

@@ -49,7 +49,7 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
return;
}
setupUi( this );

mDistanceUnitWidget->setUnits( QgsSymbolV2::OutputUnitList() << QgsSymbolV2::MM << QgsSymbolV2::MapUnit << QgsSymbolV2::Pixel );

if ( renderer )
{
@@ -105,6 +105,8 @@ QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVecto
mLabelColorButton->setColor( mRenderer->labelColor() );
mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
mDistanceSpinBox->setValue( mRenderer->tolerance() );
mDistanceUnitWidget->setUnit( mRenderer->toleranceUnit() );
mDistanceUnitWidget->setMapUnitScale( mRenderer->toleranceMapUnitScale() );

//scale dependent labelling
mMaxScaleDenominatorEdit->setText( QString::number( mRenderer->maxLabelScaleDenominator() ) );
@@ -267,6 +269,15 @@ void QgsPointDisplacementRendererWidget::on_mDistanceSpinBox_valueChanged( doubl
}
}

void QgsPointDisplacementRendererWidget::on_mDistanceUnitWidget_changed()
{
if ( mRenderer )
{
mRenderer->setToleranceUnit( mDistanceUnitWidget->unit() );
mRenderer->setToleranceMapUnitScale( mDistanceUnitWidget->getMapUnitScale() );
}
}

void QgsPointDisplacementRendererWidget::on_mScaleDependentLabelsCheckBox_stateChanged( int state )
{
if ( state == Qt::Unchecked )
@@ -308,6 +319,7 @@ void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
mMaxScaleDenominatorEdit->blockSignals( block );
mCenterSymbolPushButton->blockSignals( block );
mDistanceSpinBox->blockSignals( block );
mDistanceUnitWidget->blockSignals( block );
}

void QgsPointDisplacementRendererWidget::on_mCenterSymbolPushButton_clicked()
@@ -48,6 +48,7 @@ class GUI_EXPORT QgsPointDisplacementRendererWidget: public QgsRendererV2Widget,
void on_mCircleWidthSpinBox_valueChanged( double d );
void on_mCircleColorButton_colorChanged( const QColor& newColor );
void on_mDistanceSpinBox_valueChanged( double d );
void on_mDistanceUnitWidget_changed();
void on_mLabelColorButton_colorChanged( const QColor& newColor );
void on_mCircleModificationSpinBox_valueChanged( double d );
void on_mScaleDependentLabelsCheckBox_stateChanged( int state );
@@ -57,7 +57,7 @@
</widget>
</item>
<item row="4" column="0">
<widget class="QGroupBox" name="mLabellingGroupBox">
<widget class="QgsCollapsibleGroupBoxBasic" name="mLabellingGroupBox">
<property name="title">
<string>Labels</string>
</property>
@@ -133,7 +133,7 @@
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="mDisplacementCirclesGroupBox">
<widget class="QgsCollapsibleGroupBoxBasic" name="mDisplacementCirclesGroupBox">
<property name="title">
<string>Displacement circles</string>
</property>
@@ -171,19 +171,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="mCircleWidthSpinBox"/>
</item>
<item row="6" column="1">
<widget class="QDoubleSpinBox" name="mDistanceSpinBox">
<property name="decimals">
<number>7</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="mCircleColorLabel">
<property name="text">
@@ -199,12 +186,36 @@
</widget>
</item>
<item row="3" column="1">
<widget class="QDoubleSpinBox" name="mCircleModificationSpinBox">
<widget class="QgsDoubleSpinBox" name="mCircleModificationSpinBox">
<property name="minimum">
<double>-99.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QgsDoubleSpinBox" name="mCircleWidthSpinBox"/>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QgsDoubleSpinBox" name="mDistanceSpinBox">
<property name="decimals">
<number>7</number>
</property>
<property name="maximum">
<double>999999999.000000000000000</double>
</property>
</widget>
</item>
<item>
<widget class="QgsUnitSelectionWidget" name="mDistanceUnitWidget" native="true">
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
@@ -217,6 +228,23 @@
<header>qgscolorbuttonv2.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
<customwidget>
<class>QgsUnitSelectionWidget</class>
<extends>QWidget</extends>
<header>qgsunitselectionwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBoxBasic</class>
<extends>QGroupBox</extends>
<header location="global">qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mCenterSymbolPushButton</tabstop>
@@ -226,6 +254,7 @@
<tabstop>mCircleColorButton</tabstop>
<tabstop>mCircleModificationSpinBox</tabstop>
<tabstop>mDistanceSpinBox</tabstop>
<tabstop>mDistanceUnitWidget</tabstop>
<tabstop>mLabelFieldComboBox</tabstop>
<tabstop>mLabelFontButton</tabstop>
<tabstop>mLabelColorButton</tabstop>

0 comments on commit 5a9d932

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