QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 
35 {
36  return compatibleGeometryTypes().contains( layer->geometryType() );
37 }
38 
39 QgsGeometryCheck::Flags QgsGeometryCheck::flags() const
40 {
41  return nullptr;
42 }
43 
44 void QgsGeometryCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, QgsGeometryCheck::Changes &changes ) const
45 {
46  Q_UNUSED( featurePools )
47  Q_UNUSED( error )
48  Q_UNUSED( method )
49  Q_UNUSED( mergeAttributeIndices )
50  Q_UNUSED( changes )
51 }
52 
53 QMap<QString, QgsFeatureIds> QgsGeometryCheck::allLayerFeatureIds( const QMap<QString, QgsFeaturePool *> &featurePools ) const
54 {
55  QMap<QString, QgsFeatureIds> featureIds;
56  for ( QgsFeaturePool *pool : featurePools )
57  {
58  featureIds.insert( pool->layerId(), pool->allFeatureIds() );
59  }
60  return featureIds;
61 }
62 
63 void QgsGeometryCheck::replaceFeatureGeometryPart( const QMap<QString, QgsFeaturePool *> &featurePools,
64  const QString &layerId, QgsFeature &feature,
65  int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes ) const
66 {
67  QgsFeaturePool *featurePool = featurePools[layerId];
68  QgsGeometry featureGeom = feature.geometry();
69  QgsAbstractGeometry *geom = featureGeom.get();
70  if ( QgsGeometryCollection *geomCollection = dynamic_cast< QgsGeometryCollection *>( geom ) )
71  {
72  geomCollection->removeGeometry( partIdx );
73  geomCollection->addGeometry( newPartGeom );
74  changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
75  changes[layerId][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) );
76  feature.setGeometry( featureGeom );
77  }
78  else
79  {
80  feature.setGeometry( QgsGeometry( newPartGeom ) );
81  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
82  }
83  featurePool->updateFeature( feature );
84 }
85 
86 void QgsGeometryCheck::deleteFeatureGeometryPart( const QMap<QString, QgsFeaturePool *> &featurePools, const QString &layerId, QgsFeature &feature, int partIdx, Changes &changes ) const
87 {
88  QgsFeaturePool *featurePool = featurePools[layerId];
89  QgsGeometry featureGeom = feature.geometry();
90  QgsAbstractGeometry *geom = featureGeom.get();
91  if ( dynamic_cast<QgsGeometryCollection *>( geom ) )
92  {
93  static_cast<QgsGeometryCollection *>( geom )->removeGeometry( partIdx );
94  if ( static_cast<QgsGeometryCollection *>( geom )->numGeometries() == 0 )
95  {
96  featurePool->deleteFeature( feature.id() );
97  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
98  }
99  else
100  {
101  feature.setGeometry( featureGeom );
102  featurePool->updateFeature( feature );
103  changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
104  }
105  }
106  else
107  {
108  featurePool->deleteFeature( feature.id() );
109  changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
110  }
111 }
112 
113 void QgsGeometryCheck::deleteFeatureGeometryRing( const QMap<QString, QgsFeaturePool *> &featurePools,
114  const QString &layerId, QgsFeature &feature,
115  int partIdx, int ringIdx, Changes &changes ) const
116 {
117  QgsFeaturePool *featurePool = featurePools[layerId];
118  QgsGeometry featureGeom = feature.geometry();
119  QgsAbstractGeometry *partGeom = QgsGeometryCheckerUtils::getGeomPart( featureGeom.get(), partIdx );
120  if ( dynamic_cast<QgsCurvePolygon *>( partGeom ) )
121  {
122  // If we delete the exterior ring of a polygon, it makes no sense to keep the interiors
123  if ( ringIdx == 0 )
124  {
125  deleteFeatureGeometryPart( featurePools, layerId, feature, partIdx, changes );
126  }
127  else
128  {
129  static_cast<QgsCurvePolygon *>( partGeom )->removeInteriorRing( ringIdx - 1 );
130  feature.setGeometry( featureGeom );
131  featurePool->updateFeature( feature );
132  changes[layerId][feature.id()].append( Change( ChangeRing, ChangeRemoved, QgsVertexId( partIdx, ringIdx ) ) );
133  }
134  }
135  // Other geometry types do not have rings, remove the entire part
136  else
137  {
138  deleteFeatureGeometryPart( featurePools, layerId, feature, partIdx, changes );
139  }
140 }
141 
142 double QgsGeometryCheck::scaleFactor( const QPointer<QgsVectorLayer> &layer ) const
143 {
144  double scaleFactor = 1.0;
145 
146  QgsVectorLayer *lyr = layer.data();
147  if ( lyr )
148  {
150  scaleFactor = ct.scaleFactor( lyr->extent() );
151  }
152  return scaleFactor;
153 }
154 
155 
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.
const QgsCoordinateReferenceSystem mapCrs
The coordinate system in which calculations should be done.
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:111
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.
Base configuration for geometry checks.
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
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
Fix 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.
const QgsCoordinateTransformContext transformContext
The coordinate transform context with which transformations will be done.
virtual QgsGeometryCheck::Flags flags() const
Flags for this geometry check.
QgsGeometry geometry
Definition: qgsfeature.h:67
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.
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:85