Skip to content

Commit b9966aa

Browse files
committed
[Geometry checker] Extend duplicate check to also handle points
1 parent ee47d42 commit b9966aa

File tree

3 files changed

+46
-19
lines changed

3 files changed

+46
-19
lines changed

src/plugins/geometry_checker/checks/qgsgeometryduplicatecheck.cpp

+43-16
Original file line numberDiff line numberDiff line change
@@ -26,37 +26,49 @@ void QgsGeometryDuplicateCheck::collectErrors( QList<QgsGeometryCheckError *> &e
2626
QList<QString> layerIds = featureIds.keys();
2727
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeatureA : layerFeaturesA )
2828
{
29-
// Don't check already checked layers
30-
layerIds.removeOne( layerFeatureA.layer().id() );
31-
3229
QgsRectangle bboxA = layerFeatureA.geometry()->boundingBox();
3330
QSharedPointer<QgsGeometryEngine> geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry(), mContext->tolerance );
3431
QMap<QString, QList<QgsFeatureId>> duplicates;
3532

36-
QgsGeometryCheckerUtils::LayerFeatures layerFeaturesB( mContext->featurePools, QList<QString>() << layerFeatureA.layer().id() << layerIds, bboxA, mCompatibleGeometryTypes );
33+
QgsWkbTypes::GeometryType geomType = layerFeatureA.feature().geometry().type();
34+
QgsGeometryCheckerUtils::LayerFeatures layerFeaturesB( mContext->featurePools, layerIds, bboxA, {geomType} );
3735
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeatureB : layerFeaturesB )
3836
{
3937
// > : only report overlaps within same layer once
4038
if ( layerFeatureA.layer().id() == layerFeatureB.layer().id() && layerFeatureB.feature().id() >= layerFeatureA.feature().id() )
4139
{
4240
continue;
4341
}
44-
QString errMsg;
45-
QgsAbstractGeometry *diffGeom = geomEngineA->symDifference( *layerFeatureB.geometry(), &errMsg );
46-
if ( diffGeom && diffGeom->area() < mContext->tolerance )
42+
if ( geomType == QgsWkbTypes::PointGeometry )
4743
{
48-
duplicates[layerFeatureB.layer().id()].append( layerFeatureB.feature().id() );
44+
const QgsPoint *p = dynamic_cast<const QgsPoint *>( layerFeatureA.geometry() );
45+
const QgsPoint *q = dynamic_cast<const QgsPoint *>( layerFeatureB.geometry() );
46+
if ( p && q && p->distanceSquared( *q ) < mContext->tolerance * mContext->tolerance )
47+
{
48+
duplicates[layerFeatureB.layer().id()].append( layerFeatureB.feature().id() );
49+
}
4950
}
50-
else if ( !diffGeom )
51+
else if ( geomType == QgsWkbTypes::PolygonGeometry )
5152
{
52-
messages.append( tr( "Duplicate check between features %1 and %2: %3" ).arg( layerFeatureA.id() ).arg( layerFeatureB.id() ).arg( errMsg ) );
53+
QString errMsg;
54+
QgsAbstractGeometry *diffGeom = geomEngineA->symDifference( *layerFeatureB.geometry(), &errMsg );
55+
if ( diffGeom && diffGeom->area() < mContext->tolerance )
56+
{
57+
duplicates[layerFeatureB.layer().id()].append( layerFeatureB.feature().id() );
58+
}
59+
else if ( !diffGeom )
60+
{
61+
messages.append( tr( "Duplicate check between features %1 and %2: %3" ).arg( layerFeatureA.id() ).arg( layerFeatureB.id() ).arg( errMsg ) );
62+
}
63+
delete diffGeom;
5364
}
54-
delete diffGeom;
5565
}
5666
if ( !duplicates.isEmpty() )
5767
{
5868
errors.append( new QgsGeometryDuplicateCheckError( this, layerFeatureA, layerFeatureA.geometry()->centroid(), duplicates ) );
5969
}
70+
// Don't check already checked layers
71+
layerIds.removeOne( layerFeatureA.layer().id() );
6072
}
6173
}
6274

