QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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  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  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 QStringList methods = QStringList() << tr( "No action" );
100  return methods;
101 }
102 
104 {
106 }
static QgsGeometryCheck::CheckType factoryCheckType()
QStringList resolutionMethods() const override
Returns a list of descriptions for available resolutions for errors.
CheckType
The type of a check.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
void setFixFailed(const QString &reason)
Set the error status to failed and specify the reason for failure.
Utility class for identifying a unique vertex within a geometry.
QList< QgsSingleGeometryCheckError * > processGeometry(const QgsGeometry &geometry) const override
Check the geometry for errors.
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:97
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
Abstract base class for all geometries.
const QgsGeometryCheckContext * mContext
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
An error from a QgsSingleGeometryCheck.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static double sqrDistance2D(const QgsPoint &pt1, const QgsPoint &pt2)
Returns the squared 2D distance between two points.
QMap< QString, QMap< QgsFeatureId, QList< QgsGeometryCheck::Change > > > Changes
A collection of changes.
const double tolerance
The tolerance to allow for in geometry checks.
void setFixed(int method)
Set the status to fixed and specify the method that has been used to fix the error.
virtual int vertexCount(int part=0, int ring=0) const =0
Returns the number of vertices of which this geometry is built.
static QgsPoint projectPointOnSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2)
Project the point on a segment.
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.
This represents an error reported by a geometry check.
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.
The check controls individual nodes.