35 , mGapThresholdMapUnits( configuration.value( QStringLiteral(
"gapThreshold" ) ).toDouble() )
41 if ( configuration.value( QStringLiteral(
"allowedGapsEnabled" ) ).toBool() )
46 mAllowedGapsLayer = layer;
47 mAllowedGapsSource = std::make_unique<QgsVectorLayerFeatureSource>( layer );
49 mAllowedGapsBuffer = configuration.value( QStringLiteral(
"allowedGapsBuffer" ) ).toDouble();
54 mAllowedGapsSource.reset();
63 std::unique_ptr<QgsAbstractGeometry> allowedGapsGeom;
64 std::unique_ptr<QgsGeometryEngine> allowedGapsGeomEngine;
66 if ( mAllowedGapsSource )
68 QVector<QgsGeometry> allowedGaps;
78 allowedGaps.append( gg );
85 allowedGapsGeom.reset( allowedGapsEngine->combine( allowedGaps, &errMsg ) );
87 allowedGapsGeomEngine->prepareGeometry();
90 QVector<QgsGeometry> geomList;
95 geomList.append( layerFeature.geometry() );
104 if ( geomList.isEmpty() )
113 std::unique_ptr<QgsAbstractGeometry> unionGeom( geomEngine->combine( geomList, &errMsg ) );
116 messages.append( tr(
"Gap check: %1" ).arg( errMsg ) );
122 geomEngine->prepareGeometry();
123 std::unique_ptr<QgsAbstractGeometry> envelope( geomEngine->envelope( &errMsg ) );
126 messages.append( tr(
"Gap check: %1" ).arg( errMsg ) );
132 geomEngine->prepareGeometry();
133 QgsAbstractGeometry *bufEnvelope = geomEngine->buffer( 2, 0, GEOSBUF_CAP_SQUARE, GEOSBUF_JOIN_MITRE, 4. );
134 envelope.reset( bufEnvelope );
138 geomEngine->prepareGeometry();
139 std::unique_ptr<QgsAbstractGeometry> diffGeom( geomEngine->difference( unionGeom.get(), &errMsg ) );
142 messages.append( tr(
"Gap check: %1" ).arg( errMsg ) );
167 QMap<QString, QgsFeatureIds> neighboringIds;
170 gapGeomEngine->prepareGeometry();
176 neighboringIds[layerFeature.layer()->id()].insert( layerFeature.feature().id() );
181 if ( neighboringIds.isEmpty() )
186 if ( allowedGapsGeomEngine && allowedGapsGeomEngine->contains( gapGeom ) )
192 double area = gapGeom->
area();
200 QMetaEnum metaEnum = QMetaEnum::fromType<QgsGeometryGapCheck::ResolutionMethod>();
201 if ( !metaEnum.isValid() || !metaEnum.valueToKey( method ) )
208 switch ( methodValue )
217 if ( mergeWithNeighbor( featurePools,
static_cast<QgsGeometryGapCheckError *
>( error ), changes, errMsg, LongestSharedEdge ) )
223 error->
setFixFailed( tr(
"Failed to merge with neighbor: %1" ).arg( errMsg ) );
230 QgsVectorLayer *layer = qobject_cast<QgsVectorLayer *>( mAllowedGapsLayer.data() );
235 error->
setFixFailed( tr(
"Could not start editing layer %1" ).arg( layer->
name() ) );
243 error->
setFixFailed( tr(
"Could not add feature to layer %1" ).arg( layer->
name() ) );
253 error->
setFixFailed( tr(
"Allowed gaps layer could not be resolved" ) );
279 error->
setFixFailed( tr(
"Could not resolve target layer %1 to add feature" ).arg( error->
layerId() ) );
287 if ( mergeWithNeighbor( featurePools,
static_cast<QgsGeometryGapCheckError *
>( error ), changes, errMsg, LargestArea ) )
293 error->
setFixFailed( tr(
"Failed to merge with neighbor: %1" ).arg( errMsg ) );
301 bool QgsGeometryGapCheck::mergeWithNeighbor(
const QMap<QString, QgsFeaturePool *> &featurePools,
QgsGeometryGapCheckError *err, Changes &changes, QString &errMsg, Condition condition )
const
304 QString mergeLayerId;
306 int mergePartIdx = -1;
311 const auto layerIds = err->
neighbors().keys();
312 QList<QgsFeature> neighbours;
315 for (
const QString &layerId : layerIds )
318 std::unique_ptr<QgsAbstractGeometry> errLayerGeom( errGeometry->
clone() );
322 const auto featureIds = err->
neighbors().value( layerId );
327 if ( !featurePool->
getFeature( testId, feature ) )
335 neighbours.append( feature );
338 for (
const QgsFeature &testFeature : neighbours )
340 const QgsGeometry featureGeom = testFeature.geometry();
342 for (
int iPart = 0, nParts = testGeom->
partCount(); iPart < nParts; ++iPart )
347 case LongestSharedEdge:
361 mergeFeature = testFeature;
362 mergePartIdx = iPart;
363 mergeLayerId = layerId;
375 QgsSpatialIndex neighbourVerticesIndex( QgsSpatialIndex::Flag::FlagStoreFeatureGeometries );
377 for (
const QgsFeature &neighbour : neighbours )
386 neighbourVerticesIndex.addFeature( f );
397 QgsGeometry closestGeom = neighbourVerticesIndex.geometry( neighbourVerticesIndex.nearestNeighbor(
QgsPointXY( pt ) ).first() );
404 std::unique_ptr<QgsPolygon> snappedErrGeom = std::make_unique<QgsPolygon>();
405 snappedErrGeom->setExteriorRing(
new QgsLineString( snappedRing ) );
409 std::unique_ptr<QgsAbstractGeometry> errLayerGeom( snappedErrGeom->clone() );
430 QStringList methods = QStringList()
431 << tr(
"Add gap area to neighboring polygon with longest shared edge" )
432 << tr(
"No action" );
433 if ( mAllowedGapsSource )
434 methods << tr(
"Add gap to allowed exceptions" );
441 QList<QgsGeometryCheckResolutionMethod> fixes
448 if ( mAllowedGapsSource )
458 return factoryDescription();
468 return factoryFlags();
472 QString QgsGeometryGapCheck::factoryDescription()
477 QString QgsGeometryGapCheck::factoryId()
479 return QStringLiteral(
"QgsGeometryGapCheck" );
482 QgsGeometryCheck::Flags QgsGeometryGapCheck::factoryFlags()
487 QList<QgsWkbTypes::GeometryType> QgsGeometryGapCheck::factoryCompatibleGeometryTypes()
494 return factoryCompatibleGeometryTypes().contains( layer->geometryType() );
505 return mContextBoundingBox;
525 mNeighbors = err->mNeighbors;
526 mGapAreaBBox = err->mGapAreaBBox;
Abstract base class for all geometries.
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
virtual QgsRectangle boundingBox() const =0
Returns the minimal bounding box for the geometry.
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.
virtual double area() const
Returns the planar, 2-dimensional area of the geometry.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
A feature pool is based on a vector layer and caches features.
QgsCoordinateReferenceSystem crs() const
The coordinate reference system of this layer.
bool getFeature(QgsFeatureId id, QgsFeature &feature)
Retrieves the feature with the specified id into feature.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void setId(QgsFeatureId id)
Sets the feature id for this feature.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
double progress() const SIP_HOLDGIL
Returns the current progress reported by the feedback object.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
Base configuration for geometry checks.
const QgsProject * project() const
The project can be used to resolve additional layers.
const double reducedTolerance
The tolerance to allow for in 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.
const double tolerance
The tolerance to allow for in geometry checks.
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.
@ StatusFixed
The error is fixed.
Status status() const
The status of the error.
virtual void update(const QgsGeometryCheckError *other)
Update this error with the information from other.
const QgsGeometryCheck * mCheck
const QgsPointXY & location() const
The location of the error in map units.
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.
QgsGeometry geometry() const
The geometry of the error in map units.
This class implements a resolution for problems detected in geometry checks.
This class implements a geometry check.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
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.
const QgsGeometryCheckContext * mContext
@ AvailableInValidation
This geometry check should be available in layer validation on the vector layer peroperties.
CheckType
The type of a check.
@ LayerCheck
The check controls a whole layer (topology checks)
QMap< QString, QgsFeatureIds > allLayerFeatureIds(const QMap< QString, QgsFeaturePool * > &featurePools) const
Returns all layers and feature ids.
const QgsGeometryCheckContext * context() const
Returns the context.
A layer feature combination to uniquely identify and access a feature in a set of layers.
Contains a set of layers and feature ids in those layers to pass to a geometry check.
static std::unique_ptr< QgsGeometryEngine > createGeomEngine(const QgsAbstractGeometry *geometry, double tolerance)
static QgsAbstractGeometry * getGeomPart(QgsAbstractGeometry *geom, int partIdx)
static double sharedEdgeLength(const QgsAbstractGeometry *geom1, const QgsAbstractGeometry *geom2, double tol)
static bool pointsFuzzyEqual(const QgsPointXY &p1, const QgsPointXY &p2, double tol)
Determine whether two points are equal up to the specified tolerance.
An error produced by a QgsGeometryGapCheck.
void update(const QgsGeometryCheckError *other) override
Update this error with the information from other.
QMap< QString, QgsFeatureIds > involvedFeatures() const override
Returns a list of involved features.
bool closeMatch(QgsGeometryCheckError *other) const override
Check if this error is almost equal to other.
QIcon icon() const override
Returns an icon that should be shown for this kind of error.
QgsRectangle affectedAreaBBox() const override
The bounding box of the affected area of the error.
QgsRectangle contextBoundingBox() const override
The context of the error.
const QMap< QString, QgsFeatureIds > & neighbors() const
A map of layers and feature ids of the neighbors of the gap.
bool isEqual(QgsGeometryCheckError *other) const override
Check if this error is equal to other.
bool handleChanges(const QgsGeometryCheck::Changes &) override
Apply a list of changes.
QgsGeometryGapCheck(const QgsGeometryCheckContext *context, const QVariantMap &configuration)
The configuration accepts a "gapThreshold" key which specifies the maximum gap size in squared map un...
void collectErrors(const QMap< QString, QgsFeaturePool * > &featurePools, QList< QgsGeometryCheckError * > &errors, QStringList &messages, QgsFeedback *feedback, const LayerFeatureIds &ids=LayerFeatureIds()) const override
The main worker method.
Q_DECL_DEPRECATED QStringList resolutionMethods() const override
Returns a list of descriptions for available resolutions for errors.
QString description() const override
Returns a human readable description 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.
void prepare(const QgsGeometryCheckContext *context, const QVariantMap &configuration) override
Will be run in the main thread before collectErrors is called (which may be run from a background thr...
QList< QgsGeometryCheckResolutionMethod > availableResolutionMethods() const override
Returns a list of available resolution methods.
QList< QgsWkbTypes::GeometryType > compatibleGeometryTypes() const override
A list of geometry types for which this check can be performed.
QString id() const override
Returns an id for this check.
ResolutionMethod
Resolution methods for geometry gap checks.
@ CreateNewFeature
Create a new feature with the gap geometry.
@ AddToAllowedGaps
Add gap geometry to allowed gaps layer.
@ MergeLongestEdge
Merge the gap with the polygon with the longest shared edge.
@ NoChange
Do not handle the error.
@ MergeLargestArea
Merge with neighbouring polygon with largest area.
QgsGeometryCheck::Flags flags() const override
Flags for this geometry check.
Java-style iterator for traversal of parts of a geometry.
bool hasNext() const SIP_HOLDGIL
Find out whether there are more parts.
QgsAbstractGeometry * next()
Returns next part of the geometry (undefined behavior if hasNext() returns false before calling next(...
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
QgsGeometry buffer(double distance, int segments) const
Returns a buffer region around this geometry having the given width and with a specified number of se...
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Line string geometry type, with support for z-dimension and m-values.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID.
A rectangle specified with double values.
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
QgsRectangle snappedToGrid(double spacing) const
Returns a copy of this rectangle that is snapped to a grid with the specified spacing between the gri...
A spatial index for QgsFeature objects.
static QgsFeatureList makeFeatureCompatible(const QgsFeature &feature, const QgsVectorLayer *layer, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags())
Converts input feature to be compatible with the given layer.
static QgsFeature createFeature(const QgsVectorLayer *layer, const QgsGeometry &geometry=QgsGeometry(), const QgsAttributeMap &attributes=QgsAttributeMap(), QgsExpressionContext *context=nullptr)
Creates a new feature ready for insertion into a layer.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a list of features to the sink.
bool isEditable() const FINAL
Returns true if the provider is in editing mode.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) FINAL
Adds a single feature to the sink.
Java-style iterator for traversal of vertices of a geometry.
bool hasNext() const
Find out whether there are more vertices.
QgsPoint next()
Returns next vertex of the geometry (undefined behavior if hasNext() returns false before calling nex...
static bool isSingleType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a single type.
QMap< int, QVariant > QgsAttributeMap
QList< QgsFeature > QgsFeatureList
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
QList< int > QgsAttributeList
QgsPointSequence QgsPolyline
Polyline as represented as a vector of points.
A list of layers and feature ids for each of these layers.
QMap< QString, QgsFeatureIds > toMap() const