QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsgeometryfollowboundariescheck.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometryfollowboundariescheck.cpp
3  ---------------------
4  begin : September 2017
5  copyright : (C) 2017 by Sandro Mani / Sourcepole AG
6  email : smani at sourcepole dot ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
18 #include "qgsgeometryengine.h"
19 #include "qgsproject.h"
20 #include "qgsspatialindex.h"
21 #include "qgsvectorlayer.h"
22 #include "qgsgeometrycheckerror.h"
23 
25  : QgsGeometryCheck( context, configuration )
26 {
27  mCheckLayer = checkLayer;
28  if ( mCheckLayer )
29  {
30  mIndex = new QgsSpatialIndex( *mCheckLayer->dataProvider() );
31  }
32 }
33 
35 {
36  delete mIndex;
37 }
38 
39 void QgsGeometryFollowBoundariesCheck::collectErrors( const QMap<QString, QgsFeaturePool *> &featurePools, QList<QgsGeometryCheckError *> &errors, QStringList &messages, QgsFeedback *feedback, const LayerFeatureIds &ids ) const
40 {
41  Q_UNUSED( messages )
42 
43  if ( !mIndex || !mCheckLayer )
44  {
45  return;
46  }
47 
48  QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds( featurePools ) : ids.toMap();
49  featureIds.remove( mCheckLayer->id() ); // Don't check layer against itself
50  QgsGeometryCheckerUtils::LayerFeatures layerFeatures( featurePools, featureIds, compatibleGeometryTypes(), feedback, mContext );
51  for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
52  {
53  const QgsAbstractGeometry *geom = layerFeature.geometry().constGet();
54 
55  // The geometry to crs of the check layer
56  QgsCoordinateTransform crst( layerFeature.layer()->crs(), mCheckLayer->crs(), QgsProject::instance() );
57  QgsGeometry geomt( geom->clone() );
58  geomt.transform( crst );
59 
60  std::unique_ptr< QgsGeometryEngine > geomEngine = QgsGeometryCheckerUtils::createGeomEngine( geomt.constGet(), mContext->tolerance );
61 
62  // Get potential reference features
63  QgsRectangle searchBounds = geomt.constGet()->boundingBox();
64  searchBounds.grow( mContext->tolerance );
65  QgsFeatureIds refFeatureIds = qgis::listToSet( mIndex->intersects( searchBounds ) );
66 
67  QgsFeatureRequest refFeatureRequest = QgsFeatureRequest().setFilterFids( refFeatureIds ).setNoAttributes();
68  QgsFeatureIterator refFeatureIt = mCheckLayer->getFeatures( refFeatureRequest );
69 
70  if ( refFeatureIds.isEmpty() )
71  {
72  // If no potential reference features are found, the geometry is definitely not following boundaries of reference layer features
73  errors.append( new QgsGeometryCheckError( this, layerFeature, QgsPointXY( geom->centroid() ) ) );
74  }
75  else
76  {
77  // All reference features must be either contained or disjoint from tested geometry
78  QgsFeature refFeature;
79  while ( refFeatureIt.nextFeature( refFeature ) )
80  {
81  const QgsAbstractGeometry *refGeom = refFeature.geometry().constGet();
82  std::unique_ptr<QgsGeometryEngine> refgeomEngine( QgsGeometryCheckerUtils::createGeomEngine( refGeom, mContext->tolerance ) );
83  QgsGeometry reducedRefGeom( refgeomEngine->buffer( -mContext->tolerance, 0 ) );
84  if ( !( geomEngine->contains( reducedRefGeom.constGet() ) || geomEngine->disjoint( reducedRefGeom.constGet() ) ) )
85  {
86  errors.append( new QgsGeometryCheckError( this, layerFeature, QgsPointXY( geom->centroid() ) ) );
87  break;
88  }
89  }
90  }
91  }
92 }
93 
94 void QgsGeometryFollowBoundariesCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes & /*changes*/ ) const
95 {
96  Q_UNUSED( featurePools )
97 
98  if ( method == NoChange )
99  {
100  error->setFixed( method );
101  }
102  else
103  {
104  error->setFixFailed( tr( "Unknown method" ) );
105  }
106 }
107 
109 {
110  static QStringList methods = QStringList() << tr( "No action" );
111  return methods;
112 }
113 
115 {
117 }
Abstract base class for all geometries.
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
virtual QgsPoint centroid() const
Returns the centroid of the geometry.
Class for doing transforms between two map coordinate systems.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsGeometry geometry
Definition: qgsfeature.h:67
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
Base configuration for geometry checks.
const double tolerance
The tolerance to allow for in geometry checks.
This represents an error reported by a geometry check.
void setFixed(int method)
Set the status to fixed and specify the method that has been used to fix the error.
void setFixFailed(const QString &reason)
Set the error status to failed and specify the reason for failure.
This class implements a geometry check.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
const QgsGeometryCheckContext * mContext
CheckType
The type of a check.
@ FeatureNodeCheck
The check controls individual nodes.
QMap< QString, QgsFeatureIds > allLayerFeatureIds(const QMap< QString, QgsFeaturePool * > &featurePools) const
Returns all layers and feature ids.
A layer feature combination to uniquely identify and access a feature in a set of layers.
Contains a set of layers and feature ids in those layers to pass to a geometry check.
static std::unique_ptr< QgsGeometryEngine > createGeomEngine(const QgsAbstractGeometry *geometry, double tolerance)
static QgsGeometryCheck::CheckType factoryCheckType()
QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const override
A list of geometry types for which this check can be performed.
Q_DECL_DEPRECATED QStringList resolutionMethods() const override
Returns a list of descriptions for available resolutions for errors.
QgsGeometryFollowBoundariesCheck(QgsGeometryCheckContext *context, const QVariantMap &configuration, QgsVectorLayer *checkLayer)
void fixError(const QMap< QString, QgsFeaturePool * > &featurePools, QgsGeometryCheckError *error, int method, const QMap< QString, int > &mergeAttributeIndices, Changes &changes) const override
Fixes the error error with the specified method.
void collectErrors(const QMap< QString, QgsFeaturePool * > &featurePools, QList< QgsGeometryCheckError * > &errors, QStringList &messages, QgsFeedback *feedback, const LayerFeatureIds &ids=LayerFeatureIds()) const override
The main worker method.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:76
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
A class to represent a 2D point.
Definition: qgspointxy.h:59
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:467
A rectangle specified with double values.
Definition: qgsrectangle.h:42
void grow(double delta)
Grows the rectangle in place by the specified amount.
Definition: qgsrectangle.h:296
A spatial index for QgsFeature objects.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
Represents a vector layer which manages a vector based data sets.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:37
A list of layers and feature ids for each of these layers.
QMap< QString, QgsFeatureIds > toMap() const