[Geometry checker] Introduce QgsGeometryCheckerContext

This commit is contained in:
Sandro Mani 2017-03-30 17:59:41 +02:00
parent 31cc65df49
commit 2a92bfb2c9
45 changed files with 353 additions and 338 deletions

View File

@ -22,7 +22,8 @@ void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &error
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -30,7 +31,7 @@ void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &error
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -77,8 +78,9 @@ void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &error
void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -140,14 +142,14 @@ void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError *error, int method,
else
{
changes[error->layerId()][error->featureId()].append( Change( ChangeNode, ChangeRemoved, vidx ) );
if ( QgsGeometryUtils::sqrDistance2D( p1, p3 ) < QgsGeometryCheckPrecision::tolerance() * QgsGeometryCheckPrecision::tolerance()
&& QgsGeometryCheckerUtils::canDeleteVertex( geometry, vidx.part, vidx.ring ) &&
if ( QgsGeometryUtils::sqrDistance2D( p1, p3 ) < mContext->tolerance &&
QgsGeometryCheckerUtils::canDeleteVertex( geometry, vidx.part, vidx.ring ) &&
geometry->deleteVertex( error->vidx() ) ) // error->vidx points to p3 after removing p2
{
changes[error->layerId()][error->featureId()].append( Change( ChangeNode, ChangeRemoved, QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + 1 ) % n ) ) );
}
feature.setGeometry( g );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
error->setFixed( method );
}
}

View File

@ -23,8 +23,8 @@ class QgsGeometryAngleCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometryAngleCheck( const QMap<QString, QgsFeaturePool *> &featurePools, double minAngle )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools )
QgsGeometryAngleCheck( QgsGeometryCheckerContext *context, double minAngle )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context )
, mMinAngle( minAngle )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;

View File

