QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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 nullptr;
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 
QgsGeometryCheck::prepare
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...
Definition: qgsgeometrycheck.cpp:34
QgsMapLayer::crs
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:88
qgsreadwritelocker.h
QgsGeometryCheck::Change
Descripts a change to fix a geometry.
Definition: qgsgeometrycheck.h:177
QgsGeometryCheck::compatibleGeometryTypes
virtual QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const =0
A list of geometry types for which this check can be performed.
QgsGeometryCheckerUtils::getGeomPart
static QgsAbstractGeometry * getGeomPart(QgsAbstractGeometry *geom, int partIdx)
Definition: qgsgeometrycheckerutils.cpp:268
QgsGeometryCheck::ChangeAdded
@ ChangeAdded
Something has been added.
Definition: qgsgeometrycheck.h:145
QgsGeometryCheck::ChangeFeature
@ ChangeFeature
This change happens on feature level.
Definition: qgsgeometrycheck.h:132
QgsGeometryCollection::numGeometries
int numGeometries() const
Returns the number of geometries within the collection.
Definition: qgsgeometrycollection.h:51
QgsGeometryCheck::QgsGeometryCheck
QgsGeometryCheck(const QgsGeometryCheckContext *context, const QVariantMap &configuration)
Create a new geometry check.
Definition: qgsgeometrycheck.cpp:29
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:34
QgsGeometryCheck::Changes
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
Definition: qgsgeometrycheck.h:214
QgsGeometryCheck::replaceFeatureGeometryPart
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.
Definition: qgsgeometrycheck.cpp:92
QgsGeometryCheck::allLayerFeatureIds
QMap< QString, QgsFeatureIds > allLayerFeatureIds(const QMap< QString, QgsFeaturePool * > &featurePools) const
Returns all layers and feature ids.
Definition: qgsgeometrycheck.cpp:82
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsGeometryCheck::context
const QgsGeometryCheckContext * context() const
Returns the context.
Definition: qgsgeometrycheck.h:323
QgsGeometryCheck::ChangeChanged
@ ChangeChanged
Something has been updated.
Definition: qgsgeometrycheck.h:147
QgsGeometryCheck::resolutionMethods
virtual Q_DECL_DEPRECATED QStringList resolutionMethods() const
Returns a list of descriptions for available resolutions for errors.
Definition: qgsgeometrycheck.cpp:77
qgsgeometrycheckerror.h
qgsfeaturepool.h
QgsGeometryCheck::ChangeRemoved
@ ChangeRemoved
Something has been removed.
Definition: qgsgeometrycheck.h:146
Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:752
QgsFeature::id
QgsFeatureId id
Definition: qgsfeature.h:68
QgsGeometryCheck::flags
virtual QgsGeometryCheck::Flags flags() const
Flags for this geometry check.
Definition: qgsgeometrycheck.cpp:45
QgsGeometryCollection
Geometry collection.
Definition: qgsgeometrycollection.h:35
QgsGeometryCheck::fixError
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.
Definition: qgsgeometrycheck.cpp:50
qgsgeometrycheckcontext.h
QgsFeaturePool::deleteFeature
virtual void deleteFeature(QgsFeatureId fid)=0
Removes a feature from this pool.
qgsgeometrycheck.h
QgsFeature::setGeometry
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:137
QgsFeaturePool::updateFeature
virtual void updateFeature(QgsFeature &feature)=0
Updates a feature in this pool.
QgsGeometryCheck::scaleFactor
double scaleFactor(const QPointer< QgsVectorLayer > &layer) const
Determines the scale factor of a layer to the map coordinate reference system.
Definition: qgsgeometrycheck.cpp:171
QgsGeometryCheck::deleteFeatureGeometryRing
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.
Definition: qgsgeometrycheck.cpp:142
QgsGeometryCheck::availableResolutionMethods
virtual QList< QgsGeometryCheckResolutionMethod > availableResolutionMethods() const
Returns a list of available resolution methods.
Definition: qgsgeometrycheck.cpp:59
QgsGeometryCheckResolutionMethod
Definition: qgsgeometrycheckresolutionmethod.h:28
QgsGeometryCheckContext
Definition: qgsgeometrycheckcontext.h:31
QgsGeometryCheckContext::mapCrs
const QgsCoordinateReferenceSystem mapCrs
The coordinate system in which calculations should be done.
Definition: qgsgeometrycheckcontext.h:74
qgscurvepolygon.h
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:71
QgsGeometryCheck::mContext
const QgsGeometryCheckContext * mContext
Definition: qgsgeometrycheck.h:359
QgsVectorLayer::extent
QgsRectangle extent() const FINAL
Returns the extent of the layer.
Definition: qgsvectorlayer.cpp:833
qgsvectorlayer.h
QgsCoordinateTransform::scaleFactor
double scaleFactor(const QgsRectangle &referenceExtent) const
Computes an estimated conversion factor between source and destination units:
Definition: qgscoordinatetransform.cpp:1123
QgsGeometry::get
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:133
QgsGeometryCheck::ChangePart
@ ChangePart
This change happens on part level.
Definition: qgsgeometrycheck.h:133
qgsthreadingutils.h
QgsGeometry
Definition: qgsgeometry.h:122
QgsGeometryCheck::ChangeRing
@ ChangeRing
This change happens on ring level.
Definition: qgsgeometrycheck.h:134
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsVertexId
Utility class for identifying a unique vertex within a geometry.
Definition: qgsabstractgeometry.h:1033
QgsGeometryCheck::isCompatible
virtual bool isCompatible(QgsVectorLayer *layer) const
Returns if this geometry check is compatible with layer.
Definition: qgsgeometrycheck.cpp:40
qgsgeometrycollection.h
QgsFeature
Definition: qgsfeature.h:55
QgsGeometryCheck::deleteFeatureGeometryPart
void deleteFeatureGeometryPart(const QMap< QString, QgsFeaturePool * > &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, Changes &changes) const
Deletes a part of a feature geometry.
Definition: qgsgeometrycheck.cpp:115
QgsCoordinateTransform
Definition: qgscoordinatetransform.h:52
QgsVectorLayer::geometryType
Q_INVOKABLE QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Definition: qgsvectorlayer.cpp:659
Q_NOWARN_DEPRECATED_PUSH
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:751
QgsGeometryCheckError
Definition: qgsgeometrycheckerror.h:35
QgsGeometryCheckContext::transformContext
const QgsCoordinateTransformContext transformContext
The coordinate transform context with which transformations will be done.
Definition: qgsgeometrycheckcontext.h:79
QgsFeaturePool
Definition: qgsfeaturepool.h:37