Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE][Geometry checker] Support checking multiple layers at once, add new checks #5410

Merged
merged 103 commits into from
Oct 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
31cc65d
[Geometry checker] Initial multi-layer support
manisandro Mar 30, 2017
2a92bfb
[Geometry checker] Introduce QgsGeometryCheckerContext
manisandro Mar 30, 2017
e7efde2
[Geometry checker] Make checks report affected are in selected crs
manisandro Mar 30, 2017
46e3ef7
[Geometry checker] Ensure headers appear in project tree
manisandro Apr 4, 2017
23affe4
[Geometry checker] Store error values in map units, perform topology …
manisandro Apr 4, 2017
dd12b13
[Geometry checker] Add multi-layer support to gap check
manisandro Apr 4, 2017
3d8ffcb
[Geometry checker] Initial multilayer support for overlap check
manisandro Apr 5, 2017
55cf125
[Geometry checker] Initial multilayer support for duplicate check
manisandro Apr 5, 2017
821eb40
[Geometry checker] Initial multilayer support for contained check
manisandro Apr 5, 2017
b52b2c5
[Geometry checker] Introduce QgsGeometryCheckerUtils::LayerFeatures
manisandro Apr 12, 2017
1642eb1
[Geometry checker] Adapt for API changes
manisandro Jun 15, 2017
84184d4
[Geometry checker] Use map crs for geometry and errorLocation in Chec…
manisandro Jun 26, 2017
7fb1c55
[Geometry checker] Add dangle check
manisandro Jun 27, 2017
ee47d42
[Geometry checker] Add point must be covered by line check
manisandro Jun 27, 2017
b9966aa
[Geometry checker] Extend duplicate check to also handle points
manisandro Jun 27, 2017
b5208c0
[Geometry checker] Simplify code
manisandro Jun 27, 2017
3842f42
[Geometry checker] Add line intersection check
manisandro Jun 27, 2017
e88f32a
[Geometry checker] Add point in polygon check
manisandro Jun 27, 2017
f0f66d7
[Geometry checker] Fix LayerFeature iterator
manisandro Jun 28, 2017
c1b06ce
[Geometry checker] Tweak logic for choosing which layers are selected…
manisandro Jun 28, 2017
45862ed
[Geometry checker] Rename tab: Settings -> Setup
manisandro Jun 28, 2017
5470b16
[Geometry checker] Set appropriate initial size for checker dialog
manisandro Jun 28, 2017
57c348b
[Geometry checker] Ensure all UI items are consistently enabled/disab…
manisandro Jun 28, 2017
7a51866
[Geometry checker] Fix angle check possibly reporting end nodes of lines
manisandro Jun 28, 2017
29d057c
[Geometry checker] Reduce icon size in setup layer list
manisandro Jun 28, 2017
81a4a52
[Geometry checker] Fix updating and gathering of layers
manisandro Jun 28, 2017
018467f
[Geometry checker] Fix determining active layer geometry types
manisandro Jun 28, 2017
b80fa36
[Geometry checker] Imporove logic for picking the output directory
manisandro Jun 28, 2017
5e6501f
[Geometry checker] Add layer column to result table
manisandro Jun 28, 2017
0740979
[Geometry checker] Improve label
manisandro Jun 28, 2017
aa27b66
[Geometry checker] Fix some feature highlighting issues
manisandro Jun 28, 2017
e0caef9
[Geometry checker] Introduce vertical-only scroll-areas
manisandro Jun 28, 2017
374e186
[Geometry checker] Add layer column to fix summary dialog tables
manisandro Jun 28, 2017
49b3cee
[Geometry checker] Various ui improvements
manisandro Jun 28, 2017
2b01ccf
[Geometry checker] Run contained check in map crs
manisandro Jun 29, 2017
5c84840
[Geometry checker] Don't self-compare features in contained check
manisandro Jun 29, 2017
f523af9
[Geometry checker] Don't use QgsScrollArea...
manisandro Jun 29, 2017
0b974c6
[Geometry checker] Only update layer list in setup tab after layers h…
manisandro Jun 29, 2017
9fe1d7b
[Geometry checker] Add tooltip with data source to layers in setup tab
manisandro Jun 29, 2017
c14cdbb
[Geometry checker] Fix incorrect mapToLayerUnits -> layerToMapUntis
manisandro Jun 29, 2017
9cbaebe
[Geometry checker] Store feature pool directly in LayerFeature instea…
manisandro Jun 29, 2017
732ce4c
[Geometry checker] Handle fid changes
manisandro Jul 6, 2017
d6d584b
[Geometry checker] Show layer names instead of ids in user-facing str…
manisandro Jul 6, 2017
6c088e7
[Geometry checker] Fix logic to ensure that each pair of features is …
manisandro Jul 6, 2017
f114b53
[Geometry checker] Allow adding a prefix to output layer names
manisandro Jul 6, 2017
c71d421
[Geometry checker] Fix layerFeature comparison
manisandro Jul 6, 2017
e4de3a8
[Geometry checker] Update for QgsGeometryEngine API changes
manisandro Sep 19, 2017
bd8028e
[Geometry checker] Add line layer intersection check
manisandro Sep 25, 2017
156f006
[Geometry checker] Enter update mode when editing result layers
manisandro Sep 25, 2017
a555320
[Geometry checker] Reorder some UI elements
manisandro Sep 25, 2017
767538b
[Geometry checker] Move core classes to qgis_analysis
manisandro Sep 26, 2017
816273e
[Geometry checker] Drop feature id update logic now handled by freezi…
manisandro Sep 26, 2017
183671f
[Geometry checker] Use symDifference for all geometry types to detect…
manisandro Sep 27, 2017
44ce916
[Geometry checker] Also check other parts of same feature in dangle c…
manisandro Sep 27, 2017
54019e1
[Geometry checker] Make contained check work with all geometry types
manisandro Sep 27, 2017
07dc429
[Geometry checker] Some initial tests
manisandro Sep 27, 2017
7bb5583
[Geometry checker] Don't make line intersection test report symmetric…
manisandro Sep 28, 2017
e5e3fde
[Geometry checker] Introduce QgsGeometryCheckerUtils::polygonRings
manisandro Sep 28, 2017
5ded4f8
[Geometry checker] Ensure line layer intersection test does not check…
manisandro Sep 28, 2017
baf4a39
[Geometry checker] Make line intersection test and line layer interse…
manisandro Sep 28, 2017
db8b53f
[Geometry checker] Ensure duplicate check ui is enabled also for lines
manisandro Sep 28, 2017
87cdeda
[Geometry checker] Report if geometry is invalid in overlap check
manisandro Sep 28, 2017
58e39f6
[Geometry checker] Ensure overlap check returns on error for each ove…
manisandro Sep 28, 2017
3dc083c
[Geometry checker] Uniformize error messages
manisandro Sep 28, 2017
0f68737
[Geometry checker] Simplify point in polygon check
manisandro Sep 28, 2017
3cc7272
[Geometry checker] Don't report segment lengths smaller than checker …
manisandro Sep 28, 2017
85f8c25
[Geometry checker] Specify part in error parametrization in line and …
manisandro Sep 28, 2017
f48cf24
[Geometry checker] Fix incorrect free in gap check
manisandro Sep 28, 2017
6b3309c
[Geometry checker] Add more tests
manisandro Sep 28, 2017
c44fa1d
[Geometry checker] Finish gap check test
manisandro Oct 12, 2017
bd44483
[Geometry checker] Fix type check factory
manisandro Oct 12, 2017
1e49955
[Geometry checker] Fix broken LayerFeature geometry transform
manisandro Oct 12, 2017
1372536
[Geometry checker] Add follow boundaries check
manisandro Oct 12, 2017
d71f62c
[Geometry checker] Make TestQgsGeometryChecks::searchCheckErrors retu…
manisandro Oct 14, 2017
0ffd00d
[Geometry checker] Add TestQgsGeometryChecks::createTestContext varia…
manisandro Oct 14, 2017
8f343a9
[Geometry checker] Fix wrong obsoletes test in QgsGeometryContainedCh…
manisandro Oct 16, 2017
4a6cdbe
[Geometry checker] Add a first series of fixError tests
manisandro Oct 16, 2017
edf563b
[Geometry checker] Fix crashes in QgsGeometryGapCheck::mergeWithNeigh…
manisandro Oct 17, 2017
737d513
[Geometry checker] Use centroid of actual hole to report error in Qgs…
manisandro Oct 17, 2017
5b2297f
[Geometry checker] Fix incorrect ring index in QgsGeometrySelfInterse…
manisandro Oct 17, 2017
3b6a0e2
[Geometry checker] Fix crash in QgsGeometryCheckerResultTab::addError…
manisandro Oct 17, 2017
876418c
[Geometry checker] Add more fixError tests
manisandro Oct 17, 2017
cc9a2b3
[Geometry checker] Fix incorrect logic in QgsGeometryCheckError::hand…
manisandro Oct 17, 2017
8a56166
[Geometry checker] Remove debug print
manisandro Oct 19, 2017
084660a
[Geometry checker] More change tracking tests
manisandro Oct 19, 2017
efc00c3
[Geometry checker] Fix features not correctly removed from QgsFeature…
manisandro Oct 19, 2017
fde740a
Re-add QgsGeometryEngine::combine taking a list of QgsAbstractGeometries
manisandro Oct 19, 2017
f0116b4
[Geometry checker] Use reduced tolerance when attempting to combine t…
manisandro Oct 19, 2017
15b5da8
[Geometry checker] Fix incorrect change parametrization in QgsGeometr…
manisandro Oct 19, 2017
f507246
[Geometry checker] Don't recollect errors with empty recheck list
manisandro Oct 19, 2017
9218afd
[Geometry checker] Don't make the layer-feature iterator return featu…
manisandro Oct 19, 2017
5de0c80
[Geometry checker] Fix incomplete QgsGeometryOverlapCheckError::handl…
manisandro Oct 19, 2017
50e1c7a
[Geometry checker] Disable sorting in QgsGeometryCheckerFixSummaryDia…
manisandro Oct 19, 2017
e00f767
[Geometry checker] Fix possible crash in QgsGeometryCheckerFixSummary…
manisandro Oct 19, 2017
e089b3b
[Geometry checker] Only add to feature pool spatial indices features …
manisandro Oct 19, 2017
8cefc65
[Geometry checker] Don't recheck any features if fixed error resulted…
manisandro Oct 19, 2017
ecd951d
[Geometry checker] Try harder to match old errors to those found afte…
manisandro Oct 19, 2017
2c36a51
Add missing QgsVScrollArea documentation
manisandro Oct 19, 2017
1f300cf
Add QgsVScrollArea sip bindings
manisandro Oct 23, 2017
972d14f
[Geometry checker] Exclude from sip bindings
manisandro Oct 23, 2017
9a2393e
[Geometry checker] Qt < 5.9 compatibility fix
manisandro Oct 23, 2017
2dccc3c
[Geometry checker] Remove unused includes
manisandro Oct 23, 2017
8421a7e
[Geometry checker] Add some debug code
manisandro Oct 23, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions python/core/geometry/qgsgeometryengine.sip
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions python/gui/gui_auto.sip
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 42 additions & 0 deletions python/gui/qgsvscrollarea.sip
Original file line number Diff line number Diff line change
@@ -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 *
************************************************************************/
54 changes: 54 additions & 0 deletions src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,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
Expand All @@ -89,6 +116,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})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand All @@ -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 );
}
Expand Down Expand Up @@ -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;
Expand All @@ -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 ) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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; }

Expand All @@ -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 );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) );
Expand All @@ -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
Expand Down Expand Up @@ -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 );
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down
Loading