QGIS API Documentation  2.13.0-Master
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  QgsVectorLayer::EditResult res = deleteVertexV2( atFeatureId, atVertex );
91 }
92 
94 {
95  if ( !L->hasGeometryType() )
97 
98  QgsGeometry geometry;
99  if ( !cache()->geometry( featureId, geometry ) )
100  {
101  // it's not in cache: let's fetch it from layer
102  QgsFeature f;
103  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
104  return QgsVectorLayer::FetchFeatureFailed; // geometry not found
105 
106  geometry = *f.constGeometry();
107  }
108 
109  if ( !geometry.deleteVertex( vertex ) )
111 
112  if ( geometry.geometry() && geometry.geometry()->nCoordinates() == 0 )
113  {
114  //last vertex deleted, set geometry to null
115  geometry.setGeometry( nullptr );
116  }
117 
118  L->editBuffer()->changeGeometry( featureId, &geometry );
120 }
121 
122 int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring, const QgsFeatureIds& targetFeatureIds, QgsFeatureId* modifiedFeatureId )
123 {
124  QgsLineStringV2* ringLine = new QgsLineStringV2();
125  QList< QgsPointV2 > ringPoints;
127  for ( ; ringIt != ring.constEnd(); ++ringIt )
128  {
129  ringPoints.append( QgsPointV2( ringIt->x(), ringIt->y() ) );
130  }
131  ringLine->setPoints( ringPoints );
132  return addRing( ringLine, targetFeatureIds, modifiedFeatureId );
133 }
134 
135 int QgsVectorLayerEditUtils::addRing( QgsCurveV2* ring, const QgsFeatureIds& targetFeatureIds, QgsFeatureId* modifiedFeatureId )
136 {
137  if ( !L->hasGeometryType() )
138  {
139  delete ring;
140  return 5;
141  }
142 
143  int addRingReturnCode = 5; //default: return code for 'ring not inserted'
144  QgsFeature f;
145 
146  QgsFeatureIterator fit;
147  if ( !targetFeatureIds.isEmpty() )
148  {
149  //check only specified features
150  fit = L->getFeatures( QgsFeatureRequest().setFilterFids( targetFeatureIds ) );
151  }
152  else
153  {
154  //check all intersecting features
155  QgsRectangle bBox = ring->boundingBox();
156  fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
157  }
158 
159  //find first valid feature we can add the ring to
160  while ( fit.nextFeature( f ) )
161  {
162  if ( !f.constGeometry() )
163  continue;
164 
165  //add ring takes ownership of ring, and deletes it if there's an error
166  addRingReturnCode = f.geometry()->addRing( static_cast< QgsCurveV2* >( ring->clone() ) );
167  if ( addRingReturnCode == 0 )
168  {
169  L->editBuffer()->changeGeometry( f.id(), f.geometry() );
170  if ( modifiedFeatureId )
171  *modifiedFeatureId = f.id();
172 
173  //setModified( true, true );
174  break;
175  }
176  }
177 
178  delete ring;
179  return addRingReturnCode;
180 }
181 
183 {
184  if ( !L->hasGeometryType() )
185  return 6;
186 
187  QgsGeometry geometry;
188  bool firstPart = false;
189  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
190  {
191  // it's not in cache: let's fetch it from layer
192  QgsFeature f;
193  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
194  return 6; //not found
195 
196  if ( !f.constGeometry() || f.constGeometry()->isEmpty() )
197  {
198  //no existing geometry, so adding first part to null geometry
199  firstPart = true;
200  }
201  else
202  {
203  geometry = *f.geometry();
204  }
205  }
206 
207  int errorCode = geometry.addPart( points, L->geometryType() );
208  if ( errorCode == 0 )
209  {
210  if ( firstPart && QgsWKBTypes::isSingleType( QGis::fromOldWkbType( L->wkbType() ) )
212  {
213  //convert back to single part if required by layer
214  geometry.convertToSingleType();
215  }
216  L->editBuffer()->changeGeometry( featureId, &geometry );
217  }
218  return errorCode;
219 }
220 
222 {
223  if ( !L->hasGeometryType() )
224  return 6;
225 
226  QgsGeometry geometry;
227  bool firstPart = false;
228  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
229  {
230  // it's not in cache: let's fetch it from layer
231  QgsFeature f;
232  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
233  return 6; //not found
234 
235  if ( !f.constGeometry() || f.constGeometry()->isEmpty() )
236  {
237  //no existing geometry, so adding first part to null geometry
238  firstPart = true;
239  }
240  else
241  {
242  geometry = *f.geometry();
243  }
244  }
245 
246  int errorCode = geometry.addPart( ring, L->geometryType() );
247  if ( errorCode == 0 )
248  {
249  if ( firstPart && QgsWKBTypes::isSingleType( QGis::fromOldWkbType( L->wkbType() ) )
251  {
252  //convert back to single part if required by layer
253  geometry.convertToSingleType();
254  }
255  L->editBuffer()->changeGeometry( featureId, &geometry );
256  }
257  return errorCode;
258 }
259 
260 
261 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
262 {
263  if ( !L->hasGeometryType() )
264  return 1;
265 
266  QgsGeometry geometry;
267  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
268  {
269  // it's not in cache: let's fetch it from layer
270  QgsFeature f;
271  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
272  return 1; //geometry not found
273 
274  geometry = *f.constGeometry();
275  }
276 
277  int errorCode = geometry.translate( dx, dy );
278  if ( errorCode == 0 )
279  {
280  L->editBuffer()->changeGeometry( featureId, &geometry );
281  }
282  return errorCode;
283 }
284 
285 
286 int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
287 {
288  if ( !L->hasGeometryType() )
289  return 4;
290 
291  QgsFeatureList newFeatures; //store all the newly created features
292  double xMin, yMin, xMax, yMax;
293  QgsRectangle bBox; //bounding box of the split line
294  int returnCode = 0;
295  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
296  int numberOfSplittedFeatures = 0;
297 
298  QgsFeatureIterator features;
299  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
300 
301  if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
302  {
303  features = L->selectedFeaturesIterator();
304  }
305  else //else consider all the feature that intersect the bounding box of the split line
306  {
307  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
308  {
309  bBox.setXMinimum( xMin );
310  bBox.setYMinimum( yMin );
311  bBox.setXMaximum( xMax );
312  bBox.setYMaximum( yMax );
313  }
314  else
315  {
316  return 1;
317  }
318 
319  if ( bBox.isEmpty() )
320  {
321  //if the bbox is a line, try to make a square out of it
322  if ( bBox.width() == 0.0 && bBox.height() > 0 )
323  {
324  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
325  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
326  }
327  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
328  {
329  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
330  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
331  }
332  else
333  {
334  //If we have a single point, we still create a non-null box
335  double bufferDistance = 0.000001;
336  if ( L->crs().geographicFlag() )
337  bufferDistance = 0.00000001;
338  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
339  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
340  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
341  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
342  }
343  }
344 
345  features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
346  }
347 
348  QgsFeature feat;
349  while ( features.nextFeature( feat ) )
350  {
351  if ( !feat.constGeometry() )
352  {
353  continue;
354  }
355  QList<QgsGeometry*> newGeometries;
356  QList<QgsPoint> topologyTestPoints;
357  QgsGeometry* newGeometry = nullptr;
358  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
359  if ( splitFunctionReturn == 0 )
360  {
361  //change this geometry
362  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
363 
364  //insert new features
365  for ( int i = 0; i < newGeometries.size(); ++i )
366  {
367  newGeometry = newGeometries.at( i );
368  QgsFeature newFeature;
369  newFeature.setGeometry( newGeometry );
370 
371  //use default value where possible for primary key (e.g. autoincrement),
372  //and use the value from the original (split) feature if not primary key
373  QgsAttributes newAttributes = feat.attributes();
374  Q_FOREACH ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
375  {
376  const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
377  if ( !defaultValue.isNull() )
378  {
379  newAttributes[ pkIdx ] = defaultValue;
380  }
381  else //try with NULL
382  {
383  newAttributes[ pkIdx ] = QVariant();
384  }
385  }
386 
387  newFeature.setAttributes( newAttributes );
388 
389  newFeatures.append( newFeature );
390  }
391 
392  if ( topologicalEditing )
393  {
394  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
395  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
396  {
397  addTopologicalPoints( *topol_it );
398  }
399  }
400  ++numberOfSplittedFeatures;
401  }
402  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
403  {
404  returnCode = splitFunctionReturn;
405  }
406  }
407 
408  if ( numberOfSplittedFeatures == 0 && !selectedIds.isEmpty() )
409  {
410  //There is a selection but no feature has been split.
411  //Maybe user forgot that only the selected features are split
412  returnCode = 4;
413  }
414 
415 
416  //now add the new features to this vectorlayer
417  L->editBuffer()->addFeatures( newFeatures );
418 
419  return returnCode;
420 }
421 
422 int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
423 {
424  if ( !L->hasGeometryType() )
425  return 4;
426 
427  double xMin, yMin, xMax, yMax;
428  QgsRectangle bBox; //bounding box of the split line
429  int returnCode = 0;
430  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
431  int numberOfSplittedParts = 0;
432 
433  QgsFeatureIterator fit;
434 
435  if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
436  {
437  fit = L->selectedFeaturesIterator();
438  }
439  else //else consider all the feature that intersect the bounding box of the split line
440  {
441  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
442  {
443  bBox.setXMinimum( xMin );
444  bBox.setYMinimum( yMin );
445  bBox.setXMaximum( xMax );
446  bBox.setYMaximum( yMax );
447  }
448  else
449  {
450  return 1;
451  }
452 
453  if ( bBox.isEmpty() )
454  {
455  //if the bbox is a line, try to make a square out of it
456  if ( bBox.width() == 0.0 && bBox.height() > 0 )
457  {
458  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
459  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
460  }
461  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
462  {
463  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
464  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
465  }
466  else
467  {
468  //If we have a single point, we still create a non-null box
469  double bufferDistance = 0.000001;
470  if ( L->crs().geographicFlag() )
471  bufferDistance = 0.00000001;
472  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
473  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
474  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
475  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
476  }
477  }
478 
479  fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
480  }
481 
482  int addPartRet = 0;
483 
484  QgsFeature feat;
485  while ( fit.nextFeature( feat ) )
486  {
487  QList<QgsGeometry*> newGeometries;
488  QList<QgsPoint> topologyTestPoints;
489  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
490  if ( splitFunctionReturn == 0 )
491  {
492  //add new parts
493  if ( !newGeometries.isEmpty() )
494  feat.geometry()->convertToMultiType();
495 
496  for ( int i = 0; i < newGeometries.size(); ++i )
497  {
498  addPartRet = feat.geometry()->addPart( newGeometries.at( i ) );
499  if ( addPartRet )
500  break;
501  }
502 
503  // For test only: Exception already thrown here...
504  // feat.geometry()->asWkb();
505 
506  if ( !addPartRet )
507  {
508  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
509  }
510  else
511  {
512  // Test addPartRet
513  switch ( addPartRet )
514  {
515  case 1:
516  QgsDebugMsg( "Not a multipolygon" );
517  break;
518 
519  case 2:
520  QgsDebugMsg( "Not a valid geometry" );
521  break;
522 
523  case 3:
524  QgsDebugMsg( "New polygon ring" );
525  break;
526  }
527  }
528  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
529 
530  if ( topologicalEditing )
531  {
532  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
533  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
534  {
535  addTopologicalPoints( *topol_it );
536  }
537  }
538  ++numberOfSplittedParts;
539  }
540  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
541  {
542  returnCode = splitFunctionReturn;
543  }
544 
545  qDeleteAll( newGeometries );
546  }
547 
548  if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
549  {
550  //There is a selection but no feature has been split.
551  //Maybe user forgot that only the selected features are split
552  returnCode = 4;
553  }
554 
555  return returnCode;
556 }
557 
558 
560 {
561  if ( !L->hasGeometryType() )
562  return 1;
563 
564  if ( !geom )
565  {
566  return 1;
567  }
568 
569  int returnVal = 0;
570 
571  QGis::WkbType wkbType = geom->wkbType();
572 
573  switch ( wkbType )
574  {
575  //line
577  case QGis::WKBLineString:
578  {
579  QgsPolyline theLine = geom->asPolyline();
580  QgsPolyline::const_iterator line_it = theLine.constBegin();
581  for ( ; line_it != theLine.constEnd(); ++line_it )
582  {
583  if ( addTopologicalPoints( *line_it ) != 0 )
584  {
585  returnVal = 2;
586  }
587  }
588  break;
589  }
590 
591  //multiline
594  {
595  QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
596  QgsPolyline currentPolyline;
597 
598  for ( int i = 0; i < theMultiLine.size(); ++i )
599  {
600  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
601  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
602  {
603  if ( addTopologicalPoints( *line_it ) != 0 )
604  {
605  returnVal = 2;
606  }
607  }
608  }
609  break;
610  }
611 
612  //polygon
613  case QGis::WKBPolygon25D:
614  case QGis::WKBPolygon:
615  {
616  QgsPolygon thePolygon = geom->asPolygon();
617  QgsPolyline currentRing;
618 
619  for ( int i = 0; i < thePolygon.size(); ++i )
620  {
621  currentRing = thePolygon.at( i );
622  QgsPolyline::const_iterator line_it = currentRing.constBegin();
623  for ( ; line_it != currentRing.constEnd(); ++line_it )
624  {
625  if ( addTopologicalPoints( *line_it ) != 0 )
626  {
627  returnVal = 2;
628  }
629  }
630  }
631  break;
632  }
633 
634  //multipolygon
637  {
638  QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
639  QgsPolygon currentPolygon;
640  QgsPolyline currentRing;
641 
642  for ( int i = 0; i < theMultiPolygon.size(); ++i )
643  {
644  currentPolygon = theMultiPolygon.at( i );
645  for ( int j = 0; j < currentPolygon.size(); ++j )
646  {
647  currentRing = currentPolygon.at( j );
648  QgsPolyline::const_iterator line_it = currentRing.constBegin();
649  for ( ; line_it != currentRing.constEnd(); ++line_it )
650  {
651  if ( addTopologicalPoints( *line_it ) != 0 )
652  {
653  returnVal = 2;
654  }
655  }
656  }
657  }
658  break;
659  }
660  default:
661  break;
662  }
663  return returnVal;
664 }
665 
666 
668 {
669  if ( !L->hasGeometryType() )
670  return 1;
671 
672  QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
673  //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
674  QMultiMap<double, QgsSnappingResult> vertexSnapResults;
675 
676  QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
677 
678  //work with a tolerance because coordinate projection may introduce some rounding
679  double threshold = 0.0000001;
680  if ( L->crs().mapUnits() == QGis::Meters )
681  {
682  threshold = 0.001;
683  }
684  else if ( L->crs().mapUnits() == QGis::Feet )
685  {
686  threshold = 0.0001;
687  }
688 
689 
690  if ( L->snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
691  {
692  return 2;
693  }
694 
697  for ( ; snap_it != snapResults.constEnd(); ++snap_it )
698  {
699  //test if p is already a vertex of this geometry. If yes, don't insert it
700  bool vertexAlreadyExists = false;
701  if ( L->snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
702  {
703  continue;
704  }
705 
706  vertex_snap_it = vertexSnapResults.constBegin();
707  for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
708  {
709  if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
710  {
711  vertexAlreadyExists = true;
712  }
713  }
714 
715  if ( !vertexAlreadyExists )
716  {
717  filteredSnapResults.push_back( *snap_it );
718  }
719  }
720  insertSegmentVerticesForSnap( filteredSnapResults );
721  return 0;
722 }
723 
724 
726 {
727  if ( !L->hasGeometryType() )
728  return 1;
729 
730  int returnval = 0;
731  QgsPoint layerPoint;
732 
734  for ( ; it != snapResults.constEnd(); ++it )
735  {
736  if ( it->snappedVertexNr == -1 ) // segment snap
737  {
738  layerPoint = it->snappedVertex;
739  if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
740  {
741  returnval = 3;
742  }
743  }
744  }
745  return returnval;
746 }
747 
748 
749 
750 
751 int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
752 {
753  if ( list.size() < 1 )
754  {
755  return 1;
756  }
757 
762 
763  for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
764  {
765  if ( it->x() < xmin )
766  {
767  xmin = it->x();
768  }
769  if ( it->x() > xmax )
770  {
771  xmax = it->x();
772  }
773  if ( it->y() < ymin )
774  {
775  ymin = it->y();
776  }
777  if ( it->y() > ymax )
778  {
779  ymax = it->y();
780  }
781  }
782 
783  return 0;
784 }
QgsFeatureId id() const
Get the feature ID for this feature.
Definition: qgsfeature.cpp:65
Wrapper for iterator of features from vector data provider or vector layer.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
static bool isSingleType(Type type)
Returns true if the WKB type is a single type.
Definition: qgswkbtypes.h:467
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
QgsAbstractGeometryV2 * geometry() const
Returns the underlying geometry store.
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
void setGeometry(QgsAbstractGeometryV2 *geometry)
Sets the underlying geometry store.
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:115
WkbType
Used for symbology operations.
Definition: qgis.h:57
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:187
virtual QgsAttributeList pkAttributeIndexes()
Return list of indexes of fields that make up the primary key.
virtual QgsCurveV2 * clone() const override=0
Clones the geometry by performing a deep copy.
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...
Q_DECL_DEPRECATED 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:128
int nCoordinates() const
Returns the number of nodes contained in the geometry.
int size() const
Edit operation failed.
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.
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:104
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:124
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.
Edit failed due to invalid layer.
Line string geometry type, with support for z-dimension and m-values.
QgsAttributes attributes() const
Returns the feature's attributes.
Definition: qgsfeature.cpp:110
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, with support for z-dimension and m-values.
Definition: qgspointv2.h:34
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.
Unable to fetch requested feature.
A class to represent a point.
Definition: qgspoint.h:65
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:76
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
int addRing(const QList< QgsPoint > &ring, const QgsFeatureIds &targetFeatureIds=QgsFeatureIds(), QgsFeatureId *modifiedFeatureId=nullptr)
Adds a ring to polygon/multipolygon features.
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)
Resets the line string to match the specified list of points.
QgsVectorLayer::EditResult deleteVertexV2(QgsFeatureId featureId, int vertex)
Deletes a vertex from a feature.
virtual bool doesStrictFeatureTypeCheck() const
Returns true if the provider is strict about the type of inserted features (e.g.
EditResult
Result of an edit operation.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:181
Edit operation was successful.
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
bool isEmpty() const
qint64 QgsFeatureId
Definition: qgsfeature.h:31
double y() const
Get the y value of the point.
Definition: qgspoint.h:136
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
Edit operation resulted in an empty geometry.
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.
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:115
int size() const
Represents a vector layer which manages a vector based data sets.
bool geographicFlag() const
Returns whether the CRS is a geographic CRS.
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
Returns the units for the projection used by the CRS.