Skip to content
Permalink
Browse files

Merge pull request #5410 from manisandro/geomchecker

[FEATURE][Geometry checker] Support checking multiple layers at once, add new checks
  • Loading branch information
manisandro committed Oct 23, 2017
2 parents 46a6f25 + 8421a7e commit ea0e09b322d484fcdee299171c5381146a2814a5
Showing with 5,572 additions and 2,472 deletions.
  1. +8 −0 python/core/geometry/qgsgeometryengine.sip
  2. +1 −0 python/gui/gui_auto.sip
  3. +42 −0 python/gui/qgsvscrollarea.sip
  4. +54 −0 src/analysis/CMakeLists.txt
  5. +19 −10 src/{plugins/geometry_checker/utils → analysis/vector/geometry_checker}/qgsfeaturepool.cpp
  6. +13 −5 src/{plugins/geometry_checker/utils → analysis/vector/geometry_checker}/qgsfeaturepool.h
  7. +23 −26 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryanglecheck.cpp
  8. +11 −7 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryanglecheck.h
  9. +40 −59 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryareacheck.cpp
  10. +13 −10 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryareacheck.h
  11. +76 −68 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrycheck.cpp
  12. +64 −37 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrycheck.h
  13. +292 −0 src/analysis/vector/geometry_checker/qgsgeometrychecker.cpp
  14. +11 −10 src/{plugins → analysis/vector}/geometry_checker/qgsgeometrychecker.h
  15. +335 −0 src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp
  16. +161 −0 src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.h
  17. +112 −0 src/analysis/vector/geometry_checker/qgsgeometrycontainedcheck.cpp
  18. +18 −15 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrycontainedcheck.h
  19. +109 −0 src/analysis/vector/geometry_checker/qgsgeometrydanglecheck.cpp
  20. +40 −0 src/analysis/vector/geometry_checker/qgsgeometrydanglecheck.h
  21. +12 −16 ...geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrydegeneratepolygoncheck.cpp
  22. +8 −6 ...s/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrydegeneratepolygoncheck.h
  23. +141 −0 src/analysis/vector/geometry_checker/qgsgeometryduplicatecheck.cpp
  24. +16 −22 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryduplicatecheck.h
  25. +14 −25 ...ns/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryduplicatenodescheck.cpp
  26. +7 −6 ...gins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryduplicatenodescheck.h
  27. +106 −0 src/analysis/vector/geometry_checker/qgsgeometryfollowboundariescheck.cpp
  28. +44 −0 src/analysis/vector/geometry_checker/qgsgeometryfollowboundariescheck.h
  29. +61 −62 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrygapcheck.cpp
  30. +20 −27 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrygapcheck.h
  31. +21 −18 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryholecheck.cpp
  32. +8 −6 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryholecheck.h
  33. +88 −0 src/analysis/vector/geometry_checker/qgsgeometrylineintersectioncheck.cpp
  34. +40 −0 src/analysis/vector/geometry_checker/qgsgeometrylineintersectioncheck.h
  35. +85 −0 src/analysis/vector/geometry_checker/qgsgeometrylinelayerintersectioncheck.cpp
  36. +43 −0 src/analysis/vector/geometry_checker/qgsgeometrylinelayerintersectioncheck.h
  37. +14 −20 ...plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrymultipartcheck.cpp
  38. +8 −6 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrymultipartcheck.h
  39. +200 −0 src/analysis/vector/geometry_checker/qgsgeometryoverlapcheck.cpp
  40. +40 −21 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryoverlapcheck.h
  41. +86 −0 src/analysis/vector/geometry_checker/qgsgeometrypointcoveredbylinecheck.cpp
  42. +40 −0 src/analysis/vector/geometry_checker/qgsgeometrypointcoveredbylinecheck.h
  43. +81 −0 src/analysis/vector/geometry_checker/qgsgeometrypointinpolygoncheck.cpp
  44. +40 −0 src/analysis/vector/geometry_checker/qgsgeometrypointinpolygoncheck.h
  45. +23 −21 ...ins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrysegmentlengthcheck.cpp
  46. +12 −8 ...ugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrysegmentlengthcheck.h
  47. +11 −18 ...ugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryselfcontactcheck.cpp
  48. +8 −6 ...plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryselfcontactcheck.h
  49. +43 −51 .../geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryselfintersectioncheck.cpp
  50. +12 −10 ...ns/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometryselfintersectioncheck.h
  51. +31 −0 src/analysis/vector/geometry_checker/qgsgeometrysliverpolygoncheck.cpp
  52. +10 −17 ...ugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrysliverpolygoncheck.h
  53. +20 −26 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrytypecheck.cpp
  54. +12 −10 src/{plugins/geometry_checker/checks → analysis/vector/geometry_checker}/qgsgeometrytypecheck.h
  55. +7 −0 src/core/geometry/qgsgeometryengine.h
  56. +24 −0 src/core/geometry/qgsgeos.cpp
  57. +1 −0 src/core/geometry/qgsgeos.h
  58. +2 −0 src/gui/CMakeLists.txt
  59. +36 −0 src/gui/qgsvscrollarea.cpp
  60. +44 −0 src/gui/qgsvscrollarea.h
  61. +18 −52 src/plugins/geometry_checker/CMakeLists.txt
  62. +0 −110 src/plugins/geometry_checker/checks/qgsgeometrycontainedcheck.cpp
  63. +0 −121 src/plugins/geometry_checker/checks/qgsgeometryduplicatecheck.cpp
  64. +0 −203 src/plugins/geometry_checker/checks/qgsgeometryoverlapcheck.cpp
  65. +0 −262 src/plugins/geometry_checker/qgsgeometrychecker.cpp
  66. +6 −5 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerdialog.cpp
  67. +2 −1 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerdialog.h
  68. +35 −38 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerfixsummarydialog.cpp
  69. +3 −4 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerfixsummarydialog.h
  70. +22 −2 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerfixsummarydialog.ui
  71. +1 −1 src/plugins/geometry_checker/qgsgeometrycheckerplugin.cpp
  72. +139 −109 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerresulttab.cpp
  73. +3 −4 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerresulttab.h
  74. +144 −137 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckerresulttab.ui
  75. +511 −0 src/plugins/geometry_checker/qgsgeometrycheckersetuptab.cpp
  76. +5 −5 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckersetuptab.h
  77. +231 −121 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckersetuptab.ui
  78. +270 −83 src/plugins/geometry_checker/qgsgeometrycheckfactory.cpp
  79. +5 −6 src/plugins/geometry_checker/qgsgeometrycheckfactory.h
  80. +10 −12 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckfixdialog.cpp
  81. +1 −2 src/plugins/geometry_checker/{ui → }/qgsgeometrycheckfixdialog.h
  82. +0 −341 src/plugins/geometry_checker/ui/qgsgeometrycheckersetuptab.cpp
  83. +0 −120 src/plugins/geometry_checker/utils/qgsgeometrycheckerutils.cpp
  84. +0 −84 src/plugins/geometry_checker/utils/qgsgeometrycheckerutils.h
  85. +1 −0 tests/src/CMakeLists.txt
  86. +59 −0 tests/src/geometry_checker/CMakeLists.txt
  87. +1,129 −0 tests/src/geometry_checker/testqgsgeometrychecks.cpp
  88. BIN tests/testdata/geometry_checker/follow_ref.dbf
  89. +1 −0 tests/testdata/geometry_checker/follow_ref.prj
  90. +1 −0 tests/testdata/geometry_checker/follow_ref.qpj
  91. BIN tests/testdata/geometry_checker/follow_ref.shp
  92. BIN tests/testdata/geometry_checker/follow_ref.shx
  93. BIN tests/testdata/geometry_checker/follow_subj.dbf
  94. +1 −0 tests/testdata/geometry_checker/follow_subj.prj
  95. +1 −0 tests/testdata/geometry_checker/follow_subj.qpj
  96. BIN tests/testdata/geometry_checker/follow_subj.shp
  97. BIN tests/testdata/geometry_checker/follow_subj.shx
  98. +1 −0 tests/testdata/geometry_checker/gap_layer.cpg
  99. BIN tests/testdata/geometry_checker/gap_layer.dbf
  100. +1 −0 tests/testdata/geometry_checker/gap_layer.prj
  101. +1 −0 tests/testdata/geometry_checker/gap_layer.qpj
  102. BIN tests/testdata/geometry_checker/gap_layer.shp
  103. BIN tests/testdata/geometry_checker/gap_layer.shx
  104. +1 −0 tests/testdata/geometry_checker/line_layer.cpg
  105. BIN tests/testdata/geometry_checker/line_layer.dbf
  106. +1 −0 tests/testdata/geometry_checker/line_layer.prj
  107. +1 −0 tests/testdata/geometry_checker/line_layer.qpj
  108. BIN tests/testdata/geometry_checker/line_layer.shp
  109. BIN tests/testdata/geometry_checker/line_layer.shx
  110. +1 −0 tests/testdata/geometry_checker/point_layer.cpg
  111. BIN tests/testdata/geometry_checker/point_layer.dbf
  112. +1 −0 tests/testdata/geometry_checker/point_layer.prj
  113. +1 −0 tests/testdata/geometry_checker/point_layer.qpj
  114. BIN tests/testdata/geometry_checker/point_layer.shp
  115. BIN tests/testdata/geometry_checker/point_layer.shx
  116. +1 −0 tests/testdata/geometry_checker/polygon_layer.cpg
  117. BIN tests/testdata/geometry_checker/polygon_layer.dbf
  118. +1 −0 tests/testdata/geometry_checker/polygon_layer.prj
  119. +1 −0 tests/testdata/geometry_checker/polygon_layer.qpj
  120. BIN tests/testdata/geometry_checker/polygon_layer.shp
  121. BIN tests/testdata/geometry_checker/polygon_layer.shx
