QGIS API Documentation  3.6.0-Noosa (5873452)
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 = mIndex->intersects( searchBounds ).toSet();
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 }
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeatureid.h:34
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.
A class to represent a 2D point.
Definition: qgspointxy.h:43
QMap< QString, QgsFeatureIds > toMap() const
Contains a set of layers and feature ids in those layers to pass to a geometry check.
CheckType
The type of a check.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
void setFixFailed(const QString &reason)
Set the error status to failed and specify the reason for failure.
virtual QgsPoint centroid() const
Returns the centroid of the geometry.
Base class for feedback objects to be used for cancelation of something running in a worker thread...
Definition: qgsfeedback.h:44
Base configuration for geometry checks.
void collectErrors(const QMap< QString, QgsFeaturePool *> &featurePools, QList< QgsGeometryCheckError *> &errors, QStringList &messages, QgsFeedback *feedback, const LayerFeatureIds &ids=LayerFeatureIds()) const override
The main worker method.
QString id() const
Returns the layer&#39;s unique ID, which is used to access this layer from QgsProject.
void grow(double delta)
Grows the rectangle in place by the specified amount.
Definition: qgsrectangle.h:275
static QgsGeometryCheck::CheckType factoryCheckType()
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
A layer feature combination to uniquely identify and access a feature in a set of layers...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
This class implements a geometry check.
Abstract base class for all geometries.
QMap< QString, QgsFeatureIds > allLayerFeatureIds(const QMap< QString, QgsFeaturePool *> &featurePools) const
Returns all layers and feature ids.
const double tolerance
The tolerance to allow for in geometry checks.
const QgsGeometryCheckContext * mContext
QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const override
A list of geometry types for which this check can be performed.
A list of layers and feature ids for each of these layers.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
A spatial index for QgsFeature objects.
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets feature IDs that should be fetched.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
QStringList resolutionMethods() const override
Returns a list of descriptions for available resolutions for errors.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:430
void setFixed(int method)
Set the status to fixed and specify the method that has been used to fix the error.
Class for doing transforms between two map coordinate systems.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query the layer for features specified in request.
QgsGeometry geometry
Definition: qgsfeature.h:67
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer&#39;s data provider, it may be null.
This represents an error reported by a geometry check.
static std::unique_ptr< QgsGeometryEngine > createGeomEngine(const QgsAbstractGeometry *geometry, double tolerance)
bool nextFeature(QgsFeature &f)
void fixError(const QMap< QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap< QString, int > &mergeAttributeIndices, Changes &changes) const override
Fix the error error with the specified method.
Represents a vector layer which manages a vector based data sets.
QList< QgsFeatureId > intersects(const QgsRectangle &rectangle) const
Returns a list of features with a bounding box which intersects the specified rectangle.
QgsGeometryFollowBoundariesCheck(QgsGeometryCheckContext *context, const QVariantMap &configuration, QgsVectorLayer *checkLayer)
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:71
The check controls individual nodes.