QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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
18#include "qgscurvepolygon.h"
19#include "qgsgeometrycheck.h"
21#include "qgsfeaturepool.h"
22#include "qgsvectorlayer.h"
23#include "qgsreadwritelocker.h"
24#include "qgsthreadingutils.h"
25
26
27
28
29QgsGeometryCheck::QgsGeometryCheck( const QgsGeometryCheckContext *context, const QVariantMap &configuration )
30 : mContext( context )
31 , mConfiguration( configuration )
32{}
33
34void 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
46{
48}
49
50void 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
59QList<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
82QMap<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
92void 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
115void 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
142void 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
171double 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:167
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.
QFlags< Flag > Flags
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.
@ 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.
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.
virtual QList< Qgis::GeometryType > compatibleGeometryTypes() const =0
A list of geometry types for which this check can be performed.
QgsGeometryCheck(const QgsGeometryCheckContext *context, const QVariantMap &configuration)
Create a new geometry check.
const QgsGeometryCheckContext * context() const
Returns the context.
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 t...
static QgsAbstractGeometry * getGeomPart(QgsAbstractGeometry *geom, int partIdx)
Geometry collection.
int numGeometries() const
Returns the number of geometries within the collection.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:81
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE Qgis::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:5776
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:5775
Descripts a change to fix a geometry.
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30