Skip to content

Commit

Permalink
Merge pull request #7672 from m-kuhn/geomCheckerAutoFixes
Browse files Browse the repository at this point in the history
Add automatical fixes for geometries
  • Loading branch information
m-kuhn committed Aug 24, 2018
2 parents 61c3fe4 + 9dc387f commit a5a6f00
Show file tree
Hide file tree
Showing 12 changed files with 774 additions and 59 deletions.
86 changes: 86 additions & 0 deletions python/core/auto_generated/qgsgeometryfixes.sip.in
@@ -0,0 +1,86 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsgeometryfixes.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsGeometryFixes
{
%Docstring

The QgsGeometryFixes class contains options to automatically adjust geometries to
constraints on a layer.

.. versionadded:: 3.4
%End

%TypeHeaderCode
#include "qgsgeometryfixes.h"
%End
public:

QgsGeometryFixes();
%Docstring
Create a new QgsGeometryFixes object.
%End

bool removeDuplicateNodes() const;
%Docstring
Automatically remove duplicate nodes on all geometries which are edited on this layer.

.. versionadded:: 3.4
%End

void setRemoveDuplicateNodes( bool value );
%Docstring
Automatically remove duplicate nodes on all geometries which are edited on this layer.

.. versionadded:: 3.4
%End

double geometryPrecision() const;
%Docstring
The precision in which geometries on this layer should be saved.
Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
Set to 0.0 to disable.

.. versionadded:: 3.4
%End

void setGeometryPrecision( double value );
%Docstring
The precision in which geometries on this layer should be saved.
Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
Set to 0.0 to disable.

.. versionadded:: 3.4
%End

bool isActive() const;
%Docstring
Determines if at least one fix is enabled.

.. versionadded:: 3.4
%End

void apply( QgsGeometry &geometry ) const;
%Docstring
Apply any fixes configured on this class to ``geometry``.

.. versionadded:: 3.4
%End

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/qgsgeometryfixes.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
13 changes: 10 additions & 3 deletions python/core/auto_generated/qgsvectorlayer.sip.in
Expand Up @@ -1062,7 +1062,7 @@ Query the layer for the features which intersect the specified rectangle.
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );


bool updateFeature( const QgsFeature &feature, bool skipDefaultValues = false );
bool updateFeature( QgsFeature &feature, bool skipDefaultValues = false );
%Docstring
Updates an existing ``feature`` in the layer, replacing the attributes and geometry for the feature
with matching QgsFeature.id() with the attributes and geometry from ``feature``.
Expand Down Expand Up @@ -1498,7 +1498,7 @@ Make layer read-only (editing disabled) or not
:return: false if the layer is in editing yet
%End

bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geometry, bool skipDefaultValue = false );
bool changeGeometry( QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue = false );
%Docstring
Changes a feature's ``geometry`` within the layer's edit buffer
(but does not immediately commit the changes). The ``fid`` argument
Expand Down Expand Up @@ -2223,6 +2223,13 @@ it.
Test if an edit command is active

.. versionadded:: 3.0
%End

QgsGeometryFixes *geometryFixes() const;
%Docstring
Configuration and logic to apply automatically on any edit happening on this layer.

.. versionadded:: 3.4
%End

public slots:
Expand Down Expand Up @@ -2590,7 +2597,7 @@ Emitted when the feature count for symbols on this layer has been recalculated.
Sets the extent
%End

private: // Private methods
private:
QgsVectorLayer( const QgsVectorLayer &rhs );
};

Expand Down
1 change: 1 addition & 0 deletions python/core/core_auto.sip
Expand Up @@ -53,6 +53,7 @@
%Include auto_generated/qgsfields.sip
%Include auto_generated/qgsfileutils.sip
%Include auto_generated/qgsfontutils.sip
%Include auto_generated/qgsgeometryfixes.sip
%Include auto_generated/qgsgeometrysimplifier.sip
%Include auto_generated/qgshistogram.sip
%Include auto_generated/qgshtmlutils.sip
Expand Down
3 changes: 3 additions & 0 deletions python/testing/__init__.py
Expand Up @@ -196,6 +196,9 @@ def assertFilesEqual(self, filepath_expected, filepath_result):
diff = list(diff)
self.assertEqual(0, len(diff), ''.join(diff))

def assertGeometriesEqual(self, geom0, geom1, geom0_id='geometry 1', geom1_id='geometry 2', precision=14, topo_equal_check=False):
self.checkGeometriesEqual(geom0, geom1, geom0_id, geom1_id, use_asserts=True, precision=precision, topo_equal_check=topo_equal_check)

