00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgsgeometryanalyzer.h"
00020
00021 #include "qgsapplication.h"
00022 #include "qgsfield.h"
00023 #include "qgsfeature.h"
00024 #include "qgslogger.h"
00025 #include "qgscoordinatereferencesystem.h"
00026 #include "qgsvectorfilewriter.h"
00027 #include "qgsvectordataprovider.h"
00028 #include "qgsdistancearea.h"
00029 #include <QProgressDialog>
00030
00031 bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer, const QString& shapefileName,
00032 double tolerance, bool onlySelectedFeatures, QProgressDialog* p )
00033 {
00034 if ( !layer )
00035 {
00036 return false;
00037 }
00038
00039 QgsVectorDataProvider* dp = layer->dataProvider();
00040 if ( !dp )
00041 {
00042 return false;
00043 }
00044
00045 QGis::WkbType outputType = dp->geometryType();
00046 const QgsCoordinateReferenceSystem crs = layer->srs();
00047
00048 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
00049 QgsFeature currentFeature;
00050
00051
00052 if ( onlySelectedFeatures )
00053 {
00054
00055 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00056 if ( p )
00057 {
00058 p->setMaximum( selection.size() );
00059 }
00060
00061 int processedFeatures = 0;
00062 QgsFeatureIds::const_iterator it = selection.constBegin();
00063 for ( ; it != selection.constEnd(); ++it )
00064 {
00065 if ( p )
00066 {
00067 p->setValue( processedFeatures );
00068 }
00069
00070 if ( p && p->wasCanceled() )
00071 {
00072 break;
00073 }
00074 if ( !layer->featureAtId( *it, currentFeature, true, true ) )
00075 {
00076 continue;
00077 }
00078 simplifyFeature( currentFeature, &vWriter, tolerance );
00079 ++processedFeatures;
00080 }
00081
00082 if ( p )
00083 {
00084 p->setValue( selection.size() );
00085 }
00086 }
00087
00088 else
00089 {
00090 layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
00091
00092
00093 int featureCount = layer->featureCount();
00094 if ( p )
00095 {
00096 p->setMaximum( featureCount );
00097 }
00098 int processedFeatures = 0;
00099
00100 while ( layer->nextFeature( currentFeature ) )
00101 {
00102 if ( p )
00103 {
00104 p->setValue( processedFeatures );
00105 }
00106 if ( p && p->wasCanceled() )
00107 {
00108 break;
00109 }
00110 simplifyFeature( currentFeature, &vWriter, tolerance );
00111 ++processedFeatures;
00112 }
00113 if ( p )
00114 {
00115 p->setValue( featureCount );
00116 }
00117 }
00118
00119 return true;
00120 }
00121
00122 void QgsGeometryAnalyzer::simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance )
00123 {
00124 QgsGeometry* featureGeometry = f.geometry();
00125 QgsGeometry* tmpGeometry = 0;
00126
00127 if ( !featureGeometry )
00128 {
00129 return;
00130 }
00131
00132 tmpGeometry = featureGeometry->simplify( tolerance );
00133
00134 QgsFeature newFeature;
00135 newFeature.setGeometry( tmpGeometry );
00136 newFeature.setAttributeMap( f.attributeMap() );
00137
00138
00139 if ( vfw )
00140 {
00141 vfw->addFeature( newFeature );
00142 }
00143 }
00144
00145 bool QgsGeometryAnalyzer::centroids( QgsVectorLayer* layer, const QString& shapefileName,
00146 bool onlySelectedFeatures, QProgressDialog* p )
00147 {
00148 if ( !layer )
00149 {
00150 return false;
00151 }
00152
00153 QgsVectorDataProvider* dp = layer->dataProvider();
00154 if ( !dp )
00155 {
00156 return false;
00157 }
00158
00159 QGis::WkbType outputType = QGis::WKBPoint;
00160 const QgsCoordinateReferenceSystem crs = layer->srs();
00161
00162 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
00163 QgsFeature currentFeature;
00164
00165
00166 if ( onlySelectedFeatures )
00167 {
00168
00169 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00170 if ( p )
00171 {
00172 p->setMaximum( selection.size() );
00173 }
00174
00175 int processedFeatures = 0;
00176 QgsFeatureIds::const_iterator it = selection.constBegin();
00177 for ( ; it != selection.constEnd(); ++it )
00178 {
00179 if ( p )
00180 {
00181 p->setValue( processedFeatures );
00182 }
00183
00184 if ( p && p->wasCanceled() )
00185 {
00186 break;
00187 }
00188 if ( !layer->featureAtId( *it, currentFeature, true, true ) )
00189 {
00190 continue;
00191 }
00192 centroidFeature( currentFeature, &vWriter );
00193 ++processedFeatures;
00194 }
00195
00196 if ( p )
00197 {
00198 p->setValue( selection.size() );
00199 }
00200 }
00201
00202 else
00203 {
00204 layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
00205
00206 int featureCount = layer->featureCount();
00207 if ( p )
00208 {
00209 p->setMaximum( featureCount );
00210 }
00211 int processedFeatures = 0;
00212
00213 while ( layer->nextFeature( currentFeature ) )
00214 {
00215 if ( p )
00216 {
00217 p->setValue( processedFeatures );
00218 }
00219 if ( p && p->wasCanceled() )
00220 {
00221 break;
00222 }
00223 centroidFeature( currentFeature, &vWriter );
00224 ++processedFeatures;
00225 }
00226 if ( p )
00227 {
00228 p->setValue( featureCount );
00229 }
00230 }
00231
00232 return true;
00233 }
00234
00235
00236 void QgsGeometryAnalyzer::centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw )
00237 {
00238 QgsGeometry* featureGeometry = f.geometry();
00239 QgsGeometry* tmpGeometry = 0;
00240
00241 if ( !featureGeometry )
00242 {
00243 return;
00244 }
00245
00246 tmpGeometry = featureGeometry->centroid();
00247
00248 QgsFeature newFeature;
00249 newFeature.setGeometry( tmpGeometry );
00250 newFeature.setAttributeMap( f.attributeMap() );
00251
00252
00253 if ( vfw )
00254 {
00255 vfw->addFeature( newFeature );
00256 }
00257 }
00258
00259 bool QgsGeometryAnalyzer::extent( QgsVectorLayer* layer, const QString& shapefileName,
00260 bool onlySelectedFeatures, QProgressDialog* p )
00261 {
00262 if ( !layer )
00263 {
00264 return false;
00265 }
00266
00267 QgsVectorDataProvider* dp = layer->dataProvider();
00268 if ( !dp )
00269 {
00270 return false;
00271 }
00272
00273 QGis::WkbType outputType = QGis::WKBPolygon;
00274 const QgsCoordinateReferenceSystem crs = layer->srs();
00275
00276 QgsFieldMap fields;
00277 fields.insert( 0 , QgsField( QString( "MINX" ), QVariant::Double ) );
00278 fields.insert( 1 , QgsField( QString( "MINY" ), QVariant::Double ) );
00279 fields.insert( 2 , QgsField( QString( "MAXX" ), QVariant::Double ) );
00280 fields.insert( 3 , QgsField( QString( "MAXY" ), QVariant::Double ) );
00281 fields.insert( 4 , QgsField( QString( "CNTX" ), QVariant::Double ) );
00282 fields.insert( 5 , QgsField( QString( "CNTY" ), QVariant::Double ) );
00283 fields.insert( 6 , QgsField( QString( "AREA" ), QVariant::Double ) );
00284 fields.insert( 7 , QgsField( QString( "PERIM" ), QVariant::Double ) );
00285 fields.insert( 8 , QgsField( QString( "HEIGHT" ), QVariant::Double ) );
00286 fields.insert( 9 , QgsField( QString( "WIDTH" ), QVariant::Double ) );
00287
00288 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
00289
00290 QgsRectangle rect;
00291 if ( onlySelectedFeatures )
00292 {
00293 rect = layer->boundingBoxOfSelected();
00294 }
00295 else
00296 {
00297 rect = layer->extent();
00298 }
00299
00300 double minx = rect.xMinimum();
00301 double miny = rect.yMinimum();
00302 double maxx = rect.xMaximum();
00303 double maxy = rect.yMaximum();
00304 double height = rect.height();
00305 double width = rect.width();
00306 double cntx = minx + ( width / 2.0 );
00307 double cnty = miny + ( height / 2.0 );
00308 double area = width * height;
00309 double perim = ( 2 * width ) + ( 2 * height );
00310
00311 QgsFeature feat;
00312 QgsAttributeMap map;
00313 map.insert( 0 , QVariant( minx ) );
00314 map.insert( 1 , QVariant( miny ) );
00315 map.insert( 2 , QVariant( maxx ) );
00316 map.insert( 3 , QVariant( maxy ) );
00317 map.insert( 4 , QVariant( cntx ) );
00318 map.insert( 5 , QVariant( cnty ) );
00319 map.insert( 6 , QVariant( area ) );
00320 map.insert( 7 , QVariant( perim ) );
00321 map.insert( 8 , QVariant( height ) );
00322 map.insert( 9 , QVariant( width ) );
00323 feat.setAttributeMap( map );
00324 feat.setGeometry( QgsGeometry::fromRect( rect ) );
00325 vWriter.addFeature( feat );
00326 return true;
00327 }
00328
00329 QList<double> QgsGeometryAnalyzer::simpleMeasure( QgsGeometry* mpGeometry )
00330 {
00331 QList<double> list;
00332 double perim;
00333 if ( mpGeometry->wkbType() == QGis::WKBPoint )
00334 {
00335 QgsPoint pt = mpGeometry->asPoint();
00336 list.append( pt.x() );
00337 list.append( pt.y() );
00338 }
00339 else
00340 {
00341 QgsDistanceArea measure;
00342 list.append( measure.measure( mpGeometry ) );
00343 if ( mpGeometry->type() == QGis::Polygon )
00344 {
00345 perim = perimeterMeasure( mpGeometry, measure );
00346 list.append( perim );
00347 }
00348 }
00349 return list;
00350 }
00351
00352 double QgsGeometryAnalyzer::perimeterMeasure( QgsGeometry* geometry, QgsDistanceArea& measure )
00353 {
00354 double value = 0.00;
00355 if ( geometry->isMultipart() )
00356 {
00357 QgsMultiPolygon poly = geometry->asMultiPolygon();
00358 QgsMultiPolygon::iterator it;
00359 QgsPolygon::iterator jt;
00360 for ( it = poly.begin(); it != poly.end(); ++it )
00361 {
00362 for ( jt = it->begin(); jt != it->end(); ++jt )
00363 {
00364 value = value + measure.measure( QgsGeometry::fromPolyline( *jt ) );
00365 }
00366 }
00367 }
00368 else
00369 {
00370 QgsPolygon::iterator jt;
00371 QgsPolygon poly = geometry->asPolygon();
00372 for ( jt = poly.begin(); jt != poly.end(); ++jt )
00373 {
00374 value = value + measure.measure( QgsGeometry::fromPolyline( *jt ) );
00375 }
00376 }
00377 return value;
00378 }
00379
00380 bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName,
00381 bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
00382 {
00383 if ( !layer )
00384 {
00385 return false;
00386 }
00387 QgsVectorDataProvider* dp = layer->dataProvider();
00388 if ( !dp )
00389 {
00390 return false;
00391 }
00392 bool useField = false;
00393 if ( uniqueIdField == -1 )
00394 {
00395 uniqueIdField = 0;
00396 }
00397 else
00398 {
00399 useField = true;
00400 }
00401 QgsFieldMap fields;
00402 fields.insert( 0 , QgsField( QString( "UID" ), QVariant::String ) );
00403 fields.insert( 1 , QgsField( QString( "AREA" ), QVariant::Double ) );
00404 fields.insert( 2 , QgsField( QString( "PERIM" ), QVariant::Double ) );
00405
00406 QGis::WkbType outputType = QGis::WKBPolygon;
00407 const QgsCoordinateReferenceSystem crs = layer->srs();
00408
00409 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
00410 QgsFeature currentFeature;
00411 QgsGeometry* dissolveGeometry = 0;
00412 QMultiMap<QString, int> map;
00413
00414 if ( onlySelectedFeatures )
00415 {
00416
00417 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00418 QgsFeatureIds::const_iterator it = selection.constBegin();
00419 for ( ; it != selection.constEnd(); ++it )
00420 {
00421 #if 0
00422 if ( p )
00423 {
00424 p->setValue( processedFeatures );
00425 }
00426 if ( p && p->wasCanceled() )
00427 {
00428
00429 return false;
00430 }
00431 #endif
00432 if ( !layer->featureAtId( *it, currentFeature, true, true ) )
00433 {
00434 continue;
00435 }
00436 map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
00437 }
00438 }
00439 else
00440 {
00441 layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
00442 while ( layer->nextFeature( currentFeature ) )
00443 {
00444 #if 0
00445 if ( p )
00446 {
00447 p->setValue( processedFeatures );
00448 }
00449 if ( p && p->wasCanceled() )
00450 {
00451
00452 return false;
00453 }
00454 #endif
00455 map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
00456 }
00457 }
00458
00459 QMultiMap<QString, int>::const_iterator jt = map.constBegin();
00460 while ( jt != map.constEnd() )
00461 {
00462 QString currentKey = jt.key();
00463 int processedFeatures = 0;
00464
00465 if ( onlySelectedFeatures )
00466 {
00467
00468 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00469 if ( p )
00470 {
00471 p->setMaximum( selection.size() );
00472 }
00473 processedFeatures = 0;
00474 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
00475 {
00476 if ( p && p->wasCanceled() )
00477 {
00478 break;
00479 }
00480 if ( selection.contains( jt.value() ) )
00481 {
00482 if ( p )
00483 {
00484 p->setValue( processedFeatures );
00485 }
00486 if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
00487 {
00488 continue;
00489 }
00490 convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
00491 ++processedFeatures;
00492 }
00493 ++jt;
00494 }
00495 QList<double> values;
00496 if ( !dissolveGeometry )
00497 {
00498 QgsDebugMsg( "no dissolved geometry - should not happen" );
00499 return false;
00500 }
00501 dissolveGeometry = dissolveGeometry->convexHull();
00502 values = simpleMeasure( dissolveGeometry );
00503 QgsAttributeMap attributeMap;
00504 attributeMap.insert( 0 , QVariant( currentKey ) );
00505 attributeMap.insert( 1 , values[ 0 ] );
00506 attributeMap.insert( 2 , values[ 1 ] );
00507 QgsFeature dissolveFeature;
00508 dissolveFeature.setAttributeMap( attributeMap );
00509 dissolveFeature.setGeometry( dissolveGeometry );
00510 vWriter.addFeature( dissolveFeature );
00511 }
00512
00513 else
00514 {
00515 int featureCount = layer->featureCount();
00516 if ( p )
00517 {
00518 p->setMaximum( featureCount );
00519 }
00520 processedFeatures = 0;
00521 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
00522 {
00523 if ( p )
00524 {
00525 p->setValue( processedFeatures );
00526 }
00527
00528 if ( p && p->wasCanceled() )
00529 {
00530 break;
00531 }
00532 if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
00533 {
00534 continue;
00535 }
00536 convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
00537 ++processedFeatures;
00538 ++jt;
00539 }
00540 QList<double> values;
00541
00542 if ( !dissolveGeometry )
00543 {
00544 QgsDebugMsg( "no dissolved geometry - should not happen" );
00545 return false;
00546 }
00547 dissolveGeometry = dissolveGeometry->convexHull();
00548
00549 values = simpleMeasure( dissolveGeometry );
00550 QgsAttributeMap attributeMap;
00551 attributeMap.insert( 0 , QVariant( currentKey ) );
00552 attributeMap.insert( 1 , QVariant( values[ 0 ] ) );
00553 attributeMap.insert( 2 , QVariant( values[ 1 ] ) );
00554 QgsFeature dissolveFeature;
00555 dissolveFeature.setAttributeMap( attributeMap );
00556 dissolveFeature.setGeometry( dissolveGeometry );
00557 vWriter.addFeature( dissolveFeature );
00558 }
00559 }
00560 return true;
00561 }
00562
00563
00564 void QgsGeometryAnalyzer::convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry )
00565 {
00566 QgsGeometry* featureGeometry = f.geometry();
00567 QgsGeometry* tmpGeometry = 0;
00568 QgsGeometry* convexGeometry = 0;
00569
00570 if ( !featureGeometry )
00571 {
00572 return;
00573 }
00574
00575 convexGeometry = featureGeometry->convexHull();
00576
00577 if ( nProcessedFeatures == 0 )
00578 {
00579 *dissolveGeometry = convexGeometry;
00580 }
00581 else
00582 {
00583 tmpGeometry = *dissolveGeometry;
00584 *dissolveGeometry = ( *dissolveGeometry )->combine( convexGeometry );
00585 delete tmpGeometry;
00586 delete convexGeometry;
00587 }
00588 }
00589
00590 bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName,
00591 bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
00592 {
00593 if ( !layer )
00594 {
00595 return false;
00596 }
00597 QgsVectorDataProvider* dp = layer->dataProvider();
00598 if ( !dp )
00599 {
00600 return false;
00601 }
00602 bool useField = false;
00603 if ( uniqueIdField == -1 )
00604 {
00605 uniqueIdField = 0;
00606 }
00607 else
00608 {
00609 useField = true;
00610 }
00611
00612 QGis::WkbType outputType = dp->geometryType();
00613 const QgsCoordinateReferenceSystem crs = layer->srs();
00614
00615 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
00616 QgsFeature currentFeature;
00617 QMultiMap<QString, int> map;
00618
00619 if ( onlySelectedFeatures )
00620 {
00621
00622 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00623 QgsFeatureIds::const_iterator it = selection.constBegin();
00624 for ( ; it != selection.constEnd(); ++it )
00625 {
00626 if ( !layer->featureAtId( *it, currentFeature, true, true ) )
00627 {
00628 continue;
00629 }
00630 map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
00631 }
00632 }
00633 else
00634 {
00635 layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
00636 while ( layer->nextFeature( currentFeature ) )
00637 {
00638 map.insert( currentFeature.attributeMap()[ uniqueIdField ].toString(), currentFeature.id() );
00639 }
00640 }
00641
00642 QgsGeometry *dissolveGeometry = 0;
00643 QMultiMap<QString, int>::const_iterator jt = map.constBegin();
00644 QgsFeature outputFeature;
00645 while ( jt != map.constEnd() )
00646 {
00647 QString currentKey = jt.key();
00648 int processedFeatures = 0;
00649 bool first = true;
00650
00651 if ( onlySelectedFeatures )
00652 {
00653
00654 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00655 if ( p )
00656 {
00657 p->setMaximum( selection.size() );
00658 }
00659 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
00660 {
00661 if ( p && p->wasCanceled() )
00662 {
00663 break;
00664 }
00665 if ( selection.contains( jt.value() ) )
00666 {
00667 if ( p )
00668 {
00669 p->setValue( processedFeatures );
00670 }
00671 if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
00672 {
00673 continue;
00674 }
00675 if ( first )
00676 {
00677 outputFeature.setAttributeMap( currentFeature.attributeMap() );
00678 first = false;
00679 }
00680 dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
00681 ++processedFeatures;
00682 }
00683 ++jt;
00684 }
00685 }
00686
00687 else
00688 {
00689 int featureCount = layer->featureCount();
00690 if ( p )
00691 {
00692 p->setMaximum( featureCount );
00693 }
00694 while ( jt != map.constEnd() && ( jt.key() == currentKey || !useField ) )
00695 {
00696 if ( p )
00697 {
00698 p->setValue( processedFeatures );
00699 }
00700
00701 if ( p && p->wasCanceled() )
00702 {
00703 break;
00704 }
00705 if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
00706 {
00707 continue;
00708 }
00709 {
00710 outputFeature.setAttributeMap( currentFeature.attributeMap() );
00711 first = false;
00712 }
00713 dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
00714 ++processedFeatures;
00715 ++jt;
00716 }
00717 }
00718 outputFeature.setGeometry( dissolveGeometry );
00719 vWriter.addFeature( outputFeature );
00720 }
00721 return true;
00722 }
00723
00724 void QgsGeometryAnalyzer::dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry )
00725 {
00726 QgsGeometry* featureGeometry = f.geometry();
00727
00728 if ( !featureGeometry )
00729 {
00730 return;
00731 }
00732
00733 if ( nProcessedFeatures == 0 )
00734 {
00735 int geomSize = featureGeometry->wkbSize();
00736 *dissolveGeometry = new QgsGeometry();
00737 unsigned char* wkb = new unsigned char[geomSize];
00738 memcpy( wkb, featureGeometry->asWkb(), geomSize );
00739 ( *dissolveGeometry )->fromWkb( wkb, geomSize );
00740 }
00741 else
00742 {
00743 *dissolveGeometry = ( *dissolveGeometry )->combine( featureGeometry );
00744 }
00745 }
00746
00747 bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance,
00748 bool onlySelectedFeatures, bool dissolve, int bufferDistanceField, QProgressDialog* p )
00749 {
00750 if ( !layer )
00751 {
00752 return false;
00753 }
00754
00755 QgsVectorDataProvider* dp = layer->dataProvider();
00756 if ( !dp )
00757 {
00758 return false;
00759 }
00760
00761 QGis::WkbType outputType = QGis::WKBPolygon;
00762 if ( dissolve )
00763 {
00764 outputType = QGis::WKBMultiPolygon;
00765 }
00766 const QgsCoordinateReferenceSystem crs = layer->srs();
00767
00768 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
00769 QgsFeature currentFeature;
00770 QgsGeometry *dissolveGeometry = 0;
00771
00772
00773 if ( onlySelectedFeatures )
00774 {
00775
00776 const QgsFeatureIds selection = layer->selectedFeaturesIds();
00777 if ( p )
00778 {
00779 p->setMaximum( selection.size() );
00780 }
00781
00782 int processedFeatures = 0;
00783 QgsFeatureIds::const_iterator it = selection.constBegin();
00784 for ( ; it != selection.constEnd(); ++it )
00785 {
00786 if ( p )
00787 {
00788 p->setValue( processedFeatures );
00789 }
00790
00791 if ( p && p->wasCanceled() )
00792 {
00793 break;
00794 }
00795 if ( !layer->featureAtId( *it, currentFeature, true, true ) )
00796 {
00797 continue;
00798 }
00799 bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
00800 ++processedFeatures;
00801 }
00802
00803 if ( p )
00804 {
00805 p->setValue( selection.size() );
00806 }
00807 }
00808
00809 else
00810 {
00811 layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
00812
00813
00814 int featureCount = layer->featureCount();
00815 if ( p )
00816 {
00817 p->setMaximum( featureCount );
00818 }
00819 int processedFeatures = 0;
00820
00821 while ( layer->nextFeature( currentFeature ) )
00822 {
00823 if ( p )
00824 {
00825 p->setValue( processedFeatures );
00826 }
00827 if ( p && p->wasCanceled() )
00828 {
00829 break;
00830 }
00831 bufferFeature( currentFeature, processedFeatures, &vWriter, dissolve, &dissolveGeometry, bufferDistance, bufferDistanceField );
00832 ++processedFeatures;
00833 }
00834 if ( p )
00835 {
00836 p->setValue( featureCount );
00837 }
00838 }
00839
00840 if ( dissolve )
00841 {
00842 QgsFeature dissolveFeature;
00843 if ( !dissolveGeometry )
00844 {
00845 QgsDebugMsg( "no dissolved geometry - should not happen" );
00846 return false;
00847 }
00848 dissolveFeature.setGeometry( dissolveGeometry );
00849 vWriter.addFeature( dissolveFeature );
00850 }
00851 return true;
00852 }
00853
00854 void QgsGeometryAnalyzer::bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, bool dissolve,
00855 QgsGeometry** dissolveGeometry, double bufferDistance, int bufferDistanceField )
00856 {
00857 double currentBufferDistance;
00858 QgsGeometry* featureGeometry = f.geometry();
00859 QgsGeometry* tmpGeometry = 0;
00860 QgsGeometry* bufferGeometry = 0;
00861
00862 if ( !featureGeometry )
00863 {
00864 return;
00865 }
00866
00867
00868 if ( bufferDistanceField == -1 )
00869 {
00870 currentBufferDistance = bufferDistance;
00871 }
00872 else
00873 {
00874 currentBufferDistance = f.attributeMap()[bufferDistanceField].toDouble();
00875 }
00876 bufferGeometry = featureGeometry->buffer( currentBufferDistance, 5 );
00877
00878 if ( dissolve )
00879 {
00880 if ( nProcessedFeatures == 0 )
00881 {
00882 *dissolveGeometry = bufferGeometry;
00883 }
00884 else
00885 {
00886 tmpGeometry = *dissolveGeometry;
00887 *dissolveGeometry = ( *dissolveGeometry )->combine( bufferGeometry );
00888 delete tmpGeometry;
00889 delete bufferGeometry;
00890 }
00891 }
00892 else
00893 {
00894 QgsFeature newFeature;
00895 newFeature.setGeometry( bufferGeometry );
00896 newFeature.setAttributeMap( f.attributeMap() );
00897
00898
00899 if ( vfw )
00900 {
00901 vfw->addFeature( newFeature );
00902 }
00903 }
00904 }