@ -23,7 +23,8 @@ void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -31,7 +32,7 @@ void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -44,7 +45,7 @@ void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
for ( int i = 0, n = multiGeom->numGeometries(); i < n; ++i )
{
double value;
if ( checkThreshold( layerId, multiGeom->geometryN( i ), value ) )
if ( checkThreshold( featurePool->getMapToLayerUnits(), multiGeom->geometryN( i ), value ) )
{
errors.append( new QgsGeometryCheckError( this, layerId, featureid, multiGeom->geometryN( i )->centroid(), QgsVertexId( i ), value, QgsGeometryCheckError::ValueArea ) );
}
@ -53,7 +54,7 @@ void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
else
{
double value;
if ( checkThreshold( layerId, geom, value ) )
if ( checkThreshold( featurePool->getMapToLayerUnits(), geom, value ) )
{
errors.append( new QgsGeometryCheckError( this, layerId, featureid, geom->centroid(), QgsVertexId( 0 ), value, QgsGeometryCheckError::ValueArea ) );
}
@ -64,12 +65,14 @@ void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
void QgsGeometryAreaCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
}
double mapToLayerUnits = featurePool->getMapToLayerUnits();
QgsGeometry g = feature.geometry();
QgsAbstractGeometry *geom = g.geometry();
QgsVertexId vidx = error->vidx();
@ -85,7 +88,7 @@ void QgsGeometryAreaCheck::fixError( QgsGeometryCheckError *error, int method, c
if ( dynamic_cast<QgsGeometryCollection *>( geom ) )
{
double value;
if ( !checkThreshold( error->layerId(), static_cast<QgsGeometryCollection *>( geom )->geometryN( vidx.part ), value ) )
if ( !checkThreshold( mapToLayerUnits, static_cast<QgsGeometryCollection *>( geom )->geometryN( vidx.part ), value ) )
{
error->setObsolete();
return;
@ -94,7 +97,7 @@ void QgsGeometryAreaCheck::fixError( QgsGeometryCheckError *error, int method, c
else
{
double value;
if ( !checkThreshold( error->layerId(), geom, value ) )
if ( !checkThreshold( mapToLayerUnits, geom, value ) )
{
error->setObsolete();
return;
@ -129,16 +132,17 @@ void QgsGeometryAreaCheck::fixError( QgsGeometryCheckError *error, int method, c
}
}
bool QgsGeometryAreaCheck::checkThreshold( const QString &layerId, const QgsAbstractGeometry *geom, double &value ) const
bool QgsGeometryAreaCheck::checkThreshold( double mapToLayerUnits, const QgsAbstractGeometry *geom, double &value ) const
{
value = geom->area();
double mapToLayerUnits = getFeaturePool( layerId )->getMapToLayerUnits();
double threshold = mThresholdMapUnits * mapToLayerUnits * mapToLayerUnits;
return value < threshold;
}
bool QgsGeometryAreaCheck::mergeWithNeighbor( const QString &layerId, QgsFeature &feature, int partIdx, int method, int mergeAttributeIndex, Changes &changes, QString &errMsg ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
double maxVal = 0.;
QgsFeature mergeFeature;
int mergePartIdx = -1;
@ -147,10 +151,10 @@ bool QgsGeometryAreaCheck::mergeWithNeighbor( const QString &layerId, QgsFeature
QgsAbstractGeometry *geom = g.geometry();
// Search for touching neighboring geometries
for ( QgsFeatureId testId : getFeaturePool( layerId )->getIntersects( g.boundingBox() ) )
for ( QgsFeatureId testId : featurePool->getIntersects( g.boundingBox() ) )
{
QgsFeature testFeature;
if ( !getFeaturePool( layerId )->get( testId, testFeature ) )
if ( !featurePool->get( testId, testFeature ) )
{
continue;
}
@ -162,7 +166,7 @@ bool QgsGeometryAreaCheck::mergeWithNeighbor( const QString &layerId, QgsFeature
{
continue;
}
double len = QgsGeometryCheckerUtils::sharedEdgeLength( QgsGeometryCheckerUtils::getGeomPart( geom, partIdx ), QgsGeometryCheckerUtils::getGeomPart( testGeom, testPartIdx ), QgsGeometryCheckPrecision::reducedTolerance() );
double len = QgsGeometryCheckerUtils::sharedEdgeLength( QgsGeometryCheckerUtils::getGeomPart( geom, partIdx ), QgsGeometryCheckerUtils::getGeomPart( testGeom, testPartIdx ), mContext->reducedTolerance );
if ( len > 0. )
{
if ( method == MergeLongestEdge || method == MergeLargestArea )
@ -212,8 +216,8 @@ bool QgsGeometryAreaCheck::mergeWithNeighbor( const QString &layerId, QgsFeature
// Merge geometries
QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), QgsGeometryCheckPrecision::tolerance() );
QgsAbstractGeometry *combinedGeom = geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( geom, partIdx ), &errMsg );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), mContext->tolerance );
QgsAbstractGeometry *combinedGeom = geomEngine->combine( *QgsGeometryCheckerUtils::getGeomPart( geom, partIdx ), &errMsg );
delete geomEngine;
if ( !combinedGeom || combinedGeom->isEmpty() )
{

View File

@ -25,8 +25,8 @@ class QgsGeometryAreaCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometryAreaCheck( const QMap<QString, QgsFeaturePool *> &featurePools, double thresholdMapUnits )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, featurePools )
QgsGeometryAreaCheck( QgsGeometryCheckerContext *context, double thresholdMapUnits )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, context )
, mThresholdMapUnits( thresholdMapUnits )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
@ -37,7 +37,7 @@ class QgsGeometryAreaCheck : public QgsGeometryCheck
private:
enum ResolutionMethod { MergeLongestEdge, MergeLargestArea, MergeIdenticalAttribute, Delete, NoChange };
virtual bool checkThreshold( const QString &layerId, const QgsAbstractGeometry *geom, double &value ) const;
virtual bool checkThreshold( double mapToLayerUnits, const QgsAbstractGeometry *geom, double &value ) const;
bool mergeWithNeighbor( const QString &layerId, QgsFeature &feature, int partIdx, int method, int mergeAttributeIndex, Changes &changes, QString &errMsg ) const;
protected:

View File

@ -18,43 +18,13 @@
#include "qgsgeometrycheck.h"
#include "../utils/qgsfeaturepool.h"
QgsGeometryCheckPrecision::QgsGeometryCheckPrecision()
{
mPrecision = 10;
mReducedPrecision = 6;
}
QgsGeometryCheckPrecision *QgsGeometryCheckPrecision::get()
{
static QgsGeometryCheckPrecision sInstance;
return &sInstance;
}
void QgsGeometryCheckPrecision::setPrecision( int tolerance )
{
get()->mPrecision = tolerance;
get()->mReducedPrecision = tolerance / 2;
}
int QgsGeometryCheckPrecision::precision()
{
return get()->mPrecision;
}
int QgsGeometryCheckPrecision::reducedPrecision()
{
return get()->mReducedPrecision;
}
double QgsGeometryCheckPrecision::tolerance()
{
return std::pow( 10, -get()->mPrecision );
}
double QgsGeometryCheckPrecision::reducedTolerance()
{
return std::pow( 10, -get()->mReducedPrecision );
}
QgsGeometryCheckerContext::QgsGeometryCheckerContext( int _precision, const QString &_crs, const QMap<QString, QgsFeaturePool *> &_featurePools )
: tolerance( qPow( 10, -_precision ) )
, reducedTolerance( qPow( 10, -_precision / 2 ) )
, crs( _crs )
, featurePools( _featurePools )
{}
QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check, const QString &layerId,
QgsFeatureId featureId,
@ -74,7 +44,7 @@ QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check, con
QgsAbstractGeometry *QgsGeometryCheckError::geometry()
{
QgsFeature f;
if ( mCheck->getFeaturePool( layerId() )->get( featureId(), f ) && f.hasGeometry() )
if ( mCheck->getContext()->featurePools[ layerId() ]->get( featureId(), f ) && f.hasGeometry() )
{
QgsGeometry featureGeom = f.geometry();
QgsAbstractGeometry *geom = featureGeom.geometry();
@ -152,7 +122,7 @@ bool QgsGeometryCheckError::handleChanges( const QgsGeometryCheck::Changes &chan
QMap<QString, QgsFeatureIds> QgsGeometryCheck::allLayerFeatureIds() const
{
QMap<QString, QgsFeatureIds> featureIds;
for ( QgsFeaturePool *pool : mFeaturePools )
for ( QgsFeaturePool *pool : mContext->featurePools )
{
featureIds.insert( pool->getLayer()->id(), pool->getFeatureIds() );
}
@ -161,6 +131,7 @@ QMap<QString, QgsFeatureIds> QgsGeometryCheck::allLayerFeatureIds() const
void QgsGeometryCheck::replaceFeatureGeometryPart( const QString &layerId, QgsFeature &feature, int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[layerId];
QgsGeometry featureGeom = feature.geometry();
QgsAbstractGeometry *geom = featureGeom.geometry();
if ( dynamic_cast<QgsGeometryCollection *>( geom ) )
@ -177,11 +148,12 @@ void QgsGeometryCheck::replaceFeatureGeometryPart( const QString &layerId, QgsFe
feature.setGeometry( QgsGeometry( newPartGeom ) );
changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
}
mFeaturePools[layerId]->updateFeature( feature );
featurePool->updateFeature( feature );
}
void QgsGeometryCheck::deleteFeatureGeometryPart( const QString &layerId, QgsFeature &feature, int partIdx, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[layerId];
QgsGeometry featureGeom = feature.geometry();
QgsAbstractGeometry *geom = featureGeom.geometry();
if ( dynamic_cast<QgsGeometryCollection *>( geom ) )
@ -189,25 +161,26 @@ void QgsGeometryCheck::deleteFeatureGeometryPart( const QString &layerId, QgsFea
static_cast<QgsGeometryCollection *>( geom )->removeGeometry( partIdx );
if ( static_cast<QgsGeometryCollection *>( geom )->numGeometries() == 0 )
{
mFeaturePools[layerId]->deleteFeature( feature );
featurePool->deleteFeature( feature );
changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
}
else
{
feature.setGeometry( featureGeom );
mFeaturePools[layerId]->updateFeature( feature );
featurePool->updateFeature( feature );
changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
}
}
else
{
mFeaturePools[layerId]->deleteFeature( feature );
featurePool->deleteFeature( feature );
changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
}
}
void QgsGeometryCheck::deleteFeatureGeometryRing( const QString &layerId, QgsFeature &feature, int partIdx, int ringIdx, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[layerId];
QgsGeometry featureGeom = feature.geometry();
QgsAbstractGeometry *partGeom = QgsGeometryCheckerUtils::getGeomPart( featureGeom.geometry(), partIdx );
if ( dynamic_cast<QgsCurvePolygon *>( partGeom ) )
@ -221,7 +194,7 @@ void QgsGeometryCheck::deleteFeatureGeometryRing( const QString &layerId, QgsFea
{
static_cast<QgsCurvePolygon *>( partGeom )->removeInteriorRing( ringIdx - 1 );
feature.setGeometry( featureGeom );
mFeaturePools[layerId]->updateFeature( feature );
featurePool->updateFeature( feature );
changes[layerId][feature.id()].append( Change( ChangeRing, ChangeRemoved, QgsVertexId( partIdx, ringIdx ) ) );
}
}

View File

@ -30,21 +30,13 @@ class QgsFeaturePool;
#define FEATUREID_NULL std::numeric_limits<QgsFeatureId>::min()
class QgsGeometryCheckPrecision
struct QgsGeometryCheckerContext
{
public:
static void setPrecision( int precision );
static int precision();
static int reducedPrecision();
static double tolerance();
static double reducedTolerance();
private:
QgsGeometryCheckPrecision();
static QgsGeometryCheckPrecision *get();
int mPrecision;
int mReducedPrecision;
QgsGeometryCheckerContext( int _precision, const QString &_crs, const QMap<QString, QgsFeaturePool *> &_featurePools );
const double tolerance;
const double reducedTolerance;
const QString crs;
const QMap<QString, QgsFeaturePool *> featurePools;
};
class QgsGeometryCheck : public QObject
@ -71,10 +63,10 @@ class QgsGeometryCheck : public QObject
typedef QMap<QString, QMap<QgsFeatureId, QList<Change>>> Changes;
QgsGeometryCheck( CheckType checkType, const QList<QgsWkbTypes::GeometryType> &compatibleGeometryTypes, const QMap<QString, QgsFeaturePool *> &featurePools )
QgsGeometryCheck( CheckType checkType, const QList<QgsWkbTypes::GeometryType> &compatibleGeometryTypes, QgsGeometryCheckerContext *context )
: mCheckType( checkType )
, mCompatibleGeometryTypes( compatibleGeometryTypes )
, mFeaturePools( featurePools )
, mContext( context )
{}
virtual void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const = 0;
virtual void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const = 0;
@ -83,8 +75,7 @@ class QgsGeometryCheck : public QObject
virtual QString errorName() const = 0;
CheckType getCheckType() const { return mCheckType; }
bool getCompatibility( QgsWkbTypes::GeometryType type ) const { return mCompatibleGeometryTypes.contains( type ); }
const QMap<QString, QgsFeaturePool *> &getFeaturePools() const { return mFeaturePools; }
QgsFeaturePool *getFeaturePool( const QString &layerId ) const { return mFeaturePools.value( layerId, nullptr ); }
QgsGeometryCheckerContext *getContext() const { return mContext; }
protected:
QMap<QString, QgsFeatureIds> allLayerFeatureIds() const;
@ -95,7 +86,9 @@ class QgsGeometryCheck : public QObject
private:
const CheckType mCheckType;
QList<QgsWkbTypes::GeometryType> mCompatibleGeometryTypes;
QMap<QString, QgsFeaturePool *> mFeaturePools;
protected:
QgsGeometryCheckerContext *mContext;
};

View File

@ -22,7 +22,8 @@ void QgsGeometryContainedCheck::collectErrors( QList<QgsGeometryCheckError *> &e
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -30,15 +31,15 @@ void QgsGeometryContainedCheck::collectErrors( QList<QgsGeometryCheckError *> &e
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
QgsGeometry featureGeom = feature.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), mContext->tolerance );
QgsFeatureIds ids = getFeaturePool( layerId )->getIntersects( featureGeom.geometry()->boundingBox() );
QgsFeatureIds ids = featurePool->getIntersects( featureGeom.geometry()->boundingBox() );
for ( QgsFeatureId otherid : ids )
{
if ( otherid == featureid )
@ -46,7 +47,7 @@ void QgsGeometryContainedCheck::collectErrors( QList<QgsGeometryCheckError *> &e
continue;
}
QgsFeature otherFeature;
if ( !getFeaturePool( layerId )->get( otherid, otherFeature ) )
if ( !featurePool->get( otherid, otherFeature ) )
{
continue;
}
@ -68,12 +69,13 @@ void QgsGeometryContainedCheck::collectErrors( QList<QgsGeometryCheckError *> &e
void QgsGeometryContainedCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsGeometryContainedCheckError *coverError = static_cast<QgsGeometryContainedCheckError *>( error );
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsGeometryContainedCheckError *containerError = static_cast<QgsGeometryContainedCheckError *>( error );
QgsFeature feature;
QgsFeature otherFeature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) ||
!getFeaturePool( error->layerId() )->get( coverError->otherId(), otherFeature ) )
if ( !featurePool->get( error->featureId(), feature ) ||
!featurePool->get( containerError->otherId(), otherFeature ) )
{
error->setObsolete();
return;
@ -81,7 +83,7 @@ void QgsGeometryContainedCheck::fixError( QgsGeometryCheckError *error, int meth
// Check if error still applies
QgsGeometry featureGeom = feature.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), mContext->tolerance );
if ( !geomEngine->within( otherFeature.geometry().geometry() ) )
{
@ -99,7 +101,7 @@ void QgsGeometryContainedCheck::fixError( QgsGeometryCheckError *error, int meth
else if ( method == Delete )
{
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
getFeaturePool( error->layerId() )->deleteFeature( feature );
featurePool->deleteFeature( feature );
error->setFixed( method );
}
else

View File

@ -50,8 +50,8 @@ class QgsGeometryContainedCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometryContainedCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometryContainedCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -21,7 +21,8 @@ void QgsGeometryDegeneratePolygonCheck::collectErrors( QList<QgsGeometryCheckErr
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -29,7 +30,7 @@ void QgsGeometryDegeneratePolygonCheck::collectErrors( QList<QgsGeometryCheckErr
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -51,8 +52,9 @@ void QgsGeometryDegeneratePolygonCheck::collectErrors( QList<QgsGeometryCheckErr
void QgsGeometryDegeneratePolygonCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;

View File

@ -23,8 +23,8 @@ class QgsGeometryDegeneratePolygonCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometryDegeneratePolygonCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometryDegeneratePolygonCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -24,7 +24,8 @@ void QgsGeometryDuplicateCheck::collectErrors( QList<QgsGeometryCheckError *> &e
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -32,15 +33,15 @@ void QgsGeometryDuplicateCheck::collectErrors( QList<QgsGeometryCheckError *> &e
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
QgsGeometry featureGeom = feature.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), mContext->tolerance );
QList<QgsFeatureId> duplicates;
QgsFeatureIds ids = getFeaturePool( layerId )->getIntersects( featureGeom.geometry()->boundingBox() );
QgsFeatureIds ids = featurePool->getIntersects( featureGeom.geometry()->boundingBox() );
for ( QgsFeatureId id : ids )
{
// > : only report overlaps once
@ -49,13 +50,13 @@ void QgsGeometryDuplicateCheck::collectErrors( QList<QgsGeometryCheckError *> &e
continue;
}
QgsFeature testFeature;
if ( !getFeaturePool( layerId )->get( id, testFeature ) )
if ( !featurePool->get( id, testFeature ) )
{
continue;
}
QString errMsg;
QgsAbstractGeometry *diffGeom = geomEngine->symDifference( *testFeature.geometry().geometry(), &errMsg );
if ( diffGeom && diffGeom->area() < QgsGeometryCheckPrecision::tolerance() )
if ( diffGeom && diffGeom->area() < mContext->tolerance )
{
duplicates.append( id );
}
@ -77,8 +78,9 @@ void QgsGeometryDuplicateCheck::collectErrors( QList<QgsGeometryCheckError *> &e
void QgsGeometryDuplicateCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -91,20 +93,20 @@ void QgsGeometryDuplicateCheck::fixError( QgsGeometryCheckError *error, int meth
else if ( method == RemoveDuplicates )
{
QgsGeometry featureGeom = feature.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeom.geometry(), mContext->tolerance );
QgsGeometryDuplicateCheckError *duplicateError = static_cast<QgsGeometryDuplicateCheckError *>( error );
for ( QgsFeatureId id : duplicateError->duplicates() )
{
QgsFeature testFeature;
if ( !getFeaturePool( error->layerId() )->get( id, testFeature ) )
if ( !featurePool->get( id, testFeature ) )
{
continue;
}
QgsAbstractGeometry *diffGeom = geomEngine->symDifference( testFeature.geometry().geometry() );
if ( diffGeom && diffGeom->area() < QgsGeometryCheckPrecision::tolerance() )
QgsAbstractGeometry *diffGeom = geomEngine->symDifference( *testFeature.geometry().geometry() );
if ( diffGeom && diffGeom->area() < mContext->tolerance )
{
getFeaturePool( error->layerId() )->deleteFeature( testFeature );
featurePool->deleteFeature( testFeature );
changes[error->layerId()][id].append( Change( ChangeFeature, ChangeRemoved ) );
}

View File

@ -59,8 +59,8 @@ class QgsGeometryDuplicateCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometryDuplicateCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometryDuplicateCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -22,7 +22,8 @@ void QgsGeometryDuplicateNodesCheck::collectErrors( QList<QgsGeometryCheckError
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -30,7 +31,7 @@ void QgsGeometryDuplicateNodesCheck::collectErrors( QList<QgsGeometryCheckError
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -48,7 +49,7 @@ void QgsGeometryDuplicateNodesCheck::collectErrors( QList<QgsGeometryCheckError
{
QgsPoint pi = geom->vertexAt( QgsVertexId( iPart, iRing, iVert ) );
QgsPoint pj = geom->vertexAt( QgsVertexId( iPart, iRing, jVert ) );
if ( QgsGeometryUtils::sqrDistance2D( pi, pj ) < QgsGeometryCheckPrecision::tolerance() * QgsGeometryCheckPrecision::tolerance() )
if ( QgsGeometryUtils::sqrDistance2D( pi, pj ) < mContext->tolerance )
{
errors.append( new QgsGeometryCheckError( this, layerId, featureid, pj, QgsVertexId( iPart, iRing, jVert ) ) );
}
@ -61,8 +62,9 @@ void QgsGeometryDuplicateNodesCheck::collectErrors( QList<QgsGeometryCheckError
void QgsGeometryDuplicateNodesCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -80,14 +82,9 @@ void QgsGeometryDuplicateNodesCheck::fixError( QgsGeometryCheckError *error, int
// Check if error still applies
int nVerts = QgsGeometryCheckerUtils::polyLineSize( geom, vidx.part, vidx.ring );
if ( nVerts == 0 )
{
error->setObsolete();
return;
}
QgsPoint pi = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + nVerts - 1 ) % nVerts ) );
QgsPoint pj = geom->vertexAt( error->vidx() );
if ( QgsGeometryUtils::sqrDistance2D( pi, pj ) >= QgsGeometryCheckPrecision::tolerance() * QgsGeometryCheckPrecision::tolerance() )
if ( QgsGeometryUtils::sqrDistance2D( pi, pj ) >= mContext->tolerance )
{
error->setObsolete();
return;
@ -111,7 +108,7 @@ void QgsGeometryDuplicateNodesCheck::fixError( QgsGeometryCheckError *error, int
else
{
feature.setGeometry( featureGeom );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
error->setFixed( method );
changes[error->layerId()][error->featureId()].append( Change( ChangeNode, ChangeRemoved, error->vidx() ) );
}

View File

@ -23,8 +23,8 @@ class QgsGeometryDuplicateNodesCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometryDuplicateNodesCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometryDuplicateNodesCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -27,17 +27,18 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
// Collect geometries, build spatial index
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
double mapToLayerUnits = getFeaturePool( layerId )->getMapToLayerUnits();
double mapToLayerUnits = featurePool->getMapToLayerUnits();
double gapAreaThreshold = mThresholdMapUnits * mapToLayerUnits * mapToLayerUnits;
QList<QgsAbstractGeometry *> geomList;
for ( QgsFeatureId id : featureIds[layerId] )
{
QgsFeature feature;
if ( getFeaturePool( layerId )->get( id, feature ) )
if ( featurePool->get( id, feature ) )
{
geomList.append( feature.geometry().geometry()->clone() );
}
@ -48,7 +49,7 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
return;
}
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( nullptr, QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( nullptr, mContext->tolerance );
// Create union of geometry
QString errMsg;
@ -62,7 +63,7 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
}
// Get envelope of union
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( unionGeom, QgsGeometryCheckPrecision::tolerance() );
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( unionGeom, mContext->tolerance );
QgsAbstractGeometry *envelope = geomEngine->envelope( &errMsg );
delete geomEngine;
if ( !envelope )
@ -73,14 +74,14 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
}
// Buffer envelope
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( envelope, QgsGeometryCheckPrecision::tolerance() );
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( envelope, mContext->tolerance );
QgsAbstractGeometry *bufEnvelope = geomEngine->buffer( 2, 0, GEOSBUF_CAP_SQUARE, GEOSBUF_JOIN_MITRE, 4. );
delete geomEngine;
delete envelope;
envelope = bufEnvelope;
// Compute difference between envelope and union to obtain gap polygons
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( envelope, QgsGeometryCheckPrecision::tolerance() );
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( envelope, mContext->tolerance );
QgsAbstractGeometry *diffGeom = geomEngine->difference( *unionGeom, &errMsg );
delete geomEngine;
if ( !diffGeom )
@ -102,7 +103,7 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
}
// Skip gaps above threshold
if ( geom->area() > gapAreaThreshold || geom->area() < QgsGeometryCheckPrecision::reducedTolerance() )
if ( geom->area() > gapAreaThreshold || geom->area() < mContext->reducedTolerance )
{
continue;
}
@ -110,18 +111,18 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
// Get neighboring polygons
QgsFeatureIds neighboringIds;
QgsRectangle gapAreaBBox = geom->boundingBox();
QgsFeatureIds intersectIds = getFeaturePool( layerId )->getIntersects( geom->boundingBox() );
QgsFeatureIds intersectIds = featurePool->getIntersects( geom->boundingBox() );
for ( QgsFeatureId id : intersectIds )
{
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( id, feature ) )
if ( !featurePool->get( id, feature ) )
{
continue;
}
QgsGeometry featureGeom = feature.geometry();
QgsAbstractGeometry *geom2 = featureGeom.geometry();
if ( QgsGeometryCheckerUtils::sharedEdgeLength( geom, geom2, QgsGeometryCheckPrecision::reducedTolerance() ) > 0 )
if ( QgsGeometryCheckerUtils::sharedEdgeLength( geom, geom2, mContext->reducedTolerance ) > 0 )
{
neighboringIds.insert( feature.id() );
gapAreaBBox.unionRect( geom2->boundingBox() );
@ -169,6 +170,7 @@ void QgsGeometryGapCheck::fixError( QgsGeometryCheckError *error, int method, co
bool QgsGeometryGapCheck::mergeWithNeighbor( QgsGeometryGapCheckError *err, Changes &changes, QString &errMsg ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ err->layerId() ];
double maxVal = 0.;
QgsFeature mergeFeature;
int mergePartIdx = -1;
@ -179,7 +181,7 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( QgsGeometryGapCheckError *err, Chan
for ( QgsFeatureId testId : err->neighbors() )
{
QgsFeature testFeature;
if ( !getFeaturePool( err->layerId() )->get( testId, testFeature ) )
if ( !featurePool->get( testId, testFeature ) )
{
continue;
}
@ -187,7 +189,7 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( QgsGeometryGapCheckError *err, Chan
QgsAbstractGeometry *testGeom = featureGeom.geometry();
for ( int iPart = 0, nParts = testGeom->partCount(); iPart < nParts; ++iPart )
{
double len = QgsGeometryCheckerUtils::sharedEdgeLength( errGeometry, QgsGeometryCheckerUtils::getGeomPart( testGeom, iPart ), QgsGeometryCheckPrecision::reducedTolerance() );
double len = QgsGeometryCheckerUtils::sharedEdgeLength( errGeometry, QgsGeometryCheckerUtils::getGeomPart( testGeom, iPart ), mContext->reducedTolerance );
if ( len > maxVal )
{
maxVal = len;
@ -205,8 +207,8 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( QgsGeometryGapCheckError *err, Chan
// Merge geometries
QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errGeometry, QgsGeometryCheckPrecision::tolerance() );
QgsAbstractGeometry *combinedGeom = geomEngine->combine( QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), &errMsg );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errGeometry, mContext->tolerance );
QgsAbstractGeometry *combinedGeom = geomEngine->combine( *QgsGeometryCheckerUtils::getGeomPart( mergeGeom, mergePartIdx ), &errMsg );
delete geomEngine;
if ( !combinedGeom || combinedGeom->isEmpty() )
{

View File

@ -45,7 +45,7 @@ class QgsGeometryGapCheckError : public QgsGeometryCheckError
bool isEqual( QgsGeometryCheckError *other ) const override
{
QgsGeometryGapCheckError *err = dynamic_cast<QgsGeometryGapCheckError *>( other );
return err && QgsGeometryCheckerUtils::pointsFuzzyEqual( err->location(), location(), QgsGeometryCheckPrecision::reducedTolerance() ) && err->neighbors() == neighbors();
return err && QgsGeometryCheckerUtils::pointsFuzzyEqual( err->location(), location(), mCheck->getContext()->reducedTolerance ) && err->neighbors() == neighbors();
}
bool closeMatch( QgsGeometryCheckError *other ) const override
@ -86,8 +86,8 @@ class QgsGeometryGapCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometryGapCheck( const QMap<QString, QgsFeaturePool *> &featurePools, double thresholdMapUnits )
: QgsGeometryCheck( LayerCheck, {QgsWkbTypes::PolygonGeometry}, featurePools )
QgsGeometryGapCheck( QgsGeometryCheckerContext *context, double thresholdMapUnits )
: QgsGeometryCheck( LayerCheck, {QgsWkbTypes::PolygonGeometry}, context )
, mThresholdMapUnits( thresholdMapUnits )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;

View File

@ -21,7 +21,8 @@ void QgsGeometryHoleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -29,7 +30,7 @@ void QgsGeometryHoleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -50,8 +51,9 @@ void QgsGeometryHoleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
void QgsGeometryHoleCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;

View File

@ -23,8 +23,8 @@ class QgsGeometryHoleCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometryHoleCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometryHoleCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -21,7 +21,8 @@ void QgsGeometryMultipartCheck::collectErrors( QList<QgsGeometryCheckError *> &e
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -29,7 +30,7 @@ void QgsGeometryMultipartCheck::collectErrors( QList<QgsGeometryCheckError *> &e
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -47,8 +48,9 @@ void QgsGeometryMultipartCheck::collectErrors( QList<QgsGeometryCheckError *> &e
void QgsGeometryMultipartCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -71,13 +73,13 @@ void QgsGeometryMultipartCheck::fixError( QgsGeometryCheckError *error, int meth
else if ( method == ConvertToSingle )
{
feature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, 0 )->clone() ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
error->setFixed( method );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
}
else if ( method == RemoveObject )
{
getFeaturePool( error->layerId() )->deleteFeature( feature );
featurePool->deleteFeature( feature );
error->setFixed( method );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
}

View File

@ -23,8 +23,8 @@ class QgsGeometryMultipartCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometryMultipartCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PointGeometry, QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometryMultipartCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PointGeometry, QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -22,25 +22,26 @@ void QgsGeometryOverlapCheck::collectErrors( QList<QgsGeometryCheckError *> &err
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
double mapToLayerUnits = getFeaturePool( layerId )->getMapToLayerUnits();
double mapToLayerUnits = featurePool->getMapToLayerUnits();
double overlapThreshold = mThresholdMapUnits * mapToLayerUnits * mapToLayerUnits;
for ( QgsFeatureId featureid : featureIds[layerId] )
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
QgsGeometry featureGeom = feature.geometry();
QgsAbstractGeometry *geom = featureGeom.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geom, QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geom, mContext->tolerance );
QgsFeatureIds ids = getFeaturePool( layerId )->getIntersects( feature.geometry().boundingBox() );
QgsFeatureIds ids = featurePool->getIntersects( feature.geometry().boundingBox() );
for ( QgsFeatureId otherid : ids )
{
// >= : only report overlaps once
@ -50,7 +51,7 @@ void QgsGeometryOverlapCheck::collectErrors( QList<QgsGeometryCheckError *> &err
}
QgsFeature otherFeature;
if ( !getFeaturePool( layerId )->get( otherid, otherFeature ) )
if ( !featurePool->get( otherid, otherFeature ) )
{
continue;
}
@ -65,7 +66,7 @@ void QgsGeometryOverlapCheck::collectErrors( QList<QgsGeometryCheckError *> &err
for ( int iPart = 0, nParts = interGeom->partCount(); iPart < nParts; ++iPart )
{
double area = QgsGeometryCheckerUtils::getGeomPart( interGeom, iPart )->area();
if ( area > QgsGeometryCheckPrecision::reducedTolerance() && area < overlapThreshold )
if ( area > mContext->reducedTolerance && area < overlapThreshold )
{
errors.append( new QgsGeometryOverlapCheckError( this, layerId, featureid, QgsGeometryCheckerUtils::getGeomPart( interGeom, iPart )->centroid(), area, otherid ) );
}
@ -88,17 +89,18 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
QString errMsg;
QgsGeometryOverlapCheckError *overlapError = static_cast<QgsGeometryOverlapCheckError *>( error );
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
QgsFeature otherFeature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) ||
!getFeaturePool( error->layerId() )->get( overlapError->otherId(), otherFeature ) )
if ( !featurePool->get( error->featureId(), feature ) ||
!featurePool->get( overlapError->otherId(), otherFeature ) )
{
error->setObsolete();
return;
}
QgsGeometry featureGeom = feature.geometry();
QgsAbstractGeometry *geom = featureGeom.geometry();
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geom, QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geom, mContext->tolerance );
// Check if error still applies
if ( !geomEngine->overlaps( otherFeature.geometry().geometry() ) )
@ -120,8 +122,8 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
for ( int iPart = 0, nParts = interGeom->partCount(); iPart < nParts; ++iPart )
{
QgsAbstractGeometry *part = QgsGeometryCheckerUtils::getGeomPart( interGeom, iPart );
if ( std::fabs( part->area() - overlapError->value().toDouble() ) < QgsGeometryCheckPrecision::reducedTolerance() &&
QgsGeometryCheckerUtils::pointsFuzzyEqual( part->centroid(), overlapError->location(), QgsGeometryCheckPrecision::reducedTolerance() ) )
if ( qAbs( part->area() - overlapError->value().toDouble() ) < mContext->reducedTolerance &&
QgsGeometryCheckerUtils::pointsFuzzyEqual( part->centroid(), overlapError->location(), mContext->reducedTolerance ) )
{
interPart = part;
break;
@ -141,8 +143,8 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
}
else if ( method == Subtract )
{
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geom, QgsGeometryCheckPrecision::reducedTolerance() );
QgsAbstractGeometry *diff1 = geomEngine->difference( interPart, &errMsg );
geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geom, mContext->reducedTolerance );
QgsAbstractGeometry *diff1 = geomEngine->difference( *interPart, &errMsg );
delete geomEngine;
if ( !diff1 || diff1->isEmpty() )
{
@ -154,8 +156,8 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
QgsGeometryCheckerUtils::filter1DTypes( diff1 );
}
QgsGeometry otherFeatureGeom = otherFeature.geometry();
QgsGeometryEngine *otherGeomEngine = QgsGeometryCheckerUtils::createGeomEngine( otherFeatureGeom.geometry(), QgsGeometryCheckPrecision::reducedTolerance() );
QgsAbstractGeometry *diff2 = otherGeomEngine->difference( interPart, &errMsg );
QgsGeometryEngine *otherGeomEngine = QgsGeometryCheckerUtils::createGeomEngine( otherFeatureGeom.geometry(), mContext->reducedTolerance );
QgsAbstractGeometry *diff2 = otherGeomEngine->difference( *interPart, &errMsg );
delete otherGeomEngine;
if ( !diff2 || diff2->isEmpty() )
{
@ -166,8 +168,8 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
{
QgsGeometryCheckerUtils::filter1DTypes( diff2 );
}
double shared1 = diff1 ? QgsGeometryCheckerUtils::sharedEdgeLength( diff1, interPart, QgsGeometryCheckPrecision::reducedPrecision() ) : 0;
double shared2 = diff2 ? QgsGeometryCheckerUtils::sharedEdgeLength( diff2, interPart, QgsGeometryCheckPrecision::reducedPrecision() ) : 0;
double shared1 = diff1 ? QgsGeometryCheckerUtils::sharedEdgeLength( diff1, interPart, mContext->reducedTolerance ) : 0;
double shared2 = diff2 ? QgsGeometryCheckerUtils::sharedEdgeLength( diff2, interPart, mContext->reducedTolerance ) : 0;
if ( shared1 == 0. || shared2 == 0. )
{
error->setFixFailed( tr( "Could not find shared edges between intersection and overlapping features" ) );
@ -179,7 +181,7 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
feature.setGeometry( QgsGeometry( diff1 ) );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
delete diff2;
}
@ -188,7 +190,7 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
otherFeature.setGeometry( QgsGeometry( diff2 ) );
changes[error->layerId()][otherFeature.id()].append( Change( ChangeFeature, ChangeChanged ) );
getFeaturePool( error->layerId() )->updateFeature( otherFeature );
featurePool->updateFeature( otherFeature );
delete diff1;
}

View File

@ -39,8 +39,8 @@ class QgsGeometryOverlapCheckError : public QgsGeometryCheckError
other->layerId() == layerId() &&
other->featureId() == featureId() &&
err->otherId() == otherId() &&
QgsGeometryCheckerUtils::pointsFuzzyEqual( location(), other->location(), QgsGeometryCheckPrecision::reducedTolerance() ) &&
std::fabs( value().toDouble() - other->value().toDouble() ) < QgsGeometryCheckPrecision::reducedTolerance();
QgsGeometryCheckerUtils::pointsFuzzyEqual( location(), other->location(), mCheck->getContext()->reducedTolerance ) &&
qAbs( value().toDouble() - other->value().toDouble() ) < mCheck->getContext()->reducedTolerance;
}
bool closeMatch( QgsGeometryCheckError *other ) const override
@ -60,8 +60,8 @@ class QgsGeometryOverlapCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometryOverlapCheck( const QMap<QString, QgsFeaturePool *> &featurePools, double thresholdMapUnits )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, featurePools )
QgsGeometryOverlapCheck( QgsGeometryCheckerContext *context, double thresholdMapUnits )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PolygonGeometry}, context )
, mThresholdMapUnits( thresholdMapUnits )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;

View File

@ -22,17 +22,18 @@ void QgsGeometrySegmentLengthCheck::collectErrors( QList<QgsGeometryCheckError *
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
double mapToLayerUnits = getFeaturePool( layerId )->getMapToLayerUnits();
double mapToLayerUnits = featurePool->getMapToLayerUnits();
double minLength = mMinLengthMapUnits * mapToLayerUnits;
for ( QgsFeatureId featureid : featureIds[layerId] )
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -66,8 +67,9 @@ void QgsGeometrySegmentLengthCheck::collectErrors( QList<QgsGeometryCheckError *
void QgsGeometrySegmentLengthCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &/*changes*/ ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -95,7 +97,7 @@ void QgsGeometrySegmentLengthCheck::fixError( QgsGeometryCheckError *error, int
QgsPoint pi = geom->vertexAt( error->vidx() );
QgsPoint pj = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex - 1 + nVerts ) % nVerts ) );
double dist = qSqrt( QgsGeometryUtils::sqrDistance2D( pi, pj ) );
double mapToLayerUnits = getFeaturePool( error->layerId() )->getMapToLayerUnits();
double mapToLayerUnits = featurePool->getMapToLayerUnits();
double minLength = mMinLengthMapUnits * mapToLayerUnits;
if ( dist >= minLength )
{

View File

@ -23,8 +23,8 @@ class QgsGeometrySegmentLengthCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometrySegmentLengthCheck( const QMap<QString, QgsFeaturePool *> &featurePools, double minLengthMapUnits )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools )
QgsGeometrySegmentLengthCheck( QgsGeometryCheckerContext *context, double minLengthMapUnits )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context )
, mMinLengthMapUnits( minLengthMapUnits )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;

View File

@ -12,10 +12,10 @@
void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QMap<QString, QgsFeatureIds> &ids ) const
{
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
double tolerance = QgsGeometryCheckPrecision::tolerance();
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -23,7 +23,7 @@ void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *>
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -44,14 +44,19 @@ void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *>
ring.append( geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) ) );
for ( int i = 1; i < n; ++i )
{
<<<<<<< HEAD
QgsPoint p = geom->vertexAt( QgsVertexId( iPart, iRing, i ) );
if ( QgsGeometryUtils::sqrDistance2D( p, ring.last() ) > tolerance * tolerance )
=======
QgsPoint p = geom->vertexAt( QgsVertexId( iPart, iRing, i ) );
if ( QgsGeometryUtils::sqrDistance2D( p, ring.last() ) > mContext->tolerance * mContext->tolerance )
>>>>>>> [GeometryChecker] Introduce QgsGeometryCheckerContext
{
vtxMap.append( i );
ring.append( p );
}
}
while ( QgsGeometryUtils::sqrDistance2D( ring.front(), ring.back() ) < tolerance * tolerance )
while ( QgsGeometryUtils::sqrDistance2D( ring.front(), ring.back() ) < mContext->tolerance * mContext->tolerance )
{
vtxMap.pop_back();
ring.pop_back();
@ -76,7 +81,7 @@ void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *>
const QgsPoint &si = ring[i];
const QgsPoint &sj = ring[j];
QgsPoint q = QgsGeometryUtils::projPointOnSegment( p, si, sj );
if ( QgsGeometryUtils::sqrDistance2D( p, q ) < tolerance * tolerance )
if ( QgsGeometryUtils::sqrDistance2D( p, q ) < mContext->tolerance * mContext->tolerance )
{
errors.append( new QgsGeometryCheckError( this, layerId, featureid, p, QgsVertexId( iPart, iRing, vtxMap[iVert] ) ) );
break; // No need to report same contact on different segments multiple times

View File

@ -15,8 +15,8 @@ class QgsGeometrySelfContactCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometrySelfContactCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools ) {}
QgsGeometrySelfContactCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = 0, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes & ) const;
QStringList getResolutionMethods() const;

View File

@ -65,7 +65,8 @@ void QgsGeometrySelfIntersectionCheck::collectErrors( QList<QgsGeometryCheckErro
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -73,7 +74,7 @@ void QgsGeometrySelfIntersectionCheck::collectErrors( QList<QgsGeometryCheckErro
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -84,7 +85,7 @@ void QgsGeometrySelfIntersectionCheck::collectErrors( QList<QgsGeometryCheckErro
{
for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )
{
for ( const QgsGeometryUtils::SelfIntersection &inter : QgsGeometryUtils::getSelfIntersections( geom, iPart, iRing, QgsGeometryCheckPrecision::tolerance() ) )
for ( const QgsGeometryUtils::SelfIntersection &inter : QgsGeometryUtils::getSelfIntersections( geom, iPart, iRing, mContext->tolerance ) )
{
errors.append( new QgsGeometrySelfIntersectionCheckError( this, layerId, featureid, inter.point, QgsVertexId( iPart, iRing ), inter ) );
}
@ -96,8 +97,9 @@ void QgsGeometrySelfIntersectionCheck::collectErrors( QList<QgsGeometryCheckErro
void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -127,7 +129,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
QgsPoint p2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment1 + 1 ) % nVerts ) );
QgsPoint q2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment2 + 1 ) % nVerts ) );
QgsPoint s;
if ( !QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, s, QgsGeometryCheckPrecision::tolerance() ) )
if ( !QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, s, mContext->tolerance ) )
{
error->setObsolete();
return;
@ -202,7 +204,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeAdded, QgsVertexId( vidx.part, poly->ringCount() - 2 ) ) );
changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeAdded, QgsVertexId( vidx.part, poly->ringCount() - 1 ) ) );
feature.setGeometry( featureGeom );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
}
else
{
@ -214,8 +216,8 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
poly2->setExteriorRing( ringGeom2 );
// Reassing interiors as necessary
QgsGeometryEngine *geomEnginePoly1 = QgsGeometryCheckerUtils::createGeomEngine( poly, QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEnginePoly2 = QgsGeometryCheckerUtils::createGeomEngine( poly2, QgsGeometryCheckPrecision::tolerance() );
QgsGeometryEngine *geomEnginePoly1 = QgsGeometryCheckerUtils::createGeomEngine( poly, mContext->tolerance );
QgsGeometryEngine *geomEnginePoly2 = QgsGeometryCheckerUtils::createGeomEngine( poly2, mContext->tolerance );
for ( int n = poly->numInteriorRings(), i = n - 1; i >= 0; --i )
{
if ( !geomEnginePoly1->contains( poly->interiorRing( i ) ) )
@ -241,7 +243,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeChanged, QgsVertexId( vidx.part, vidx.ring ) ) );
changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geom->partCount() - 1 ) ) );
feature.setGeometry( featureGeom );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
}
// Otherwise, create multipolygon
else
@ -250,7 +252,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
multiPoly->addGeometry( poly->clone() );
multiPoly->addGeometry( poly2 );
feature.setGeometry( QgsGeometry( multiPoly ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
}
}
@ -259,8 +261,8 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
QgsFeature newFeature;
newFeature.setAttributes( feature.attributes() );
newFeature.setGeometry( QgsGeometry( poly2 ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
getFeaturePool( error->layerId() )->addFeature( newFeature );
featurePool->updateFeature( feature );
featurePool->addFeature( newFeature );
changes[error->layerId()][feature.id()].append( Change( ChangeRing, ChangeChanged, QgsVertexId( vidx.part, vidx.ring ) ) );
changes[error->layerId()][newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) );
}
@ -276,7 +278,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
geomCollection->removeGeometry( vidx.part );
geomCollection->addGeometry( ringGeom1 );
geomCollection->addGeometry( ringGeom2 );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( vidx.part ) ) );
changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 2 ) ) );
changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) );
@ -287,7 +289,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
geomCollection->addGeometry( ringGeom1 );
geomCollection->addGeometry( ringGeom2 );
feature.setGeometry( QgsGeometry( geomCollection ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
}
}
@ -299,20 +301,20 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i
geomCollection->removeGeometry( vidx.part );
geomCollection->addGeometry( ringGeom1 );
feature.setGeometry( featureGeom );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( vidx.part ) ) );
changes[error->layerId()][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) );
}
else
{
feature.setGeometry( QgsGeometry( ringGeom1 ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged, QgsVertexId( vidx.part ) ) );
}
QgsFeature newFeature;
newFeature.setAttributes( feature.attributes() );
newFeature.setGeometry( QgsGeometry( ringGeom2 ) );
getFeaturePool( error->layerId() )->addFeature( newFeature );
featurePool->addFeature( newFeature );
changes[error->layerId()][newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) );
}
}

