QGIS API Documentation 3.27.0-Master (9c08adf5ef)
qgsgeometryselfcontactcheck.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsgeometryselfcontactcheck.cpp
3 ---------------------
4 begin : September 2017
5 copyright : (C) 2017 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 "qgsgeometryutils.h"
19#include "qgsfeaturepool.h"
20
21QList<QgsSingleGeometryCheckError *> QgsGeometrySelfContactCheck::processGeometry( const QgsGeometry &geometry ) const
22{
23 QList<QgsSingleGeometryCheckError *> errors;
24 const QgsAbstractGeometry *geom = geometry.constGet();
25 for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart )
26 {
27 for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )
28 {
29 // Test for self-contacts
30 int n = geom->vertexCount( iPart, iRing );
31 const bool isClosed = geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) ) == geom->vertexAt( QgsVertexId( iPart, iRing, n - 1 ) );
32
33 // Geometry ring without duplicate nodes
34 QVector<int> vtxMap;
35 QVector<QgsPoint> ring;
36 vtxMap.append( 0 );
37 ring.append( geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) ) );
38 for ( int i = 1; i < n; ++i )
39 {
40 const QgsPoint p = geom->vertexAt( QgsVertexId( iPart, iRing, i ) );
42 {
43 vtxMap.append( i );
44 ring.append( p );
45 }
46 }
47 while ( !ring.empty() && QgsGeometryUtils::sqrDistance2D( ring.front(), ring.back() ) < mContext->tolerance * mContext->tolerance )
48 {
49 vtxMap.pop_back();
50 ring.pop_back();
51 }
52 if ( !ring.empty() && isClosed )
53 {
54 vtxMap.append( n - 1 );
55 ring.append( ring.front() );
56 }
57 n = ring.size();
58
59 // For each vertex, check whether it lies on a segment
60 for ( int iVert = 0, nVerts = n - isClosed; iVert < nVerts; ++iVert )
61 {
62 const QgsPoint &p = ring[iVert];
63 for ( int i = 0, j = 1; j < n; i = j++ )
64 {
65 if ( iVert == i || iVert == j || ( isClosed && iVert == 0 && j == n - 1 ) )
66 {
67 continue;
68 }
69 const QgsPoint &si = ring[i];
70 const QgsPoint &sj = ring[j];
73 {
74 errors.append( new QgsSingleGeometryCheckError( this, geometry, QgsGeometry( p.clone() ), QgsVertexId( iPart, iRing, vtxMap[iVert] ) ) );
75 break; // No need to report same contact on different segments multiple times
76 }
77 }
78 }
79 }
80 }
81 return errors;
82}
83
84void QgsGeometrySelfContactCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes & /*changes*/ ) const
85{
86 Q_UNUSED( featurePools )
87 if ( method == NoChange )
88 {
89 error->setFixed( method );
90 }
91 else
92 {
93 error->setFixFailed( tr( "Unknown method" ) );
94 }
95}
96
98{
99 static const QStringList methods = QStringList() << tr( "No action" );
100 return methods;
101}
102
104{
106}
Abstract base class for all geometries.
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
virtual int partCount() const =0
Returns count of parts contained in the geometry.
const double tolerance
The tolerance to allow for in geometry checks.
This represents an error reported by a geometry check.
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.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
const QgsGeometryCheckContext * mContext
CheckType
The type of a check.
@ FeatureNodeCheck
The check controls individual nodes.
static QgsGeometryCheck::CheckType factoryCheckType()
QList< QgsSingleGeometryCheckError * > processGeometry(const QgsGeometry &geometry) const override
Check the geometry for errors.
void fixError(const QMap< QString, QgsFeaturePool * > &featurePools, QgsGeometryCheckError *error, int method, const QMap< QString, int > &mergeAttributeIndices, Changes &) const override
Fixes the error error with the specified method.
Q_DECL_DEPRECATED QStringList resolutionMethods() const override
Returns a list of descriptions for available resolutions for errors.
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2) SIP_HOLDGIL
Returns the squared 2D distance between two points.
static QgsPoint projectPointOnSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2) SIP_HOLDGIL
Project the point on a segment.
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.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:104
An error from a QgsSingleGeometryCheck.
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31