31
31
QgsGeometry ,
32
32
QgsPointXY ,
33
33
QgsWkbTypes ,
34
- QgsApplication ,
35
- QgsProcessingUtils )
34
+ QgsFeatureRequest ,
35
+ QgsProcessing ,
36
+ QgsProcessingParameterFeatureSource ,
37
+ QgsProcessingParameterField ,
38
+ QgsProcessingParameterFeatureSink ,
39
+ QgsProcessingException ,
40
+ QgsExpression )
36
41
from processing .algs .qgis .QgisAlgorithm import QgisAlgorithm
37
- from processing .core .GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
38
- from processing .core .parameters import ParameterVector
39
- from processing .core .parameters import ParameterTableField
40
- from processing .core .outputs import OutputVector
41
-
42
- from processing .tools import dataobjects
42
+ from processing .tools import vector
43
43
44
44
45
45
class HubLines (QgisAlgorithm ):
@@ -55,17 +55,21 @@ def group(self):
55
55
def __init__ (self ):
56
56
super ().__init__ ()
57
57
58
+ def tags (self ):
59
+ return self .tr ('join,points,lines,connect,hub,spoke' ).split (',' )
60
+
58
61
def initAlgorithm (self , config = None ):
59
- self .addParameter (ParameterVector (self .HUBS ,
60
- self .tr ('Hub layer' )))
61
- self .addParameter (ParameterTableField (self .HUB_FIELD ,
62
- self .tr ('Hub ID field' ), self .HUBS ))
63
- self .addParameter (ParameterVector (self .SPOKES ,
64
- self .tr ('Spoke layer' )))
65
- self .addParameter (ParameterTableField (self .SPOKE_FIELD ,
66
- self .tr ('Spoke ID field' ), self .SPOKES ))
67
62
68
- self .addOutput (OutputVector (self .OUTPUT , self .tr ('Hub lines' ), datatype = [dataobjects .TYPE_VECTOR_LINE ]))
63
+ self .addParameter (QgsProcessingParameterFeatureSource (self .HUBS ,
64
+ self .tr ('Hub layer' )))
65
+ self .addParameter (QgsProcessingParameterField (self .HUB_FIELD ,
66
+ self .tr ('Hub ID field' ), parentLayerParameterName = self .HUBS ))
67
+ self .addParameter (QgsProcessingParameterFeatureSource (self .SPOKES ,
68
+ self .tr ('Spoke layer' )))
69
+ self .addParameter (QgsProcessingParameterField (self .SPOKE_FIELD ,
70
+ self .tr ('Spoke ID field' ), parentLayerParameterName = self .SPOKES ))
71
+
72
+ self .addParameter (QgsProcessingParameterFeatureSink (self .OUTPUT , self .tr ('Hub lines' ), QgsProcessing .TypeVectorLine ))
69
73
70
74
def name (self ):
71
75
return 'hublines'
@@ -74,44 +78,61 @@ def displayName(self):
74
78
return self .tr ('Hub lines' )
75
79
76
80
def processAlgorithm (self , parameters , context , feedback ):
77
- layerHub = QgsProcessingUtils .mapLayerFromString (self .getParameterValue (self .HUBS ), context )
78
- layerSpoke = QgsProcessingUtils .mapLayerFromString (self .getParameterValue (self .SPOKES ), context )
81
+ if parameters [self .SPOKES ] == parameters [self .HUBS ]:
82
+ raise QgsProcessingException (
83
+ self .tr ('Same layer given for both hubs and spokes' ))
79
84
80
- fieldHub = self .getParameterValue (self .HUB_FIELD )
81
- fieldSpoke = self .getParameterValue (self .SPOKE_FIELD )
85
+ hub_source = self .parameterAsSource (parameters , self .HUBS , context )
86
+ spoke_source = self .parameterAsSource (parameters , self .SPOKES , context )
87
+ field_hub = self .parameterAsString (parameters , self .HUB_FIELD , context )
88
+ field_hub_index = hub_source .fields ().lookupField (field_hub )
89
+ field_spoke = self .parameterAsString (parameters , self .SPOKE_FIELD , context )
90
+ field_spoke_index = hub_source .fields ().lookupField (field_spoke )
82
91
83
- if layerHub .source () == layerSpoke .source ():
84
- raise GeoAlgorithmExecutionException (
85
- self .tr ('Same layer given for both hubs and spokes' ))
92
+ fields = vector .combineFields (hub_source .fields (), spoke_source .fields ())
86
93
87
- writer = self .getOutputFromName ( self .OUTPUT ). getVectorWriter ( layerSpoke . fields (), QgsWkbTypes . LineString ,
88
- layerSpoke . crs (), context )
94
+ ( sink , dest_id ) = self .parameterAsSink ( parameters , self .OUTPUT , context ,
95
+ fields , QgsWkbTypes . LineString , hub_source . sourceCrs () )
89
96
90
- spokes = QgsProcessingUtils .getFeatures (layerSpoke , context )
91
- hubs = QgsProcessingUtils .getFeatures (layerHub , context )
92
- total = 100.0 / layerSpoke .featureCount () if layerSpoke .featureCount () else 0
97
+ hubs = hub_source .getFeatures ()
98
+ total = 100.0 / hub_source .featureCount () if hub_source .featureCount () else 0
93
99
94
- for current , spokepoint in enumerate (spokes ):
95
- p = spokepoint .geometry ().boundingBox ().center ()
96
- spokeX = p .x ()
97
- spokeY = p .y ()
98
- spokeId = str (spokepoint [fieldSpoke ])
100
+ matching_field_types = hub_source .fields ().at (field_hub_index ).type () == spoke_source .fields ().at (field_spoke_index ).type ()
99
101
100
- for hubpoint in hubs :
101
- hubId = str (hubpoint [fieldHub ])
102
- if hubId == spokeId :
103
- p = hubpoint .geometry ().boundingBox ().center ()
104
- hubX = p .x ()
105
- hubY = p .y ()
102
+ for current , hub_point in enumerate (hubs ):
103
+ if feedback .isCanceled ():
104
+ break
106
105
107
- f = QgsFeature ()
108
- f .setAttributes (spokepoint .attributes ())
109
- f .setGeometry (QgsGeometry .fromPolyline (
110
- [QgsPointXY (spokeX , spokeY ), QgsPointXY (hubX , hubY )]))
111
- writer .addFeature (f , QgsFeatureSink .FastInsert )
106
+ if not hub_point .hasGeometry ():
107
+ continue
112
108
109
+ p = hub_point .geometry ().boundingBox ().center ()
110
+ hub_x = p .x ()
111
+ hub_y = p .y ()
112
+ hub_id = str (hub_point [field_hub ])
113
+ hub_attributes = hub_point .attributes ()
114
+
115
+ request = QgsFeatureRequest ().setDestinationCrs (hub_source .sourceCrs ())
116
+ if matching_field_types :
117
+ request .setFilterExpression (QgsExpression .createFieldEqualityExpression (field_spoke , hub_attributes [field_hub_index ]))
118
+
119
+ spokes = spoke_source .getFeatures ()
120
+ for spoke_point in spokes :
121
+ if feedback .isCanceled ():
113
122
break
114
123
124
+ spoke_id = str (spoke_point [field_spoke ])
125
+ if hub_id == spoke_id :
126
+ p = spoke_point .geometry ().boundingBox ().center ()
127
+ spoke_x = p .x ()
128
+ spoke_y = p .y ()
129
+
130
+ f = QgsFeature ()
131
+ f .setAttributes (hub_attributes + spoke_point .attributes ())
132
+ f .setGeometry (QgsGeometry .fromPolyline (
133
+ [QgsPointXY (hub_x , hub_y ), QgsPointXY (spoke_x , spoke_y )]))
134
+ sink .addFeature (f , QgsFeatureSink .FastInsert )
135
+
115
136
feedback .setProgress (int (current * total ))
116
137
117
- del writer
138
+ return { self . OUTPUT : dest_id }
0 commit comments