Quantum GIS API Documentation
1.7.4
|
00001 /*************************************************************************** 00002 qgsgeometryanalyzer.cpp - QGIS Tools for vector geometry analysis 00003 ------------------- 00004 begin : 19 March 2009 00005 copyright : (C) Carson Farmer 00006 email : carson.farmer@gmail.com 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 /* $Id: qgis.h 9774 2008-12-12 05:41:24Z timlinux $ */ 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->crs(); 00047 00048 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); 00049 QgsFeature currentFeature; 00050 00051 //take only selection 00052 if ( onlySelectedFeatures ) 00053 { 00054 //use QgsVectorLayer::featureAtId 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 //take all features 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 // simplify feature 00132 tmpGeometry = featureGeometry->simplify( tolerance ); 00133 00134 QgsFeature newFeature; 00135 newFeature.setGeometry( tmpGeometry ); 00136 newFeature.setAttributeMap( f.attributeMap() ); 00137 00138 //add it to vector file writer 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->crs(); 00161 00162 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); 00163 QgsFeature currentFeature; 00164 00165 //take only selection 00166 if ( onlySelectedFeatures ) 00167 { 00168 //use QgsVectorLayer::featureAtId 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 //take all features 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 //add it to vector file writer 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->crs(); 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 ) // take only selection 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->crs(); 00408 00409 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs ); 00410 QgsFeature currentFeature; 00411 QgsGeometry* dissolveGeometry = 0; //dissolve geometry 00412 QMultiMap<QString, int> map; 00413 00414 if ( onlySelectedFeatures ) 00415 { 00416 //use QgsVectorLayer::featureAtId 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 // break; // it may be better to do something else here? 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 // break; // it may be better to do something else here? 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 //take only selection 00465 if ( onlySelectedFeatures ) 00466 { 00467 //use QgsVectorLayer::featureAtId 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 //take all features 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 // QgsGeometry* tmpGeometry = 0; 00542 if ( !dissolveGeometry ) 00543 { 00544 QgsDebugMsg( "no dissolved geometry - should not happen" ); 00545 return false; 00546 } 00547 dissolveGeometry = dissolveGeometry->convexHull(); 00548 // values = simpleMeasure( tmpGeometry ); 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->crs(); 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 //use QgsVectorLayer::featureAtId 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; //dissolve geometry 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 //take only selection 00651 if ( onlySelectedFeatures ) 00652 { 00653 //use QgsVectorLayer::featureAtId 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 //take all features 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->crs(); 00767 00768 QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); 00769 QgsFeature currentFeature; 00770 QgsGeometry *dissolveGeometry = 0; //dissolve geometry (if dissolve enabled) 00771 00772 //take only selection 00773 if ( onlySelectedFeatures ) 00774 { 00775 //use QgsVectorLayer::featureAtId 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 //take all features 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 //create buffer 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 //dissolve 00893 { 00894 QgsFeature newFeature; 00895 newFeature.setGeometry( bufferGeometry ); 00896 newFeature.setAttributeMap( f.attributeMap() ); 00897 00898 //add it to vector file writer 00899 if ( vfw ) 00900 { 00901 vfw->addFeature( newFeature ); 00902 } 00903 } 00904 }