QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties 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  QgsFeatureList featureList;
202  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
203 
204  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
205  {
206  featureList = L->selectedFeatures();
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  QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
247 
248  QgsFeature f;
249  while ( fit.nextFeature( f ) )
250  featureList << QgsFeature( f );
251  }
252 
253  QgsFeatureList::iterator select_it = featureList.begin();
254  for ( ; select_it != featureList.end(); ++select_it )
255  {
256  if ( !select_it->geometry() )
257  {
258  continue;
259  }
260  QList<QgsGeometry*> newGeometries;
261  QList<QgsPoint> topologyTestPoints;
262  QgsGeometry* newGeometry = 0;
263  splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
264  if ( splitFunctionReturn == 0 )
265  {
266  //change this geometry
267  L->editBuffer()->changeGeometry( select_it->id(), select_it->geometry() );
268 
269  //insert new features
270  for ( int i = 0; i < newGeometries.size(); ++i )
271  {
272  newGeometry = newGeometries.at( i );
273  QgsFeature newFeature;
274  newFeature.setGeometry( newGeometry );
275 
276  //use default value where possible for primary key (e.g. autoincrement),
277  //and use the value from the original (split) feature if not primary key
278  QgsAttributes newAttributes = select_it->attributes();
279  foreach ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
280  {
281  const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
282  if ( !defaultValue.isNull() )
283  {
284  newAttributes[ pkIdx ] = defaultValue;
285  }
286  else //try with NULL
287  {
288  newAttributes[ pkIdx ] = QVariant();
289  }
290  }
291 
292  newFeature.setAttributes( newAttributes );
293 
294  newFeatures.append( newFeature );
295  }
296 
297  if ( topologicalEditing )
298  {
299  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
300  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
301  {
302  addTopologicalPoints( *topol_it );
303  }
304  }
305  ++numberOfSplittedFeatures;
306  }
307  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
308  {
309  returnCode = splitFunctionReturn;
310  }
311  }
312 
313  if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
314  {
315  //There is a selection but no feature has been split.
316  //Maybe user forgot that only the selected features are split
317  returnCode = 4;
318  }
319 
320 
321  //now add the new features to this vectorlayer
322  L->editBuffer()->addFeatures( newFeatures );
323 
324  return returnCode;
325 }
326 
327 int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
328 {
329  if ( !L->hasGeometryType() )
330  return 4;
331 
332  double xMin, yMin, xMax, yMax;
333  QgsRectangle bBox; //bounding box of the split line
334  int returnCode = 0;
335  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
336  int numberOfSplittedParts = 0;
337 
338  QgsFeatureList featureList;
339  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();
340 
341  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
342  {
343  featureList = L->selectedFeatures();
344  }
345  else //else consider all the feature that intersect the bounding box of the split line
346  {
347  if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
348  {
349  bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
350  bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
351  }
352  else
353  {
354  return 1;
355  }
356 
357  if ( bBox.isEmpty() )
358  {
359  //if the bbox is a line, try to make a square out of it
360  if ( bBox.width() == 0.0 && bBox.height() > 0 )
361  {
362  bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
363  bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
364  }
365  else if ( bBox.height() == 0.0 && bBox.width() > 0 )
366  {
367  bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
368  bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
369  }
370  else
371  {
372  //If we have a single point, we still create a non-null box
373  double bufferDistance = 0.000001;
374  if ( L->crs().geographicFlag() )
375  bufferDistance = 0.00000001;
376  bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
377  bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
378  bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
379  bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
380  }
381  }
382 
383  QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
384 
385  QgsFeature f;
386  while ( fit.nextFeature( f ) )
387  featureList << QgsFeature( f );
388  }
389 
390  int addPartRet = 0;
391  foreach ( const QgsFeature& feat, featureList )
392  {
393  QList<QgsGeometry*> newGeometries;
394  QList<QgsPoint> topologyTestPoints;
395  splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
396  if ( splitFunctionReturn == 0 )
397  {
398  //add new parts
399  for ( int i = 0; i < newGeometries.size(); ++i )
400  {
401  addPartRet = feat.geometry()->addPart( newGeometries.at( i ) );
402  if ( addPartRet )
403  break;
404  }
405 
406  // For test only: Exception already thrown here...
407  // feat.geometry()->asWkb();
408 
409  if ( !addPartRet )
410  {
411  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
412  }
413  else
414  {
415  // Test addPartRet
416  switch ( addPartRet )
417  {
418  case 1:
419  QgsDebugMsg( "Not a multipolygon" );
420  break;
421 
422  case 2:
423  QgsDebugMsg( "Not a valid geometry" );
424  break;
425 
426  case 3:
427  QgsDebugMsg( "New polygon ring" );
428  break;
429  }
430  }
431  L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );
432 
433  if ( topologicalEditing )
434  {
435  QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
436  for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
437  {
438  addTopologicalPoints( *topol_it );
439  }
440  }
441  ++numberOfSplittedParts;
442  }
443  else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
444  {
445  returnCode = splitFunctionReturn;
446  }
447 
448  qDeleteAll( newGeometries );
449  }
450 
451  if ( numberOfSplittedParts == 0 && selectedIds.size() > 0 && returnCode == 0 )
452  {
453  //There is a selection but no feature has been split.
454  //Maybe user forgot that only the selected features are split
455  returnCode = 4;
456  }
457 
458  return returnCode;
459 }
460 
461 
463 {
464  if ( !L->hasGeometryType() )
465  return 1;
466 
467  if ( !geom )
468  {
469  return 1;
470  }
471 
472  int returnVal = 0;
473 
474  QGis::WkbType wkbType = geom->wkbType();
475 
476  switch ( wkbType )
477  {
478  //line
480  case QGis::WKBLineString:
481  {
482  QgsPolyline theLine = geom->asPolyline();
483  QgsPolyline::const_iterator line_it = theLine.constBegin();
484  for ( ; line_it != theLine.constEnd(); ++line_it )
485  {
486  if ( addTopologicalPoints( *line_it ) != 0 )
487  {
488  returnVal = 2;
489  }
490  }
491  break;
492  }
493 
494  //multiline
497  {
498  QgsMultiPolyline theMultiLine = geom->asMultiPolyline();
499  QgsPolyline currentPolyline;
500 
501  for ( int i = 0; i < theMultiLine.size(); ++i )
502  {
503  QgsPolyline::const_iterator line_it = currentPolyline.constBegin();
504  for ( ; line_it != currentPolyline.constEnd(); ++line_it )
505  {
506  if ( addTopologicalPoints( *line_it ) != 0 )
507  {
508  returnVal = 2;
509  }
510  }
511  }
512  break;
513  }
514 
515  //polygon
516  case QGis::WKBPolygon25D:
517  case QGis::WKBPolygon:
518  {
519  QgsPolygon thePolygon = geom->asPolygon();
520  QgsPolyline currentRing;
521 
522  for ( int i = 0; i < thePolygon.size(); ++i )
523  {
524  currentRing = thePolygon.at( i );
525  QgsPolyline::const_iterator line_it = currentRing.constBegin();
526  for ( ; line_it != currentRing.constEnd(); ++line_it )
527  {
528  if ( addTopologicalPoints( *line_it ) != 0 )
529  {
530  returnVal = 2;
531  }
532  }
533  }
534  break;
535  }
536 
537  //multipolygon
540  {
541  QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon();
542  QgsPolygon currentPolygon;
543  QgsPolyline currentRing;
544 
545  for ( int i = 0; i < theMultiPolygon.size(); ++i )
546  {
547  currentPolygon = theMultiPolygon.at( i );
548  for ( int j = 0; j < currentPolygon.size(); ++j )
549  {
550  currentRing = currentPolygon.at( j );
551  QgsPolyline::const_iterator line_it = currentRing.constBegin();
552  for ( ; line_it != currentRing.constEnd(); ++line_it )
553  {
554  if ( addTopologicalPoints( *line_it ) != 0 )
555  {
556  returnVal = 2;
557  }
558  }
559  }
560  }
561  break;
562  }
563  default:
564  break;
565  }
566  return returnVal;
567 }
568 
569 
571 {
572  if ( !L->hasGeometryType() )
573  return 1;
574 
575  QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
576  //we also need to snap to vertex to make sure the vertex does not already exist in this geometry
577  QMultiMap<double, QgsSnappingResult> vertexSnapResults;
578 
579  QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices
580 
581  //work with a tolerance because coordinate projection may introduce some rounding
582  double threshold = 0.0000001;
583  if ( L->crs().mapUnits() == QGis::Meters )
584  {
585  threshold = 0.001;
586  }
587  else if ( L->crs().mapUnits() == QGis::Feet )
588  {
589  threshold = 0.0001;
590  }
591 
592 
593  if ( L->snapWithContext( p, threshold, snapResults, QgsSnapper::SnapToSegment ) != 0 )
594  {
595  return 2;
596  }
597 
598  QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();
599  QMultiMap<double, QgsSnappingResult>::const_iterator vertex_snap_it;
600  for ( ; snap_it != snapResults.constEnd(); ++snap_it )
601  {
602  //test if p is already a vertex of this geometry. If yes, don't insert it
603  bool vertexAlreadyExists = false;
604  if ( L->snapWithContext( p, threshold, vertexSnapResults, QgsSnapper::SnapToVertex ) != 0 )
605  {
606  continue;
607  }
608 
609  vertex_snap_it = vertexSnapResults.constBegin();
610  for ( ; vertex_snap_it != vertexSnapResults.constEnd(); ++vertex_snap_it )
611  {
612  if ( snap_it.value().snappedAtGeometry == vertex_snap_it.value().snappedAtGeometry )
613  {
614  vertexAlreadyExists = true;
615  }
616  }
617 
618  if ( !vertexAlreadyExists )
619  {
620  filteredSnapResults.push_back( *snap_it );
621  }
622  }
623  insertSegmentVerticesForSnap( filteredSnapResults );
624  return 0;
625 }
626 
627 
628 int QgsVectorLayerEditUtils::insertSegmentVerticesForSnap( const QList<QgsSnappingResult>& snapResults )
629 {
630  if ( !L->hasGeometryType() )
631  return 1;
632 
633  int returnval = 0;
634  QgsPoint layerPoint;
635 
636  QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
637  for ( ; it != snapResults.constEnd(); ++it )
638  {
639  if ( it->snappedVertexNr == -1 ) // segment snap
640  {
641  layerPoint = it->snappedVertex;
642  if ( !insertVertex( layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr ) )
643  {
644  returnval = 3;
645  }
646  }
647  }
648  return returnval;
649 }
650 
651 
652 
653 
654 int QgsVectorLayerEditUtils::boundingBoxFromPointList( const QList<QgsPoint>& list, double& xmin, double& ymin, double& xmax, double& ymax ) const
655 {
656  if ( list.size() < 1 )
657  {
658  return 1;
659  }
660 
665 
666  for ( QList<QgsPoint>::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
667  {
668  if ( it->x() < xmin )
669  {
670  xmin = it->x();
671  }
672  if ( it->x() > xmax )
673  {
674  xmax = it->x();
675  }
676  if ( it->y() < ymin )
677  {
678  ymin = it->y();
679  }
680  if ( it->y() > ymax )
681  {
682  ymax = it->y();
683  }
684  }
685 
686  return 0;
687 }
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.
QgsFeatureList selectedFeatures()
Get a copy of the user-selected features.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:169
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:194
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:325
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:330
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:38
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:110
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:199
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
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:174
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:53
QList< int > QgsAttributeList
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:44
A class to represent a point geometry.
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:50
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:179
qint64 QgsFeatureId
Definition: qgsfeature.h:30
double y() const
Definition: qgspoint.h:118
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:204
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.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:189
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:164
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:209
QgsVectorLayerEditUtils(QgsVectorLayer *layer)