@@ -73,6 +73,14 @@ class QgsGeometryEngine
%Docstring
Calculate the combination of this and ``geom``.

.. versionadded:: 3.0
:rtype: QgsAbstractGeometry
%End

virtual QgsAbstractGeometry *combine( const QList<QgsAbstractGeometry *> &geomList, QString *errorMsg ) const = 0 /Factory/;
%Docstring
Calculate the combination of this and ``geometries``.

.. versionadded:: 3.0
:rtype: QgsAbstractGeometry
%End
@@ -21,6 +21,7 @@
%Include qgsabstractdatasourcewidget.sip
%Include qgssourceselectprovider.sip
%Include qgssourceselectproviderregistry.sip
%Include qgsvscrollarea.sip
%Include attributetable/qgsfeaturemodel.sip
%Include auth/qgsauthauthoritieseditor.sip
%Include auth/qgsauthcertificateinfo.sip
@@ -0,0 +1,42 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsvscrollarea.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsVScrollArea : QScrollArea
{
%Docstring
QgsVScrollArea is a QScrollArea subclass which only displays a vertical
scrollbar and fits the width to the contents.

.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsvscrollarea.h"
%End
public:

QgsVScrollArea( QWidget *parent = 0 );
%Docstring
QgsVScrollArea
\param parent The parent widget
%End

virtual bool eventFilter( QObject *o, QEvent *e );

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsvscrollarea.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
@@ -82,6 +82,33 @@ SET(QGIS_ANALYSIS_SRCS
network/qgsnetworkdistancestrategy.cpp
network/qgsvectorlayerdirector.cpp
network/qgsgraphanalyzer.cpp

vector/geometry_checker/qgsfeaturepool.cpp
vector/geometry_checker/qgsgeometrychecker.cpp
vector/geometry_checker/qgsgeometryanglecheck.cpp
vector/geometry_checker/qgsgeometryareacheck.cpp
vector/geometry_checker/qgsgeometrycheck.cpp
vector/geometry_checker/qgsgeometrychecker.cpp
vector/geometry_checker/qgsgeometrycheckerutils.cpp
vector/geometry_checker/qgsgeometrycontainedcheck.cpp
vector/geometry_checker/qgsgeometrydanglecheck.cpp
vector/geometry_checker/qgsgeometrydegeneratepolygoncheck.cpp
vector/geometry_checker/qgsgeometryduplicatecheck.cpp
vector/geometry_checker/qgsgeometryduplicatenodescheck.cpp
vector/geometry_checker/qgsgeometrygapcheck.cpp
vector/geometry_checker/qgsgeometryfollowboundariescheck.cpp
vector/geometry_checker/qgsgeometryholecheck.cpp
vector/geometry_checker/qgsgeometrylineintersectioncheck.cpp
vector/geometry_checker/qgsgeometrylinelayerintersectioncheck.cpp
vector/geometry_checker/qgsgeometrymultipartcheck.cpp
vector/geometry_checker/qgsgeometryoverlapcheck.cpp
vector/geometry_checker/qgsgeometrypointcoveredbylinecheck.cpp
vector/geometry_checker/qgsgeometrypointinpolygoncheck.cpp
vector/geometry_checker/qgsgeometrysegmentlengthcheck.cpp
vector/geometry_checker/qgsgeometryselfcontactcheck.cpp
vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp
vector/geometry_checker/qgsgeometrysliverpolygoncheck.cpp
vector/geometry_checker/qgsgeometrytypecheck.cpp
)

SET(QGIS_ANALYSIS_MOC_HDRS
@@ -91,6 +118,33 @@ SET(QGIS_ANALYSIS_MOC_HDRS

network/qgsgraphdirector.h
network/qgsvectorlayerdirector.h

vector/geometry_checker/qgsfeaturepool.h
vector/geometry_checker/qgsgeometrychecker.h
vector/geometry_checker/qgsgeometryanglecheck.h
vector/geometry_checker/qgsgeometryareacheck.h
vector/geometry_checker/qgsgeometrychecker.h
vector/geometry_checker/qgsgeometrycheckerutils.h
vector/geometry_checker/qgsgeometrycheck.h
vector/geometry_checker/qgsgeometrycontainedcheck.h
vector/geometry_checker/qgsgeometrydanglecheck.h
vector/geometry_checker/qgsgeometrydegeneratepolygoncheck.h
vector/geometry_checker/qgsgeometryduplicatecheck.h
vector/geometry_checker/qgsgeometryduplicatenodescheck.h
vector/geometry_checker/qgsgeometryfollowboundariescheck.h
vector/geometry_checker/qgsgeometrygapcheck.h
vector/geometry_checker/qgsgeometryholecheck.h
vector/geometry_checker/qgsgeometrylineintersectioncheck.h
vector/geometry_checker/qgsgeometrylinelayerintersectioncheck.h
vector/geometry_checker/qgsgeometrymultipartcheck.h
vector/geometry_checker/qgsgeometryoverlapcheck.h
vector/geometry_checker/qgsgeometrypointcoveredbylinecheck.h
vector/geometry_checker/qgsgeometrypointinpolygoncheck.h
vector/geometry_checker/qgsgeometrysegmentlengthcheck.h
vector/geometry_checker/qgsgeometryselfcontactcheck.h
vector/geometry_checker/qgsgeometryselfintersectioncheck.h
vector/geometry_checker/qgsgeometrysliverpolygoncheck.h
vector/geometry_checker/qgsgeometrytypecheck.h
)

INCLUDE_DIRECTORIES(SYSTEM ${SPATIALITE_INCLUDE_DIR})
@@ -25,9 +25,11 @@
#include <QMutexLocker>
#include <limits>

QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, bool selectedOnly )
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, double layerToMapUnits, const QgsCoordinateTransform &layerToMapTransform, bool selectedOnly )
: mFeatureCache( CACHE_SIZE )
, mLayer( layer )
, mLayerToMapUnits( layerToMapUnits )
, mLayerToMapTransform( layerToMapTransform )
, mSelectedOnly( selectedOnly )
{
if ( selectedOnly )
@@ -46,7 +48,7 @@ QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, bool selectedOnly )
QgsFeatureIterator it = layer->getFeatures( req );
while ( it.nextFeature( feature ) )
{
if ( feature.geometry() )
if ( mFeatureIds.contains( feature.id() ) && feature.geometry() )
{
mIndex.insertFeature( feature );
}
@@ -103,6 +105,9 @@ void QgsFeaturePool::addFeature( QgsFeature &feature )

void QgsFeaturePool::updateFeature( QgsFeature &feature )
{
QgsFeature origFeature;
get( feature.id(), origFeature );

QgsGeometryMap geometryMap;
geometryMap.insert( feature.id(), QgsGeometry( feature.geometry().geometry()->clone() ) );
QgsChangedAttributesMap changedAttributesMap;
@@ -118,23 +123,27 @@ void QgsFeaturePool::updateFeature( QgsFeature &feature )
mLayer->dataProvider()->changeAttributeValues( changedAttributesMap );
mLayerMutex.unlock();
mIndexMutex.lock();
mIndex.deleteFeature( feature );
mIndex.deleteFeature( origFeature );
mIndex.insertFeature( feature );
mIndexMutex.unlock();
}

void QgsFeaturePool::deleteFeature( QgsFeature &feature )
void QgsFeaturePool::deleteFeature( const QgsFeatureId &fid )
{
mIndexMutex.lock();
mIndex.deleteFeature( feature );
mIndexMutex.unlock();
QgsFeature origFeature;
if ( get( fid, origFeature ) )
{
mIndexMutex.lock();
mIndex.deleteFeature( origFeature );
mIndexMutex.unlock();
}
mLayerMutex.lock();
mFeatureCache.remove( feature.id() );
mLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << feature.id() );
mFeatureCache.remove( origFeature.id() );
mLayer->dataProvider()->deleteFeatures( QgsFeatureIds() << fid );
mLayerMutex.unlock();
}

