QGIS API Documentation  3.23.0-Master (c716e02dd3)
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 
21 QList<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 
84 void 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