Skip to content

Commit

Permalink
[FEATURE] Add choice of simplification method to simplify map tool
Browse files Browse the repository at this point in the history
Allows different techniques to be used for simplification, including
the more cartographically pleasing "Visvalingam" simplification algorithm.

Fixes #18083
  • Loading branch information
nyalldawson authored and 3nids committed Feb 26, 2018
1 parent c0b8fbf commit dce2188
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 32 deletions.
51 changes: 48 additions & 3 deletions src/app/qgsmaptoolsimplify.cpp
Expand Up @@ -23,7 +23,7 @@
#include "qgstolerance.h"
#include "qgisapp.h"
#include "qgssettings.h"

#include "qgsmaptopixelgeometrysimplifier.h"
#include <QMouseEvent>

#include <cmath>
Expand All @@ -35,12 +35,22 @@ QgsSimplifyDialog::QgsSimplifyDialog( QgsMapToolSimplify *tool, QWidget *parent
{
setupUi( this );

mMethodComboBox->addItem( tr( "Simplify by distance" ), ( int )QgsVectorSimplifyMethod::Distance );
mMethodComboBox->addItem( tr( "Simplify by snapping to grid" ), ( int )QgsVectorSimplifyMethod::SnapToGrid );
mMethodComboBox->addItem( tr( "Simplify by area (Visvalingam)" ), ( int )QgsVectorSimplifyMethod::Visvalingam );

spinTolerance->setValue( mTool->tolerance() );
spinTolerance->setShowClearButton( false );
cboToleranceUnits->setCurrentIndex( ( int ) mTool->toleranceUnits() );
mMethodComboBox->setCurrentIndex( mMethodComboBox->findData( mTool->method() ) );

// communication with map tool
connect( spinTolerance, static_cast < void ( QDoubleSpinBox::* )( double ) > ( &QDoubleSpinBox::valueChanged ), mTool, &QgsMapToolSimplify::setTolerance );
connect( cboToleranceUnits, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), mTool, &QgsMapToolSimplify::setToleranceUnits );
connect( mMethodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), mTool, [ = ]
{
mTool->setMethod( static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( mMethodComboBox->currentData().toInt() ) );
} );
connect( okButton, &QAbstractButton::clicked, mTool, &QgsMapToolSimplify::storeSimplified );
}

Expand Down Expand Up @@ -70,6 +80,7 @@ QgsMapToolSimplify::QgsMapToolSimplify( QgsMapCanvas *canvas )
QgsSettings settings;
mTolerance = settings.value( QStringLiteral( "digitizing/simplify_tolerance" ), 1 ).toDouble();
mToleranceUnits = settings.enumValue( QStringLiteral( "digitizing/simplify_tolerance_units" ), QgsTolerance::LayerUnits );
mMethod = static_cast< QgsMapToPixelSimplifier::SimplifyAlgorithm >( settings.value( QStringLiteral( "digitizing/simplify_method" ), 0 ).toInt() );

mSimplifyDialog = new QgsSimplifyDialog( this, canvas->topLevelWidget() );
}
Expand Down Expand Up @@ -111,9 +122,10 @@ void QgsMapToolSimplify::updateSimplificationPreview()
mReducedHasErrors = false;
mReducedVertexCount = 0;
int i = 0;