View File

@ -51,8 +51,8 @@ class QgsGeometrySelfIntersectionCheck : public QgsGeometryCheck
Q_OBJECT
public:
explicit QgsGeometrySelfIntersectionCheck( const QMap<QString, QgsFeaturePool *> &featurePools )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools ) {}
explicit QgsGeometrySelfIntersectionCheck( QgsGeometryCheckerContext *context )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context ) {}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;

View File

@ -16,9 +16,8 @@
#include "qgsgeometrysliverpolygoncheck.h"
#include "../utils/qgsfeaturepool.h"
bool QgsGeometrySliverPolygonCheck::checkThreshold( const QString &layerId, const QgsAbstractGeometry *geom, double &value ) const
bool QgsGeometrySliverPolygonCheck::checkThreshold( double mapToLayerUnits, const QgsAbstractGeometry *geom, double &value ) const
{
double mapToLayerUnits = getFeaturePool( layerId )->getMapToLayerUnits();
double maxArea = mMaxAreaMapUnits * mapToLayerUnits * mapToLayerUnits;
QgsRectangle bb = geom->boundingBox();
double maxDim = qMax( bb.width(), bb.height() );

View File

@ -23,8 +23,8 @@ class QgsGeometrySliverPolygonCheck : public QgsGeometryAreaCheck
Q_OBJECT
public:
QgsGeometrySliverPolygonCheck( const QMap<QString, QgsFeaturePool *> &featurePools, double threshold, double maxAreaMapUnits )
: QgsGeometryAreaCheck( featurePools, threshold )
QgsGeometrySliverPolygonCheck( QgsGeometryCheckerContext *context, double threshold, double maxAreaMapUnits )
: QgsGeometryAreaCheck( context, threshold )
, mMaxAreaMapUnits( maxAreaMapUnits )
{}
QString errorDescription() const override { return tr( "Sliver polygon" ); }
@ -33,7 +33,7 @@ class QgsGeometrySliverPolygonCheck : public QgsGeometryAreaCheck
private:
double mMaxAreaMapUnits;
bool checkThreshold( const QString &layerId, const QgsAbstractGeometry *geom, double &value ) const override;
bool checkThreshold( double mapToLayerUnits, const QgsAbstractGeometry *geom, double &value ) const override;
};
#endif // QGS_GEOMETRY_SLIVERPOLYGON_CHECK_H

