Skip to content

Commit 256876e

Browse files
committed
Add autofixers for geomtries
* Snap to grid * Remove duplicate nodes
1 parent c0032f1 commit 256876e

File tree

5 files changed

+510
-56
lines changed

5 files changed

+510
-56
lines changed

python/core/auto_generated/qgsvectorlayer.sip.in

+19-2
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,16 @@ Constructor for LayerOptions.
329329

330330
};
331331

332+
struct GeometryOptions
333+
{
334+
explicit GeometryOptions( bool removeDuplicateNodes = false, double geometryPrecision = 0.0 );
335+
336+
337+
bool removeDuplicateNodes;
338+
339+
double geometryPrecision;
340+
};
341+
332342
explicit QgsVectorLayer( const QString &path = QString(), const QString &baseName = QString(),
333343
const QString &providerLib = "ogr", const QgsVectorLayer::LayerOptions &options = QgsVectorLayer::LayerOptions() );
334344
%Docstring
@@ -1062,7 +1072,7 @@ Query the layer for the features which intersect the specified rectangle.
10621072
virtual bool addFeature( QgsFeature &feature, QgsFeatureSink::Flags flags = 0 );
10631073

10641074

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

1501-
bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geometry, bool skipDefaultValue = false );
1511+
bool changeGeometry( QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue = false );
15021512
%Docstring
15031513
Changes a feature's ``geometry`` within the layer's edit buffer
15041514
(but does not immediately commit the changes). The ``fid`` argument
@@ -2225,6 +2235,13 @@ Test if an edit command is active
22252235
.. versionadded:: 3.0
22262236
%End
22272237

2238+
2239+
bool removeDuplicateNodes() const;
2240+
void setRemoveDuplicateNodes( bool removeDuplicateNodes );
2241+
2242+
double geometryPrecision() const;
2243+
void setGeometryPrecision( double geometryPrecision );
2244+
22282245
public slots:
22292246

22302247
void select( QgsFeatureId featureId );

src/app/qgsvectorlayerproperties.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -289,9 +289,9 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
289289

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

297297
mOldJoins = mLayer->vectorJoins();
@@ -423,6 +423,9 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
423423

424424
updateAuxiliaryStoragePage();
425425

426+
mRemoveDuplicateVerticeCheckbox->setChecked( mLayer->removeDuplicateNodes() );
427+
mGeometryPrecisionSpinBox->setValue( mLayer->geometryPrecision() );
428+
426429
optionsStackedWidget_CurrentChanged( mOptStackedWidget->currentIndex() );
427430
}
428431

@@ -761,6 +764,9 @@ void QgsVectorLayerProperties::apply()
761764
mVector3DWidget->apply();
762765
#endif
763766

767+
mLayer->setRemoveDuplicateNodes( mRemoveDuplicateVerticeCheckbox->isChecked() );
768+
mLayer->setGeometryPrecision( mGeometryPrecisionSpinBox->value() );
769+
764770
// update symbology
765771
emit refreshLegend( mLayer->id() );
766772

src/core/qgsvectorlayer.cpp

+61-3
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,20 @@ bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
944944
if ( !mValid || !mEditBuffer || !mDataProvider )
945945
return false;
946946

947+
948+
if ( mGeometryOptions.geometryPrecision != 0.0 || mGeometryOptions.removeDuplicateNodes )
949+
{
950+
QgsGeometry geom = feature.geometry();
951+
952+
if ( mGeometryOptions.geometryPrecision != 0.0 )
953+
geom = geom.snappedToGrid( mGeometryOptions.geometryPrecision, mGeometryOptions.geometryPrecision );
954+
955+
if ( mGeometryOptions.removeDuplicateNodes )
956+
geom.removeDuplicateNodes();
957+
958+
feature.setGeometry( geom );
959+
}
960+
947961
bool success = mEditBuffer->addFeature( feature );
948962

949963
if ( success )
@@ -957,7 +971,7 @@ bool QgsVectorLayer::addFeature( QgsFeature &feature, Flags )
957971
return success;
958972
}
959973

