QGIS API Documentation  2.12.0-Lyon
qgsvectorlayereditutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorlayereditutils.cpp
3  ---------------------
4  begin : Dezember 2012
5  copyright : (C) 2012 by Martin Dobias
6  email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
16 
17 #include "qgsvectordataprovider.h"
18 #include "qgsgeometrycache.h"
20 #include "qgslinestringv2.h"
21 #include "qgslogger.h"
22 #include "qgspointv2.h"
23 #include "qgsgeometryfactory.h"
24 #include "qgis.h"
25 #include "qgswkbtypes.h"
26 
27 #include <limits>
28 
29 
31  : L( layer )
32 {
33 }
34 
35 bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
36 {
37  if ( !L->hasGeometryType() )
38  return false;
39 
40  QgsGeometry geometry;
41  if ( !cache()->geometry( atFeatureId, geometry ) )
42  {
43  // it's not in cache: let's fetch it from layer
44  QgsFeature f;
45  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
46  return false; // geometry not found
47 
48  geometry = *f.constGeometry();
49  }
50 
51  geometry.insertVertex( x, y, beforeVertex );
52 
53  L->editBuffer()->changeGeometry( atFeatureId, &geometry );
54  return true;
55 }
56 
57 
58 bool QgsVectorLayerEditUtils::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
59 {
60  QgsPointV2 p( x, y );
61  return moveVertex( p, atFeatureId, atVertex );
62 }
63 
64 bool QgsVectorLayerEditUtils::moveVertex( const QgsPointV2& p, QgsFeatureId atFeatureId, int atVertex )
65 {
66  if ( !L->hasGeometryType() )
67  return false;
68 
69  QgsGeometry geometry;
70  if ( !cache()->geometry( atFeatureId, geometry ) )
71  {
72  // it's not in cache: let's fetch it from layer
73  QgsFeature f;
74  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
75  return false; // geometry not found
76 
77  geometry = *f.constGeometry();
78  }
79 
80  geometry.moveVertex( p, atVertex );
81 
82  L->editBuffer()->changeGeometry( atFeatureId, &geometry );
83  return true;
84 }
85 
86 
87 bool QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
88 {
89  if ( !L->hasGeometryType() )
90  return false;
91 
92  QgsGeometry geometry;
93  if ( !cache()->geometry( atFeatureId, geometry ) )
94  {
95  // it's not in cache: let's fetch it from layer
96  QgsFeature f;
97  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
98  return false; // geometry not found
99 
100  geometry = *f.constGeometry();
101  }
102 
103  if ( !geometry.deleteVertex( atVertex ) )
104  return false;
105 
106  L->editBuffer()->changeGeometry( atFeatureId, &geometry );
107  return true;
108 }
109 
110 int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring, const QgsFeatureIds& targetFeatureIds, QgsFeatureId* modifiedFeatureId )
111 {
112  QgsLineStringV2* ringLine = new QgsLineStringV2();
113  QList< QgsPointV2 > ringPoints;
115  for ( ; ringIt != ring.constEnd(); ++ringIt )
116  {
117  ringPoints.append( QgsPointV2( ringIt->x(), ringIt->y() ) );
118  }
119  ringLine->setPoints( ringPoints );
120  return addRing( ringLine, targetFeatureIds, modifiedFeatureId );
121 }
122 
123 int QgsVectorLayerEditUtils::addRing( QgsCurveV2* ring, const QgsFeatureIds& targetFeatureIds, QgsFeatureId* modifiedFeatureId )
124 {
125  if ( !L->hasGeometryType() )
126  {
127  delete ring;
128  return 5;
129  }
130 
131  int addRingReturnCode = 5; //default: return code for 'ring not inserted'
132  QgsFeature f;
133 
134  QgsFeatureIterator fit;
135  if ( !targetFeatureIds.isEmpty() )
136  {
137  //check only specified features
138  fit = L->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
139  }
140  else
141  {
142  //check all intersecting features
143  QgsRectangle bBox = ring->boundingBox();
144  fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
145  }
146 
147  //find first valid feature we can add the ring to
148  while ( fit.nextFeature( f ) )
149  {
150  if ( !f.constGeometry() )
151  continue;
152 
153  //add ring takes ownership of ring, and deletes it if there's an error
154  addRingReturnCode = f.geometry()->addRing( static_cast< QgsCurveV2* >( ring->clone() ) );
155  if ( addRingReturnCode == 0 )
156  {
157  L->editBuffer()->changeGeometry( f.id(), f.geometry() );
158  if ( modifiedFeatureId )
159  *modifiedFeatureId = f.id();
160 
161  //setModified( true, true );
162  break;
163  }
164  }
165 
166  delete ring;
167  return addRingReturnCode;
168 }
169 
171 {
172  if ( !L->hasGeometryType() )
173  return 6;
174 
175  QgsGeometry geometry;
176  bool firstPart = false;
177  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
178  {
179  // it's not in cache: let's fetch it from layer
180  QgsFeature f;
181  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
182  return 6; //not found
183 
184  if ( !f.constGeometry() || f.constGeometry()->isEmpty() )
185  {
186  //no existing geometry, so adding first part to null geometry
187  firstPart = true;
188  }
189  else
190  {
191  geometry = *f.geometry();
192  }
193  }
194 
195  int errorCode = geometry.addPart( points, L->geometryType() );
196  if ( errorCode == 0 )
197  {
198  if ( firstPart && QgsWKBTypes::isSingleType( QGis::fromOldWkbType( L->wkbType() ) )
200  {
201  //convert back to single part if required by layer
202  geometry.convertToSingleType();
203  }
204  L->editBuffer()->changeGeometry( featureId, &geometry );
205  }
206  return errorCode;
207 }
208 
210 {
211  if ( !L->hasGeometryType() )
212  return 6;
213 
214  QgsGeometry geometry;
215  bool firstPart = false;
216  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
217  {
218  // it's not in cache: let's fetch it from layer
219  QgsFeature f;
220  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
221  return 6; //not found
222 
223  if ( !f.constGeometry() || f.constGeometry()->isEmpty() )
224  {
225  //no existing geometry, so adding first part to null geometry
226  firstPart = true;
227  }
228  else
229  {
230  geometry = *f.geometry();
231  }
232  }
233 
234  int errorCode = geometry.addPart( ring, L->geometryType() );
235  if ( errorCode == 0 )
236  {
237  if ( firstPart && QgsWKBTypes::isSingleType( QGis::fromOldWkbType( L->wkbType() ) )
239  {
240  //convert back to single part if required by layer
241  geometry.convertToSingleType();
242  }
243  L->editBuffer()->changeGeometry( featureId, &geometry );
244  }
245  return errorCode;
246 }
247 
248 
249 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
250 {
251  if ( !L->hasGeometryType() )
252  return 1;
253 
254  QgsGeometry geometry;
255  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
256  {
257  // it's not in cache: let's fetch it from layer
258  QgsFeature f;
259  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
260  return 1; //geometry not found
261 
262  geometry = *f.constGeometry();
263  }
264 
265  int errorCode = geometry.translate( dx, dy );
266  if ( errorCode == 0 )
267  {
268  L->editBuffer()->changeGeometry( featureId, &geometry );
269  }
270  return errorCode;
271 }
272 
273 
274 int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
275 {
276  if ( !L->hasGeometryType() )
277  return 4;
278 
279  QgsFeatureList newFeatures; //store all the newly created features
280  double xMin, yMin, xMax, yMax;
281  QgsRectangle bBox; //bounding box of the split line
282  int returnCode = 0;
283  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
284  int numberOfSplittedFeatures = 0;
285 
286  QgsFeatureIterator features;
287  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
288 
289  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
290  {
291  features = L->selectedFeaturesIterator();
292  }
293  else //else consider all the feature that intersect the bounding box of the split line
294  {
295  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
296  {
297  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
298  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
299  }
300  else
301  {
302  return 1;
303  }
304 
305  if ( bBox.isEmpty() )
306  {
307  //if the bbox is a line, try to make a square out of it
308  if ( bBox.width() == 0.0 && bBox.height() > 0 )
309  {
310  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
311  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
312  }
313  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
314  {
315  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
316  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
317  }
318  else
319  {
320  //If we have a single point, we still create a non-null box
321  double bufferDistance = 0.000001;
322  if ( L->crs().geographicFlag() )
323  bufferDistance = 0.00000001;
324  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
325  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
326  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
327  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
328  }
329  }
330 
331  features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
332  }
333 
334  QgsFeature feat;
335  while ( features.nextFeature( feat ) )
336  {
337  if ( !feat.constGeometry() )
338  {
339  continue;
340  }
341  QList<QgsGeometry*> newGeometries;
342  QList<QgsPoint> topologyTestPoints;
343  QgsGeometry* newGeometry = 0;
344  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
345  if ( splitFunctionReturn == 0 )
346  {
347  //change this geometry
348  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
349 
350  //insert new features
351  for ( int i = 0; i < newGeometries.size(); ++i )
352  {
353  newGeometry = newGeometries.at( i );
354  QgsFeature newFeature;
355  newFeature.setGeometry( newGeometry );
356 
357  //use default value where possible for primary key (e.g. autoincrement),
358  //and use the value from the original (split) feature if not primary key
359  QgsAttributes newAttributes = feat.attributes();
360  Q_FOREACH ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
361  {
362  const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
363  if ( !defaultValue.isNull() )
364  {
365  newAttributes[ pkIdx ] = defaultValue;
366  }
367  else //try with NULL
368  {
369  newAttributes[ pkIdx ] = QVariant();
370  }
371  }
372 
373  newFeature.setAttributes( newAttributes );
374 
375  newFeatures.append( newFeature );
376  }
377 
378  if ( topologicalEditing )
379  {
380  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
381  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
382  {
383  addTopologicalPoints( *topol_it );
384  }
385  }
386  ++numberOfSplittedFeatures;
387  }
388  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
389  {
390  returnCode = splitFunctionReturn;
391  }
392  }
393 
394  if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
395  {
396  //There is a selection but no feature has been split.
397  //Maybe user forgot that only the selected features are split
398  returnCode = 4;
399  }
400 
401 
402  //now add the new features to this vectorlayer
403  L->editBuffer()->addFeatures( newFeatures );
404 
405  return returnCode;
406 }
407 
408 int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
409 {
410  if ( !L->hasGeometryType() )
411  return 4;
412 
413  double xMin, yMin, xMax, yMax;
414  QgsRectangle bBox; //bounding box of the split line
415  int returnCode = 0;
416  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
417  int numberOfSplittedParts = 0;
418 
419  QgsFeatureIterator fit;
420 
421  if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
422  {
423  fit = L->selectedFeaturesIterator();
424  }
425  else //else consider all the feature that intersect the bounding box of the split line
426  {
427  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
428  {
429  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
430  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
431  }
432  else
433  {
434  return 1;
435  }
436 
437  if ( bBox.isEmpty() )
438  {
439  //if the bbox is a line, try to make a square out of it
440  if ( bBox.width() == 0.0 && bBox.height() > 0 )
441  {
442  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
443  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
444  }
445  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
446  {
447  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
448  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
449  }
450  else
451  {
452  //If we have a single point, we still create a non-null box
453  double bufferDistance = 0.000001;
454  if ( L->crs().geographicFlag() )
455  bufferDistance = 0.00000001;
456  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
457  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
458  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
459  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
460  }
461  }
462 
463  fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
464  }
465 
466  int addPartRet = 0;
467 
468  QgsFeature feat;
469  while ( fit.nextFeature( feat ) )
470  {
471  QList<QgsGeometry*> newGeometries;
472  QList<QgsPoint> topologyTestPoints;
473  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
474  if ( splitFunctionReturn == 0 )
475  {
476  //add new parts
477  if ( !newGeometries.isEmpty() )
478  feat.geometry()->convertToMultiType();
479 
480  for ( int i = 0; i < newGeometries.size(); ++i )
481  {
482  addPartRet = feat.geometry()->addPart( newGeometries.at( i ) );
483  if ( addPartRet )
484  break;
485  }
486 
487  // For test only: Exception already thrown here...
488  // feat.geometry()->asWkb();
489 
490  if ( !addPartRet )
491  {
492  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
493  }
494  else
495  {
496  // Test addPartRet
497  switch ( addPartRet )
498  {
499  case 1:
500  QgsDebugMsg( "Not a multipolygon" );
501  break;
502 
503  case 2:
504  QgsDebugMsg( "Not a valid geometry" );
505  break;
506 
507  case 3:
508  QgsDebugMsg( "New polygon ring" );
509  break;
510  }
511  }
512  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
513 
514  if ( topologicalEditing )
515  {
516  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
517  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
518  {
519  addTopologicalPoints( *topol_it );
520  }
521  }
522  ++numberOfSplittedParts;
523  }
524  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
525  {
526  returnCode = splitFunctionReturn;
527  }
528 
529  qDeleteAll( newGeometries );
530  }
531 
532  if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
533  {
534  //There is a selection but no feature has been split.
535  //Maybe user forgot that only the selected features are split
536  returnCode = 4;
537  }
538 
539  return returnCode;
540 }
541 
542 
544 {
545  if ( !L->hasGeometryType() )
546  return 1;
547 
548  if ( !geom )
549  {
550  return 1;
551  }
552 
553  int returnVal = 0;
554 
555  QGis::WkbType wkbType = geom->wkbType();
556 
557  switch ( wkbType )
558  {
559  //line
561  case QGis::WKBLineString:
562  {
563  QgsPolyline theLine = geom->asPolyline();
564  QgsPolyline::const_iterator line_it = theLine.constBegin();
565  for ( ; line_it != theLine.constEnd(); ++line_it )
566  {
567  if ( addTopologicalPoints( *line_it ) != 0 )
568  {
569  returnVal = 2;
570  }
571  }
572  break;
573  }
574 
575  //multiline
578  {
579  QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
580  QgsPolyline currentPolyline;
581 
582  for ( int i = 0; i < theMultiLine.size(); ++i )
583  {
584  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
585  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
586  {
587  if ( addTopologicalPoints( *line_it ) != 0 )
588  {
589  returnVal = 2;
590  }
591  }
592  }
593  break;
594  }
595 
596  //polygon
597  case QGis::WKBPolygon25D:
598  case QGis::WKBPolygon:
599  {
600  QgsPolygon thePolygon = geom->asPolygon();
601  QgsPolyline currentRing;
602 
603  for ( int i = 0; i < thePolygon.size(); ++i )
604  {
605  currentRing = thePolygon.at( i );
606  QgsPolyline::const_iterator line_it = currentRing.constBegin();
607  for ( ; line_it != currentRing.constEnd(); ++line_it )
608  {
609  if ( addTopologicalPoints( *line_it ) != 0 )
610  {
611  returnVal = 2;
612  }
613  }
614  }
615  break;
616  }
617 
618  //multipolygon
621  {
622  QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
623  QgsPolygon currentPolygon;
624  QgsPolyline currentRing;
625 
626  for ( int i = 0; i < theMultiPolygon.size(); ++i )
627  {
628  currentPolygon = theMultiPolygon.at( i );
629  for ( int j = 0; j < currentPolygon.size(); ++j )
630  {
631  currentRing = currentPolygon.at( j );
632  QgsPolyline::const_iterator line_it = currentRing.constBegin();
633  for ( ; line_it != currentRing.constEnd(); ++line_it )
634  {
635  if ( addTopologicalPoints( *line_it ) != 0 )
636  {
637  returnVal = 2;
638  }
639  }
640  }
641  }
642  break;
643  }
644  default:
645  break;
646  }
647  return returnVal;
648 }
649 
650 
652 {
653  if ( !L->hasGeometryType() )
654  return 1;
655 
656  QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
657  //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
658  QMultiMap<double, QgsSnappingResult> vertexSnapResults;
659 
660  QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
661 
662  //work with a tolerance because coordinate projection may introduce some rounding
663  double threshold = 0.0000001;
664  if ( L->crs().mapUnits() == QGis::Meters )
665  {
666  threshold = 0.001;
667  }
668  else if ( L->crs().mapUnits() == QGis::Feet )
669  {
670  threshold = 0.0001;
671  }
672 
673 
674  if ( L->snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
675  {
676  return 2;
677  }
678 
681  for ( ; snap_it != snapResults.constEnd(); ++snap_it )
682  {
683  //test if p is already a vertex of this geometry. If yes, don't insert it
684  bool vertexAlreadyExists = false;
685  if ( L->snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
686  {
687  continue;
688  }
689 
690  vertex_snap_it = vertexSnapResults.constBegin();
691  for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
692  {
693  if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
694  {
695  vertexAlreadyExists = true;
696  }
697  }
698 
699  if ( !vertexAlreadyExists )
700  {
701  filteredSnapResults.push_back( *snap_it );
702  }
703  }
704  insertSegmentVerticesForSnap( filteredSnapResults );
705  return 0;
706 }
707 
708 
710 {
711  if ( !L->hasGeometryType() )
712  return 1;
713 
714  int returnval = 0;
715  QgsPoint layerPoint;
716 
718  for ( ; it != snapResults.constEnd(); ++it )
719  {
720  if ( it->snappedVertexNr == -1 ) // segment snap
721  {
722  layerPoint = it->snappedVertex;
723  if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
724  {
725  returnval = 3;
726  }
727  }
728  }
729  return returnval;
730 }
731 
732 
733 
734 
735 int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
736 {
737  if ( list.size() < 1 )
738  {
739  return 1;
740  }
741 
746 
747  for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
748  {
749  if ( it->x() < xmin )
750  {
751  xmin = it->x();
752  }
753  if ( it->x() > xmax )
754  {
755  xmax = it->x();
756  }
757  if ( it->y() < ymin )
758  {
759  ymin = it->y();
760  }
761  if ( it->y() > ymax )
762  {
763  ymax = it->y();
764  }
765  }
766 
767  return 0;
768 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:53
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
bool isEmpty() const
test if rectangle is empty.
int insertSegmentVerticesForSnap(const QList< QgsSnappingResult > &snapResults)
Inserts vertices to the snapped segments.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:171
virtual bool addFeatures(QgsFeatureList &features)
Insert a copy of the given features into the layer (but does not commit it)
Use exact geometry intersection (slower) instead of bounding boxes.
void push_back(const T &value)
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:196
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
int size() const
QgsMultiPolyline asMultiPolyline() const
Return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsPolygon asPolygon() const
Return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list...
const_iterator constEnd() const
const_iterator constBegin() const
const T & at(int i) const
bool moveVertex(double x, double y, int atVertex)
Moves the vertex at the given position number and item (first number is index 0) to the given coordin...
int addPart(const QList< QgsPoint > &points, QGis::GeometryType geomType=QGis::UnknownGeometry)
Adds a new part to a the geometry.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:97
WkbType
Used for symbology operations.
Definition: qgis.h:56
int addPart(const QList< QgsPoint > &ring, QgsFeatureId featureId)
Adds a new part polygon to a multipart feature.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:176
virtual QgsAttributeList pkAttributeIndexes()
Return list of indexes of fields that make up the primary key.
bool insertVertex(double x, double y, int beforeVertex)
Insert a new vertex before the given vertex index, ring and item (first number is index 0) If the req...
bool deleteVertex(QgsFeatureId atFeatureId, int atVertex)
Deletes a vertex from a feature.
double x() const
Get the x value of the point.
Definition: qgspoint.h:126
int size() const
int boundingBoxFromPointList(const QList< QgsPoint > &list, double &xmin, double &ymin, double &xmax, double &ymax) const
Little helper function that gives bounding box from a list of points.
QgsMultiPolygon asMultiPolygon() const
Return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
int addRing(const QList< QgsPoint > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=0)
Adds a ring to polygon/multipolygon features.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
static QgsWKBTypes::Type fromOldWkbType(QGis::WkbType type)
Converts from old (pre 2.10) WKB type to new WKB type.
Definition: qgis.cpp:103
int splitGeometry(const QList< QgsPoint > &splitLine, QList< QgsGeometry * > &newGeometries, bool topological, QList< QgsPoint > &topologyTestPoints)
Splits this geometry according to a given line.
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object.
Definition: qgsfeature.cpp:106
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
void append(const T &value)
bool isNull() const
bool convertToSingleType()
Converts multi type geometry into single type geometry e.g.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:201
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:186
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
Line string geometry type.
QgsAttributes attributes() const
Returns the feature's attributes.
Definition: qgsfeature.cpp:92
int addTopologicalPoints(const QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
int snapWithContext(const QgsPoint &startPoint, double snappingTolerance, QMultiMap< double, QgsSnappingResult > &snappingResults, QgsSnapper::SnappingType snap_to)
Snaps to segment or vertex within given tolerance.
Point geometry type.
Definition: qgspointv2.h:29
bool geometry(QgsFeatureId fid, QgsGeometry &geometry)
fetch geometry from cache, return true if successful
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:176
bool isEmpty() const
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) Returns false if a...
const_iterator constEnd() const
int translateFeature(QgsFeatureId featureId, double dx, double dy)
Translates feature by dx, dy.
bool moveVertex(double x, double y, QgsFeatureId atFeatureId, int atVertex)
Moves the vertex at the given position number, ring and item (first number is index 0)...
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
const T & value() const
QGis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QGis::GeometryType geometryType() const
Returns point, line or polygon.
A class to represent a point.
Definition: qgspoint.h:63
int translate(double dx, double dy)
Translate this geometry by dx, dy.
QgsGeometry * geometry()
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:64
QgsFeatureIterator selectedFeaturesIterator(QgsFeatureRequest request=QgsFeatureRequest())
Get an iterator of the selected features.
QgsPolyline asPolyline() const
Return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list...
bool insertVertex(double x, double y, QgsFeatureId atFeatureId, int beforeVertex)
Insert a new vertex before the given vertex number, in the given ring, item (first number is index 0)...
const T & at(int i) const
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
const_iterator constBegin() const
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
virtual QVariant defaultValue(int fieldId)
Returns the default value for field specified by fieldId.
void setPoints(const QList< QgsPointV2 > &points)
static bool isSingleType(Type type)
Definition: qgswkbtypes.cpp:70
virtual bool doesStrictFeatureTypeCheck() const
Returns true if the provider is strict about the type of inserted features (e.g.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:181
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:70
bool isEmpty() const
qint64 QgsFeatureId
Definition: qgsfeature.h:31
double y() const
Get the y value of the point.
Definition: qgspoint.h:134
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
bool isEmpty() const
Returns true if the geometry is empty (ie, contains no underlying geometry accessible via geometry)...
typedef const_iterator
int addRing(const QList< QgsPoint > &ring)
Adds a new ring to this geometry.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
const_iterator constEnd() const
bool nextFeature(QgsFeature &f)
const_iterator constBegin() const
QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
virtual QgsAbstractGeometryV2 * clone() const =0
Clones the geometry by performing a deep copy.
Abstract base class for curved geometry type.
Definition: qgscurvev2.h:32
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:206
A vector of attributes.
Definition: qgsfeature.h:109
int size() const
Represents a vector layer which manages a vector based data sets.
bool geographicFlag() const
Get this Geographic? flag.
int splitParts(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits parts cut by the given line.
int selectedFeatureCount()
The number of features that are selected in this layer.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:191
virtual bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
Change feature's geometry.
int splitFeatures(const QList< QgsPoint > &splitLine, bool topologicalEditing=false)
Splits features cut by the given line.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:166
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:211
QgsVectorLayerEditUtils(QgsVectorLayer *layer)
QGis::UnitType mapUnits() const
Get the units that the projection is in.