Q_FOREACH ( const QgsFeature &fSel, mSelectedFeatures )
{
QgsGeometry g = fSel.geometry().simplify( layerTolerance );
QgsGeometry g = processGeometry( fSel.geometry(), layerTolerance );
if ( !g.isNull() )
{
mReducedVertexCount += g.constGet()->nCoordinates();
Expand All @@ -128,6 +140,39 @@ void QgsMapToolSimplify::updateSimplificationPreview()
mSimplifyDialog->enableOkButton( !mReducedHasErrors );
}

QgsGeometry QgsMapToolSimplify::processGeometry( const QgsGeometry &geometry, double tolerance ) const
{
switch ( mMethod )
{
case QgsMapToPixelSimplifier::Distance:
return geometry.simplify( tolerance );

case QgsMapToPixelSimplifier::SnapToGrid:
case QgsMapToPixelSimplifier::Visvalingam:
{
QgsMapToPixelSimplifier simplifier( QgsMapToPixelSimplifier::SimplifyGeometry, tolerance, mMethod );
return simplifier.simplify( geometry );
}
}
return QgsGeometry(); //no warnings
}

QgsMapToPixelSimplifier::SimplifyAlgorithm QgsMapToolSimplify::method() const
{
return mMethod;
}

void QgsMapToolSimplify::setMethod( QgsMapToPixelSimplifier::SimplifyAlgorithm method )
{
mMethod = method;

QgsSettings settings;
settings.setValue( QStringLiteral( "digitizing/simplify_method" ), method );

if ( !mSelectedFeatures.isEmpty() )
updateSimplificationPreview();
}

void QgsMapToolSimplify::storeSimplified()
{
QgsVectorLayer *vlayer = currentVectorLayer();
Expand All @@ -136,7 +181,7 @@ void QgsMapToolSimplify::storeSimplified()
vlayer->beginEditCommand( tr( "Geometry simplified" ) );
Q_FOREACH ( const QgsFeature &feat, mSelectedFeatures )
{
QgsGeometry g = feat.geometry().simplify( layerTolerance );
QgsGeometry g = processGeometry( feat.geometry(), layerTolerance );
if ( !g.isNull() )
{
vlayer->changeGeometry( feat.id(), g );
Expand Down
14 changes: 14 additions & 0 deletions src/app/qgsmaptoolsimplify.h
Expand Up @@ -23,6 +23,7 @@
#include "qgsfeature.h"
#include "qgstolerance.h"
#include "qgis_app.h"
#include "qgsmaptopixelgeometrysimplifier.h"

class QgsRubberBand;
class QgsMapToolSimplify;
Expand Down Expand Up @@ -71,6 +72,10 @@ class APP_EXPORT QgsMapToolSimplify: public QgsMapToolEdit

QString statusText() const;

QgsMapToPixelSimplifier::SimplifyAlgorithm method() const;

void setMethod( QgsMapToPixelSimplifier::SimplifyAlgorithm method );

public slots:
//! Slot to change display when slidebar is moved
void setTolerance( double tolerance );
Expand All @@ -89,6 +94,12 @@ class APP_EXPORT QgsMapToolSimplify: public QgsMapToolEdit

void updateSimplificationPreview();

/**
* Simplifies a \a geometry to the specified \a tolerance, respecting the preset
* simplification method.
*/
QgsGeometry processGeometry( const QgsGeometry &geometry, double tolerance ) const;

// data
//! Dialog with slider to set correct tolerance value
QgsSimplifyDialog *mSimplifyDialog = nullptr;
Expand All @@ -113,6 +124,9 @@ class APP_EXPORT QgsMapToolSimplify: public QgsMapToolEdit
int mOriginalVertexCount = 0;
int mReducedVertexCount = 0;
bool mReducedHasErrors = false;

QgsMapToPixelSimplifier::SimplifyAlgorithm mMethod = QgsMapToPixelSimplifier::Distance;

};

#endif
50 changes: 34 additions & 16 deletions src/ui/qgssimplifytolerancedialog.ui
Expand Up @@ -7,21 +7,24 @@
<x>0</x>
<y>0</y>
<width>527</width>
<height>63</height>
<height>98</height>
</rect>
</property>
<property name="windowTitle">
<string>Simplification Tool</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="3">
<widget class="QPushButton" name="okButton">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>OK</string>
<string>Tolerance</string>
</property>
</widget>
</item>
<item row="0" column="2">
<item row="3" column="0" colspan="4">
<widget class="QLabel" name="labelStatus"/>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="cboToleranceUnits">
<item>
<property name="text">
Expand All @@ -40,15 +43,8 @@
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Tolerance</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="spinTolerance">
<item row="1" column="1">
<widget class="QgsDoubleSpinBox" name="spinTolerance">
<property name="decimals">
<number>6</number>
</property>
Expand All @@ -60,12 +56,34 @@
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QLabel" name="labelStatus"/>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Method</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="okButton">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mMethodComboBox"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsDoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>qgsdoublespinbox.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mMethodComboBox</tabstop>
<tabstop>spinTolerance</tabstop>
<tabstop>cboToleranceUnits</tabstop>
<tabstop>okButton</tabstop>
Expand Down
54 changes: 41 additions & 13 deletions src/ui/qgsvectorlayerpropertiesbase.ui
Expand Up @@ -345,7 +345,7 @@
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
<number>12</number>
</property>
<widget class="QWidget" name="mOptsPage_Information">
<layout class="QVBoxLayout" name="verticalLayout_5">
Expand Down Expand Up @@ -421,8 +421,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>651</width>
<height>537</height>
<width>285</width>
<height>399</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
Expand Down Expand Up @@ -696,8 +696,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>651</width>
<height>537</height>
<width>100</width>
<height>30</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_18">
Expand Down Expand Up @@ -882,8 +882,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>651</width>
<height>537</height>
<width>104</width>
<height>102</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_23">
Expand Down Expand Up @@ -1277,8 +1277,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>651</width>
<height>537</height>
<width>100</width>
<height>30</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
Expand Down Expand Up @@ -1451,8 +1451,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>696</width>
<height>521</height>
<width>671</width>
<height>522</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_32">
Expand Down Expand Up @@ -1905,8 +1905,8 @@ border-radius: 2px;</string>
<rect>
<x>0</x>
<y>0</y>
<width>651</width>
<height>537</height>
<width>639</width>
<height>656</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
Expand Down Expand Up @@ -2467,6 +2467,34 @@ border-radius: 2px;</string>
</tabstops>
<resources>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
<include location="../../images/images.qrc"/>
</resources>
<connections>
<connection>
Expand Down

0 comments on commit dce2188

Please sign in to comment.