def checkGeometriesEqual(self, geom0, geom1, geom0_id, geom1_id, use_asserts=False, precision=14, topo_equal_check=False):
""" Checks whether two geometries are the same - using either a strict check of coordinates (up to given precision)
or by using topological equality (where e.g. a polygon with clockwise is equal to a polygon with counter-clockwise
Expand Down
24 changes: 22 additions & 2 deletions src/app/qgsvectorlayerproperties.cpp
Expand Up @@ -62,6 +62,7 @@
#include "qgsnewauxiliaryfielddialog.h"
#include "qgslabelinggui.h"
#include "qgssymbollayer.h"
#include "qgsgeometryfixes.h"

#include "layertree/qgslayertreelayer.h"
#include "qgslayertree.h"
Expand Down Expand Up @@ -289,9 +290,9 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(

//insert existing join info
const QList< QgsVectorLayerJoinInfo > &joins = mLayer->vectorJoins();
for ( int i = 0; i < joins.size(); ++i )
for ( const QgsVectorLayerJoinInfo &join : joins )
{
addJoinToTreeWidget( joins[i] );
addJoinToTreeWidget( join );
}

mOldJoins = mLayer->vectorJoins();
Expand Down Expand Up @@ -423,6 +424,22 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(

updateAuxiliaryStoragePage();

if ( mLayer->isSpatial() )
{
mRemoveDuplicateNodesCheckbox->setEnabled( true );
mGeometryPrecisionSpinBox->setEnabled( true );

mRemoveDuplicateNodesCheckbox->setChecked( mLayer->geometryFixes()->removeDuplicateNodes() );
mGeometryPrecisionSpinBox->setValue( mLayer->geometryFixes()->geometryPrecision() );

mGeometryPrecisionSpinBox->setSuffix( QStringLiteral( " [%1]" ).arg( QgsUnitTypes::toAbbreviatedString( mLayer->crs().mapUnits() ) ) );
}
else
{
mRemoveDuplicateNodesCheckbox->setEnabled( false );
mGeometryPrecisionSpinBox->setEnabled( false );
}

optionsStackedWidget_CurrentChanged( mOptStackedWidget->currentIndex() );
}

Expand Down Expand Up @@ -761,6 +778,9 @@ void QgsVectorLayerProperties::apply()
mVector3DWidget->apply();
#endif

mLayer->geometryFixes()->setRemoveDuplicateNodes( mRemoveDuplicateNodesCheckbox->isChecked() );
mLayer->geometryFixes()->setGeometryPrecision( mGeometryPrecisionSpinBox->value() );

// update symbology
emit refreshLegend( mLayer->id() );

Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -203,6 +203,7 @@ SET(QGIS_CORE_SRCS
qgsfontutils.cpp
qgsgeometrysimplifier.cpp
qgsgeometryvalidator.cpp
qgsgeometryfixes.cpp
qgsgml.cpp
qgsgmlschema.cpp
qgshistogram.cpp
Expand Down Expand Up @@ -860,6 +861,7 @@ SET(QGIS_CORE_HDRS
qgsfields.h
qgsfileutils.h
qgsfontutils.h
qgsgeometryfixes.h
qgsgeometrysimplifier.h
qgshistogram.h
qgshtmlutils.h
Expand Down
52 changes: 52 additions & 0 deletions src/core/qgsgeometryfixes.cpp
@@ -0,0 +1,52 @@
/***************************************************************************
qgsgeometryfixes.cpp
-------------------
begin : Aug 23, 2018
copyright : (C) 2018 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsgeometryfixes.h"

bool QgsGeometryFixes::removeDuplicateNodes() const
{
return mRemoveDuplicateNodes;
}

void QgsGeometryFixes::setRemoveDuplicateNodes( bool value )
{
mRemoveDuplicateNodes = value;
}

double QgsGeometryFixes::geometryPrecision() const
{
return mGeometryPrecision;
}

void QgsGeometryFixes::setGeometryPrecision( double value )
{
mGeometryPrecision = value;
}

bool QgsGeometryFixes::isActive() const
{
return mGeometryPrecision != 0.0 || mRemoveDuplicateNodes;
}

void QgsGeometryFixes::apply( QgsGeometry &geometry ) const
{
if ( mGeometryPrecision != 0.0 )
geometry = geometry.snappedToGrid( mGeometryPrecision, mGeometryPrecision );

if ( mRemoveDuplicateNodes )
geometry.removeDuplicateNodes();
}
105 changes: 105 additions & 0 deletions src/core/qgsgeometryfixes.h
@@ -0,0 +1,105 @@
/***************************************************************************
qgsgeometryfixes.h
-------------------
begin : Aug 23, 2018
copyright : (C) 2018 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSGEOMETRYFIXES_H
#define QGSGEOMETRYFIXES_H

#include "qgsgeometry.h"

/**
* \ingroup core
*
* The QgsGeometryFixes class contains options to automatically adjust geometries to
* constraints on a layer.
*
* \since QGIS 3.4
*/
class CORE_EXPORT QgsGeometryFixes
{
public:

/**
* Create a new QgsGeometryFixes object.
*/
QgsGeometryFixes() = default;

/**
* Automatically remove duplicate nodes on all geometries which are edited on this layer.
*
* \since QGIS 3.4
*/
bool removeDuplicateNodes() const;

/**
* Automatically remove duplicate nodes on all geometries which are edited on this layer.
*
* \since QGIS 3.4
*/
void setRemoveDuplicateNodes( bool value );

/**
* The precision in which geometries on this layer should be saved.
* Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
* Set to 0.0 to disable.
*
* \since QGIS 3.4
*/
double geometryPrecision() const;

/**
* The precision in which geometries on this layer should be saved.
* Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
* Set to 0.0 to disable.
*
* \since QGIS 3.4
*/
void setGeometryPrecision( double value );

/**
* Determines if at least one fix is enabled.
*
* \since QGIS 3.4
*/
bool isActive() const;

/**
* Apply any fixes configured on this class to \a geometry.
*
* \since QGIS 3.4
*/
void apply( QgsGeometry &geometry ) const;

private:

/**
* Automatically remove duplicate nodes on all geometries which are edited on this layer.
*
* \since QGIS 3.4
*/
bool mRemoveDuplicateNodes = false;

/**
* The precision in which geometries on this layer should be saved.
* Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
* Set to 0.0 to disable.
*
* \since QGIS 3.4
*/
double mGeometryPrecision = 0.0;
};

#endif // QGSGEOMETRYFIXES_H

0 comments on commit a5a6f00

Please sign in to comment.