QgsFeatureIds QgsFeaturePool::getIntersects( const QgsRectangle &rect )
QgsFeatureIds QgsFeaturePool::getIntersects( const QgsRectangle &rect ) const
{
QMutexLocker lock( &mIndexMutex );
return QgsFeatureIds::fromList( mIndex.intersects( rect ) );
@@ -14,30 +14,36 @@
* *
***************************************************************************/

#define SIP_NO_FILE

#ifndef QGS_FEATUREPOOL_H
#define QGS_FEATUREPOOL_H

#include <QCache>
#include <QLinkedList>
#include <QMap>
#include <QMutex>
#include "qgis_analysis.h"
#include "qgsfeature.h"
#include "qgsspatialindex.h"
#include "qgsgeometrycheckerutils.h"

class QgsVectorLayer;

class QgsFeaturePool
class ANALYSIS_EXPORT QgsFeaturePool : public QObject
{
Q_OBJECT
public:
QgsFeaturePool( QgsVectorLayer *layer, bool selectedOnly = false );
QgsFeaturePool( QgsVectorLayer *layer, double layerToMapUnits, const QgsCoordinateTransform &layerToMapTransform, bool selectedOnly = false );
bool get( QgsFeatureId id, QgsFeature &feature );
void addFeature( QgsFeature &feature );
void updateFeature( QgsFeature &feature );
void deleteFeature( QgsFeature &feature );
QgsFeatureIds getIntersects( const QgsRectangle &rect );
void deleteFeature( const QgsFeatureId &fid );
QgsFeatureIds getIntersects( const QgsRectangle &rect ) const;
QgsVectorLayer *getLayer() const { return mLayer; }
const QgsFeatureIds &getFeatureIds() const { return mFeatureIds; }
double getLayerToMapUnits() const { return mLayerToMapUnits; }
const QgsCoordinateTransform &getLayerToMapTransform() const { return mLayerToMapTransform; }
bool getSelectedOnly() const { return mSelectedOnly; }
void clearLayer() { mLayer = nullptr; }

@@ -58,8 +64,10 @@ class QgsFeaturePool
QgsVectorLayer *mLayer = nullptr;
QgsFeatureIds mFeatureIds;
QMutex mLayerMutex;
QMutex mIndexMutex;
mutable QMutex mIndexMutex;
QgsSpatialIndex mIndex;
double mLayerToMapUnits;
QgsCoordinateTransform mLayerToMapTransform;
bool mSelectedOnly;

bool getTouchingWithSharedEdge( QgsFeature &feature, QgsFeatureId &touchingId, const double & ( *comparator )( const double &, const double & ), double init );
@@ -15,32 +15,27 @@

#include "qgsgeometryanglecheck.h"
#include "qgsgeometryutils.h"
#include "../utils/qgsfeaturepool.h"
#include "qgsfeaturepool.h"

void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QgsFeatureIds &ids ) const
void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QMap<QString, QgsFeatureIds> &ids ) const
{
const QgsFeatureIds &featureIds = ids.isEmpty() ? mFeaturePool->getFeatureIds() : ids;
Q_FOREACH ( QgsFeatureId featureid, featureIds )
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
QgsGeometryCheckerUtils::LayerFeatures layerFeatures( mContext->featurePools, featureIds, mCompatibleGeometryTypes, progressCounter );
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
{
if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
QgsFeature feature;
if ( !mFeaturePool->get( featureid, feature ) )
{
continue;
}
QgsGeometry g = feature.geometry();
const QgsAbstractGeometry *geom = g.geometry();
const QgsAbstractGeometry *geom = layerFeature.geometry();
for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart )
{
for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )
{
int nVerts = QgsGeometryCheckerUtils::polyLineSize( geom, iPart, iRing );
bool closed = false;
int nVerts = QgsGeometryCheckerUtils::polyLineSize( geom, iPart, iRing, &closed );
// Less than three points, no angles to check
if ( nVerts < 3 )
{
continue;
}
for ( int iVert = 0; iVert < nVerts; ++iVert )
for ( int iVert = !closed; iVert < nVerts - !closed; ++iVert )
{
const QgsPoint &p1 = geom->vertexAt( QgsVertexId( iPart, iRing, ( iVert - 1 + nVerts ) % nVerts ) );
const QgsPoint &p2 = geom->vertexAt( QgsVertexId( iPart, iRing, iVert ) );
@@ -57,27 +52,28 @@ void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &error
continue;
}

double angle = std::acos( v21 * v23 ) / M_PI * 180.0;
double angle = qAcos( v21 * v23 ) / M_PI * 180.0;
if ( angle < mMinAngle )
{
errors.append( new QgsGeometryCheckError( this, featureid, p2, QgsVertexId( iPart, iRing, iVert ), angle ) );
errors.append( new QgsGeometryCheckError( this, layerFeature, p2, QgsVertexId( iPart, iRing, iVert ), angle ) );
}
}
}
}
}
}

