Skip to content

Commit 1af35b2

Browse files
committedSep 13, 2018
Moved new snapping alg as another mode of "Snap geometries" processing alg
1 parent cef3395 commit 1af35b2

File tree

10 files changed

+145
-137
lines changed

10 files changed

+145
-137
lines changed
 

‎python/analysis/analysis_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
%Include auto_generated/raster/qgsrastercalcnode.sip
1414
%Include auto_generated/raster/qgstotalcurvaturefilter.sip
1515
%Include auto_generated/vector/qgsgeometrysnapper.sip
16+
%Include auto_generated/vector/qgsgeometrysnappersinglesource.sip
1617
%Include auto_generated/vector/qgszonalstatistics.sip
1718
%Include auto_generated/interpolation/qgsinterpolator.sip
1819
%Include auto_generated/interpolation/qgsgridfilewriter.sip
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/analysis/vector/qgsgeometrysnappersinglesource.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsGeometrySnapperSingleSource
13+
{
14+
%Docstring
15+
16+
Makes sure that any two vertices of the vector layer are at least at distance given by the threshold value.
17+
The algorithm moves nearby vertices to one location and adds vertices to segments that are passing around other
18+
vertices within the threshold. It does not remove any vertices. Also, it does not modify geometries unless
19+
needed (it does not snap coordinates to a grid).
20+
21+
This algorithm comes handy when doing vector overlay operations such as intersection, union or difference
22+
to prevent possible topological errors caused by numerical errors if coordinates are very close to each other.
23+
24+
After running the algorithm some previously valid geometries may become invalid and therefore it may be useful
25+
to run Fix geometries algorithm afterwards.
26+
27+
.. note::
28+
29+
Originally ported from GRASS implementation of Vect_snap_lines_list()
30+
31+
.. versionadded:: 3.4
32+
%End
33+
34+
%TypeHeaderCode
35+
#include "qgsgeometrysnappersinglesource.h"
36+
%End
37+
public:
38+
39+
static int run( const QgsFeatureSource &source, QgsFeatureSink &sink, double thresh, QgsFeedback *feedback );
40+
%Docstring
41+
Run the algorithm on given source and output results to the sink, using threshold value in the source's map units.
42+
Returns number of modified geometries.
43+
%End
44+
};
45+
46+
/************************************************************************
47+
* This file has been generated automatically from *
48+
* *
49+
* src/analysis/vector/qgsgeometrysnappersinglesource.h *
50+
* *
51+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
52+
************************************************************************/

‎python/plugins/processing/algs/qgis/SnapGeometries.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
__revision__ = '$Format:%H$'
2727

2828
from qgis.analysis import (QgsGeometrySnapper,
29+
QgsGeometrySnapperSingleSource,
2930
QgsInternalGeometrySnapper)
3031
from qgis.core import (QgsFeatureSink,
3132
QgsProcessing,
@@ -71,7 +72,8 @@ def initAlgorithm(self, config=None):
7172
self.tr('Prefer closest point, don\'t insert new vertices'),
7273
self.tr('Move end points only, prefer aligning nodes'),
7374
self.tr('Move end points only, prefer closest point'),
74-
self.tr('Snap end points to end points only')]
75+
self.tr('Snap end points to end points only'),
76+
self.tr('Snap to anchor nodes (single layer only)')]
7577
self.addParameter(QgsProcessingParameterEnum(
7678
self.BEHAVIOR,
7779
self.tr('Behavior'),
@@ -106,6 +108,9 @@ def processAlgorithm(self, parameters, context, feedback):
106108
total = 100.0 / source.featureCount() if source.featureCount() else 0
107109

108110
if parameters[self.INPUT] != parameters[self.REFERENCE_LAYER]:
111+
if mode == 7:
112+
raise QgsProcessingException(self.tr('This mode applies when the input and reference layer are the same.'))
113+
109114
snapper = QgsGeometrySnapper(reference_source)
110115
processed = 0
111116
for f in features:
@@ -119,6 +124,10 @@ def processAlgorithm(self, parameters, context, feedback):
119124
sink.addFeature(f)
120125
processed += 1
121126
feedback.setProgress(processed * total)
127+
elif mode == 7:
128+
# input layer == ref layer
129+
modified_count = QgsGeometrySnapperSingleSource.run(source, sink, tolerance, feedback)
130+
feedback.pushInfo(self.tr('Snapped {} geometries.').format(modified_count))
122131
else:
123132
# snapping internally
124133
snapper = QgsInternalGeometrySnapper(tolerance, mode)
Binary file not shown.

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,22 @@ tests:
20452045
name: expected/snap_internal.gml
20462046
type: vector
20472047

2048+
- algorithm: qgis:snapgeometries
2049+
name: Test Snap Geometries (to each other)
2050+
params:
2051+
BEHAVIOR: '7'
2052+
INPUT:
2053+
name: custom/snap_geometries.geojson
2054+
type: vector
2055+
REFERENCE_LAYER:
2056+
name: custom/snap_geometries.geojson
2057+
type: vector
2058+
TOLERANCE: 0.5
2059+
results:
2060+
OUTPUT:
2061+
name: expected/snap_geometries.gml
2062+
type: vector
2063+
20482064
- algorithm: qgis:poleofinaccessibility
20492065
name: Pole of inaccessibility (polygons)
20502066
params:
@@ -5586,18 +5602,6 @@ tests:
55865602
fields:
55875603
fid: skip
55885604

5589-
- algorithm: native:snap
5590-
name: Test Snap Geometries (to each other)
5591-
params:
5592-
INPUT:
5593-
name: custom/snap_geometries.geojson
5594-
type: vector
5595-
THRESHOLD: 0.5
5596-
results:
5597-
OUTPUT:
5598-
name: expected/snap_geometries.gml
5599-
type: vector
5600-
56015605
- algorithm: native:taperedbuffer
56025606
name: Tapered buffers (lines)
56035607
params:

‎src/analysis/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ SET(QGIS_ANALYSIS_SRCS
8585
processing/qgsalgorithmshortestpathpointtopoint.cpp
8686
processing/qgsalgorithmsimplify.cpp
8787
processing/qgsalgorithmsmooth.cpp
88-
processing/qgsalgorithmsnapgeometries.cpp
8988
processing/qgsalgorithmsnaptogrid.cpp
9089
processing/qgsalgorithmsplitwithlines.cpp
9190
processing/qgsalgorithmstringconcatenation.cpp
@@ -124,6 +123,7 @@ SET(QGIS_ANALYSIS_SRCS
124123
raster/qgsrastermatrix.cpp
125124
vector/mersenne-twister.cpp
126125
vector/qgsgeometrysnapper.cpp
126+
vector/qgsgeometrysnappersinglesource.cpp
127127
vector/qgszonalstatistics.cpp
128128

129129
network/qgsgraph.cpp
@@ -232,6 +232,7 @@ SET(QGIS_ANALYSIS_HDRS
232232

233233
vector/mersenne-twister.h
234234
vector/qgsgeometrysnapper.h
235+
vector/qgsgeometrysnappersinglesource.h
235236
vector/qgszonalstatistics.h
236237
vector/geometry_checker/qgsgeometrycheckerutils.h
237238
vector/geometry_checker/qgsfeaturepool.h

‎src/analysis/processing/qgsalgorithmsnapgeometries.h

Lines changed: 0 additions & 45 deletions
This file was deleted.

‎src/analysis/processing/qgsnativealgorithms.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@
8282
#include "qgsalgorithmshortestpathpointtopoint.h"
8383
#include "qgsalgorithmsimplify.h"
8484
#include "qgsalgorithmsmooth.h"
85-
#include "qgsalgorithmsnapgeometries.h"
8685
#include "qgsalgorithmsnaptogrid.h"
8786
#include "qgsalgorithmsplitwithlines.h"
8887
#include "qgsalgorithmstringconcatenation.h"
@@ -213,7 +212,6 @@ void QgsNativeAlgorithms::loadAlgorithms()
213212
addAlgorithm( new QgsShortestPathPointToPointAlgorithm() );
214213
addAlgorithm( new QgsSimplifyAlgorithm() );
215214
addAlgorithm( new QgsSmoothAlgorithm() );
216-
addAlgorithm( new QgsSnapGeometriesAlgorithm() );
217215
addAlgorithm( new QgsSnapToGridAlgorithm() );
218216
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
219217
addAlgorithm( new QgsStringConcatenationAlgorithm() );

‎src/analysis/processing/qgsalgorithmsnapgeometries.cpp renamed to ‎src/analysis/vector/qgsgeometrysnappersinglesource.cpp

Lines changed: 10 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/***************************************************************************
2-
qgsalgorithmsnapgeometries.cpp
2+
qgsgeometrysnappersinglesource.cpp
33
---------------------
44
Date : May 2018
55
Copyright : (C) 2018 by Martin Dobias
@@ -13,81 +13,17 @@
1313
* *
1414
***************************************************************************/
1515

16-
#include "qgsalgorithmsnapgeometries.h"
16+
#include "qgsgeometrysnappersinglesource.h"
1717

18+
#include "qgsfeatureiterator.h"
19+
#include "qgsfeaturesink.h"
20+
#include "qgsfeaturesource.h"
21+
#include "qgsfeedback.h"
1822
#include "qgsgeometrycollection.h"
1923
#include "qgsgeometryutils.h"
2024
#include "qgslinestring.h"
2125
#include "qgspolygon.h"
22-
23-
///@cond PRIVATE
24-
25-
QString QgsSnapGeometriesAlgorithm::name() const
26-
{
27-
return QStringLiteral( "snap" );
28-
}
29-
30-
QString QgsSnapGeometriesAlgorithm::displayName() const
31-
{
32-
return QObject::tr( "Snap geometries" );
33-
}
34-
35-
QString QgsSnapGeometriesAlgorithm::group() const
36-
{
37-
return QObject::tr( "Vector geometry" );
38-
}
39-
40-
QString QgsSnapGeometriesAlgorithm::groupId() const
41-
{
42-
return QStringLiteral( "vectorgeometry" );
43-
}
44-
45-
QString QgsSnapGeometriesAlgorithm::shortHelpString() const
46-
{
47-
return QObject::tr( "Makes sure that any two vertices of the vector layer are at least at distance given by the threshold value. "
48-
"The algorithm moves nearby vertices to one location and adds vertices to segments that are passing around other "
49-
"vertices within the threshold. It does not remove any vertices. Also, it does not modify geometries unless "
50-
"needed (it does not snap coordinates to a grid).\n\n"
51-
"This algorithm comes handy when doing vector overlay operations such as intersection, union or difference "
52-
"to prevent possible topological errors caused by numerical errors if coordinates are very close to each other.\n\n"
53-
"After running the algorithm some previously valid geometries may become invalid and therefore it may be useful "
54-
"to run Fix geometries algorithm afterwards." );
55-
}
56-
57-
QgsProcessingAlgorithm *QgsSnapGeometriesAlgorithm::createInstance() const
58-
{
59-
return new QgsSnapGeometriesAlgorithm();
60-
}
61-
62-
void QgsSnapGeometriesAlgorithm::initAlgorithm( const QVariantMap & )
63-
{
64-
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
65-
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "THRESHOLD" ), QObject::tr( "Threshold" ), QgsProcessingParameterNumber::Double, 0.01 ) );
66-
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Output layer" ) ) );
67-
}
68-
69-
QVariantMap QgsSnapGeometriesAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
70-
{
71-
std::unique_ptr< QgsFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
72-
if ( !source )
73-
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
74-
75-
double thresh = parameterAsDouble( parameters, QStringLiteral( "THRESHOLD" ), context );
76-
77-
QString dest;
78-
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, source->fields(), source->wkbType(), source->sourceCrs() ) );
79-
if ( !sink )
80-
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
81-
82-
QVariantMap outputs;
83-
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
84-
85-
// now go and snap vertices of geometries of source together
86-
run( *source.get(), *sink.get(), thresh, feedback );
87-
88-
return outputs;
89-
}
90-
26+
#include "qgsspatialindex.h"
9127

9228
//! record about vertex coordinates and index of anchor to which it is snapped
9329
typedef struct
@@ -113,7 +49,7 @@ typedef struct
11349
} AnchorAlongSegment;
11450

11551

116-
static void buildSnapIndex( QgsFeatureIterator &fi, QgsSpatialIndex &index, QVector<AnchorPoint> &pnts, QgsProcessingFeedback *feedback, int &count, int totalCount )
52+
static void buildSnapIndex( QgsFeatureIterator &fi, QgsSpatialIndex &index, QVector<AnchorPoint> &pnts, QgsFeedback *feedback, int &count, int totalCount )
11753
{
11854
QgsFeature f;
11955
int pntId = 0;
@@ -362,7 +298,7 @@ static bool snapGeometry( QgsAbstractGeometry *g, QgsSpatialIndex &index, QVecto
362298
}
363299

364300

365-
void QgsSnapGeometriesAlgorithm::run( const QgsFeatureSource &source, QgsFeatureSink &sink, double thresh, QgsProcessingFeedback *feedback )
301+
int QgsGeometrySnapperSingleSource::run(const QgsFeatureSource &source, QgsFeatureSink &sink, double thresh, QgsFeedback *feedback)
366302
{
367303
// the logic here comes from GRASS implementation of Vect_snap_lines_list()
368304

@@ -405,7 +341,5 @@ void QgsSnapGeometriesAlgorithm::run( const QgsFeatureSource &source, QgsFeature
405341
feedback->setProgress( 100. * count / totalCount );
406342
}
407343

408-
feedback->pushInfo( QObject::tr( "Snapped %1 geometries." ).arg( modified ) );
344+
return modified;
409345
}
410-
411-
///@endcond PRIVATE
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/***************************************************************************
2+
qgsgeometrysnappersinglesource.h
3+
---------------------
4+
Date : May 2018
5+
Copyright : (C) 2018 by Martin Dobias
6+
Email : wonder dot sk at gmail dot com
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+
16+
#ifndef QGSGEOMETRYSNAPPERSINGLESOURCE_H
17+
#define QGSGEOMETRYSNAPPERSINGLESOURCE_H
18+
19+
#include "qgis_analysis.h"
20+
21+
class QgsFeatureSink;
22+
class QgsFeatureSource;
23+
class QgsFeedback;
24+
25+
/**
26+
* \ingroup analysis
27+
*
28+
* Makes sure that any two vertices of the vector layer are at least at distance given by the threshold value.
29+
* The algorithm moves nearby vertices to one location and adds vertices to segments that are passing around other
30+
* vertices within the threshold. It does not remove any vertices. Also, it does not modify geometries unless
31+
* needed (it does not snap coordinates to a grid).
32+
*
33+
* This algorithm comes handy when doing vector overlay operations such as intersection, union or difference
34+
* to prevent possible topological errors caused by numerical errors if coordinates are very close to each other.
35+
*
36+
* After running the algorithm some previously valid geometries may become invalid and therefore it may be useful
37+
* to run Fix geometries algorithm afterwards.
38+
*
39+
* \note Originally ported from GRASS implementation of Vect_snap_lines_list()
40+
*
41+
* \since QGIS 3.4
42+
*/
43+
class ANALYSIS_EXPORT QgsGeometrySnapperSingleSource
44+
{
45+
public:
46+
47+
/**
48+
* Run the algorithm on given source and output results to the sink, using threshold value in the source's map units.
49+
* Returns number of modified geometries.
50+
*/
51+
static int run( const QgsFeatureSource &source, QgsFeatureSink &sink, double thresh, QgsFeedback *feedback );
52+
};
53+
54+
#endif // QGSGEOMETRYSNAPPERSINGLESOURCE_H

0 commit comments

Comments
 (0)
Please sign in to comment.