27
27
28
28
from qgis .analysis import (QgsGeometrySnapper ,
29
29
QgsInternalGeometrySnapper )
30
- from qgis .core import (QgsApplication ,
31
- QgsFeature ,
32
- QgsFeatureSink ,
33
- QgsProcessingUtils )
30
+ from qgis .core import (QgsFeatureSink ,
31
+ QgsProcessingParameterDefinition ,
32
+ QgsProcessingParameterFeatureSource ,
33
+ QgsProcessingParameterFeatureSink ,
34
+ QgsProcessingParameterNumber ,
35
+ QgsProcessingParameterEnum ,
36
+ QgsProcessingOutputVectorLayer )
34
37
35
38
from processing .algs .qgis .QgisAlgorithm import QgisAlgorithm
36
- from processing .core .parameters import ParameterVector , ParameterNumber , ParameterSelection
37
- from processing .core .outputs import OutputVector
38
39
39
40
40
41
class SnapGeometriesToLayer (QgisAlgorithm ):
@@ -50,20 +51,28 @@ def group(self):
50
51
51
52
def __init__ (self ):
52
53
super ().__init__ ()
53
- self .addParameter (ParameterVector (self .INPUT , self .tr ('Input layer' )))
54
- self .addParameter (ParameterVector (self .REFERENCE_LAYER , self .tr ('Reference layer' )))
55
- self .addParameter (ParameterNumber (self .TOLERANCE , self .tr ('Tolerance (layer units)' ), 0.00000001 , 9999999999 , default = 10.0 ))
54
+
55
+ self .addParameter (QgsProcessingParameterFeatureSource (self .INPUT , self .tr ('Input layer' ), [QgsProcessingParameterDefinition .TypeVectorPoint , QgsProcessingParameterDefinition .TypeVectorLine , QgsProcessingParameterDefinition .TypeVectorPolygon ]))
56
+ self .addParameter (QgsProcessingParameterFeatureSource (self .REFERENCE_LAYER , self .tr ('Reference layer' ),
57
+ [QgsProcessingParameterDefinition .TypeVectorPoint ,
58
+ QgsProcessingParameterDefinition .TypeVectorLine ,
59
+ QgsProcessingParameterDefinition .TypeVectorPolygon ]))
60
+
61
+ self .addParameter (QgsProcessingParameterNumber (self .TOLERANCE , self .tr ('Tolerance (layer units)' ), type = QgsProcessingParameterNumber .Double ,
62
+ minValue = 0.00000001 , maxValue = 9999999999 , defaultValue = 10.0 ))
56
63
57
64
self .modes = [self .tr ('Prefer aligning nodes' ),
58
65
self .tr ('Prefer closest point' ),
59
66
self .tr ('Move end points only, prefer aligning nodes' ),
60
67
self .tr ('Move end points only, prefer closest point' ),
61
68
self .tr ('Snap end points to end points only' )]
62
- self .addParameter (ParameterSelection (
69
+ self .addParameter (QgsProcessingParameterEnum (
63
70
self .BEHAVIOR ,
64
71
self .tr ('Behavior' ),
65
- self .modes , default = 0 ))
66
- self .addOutput (OutputVector (self .OUTPUT , self .tr ('Snapped geometries' )))
72
+ options = self .modes , defaultValue = 0 ))
73
+
74
+ self .addParameter (QgsProcessingParameterFeatureSink (self .OUTPUT , self .tr ('Snapped geometry' )))
75
+ self .addOutput (QgsProcessingOutputVectorLayer (self .OUTPUT , self .tr ("Snapped geometry" )))
67
76
68
77
def name (self ):
69
78
return 'snapgeometries'
@@ -72,39 +81,44 @@ def displayName(self):
72
81
return self .tr ('Snap geometries to layer' )
73
82
74
83
def processAlgorithm (self , parameters , context , feedback ):
75
- layer = QgsProcessingUtils .mapLayerFromString (self .getParameterValue (self .INPUT ), context )
76
- reference_layer = QgsProcessingUtils .mapLayerFromString (self .getParameterValue (self .REFERENCE_LAYER ), context )
77
- tolerance = self .getParameterValue (self .TOLERANCE )
78
- mode = self .getParameterValue (self .BEHAVIOR )
79
-
80
- writer = self .getOutputFromName (self .OUTPUT ).getVectorWriter (layer .fields (), layer .wkbType (), layer .crs (),
81
- context )
82
-
83
- features = QgsProcessingUtils .getFeatures (layer , context )
84
-
85
- self .processed = 0
86
- self .feedback = feedback
87
- self .total = 100.0 / layer .featureCount () if layer .featureCount () else 0
88
-
89
- if self .getParameterValue (self .INPUT ) != self .getParameterValue (self .REFERENCE_LAYER ):
90
- snapper = QgsGeometrySnapper (reference_layer )
91
- snapper .featureSnapped .connect (self .featureSnapped )
92
- snapped_features = snapper .snapFeatures (features , tolerance , mode )
93
- for f in snapped_features :
94
- writer .addFeature (f , QgsFeatureSink .FastInsert )
84
+ source = self .parameterAsSource (parameters , self .INPUT , context )
85
+
86
+ reference_source = self .parameterAsSource (parameters , self .REFERENCE_LAYER , context )
87
+ tolerance = self .parameterAsDouble (parameters , self .TOLERANCE , context )
88
+ mode = self .parameterAsEnum (parameters , self .BEHAVIOR , context )
89
+
90
+ (sink , dest_id ) = self .parameterAsSink (parameters , self .OUTPUT , context ,
91
+ source .fields (), source .wkbType (), source .sourceCrs ())
92
+
93
+ features = source .getFeatures ()
94
+ total = 100.0 / source .featureCount () if source .featureCount () else 0
95
+
96
+ if parameters [self .INPUT ] != parameters [self .REFERENCE_LAYER ]:
97
+ snapper = QgsGeometrySnapper (reference_source )
98
+ processed = 0
99
+ for f in features :
100
+ if feedback .isCanceled ():
101
+ break
102
+ if f .hasGeometry ():
103
+ out_feature = f
104
+ out_feature .setGeometry (snapper .snapGeometry (f .geometry (), tolerance , mode ))
105
+ sink .addFeature (out_feature , QgsFeatureSink .FastInsert )
106
+ else :
107
+ sink .addFeature (f )
108
+ processed += 1
109
+ feedback .setProgress (processed * total )
95
110
else :
96
111
# snapping internally
97
112
snapper = QgsInternalGeometrySnapper (tolerance , mode )
98
113
processed = 0
99
114
for f in features :
115
+ if feedback .isCanceled ():
116
+ break
117
+
100
118
out_feature = f
101
119
out_feature .setGeometry (snapper .snapFeature (f ))
102
- writer .addFeature (out_feature , QgsFeatureSink .FastInsert )
120
+ sink .addFeature (out_feature , QgsFeatureSink .FastInsert )
103
121
processed += 1
104
- feedback .setProgress (processed * self .total )
105
-
106
- del writer
122
+ feedback .setProgress (processed * total )
107
123
108
- def featureSnapped (self ):
109
- self .processed += 1
110
- self .feedback .setProgress (int (self .processed * self .total ))
124
+ return {self .OUTPUT : dest_id }
0 commit comments