void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError *error, int method, int /*mergeAttributeIndex*/, Changes &changes ) const
void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
QgsFeaturePool *featurePool = mContext->featurePools[ error->layerId() ];
QgsFeature feature;
if ( !mFeaturePool->get( error->featureId(), feature ) )
if ( !featurePool->get( error->featureId(), feature ) )
{
error->setObsolete();
return;
}
QgsGeometry g = feature.geometry();
QgsAbstractGeometry *geometry = g.geometry();
QgsGeometry featureGeometry = feature.geometry();
QgsAbstractGeometry *geometry = featureGeometry.geometry();
QgsVertexId vidx = error->vidx();

// Check if point still exists
@@ -132,15 +128,16 @@ void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError *error, int method,
}
else
{
changes[error->featureId()].append( Change( ChangeNode, ChangeRemoved, vidx ) );
if ( QgsGeometryUtils::sqrDistance2D( p1, p3 ) < QgsGeometryCheckPrecision::tolerance() * QgsGeometryCheckPrecision::tolerance()
&& QgsGeometryCheckerUtils::canDeleteVertex( geometry, vidx.part, vidx.ring ) &&
changes[error->layerId()][error->featureId()].append( Change( ChangeNode, ChangeRemoved, vidx ) );
// Avoid duplicate nodes as result of deleting spike vertex
if ( QgsGeometryUtils::sqrDistance2D( p1, p3 ) < mContext->tolerance &&
QgsGeometryCheckerUtils::canDeleteVertex( geometry, vidx.part, vidx.ring ) &&
geometry->deleteVertex( error->vidx() ) ) // error->vidx points to p3 after removing p2
{
changes[error->featureId()].append( Change( ChangeNode, ChangeRemoved, QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + 1 ) % n ) ) );
changes[error->layerId()][error->featureId()].append( Change( ChangeNode, ChangeRemoved, QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + 1 ) % n ) ) );
}
feature.setGeometry( g );
mFeaturePool->updateFeature( feature );
feature.setGeometry( featureGeometry );
featurePool->updateFeature( feature );
error->setFixed( method );
}
}
@@ -13,27 +13,31 @@
* *
***************************************************************************/

