Skip to content

Commit 821eb40

Browse files
committedOct 23, 2017
[Geometry checker] Initial multilayer support for contained check
1 parent 55cf125 commit 821eb40

File tree

2 files changed

+68
-43
lines changed

2 files changed

+68
-43
lines changed
 

‎src/plugins/geometry_checker/checks/qgsgeometrycontainedcheck.cpp

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,85 +13,110 @@
1313
* *
1414
***************************************************************************/
1515

16+
#include "qgscrscache.h"
1617
#include "qgsgeometryengine.h"
1718
#include "qgsgeometrycontainedcheck.h"
1819
#include "../utils/qgsfeaturepool.h"
1920

2021
void QgsGeometryContainedCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter, const QMap<QString, QgsFeatureIds> &ids ) const
2122
{
2223
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
23-
for ( const QString &layerId : featureIds.keys() )
24+
for ( const QString &layerIdA : featureIds.keys() )
2425
{
25-
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
26-
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
26+
QgsFeaturePool *featurePoolA = mContext->featurePools[ layerIdA ];
27+
if ( !getCompatibility( featurePoolA->getLayer()->geometryType() ) )
2728
{
2829
continue;
2930
}
30-
for ( QgsFeatureId featureid : featureIds[layerId] )
31+
QgsCoordinateTransform crstA = QgsCoordinateTransformCache::instance()->transform( featurePoolA->getLayer()->crs().authid(), mContext->mapCrs );
32+
33+
for ( QgsFeatureId featureIdA : featureIds[layerIdA] )
3134
{
3235
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
33-
QgsFeature feature;
34-
if ( !featurePool->get( featureid, feature ) )
36+
QgsFeature featureA;
37+
if ( !featurePoolA->get( featureIdA, featureA ) )
3538
{
3639
continue;
3740
}
3841

39-
QgsGeometry featureGeom = feature.geometry();
40-
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), mContext->tolerance );
42+
QgsAbstractGeometry *featureGeomA = featureA.geometry().geometry()->clone();
43+
featureGeomA->transform( crstA );
44+
QgsGeometryEngine *geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( featureGeomA, mContext->tolerance );
45+
QgsRectangle bboxA = crstA.transform( featureGeomA->boundingBox() );
4146

42-
QgsFeatureIds ids = featurePool->getIntersects( featureGeom.geometry()->boundingBox() );
43-
for ( QgsFeatureId otherid : ids )
47+
for ( const QString &layerIdB : featureIds.keys() )
4448
{
45-
if ( otherid == featureid )
46-
{
47-
continue;
48-
}
49-
QgsFeature otherFeature;
50-
if ( !featurePool->get( otherid, otherFeature ) )
49+
QgsFeaturePool *featurePoolB = mContext->featurePools[ layerIdB ];
50+
if ( !getCompatibility( featurePoolB->getLayer()->geometryType() ) )
5151
{
5252
continue;
5353
}
54+
QgsCoordinateTransform crstB = QgsCoordinateTransformCache::instance()->transform( featurePoolB->getLayer()->crs().authid(), mContext->mapCrs );
5455

55-
QString errMsg;
56-
if ( geomEngine->within( *otherFeature.geometry().geometry(), &errMsg ) )
56+
QgsFeatureIds idsB = featurePoolB->getIntersects( crstB.transform( bboxA, QgsCoordinateTransform::ReverseTransform ) );
57+
for ( QgsFeatureId featureIdB : idsB )
5758
{
58-
errors.append( new QgsGeometryContainedCheckError( this, layerId, featureid, feature.geometry().geometry()->centroid(), otherid ) );
59-
}
60-
else if ( !errMsg.isEmpty() )
61-
{
62-
messages.append( tr( "Feature %1 within feature %2: %3" ).arg( feature.id() ).arg( otherFeature.id() ).arg( errMsg ) );
59+
QgsFeature featureB;
60+
if ( !featurePoolB->get( featureIdB, featureB ) )
61+
{
62+
continue;
63+
}
64+
QgsAbstractGeometry *featureGeomB = featureB.geometry().geometry()->clone();
65+
featureGeomB->transform( crstB );
66+
67+
QString errMsg;
68+
if ( geomEngineA->within( *featureGeomB, &errMsg ) )
69+
{
70+
errors.append( new QgsGeometryContainedCheckError( this, layerIdA, featureIdA, featureGeomA->centroid(), qMakePair( layerIdB, featureIdB ) ) );
71+
}
72+
else if ( !errMsg.isEmpty() )
73+
{
74+
messages.append( tr( "Feature %1:%2 within feature %3:%4: %5" ).arg( layerIdA ).arg( featureIdA ).arg( layerIdB ).arg( featureIdB ).arg( errMsg ) );
75+
}
76+
delete featureGeomB;
6377
}
6478
}
65-
delete geomEngine;
79+
delete geomEngineA;
80+
delete featureGeomA;
6681
}
6782
}
6883
}
6984

