QGIS API Documentation  2.8.6-Wien
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, QgsFeatureId* featureId )
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  if ( featureId )
129  *featureId = f.id();
130  //setModified( true, true );
131  break;
132  }
133  }
134 
135  return addRingReturnCode;
136 }
137 
138 
139 int QgsVectorLayerEditUtils::addPart( const QList<QgsPoint> &points, QgsFeatureId featureId )
140 {
141  if ( !L->hasGeometryType() )
142  return 6;
143 
144  QgsGeometry geometry;
145  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
146  {
147  // it's not in cache: let's fetch it from layer
148  QgsFeature f;
149  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
150  return 6; //geometry not found
151 
152  geometry = *f.geometry();
153  }
154 
155  int errorCode = geometry.addPart( points, L->geometryType() );
156  if ( errorCode == 0 )
157  {
158  L->editBuffer()->changeGeometry( featureId, &geometry );
159  }
160  return errorCode;
161 }
162 
163 
164 
165 int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
166 {
167  if ( !L->hasGeometryType() )
168  return 1;
169 
170  QgsGeometry geometry;
171  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
172  {
173  // it's not in cache: let's fetch it from layer
174  QgsFeature f;
175  if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
176  return 1; //geometry not found
177 
178  geometry = *f.geometry();
179  }
180 
181  int errorCode = geometry.translate( dx, dy );
182  if ( errorCode == 0 )
183  {
184  L->editBuffer()->changeGeometry( featureId, &geometry );
185  }
186  return errorCode;
187 }
188 
189 
190 int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
191 {
192  if ( !L->hasGeometryType() )
193  return 4;
194 
195  QgsFeatureList newFeatures; //store all the newly created features
196  double xMin, yMin, xMax, yMax;
197  QgsRectangle bBox; //bounding box of the split line
198  int returnCode = 0;
199  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
200  int numberOfSplittedFeatures = 0;
201 
202  QgsFeatureIterator features;
203  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
204 
205  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
206  {
207  features = L->selectedFeaturesIterator();
208  }
209  else //else consider all the feature that intersect the bounding box of the split line
210  {
211  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
212  {
213  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
214  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
215  }
216  else
217  {
218  return 1;
219  }
220 
221  if ( bBox.isEmpty() )
222  {
223  //if the bbox is a line, try to make a square out of it
224  if ( bBox.width() == 0.0 && bBox.height() > 0 )
225  {
226  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
227  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
228  }
229  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
230  {
231  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
232  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
233  }
234  else
235  {
236  //If we have a single point, we still create a non-null box
237  double bufferDistance = 0.000001;
238  if ( L->crs().geographicFlag() )
239  bufferDistance = 0.00000001;
240  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
241  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
242  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
243  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
244  }
245  }
246 
247  features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
248  }
249 
250  QgsFeature feat;
251  while ( features.nextFeature( feat ) )
252  {
253  if ( !feat.geometry() )
254  {
255  continue;
256  }
257  QList<QgsGeometry*> newGeometries;
258  QList<QgsPoint> topologyTestPoints;
259  QgsGeometry* newGeometry = 0;
260  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
261  if ( splitFunctionReturn == 0 )
262  {
263  //change this geometry
264  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
265 
266  //insert new features
267  for ( int i = 0; i < newGeometries.size(); ++i )
268  {
269  newGeometry = newGeometries.at( i );
270  QgsFeature newFeature;
271  newFeature.setGeometry( newGeometry );
272 
273  //use default value where possible for primary key (e.g. autoincrement),
274  //and use the value from the original (split) feature if not primary key
275  QgsAttributes newAttributes = feat.attributes();
276  foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
277  {
278  const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
279  if ( !defaultValue.isNull() )
280  {
281  newAttributes[ pkIdx ] = defaultValue;
282  }
283  else //try with NULL
284  {
285  newAttributes[ pkIdx ] = QVariant();
286  }
287  }
288 
289  newFeature.setAttributes( newAttributes );
290 
291  newFeatures.append( newFeature );
292  }
293 
294  if ( topologicalEditing )
295  {
296  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
297  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
298  {
299  addTopologicalPoints( *topol_it );
300  }
301  }
302  ++numberOfSplittedFeatures;
303  }
304  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
305  {
306  returnCode = splitFunctionReturn;
307  }
308  }
309 
310  if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
311  {
312  //There is a selection but no feature has been split.
313  //Maybe user forgot that only the selected features are split
314  returnCode = 4;
315  }
316 
317 
318  //now add the new features to this vectorlayer
319  L->editBuffer()->addFeatures( newFeatures );
320 
321  return returnCode;
322 }
323 
324 int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
325 {
326  if ( !L->hasGeometryType() )
327  return 4;
328 
329  double xMin, yMin, xMax, yMax;
330  QgsRectangle bBox; //bounding box of the split line
331  int returnCode = 0;
332  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
333  int numberOfSplittedParts = 0;
334 
335  QgsFeatureIterator fit;
336 
337  if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
338  {
339  fit = L->selectedFeaturesIterator();
340  }
341  else //else consider all the feature that intersect the bounding box of the split line
342  {
343  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
344  {
345  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
346  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
347  }
348  else
349  {
350  return 1;
351  }
352 
353  if ( bBox.isEmpty() )
354  {
355  //if the bbox is a line, try to make a square out of it
356  if ( bBox.width() == 0.0 && bBox.height() > 0 )
357  {
358  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
359  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
360  }
361  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
362  {
363  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
364  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
365  }
366  else
367  {
368  //If we have a single point, we still create a non-null box
369  double bufferDistance = 0.000001;
370  if ( L->crs().geographicFlag() )
371  bufferDistance = 0.00000001;
372  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
373  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
374  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
375  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
376  }
377  }
378 
379  fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
380  }
381 
382  int addPartRet = 0;
383 
384  QgsFeature feat;
385  while ( fit.nextFeature( feat ) )
386  {
387  QList<QgsGeometry*> newGeometries;
388  QList<QgsPoint> topologyTestPoints;
389  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
390  if ( splitFunctionReturn == 0 )
391  {
392  //add new parts
393  for ( int i = 0; i < newGeometries.size(); ++i )
394  {
395  addPartRet = feat.geometry()->addPart( newGeometries.at( i ) );
396  if ( addPartRet )
397  break;
398  }
399 
400  // For test only: Exception already thrown here...
401  // feat.geometry()->asWkb();
402 
403  if ( !addPartRet )
404  {
405  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
406  }
407  else
408  {
409  // Test addPartRet
410  switch ( addPartRet )
411  {
412  case 1:
413  QgsDebugMsg( "Not a multipolygon" );
414  break;
415 
416  case 2:
417  QgsDebugMsg( "Not a valid geometry" );
418  break;
419 
420  case 3:
421  QgsDebugMsg( "New polygon ring" );
422  break;
423  }
424  }
425  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
426 
427  if ( topologicalEditing )
428  {
429  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
430  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
431  {
432  addTopologicalPoints( *topol_it );
433  }
434  }
435  ++numberOfSplittedParts;
436  }
437  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
438  {
439  returnCode = splitFunctionReturn;
440  }
441 
442  qDeleteAll( newGeometries );
443  }
444 
445  if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0 && returnCode == 0 )
446  {
447  //There is a selection but no feature has been split.
448  //Maybe user forgot that only the selected features are split
449  returnCode = 4;
450  }
451 
452  return returnCode;
453 }
454 
455 
457 {
458  if ( !L->hasGeometryType() )
459  return 1;
460 
461  if ( !geom )
462  {
463  return 1;
464  }
465 
466  int returnVal = 0;
467 
468  QGis::WkbType wkbType = geom->wkbType();
469 
470  switch ( wkbType )
471  {
472  //line
474  case QGis::WKBLineString:
475  {
476  QgsPolyline theLine = geom->asPolyline();
477  QgsPolyline::const_iterator line_it = theLine.constBegin();
478  for ( ; line_it != theLine.constEnd(); ++line_it )
479  {
480  if ( addTopologicalPoints( *line_it ) != 0 )
481  {
482  returnVal = 2;
483  }
484  }
485  break;
486  }
487 
488  //multiline
491  {
492  QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
493  QgsPolyline currentPolyline;
494 
495  for ( int i = 0; i < theMultiLine.size(); ++i )
496  {
497  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
498  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
499  {
500  if ( addTopologicalPoints( *line_it ) != 0 )
501  {
502  returnVal = 2;
503  }
504  }
505  }
506  break;
507  }
508 
509  //polygon
510  case QGis::WKBPolygon25D:
511  case QGis::WKBPolygon:
512  {
513  QgsPolygon thePolygon = geom->asPolygon();
514  QgsPolyline currentRing;
515 
516  for ( int i = 0; i < thePolygon.size(); ++i )
517  {
518  currentRing = thePolygon.at( i );
519  QgsPolyline::const_iterator line_it = currentRing.constBegin();
520  for ( ; line_it != currentRing.constEnd(); ++line_it )
521  {
522  if ( addTopologicalPoints( *line_it ) != 0 )
523  {
524  returnVal = 2;
525  }
526  }
527  }
528  break;
529  }
530 
531  //multipolygon
534  {
535  QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
536  QgsPolygon currentPolygon;
537  QgsPolyline currentRing;
538 
539  for ( int i = 0; i < theMultiPolygon.size(); ++i )
540  {
541  currentPolygon = theMultiPolygon.at( i );
542  for ( int j = 0; j < currentPolygon.size(); ++j )
543  {
544  currentRing = currentPolygon.at( j );
545  QgsPolyline::const_iterator line_it = currentRing.constBegin();
546  for ( ; line_it != currentRing.constEnd(); ++line_it )
547  {
548  if ( addTopologicalPoints( *line_it ) != 0 )
549  {
550  returnVal = 2;
551  }
552  }
553  }
554  }
555  break;
556  }
557  default:
558  break;
559  }
560  return returnVal;
561 }
562 
563 
565 {
566  if ( !L->hasGeometryType() )
567  return 1;
568 
569  QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
570  //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
571  QMultiMap<double, QgsSnappingResult> vertexSnapResults;
572 
573  QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
574 
575  //work with a tolerance because coordinate projection may introduce some rounding
576  double threshold = 0.0000001;
577  if ( L->crs().mapUnits() == QGis::Meters )
578  {
579  threshold = 0.001;
580  }
581  else if ( L->crs().mapUnits() == QGis::Feet )
582  {
583  threshold = 0.0001;
584  }
585 
586 
587  if ( L->snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
588  {
589  return 2;
590  }
591 
592  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
593  QMultiMap<double, QgsSnappingResult>::const_iterator vertex_snap_it;
594  for ( ; snap_it != snapResults.constEnd(); ++snap_it )
595  {
596  //test if p is already a vertex of this geometry. If yes, don't insert it
597  bool vertexAlreadyExists = false;
598  if ( L->snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
599  {
600  continue;
601  }
602 
603  vertex_snap_it = vertexSnapResults.constBegin();
604  for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
605  {
606  if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
607  {
608  vertexAlreadyExists = true;
609  }
610  }
611 
612  if ( !vertexAlreadyExists )
613  {
614  filteredSnapResults.push_back( *snap_it );
615  }
616  }
617  insertSegmentVerticesForSnap( filteredSnapResults );
618  return 0;
619 }
620 
621 
622 int QgsVectorLayerEditUtils::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
623 {
624  if ( !L->hasGeometryType() )
625  return 1;
626 
627  int returnval = 0;
628  QgsPoint layerPoint;
629 
630  QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
631  for ( ; it != snapResults.constEnd(); ++it )
632  {
633  if ( it->snappedVertexNr == -1 ) // segment snap
634  {
635  layerPoint = it->snappedVertex;
636  if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
637  {
638  returnval = 3;
639  }
640  }
641  }
642  return returnval;
643 }
644 
645 
646 
647 
648 int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
649 {
650  if ( list.size() < 1 )
651  {
652  return 1;
653  }
654 
659 
660  for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
661  {
662  if ( it->x() < xmin )
663  {
664  xmin = it->x();
665  }
666  if ( it->x() > xmax )
667  {
668  xmax = it->x();
669  }
670  if ( it->y() < ymin )
671  {
672  ymin = it->y();
673  }
674  if ( it->y() > ymax )
675  {
676  ymax = it->y();
677  }
678  }
679 
680  return 0;
681 }
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
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.
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:360
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:365
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:187
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:156
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&#39;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:185
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)...
int addRing(const QList< QgsPoint > &ring, QgsFeatureId *featureId=0)
Adds a ring to polygon/multipolygon features.
bool hasGeometryType() const
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
virtual QVariant defaultValue(int fieldId)
Returns the default value for field specified by fieldId.
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&#39;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
A vector of attributes.
Definition: qgsfeature.h:103
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
virtual bool changeGeometry(QgsFeatureId fid, QgsGeometry *geom)
change feature&#39;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)