28
28
import os
29
29
30
30
from qgis .PyQt .QtGui import QIcon
31
-
32
- from qgis .core import QgsFeature , QgsFeatureSink , QgsGeometry , QgsFeatureRequest , QgsDistanceArea , QgsProcessingUtils
31
+ from qgis .PyQt .QtCore import QVariant
32
+ from qgis .core import (QgsFeature ,
33
+ QgsFeatureSink ,
34
+ QgsField ,
35
+ QgsGeometry ,
36
+ QgsFeatureRequest ,
37
+ QgsDistanceArea ,
38
+ QgsProcessing ,
39
+ QgsProcessingParameterString ,
40
+ QgsProcessingParameterFeatureSource ,
41
+ QgsProcessingParameterFeatureSink ,
42
+ QgsSpatialIndex )
33
43
34
44
from processing .algs .qgis .QgisAlgorithm import QgisAlgorithm
35
- from processing .core .parameters import ParameterVector
36
- from processing .core .parameters import ParameterString
37
- from processing .core .outputs import OutputVector
38
- from processing .tools import dataobjects , vector
39
45
40
46
pluginPath = os .path .split (os .path .split (os .path .dirname (__file__ ))[0 ])[0 ]
41
47
@@ -58,16 +64,16 @@ def __init__(self):
58
64
super ().__init__ ()
59
65
60
66
def initAlgorithm (self , config = None ):
61
- self .addParameter (ParameterVector (self .LINES ,
62
- self .tr ('Lines' ), [dataobjects . TYPE_VECTOR_LINE ]))
63
- self .addParameter (ParameterVector (self .POLYGONS ,
64
- self .tr ('Polygons' ), [dataobjects . TYPE_VECTOR_POLYGON ]))
65
- self .addParameter (ParameterString (self .LEN_FIELD ,
66
- self .tr ('Lines length field name' , 'LENGTH' ) ))
67
- self .addParameter (ParameterString (self .COUNT_FIELD ,
68
- self .tr ('Lines count field name' , 'COUNT' ) ))
67
+ self .addParameter (QgsProcessingParameterFeatureSource (self .LINES ,
68
+ self .tr ('Lines' ), [QgsProcessing . TypeVectorLine ]))
69
+ self .addParameter (QgsProcessingParameterFeatureSource (self .POLYGONS ,
70
+ self .tr ('Polygons' ), [QgsProcessing . TypeVectorPolygon ]))
71
+ self .addParameter (QgsProcessingParameterString (self .LEN_FIELD ,
72
+ self .tr ('Lines length field name' ), defaultValue = 'LENGTH' ))
73
+ self .addParameter (QgsProcessingParameterString (self .COUNT_FIELD ,
74
+ self .tr ('Lines count field name' ), defaultValue = 'COUNT' ))
69
75
70
- self .addOutput ( OutputVector (self .OUTPUT , self .tr ('Line length' ), datatype = [ dataobjects . TYPE_VECTOR_POLYGON ] ))
76
+ self .addParameter ( QgsProcessingParameterFeatureSink (self .OUTPUT , self .tr ('Line length' ), QgsProcessing . TypeVectorPolygon ))
71
77
72
78
def name (self ):
73
79
return 'sumlinelengths'
@@ -76,66 +82,73 @@ def displayName(self):
76
82
return self .tr ('Sum line lengths' )
77
83
78
84
def processAlgorithm (self , parameters , context , feedback ):
79
- lineLayer = QgsProcessingUtils . mapLayerFromString ( self .getParameterValue ( self .LINES ) , context )
80
- polyLayer = QgsProcessingUtils . mapLayerFromString ( self .getParameterValue ( self .POLYGONS ) , context )
81
- lengthFieldName = self . getParameterValue ( self . LEN_FIELD )
82
- countFieldName = self .getParameterValue ( self .COUNT_FIELD )
83
-
84
- ( idxLength , fieldList ) = vector . findOrCreateField ( polyLayer ,
85
- polyLayer .fields (), lengthFieldName )
86
- ( idxCount , fieldList ) = vector . findOrCreateField ( polyLayer , fieldList ,
87
- countFieldName )
88
-
89
- writer = self . getOutputFromName ( self . OUTPUT ). getVectorWriter ( fieldList , polyLayer . wkbType (),
90
- polyLayer . crs (), context )
91
-
92
- spatialIndex = QgsProcessingUtils . createSpatialIndex ( lineLayer , context )
93
-
94
- ftLine = QgsFeature ( )
95
- ftPoly = QgsFeature ()
96
- outFeat = QgsFeature ()
97
- inGeom = QgsGeometry ( )
98
- outGeom = QgsGeometry ()
85
+ line_source = self .parameterAsSource ( parameters , self .LINES , context )
86
+ poly_source = self .parameterAsSource ( parameters , self .POLYGONS , context )
87
+
88
+ length_field_name = self .parameterAsString ( parameters , self .LEN_FIELD , context )
89
+ count_field_name = self . parameterAsString ( parameters , self . COUNT_FIELD , context )
90
+
91
+ fields = poly_source .fields ()
92
+ if fields . lookupField ( length_field_name ) < 0 :
93
+ fields . append ( QgsField ( length_field_name , QVariant . Double ) )
94
+ length_field_index = fields . lookupField ( length_field_name )
95
+ if fields . lookupField ( count_field_name ) < 0 :
96
+ fields . append ( QgsField ( count_field_name , QVariant . Int ) )
97
+ count_field_index = fields . lookupField ( count_field_name )
98
+
99
+ ( sink , dest_id ) = self . parameterAsSink ( parameters , self . OUTPUT , context ,
100
+ fields , poly_source . wkbType (), poly_source . sourceCrs () )
101
+
102
+ spatialIndex = QgsSpatialIndex ( line_source . getFeatures (
103
+ QgsFeatureRequest (). setSubsetOfAttributes ([]). setDestinationCrs ( poly_source . sourceCrs ())) )
104
+
99
105
distArea = QgsDistanceArea ()
100
106
101
- features = QgsProcessingUtils .getFeatures (polyLayer , context )
102
- total = 100.0 / polyLayer .featureCount () if polyLayer .featureCount () else 0
103
- hasIntersections = False
104
- for current , ftPoly in enumerate (features ):
105
- inGeom = ftPoly .geometry ()
106
- attrs = ftPoly .attributes ()
107
+ features = poly_source .getFeatures ()
108
+ total = 100.0 / poly_source .featureCount () if poly_source .featureCount () else 0
109
+ for current , poly_feature in enumerate (features ):
110
+ if feedback .isCanceled ():
111
+ break
112
+
113
+ output_feature = QgsFeature ()
107
114
count = 0
108
115
length = 0
109
- hasIntersections = False
110
- lines = spatialIndex .intersects (inGeom .boundingBox ())
111
- engine = None
112
- if len (lines ) > 0 :
113
- hasIntersections = True
114
- # use prepared geometries for faster intersection tests
115
- engine = QgsGeometry .createGeometryEngine (inGeom .geometry ())
116
- engine .prepareGeometry ()
117
-
118
- if hasIntersections :
119
- request = QgsFeatureRequest ().setFilterFids (lines ).setSubsetOfAttributes ([])
120
- for ftLine in lineLayer .getFeatures (request ):
121
- tmpGeom = ftLine .geometry ()
122
- if engine .intersects (tmpGeom .geometry ()):
123
- outGeom = inGeom .intersection (tmpGeom )
124
- length += distArea .measureLength (outGeom )
125
- count += 1
126
-
127
- outFeat .setGeometry (inGeom )
128
- if idxLength == len (attrs ):
116
+ if poly_feature .hasGeometry ():
117
+ poly_geom = poly_feature .geometry ()
118
+ has_intersections = False
119
+ lines = spatialIndex .intersects (poly_geom .boundingBox ())
120
+ engine = None
121
+ if len (lines ) > 0 :
122
+ has_intersections = True
123
+ # use prepared geometries for faster intersection tests
124
+ engine = QgsGeometry .createGeometryEngine (poly_geom .geometry ())
125
+ engine .prepareGeometry ()
126
+
127
+ if has_intersections :
128
+ request = QgsFeatureRequest ().setFilterFids (lines ).setSubsetOfAttributes ([]).setDestinationCrs (poly_source .sourceCrs ())
129
+ for line_feature in line_source .getFeatures (request ):
130
+ if feedback .isCanceled ():
131
+ break
132
+
133
+ if engine .intersects (line_feature .geometry ().geometry ()):
134
+ outGeom = poly_geom .intersection (line_feature .geometry ())
135
+ length += distArea .measureLength (outGeom )
136
+ count += 1
137
+
138
+ output_feature .setGeometry (poly_geom )
139
+
140
+ attrs = poly_feature .attributes ()
141
+ if length_field_index == len (attrs ):
129
142
attrs .append (length )
130
143
else :
131
- attrs [idxLength ] = length
132
- if idxCount == len (attrs ):
144
+ attrs [length_field_index ] = length
145
+ if count_field_index == len (attrs ):
133
146
attrs .append (count )
134
147
else :
135
- attrs [idxCount ] = count
136
- outFeat .setAttributes (attrs )
137
- writer .addFeature (outFeat , QgsFeatureSink .FastInsert )
148
+ attrs [count_field_index ] = count
149
+ output_feature .setAttributes (attrs )
150
+ sink .addFeature (output_feature , QgsFeatureSink .FastInsert )
138
151
139
152
feedback .setProgress (int (current * total ))
140
153
141
- del writer
154
+ return { self . OUTPUT : dest_id }
0 commit comments