@@ -71,23 +71,28 @@ void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool u
71
71
// apply selection rectangle
72
72
resetSelection ( 0 );
73
73
74
+ BOUND_BOX box;
75
+ box.N = rect.yMaximum (); box.S = rect.yMinimum ();
76
+ box.E = rect.xMaximum (); box.W = rect.xMinimum ();
77
+ box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX;
78
+
74
79
if ( !useIntersect )
75
80
{ // select by bounding boxes only
76
- BOUND_BOX box;
77
- box.N = rect.yMaximum (); box.S = rect.yMinimum ();
78
- box.E = rect.xMaximum (); box.W = rect.xMinimum ();
79
- box.T = PORT_DOUBLE_MAX; box.B = -PORT_DOUBLE_MAX;
80
81
if ( P->mLayerType == QgsGrassProvider::POINT || P->mLayerType == QgsGrassProvider::CENTROID ||
81
82
P->mLayerType == QgsGrassProvider::LINE || P->mLayerType == QgsGrassProvider::FACE ||
82
- P->mLayerType == QgsGrassProvider::BOUNDARY )
83
+ P->mLayerType == QgsGrassProvider::BOUNDARY ||
84
+ P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
83
85
{
84
86
Vect_select_lines_by_box ( P->mMap , &box, P->mGrassType , mList );
85
87
}
86
88
else if ( P->mLayerType == QgsGrassProvider::POLYGON )
87
89
{
88
90
Vect_select_areas_by_box ( P->mMap , &box, mList );
89
91
}
90
-
92
+ else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
93
+ {
94
+ Vect_select_nodes_by_box ( P->mMap , &box, mList );
95
+ }
91
96
}
92
97
else
93
98
{ // check intersection
@@ -106,14 +111,20 @@ void QgsGrassFeatureIterator::setSelectionRect( const QgsRectangle& rect, bool u
106
111
107
112
if ( P->mLayerType == QgsGrassProvider::POINT || P->mLayerType == QgsGrassProvider::CENTROID ||
108
113
P->mLayerType == QgsGrassProvider::LINE || P->mLayerType == QgsGrassProvider::FACE ||
109
- P->mLayerType == QgsGrassProvider::BOUNDARY )
114
+ P->mLayerType == QgsGrassProvider::BOUNDARY ||
115
+ P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
110
116
{
111
117
Vect_select_lines_by_polygon ( P->mMap , Polygon, 0 , NULL , P->mGrassType , mList );
112
118
}
113
119
else if ( P->mLayerType == QgsGrassProvider::POLYGON )
114
120
{
115
121
Vect_select_areas_by_polygon ( P->mMap , Polygon, 0 , NULL , mList );
116
122
}
123
+ else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
124
+ {
125
+ // There is no Vect_select_nodes_by_polygon but for nodes it is the same as by box
126
+ Vect_select_nodes_by_box ( P->mMap , &box, mList );
127
+ }
117
128
118
129
Vect_destroy_line_struct ( Polygon );
119
130
}
@@ -153,7 +164,8 @@ bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature )
153
164
return false ;
154
165
}
155
166
156
- if ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats )
167
+ // TODO: is this necessary? the same is checked below
168
+ if ( !P->isTopoType () && ( P->mCidxFieldIndex < 0 || mNextCidx >= P->mCidxFieldNumCats ) )
157
169
{
158
170
close ();
159
171
return false ; // No features, no features in this layer
@@ -163,17 +175,39 @@ bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature )
163
175
164
176
// Get next line/area id
165
177
int found = 0 ;
166
- while ( mNextCidx < P-> mCidxFieldNumCats )
178
+ while ( true )
167
179
{
168
- Vect_cidx_get_cat_by_index ( P->mMap , P->mCidxFieldIndex , mNextCidx ++, &cat, &type, &id );
169
- // Warning: selection array is only of type line/area of current layer -> check type first
170
- if ( !( type & P->mGrassType ) )
171
- continue ;
180
+ QgsDebugMsgLevel ( QString ( " mNextTopoId = %1" ).arg ( mNextTopoId ), 3 );
181
+ if ( P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
182
+ {
183
+ if ( mNextTopoId > Vect_get_num_lines ( P->mMap ) ) break ;
184
+ id = mNextTopoId ;
185
+ type = Vect_read_line ( P->mMap , 0 , 0 , mNextTopoId ++ );
186
+ if ( !( type & P->mGrassType ) ) continue ;
187
+ featureId = id;
188
+ }
189
+ else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
190
+ {
191
+ if ( mNextTopoId > Vect_get_num_nodes ( P->mMap ) ) break ;
192
+ id = mNextTopoId ;
193
+ type = 0 ;
194
+ mNextTopoId ++;
195
+ featureId = id;
196
+ }
197
+ else
198
+ {
199
+ if ( mNextCidx >= P->mCidxFieldNumCats ) break ;
172
200
173
- // The 'id' is a unique id of a GRASS geometry object (point, line, area)
174
- // but it cannot be used as QgsFeatureId because one geometry object may
175
- // represent more features because it may have more categories.
176
- featureId = makeFeatureId ( id, cat );
201
+ Vect_cidx_get_cat_by_index ( P->mMap , P->mCidxFieldIndex , mNextCidx ++, &cat, &type, &id );
202
+ // Warning: selection array is only of type line/area of current layer -> check type first
203
+ if ( !( type & P->mGrassType ) )
204
+ continue ;
205
+
206
+ // The 'id' is a unique id of a GRASS geometry object (point, line, area)
207
+ // but it cannot be used as QgsFeatureId because one geometry object may
208
+ // represent more features because it may have more categories.
209
+ featureId = makeFeatureId ( id, cat );
210
+ }
177
211
178
212
if ( filterById && featureId != mRequest .filterFid () )
179
213
continue ;
@@ -202,10 +236,52 @@ bool QgsGrassFeatureIterator::nextFeature( QgsFeature& feature )
202
236
else
203
237
setFeatureGeometry ( feature, id, type );
204
238
205
- if ( mRequest .flags () & QgsFeatureRequest::SubsetOfAttributes )
206
- P->setFeatureAttributes ( P->mLayerId , cat, &feature, mRequest .subsetOfAttributes () );
239
+ if ( ! P->isTopoType () )
240
+ {
241
+ if ( mRequest .flags () & QgsFeatureRequest::SubsetOfAttributes )
242
+ P->setFeatureAttributes ( P->mLayerId , cat, &feature, mRequest .subsetOfAttributes () );
243
+ else
244
+ P->setFeatureAttributes ( P->mLayerId , cat, &feature );
245
+ }
207
246
else
208
- P->setFeatureAttributes ( P->mLayerId , cat, &feature );
247
+ {
248
+ feature.setAttribute ( 0 , id );
249
+ if ( P->mLayerType == QgsGrassProvider::TOPO_POINT || P->mLayerType == QgsGrassProvider::TOPO_LINE )
250
+ {
251
+ feature.setAttribute ( 1 , P->primitiveTypeName ( type ) );
252
+
253
+ int node1, node2;
254
+ Vect_get_line_nodes ( P->mMap , id, &node1, &node2 );
255
+ feature.setAttribute ( 2 , node1 );
256
+ if ( P->mLayerType == QgsGrassProvider::TOPO_LINE )
257
+ {
258
+ feature.setAttribute ( 3 , node2 );
259
+ }
260
+ }
261
+
262
+ if ( P->mLayerType == QgsGrassProvider::TOPO_LINE )
263
+ {
264
+ if ( type == GV_BOUNDARY )
265
+ {
266
+ int left, right;
267
+ Vect_get_line_areas ( P->mMap , id, &left, &right );
268
+ feature.setAttribute ( 4 , left );
269
+ feature.setAttribute ( 5 , right );
270
+ }
271
+ }
272
+ else if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
273
+ {
274
+ QString lines;
275
+ int nlines = Vect_get_node_n_lines ( P->mMap , id );
276
+ for ( int i = 0 ; i < nlines; i++ )
277
+ {
278
+ int line = Vect_get_node_line ( P->mMap , id, i );
279
+ if ( i > 0 ) lines += " ," ;
280
+ lines += QString::number ( line );
281
+ }
282
+ feature.setAttribute ( 1 , lines );
283
+ }
284
+ }
209
285
210
286
feature.setValid ( true );
211
287
@@ -227,6 +303,7 @@ bool QgsGrassFeatureIterator::rewind()
227
303
P->ensureUpdated ();
228
304
229
305
mNextCidx = 0 ;
306
+ mNextTopoId = 1 ;
230
307
231
308
return true ;
232
309
}
@@ -258,6 +335,7 @@ void QgsGrassFeatureIterator::resetSelection( bool sel )
258
335
QgsDebugMsg ( " entered." );
259
336
memset ( mSelection , ( int ) sel, mSelectionSize );
260
337
mNextCidx = 0 ;
338
+ mNextTopoId = 1 ;
261
339
}
262
340
263
341
@@ -291,12 +369,26 @@ void QgsGrassFeatureIterator::setFeatureGeometry( QgsFeature& feature, int id, i
291
369
int wkbsize;
292
370
293
371
// TODO int may be 64 bits (memcpy)
294
- if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) ) /* points or lines */
372
+ if ( type & ( GV_POINTS | GV_LINES | GV_FACE ) || P-> mLayerType == QgsGrassProvider::TOPO_NODE ) /* points or lines */
295
373
{
296
- Vect_read_line ( P->mMap , mPoints , mCats , id );
374
+ if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
375
+ {
376
+ double x, y, z;
377
+ Vect_get_node_coor ( P->mMap , id, &x, &y, &z );
378
+ Vect_reset_line ( mPoints );
379
+ Vect_append_point ( mPoints , x, y, z );
380
+ }
381
+ else
382
+ {
383
+ Vect_read_line ( P->mMap , mPoints , 0 , id );
384
+ }
297
385
int npoints = mPoints ->n_points ;
298
386
299
- if ( type & GV_POINTS )
387
+ if ( P->mLayerType == QgsGrassProvider::TOPO_NODE )
388
+ {
389
+ wkbsize = 1 + 4 + 2 * 8 ;
390
+ }
391
+ else if ( type & GV_POINTS )
300
392
{
301
393
wkbsize = 1 + 4 + 2 * 8 ;
302
394
}
0 commit comments