View File

@ -28,7 +28,8 @@ void QgsGeometryTypeCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
for ( const QString &layerId : featureIds.keys() )
{
if ( !getCompatibility( getFeaturePool( layerId )->getLayer()->geometryType() ) )
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
if ( !getCompatibility( featurePool->getLayer()->geometryType() ) )
{
continue;
}
@ -36,7 +37,7 @@ void QgsGeometryTypeCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !getFeaturePool( layerId )->get( featureid, feature ) )
if ( !featurePool->get( featureid, feature ) )
{
continue;
}
@ -54,8 +55,9 @@ void QgsGeometryTypeCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
void QgsGeometryTypeCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !getFeaturePool( error->layerId() )->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
@ -87,12 +89,12 @@ void QgsGeometryTypeCheck::fixError( QgsGeometryCheckError *error, int method, c
QgsFeature newFeature;
newFeature.setAttributes( feature.attributes() );
newFeature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, iPart )->clone() ) );
getFeaturePool( error->layerId() )->addFeature( newFeature );
featurePool->addFeature( newFeature );
changes[error->layerId()][newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) );
}
// Recycle feature for part 0
feature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, 0 )->clone() ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
}
// Check if corresponding multi type is allowed
@ -138,21 +140,21 @@ void QgsGeometryTypeCheck::fixError( QgsGeometryCheckError *error, int method, c
geomCollection->addGeometry( geom->clone() );
feature.setGeometry( QgsGeometry( geomCollection ) );
getFeaturePool( error->layerId() )->updateFeature( feature );
featurePool->updateFeature( feature );
changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
}
}
// Delete feature
else
{
getFeaturePool( error->layerId() )->deleteFeature( feature );
featurePool->deleteFeature( feature );
changes[error->layerId()][error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) );
}
error->setFixed( method );
}
else if ( method == Delete )
{
getFeaturePool( error->layerId() )->deleteFeature( feature );
featurePool->deleteFeature( feature );
error->setFixed( method );
changes[error->layerId()][error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) );
}