#define SIP_NO_FILE

#ifndef QGS_GEOMETRY_ANGLE_CHECK_H
#define QGS_GEOMETRY_ANGLE_CHECK_H

#include "qgsgeometrycheck.h"

class QgsGeometryAngleCheck : public QgsGeometryCheck
class ANALYSIS_EXPORT QgsGeometryAngleCheck : public QgsGeometryCheck
{
Q_OBJECT

public:
QgsGeometryAngleCheck( QgsFeaturePool *featurePool, double minAngle )
: QgsGeometryCheck( FeatureNodeCheck, featurePool )
, mMinAngle( minAngle )
QgsGeometryAngleCheck( QgsGeometryCheckerContext *context, double minAngle )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::LineGeometry, QgsWkbTypes::PolygonGeometry}, context )
, mMinAngle( minAngle )
{}
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QgsFeatureIds &ids = QgsFeatureIds() ) const override;
void fixError( QgsGeometryCheckError *error, int method, int mergeAttributeIndex, Changes &changes ) const override;
void collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &messages, QAtomicInt *progressCounter = nullptr, const QMap<QString, QgsFeatureIds> &ids = QMap<QString, QgsFeatureIds>() ) const override;
void fixError( QgsGeometryCheckError *error, int method, const QMap<QString, int> &mergeAttributeIndices, Changes &changes ) const override;
QStringList getResolutionMethods() const override;
QString errorDescription() const override { return tr( "Minimal angle" ); }
QString errorName() const override { return QStringLiteral( "QgsGeometryAngleCheck" ); }
private:

enum ResolutionMethod { DeleteNode, NoChange };

private:
double mMinAngle;
};

0 comments on commit ea0e09b

Please sign in to comment.
You can’t perform that action at this time.