QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 QMap<QString, QgsFeatureIds> QgsGeometryCheck::allLayerFeatureIds( const QMap<QString, QgsFeaturePool *> &featurePools ) const
60 {
61  QMap<QString, QgsFeatureIds> featureIds;
62  for ( QgsFeaturePool *pool : featurePools )
63  {
64  featureIds.insert( pool->layerId(), pool->allFeatureIds() );
65  }
66  return featureIds;
67 }
68 
69 void QgsGeometryCheck::replaceFeatureGeometryPart( const QMap<QString, QgsFeaturePool *> &featurePools,
70  const QString &layerId, QgsFeature &feature,
71  int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes ) const
72 {
73  QgsFeaturePool *featurePool = featurePools[layerId];
74  QgsGeometry featureGeom = feature.geometry();
75  QgsAbstractGeometry *geom = featureGeom.get();
76  if ( QgsGeometryCollection *geomCollection = dynamic_cast< QgsGeometryCollection *>( geom ) )
77  {
78  geomCollection->removeGeometry( partIdx );
79  geomCollection->addGeometry( newPartGeom );
80  changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
81  changes[layerId][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) );
82  feature.setGeometry( featureGeom );
83  }
84  else
85  {
86  feature.setGeometry( QgsGeometry( newPartGeom ) );
87  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
88  }
89  featurePool->updateFeature( feature );
90 }
91 
92 void QgsGeometryCheck::deleteFeatureGeometryPart( const QMap<QString, QgsFeaturePool *> &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, Changes &changes ) const
93 {
94  QgsFeaturePool *featurePool = featurePools[layerId];
95  QgsGeometry featureGeom = feature.geometry();
96  QgsAbstractGeometry *geom = featureGeom.get();
97  if ( dynamic_cast<QgsGeometryCollection *>( geom ) )
98  {
99  static_cast<QgsGeometryCollection *>( geom )->removeGeometry( partIdx );
100  if ( static_cast<QgsGeometryCollection *>( geom )->numGeometries() == 0 )
101  {
102  featurePool->deleteFeature( feature.id() );
103  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
104  }
105  else
106  {
107  feature.setGeometry( featureGeom );
108  featurePool->updateFeature( feature );
109  changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
110  }
111  }
112  else
113  {
114  featurePool->deleteFeature( feature.id() );
115  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
116  }
117 }
118 
119 void QgsGeometryCheck::deleteFeatureGeometryRing( const QMap<QString, QgsFeaturePool *> &featurePools,
120  const QString &layerId, QgsFeature &feature,
121  int partIdx, int ringIdx, Changes &changes ) const
122 {
123  QgsFeaturePool *featurePool = featurePools[layerId];
124  QgsGeometry featureGeom = feature.geometry();
125  QgsAbstractGeometry *partGeom = QgsGeometryCheckerUtils::getGeomPart( featureGeom.get(), partIdx );
126  if ( dynamic_cast<QgsCurvePolygon *>( partGeom ) )
127  {
128  // If we delete the exterior ring of a polygon, it makes no sense to keep the interiors
129  if ( ringIdx == 0 )
130  {
131  deleteFeatureGeometryPart( featurePools, layerId, feature, partIdx, changes );
132  }
133  else
134  {
135  static_cast<QgsCurvePolygon *>( partGeom )->removeInteriorRing( ringIdx - 1 );
136  feature.setGeometry( featureGeom );
137  featurePool->updateFeature( feature );
138  changes[layerId][feature.id()].append( Change( ChangeRing, ChangeRemoved, QgsVertexId( partIdx, ringIdx ) ) );
139  }
140  }
141  // Other geometry types do not have rings, remove the entire part
142  else
143  {
144  deleteFeatureGeometryPart( featurePools, layerId, feature, partIdx, changes );
145  }
146 }
147 
148 double QgsGeometryCheck::scaleFactor( const QPointer<QgsVectorLayer> &layer ) const
149 {
150  double scaleFactor = 1.0;
151 
152  QgsVectorLayer *lyr = layer.data();
153  if ( lyr )
154  {
156  scaleFactor = ct.scaleFactor( lyr->extent() );
157  }
158  return scaleFactor;
159 }
160 
161 
QgsFeatureId id
Definition: qgsfeature.h:64
This change happens on part level.
double scaleFactor(const QPointer< QgsVectorLayer > &layer) const
Determines the scale factor of a layer to the map coordinate reference system.
static QgsAbstractGeometry * getGeomPart(QgsAbstractGeometry *geom, int partIdx)
Something has been added.
Base configuration for geometry checks.
Curve polygon geometry type.
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
virtual QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const =0
A list of geometry types for which this check can be performed.
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 void updateFeature(QgsFeature &feature)=0
Updates a feature in this pool.
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.
Something has been removed.
This change happens on ring level.
Utility class for identifying a unique vertex within a geometry.
Geometry collection.
QgsGeometryCheck(const QgsGeometryCheckContext *context, const QVariantMap &configuration)
Create a new 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 QgsGeometryCheckContext * mContext
const QgsCoordinateReferenceSystem mapCrs
The coordinate system in which calculations should be done.
QgsRectangle extent() const FINAL
Returns the extent of the layer.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
A feature pool is based on a vector layer and caches features.
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.
Descripts a change to fix a geometry.
double scaleFactor(const QgsRectangle &referenceExtent) const
Computes an estimated conversion factor between source and destination units:
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
Class for doing transforms between two map coordinate systems.
virtual void deleteFeature(QgsFeatureId fid)=0
Removes a feature from this pool.
virtual QgsGeometryCheck::Flags flags() const
Flags for this geometry check.
QgsGeometry geometry
Definition: qgsfeature.h:67
const QgsGeometryCheckContext * context() const
Returns the context.
This represents an error reported by a geometry check.
Represents a vector layer which manages a vector based data sets.
Something has been updated.
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 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...
This change happens on feature level.
virtual bool isCompatible(QgsVectorLayer *layer) const
Returns if this geometry check is compatible with layer.
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:86
const QgsCoordinateTransformContext transformContext
The coordinate transform context with which transformations will be done.