Quantum GIS API Documentation  1.7.4
src/analysis/vector/qgsgeometryanalyzer.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines