-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE][processing] Snap geometries to layer algorithm
Port the Geometry Snapper plugin across to the analysis lib, and expose to python bindings Add a new algorithm which performs the snapping to layers
- Loading branch information
1 parent
b4bca5b
commit c3a978b
Showing
17 changed files
with
1,271 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* \class QgsGeometrySnapper | ||
* \ingroup analysis | ||
* QgsGeometrySnapper allows a geometry to be snapped to the geometries within a | ||
* different refence layer. Vertices in the geometries will be modified to | ||
* match the reference layer features within a specified snap tolerance. | ||
* \note added in QGIS 3.0 | ||
*/ | ||
|
||
class QgsGeometrySnapper : QObject | ||
{ | ||
%TypeHeaderCode | ||
#include <qgsgeometrysnapper.h> | ||
%End | ||
|
||
public: | ||
|
||
/** | ||
* Constructor for QgsGeometrySnapper. A reference layer which contains geometries to snap to must be | ||
* set. The snap tolerance is specified in the layer units for the | ||
* reference layer, and it is assumed that all geometries snapped using this object will have the | ||
* same CRS as the reference layer (ie, no reprojection is performed). | ||
*/ | ||
QgsGeometrySnapper( QgsVectorLayer* referenceLayer, double snapTolerance ); | ||
|
||
/** | ||
* Snaps a geometry to the reference layer and returns the result. The geometry must be in the same | ||
* CRS as the reference layer. | ||
*/ | ||
QgsGeometry snapGeometry( const QgsGeometry& geometry ) const; | ||
|
||
/** | ||
* Snaps a set of features to the reference layer and returns the result. This operation is | ||
* multithreaded for performance. The featureSnapped() signal will be emitted each time a feature | ||
* is processed. This method is not safe to call from multiple threads concurrently. | ||
*/ | ||
QgsFeatureList snapFeatures( const QgsFeatureList& features ); | ||
|
||
signals: | ||
|
||
//! Emitted each time a feature has been processed when calling snapFeatures() | ||
void featureSnapped(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
""" | ||
*************************************************************************** | ||
SnapGeometries.py | ||
----------------- | ||
Date : October 2016 | ||
Copyright : (C) 2016 by Nyall Dawson | ||
Email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
*************************************************************************** | ||
""" | ||
from builtins import str | ||
|
||
__author__ = 'Nyall Dawson' | ||
__date__ = 'October 2016' | ||
__copyright__ = '(C) 2016, Nyall Dawson' | ||
|
||
# This will get replaced with a git SHA1 when you do a git archive | ||
|
||
__revision__ = '$Format:%H$' | ||
|
||
from qgis.analysis import QgsGeometrySnapper | ||
from qgis.core import QgsFeature | ||
|
||
from processing.core.GeoAlgorithm import GeoAlgorithm | ||
from processing.core.parameters import ParameterVector, ParameterNumber | ||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException | ||
from processing.core.outputs import OutputVector | ||
from processing.tools import dataobjects, vector | ||
|
||
|
||
class SnapGeometriesToLayer(GeoAlgorithm): | ||
|
||
INPUT = 'INPUT' | ||
REFERENCE_LAYER = 'REFERENCE_LAYER' | ||
TOLERANCE = 'TOLERANCE' | ||
OUTPUT = 'OUTPUT' | ||
|
||
def defineCharacteristics(self): | ||
self.name, self.i18n_name = self.trAlgorithm('Snap geometries to layer') | ||
self.group, self.i18n_group = self.trAlgorithm('Vector geometry tools') | ||
|
||
self.addParameter(ParameterVector(self.INPUT, self.tr('Input layer'))) | ||
self.addParameter(ParameterVector(self.REFERENCE_LAYER, self.tr('Reference layer'))) | ||
self.addParameter(ParameterNumber(self.TOLERANCE, self.tr('Tolerance (layer units)'), 0.00000001, 9999999999, default=10.0)) | ||
self.addOutput(OutputVector(self.OUTPUT, self.tr('Snapped geometries'))) | ||
|
||
def processAlgorithm(self, progress): | ||
layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) | ||
reference_layer = dataobjects.getObjectFromUri(self.getParameterValue(self.REFERENCE_LAYER)) | ||
tolerance = self.getParameterValue(self.TOLERANCE) | ||
|
||
if not layer.geometryType() == reference_layer.geometryType(): | ||
raise GeoAlgorithmExecutionException( | ||
self.tr('Input layer and reference layer must have the same geometry type (eg both are line layers)')) | ||
|
||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( | ||
layer.fields(), layer.wkbType(), layer.crs()) | ||
|
||
features = vector.features(layer) | ||
|
||
self.processed = 0 | ||
self.progress = progress | ||
self.total = 100.0 / len(features) | ||
|
||
snapper = QgsGeometrySnapper(reference_layer, tolerance) | ||
snapper.featureSnapped.connect(self.featureSnapped) | ||
snapped_features = snapper.snapFeatures(features) | ||
for f in snapped_features: | ||
writer.addFeature(QgsFeature(f)) | ||
|
||
del writer | ||
|
||
def featureSnapped(self): | ||
self.processed += 1 | ||
self.progress.setPercentage(int(self.processed * self.total)) |
14 changes: 14 additions & 0 deletions
14
python/plugins/processing/tests/testdata/expected/snap_lines_to_lines.gfs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<GMLFeatureClassList> | ||
<GMLFeatureClass> | ||
<Name>snap_lines_to_lines</Name> | ||
<ElementPath>snap_lines_to_lines</ElementPath> | ||
<SRSName>EPSG:4326</SRSName> | ||
<DatasetSpecificInfo> | ||
<FeatureCount>7</FeatureCount> | ||
<ExtentXMin>-1.00000</ExtentXMin> | ||
<ExtentXMax>11.34679</ExtentXMax> | ||
<ExtentYMin>-5.00000</ExtentYMin> | ||
<ExtentYMax>5.28899</ExtentYMax> | ||
</DatasetSpecificInfo> | ||
</GMLFeatureClass> | ||
</GMLFeatureClassList> |
48 changes: 48 additions & 0 deletions
48
python/plugins/processing/tests/testdata/expected/snap_lines_to_lines.gml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<ogr:FeatureCollection | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="" | ||
xmlns:ogr="http://ogr.maptools.org/" | ||
xmlns:gml="http://www.opengis.net/gml"> | ||
<gml:boundedBy> | ||
<gml:Box> | ||
<gml:coord><gml:X>-1</gml:X><gml:Y>-5</gml:Y></gml:coord> | ||
<gml:coord><gml:X>11.34678899082569</gml:X><gml:Y>5.288990825688074</gml:Y></gml:coord> | ||
</gml:Box> | ||
</gml:boundedBy> | ||
|
||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.0"> | ||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 9,2 9,3 11,5 11.346788990825686,5.288990825688074</gml:coordinates></gml:LineString></ogr:geometryProperty> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.1"> | ||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.2"> | ||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 2,2 3,2 3,2</gml:coordinates></gml:LineString></ogr:geometryProperty> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.3"> | ||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,-3 3,-5</gml:coordinates></gml:LineString></ogr:geometryProperty> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.4"> | ||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.5"> | ||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1 10.208073394495411,0.849724770642202</gml:coordinates></gml:LineString></ogr:geometryProperty> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_lines_to_lines fid="lines.6"> | ||
</ogr:snap_lines_to_lines> | ||
</gml:featureMember> | ||
</ogr:FeatureCollection> |
32 changes: 32 additions & 0 deletions
32
python/plugins/processing/tests/testdata/expected/snap_polys_to_polys.gfs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<GMLFeatureClassList> | ||
<GMLFeatureClass> | ||
<Name>snap_polys_to_polys</Name> | ||
<ElementPath>snap_polys_to_polys</ElementPath> | ||
<!--POLYGON--> | ||
<GeometryType>3</GeometryType> | ||
<SRSName>EPSG:4326</SRSName> | ||
<DatasetSpecificInfo> | ||
<FeatureCount>4</FeatureCount> | ||
<ExtentXMin>-1.00000</ExtentXMin> | ||
<ExtentXMax>10.00000</ExtentXMax> | ||
<ExtentYMin>-3.00000</ExtentYMin> | ||
<ExtentYMax>5.00000</ExtentYMax> | ||
</DatasetSpecificInfo> | ||
<PropertyDefn> | ||
<Name>name</Name> | ||
<ElementPath>name</ElementPath> | ||
<Type>String</Type> | ||
<Width>5</Width> | ||
</PropertyDefn> | ||
<PropertyDefn> | ||
<Name>intval</Name> | ||
<ElementPath>intval</ElementPath> | ||
<Type>Integer</Type> | ||
</PropertyDefn> | ||
<PropertyDefn> | ||
<Name>floatval</Name> | ||
<ElementPath>floatval</ElementPath> | ||
<Type>Real</Type> | ||
</PropertyDefn> | ||
</GMLFeatureClass> | ||
</GMLFeatureClassList> |
43 changes: 43 additions & 0 deletions
43
python/plugins/processing/tests/testdata/expected/snap_polys_to_polys.gml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<ogr:FeatureCollection | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="" | ||
xmlns:ogr="http://ogr.maptools.org/" | ||
xmlns:gml="http://www.opengis.net/gml"> | ||
<gml:boundedBy> | ||
<gml:Box> | ||
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord> | ||
<gml:coord><gml:X>10</gml:X><gml:Y>5</gml:Y></gml:coord> | ||
</gml:Box> | ||
</gml:boundedBy> | ||
|
||
<gml:featureMember> | ||
<ogr:snap_polys_to_polys fid="polys.0"> | ||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty> | ||
<ogr:name>aaaaa</ogr:name> | ||
<ogr:intval>33</ogr:intval> | ||
<ogr:floatval>44.123456</ogr:floatval> | ||
</ogr:snap_polys_to_polys> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_polys_to_polys fid="polys.1"> | ||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty> | ||
<ogr:name>Aaaaa</ogr:name> | ||
<ogr:intval>-33</ogr:intval> | ||
<ogr:floatval>0</ogr:floatval> | ||
</ogr:snap_polys_to_polys> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_polys_to_polys fid="polys.3"> | ||
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7,0 7,-2 9,0 7,0</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty> | ||
<ogr:name>ASDF</ogr:name> | ||
<ogr:intval>0</ogr:intval> | ||
</ogr:snap_polys_to_polys> | ||
</gml:featureMember> | ||
<gml:featureMember> | ||
<ogr:snap_polys_to_polys fid="polys.4"> | ||
<ogr:intval>120</ogr:intval> | ||
<ogr:floatval>-100291.43213</ogr:floatval> | ||
</ogr:snap_polys_to_polys> | ||
</gml:featureMember> | ||
</ogr:FeatureCollection> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<GMLFeatureClassList> | ||
<GMLFeatureClass> | ||
<Name>snap_lines</Name> | ||
<ElementPath>snap_lines</ElementPath> | ||
<!--LINESTRING--> | ||
<GeometryType>2</GeometryType> | ||
<SRSName>EPSG:4326</SRSName> | ||
<DatasetSpecificInfo> | ||
<FeatureCount>7</FeatureCount> | ||
<ExtentXMin>-1.00000</ExtentXMin> | ||
<ExtentXMax>11.34679</ExtentXMax> | ||
<ExtentYMin>-5.00000</ExtentYMin> | ||
<ExtentYMax>5.28899</ExtentYMax> | ||
</DatasetSpecificInfo> | ||
</GMLFeatureClass> | ||
</GMLFeatureClassList> |
Oops, something went wrong.