7085
void QgsGeometryContainedCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
7186
{
72-
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
7387
QgsGeometryContainedCheckError *containerError = static_cast<QgsGeometryContainedCheckError *>( error );
88+
QgsFeaturePool *featurePoolA = mContext->featurePools[ error->layerId() ];
89+
QgsFeaturePool *featurePoolB = mContext->featurePools[ containerError->containingFeature().first ];
7490

75-
QgsFeature feature;
76-
QgsFeature otherFeature;
77-
if ( !featurePool->get( error->featureId(), feature ) ||
78-
!featurePool->get( containerError->otherId(), otherFeature ) )
91+
QgsFeature featureA;
92+
QgsFeature featureB;
93+
if ( !featurePoolA->get( error->featureId(), featureA ) ||
94+
!featurePoolB->get( containerError->containingFeature().second, featureB ) )
7995
{
8096
error->setObsolete();
8197
return;
8298
}
99+
QgsCoordinateTransform crstA = QgsCoordinateTransformCache::instance()->transform( featurePoolA->getLayer()->crs().authid(), mContext->mapCrs );
100+
QgsCoordinateTransform crstB = QgsCoordinateTransformCache::instance()->transform( featurePoolB->getLayer()->crs().authid(), mContext->mapCrs );
83101

84102
// Check if error still applies
85-
QgsGeometry featureGeom = feature.geometry();
86-
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), mContext->tolerance );
103+
QgsAbstractGeometry *featureGeomA = featureA.geometry().geometry()->clone();
104+
featureGeomA->transform( crstA );
105+
QgsGeometryEngine *geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( featureGeomA, mContext->tolerance );
106+
107+
QgsAbstractGeometry *featureGeomB = featureB.geometry().geometry()->clone();
108+
featureGeomB->transform( crstB );
109+
110+
bool within = geomEngineA->within( *featureGeomB );
111+
delete geomEngineA;
112+
delete featureGeomA;
113+
delete featureGeomB;
87114

88-
if ( !geomEngine->within( otherFeature.geometry().geometry() ) )
115+
if ( !within )
89116
{
90-
delete geomEngine;
91117
error->setObsolete();
92118
return;
93119
}
94-
delete geomEngine;
95120

96121
// Fix error
97122
if ( method == NoChange )
@@ -100,8 +125,8 @@ void QgsGeometryContainedCheck::fixError( QgsGeometryCheckError *error, int meth
100125
}
101126
else if ( method == Delete )
102127
{
103-
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
104-
featurePool->deleteFeature( feature );
128+
changes[error->layerId()][featureA.id()].append( Change( ChangeFeature, ChangeRemoved ) );
129+
featurePoolA->deleteFeature( featureA );
105130
error->setFixed( method );
106131
}
107132
else

‎src/plugins/geometry_checker/checks/qgsgeometrycontainedcheck.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,24 @@ class QgsGeometryContainedCheckError : public QgsGeometryCheckError
2525
const QString &layerId,
2626
QgsFeatureId featureId,
2727
const QgsPoint &errorLocation,
28-
QgsFeatureId otherId
28+
const QPair<QString, QgsFeatureId> &containingFeature
2929
)
30-
: QgsGeometryCheckError( check, layerId, featureId, errorLocation, QgsVertexId(), otherId, ValueOther )
31-
, mOtherId( otherId )
30+
: QgsGeometryCheckError( check, layerId, featureId, errorLocation, QgsVertexId(), QString( "%1:%2" ).arg( containingFeature.first ).arg( containingFeature.second ), ValueOther )
31+
, mContainingFeature( containingFeature )
3232
{ }
33-
QgsFeatureId otherId() const { return mOtherId; }
33+
const QPair<QString, QgsFeatureId> &containingFeature() const { return mContainingFeature; }
3434

3535
bool isEqual( QgsGeometryCheckError *other ) const override
3636
{
3737
return other->check() == check() &&
3838
other->featureId() == featureId() &&
39-
static_cast<QgsGeometryContainedCheckError *>( other )->otherId() == otherId();
39+
static_cast<QgsGeometryContainedCheckError *>( other )->containingFeature() == containingFeature();
4040
}
4141

42-
virtual QString description() const override { return QApplication::translate( "QgsGeometryContainedCheckError", "Within %1" ).arg( otherId() ); }
42+
virtual QString description() const override { return QApplication::translate( "QgsGeometryContainedCheckError", "Within %1:%2" ).arg( mContainingFeature.first ).arg( mContainingFeature.second ); }
4343

4444
private:
45-
QgsFeatureId mOtherId;
45+
QPair<QString, QgsFeatureId> mContainingFeature;
4646
};
4747

4848
class QgsGeometryContainedCheck : public QgsGeometryCheck

0 commit comments

Comments
 (0)
Please sign in to comment.