QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsgeometrycheck.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometrycheck.cpp
3  ---------------------
4  begin : September 2015
5  copyright : (C) 2014 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 
17 #include "qgsgeometrycollection.h"
18 #include "qgscurvepolygon.h"
19 #include "qgsgeometrycheck.h"
20 #include "qgsgeometrycheckerror.h"
21 #include "qgsfeaturepool.h"
22 #include "qgsvectorlayer.h"
23 #include "qgsreadwritelocker.h"
24 #include "qgsthreadingutils.h"
25 
26 
27 
28 
29 QgsGeometryCheck::QgsGeometryCheck( const QgsGeometryCheckContext *context, const QVariantMap &configuration )
30  : mContext( context )
31  , mConfiguration( configuration )
32 {}
33 
34 void QgsGeometryCheck::prepare( const QgsGeometryCheckContext *context, const QVariantMap &configuration )
35 {
36  Q_UNUSED( context )
37  Q_UNUSED( configuration )
38 }
39 
41 {
42  return compatibleGeometryTypes().contains( layer->geometryType() );
43 }
44 
45 QgsGeometryCheck::Flags QgsGeometryCheck::flags() const
46 {
47  return QgsGeometryCheck::Flags();
48 }
49 
50 void QgsGeometryCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, QgsGeometryCheck::Changes &changes ) const
51 {
52  Q_UNUSED( featurePools )
53  Q_UNUSED( error )
54  Q_UNUSED( method )
55  Q_UNUSED( mergeAttributeIndices )
56  Q_UNUSED( changes )
57 }
58 
59 QList<QgsGeometryCheckResolutionMethod> QgsGeometryCheck::availableResolutionMethods() const
60 {
61  QList<QgsGeometryCheckResolutionMethod> fixes;
62  // Once the deprecated `resolutionMethods()` function is gone, this default implementation
63  // should be removed and each check will need to implement this method instead of resolutionMethods().
65  const QStringList methods = resolutionMethods();
67 
68  int i = 0;
69  for ( const QString &method : methods )
70  {
71  fixes.append( QgsGeometryCheckResolutionMethod( i, method, QString(), false ) );
72  }
73 
74  return fixes;
75 }
76 
78 {
79  return QStringList();
80 }
81 
82 QMap<QString, QgsFeatureIds> QgsGeometryCheck::allLayerFeatureIds( const QMap<QString, QgsFeaturePool *> &featurePools ) const
83 {
84  QMap<QString, QgsFeatureIds> featureIds;
85  for ( QgsFeaturePool *pool : featurePools )
86  {
87  featureIds.insert( pool->layerId(), pool->allFeatureIds() );
88  }
89  return featureIds;
90 }
91 
92 void QgsGeometryCheck::replaceFeatureGeometryPart( const QMap<QString, QgsFeaturePool *> &featurePools,
93  const QString &layerId, QgsFeature &feature,
94  int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes ) const
95 {
96  QgsFeaturePool *featurePool = featurePools[layerId];
97  QgsGeometry featureGeom = feature.geometry();
98  QgsAbstractGeometry *geom = featureGeom.get();
99  if ( QgsGeometryCollection *geomCollection = dynamic_cast< QgsGeometryCollection *>( geom ) )
100  {
101  geomCollection->removeGeometry( partIdx );
102  geomCollection->addGeometry( newPartGeom );
103  changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
104  changes[layerId][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) );
105  feature.setGeometry( featureGeom );
106  }
107  else
108  {
109  feature.setGeometry( QgsGeometry( newPartGeom ) );
110  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
111  }
112  featurePool->updateFeature( feature );
113 }
114 
115 void QgsGeometryCheck::deleteFeatureGeometryPart( const QMap<QString, QgsFeaturePool *> &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, Changes &changes ) const
116 {
117  QgsFeaturePool *featurePool = featurePools[layerId];
118  QgsGeometry featureGeom = feature.geometry();
119  QgsAbstractGeometry *geom = featureGeom.get();
120  if ( dynamic_cast<QgsGeometryCollection *>( geom ) )
121  {
122  static_cast<QgsGeometryCollection *>( geom )->removeGeometry( partIdx );
123  if ( static_cast<QgsGeometryCollection *>( geom )->numGeometries() == 0 )
124  {
125  featurePool->deleteFeature( feature.id() );
126  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
127  }
128  else
129  {
130  feature.setGeometry( featureGeom );
131  featurePool->updateFeature( feature );
132  changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
133  }
134  }
135  else
136  {
137  featurePool->deleteFeature( feature.id() );
138  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
139  }
140 }
141 
142 void QgsGeometryCheck::deleteFeatureGeometryRing( const QMap<QString, QgsFeaturePool *> &featurePools,
143  const QString &layerId, QgsFeature &feature,
144  int partIdx, int ringIdx, Changes &changes ) const
145 {
146  QgsFeaturePool *featurePool = featurePools[layerId];
147  QgsGeometry featureGeom = feature.geometry();
148  QgsAbstractGeometry *partGeom = QgsGeometryCheckerUtils::getGeomPart( featureGeom.get(), partIdx );
149  if ( dynamic_cast<QgsCurvePolygon *>( partGeom ) )
150  {
151  // If we delete the exterior ring of a polygon, it makes no sense to keep the interiors
152  if ( ringIdx == 0 )
153  {
154  deleteFeatureGeometryPart( featurePools, layerId, feature, partIdx, changes );
155  }
156  else
157  {
158  static_cast<QgsCurvePolygon *>( partGeom )->removeInteriorRing( ringIdx - 1 );
159  feature.setGeometry( featureGeom );
160  featurePool->updateFeature( feature );
161  changes[layerId][feature.id()].append( Change( ChangeRing, ChangeRemoved, QgsVertexId( partIdx, ringIdx ) ) );
162  }
163  }
164  // Other geometry types do not have rings, remove the entire part
165  else
166  {
167  deleteFeatureGeometryPart( featurePools, layerId, feature, partIdx, changes );
168  }
169 }
170 
171 double QgsGeometryCheck::scaleFactor( const QPointer<QgsVectorLayer> &layer ) const
172 {
173  double scaleFactor = 1.0;
174 
175  QgsVectorLayer *lyr = layer.data();
176  if ( lyr )
177  {
179  scaleFactor = ct.scaleFactor( lyr->extent() );
180  }
181  return scaleFactor;
182 }
183 
184 
Abstract base class for all geometries.
Class for doing transforms between two map coordinate systems.
double scaleFactor(const QgsRectangle &referenceExtent) const
Computes an estimated conversion factor between source and destination units:
Curve polygon geometry type.
A feature pool is based on a vector layer and caches features.
virtual void updateFeature(QgsFeature &feature)=0
Updates a feature in this pool.
virtual void deleteFeature(QgsFeatureId fid)=0
Removes a feature from this pool.
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
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:145
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
Base configuration for geometry checks.
const QgsCoordinateTransformContext transformContext
The coordinate transform context with which transformations will be done.
const QgsCoordinateReferenceSystem mapCrs
The coordinate system in which calculations should be done.
This represents an error reported by a geometry check.
This class implements a resolution for problems detected in geometry checks.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
void deleteFeatureGeometryPart(const QMap< QString, QgsFeaturePool * > &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, Changes &changes) const
Deletes a part of a feature geometry.
virtual QList< QgsGeometryCheckResolutionMethod > availableResolutionMethods() const
Returns a list of available resolution methods.
void deleteFeatureGeometryRing(const QMap< QString, QgsFeaturePool * > &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, int ringIdx, Changes &changes) const
Deletes a ring in a feature geometry.
void replaceFeatureGeometryPart(const QMap< QString, QgsFeaturePool * > &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes) const
Replaces a part in a feature geometry.
virtual Q_DECL_DEPRECATED QStringList resolutionMethods() const
Returns a list of descriptions for available resolutions for errors.
const QgsGeometryCheckContext * mContext
@ ChangeRing
This change happens on ring level.
@ ChangeFeature
This change happens on feature level.
@ ChangePart
This change happens on part level.
QMap< QString, QgsFeatureIds > allLayerFeatureIds(const QMap< QString, QgsFeaturePool * > &featurePools) const
Returns all layers and feature ids.
virtual QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const =0
A list of geometry types for which this check can be performed.
@ ChangeChanged
Something has been updated.
@ ChangeAdded
Something has been added.
@ ChangeRemoved
Something has been removed.
double scaleFactor(const QPointer< QgsVectorLayer > &layer) const
Determines the scale factor of a layer to the map coordinate reference system.
const QgsGeometryCheckContext * context() const
Returns the context.
virtual QgsGeometryCheck::Flags flags() const
Flags for this geometry check.
virtual void fixError(const QMap< QString, QgsFeaturePool * > &featurePools, QgsGeometryCheckError *error, int method, const QMap< QString, int > &mergeAttributeIndices, Changes &changes) const
Fixes the error error with the specified method.
QgsGeometryCheck(const QgsGeometryCheckContext *context, const QVariantMap &configuration)
Create a new geometry check.
virtual bool isCompatible(QgsVectorLayer *layer) const
Returns if this geometry check is compatible with layer.
virtual void prepare(const QgsGeometryCheckContext *context, const QVariantMap &configuration)
Will be run in the main thread before collectErrors is called (which may be run from a background thr...
static QgsAbstractGeometry * getGeomPart(QgsAbstractGeometry *geom, int partIdx)
Geometry collection.
int numGeometries() const SIP_HOLDGIL
Returns the number of geometries within the collection.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:76
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:1080
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:1079
Descripts a change to fix a geometry.
Utility class for identifying a unique vertex within a geometry.