Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgsgeometryanalyzer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometryanalyzer.cpp - QGIS Tools for vector geometry analysis
3  -------------------
4  begin : 19 March 2009
5  copyright : (C) Carson Farmer
6  email : carson.farmer@gmail.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 /* $Id: qgis.h 9774 2008-12-12 05:41:24Z timlinux $ */
18 
19 #include "qgsgeometryanalyzer.h"
20 
21 #include "qgsapplication.h"
22 #include "qgsfield.h"
23 #include "qgsfeature.h"
24 #include "qgslogger.h"
26 #include "qgsvectorfilewriter.h"
27 #include "qgsvectordataprovider.h"
28 #include "qgsdistancearea.h"
29 #include <QProgressDialog>
30 
31 bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer, const QString& shapefileName,
32  double tolerance, bool onlySelectedFeatures, QProgressDialog* p )
33 {
34  if ( !layer )
35  {
36  return false;
37  }
38 
39  QgsVectorDataProvider* dp = layer->dataProvider();
40  if ( !dp )
41  {
42  return false;
43  }
44 
45  QGis::WkbType outputType = dp->geometryType();
46  const QgsCoordinateReferenceSystem crs = layer->crs();
47 
48  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
49  QgsFeature currentFeature;
50 
51  //take only selection
52  if ( onlySelectedFeatures )
53  {
54  //use QgsVectorLayer::featureAtId
55  const QgsFeatureIds selection = layer->selectedFeaturesIds();
56  if ( p )
57  {
58  p->setMaximum( selection.size() );
59  }
60 
61  int processedFeatures = 0;
62  QgsFeatureIds::const_iterator it = selection.constBegin();
63  for ( ; it != selection.constEnd(); ++it )
64  {
65  if ( p )
66  {
67  p->setValue( processedFeatures );
68  }
69 
70  if ( p && p->wasCanceled() )
71  {
72  break;
73  }
74  if ( !layer->featureAtId( *it, currentFeature, true, true ) )
75  {
76  continue;
77  }
78  simplifyFeature( currentFeature, &vWriter, tolerance );
79  ++processedFeatures;
80  }
81 
82  if ( p )
83  {
84  p->setValue( selection.size() );
85  }
86  }
87  //take all features
88  else
89  {
90  layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
91 
92 
93  int featureCount = layer->featureCount();
94  if ( p )
95  {
96  p->setMaximum( featureCount );
97  }
98  int processedFeatures = 0;
99 
100  while ( layer->nextFeature( currentFeature ) )
101  {
102  if ( p )
103  {
104  p->setValue( processedFeatures );
105  }
106  if ( p && p->wasCanceled() )
107  {
108  break;
109  }
110  simplifyFeature( currentFeature, &vWriter, tolerance );
111  ++processedFeatures;
112  }
113  if ( p )
114  {
115  p->setValue( featureCount );
116  }
117  }
118 
119  return true;
120 }
121 
123 {
124  QgsGeometry* featureGeometry = f.geometry();
125  QgsGeometry* tmpGeometry = 0;
126 
127  if ( !featureGeometry )
128  {
129  return;
130  }
131  // simplify feature
132  tmpGeometry = featureGeometry->simplify( tolerance );
133 
134  QgsFeature newFeature;
135  newFeature.setGeometry( tmpGeometry );
136  newFeature.setAttributeMap( f.attributeMap() );
137 
138  //add it to vector file writer
139  if ( vfw )
140  {
141  vfw->addFeature( newFeature );
142  }
143 }
144 
145 bool QgsGeometryAnalyzer::centroids( QgsVectorLayer* layer, const QString& shapefileName,
146  bool onlySelectedFeatures, QProgressDialog* p )
147 {
148  if ( !layer )
149  {
150  return false;
151  }
152 
153  QgsVectorDataProvider* dp = layer->dataProvider();
154  if ( !dp )
155  {
156  return false;
157  }
158 
159  QGis::WkbType outputType = QGis::WKBPoint;
160  const QgsCoordinateReferenceSystem crs = layer->crs();
161 
162  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
163  QgsFeature currentFeature;
164 
165  //take only selection
166  if ( onlySelectedFeatures )
167  {
168  //use QgsVectorLayer::featureAtId
169  const QgsFeatureIds selection = layer->selectedFeaturesIds();
170  if ( p )
171  {
172  p->setMaximum( selection.size() );
173  }
174 
175  int processedFeatures = 0;
176  QgsFeatureIds::const_iterator it = selection.constBegin();
177  for ( ; it != selection.constEnd(); ++it )
178  {
179  if ( p )
180  {
181  p->setValue( processedFeatures );
182  }
183 
184  if ( p && p->wasCanceled() )
185  {
186  break;
187  }
188  if ( !layer->featureAtId( *it, currentFeature, true, true ) )
189  {
190  continue;
191  }
192  centroidFeature( currentFeature, &vWriter );
193  ++processedFeatures;
194  }
195 
196  if ( p )
197  {
198  p->setValue( selection.size() );
199  }
200  }
201  //take all features
202  else
203  {
204  layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
205 
206  int featureCount = layer->featureCount();
207  if ( p )
208  {
209  p->setMaximum( featureCount );
210  }
211  int processedFeatures = 0;
212 
213  while ( layer->nextFeature( currentFeature ) )
214  {
215  if ( p )
216  {
217  p->setValue( processedFeatures );
218  }
219  if ( p && p->wasCanceled() )
220  {
221  break;
222  }
223  centroidFeature( currentFeature, &vWriter );
224  ++processedFeatures;
225  }
226  if ( p )
227  {
228  p->setValue( featureCount );
229  }
230  }
231 
232  return true;
233 }
234 
235 
237 {
238  QgsGeometry* featureGeometry = f.geometry();
239  QgsGeometry* tmpGeometry = 0;
240 
241  if ( !featureGeometry )
242  {
243  return;
244  }
245 
246  tmpGeometry = featureGeometry->centroid();
247 
248  QgsFeature newFeature;
249  newFeature.setGeometry( tmpGeometry );
250  newFeature.setAttributeMap( f.attributeMap() );
251 
252  //add it to vector file writer
253  if ( vfw )
254  {
255  vfw->addFeature( newFeature );
256  }
257 }
258 
259 bool QgsGeometryAnalyzer::extent( QgsVectorLayer* layer, const QString& shapefileName,
260  bool onlySelectedFeatures, QProgressDialog* p )
261 {
262  if ( !layer )
263  {
264  return false;
265  }
266 
267  QgsVectorDataProvider* dp = layer->dataProvider();
268  if ( !dp )
269  {
270  return false;
271  }
272 
273  QGis::WkbType outputType = QGis::WKBPolygon;
274  const QgsCoordinateReferenceSystem crs = layer->crs();
275 
276  QgsFieldMap fields;
277  fields.insert( 0 , QgsField( QString( "MINX" ), QVariant::Double ) );
278  fields.insert( 1 , QgsField( QString( "MINY" ), QVariant::Double ) );
279  fields.insert( 2 , QgsField( QString( "MAXX" ), QVariant::Double ) );
280  fields.insert( 3 , QgsField( QString( "MAXY" ), QVariant::Double ) );
281  fields.insert( 4 , QgsField( QString( "CNTX" ), QVariant::Double ) );
282  fields.insert( 5 , QgsField( QString( "CNTY" ), QVariant::Double ) );
283  fields.insert( 6 , QgsField( QString( "AREA" ), QVariant::Double ) );
284  fields.insert( 7 , QgsField( QString( "PERIM" ), QVariant::Double ) );
285  fields.insert( 8 , QgsField( QString( "HEIGHT" ), QVariant::Double ) );
286  fields.insert( 9 , QgsField( QString( "WIDTH" ), QVariant::Double ) );
287 
288  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
289 
290  QgsRectangle rect;
291  if ( onlySelectedFeatures ) // take only selection
292  {
293  rect = layer->boundingBoxOfSelected();
294  }
295  else
296  {
297  rect = layer->extent();
298  }
299 
300  double minx = rect.xMinimum();
301  double miny = rect.yMinimum();
302  double maxx = rect.xMaximum();
303  double maxy = rect.yMaximum();
304  double height = rect.height();
305  double width = rect.width();
306  double cntx = minx + ( width / 2.0 );
307  double cnty = miny + ( height / 2.0 );
308  double area = width * height;
309  double perim = ( 2 * width ) + ( 2 * height );
310 
311  QgsFeature feat;
312  QgsAttributeMap map;
313  map.insert( 0 , QVariant( minx ) );
314  map.insert( 1 , QVariant( miny ) );
315  map.insert( 2 , QVariant( maxx ) );
316  map.insert( 3 , QVariant( maxy ) );
317  map.insert( 4 , QVariant( cntx ) );
318  map.insert( 5 , QVariant( cnty ) );
319  map.insert( 6 , QVariant( area ) );
320  map.insert( 7 , QVariant( perim ) );
321  map.insert( 8 , QVariant( height ) );
322  map.insert( 9 , QVariant( width ) );
323  feat.setAttributeMap( map );
324  feat.setGeometry( QgsGeometry::fromRect( rect ) );
325  vWriter.addFeature( feat );
326  return true;
327 }
328 
330 {
331  QList<double> list;
332  double perim;
333  if ( mpGeometry->wkbType() == QGis::WKBPoint )
334  {
335  QgsPoint pt = mpGeometry->asPoint();
336  list.append( pt.x() );
337  list.append( pt.y() );
338  }
339  else
340  {
341  QgsDistanceArea measure;
342  list.append( measure.measure( mpGeometry ) );
343  if ( mpGeometry->type() == QGis::Polygon )
344  {
345  perim = perimeterMeasure( mpGeometry, measure );
346  list.append( perim );
347  }
348  }
349  return list;
350 }
351 
353 {
354  double value = 0.00;
355  if ( geometry->isMultipart() )
356  {
357  QgsMultiPolygon poly = geometry->asMultiPolygon();
358  QgsMultiPolygon::iterator it;
359  QgsPolygon::iterator jt;
360  for ( it = poly.begin(); it != poly.end(); ++it )
361  {
362  for ( jt = it->begin(); jt != it->end(); ++jt )
363  {
364  value = value + measure.measure( QgsGeometry::fromPolyline( *jt ) );
365  }
366  }
367  }
368  else
369  {
370  QgsPolygon::iterator jt;
371  QgsPolygon poly = geometry->asPolygon();
372  for ( jt = poly.begin(); jt != poly.end(); ++jt )
373  {
374  value = value + measure.measure( QgsGeometry::fromPolyline( *jt ) );
375  }
376  }
377  return value;
378 }
379 
380 bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName,
381  bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
382 {
383  if ( !layer )
384  {
385  return false;
386  }
387  QgsVectorDataProvider* dp = layer->dataProvider();
388  if ( !dp )
389  {
390  return false;
391  }
392  bool useField = false;
393  if ( uniqueIdField == -1 )
394  {
395  uniqueIdField = 0;
396  }
397  else
398  {
399  useField = true;
400  }
401  QgsFieldMap fields;
402  fields.insert( 0 , QgsField( QString( "UID" ), QVariant::String ) );
403  fields.insert( 1 , QgsField( QString( "AREA" ), QVariant::Double ) );
404  fields.insert( 2 , QgsField( QString( "PERIM" ), QVariant::Double ) );
405 
406  QGis::WkbType outputType = QGis::WKBPolygon;
407  const QgsCoordinateReferenceSystem crs = layer->crs();
408 
409  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
410  QgsFeature currentFeature;
411  QgsGeometry* dissolveGeometry = 0; //dissolve geometry
412  QMultiMap<QString, int> map;
413 
414  if ( onlySelectedFeatures )
415  {
416  //use QgsVectorLayer::featureAtId
417  const QgsFeatureIds selection = layer->selectedFeaturesIds();
418  QgsFeatureIds::const_iterator it = selection.constBegin();
419  for ( ; it != selection.constEnd(); ++it )
420  {
421 #if 0
422  if ( p )
423  {
424  p->setValue( processedFeatures );
425  }
426  if ( p && p->wasCanceled() )
427  {
428  // break; // it may be better to do something else here?
429  return false;
430  }
431 #endif
432  if ( !layer->featureAtId( *it, currentFeature, true, true ) )
433  {
434  continue;
435  }
436  map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
437  }
438  }
439  else
440  {
441  layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
442  while ( layer->nextFeature( currentFeature ) )
443  {
444 #if 0
445  if ( p )
446  {
447  p->setValue( processedFeatures );
448  }
449  if ( p && p->wasCanceled() )
450  {
451  // break; // it may be better to do something else here?
452  return false;
453  }
454 #endif
455  map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
456  }
457  }
458 
459  QMultiMap<QString, int>::const_iterator jt = map.constBegin();
460  while ( jt != map.constEnd() )
461  {
462  QString currentKey = jt.key();
463  int processedFeatures = 0;
464  //take only selection
465  if ( onlySelectedFeatures )
466  {
467  //use QgsVectorLayer::featureAtId
468  const QgsFeatureIds selection = layer->selectedFeaturesIds();
469  if ( p )
470  {
471  p->setMaximum( selection.size() );
472  }
473  processedFeatures = 0;
474  while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
475  {
476  if ( p && p->wasCanceled() )
477  {
478  break;
479  }
480  if ( selection.contains( jt.value() ) )
481  {
482  if ( p )
483  {
484  p->setValue( processedFeatures );
485  }
486  if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
487  {
488  continue;
489  }
490  convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
491  ++processedFeatures;
492  }
493  ++jt;
494  }
495  QList<double> values;
496  if ( !dissolveGeometry )
497  {
498  QgsDebugMsg( "no dissolved geometry - should not happen" );
499  return false;
500  }
501  dissolveGeometry = dissolveGeometry->convexHull();
502  values = simpleMeasure( dissolveGeometry );
503  QgsAttributeMap attributeMap;
504  attributeMap.insert( 0 , QVariant( currentKey ) );
505  attributeMap.insert( 1 , values[ 0 ] );
506  attributeMap.insert( 2 , values[ 1 ] );
508  dissolveFeature.setAttributeMap( attributeMap );
509  dissolveFeature.setGeometry( dissolveGeometry );
510  vWriter.addFeature( dissolveFeature );
511  }
512  //take all features
513  else
514  {
515  int featureCount = layer->featureCount();
516  if ( p )
517  {
518  p->setMaximum( featureCount );
519  }
520  processedFeatures = 0;
521  while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
522  {
523  if ( p )
524  {
525  p->setValue( processedFeatures );
526  }
527 
528  if ( p && p->wasCanceled() )
529  {
530  break;
531  }
532  if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
533  {
534  continue;
535  }
536  convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
537  ++processedFeatures;
538  ++jt;
539  }
540  QList<double> values;
541  // QgsGeometry* tmpGeometry = 0;
542  if ( !dissolveGeometry )
543  {
544  QgsDebugMsg( "no dissolved geometry - should not happen" );
545  return false;
546  }
547  dissolveGeometry = dissolveGeometry->convexHull();
548  // values = simpleMeasure( tmpGeometry );
549  values = simpleMeasure( dissolveGeometry );
550  QgsAttributeMap attributeMap;
551  attributeMap.insert( 0 , QVariant( currentKey ) );
552  attributeMap.insert( 1 , QVariant( values[ 0 ] ) );
553  attributeMap.insert( 2 , QVariant( values[ 1 ] ) );
555  dissolveFeature.setAttributeMap( attributeMap );
556  dissolveFeature.setGeometry( dissolveGeometry );
557  vWriter.addFeature( dissolveFeature );
558  }
559  }
560  return true;
561 }
562 
563 
564 void QgsGeometryAnalyzer::convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry )
565 {
566  QgsGeometry* featureGeometry = f.geometry();
567  QgsGeometry* tmpGeometry = 0;
568  QgsGeometry* convexGeometry = 0;
569 
570  if ( !featureGeometry )
571  {
572  return;
573  }
574 
575  convexGeometry = featureGeometry->convexHull();
576 
577  if ( nProcessedFeatures == 0 )
578  {
579  *dissolveGeometry = convexGeometry;
580  }
581  else
582  {
583  tmpGeometry = *dissolveGeometry;
584  *dissolveGeometry = ( *dissolveGeometry )->combine( convexGeometry );
585  delete tmpGeometry;
586  delete convexGeometry;
587  }
588 }
589 
590 bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName,
591  bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
592 {
593  if ( !layer )
594  {
595  return false;
596  }
597  QgsVectorDataProvider* dp = layer->dataProvider();
598  if ( !dp )
599  {
600  return false;
601  }
602  bool useField = false;
603  if ( uniqueIdField == -1 )
604  {
605  uniqueIdField = 0;
606  }
607  else
608  {
609  useField = true;
610  }
611 
612  QGis::WkbType outputType = dp->geometryType();
613  const QgsCoordinateReferenceSystem crs = layer->crs();
614 
615  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
616  QgsFeature currentFeature;
617  QMultiMap<QString, int> map;
618 
619  if ( onlySelectedFeatures )
620  {
621  //use QgsVectorLayer::featureAtId
622  const QgsFeatureIds selection = layer->selectedFeaturesIds();
623  QgsFeatureIds::const_iterator it = selection.constBegin();
624  for ( ; it != selection.constEnd(); ++it )
625  {
626  if ( !layer->featureAtId( *it, currentFeature, true, true ) )
627  {
628  continue;
629  }
630  map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
631  }
632  }
633  else
634  {
635  layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
636  while ( layer->nextFeature( currentFeature ) )
637  {
638  map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
639  }
640  }
641 
642  QgsGeometry *dissolveGeometry = 0; //dissolve geometry
643  QMultiMap<QString, int>::const_iterator jt = map.constBegin();
644  QgsFeature outputFeature;
645  while ( jt != map.constEnd() )
646  {
647  QString currentKey = jt.key();
648  int processedFeatures = 0;
649  bool first = true;
650  //take only selection
651  if ( onlySelectedFeatures )
652  {
653  //use QgsVectorLayer::featureAtId
654  const QgsFeatureIds selection = layer->selectedFeaturesIds();
655  if ( p )
656  {
657  p->setMaximum( selection.size() );
658  }
659  while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
660  {
661  if ( p && p->wasCanceled() )
662  {
663  break;
664  }
665  if ( selection.contains( jt.value() ) )
666  {
667  if ( p )
668  {
669  p->setValue( processedFeatures );
670  }
671  if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
672  {
673  continue;
674  }
675  if ( first )
676  {
677  outputFeature.setAttributeMap( currentFeature.attributeMap() );
678  first = false;
679  }
680  dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
681  ++processedFeatures;
682  }
683  ++jt;
684  }
685  }
686  //take all features
687  else
688  {
689  int featureCount = layer->featureCount();
690  if ( p )
691  {
692  p->setMaximum( featureCount );
693  }
694  while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
695  {
696  if ( p )
697  {
698  p->setValue( processedFeatures );
699  }
700 
701  if ( p && p->wasCanceled() )
702  {
703  break;
704  }
705  if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
706  {
707  continue;
708  }
709  {
710  outputFeature.setAttributeMap( currentFeature.attributeMap() );
711  first = false;
712  }
713  dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
714  ++processedFeatures;
715  ++jt;
716  }
717  }
718  outputFeature.setGeometry( dissolveGeometry );
719  vWriter.addFeature( outputFeature );
720  }
721  return true;
722 }
723 
724 void QgsGeometryAnalyzer::dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry )
725 {
726  QgsGeometry* featureGeometry = f.geometry();
727 
728  if ( !featureGeometry )
729  {
730  return;
731  }
732 
733  if ( nProcessedFeatures == 0 )
734  {
735  int geomSize = featureGeometry->wkbSize();
736  *dissolveGeometry = new QgsGeometry();
737  unsigned char* wkb = new unsigned char[geomSize];
738  memcpy( wkb, featureGeometry->asWkb(), geomSize );
739  ( *dissolveGeometry )->fromWkb( wkb, geomSize );
740  }
741  else
742  {
743  *dissolveGeometry = ( *dissolveGeometry )->combine( featureGeometry );
744  }
745 }
746 
747 bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance,
748  bool onlySelectedFeatures, bool dissolve, int bufferDistanceField, QProgressDialog* p )
749 {
750  if ( !layer )
751  {
752  return false;
753  }
754 
755  QgsVectorDataProvider* dp = layer->dataProvider();
756  if ( !dp )
757  {
758  return false;
759  }
760 
761  QGis::WkbType outputType = QGis::WKBPolygon;
762  if ( dissolve )
763  {
764  outputType = QGis::WKBMultiPolygon;
765  }
766  const QgsCoordinateReferenceSystem crs = layer->crs();
767 
768  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
769  QgsFeature currentFeature;
770  QgsGeometry *dissolveGeometry = 0; //dissolve geometry (if dissolve enabled)
771 
772  //take only selection
773  if ( onlySelectedFeatures )
774  {
775  //use QgsVectorLayer::featureAtId
776  const QgsFeatureIds selection = layer->selectedFeaturesIds();
777  if ( p )
778  {
779  p->setMaximum( selection.size() );
780  }
781 
782  int processedFeatures = 0;
783  QgsFeatureIds::const_iterator it = selection.constBegin();
784  for ( ; it != selection.constEnd(); ++it )
785  {
786  if ( p )
787  {
788  p->setValue( processedFeatures );
789  }
790 
791  if ( p && p->wasCanceled() )
792  {
793  break;
794  }
795  if ( !layer->featureAtId( *it, currentFeature, true, true ) )
796  {
797  continue;
798  }
799  bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
800  ++processedFeatures;
801  }
802 
803  if ( p )
804  {
805  p->setValue( selection.size() );
806  }
807  }
808  //take all features
809  else
810  {
811  layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
812 
813 
814  int featureCount = layer->featureCount();
815  if ( p )
816  {
817  p->setMaximum( featureCount );
818  }
819  int processedFeatures = 0;
820 
821  while ( layer->nextFeature( currentFeature ) )
822  {
823  if ( p )
824  {
825  p->setValue( processedFeatures );
826  }
827  if ( p && p->wasCanceled() )
828  {
829  break;
830  }
831  bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
832  ++processedFeatures;
833  }
834  if ( p )
835  {
836  p->setValue( featureCount );
837  }
838  }
839 
840  if ( dissolve )
841  {
843  if ( !dissolveGeometry )
844  {
845  QgsDebugMsg( "no dissolved geometry - should not happen" );
846  return false;
847  }
848  dissolveFeature.setGeometry( dissolveGeometry );
849  vWriter.addFeature( dissolveFeature );
850  }
851  return true;
852 }
853 
854 void QgsGeometryAnalyzer::bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, bool dissolve,
855  QgsGeometry** dissolveGeometry, double bufferDistance, int bufferDistanceField )
856 {
857  double currentBufferDistance;
858  QgsGeometry* featureGeometry = f.geometry();
859  QgsGeometry* tmpGeometry = 0;
860  QgsGeometry* bufferGeometry = 0;
861 
862  if ( !featureGeometry )
863  {
864  return;
865  }
866 
867  //create buffer
868  if ( bufferDistanceField == -1 )
869  {
870  currentBufferDistance = bufferDistance;
871  }
872  else
873  {
874  currentBufferDistance = f.attributeMap()[bufferDistanceField].toDouble();
875  }
876  bufferGeometry = featureGeometry->buffer( currentBufferDistance, 5 );
877 
878  if ( dissolve )
879  {
880  if ( nProcessedFeatures == 0 )
881  {
882  *dissolveGeometry = bufferGeometry;
883  }
884  else
885  {
886  tmpGeometry = *dissolveGeometry;
887  *dissolveGeometry = ( *dissolveGeometry )->combine( bufferGeometry );
888  delete tmpGeometry;
889  delete bufferGeometry;
890  }
891  }
892  else //dissolve
893  {
894  QgsFeature newFeature;
895  newFeature.setGeometry( bufferGeometry );
896  newFeature.setAttributeMap( f.attributeMap() );
897 
898  //add it to vector file writer
899  if ( vfw )
900  {
901  vfw->addFeature( newFeature );
902  }
903  }
904 }