QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 "qgslogger.h"
21 
22 #include <limits>
23 
24 
26  : L( layer )
27 {
28 }
29 
30 bool QgsVectorLayerEditUtils::insertVertex( double x, double y, QgsFeatureId atFeatureId, int beforeVertex )
31 {
32  if ( !L->hasGeometryType() )
33  return false;
34 
35  QgsGeometry geometry;
36  if ( !cache()->geometry( atFeatureId, geometry ) )
37  {
38  // it's not in cache: let's fetch it from layer
39  QgsFeature f;
40  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
41  return false; // geometry not found
42 
43  geometry = *f.geometry();
44  }
45 
46  geometry.insertVertex( x, y, beforeVertex );
47 
48  L->editBuffer()->changeGeometry( atFeatureId, &geometry );
49  return true;
50 }
51 
52 
53 bool QgsVectorLayerEditUtils::moveVertex( double x, double y, QgsFeatureId atFeatureId, int atVertex )
54 {
55  if ( !L->hasGeometryType() )
56  return false;
57 
58  QgsGeometry geometry;
59  if ( !cache()->geometry( atFeatureId, geometry ) )
60  {
61  // it's not in cache: let's fetch it from layer
62  QgsFeature f;
63  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
64  return false; // geometry not found
65 
66  geometry = *f.geometry();
67  }
68 
69  geometry.moveVertex( x, y, atVertex );
70 
71  L->editBuffer()->changeGeometry( atFeatureId, &geometry );
72  return true;
73 }
74 
75 
76 bool QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId atFeatureId, int atVertex )
77 {
78  if ( !L->hasGeometryType() )
79  return false;
80 
81  QgsGeometry geometry;
82  if ( !cache()->geometry( atFeatureId, geometry ) )
83  {
84  // it's not in cache: let's fetch it from layer
85  QgsFeature f;
86  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( atFeatureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
87  return false; // geometry not found
88 
89  geometry = *f.geometry();
90  }
91 
92  if ( !geometry.deleteVertex( atVertex ) )
93  return false;
94 
95  L->editBuffer()->changeGeometry( atFeatureId, &geometry );
96  return true;
97 }
98 
99 
100 int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring )
101 {
102  if ( !L->hasGeometryType() )
103  return 5;
104 
105  int addRingReturnCode = 5; //default: return code for 'ring not inserted'
106  double xMin, yMin, xMax, yMax;
107  QgsRectangle bBox;
108 
109  if ( boundingBoxFromPointList( ring, xMin, yMin, xMax, yMax ) == 0 )
110  {
111  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
112  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
113  }
114  else
115  {
116  return 3; //ring not valid
117  }
118 
119  QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
120 
121  QgsFeature f;
122  while ( fit.nextFeature( f ) )
123  {
124  addRingReturnCode = f.geometry()->addRing( ring );
125  if ( addRingReturnCode == 0 )
126  {
127  L->editBuffer()->changeGeometry( f.id(), f.geometry() );
128 
129  //setModified( true, true );
130  break;
131  }
132  }
133 
134  return addRingReturnCode;
135 }
136 
137 
138 int QgsVectorLayerEditUtils::addPart( const QList<QgsPoint> &points, QgsFeatureId featureId )
139 {
140  if ( !L->hasGeometryType() )
141  return 6;
142 
143  QgsGeometry geometry;
144  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
145  {
146  // it's not in cache: let's fetch it from layer
147  QgsFeature f;
148  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
149  return 6; //geometry not found
150 
151  geometry = *f.geometry();
152  }
153 
154  int errorCode = geometry.addPart( points, L->geometryType() );
155  if ( errorCode == 0 )
156  {
157  L->editBuffer()->changeGeometry( featureId, &geometry );
158  }
159  return errorCode;
160 }
161 
162 
163 
164 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
165 {
166  if ( !L->hasGeometryType() )
167  return 1;
168 
169  QgsGeometry geometry;
170  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
171  {
172  // it's not in cache: let's fetch it from layer
173  QgsFeature f;
174  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
175  return 1; //geometry not found
176 
177  geometry = *f.geometry();
178  }
179 
180  int errorCode = geometry.translate( dx, dy );
181  if ( errorCode == 0 )
182  {
183  L->editBuffer()->changeGeometry( featureId, &geometry );
184  }
185  return errorCode;
186 }
187 
188 
189 int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
190 {
191  if ( !L->hasGeometryType() )
192  return 4;
193 
194  QgsFeatureList newFeatures; //store all the newly created features
195  double xMin, yMin, xMax, yMax;
196  QgsRectangle bBox; //bounding box of the split line
197  int returnCode = 0;
198  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
199  int numberOfSplittedFeatures = 0;
200 
201  QgsFeatureIterator features;
202  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
203 
204  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
205  {
206  features = L->selectedFeaturesIterator();
207  }
208  else //else consider all the feature that intersect the bounding box of the split line
209  {
210  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
211  {
212  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
213  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
214  }
215  else
216  {
217  return 1;
218  }
219 
220  if ( bBox.isEmpty() )
221  {
222  //if the bbox is a line, try to make a square out of it
223  if ( bBox.width() == 0.0 && bBox.height() > 0 )
224  {
225  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
226  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
227  }
228  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
229  {
230  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
231  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
232  }
233  else
234  {
235  //If we have a single point, we still create a non-null box
236  double bufferDistance = 0.000001;
237  if ( L->crs().geographicFlag() )
238  bufferDistance = 0.00000001;
239  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
240  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
241  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
242  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
243  }
244  }
245 
246  features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
247  }
248 
249  QgsFeature feat;
250  while ( features.nextFeature( feat ) )
251  {
252  if ( !feat.geometry() )
253  {
254  continue;
255  }
256  QList<QgsGeometry*> newGeometries;
257  QList<QgsPoint> topologyTestPoints;
258  QgsGeometry* newGeometry = 0;
259  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
260  if ( splitFunctionReturn == 0 )
261  {
262  //change this geometry
263  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
264 
265  //insert new features
266  for ( int i = 0; i < newGeometries.size(); ++i )
267  {
268  newGeometry = newGeometries.at( i );
269  QgsFeature newFeature;
270  newFeature.setGeometry( newGeometry );
271 
272  //use default value where possible for primary key (e.g. autoincrement),
273  //and use the value from the original (split) feature if not primary key
274  QgsAttributes newAttributes = feat.attributes();
275  foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
276  {
277  const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
278  if ( !defaultValue.isNull() )
279  {
280  newAttributes[ pkIdx ] = defaultValue;
281  }
282  else //try with NULL
283  {
284  newAttributes[ pkIdx ] = QVariant();
285  }
286  }
287 
288  newFeature.setAttributes( newAttributes );
289 
290  newFeatures.append( newFeature );
291  }
292 
293  if ( topologicalEditing )
294  {
295  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
296  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
297  {
298  addTopologicalPoints( *topol_it );
299  }
300  }
301  ++numberOfSplittedFeatures;
302  }
303  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
304  {
305  returnCode = splitFunctionReturn;
306  }
307  }
308 
309  if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
310  {
311  //There is a selection but no feature has been split.
312  //Maybe user forgot that only the selected features are split
313  returnCode = 4;
314  }
315 
316 
317  //now add the new features to this vectorlayer
318  L->editBuffer()->addFeatures( newFeatures );
319 
320  return returnCode;
321 }
322 
323 int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
324 {
325  if ( !L->hasGeometryType() )
326  return 4;
327 
328  double xMin, yMin, xMax, yMax;
329  QgsRectangle bBox; //bounding box of the split line
330  int returnCode = 0;
331  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
332  int numberOfSplittedParts = 0;
333 
334  QgsFeatureIterator fit;
335 
336  if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
337  {
338  fit = L->selectedFeaturesIterator();
339  }
340  else //else consider all the feature that intersect the bounding box of the split line
341  {
342  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
343  {
344  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
345  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
346  }
347  else
348  {
349  return 1;
350  }
351 
352  if ( bBox.isEmpty() )
353  {
354  //if the bbox is a line, try to make a square out of it
355  if ( bBox.width() == 0.0 && bBox.height() > 0 )
356  {
357  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
358  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
359  }
360  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
361  {
362  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
363  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
364  }
365  else
366  {
367  //If we have a single point, we still create a non-null box
368  double bufferDistance = 0.000001;
369  if ( L->crs().geographicFlag() )
370  bufferDistance = 0.00000001;
371  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
372  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
373  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
374  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
375  }
376  }
377 
378  fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
379  }
380 
381  int addPartRet = 0;
382 
383  QgsFeature feat;
384  while ( fit.nextFeature( feat ) )
385  {
386  QList<QgsGeometry*> newGeometries;
387  QList<QgsPoint> topologyTestPoints;
388  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
389  if ( splitFunctionReturn == 0 )
390  {
391  //add new parts
392  for ( int i = 0; i < newGeometries.size(); ++i )
393  {
394  addPartRet = feat.geometry()->addPart( newGeometries.at( i ) );
395  if ( addPartRet )
396  break;
397  }
398 
399  // For test only: Exception already thrown here...
400  // feat.geometry()->asWkb();
401 
402  if ( !addPartRet )
403  {
404  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
405  }
406  else
407  {
408  // Test addPartRet
409  switch ( addPartRet )
410  {
411  case 1:
412  QgsDebugMsg( "Not a multipolygon" );
413  break;
414 
415  case 2:
416  QgsDebugMsg( "Not a valid geometry" );
417  break;
418 
419  case 3:
420  QgsDebugMsg( "New polygon ring" );
421  break;
422  }
423  }
424  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
425 
426  if ( topologicalEditing )
427  {
428  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
429  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
430  {
431  addTopologicalPoints( *topol_it );
432  }
433  }
434  ++numberOfSplittedParts;
435  }
436  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
437  {
438  returnCode = splitFunctionReturn;
439  }
440 
441  qDeleteAll( newGeometries );
442  }
443 
444  if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
445  {
446  //There is a selection but no feature has been split.
447  //Maybe user forgot that only the selected features are split
448  returnCode = 4;
449  }
450 
451  return returnCode;
452 }
453 
454 
456 {
457  if ( !L->hasGeometryType() )
458  return 1;
459 
460  if ( !geom )
461  {
462  return 1;
463  }
464 
465  int returnVal = 0;
466 
467  QGis::WkbType wkbType = geom->wkbType();
468 
469  switch ( wkbType )
470  {
471  //line
473  case QGis::WKBLineString:
474  {
475  QgsPolyline theLine = geom->asPolyline();
476  QgsPolyline::const_iterator line_it = theLine.constBegin();
477  for ( ; line_it != theLine.constEnd(); ++line_it )
478  {
479  if ( addTopologicalPoints( *line_it ) != 0 )
480  {
481  returnVal = 2;
482  }
483  }
484  break;
485  }
486 
487  //multiline
490  {
491  QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
492  QgsPolyline currentPolyline;
493 
494  for ( int i = 0; i < theMultiLine.size(); ++i )
495  {
496  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
497  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
498  {
499  if ( addTopologicalPoints( *line_it ) != 0 )
500  {
501  returnVal = 2;
502  }
503  }
504  }
505  break;
506  }
507 
508  //polygon
509  case QGis::WKBPolygon25D:
510  case QGis::WKBPolygon:
511  {
512  QgsPolygon thePolygon = geom->asPolygon();
513  QgsPolyline currentRing;
514 
515  for ( int i = 0; i < thePolygon.size(); ++i )
516  {
517  currentRing = thePolygon.at( i );
518  QgsPolyline::const_iterator line_it = currentRing.constBegin();
519  for ( ; line_it != currentRing.constEnd(); ++line_it )
520  {
521  if ( addTopologicalPoints( *line_it ) != 0 )
522  {
523  returnVal = 2;
524  }
525  }
526  }
527  break;
528  }
529 
530  //multipolygon
533  {
534  QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
535  QgsPolygon currentPolygon;
536  QgsPolyline currentRing;
537 
538  for ( int i = 0; i < theMultiPolygon.size(); ++i )
539  {
540  currentPolygon = theMultiPolygon.at( i );
541  for ( int j = 0; j < currentPolygon.size(); ++j )
542  {
543  currentRing = currentPolygon.at( j );
544  QgsPolyline::const_iterator line_it = currentRing.constBegin();
545  for ( ; line_it != currentRing.constEnd(); ++line_it )
546  {
547  if ( addTopologicalPoints( *line_it ) != 0 )
548  {
549  returnVal = 2;
550  }
551  }
552  }
553  }
554  break;
555  }
556  default:
557  break;
558  }
559  return returnVal;
560 }
561 
562 
564 {
565  if ( !L->hasGeometryType() )
566  return 1;
567 
568  QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
569  //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
570  QMultiMap<double, QgsSnappingResult> vertexSnapResults;
571 
572  QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
573 
574  //work with a tolerance because coordinate projection may introduce some rounding
575  double threshold = 0.0000001;
576  if ( L->crs().mapUnits() == QGis::Meters )
577  {
578  threshold = 0.001;
579  }
580  else if ( L->crs().mapUnits() == QGis::Feet )
581  {
582  threshold = 0.0001;
583  }
584 
585 
586  if ( L->snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
587  {
588  return 2;
589  }
590 
591  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
592  QMultiMap<double, QgsSnappingResult>::const_iterator vertex_snap_it;
593  for ( ; snap_it != snapResults.constEnd(); ++snap_it )
594  {
595  //test if p is already a vertex of this geometry. If yes, don't insert it
596  bool vertexAlreadyExists = false;
597  if ( L->snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
598  {
599  continue;
600  }
601 
602  vertex_snap_it = vertexSnapResults.constBegin();
603  for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
604  {
605  if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
606  {
607  vertexAlreadyExists = true;
608  }
609  }
610 
611  if ( !vertexAlreadyExists )
612  {
613  filteredSnapResults.push_back( *snap_it );
614  }
615  }
616  insertSegmentVerticesForSnap( filteredSnapResults );
617  return 0;
618 }
619 
620 
621 int QgsVectorLayerEditUtils::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
622 {
623  if ( !L->hasGeometryType() )
624  return 1;
625 
626  int returnval = 0;
627  QgsPoint layerPoint;
628 
629  QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
630  for ( ; it != snapResults.constEnd(); ++it )
631  {
632  if ( it->snappedVertexNr == -1 ) // segment snap
633  {
634  layerPoint = it->snappedVertex;
635  if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
636  {
637  returnval = 3;
638  }
639  }
640  }
641  return returnval;
642 }
643 
644 
645 
646 
647 int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
648 {
649  if ( list.size() < 1 )
650  {
651  return 1;
652  }
653 
658 
659  for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
660  {
661  if ( it->x() < xmin )
662  {
663  xmin = it->x();
664  }
665  if ( it->x() > xmax )
666  {
667  xmax = it->x();
668  }
669  if ( it->y() < ymin )
670  {
671  ymin = it->y();
672  }
673  if ( it->y() > ymax )
674  {
675  ymax = it->y();
676  }
677  }
678 
679  return 0;
680 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
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:163
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.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:317
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:322
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.
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
Definition: qgsgeometry.h:33
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
QgsPolygon asPolygon() const
return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list ...
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 island polygon to a multipolygon feature.
void setAttributes(const QgsAttributes &attrs)
Definition: qgsfeature.h:144
WkbType
Used for symbology operations.
Definition: qgis.h:53
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:113
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
Definition: qgspoint.h:126
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 ...
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 (deep copy)
Definition: qgsfeature.cpp:134
QgsVectorLayerEditBuffer * editBuffer()
Buffer with uncommitted editing operations. Only valid after editing has been turned on...
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
int snapWithContext(const QgsPoint &startPoint, double snappingTolerance, QMultiMap< double, QgsSnappingResult > &snappingResults, QgsSnapper::SnappingType snap_to)
Snaps to segment or vertex within given tolerance.
bool geometry(QgsFeatureId fid, QgsGeometry &geometry)
fetch geometry from cache, return true if successful
int addTopologicalPoints(QgsGeometry *geom)
Adds topological points for every vertex of the geometry.
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:168
bool deleteVertex(int atVertex)
Deletes the vertex at the given position number and item (first number is index 0) Returns false if a...
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)...
QVector< QgsPolygon > QgsMultiPolygon
a collection of QgsPolygons that share a common collection of attributes
Definition: qgsgeometry.h:48
QList< int > QgsAttributeList
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
QGis::GeometryType geometryType() const
Returns point, line or polygon.
QVector< QgsPolyline > QgsPolygon
polygon: first item of the list is outer ring, inner rings (if any) start from second item ...
Definition: qgsgeometry.h:39
A class to represent a point.
Definition: qgspoint.h:63
int translate(double dx, double dy)
Translate this geometry by dx, dy.
QVector< QgsPolyline > QgsMultiPolyline
a collection of QgsPolylines that share a common collection of attributes
Definition: qgsgeometry.h:45
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)...
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
int addRing(const QList< QgsPoint > &ring)
Adds a ring to polygon/multipolygon features.
virtual QVariant defaultValue(int fieldId)
Returns the default value for field specified by fieldId.
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:173
qint64 QgsFeatureId
Definition: qgsfeature.h:30
double y() const
Definition: qgspoint.h:134
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
int addRing(const QList< QgsPoint > &ring)
Adds a new ring to this geometry.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
Represents a vector layer which manages a vector based data sets.
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:183
int max(int a, int b)
Definition: util.h:87
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:158
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:203
QgsVectorLayerEditUtils(QgsVectorLayer *layer)