960-
bool QgsVectorLayer::updateFeature( const QgsFeature &updatedFeature, bool skipDefaultValues )
974+
bool QgsVectorLayer::updateFeature( QgsFeature &updatedFeature, bool skipDefaultValues )
961975
{
962976
if ( !mEditBuffer || !mDataProvider )
963977
{
@@ -972,9 +986,11 @@ bool QgsVectorLayer::updateFeature( const QgsFeature &updatedFeature, bool skipD
972986

973987
if ( ( updatedFeature.hasGeometry() || currentFeature.hasGeometry() ) && !updatedFeature.geometry().equals( currentFeature.geometry() ) )
974988
{
975-
if ( changeGeometry( updatedFeature.id(), updatedFeature.geometry(), true ) )
989+
QgsGeometry geometry = updatedFeature.geometry();
990+
if ( changeGeometry( updatedFeature.id(), geometry, true ) )
976991
{
977992
hasChanged = true;
993+
updatedFeature.setGeometry( geometry );
978994
}
979995
else
980996
{
@@ -2485,13 +2501,19 @@ bool QgsVectorLayer::writeSld( QDomNode &node, QDomDocument &doc, QString &error
24852501
}
24862502

24872503

2488-
bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, const QgsGeometry &geom, bool skipDefaultValue )
2504+
bool QgsVectorLayer::changeGeometry( QgsFeatureId fid, QgsGeometry &geom, bool skipDefaultValue )
24892505
{
24902506
if ( !mEditBuffer || !mDataProvider )
24912507
{
24922508
return false;
24932509
}
24942510

2511+
if ( mGeometryOptions.geometryPrecision != 0.0 )
2512+
geom = geom.snappedToGrid( mGeometryOptions.geometryPrecision, mGeometryOptions.geometryPrecision );
2513+
2514+
if ( mGeometryOptions.removeDuplicateNodes )
2515+
geom.removeDuplicateNodes();
2516+
24952517
updateExtents();
24962518

24972519
bool result = mEditBuffer->changeGeometry( fid, geom );
@@ -2960,6 +2982,22 @@ bool QgsVectorLayer::addFeatures( QgsFeatureList &features, Flags )
29602982
if ( !mEditBuffer || !mDataProvider )
29612983
return false;
29622984

2985+
if ( mGeometryOptions.geometryPrecision != 0.0 || mGeometryOptions.removeDuplicateNodes )
2986+
{
2987+
for ( auto feature = features.begin(); feature != features.end(); ++feature )
2988+
{
2989+
QgsGeometry geom = feature->geometry();
2990+
2991+
if ( mGeometryOptions.geometryPrecision != 0.0 )
2992+
geom = geom.snappedToGrid( mGeometryOptions.geometryPrecision, mGeometryOptions.geometryPrecision );
2993+
2994+
if ( mGeometryOptions.removeDuplicateNodes )
2995+
geom.removeDuplicateNodes();
2996+
2997+
feature->setGeometry( geom );
2998+
}
2999+
}
3000+
29633001
bool res = mEditBuffer->addFeatures( features );
29643002
updateExtents();
29653003

@@ -4744,6 +4782,26 @@ QgsAbstractVectorLayerLabeling *QgsVectorLayer::readLabelingFromCustomProperties
47444782
return labeling;
47454783
}
47464784

4785+
double QgsVectorLayer::geometryPrecision() const
4786+
{
4787+
return mGeometryOptions.geometryPrecision;
4788+
}
4789+
4790+
void QgsVectorLayer::setGeometryPrecision( double geometryPrecision )
4791+
{
4792+
mGeometryOptions.geometryPrecision = geometryPrecision;
4793+
}
4794+
4795+
bool QgsVectorLayer::removeDuplicateNodes() const
4796+
{
4797+
return mGeometryOptions.removeDuplicateNodes;
4798+
}
4799+
4800+
void QgsVectorLayer::setRemoveDuplicateNodes( bool removeDuplicateNodes )
4801+
{
4802+
mGeometryOptions.removeDuplicateNodes = removeDuplicateNodes;
4803+
}
4804+
47474805
void QgsVectorLayer::setReadExtentFromXml( bool readExtentFromXml )
47484806
{
47494807
mReadExtentFromXml = readExtentFromXml;

src/core/qgsvectorlayer.h

+37-2
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,32 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
408408

409409
};
410410

411+
struct GeometryOptions
412+
{
413+
explicit GeometryOptions( bool removeDuplicateNodes = false, double geometryPrecision = 0.0 )
414+
: removeDuplicateNodes( removeDuplicateNodes )
415+
, geometryPrecision( geometryPrecision )
416+
{
417+
}
418+
419+
420+
/**
421+
* Automatically remove duplicate nodes on all geometries which are edited on this layer.
422+
*
423+
* \since QGIS 3.4
424+
*/
425+
bool removeDuplicateNodes = false;
426+
427+
/**
428+
* The precision in which geometries on this layer should be saved.
429+
* Geometries which are edited on this layer will be rounded to multiples of this value (snap to grid).
430+
* Set to 0.0 to disable.
431+
*
432+
* \since QGIS 3.4
433+
*/
434+
double geometryPrecision = 0.0;
435+
};
436+
411437
/**
412438
* Constructor - creates a vector layer
413439
*
@@ -1069,7 +1095,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
10691095
* \see changeGeometry()
10701096
* \see changeAttributeValue()
10711097
*/
1072-
bool updateFeature( const QgsFeature &feature, bool skipDefaultValues = false );
1098+
bool updateFeature( QgsFeature &feature, bool skipDefaultValues = false );
10731099

10741100
/**
10751101
* Insert a new vertex before the given vertex number,
@@ -1402,7 +1428,7 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
14021428
* \see changeAttributeValue()
14031429
* \see updateFeature()
14041430
*/
1405-
bool changeGeometry( QgsFeatureId fid, const QgsGeometry &geometry, bool skipDefaultValue = false );
1431+
bool changeGeometry( QgsFeatureId fid, QgsGeometry &geometry, bool skipDefaultValue = false );
14061432

14071433
/**
14081434
* Changes an attribute value for a feature (but does not immediately commit the changes).
@@ -1992,6 +2018,13 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
19922018
*/
19932019
bool isEditCommandActive() const { return mEditCommandActive; }
19942020

2021+
2022+
bool removeDuplicateNodes() const;
2023+
void setRemoveDuplicateNodes( bool removeDuplicateNodes );
2024+
2025+
double geometryPrecision() const;
2026+
void setGeometryPrecision( double geometryPrecision );
2027+
19952028
public slots:
19962029

19972030
/**
@@ -2483,6 +2516,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
24832516

24842517
QgsVectorLayerFeatureCounter *mFeatureCounter = nullptr;
24852518

2519+
GeometryOptions mGeometryOptions;
2520+
24862521
friend class QgsVectorLayerFeatureSource;
24872522
};
24882523

0 commit comments

Comments
 (0)