@@ -76,6 +88,8 @@ void QgsGeometryDuplicateCheck::fixError( QgsGeometryCheckError *error, int meth
7688
}
7789
else if ( method == RemoveDuplicates )
7890
{
91+
QgsWkbTypes::GeometryType geomType = featureA.geometry().type();
92+
7993
QgsGeometryCheckerUtils::LayerFeature layerFeatureA( featurePoolA, featureA, true );
8094
QSharedPointer<QgsGeometryEngine> geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( layerFeatureA.geometry(), mContext->tolerance );
8195

@@ -91,14 +105,27 @@ void QgsGeometryDuplicateCheck::fixError( QgsGeometryCheckError *error, int meth
91105
continue;
92106
}
93107
QgsGeometryCheckerUtils::LayerFeature layerFeatureB( featurePoolB, featureB, true );
94-
QgsAbstractGeometry *diffGeom = geomEngineA->symDifference( *layerFeatureB.geometry() );
95-
if ( diffGeom && diffGeom->area() < mContext->tolerance )
108+
if ( geomType == QgsWkbTypes::PointGeometry )
96109
{
97-
featurePoolB->deleteFeature( featureB );
98-
changes[layerIdB][idB].append( Change( ChangeFeature, ChangeRemoved ) );
110+
const QgsPoint *p = dynamic_cast<const QgsPoint *>( layerFeatureA.geometry() );
111+
const QgsPoint *q = dynamic_cast<const QgsPoint *>( layerFeatureB.geometry() );
112+
if ( p && q && p->distanceSquared( *q ) < mContext->tolerance * mContext->tolerance )
113+
{
114+
featurePoolB->deleteFeature( featureB );
115+
changes[layerIdB][idB].append( Change( ChangeFeature, ChangeRemoved ) );
116+
}
99117
}
118+
else if ( geomType == QgsWkbTypes::PolygonGeometry )
119+
{
120+
QgsAbstractGeometry *diffGeom = geomEngineA->symDifference( *layerFeatureB.geometry() );
121+
if ( diffGeom && diffGeom->area() < mContext->tolerance )
122+
{
123+
featurePoolB->deleteFeature( featureB );
124+
changes[layerIdB][idB].append( Change( ChangeFeature, ChangeRemoved ) );
125+
}
100126

101-
delete diffGeom;
127+
delete diffGeom;
128+
}
102129
}
103130
}
104131
error->setFixed( method );

src/plugins/geometry_checker/checks/qgsgeometryduplicatecheck.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class QgsGeometryDuplicateCheck : public QgsGeometryCheck
6565

6666
public:
6767
explicit QgsGeometryDuplicateCheck( QgsGeometryCheckerContext *context )
68-
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, context ) {}
68+
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PointGeometry, QgsWkbTypes::PolygonGeometry}, context ) {}
6969
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
7070
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
7171
QStringList getResolutionMethods() const override;

src/plugins/geometry_checker/qgsgeometrycheckfactory.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,9 @@ template<> void QgsGeometryCheckFactoryT<QgsGeometryDuplicateCheck>::restorePrev
189189
ui.checkBoxDuplicates->setChecked( QgsSettings().value( sSettingsGroup + "checkDuplicates" ).toBool() );
190190
}
191191

192-
template<> bool QgsGeometryCheckFactoryT<QgsGeometryDuplicateCheck>::checkApplicability( Ui::QgsGeometryCheckerSetupTab &ui, int /*nPoint*/, int /*nLineString*/, int nPolygon ) const
192+
template<> bool QgsGeometryCheckFactoryT<QgsGeometryDuplicateCheck>::checkApplicability( Ui::QgsGeometryCheckerSetupTab &ui, int nPoint, int /*nLineString*/, int nPolygon ) const
193193
{
194-
ui.checkBoxDuplicates->setEnabled( nPolygon > 0 );
194+
ui.checkBoxDuplicates->setEnabled( nPoint > 0 || nPolygon > 0 );
195195
return ui.checkBoxDuplicates->isEnabled();
196196
}
197197

0 commit comments

Comments
 (0)