QGIS API Documentation  3.27.0-Master (aef1b1ec20)
qgsgeometrytypecheck.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometrytypecheck.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 "qgsgeometrytypecheck.h"
18 #include "qgsgeometrycollection.h"
19 #include "qgsmulticurve.h"
20 #include "qgsmultilinestring.h"
21 #include "qgsmultipoint.h"
22 #include "qgsmultipolygon.h"
23 #include "qgsmultirenderchecker.h"
24 #include "qgsfeaturepool.h"
25 
26 
27 
28 QList<QgsSingleGeometryCheckError *> QgsGeometryTypeCheck::processGeometry( const QgsGeometry &geometry ) const
29 {
30  QList<QgsSingleGeometryCheckError *> errors;
31  const QgsAbstractGeometry *geom = geometry.constGet();
32  const QgsWkbTypes::Type type = QgsWkbTypes::flatType( geom->wkbType() );
33  if ( ( mAllowedTypes & ( 1 << type ) ) == 0 )
34  {
35  errors.append( new QgsGeometryTypeCheckError( this, geometry, geometry, type ) );
36  }
37  return errors;
38 }
39 
40 void QgsGeometryTypeCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
41 {
42  QgsFeaturePool *featurePool = featurePools[ error->layerId() ];
43  QgsFeature feature;
44  if ( !featurePool->getFeature( error->featureId(), feature ) )
45  {
46  error->setObsolete();
47  return;
48  }
49  const QgsGeometry featureGeom = feature.geometry();
50  const QgsAbstractGeometry *geom = featureGeom.constGet();
51 
52  // Check if error still applies
53  const QgsWkbTypes::Type type = QgsWkbTypes::flatType( geom->wkbType() );
54  if ( ( mAllowedTypes & ( 1 << type ) ) != 0 )
55  {
56  error->setObsolete();
57  return;
58  }
59 
60  // Fix with selected method
61  if ( method == NoChange )
62  {
63  error->setFixed( method );
64  }
65  else if ( method == Convert )
66  {
67  // Check if corresponding single type is allowed
68  if ( QgsWkbTypes::isMultiType( type ) && ( ( 1 << QgsWkbTypes::singleType( type ) ) & mAllowedTypes ) != 0 )
69  {
70  // Explode multi-type feature into single-type features
71  for ( int iPart = 1, nParts = geom->partCount(); iPart < nParts; ++iPart )
72  {
73  QgsFeature newFeature;
74  newFeature.setAttributes( feature.attributes() );
75  newFeature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, iPart )->clone() ) );
76  featurePool->addFeature( newFeature );
77  changes[error->layerId()][newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) );
78  }
79  // Recycle feature for part 0
80  feature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, 0 )->clone() ) );
81  featurePool->updateFeature( feature );
82  changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
83  }
84  // Check if corresponding multi type is allowed
85  else if ( QgsWkbTypes::isSingleType( type ) && ( ( 1 << QgsWkbTypes::multiType( type ) ) & mAllowedTypes ) != 0 )
86  {
87  QgsGeometryCollection *geomCollection = nullptr;
88  switch ( QgsWkbTypes::multiType( type ) )
89  {
91  {
92  geomCollection = new QgsMultiPoint();
93  break;
94  }
96  {
97  geomCollection = new QgsMultiLineString();
98  break;
99  }
101  {
102  geomCollection = new QgsMultiPolygon();
103  break;
104  }
106  {
107  geomCollection = new QgsMultiCurve();
108  break;
109  }
111  {
112  geomCollection = new QgsMultiSurface();
113  break;
114  }
115  default:
116  break;
117  }
118  if ( !geomCollection )
119  {
120  error->setFixFailed( tr( "Unknown geometry type" ) );
121  }
122  else
123  {
124  geomCollection->addGeometry( geom->clone() );
125 
126  feature.setGeometry( QgsGeometry( geomCollection ) );
127  featurePool->updateFeature( feature );
128  changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
129  }
130  }
131  // Delete feature
132  else
133  {
134  featurePool->deleteFeature( feature.id() );
135  changes[error->layerId()][error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) );
136  }
137  error->setFixed( method );
138  }
139  else if ( method == Delete )
140  {
141  featurePool->deleteFeature( feature.id() );
142  error->setFixed( method );
143  changes[error->layerId()][error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) );
144  }
145  else
146  {
147  error->setFixFailed( tr( "Unknown method" ) );
148  }
149 }
150 
152 {
153  static const QStringList methods = QStringList()
154  << tr( "Convert to corresponding multi or single type if possible, otherwise delete feature" )
155  << tr( "Delete feature" )
156  << tr( "No action" );
157  return methods;
158 }
159 
161 {
162  return tr( "Geometry type" );
163 }
164 
166 {
167  return factoryDescription();
168 }
169 
171 {
172  return QStringLiteral( "QgsGeometryTypeCheck" );
173 }
174 
176 {
178 }
179 
181 {
182  return factoryId();
183 }
184 
186 {
187  return factoryCheckType();
188 }
189 
191 {
192  return QgsSingleGeometryCheckError::isEqual( other ) &&
193  mFlatType == static_cast<const QgsGeometryTypeCheckError *>( other )->mFlatType;
194 }
195 
197 {
198  return QStringLiteral( "%1 (%2)" ).arg( mCheck->description(), QgsWkbTypes::displayString( mFlatType ) );
199 }
Abstract base class for all geometries.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
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.
bool getFeature(QgsFeatureId id, QgsFeature &feature)
Retrieves the feature with the specified id into feature.
virtual bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags())
Adds a single feature to the sink.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:56
QgsAttributes attributes
Definition: qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:153
QgsGeometry geometry
Definition: qgsfeature.h:67
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:163
Q_GADGET QgsFeatureId id
Definition: qgsfeature.h:64
This represents an error reported by a geometry check.
const QString & layerId() const
The id of the layer on which this error has been detected.
QgsFeatureId featureId() const
The id of the feature on which this error has been detected.
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.
void setObsolete()
Set the error status to obsolete.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
@ ChangeFeature
This change happens on feature level.
CheckType
The type of a check.
@ FeatureCheck
The check controls geometries as a whole.
@ ChangeChanged
Something has been updated.
@ ChangeAdded
Something has been added.
@ ChangeRemoved
Something has been removed.
virtual QString description() const =0
Returns a human readable description for this check.
static QgsAbstractGeometry * getGeomPart(QgsAbstractGeometry *geom, int partIdx)
Geometry collection.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
A geometry type check error.
bool isEqual(const QgsSingleGeometryCheckError *other) const override
Check if this error is equal to other.
QString description() const override
A human readable description of this error.
Q_DECL_DEPRECATED QStringList resolutionMethods() const override
Returns a list of descriptions for available resolutions for errors.
QgsGeometryCheck::CheckType checkType() const override
Returns the check type.
QString id() const override
Returns an id for this check.
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.
QList< QgsSingleGeometryCheckError * > processGeometry(const QgsGeometry &geometry) const override
Check the geometry for errors.
static QgsGeometryCheck::CheckType factoryCheckType()
QString description() const override
Returns a human readable description for this check.
static QString factoryDescription()
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Multi curve geometry collection.
Definition: qgsmulticurve.h:30
Multi line string geometry collection.
Multi point geometry collection.
Definition: qgsmultipoint.h:30
Multi polygon geometry collection.
Multi surface geometry collection.
An error from a QgsSingleGeometryCheck.
const QgsSingleGeometryCheck * mCheck
virtual bool isEqual(const QgsSingleGeometryCheckError *other) const
Check if this error is equal to other.
static bool isSingleType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:852
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:862
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static Type singleType(Type type) SIP_HOLDGIL
Returns the single type for a WKB type.
Definition: qgswkbtypes.h:157
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
static Type multiType(Type type) SIP_HOLDGIL
Returns the multi type for a WKB type.
Definition: qgswkbtypes.h:304
Descripts a change to fix a geometry.