View File

@ -48,8 +48,8 @@ class QgsGeometryTypeCheck : public QgsGeometryCheck
Q_OBJECT
public:
QgsGeometryTypeCheck( const QMap<QString, QgsFeaturePool *> &featurePools, int allowedTypes )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PointGeometry, QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, featurePools )
QgsGeometryTypeCheck( QgsGeometryCheckerContext *context, int allowedTypes )
: QgsGeometryCheck( FeatureCheck, {QgsWkbTypes::PointGeometry, QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context )
, mAllowedTypes( allowedTypes )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;

View File

@ -24,9 +24,9 @@
#include <QTimer>
QgsGeometryChecker::QgsGeometryChecker( const QList<QgsGeometryCheck *> &checks, const QMap<QString, QgsFeaturePool *> &featurePools )
QgsGeometryChecker::QgsGeometryChecker( const QList<QgsGeometryCheck *> &checks, QgsGeometryCheckerContext *context )
: mChecks( checks )
, mFeaturePools( featurePools )
, mContext( context )
{
}
@ -34,6 +34,13 @@ QgsGeometryChecker::~QgsGeometryChecker()
{
qDeleteAll( mCheckErrors );
qDeleteAll( mChecks );
for ( const QgsFeaturePool *featurePool : mContext->featurePools.values() )
{
if ( featurePool->getLayer() )
featurePool->getLayer()->setReadOnly( false );
delete featurePool;
}
delete mContext;
}
QFuture<void> QgsGeometryChecker::execute( int *totalSteps )
@ -43,7 +50,7 @@ QFuture<void> QgsGeometryChecker::execute( int *totalSteps )
*totalSteps = 0;
for ( QgsGeometryCheck *check : mChecks )
{
for ( const QgsFeaturePool *featurePool : mFeaturePools.values() )
for ( const QgsFeaturePool *featurePool : mContext->featurePools.values() )
{
if ( check->getCheckType() <= QgsGeometryCheck::FeatureCheck )
{
@ -118,7 +125,7 @@ bool QgsGeometryChecker::fixError( QgsGeometryCheckError *error, int method, boo
if ( !removed )
{
QgsFeature f;
if ( mFeaturePools[layerId]->get( id, f ) )
if ( mContext->featurePools[layerId]->get( id, f ) )
{
recheckFeatures[layerId].insert( id );
recheckArea.combineExtentWith( f.geometry().boundingBox() );
@ -137,15 +144,16 @@ bool QgsGeometryChecker::fixError( QgsGeometryCheckError *error, int method, boo
}
}
}
recheckArea.grow( 10 * QgsGeometryCheckPrecision::tolerance() );
recheckArea.grow( 10 * mContext->tolerance );
QMap<QString, QgsFeatureIds> recheckAreaFeatures;
for ( const QString &layerId : mFeaturePools.keys() )
for ( const QString &layerId : mContext->featurePools.keys() )
{
recheckAreaFeatures[layerId] = mFeaturePools[layerId]->getIntersects( recheckArea );
QgsFeaturePool *featurePool = mContext->featurePools[layerId];
recheckAreaFeatures[layerId] = featurePool->getIntersects( recheckArea );
// If only selected features were checked, confine the recheck areas to the selected features
if ( mFeaturePools[layerId]->getSelectedOnly() )
if ( featurePool->getSelectedOnly() )
{
recheckAreaFeatures[layerId] = recheckAreaFeatures[layerId].intersect( mFeaturePools[layerId]->getLayer()->selectedFeatureIds() );
recheckAreaFeatures[layerId] = recheckAreaFeatures[layerId].intersect( featurePool->getLayer()->selectedFeatureIds() );
}
}
@ -249,7 +257,7 @@ bool QgsGeometryChecker::fixError( QgsGeometryCheckError *error, int method, boo
{
for ( const QString &layerId : changes.keys() )
{
mFeaturePools[layerId]->getLayer()->triggerRepaint();
mContext->featurePools[layerId]->getLayer()->triggerRepaint();
}
}

View File

@ -24,7 +24,7 @@
typedef qint64 QgsFeatureId;
typedef QSet<QgsFeatureId> QgsFeatureIds;
class QgsFeaturePool;
struct QgsGeometryCheckerContext;
class QgsGeometryCheck;
class QgsGeometryCheckError;
class QgsMapLayer;
@ -35,13 +35,14 @@ class QgsGeometryChecker : public QObject
{
Q_OBJECT
public:
QgsGeometryChecker( const QList<QgsGeometryCheck *> &checks, const QMap<QString, QgsFeaturePool *> &featurePools );
QgsGeometryChecker( const QList<QgsGeometryCheck *> &checks, QgsGeometryCheckerContext *context );
~QgsGeometryChecker();
QFuture<void> execute( int *totalSteps = nullptr );
bool fixError( QgsGeometryCheckError *error, int method, bool triggerRepaint = false );
const QList<QgsGeometryCheck *> getChecks() const { return mChecks; }
QStringList getMessages() const { return mMessages; }
void setMergeAttributeIndices( const QMap<QString, int> &mergeAttributeIndices ) { mMergeAttributeIndices = mergeAttributeIndices; }
QgsGeometryCheckerContext *getContext() const { return mContext; }
signals:
void errorAdded( QgsGeometryCheckError *error );
@ -59,7 +60,7 @@ class QgsGeometryChecker : public QObject
};
QList<QgsGeometryCheck *> mChecks;
QMap<QString, QgsFeaturePool *> mFeaturePools;
QgsGeometryCheckerContext *mContext;
QList<QgsGeometryCheckError *> mCheckErrors;
QStringList mMessages;
QMutex mErrorListMutex;

View File

@ -50,13 +50,13 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryAngleCheck>::checkApplicabil
return ui.checkBoxAngle->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryAngleCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryAngleCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkAngle", ui.checkBoxAngle->isChecked() );
QgsSettings().setValue( sSettingsGroup + "minimalAngle", ui.doubleSpinBoxAngle->value() );
if ( ui.checkBoxAngle->isEnabled() && ui.checkBoxAngle->isChecked() )
{
return new QgsGeometryAngleCheck( featurePools, ui.doubleSpinBoxAngle->value() );
return new QgsGeometryAngleCheck( context, ui.doubleSpinBoxAngle->value() );
}
else
{
@ -80,13 +80,13 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryAreaCheck>::checkApplicabili
return ui.checkBoxArea->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryAreaCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryAreaCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkArea", ui.checkBoxArea->isChecked() );
QgsSettings().setValue( sSettingsGroup + "minimalArea", ui.doubleSpinBoxArea->value() );
if ( ui.checkBoxArea->isEnabled() && ui.checkBoxArea->isChecked() )
{
return new QgsGeometryAreaCheck( featurePools, ui.doubleSpinBoxArea->value() );
return new QgsGeometryAreaCheck( context, ui.doubleSpinBoxArea->value() );
}
else
{
@ -109,12 +109,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryContainedCheck>::checkApplic
return ui.checkBoxCovered->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryContainedCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryContainedCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkCovers", ui.checkBoxCovered->isChecked() );
if ( ui.checkBoxCovered->isEnabled() && ui.checkBoxCovered->isChecked() )
{
return new QgsGeometryContainedCheck( featurePools );
return new QgsGeometryContainedCheck( context );
}
else
{
@ -137,12 +137,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryDegeneratePolygonCheck>::che
return ui.checkBoxDegeneratePolygon->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryDegeneratePolygonCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryDegeneratePolygonCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkDegeneratePolygon", ui.checkBoxDegeneratePolygon->isChecked() );
if ( ui.checkBoxDegeneratePolygon->isEnabled() && ui.checkBoxDegeneratePolygon->isChecked() )
{
return new QgsGeometryDegeneratePolygonCheck( featurePools );
return new QgsGeometryDegeneratePolygonCheck( context );
}
else
{
@ -165,12 +165,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryDuplicateCheck>::checkApplic
return ui.checkBoxDuplicates->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryDuplicateCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryDuplicateCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkDuplicates", ui.checkBoxDuplicates->isChecked() );
if ( ui.checkBoxDuplicates->isEnabled() && ui.checkBoxDuplicates->isChecked() )
{
return new QgsGeometryDuplicateCheck( featurePools );
return new QgsGeometryDuplicateCheck( context );
}
else
{
@ -193,12 +193,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryDuplicateNodesCheck>::checkA
return ui.checkBoxDuplicateNodes->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryDuplicateNodesCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryDuplicateNodesCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkDuplicateNodes", ui.checkBoxDuplicateNodes->isChecked() );
if ( ui.checkBoxDuplicateNodes->isEnabled() && ui.checkBoxDuplicateNodes->isChecked() )
{
return new QgsGeometryDuplicateNodesCheck( featurePools );
return new QgsGeometryDuplicateNodesCheck( context );
}
else
{
@ -223,13 +223,13 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryGapCheck>::checkApplicabilit
return ui.checkBoxGaps->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryGapCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryGapCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkGaps", ui.checkBoxGaps->isChecked() );
QgsSettings().setValue( sSettingsGroup + "maxGapArea", ui.doubleSpinBoxGapArea->value() );
if ( ui.checkBoxGaps->isEnabled() && ui.checkBoxGaps->isChecked() )
{
return new QgsGeometryGapCheck( featurePools, ui.doubleSpinBoxGapArea->value() );
return new QgsGeometryGapCheck( context, ui.doubleSpinBoxGapArea->value() );
}
else
{
@ -252,12 +252,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryHoleCheck>::checkApplicabili
return ui.checkBoxNoHoles->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryHoleCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryHoleCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkHoles", ui.checkBoxNoHoles->isChecked() );
if ( ui.checkBoxNoHoles->isEnabled() && ui.checkBoxNoHoles->isChecked() )
{
return new QgsGeometryHoleCheck( featurePools );
return new QgsGeometryHoleCheck( context );
}
else
{
@ -279,12 +279,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryMultipartCheck>::checkApplic
return true;
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryMultipartCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryMultipartCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkMultipart", ui.checkBoxMultipart->isChecked() );
if ( ui.checkBoxMultipart->isEnabled() && ui.checkBoxMultipart->isChecked() )
{
return new QgsGeometryMultipartCheck( featurePools );
return new QgsGeometryMultipartCheck( context );
}
else
{
@ -309,13 +309,13 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryOverlapCheck>::checkApplicab
return ui.checkBoxOverlaps->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryOverlapCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryOverlapCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkOverlaps", ui.checkBoxOverlaps->isChecked() );
QgsSettings().setValue( sSettingsGroup + "maxOverlapArea", ui.doubleSpinBoxOverlapArea->value() );
if ( ui.checkBoxOverlaps->isEnabled() && ui.checkBoxOverlaps->isChecked() )
{
return new QgsGeometryOverlapCheck( featurePools, ui.doubleSpinBoxOverlapArea->value() );
return new QgsGeometryOverlapCheck( context, ui.doubleSpinBoxOverlapArea->value() );
}
else
{
@ -340,13 +340,13 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometrySegmentLengthCheck>::checkAp
return ui.checkBoxSegmentLength->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySegmentLengthCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySegmentLengthCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkSegmentLength", ui.checkBoxSegmentLength->isChecked() );
QgsSettings().setValue( sSettingsGroup + "minSegmentLength", ui.doubleSpinBoxSegmentLength->value() );
if ( ui.checkBoxSegmentLength->isEnabled() && ui.checkBoxSegmentLength->isChecked() )
{
return new QgsGeometrySegmentLengthCheck( featurePools, ui.doubleSpinBoxSegmentLength->value() );
return new QgsGeometrySegmentLengthCheck( context, ui.doubleSpinBoxSegmentLength->value() );
}
else
{
@ -369,12 +369,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometrySelfContactCheck>::checkAppl
return ui.checkBoxSelfContacts->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySelfContactCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySelfContactCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkSelfContacts", ui.checkBoxSelfContacts->isChecked() );
if ( ui.checkBoxSelfContacts->isEnabled() && ui.checkBoxSelfContacts->isChecked() )
{
return new QgsGeometrySelfContactCheck( featurePools );
return new QgsGeometrySelfContactCheck( context );
}
else
{
@ -397,12 +397,12 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometrySelfIntersectionCheck>::chec
return ui.checkBoxSelfIntersections->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySelfIntersectionCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySelfIntersectionCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkSelfIntersections", ui.checkBoxSelfIntersections->isChecked() );
if ( ui.checkBoxSelfIntersections->isEnabled() && ui.checkBoxSelfIntersections->isChecked() )
{
return new QgsGeometrySelfIntersectionCheck( featurePools );
return new QgsGeometrySelfIntersectionCheck( context );
}
else
{
@ -429,7 +429,7 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometrySliverPolygonCheck>::checkAp
return ui.checkBoxSliverPolygons->isEnabled();
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySliverPolygonCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySliverPolygonCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
double threshold = ui.doubleSpinBoxSliverThinness->value();
double maxArea = ui.checkBoxSliverArea->isChecked() ? ui.doubleSpinBoxSliverArea->value() : 0.;
@ -439,7 +439,7 @@ template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometrySliverPolygonCh
QgsSettings().setValue( sSettingsGroup + "checkSliverPolygons", ui.checkBoxSliverPolygons->isChecked() );
if ( ui.checkBoxSliverPolygons->isEnabled() && ui.checkBoxSliverPolygons->isChecked() )
{
return new QgsGeometrySliverPolygonCheck( featurePools, threshold, maxArea );
return new QgsGeometrySliverPolygonCheck( context, threshold, maxArea );
}
else
{
@ -466,7 +466,7 @@ template<> bool QgsGeometryCheckFactoryT<QgsGeometryTypeCheck>::checkApplicabili
return true;
}
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryTypeCheck>::createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const
template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryTypeCheck>::createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const
{
QgsSettings().setValue( sSettingsGroup + "checkTypePoint", ui.checkBoxPoint->isChecked() );
QgsSettings().setValue( sSettingsGroup + "checkTypeMultipoint", ui.checkBoxMultipoint->isChecked() );
@ -502,7 +502,7 @@ template<> QgsGeometryCheck *QgsGeometryCheckFactoryT<QgsGeometryTypeCheck>::cre
}
if ( allowedTypes != 0 )
{
return new QgsGeometryTypeCheck( featurePools, allowedTypes );
return new QgsGeometryTypeCheck( context, allowedTypes );
}
else
{

View File

@ -18,7 +18,7 @@
#include "qgis.h"
#include "ui_qgsgeometrycheckersetuptab.h"
class QgsFeaturePool;
struct QgsGeometryCheckerContext;
class QgsGeometryCheck;
class QgsGeometryCheckFactory
@ -27,7 +27,7 @@ class QgsGeometryCheckFactory
virtual ~QgsGeometryCheckFactory() = default;
virtual void restorePrevious( Ui::QgsGeometryCheckerSetupTab & /*ui*/ ) const = 0;
virtual bool checkApplicability( Ui::QgsGeometryCheckerSetupTab & /*ui*/, int /*nPoint*/, int /*nLineString*/, int /*nPolygon*/ ) const = 0;
virtual QgsGeometryCheck *createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const = 0;
virtual QgsGeometryCheck *createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const = 0;
protected:
static QString sSettingsGroup;
@ -38,7 +38,7 @@ class QgsGeometryCheckFactoryT : public QgsGeometryCheckFactory
{
void restorePrevious( Ui::QgsGeometryCheckerSetupTab & /*ui*/ ) const override;
bool checkApplicability( Ui::QgsGeometryCheckerSetupTab &ui, int nPoint, int nLineString, int nPolygon ) const override;
QgsGeometryCheck *createInstance( const QMap<QString, QgsFeaturePool *> &featurePools, const Ui::QgsGeometryCheckerSetupTab &ui ) const override;
QgsGeometryCheck *createInstance( QgsGeometryCheckerContext *context, const Ui::QgsGeometryCheckerSetupTab &ui ) const override;
};
class QgsGeometryCheckFactoryRegistry

View File

@ -57,11 +57,11 @@ QgsGeometryCheckerDialog::~QgsGeometryCheckerDialog()
s.setValue( QStringLiteral( "/Plugin-GeometryChecker/Window/geometry" ), saveGeometry() );
}
void QgsGeometryCheckerDialog::onCheckerStarted( QgsGeometryChecker *checker, QMap<QString, QgsFeaturePool *> featurePools )
void QgsGeometryCheckerDialog::onCheckerStarted( QgsGeometryChecker *checker )
{
delete mTabWidget->widget( 1 );
mTabWidget->removeTab( 1 );
mTabWidget->addTab( new QgsGeometryCheckerResultTab( mIface, checker, featurePools, mTabWidget ), tr( "Result" ) );
mTabWidget->addTab( new QgsGeometryCheckerResultTab( mIface, checker, mTabWidget ), tr( "Result" ) );
mTabWidget->setTabEnabled( 1, false );
mButtonBox->button( QDialogButtonBox::Close )->setEnabled( false );
}

View File

@ -45,7 +45,7 @@ class QgsGeometryCheckerDialog : public QDialog
void closeEvent( QCloseEvent *ev ) override;
private slots:
void onCheckerStarted( QgsGeometryChecker *checker, QMap<QString, QgsFeaturePool *> featurePools );
void onCheckerStarted( QgsGeometryChecker *checker );
void onCheckerFinished( bool successful );
void showHelp();
};

View File

@ -15,14 +15,15 @@
***************************************************************************/
#include "qgsgeometrycheckerfixsummarydialog.h"
#include "../qgsgeometrychecker.h"
#include "../checks/qgsgeometrycheck.h"
#include "../utils/qgsfeaturepool.h"
#include "qgisinterface.h"
#include "qgsmapcanvas.h"
QgsGeometryCheckerFixSummaryDialog::QgsGeometryCheckerFixSummaryDialog( const QMap<QString, QgsFeaturePool *> &featurePools, const Statistics &stats, const QStringList &messages, QWidget *parent )
QgsGeometryCheckerFixSummaryDialog::QgsGeometryCheckerFixSummaryDialog( const Statistics &stats, QgsGeometryChecker *checker, QWidget *parent )
: QDialog( parent )
, mFeaturePools( featurePools )
, mChecker( checker )
{
ui.setupUi( this );
@ -53,20 +54,20 @@ QgsGeometryCheckerFixSummaryDialog::QgsGeometryCheckerFixSummaryDialog( const QM
setupTable( ui.tableWidgetNotFixed );
setupTable( ui.tableWidgetObsoleteErrors );
ui.plainTextEditMessages->setPlainText( messages.join( QStringLiteral( "\n" ) ) );
ui.plainTextEditMessages->setPlainText( checker->getMessages().join( QStringLiteral( "\n" ) ) );
ui.groupBoxFixedErrors->setVisible( !stats.fixedErrors.isEmpty() );
ui.groupBoxNewErrors->setVisible( !stats.newErrors.isEmpty() );
ui.groupBoxNotFixed->setVisible( !stats.failedErrors.isEmpty() );
ui.groupBoxObsoleteErrors->setVisible( !stats.obsoleteErrors.isEmpty() );
ui.groupBoxMessages->setVisible( !messages.isEmpty() );
ui.groupBoxMessages->setVisible( !checker->getMessages().isEmpty() );
}
void QgsGeometryCheckerFixSummaryDialog::addError( QTableWidget *table, QgsGeometryCheckError *error )
{
int prec = 7 - std::floor( std::max( 0., std::log10( std::max( error->location().x(), error->location().y() ) ) ) );
QString posStr = QStringLiteral( "%1, %2" ).arg( error->location().x(), 0, 'f', prec ).arg( error->location().y(), 0, 'f', prec );
double layerToMap = 1. / mFeaturePools[error->layerId()]->getMapToLayerUnits();
double layerToMap = 1. / mChecker->getContext()->featurePools[error->layerId()]->getMapToLayerUnits();
QVariant value;
if ( error->valueType() == QgsGeometryCheckError::ValueLength )
{

View File

@ -23,7 +23,7 @@
class QgisInterface;
class QgsGeometryCheckError;
class QgsFeaturePool;
class QgsGeometryChecker;
class QgsGeometryCheckerFixSummaryDialog : public QDialog
{
@ -41,14 +41,14 @@ class QgsGeometryCheckerFixSummaryDialog : public QDialog
}
};
QgsGeometryCheckerFixSummaryDialog( const QMap<QString, QgsFeaturePool *> &featurePools, const Statistics &stats, const QStringList &messages, QWidget *parent = nullptr );
QgsGeometryCheckerFixSummaryDialog( const Statistics &stats, QgsGeometryChecker *checker, QWidget *parent = nullptr );
signals:
void errorSelected( QgsGeometryCheckError *error );
private:
Ui::QgsGeometryCheckerFixSummaryDialog ui;
QMap<QString, QgsFeaturePool *> mFeaturePools;
QgsGeometryChecker *mChecker;
void addError( QTableWidget *table, QgsGeometryCheckError *error );
void setupTable( QTableWidget *table );

View File

@ -43,23 +43,22 @@
QString QgsGeometryCheckerResultTab::sSettingsGroup = QStringLiteral( "/geometry_checker/default_fix_methods/" );
QgsGeometryCheckerResultTab::QgsGeometryCheckerResultTab( QgisInterface *iface, QgsGeometryChecker *checker, const QMap<QString, QgsFeaturePool *> &featurePools, QTabWidget *tabWidget, QWidget *parent )
QgsGeometryCheckerResultTab::QgsGeometryCheckerResultTab( QgisInterface *iface, QgsGeometryChecker *checker, QTabWidget *tabWidget, QWidget *parent )
: QWidget( parent )
, mTabWidget( tabWidget )
, mIface( iface )
, mChecker( checker )
, mFeaturePools( featurePools )
{
ui.setupUi( this );
mErrorCount = 0;
mFixedCount = 0;
mCloseable = true;
for ( const QString &layerId : mFeaturePools.keys() )
for ( const QString &layerId : mChecker->getContext()->featurePools.keys() )
{
QTreeWidgetItem *item = new QTreeWidgetItem( ui.treeWidgetMergeAttribute, QStringList() << layerId << "" );
QComboBox *attribCombo = new QComboBox();
QgsVectorLayer *layer = mFeaturePools[layerId]->getLayer();
QgsVectorLayer *layer = mChecker->getContext()->featurePools[layerId]->getLayer();
for ( int i = 0, n = layer->fields().count(); i < n; ++i )
{
attribCombo->addItem( layer->fields().at( i ).name() );
@ -83,7 +82,7 @@ QgsGeometryCheckerResultTab::QgsGeometryCheckerResultTab( QgisInterface *iface,
connect( ui.pushButtonExport, &QAbstractButton::clicked, this, &QgsGeometryCheckerResultTab::exportErrors );
bool allLayersEditable = true;
for ( const QgsFeaturePool *featurePool : mFeaturePools.values() )
for ( const QgsFeaturePool *featurePool : mChecker->getContext()->featurePools.values() )
{
if ( ( featurePool->getLayer()->dataProvider()->capabilities() & QgsVectorDataProvider::ChangeGeometries ) == 0 )
{
@ -106,12 +105,7 @@ QgsGeometryCheckerResultTab::QgsGeometryCheckerResultTab( QgisInterface *iface,
QgsGeometryCheckerResultTab::~QgsGeometryCheckerResultTab()
{
for ( const QgsFeaturePool *featurePool : mFeaturePools.values() )
{
if ( featurePool->getLayer() )
featurePool->getLayer()->setReadOnly( false );
delete featurePool;
}
delete mChecker;
qDeleteAll( mCurrentRubberBands );
}
@ -143,7 +137,7 @@ void QgsGeometryCheckerResultTab::addError( QgsGeometryCheckError *error )
int row = ui.tableWidgetErrors->rowCount();
int prec = 7 - std::floor( std::max( 0., std::log10( std::max( error->location().x(), error->location().y() ) ) ) );
QString posStr = QStringLiteral( "%1, %2" ).arg( error->location().x(), 0, 'f', prec ).arg( error->location().y(), 0, 'f', prec );
double layerToMap = 1. / mFeaturePools[error->layerId()]->getMapToLayerUnits();
double layerToMap = 1. / mChecker->getContext()->featurePools[error->layerId()]->getMapToLayerUnits();
QVariant value;
if ( error->valueType() == QgsGeometryCheckError::ValueLength )
{
@ -191,7 +185,7 @@ void QgsGeometryCheckerResultTab::updateError( QgsGeometryCheckError *error, boo
int row = mErrorMap.value( error ).row();
int prec = 7 - std::floor( std::max( 0., std::log10( std::max( error->location().x(), error->location().y() ) ) ) );
QString posStr = QStringLiteral( "%1, %2" ).arg( error->location().x(), 0, 'f', prec ).arg( error->location().y(), 0, 'f', prec );
double layerToMap = 1. / mFeaturePools[error->layerId()]->getMapToLayerUnits();
double layerToMap = 1. / mChecker->getContext()->featurePools[error->layerId()]->getMapToLayerUnits();
QVariant value;
if ( error->valueType() == QgsGeometryCheckError::ValueLength )
{
@ -243,7 +237,7 @@ void QgsGeometryCheckerResultTab::updateError( QgsGeometryCheckError *error, boo
void QgsGeometryCheckerResultTab::exportErrors()
{
QString initialdir;
QDir dir = QFileInfo( mFeaturePools.first()->getLayer()->dataProvider()->dataSourceUri() ).dir();
QDir dir = QFileInfo( mChecker->getContext()->featurePools.first()->getLayer()->dataProvider()->dataSourceUri() ).dir();
if ( dir.exists() )
{
initialdir = dir.absolutePath();
@ -295,7 +289,7 @@ bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString &file )
for ( int row = 0, nRows = ui.tableWidgetErrors->rowCount(); row < nRows; ++row )
{
QgsGeometryCheckError *error = ui.tableWidgetErrors->item( row, 0 )->data( Qt::UserRole ).value<QgsGeometryCheckError *>();
QgsVectorLayer *srcLayer = mFeaturePools[error->layerId()]->getLayer();
QgsVectorLayer *srcLayer = mChecker->getContext()->featurePools[error->layerId()]->getLayer();
QgsFeature f( layer->fields() );
f.setAttribute( fieldLayer, srcLayer->name() );
f.setAttribute( fieldFeatureId, error->featureId() );
@ -356,7 +350,7 @@ void QgsGeometryCheckerResultTab::highlightErrors( bool current )
for ( QTableWidgetItem *item : items )
{
QgsGeometryCheckError *error = ui.tableWidgetErrors->item( item->row(), 0 )->data( Qt::UserRole ).value<QgsGeometryCheckError *>();
QgsVectorLayer *layer = mFeaturePools[error->layerId()]->getLayer();
QgsVectorLayer *layer = mChecker->getContext()->featurePools[error->layerId()]->getLayer();
QgsAbstractGeometry *geometry = error->geometry();
if ( ui.checkBoxHighlight->isChecked() && geometry )
@ -475,7 +469,7 @@ void QgsGeometryCheckerResultTab::openAttributeTable()
{
mAttribTableDialogs[layerId]->close();
}
mAttribTableDialogs[layerId] = mIface->showAttributeTable( mFeaturePools[layerId]->getLayer(), expr.join( QStringLiteral( " or " ) ) );
mAttribTableDialogs[layerId] = mIface->showAttributeTable( mChecker->getContext()->featurePools[layerId]->getLayer(), expr.join( QStringLiteral( " or " ) ) );
}
}
@ -543,14 +537,14 @@ void QgsGeometryCheckerResultTab::fixErrors( bool prompt )
ui.progressBarFixErrors->setVisible( false );
unsetCursor();
}
for ( const QString &layerId : mFeaturePools.keys() )
for ( const QString &layerId : mChecker->getContext()->featurePools.keys() )
{
mFeaturePools[layerId]->getLayer()->triggerRepaint();
mChecker->getContext()->featurePools[layerId]->getLayer()->triggerRepaint();
}
if ( mStatistics.itemCount() > 0 )
{
QgsGeometryCheckerFixSummaryDialog summarydialog( mFeaturePools, mStatistics, mChecker->getMessages(), mIface->mainWindow() );
QgsGeometryCheckerFixSummaryDialog summarydialog( mStatistics, mChecker, mIface->mainWindow() );
QEventLoop loop;
connect( &summarydialog, &QgsGeometryCheckerFixSummaryDialog::errorSelected, this, &QgsGeometryCheckerResultTab::highlightError );
connect( &summarydialog, &QDialog::finished, &loop, &QEventLoop::quit );
@ -632,11 +626,11 @@ void QgsGeometryCheckerResultTab::storeDefaultResolutionMethod( int id ) const
void QgsGeometryCheckerResultTab::checkRemovedLayer( const QStringList &ids )
{
bool requiredLayersRemoved = false;
for ( const QString &id : mFeaturePools.keys() )
for ( const QString &layerId : mChecker->getContext()->featurePools.keys() )
{
if ( ids.contains( id ) && isEnabled() )
if ( ids.contains( layerId ) && isEnabled() )
{
mFeaturePools[id]->clearLayer();
mChecker->getContext()->featurePools[layerId]->clearLayer();
requiredLayersRemoved = true;
}
}

View File

@ -32,7 +32,7 @@ class QgsGeometryCheckerResultTab : public QWidget
{
Q_OBJECT
public:
QgsGeometryCheckerResultTab( QgisInterface *iface, QgsGeometryChecker *checker, const QMap<QString, QgsFeaturePool *> &featurePools, QTabWidget *tabWidget, QWidget *parent = nullptr );
QgsGeometryCheckerResultTab( QgisInterface *iface, QgsGeometryChecker *checker, QTabWidget *tabWidget, QWidget *parent = nullptr );
~QgsGeometryCheckerResultTab();
void finalize();
bool isCloseable() const { return mCloseable; }
@ -44,7 +44,6 @@ class QgsGeometryCheckerResultTab : public QWidget
Ui::QgsGeometryCheckerResultTab ui;
QgisInterface *mIface = nullptr;
QgsGeometryChecker *mChecker = nullptr;
QMap<QString, QgsFeaturePool *> mFeaturePools;
QList<QgsRubberBand *> mCurrentRubberBands;
QMap<QgsGeometryCheckError *, QPersistentModelIndex> mErrorMap;
QMap<QString, QPointer<QDialog>> mAttribTableDialogs;

View File

@ -69,8 +69,8 @@ QgsGeometryCheckerSetupTab::QgsGeometryCheckerSetupTab( QgisInterface *iface, QW
connect( QgsProject::instance(), static_cast<void ( QgsProject::* )( const QStringList & )>( &QgsProject::layersWillBeRemoved ), this, &QgsGeometryCheckerSetupTab::updateLayers );
connect( ui.radioButtonOutputNew, &QAbstractButton::toggled, ui.frameOutput, &QWidget::setEnabled );
connect( ui.buttonGroupOutput, static_cast<void ( QButtonGroup::* )( int )>( &QButtonGroup::buttonClicked ), this, &QgsGeometryCheckerSetupTab::validateInput );
connect( ui.pushButtonOutputBrowse, &QAbstractButton::clicked, this, &QgsGeometryCheckerSetupTab::selectOutputFile );
connect( ui.lineEditOutput, &QLineEdit::textChanged, this, &QgsGeometryCheckerSetupTab::validateInput );
connect( ui.pushButtonOutputDirectory, &QAbstractButton::clicked, this, &QgsGeometryCheckerSetupTab::selectOutputDirectory );
connect( ui.lineEditOutputDirectory, &QLineEdit::textChanged, this, &QgsGeometryCheckerSetupTab::validateInput );
connect( ui.checkBoxSliverPolygons, &QAbstractButton::toggled, ui.widgetSliverThreshold, &QWidget::setEnabled );
connect( ui.checkBoxSliverArea, &QAbstractButton::toggled, ui.doubleSpinBoxSliverArea, &QWidget::setEnabled );
@ -153,6 +153,7 @@ QList<QgsVectorLayer *> QgsGeometryCheckerSetupTab::getSelectedLayers()
void QgsGeometryCheckerSetupTab::validateInput()
{
QStringList layerCrs = QStringList() << mIface->mapCanvas()->mapSettings().destinationCrs().authid();
QList<QgsVectorLayer *> layers = getSelectedLayers();
int nApplicable = 0;
if ( !layers.isEmpty() )
@ -175,17 +176,27 @@ void QgsGeometryCheckerSetupTab::validateInput()
{
++nPolygon;
}
layerCrs.append( layer->crs().authid() );
}
for ( const QgsGeometryCheckFactory *factory : QgsGeometryCheckFactoryRegistry::getCheckFactories() )
{
nApplicable += factory->checkApplicability( ui, nPoint, nLineString, nPolygon );
}
}
QString prevCrs = ui.comboBoxTopologyCrs->currentText();
ui.comboBoxTopologyCrs->clear();
ui.comboBoxTopologyCrs->addItems( layerCrs );
ui.comboBoxTopologyCrs->setCurrentIndex( ui.comboBoxTopologyCrs->findText( prevCrs ) );
if ( ui.comboBoxTopologyCrs->currentIndex() == -1 )
{
ui.comboBoxTopologyCrs->setCurrentIndex( 0 );
}
bool outputOk = ui.radioButtonOutputModifyInput->isChecked() || !ui.lineEditOutputDirectory->text().isEmpty();
mRunButton->setEnabled( !layers.isEmpty() && nApplicable > 0 && outputOk );
}
void QgsGeometryCheckerSetupTab::selectOutputFile()
void QgsGeometryCheckerSetupTab::selectOutputDirectory()
{
QString filterString = QgsVectorFileWriter::filterForDriver( QStringLiteral( "GPKG" ) );
QMap<QString, QString> filterFormatMap = QgsVectorFileWriter::supportedFiltersAndFormats();
@ -397,19 +408,20 @@ void QgsGeometryCheckerSetupTab::runChecks()
featurePools.insert( layer->id(), new QgsFeaturePool( layer, mapToLayerUnits, selectedOnly ) );
}
QgsGeometryCheckerContext *context = new QgsGeometryCheckerContext( ui.spinBoxTolerance->value(), ui.comboBoxTopologyCrs->currentText(), featurePools );
QList<QgsGeometryCheck *> checks;
for ( const QgsGeometryCheckFactory *factory : QgsGeometryCheckFactoryRegistry::getCheckFactories() )
{
QgsGeometryCheck *check = factory->createInstance( featurePools, ui );
QgsGeometryCheck *check = factory->createInstance( context, ui );
if ( check )
{
checks.append( check );
}
}
QgsGeometryCheckPrecision::setPrecision( ui.spinBoxTolerance->value() );
QgsGeometryChecker *checker = new QgsGeometryChecker( checks, featurePools );
QgsGeometryChecker *checker = new QgsGeometryChecker( checks, context );
emit checkerStarted( checker, featurePools );
emit checkerStarted( checker );
// Add result layer (do this after checkerStarted, otherwise warning about removing of result layer may appear)
for ( QgsVectorLayer *layer : processLayers )

View File

@ -35,7 +35,7 @@ class QgsGeometryCheckerSetupTab : public QWidget
~QgsGeometryCheckerSetupTab();
signals:
void checkerStarted( QgsGeometryChecker *checker, QMap<QString, QgsFeaturePool *> featurePools );
void checkerStarted( QgsGeometryChecker *checker );
void checkerFinished( bool );
private:
@ -51,7 +51,7 @@ class QgsGeometryCheckerSetupTab : public QWidget
void runChecks();
void updateLayers();
void validateInput();
void selectOutputFile();
void selectOutputDirectory();
void showCancelFeedback();
};

View File

@ -41,9 +41,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-46</y>
<y>-106</y>
<width>626</width>
<height>804</height>
<height>832</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_4">
@ -549,10 +549,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>2</number>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<property name="leftMargin">
<number>2</number>
</property>
@ -565,14 +562,7 @@
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QLabel" name="labelTolerance">
<property name="text">
<string>Tolerance</string>
</property>
</widget>
</item>
<item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinBoxTolerance">
<property name="prefix">
<string notr="true">1E-</string>
@ -588,6 +578,23 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelTolerance">
<property name="text">
<string>Tolerance</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelTopologyCrs">
<property name="text">
<string>CRS for topology checks:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxTopologyCrs"/>
</item>
</layout>
</item>
<item>