[QGIS Commit] r11976 - in trunk/qgis: python python/analysis src/analysis/vector

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat Nov 7 14:22:27 EST 2009


Author: cfarmer
Date: 2009-11-07 14:22:27 -0500 (Sat, 07 Nov 2009)
New Revision: 11976

Added:
   trunk/qgis/python/analysis/
   trunk/qgis/python/analysis/analysis.sip
   trunk/qgis/python/analysis/qgsgeometryanalyzer.sip
Modified:
   trunk/qgis/python/CMakeLists.txt
   trunk/qgis/python/configure.py.in
   trunk/qgis/python/qgisconfig.py.in
   trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.cpp
   trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.h
Log:
add new functions to analysis library, also adds python bindings to analysis library

Modified: trunk/qgis/python/CMakeLists.txt
===================================================================
--- trunk/qgis/python/CMakeLists.txt	2009-11-07 19:20:35 UTC (rev 11975)
+++ trunk/qgis/python/CMakeLists.txt	2009-11-07 19:22:27 UTC (rev 11976)
@@ -2,38 +2,45 @@
 IF (WIN32)
   SET(BINDINGS_CORE_LIB ${CMAKE_CURRENT_BINARY_DIR}/core/core.pyd)
   SET(BINDINGS_GUI_LIB  ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.pyd)
+  SET(BINDINGS_ANALYSIS_LIB  ${CMAKE_CURRENT_BINARY_DIR}/analysis/analysis.pyd)
   IF (NOT MSVC)
     SET(QGIS_CORE_LIB     ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dll)
     SET(QGIS_GUI_LIB      ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dll)
+    SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.dll)
   ELSE (NOT MSVC)
-    SET(QGIS_CORE_LIB	  ${CMAKE_BINARY_DIR}/src/core/${CMAKE_CFG_INTDIR}/qgis_core.lib)
-    SET(QGIS_GUI_LIB	  ${CMAKE_BINARY_DIR}/src/gui/${CMAKE_CFG_INTDIR}/qgis_gui.lib)
+    SET(QGIS_CORE_LIB	    ${CMAKE_BINARY_DIR}/src/core/${CMAKE_CFG_INTDIR}/qgis_core.lib)
+    SET(QGIS_GUI_LIB	    ${CMAKE_BINARY_DIR}/src/gui/${CMAKE_CFG_INTDIR}/qgis_gui.lib)
+    SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/${CMAKE_CFG_INTDIR}/qgis_analysis.lib)
   ENDIF (NOT MSVC)
 ELSE (WIN32)
-  SET(BINDINGS_CORE_LIB ${CMAKE_CURRENT_BINARY_DIR}/core/core.so)
-  SET(BINDINGS_GUI_LIB  ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.so)
+  SET(BINDINGS_CORE_LIB     ${CMAKE_CURRENT_BINARY_DIR}/core/core.so)
+  SET(BINDINGS_GUI_LIB      ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.so)
+  SET(BINDINGS_ANALYSIS_LIB ${CMAKE_CURRENT_BINARY_DIR}/analysis/analysis.so)
   IF (APPLE)
-    SET(QGIS_CORE_LIB   ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dylib)
-    SET(QGIS_GUI_LIB    ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dylib)
+    SET(QGIS_CORE_LIB     ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dylib)
+    SET(QGIS_GUI_LIB      ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dylib)
+    SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.dylib)
   ELSE (APPLE)
-    SET(QGIS_CORE_LIB   ${CMAKE_BINARY_DIR}/src/core/libqgis_core.so)
-    SET(QGIS_GUI_LIB    ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.so)
+    SET(QGIS_CORE_LIB     ${CMAKE_BINARY_DIR}/src/core/libqgis_core.so)
+    SET(QGIS_GUI_LIB      ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.so)
+    SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.so)
   ENDIF (APPLE)
 ENDIF (WIN32)
 
-SET (BINDINGS_LIBS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB})
+SET (BINDINGS_LIBS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB} ${BINDINGS_ANALYSIS_LIB})
+SET (BINDINGS_CORE_MAKEFILE     ${CMAKE_CURRENT_BINARY_DIR}/core/Makefile)
+SET (BINDINGS_GUI_MAKEFILE      ${CMAKE_CURRENT_BINARY_DIR}/gui/Makefile)
+SET (BINDINGS_ANALYSIS_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/analysis/Makefile)
 
-SET (BINDINGS_CORE_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/core/Makefile)
-SET (BINDINGS_GUI_MAKEFILE  ${CMAKE_CURRENT_BINARY_DIR}/gui/Makefile)
-
 # 'python' target will force to build bindings libs for core and gui
-ADD_CUSTOM_TARGET (python ALL DEPENDS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB})
+ADD_CUSTOM_TARGET (python ALL DEPENDS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB} ${BINDINGS_ANALYSIS_LIB})
 
 # don't run python before the libs are built
-ADD_DEPENDENCIES (python qgis_core qgis_gui)
+ADD_DEPENDENCIES (python qgis_core qgis_gui qgis_analysis)
 
-FILE(GLOB CORE_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/core/*.sip")
-FILE(GLOB GUI_SIP_FILES  "${CMAKE_CURRENT_SOURCE_DIR}/gui/*.sip")
+FILE(GLOB CORE_SIP_FILES     "${CMAKE_CURRENT_SOURCE_DIR}/core/*.sip")
+FILE(GLOB GUI_SIP_FILES      "${CMAKE_CURRENT_SOURCE_DIR}/gui/*.sip")
+FILE(GLOB ANALYSIS_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/analysis/*.sip")
 
 # Step 1: during configuration
 # create file configure.py from configure.py.in
@@ -50,12 +57,12 @@
 # run python configure.py
 # it will run SIP utility to generate sources and will prepare makefiles
 # should be run everytime core or gui library has been changed
-ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_MAKEFILE} ${BINDINGS_GUI_MAKEFILE} PRE_BUILD
+ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_MAKEFILE} ${BINDINGS_GUI_MAKEFILE} ${BINDINGS_ANALYSIS_MAKEFILE} PRE_BUILD
                    COMMAND ${PYTHON_EXECUTABLE}
                    ARGS ${CMAKE_CURRENT_BINARY_DIR}/configure.py ${CMAKE_CFG_INTDIR} ${EXPORT}
-		   DEPENDS ${QGIS_CORE_LIB} ${QGIS_GUI_LIB}
+		   DEPENDS ${QGIS_CORE_LIB} ${QGIS_GUI_LIB} ${QGIS_ANALYSIS_LIB}
 		           ${CMAKE_CURRENT_BINARY_DIR}/configure.py
-			   ${CORE_SIP_FILES} ${GUI_SIP_FILES})
+			   ${CORE_SIP_FILES} ${GUI_SIP_FILES} ${ANALYSIS_SIP_FILES})
 
 # Step 3: run make in core and gui subdirs
 ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_LIB} PRE_LINK
@@ -66,6 +73,10 @@
                    COMMAND ${SIP_MAKE_PROGRAM}
                    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gui
                    DEPENDS ${BINDINGS_GUI_MAKEFILE})
+ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_ANALYSIS_LIB} PRE_LINK
+                   COMMAND ${SIP_MAKE_PROGRAM}
+                   WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/analysis
+                   DEPENDS ${BINDINGS_ANALYSIS_MAKEFILE})
 
 IF (BINDINGS_GLOBAL_INSTALL)
 

Added: trunk/qgis/python/analysis/analysis.sip
===================================================================
--- trunk/qgis/python/analysis/analysis.sip	                        (rev 0)
+++ trunk/qgis/python/analysis/analysis.sip	2009-11-07 19:22:27 UTC (rev 11976)
@@ -0,0 +1,11 @@
+
+%Module qgis.analysis 0
+
+%Import QtCore/QtCoremod.sip
+%Import QtGui/QtGuimod.sip
+%Import QtXml/QtXmlmod.sip
+
+%Import core/core.sip
+
+%Include qgsgeometryanalyzer.sip
+

Added: trunk/qgis/python/analysis/qgsgeometryanalyzer.sip
===================================================================
--- trunk/qgis/python/analysis/qgsgeometryanalyzer.sip	                        (rev 0)
+++ trunk/qgis/python/analysis/qgsgeometryanalyzer.sip	2009-11-07 19:22:27 UTC (rev 11976)
@@ -0,0 +1,67 @@
+/** \ingroup analysis
+ * The QGis class provides vector geometry analysis functions
+ */
+
+class QgsGeometryAnalyzer
+{
+%TypeHeaderCode
+#include <qgsgeometryanalyzer.h>
+%End
+
+  public:
+
+    /**
+     * Simplify vector layer using (a modified) Douglas-Peucker algorithm
+     * and write it to a new shape file
+     */
+    bool simplify( QgsVectorLayer* layer, const QString& shapefileName, double tolerance,
+                 bool onlySelectedFeatures = false );
+
+    /**Calculate the true centroids, or 'center of mass' for a vector layer and 
+       write it to a new shape file
+    */
+    bool centroids( QgsVectorLayer* layer, const QString& shapefileName,
+                 bool onlySelectedFeatures = false );
+
+    /**Create a polygon based on the extent of all (selected) features and write it to a new shape file
+    */
+    bool extent( QgsVectorLayer* layer, const QString& shapefileName, 
+                 bool onlySelectedFeatures = false );
+
+    /**Create buffers for a vector layer and write it to a new shape file
+    */
+    bool buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance,
+                 bool onlySelectedFeatures = false, bool dissolve = false, 
+                 int bufferDistanceField = -1 );
+
+    /**Create convex hull(s) of a vector layer and write it to a new shape file
+    */
+    bool convexHull( QgsVectorLayer* layer, const QString& shapefileName, 
+                     bool onlySelectedFeatures = false,
+                     int uniqueIdField = -1 );
+
+    /**Dissolve a vector layer and write it to a new shape file
+    */
+    bool dissolve( QgsVectorLayer* layer, const QString& shapefileName, 
+                   bool onlySelectedFeatures = false,
+                     int uniqueIdField = -1 );
+
+  private:
+
+    QList<double> simpleMeasure( QgsGeometry* geometry );
+    double perimeterMeasure( QgsGeometry* geometry, QgsDistanceArea& measure );
+    /**Helper function to simplify an individual feature*/
+    void simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance );
+    /**Helper function to get the cetroid of an individual feature*/
+    void centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw );
+    /**Helper function to buffer an individual feature*/
+    void bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, 
+                        bool dissolve, QgsGeometry** dissolveGeometry,
+                        double bufferDistance, int bufferDistanceField );
+    /**Helper function to get the convex hull of feature(s)*/
+    void convexFeature( QgsFeature& f, int nProcessedFeatures, 
+                        QgsGeometry** dissolveGeometry );
+    /**Helper function to dissolve feature(s)*/
+    void dissolveFeature( QgsFeature& f, int nProcessedFeatures, 
+                          QgsGeometry** dissolveGeometry );
+};

Modified: trunk/qgis/python/configure.py.in
===================================================================
--- trunk/qgis/python/configure.py.in	2009-11-07 19:20:35 UTC (rev 11975)
+++ trunk/qgis/python/configure.py.in	2009-11-07 19:22:27 UTC (rev 11976)
@@ -38,6 +38,8 @@
   os.mkdir("./core")
 if not os.path.isdir("./gui"):
     os.mkdir("./gui")
+if not os.path.isdir("./analysis"):
+    os.mkdir("./analysis")
 
 ##########################################################################
 # SIP -> *.CPP + *.H
@@ -46,6 +48,7 @@
 # system.
 build_file_core = build_path + "/python/core/core.sbf"
 build_file_gui = build_path + "/python/gui/gui.sbf"
+build_file_analysis = build_path + "/python/analysis/analysis.sbf"
 
 # Get the SIP configuration information.
 config = PyQt4.pyqtconfig.Configuration()
@@ -61,6 +64,7 @@
 # directory where sip files will be installed
 sip_dir_core = os.path.join(config.default_sip_dir, "qgis/core")
 sip_dir_gui = os.path.join(config.default_sip_dir, "qgis/gui")
+sip_dir_analysis = os.path.join(config.default_sip_dir, "qgis/analysis")
   
 # Run SIP to generate the code.
 print "Parsing SIP files for 'core' library..."
@@ -73,7 +77,12 @@
 print cmd
 os.system(cmd)
 
+print "Parsing SIP files for 'analysis' library..."
+cmd = " ".join([config.sip_bin, "-c", "analysis", "-b", build_file_analysis, "-I", python_path, "-I", config.pyqt_sip_dir, qt_sip_flags, python_path + "/analysis/analysis.sip"])
+print cmd
+os.system(cmd)
 
+
 ##########################################################################
 # MAKEFILES
 
@@ -83,12 +92,13 @@
 # its configuration module.
 installs = []
 
-# directories relative to core (gui) directories
+# directories relative to core (gui, analysis) directories
 installs.append([[python_path + "__init__.py", python_path + "qgisconfig.py"], mod_dir])
 
 
 installs_core = copy.copy(installs)
 installs_gui = copy.copy(installs)
+installs_analysis = copy.copy(installs)
 
 # install all sip files
 sips_core = glob.glob(python_path + "/core/*.sip")
@@ -98,6 +108,10 @@
 sips_gui = glob.glob(python_path + "/gui/*.sip")
 for sip in sips_gui:
   installs_gui.append([os.path.basename(sip), sip_dir_gui])
+  
+sips_analysis = glob.glob(python_path + "/analysis/*.sip")
+for sip in sips_analysis:
+  installs_analysis.append([os.path.basename(sip), sip_dir_analysis])
 
 
 # Create the Makefile.  The QtModuleMakefile class provided by the
@@ -120,9 +134,18 @@
         install_dir=mod_dir,
         dir="gui",
         universal=osx_universal)
+        
+makefile_analysis = sipconfig.ModuleMakefile(
+        configuration=config,
+        qt=qt_libs,
+        build_file=build_file_analysis,
+        installs=installs_analysis,
+        install_dir=mod_dir,
+        dir="analysis",
+        universal=osx_universal)
 
-# common settings for both core and gui libs
-for mk in [ makefile_core, makefile_gui ]:
+# common settings for core, gui and analysis libs
+for mk in [ makefile_core, makefile_gui, makefile_analysis ]:
   mk.extra_lflags.extend( "@CMAKE_MODULE_LINKER_FLAGS@".strip(' ').split(' ') )
   mk.extra_libs = ["qgis_core"]
   mk.extra_lib_dirs = [build_path+"/src/core"+intdir]
@@ -145,9 +168,18 @@
 makefile_gui.extra_include_dirs.append(src_path+"/src/plugins") # because of qgisplugin.h TODO: sort out
 makefile_gui.extra_cxxflags.append("-DGUI_EXPORT="+export)
 
+# more settings for analysis lib
+makefile_analysis.extra_libs.append("qgis_analysis")
+makefile_analysis.extra_lib_dirs.append(build_path+"/src/analysis/vector"+intdir)
+makefile_analysis.extra_include_dirs.append(src_path+"/src/analysis/vector")
+makefile_analysis.extra_include_dirs.append(build_path+"/src/analysis/vector")
+makefile_analysis.extra_include_dirs.append(src_path+"/src/plugins") # because of qgisplugin.h TODO: sort out
+makefile_analysis.extra_cxxflags.append("-DANALYSIS_EXPORT="+export)
+
 # Generate the Makefile itself.
 makefile_core.generate()
 makefile_gui.generate()
+makefile_analysis.generate()
 
 ##########################################################################
 # QGIS CONFIG

Modified: trunk/qgis/python/qgisconfig.py.in
===================================================================
--- trunk/qgis/python/qgisconfig.py.in	2009-11-07 19:20:35 UTC (rev 11975)
+++ trunk/qgis/python/qgisconfig.py.in	2009-11-07 19:22:27 UTC (rev 11976)
@@ -34,6 +34,7 @@
         # Make sure our C++ library is linked.
         self.extra_libs.append("qgis_core")
         self.extra_libs.append("qgis_gui")
+        self.extra_libs.append("qgis_analysis")
 
         # Let the super-class do what it needs to.
         pyqtconfig.QtModuleMakefile.finalise(self)

Modified: trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.cpp
===================================================================
--- trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.cpp	2009-11-07 19:20:35 UTC (rev 11975)
+++ trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.cpp	2009-11-07 19:22:27 UTC (rev 11976)
@@ -28,262 +28,251 @@
 #include "qgsdistancearea.h"
 #include <QProgressDialog>
 
+bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer, const QString& shapefileName, \
+                                  double tolerance, bool onlySelectedFeatures, QProgressDialog* p )
+{
+  if ( !layer )
+  {
+    return false;
+  }
 
+  QgsVectorDataProvider* dp = layer->dataProvider();
+  if ( !dp )
+  {
+    return false;
+  }
 
-bool QgsGeometryAnalyzer::singlepartsToMultipart( QgsVectorLayer* layer,
-    const QString& shapefileName,
-    const QString& fileEncoding,
-    const int fieldIndex )
-{
-  return false;
-  /*
-    QgsVectorDataProvider* provider = layer->dataProvider();
-    QgsAttributeList allAttrs = provider->attributeIndexes();
-    provider->select( allAttrs, QgsRectangle(), true );
-    const QgsCoordinateReferenceSystem* outputCRS;
-    outputCRS = &layer->srs();
-    QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName,
-    fileEncoding, provider->fields(), provider->geometryType(), outputCRS );
+  QGis::WkbType outputType = dp->geometryType();
+  const QgsCoordinateReferenceSystem crs = layer->srs();
 
-    QgsGeometry inGeom;
-    QgsGeometry outGeom;
-    QList<QVariant> unique;
-    provider->uniqueValues( index, unique )
-    if ( unique->size() < layer->featureCount() )
+  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
+  QgsFeature currentFeature;
+
+  //take only selection
+  if ( onlySelectedFeatures )
+  {
+    //use QgsVectorLayer::featureAtId
+    const QgsFeatureIds selection = layer->selectedFeaturesIds();
+    if ( p )
     {
-      QList<QgsGeometry> multiGeom;
-      bool first;
-      QgsAttributeMap atMap;
+      p->setMaximum( selection.size() );
+    }
 
-      for ( int it = unique.begin(); it != unique.end(); ++it )
+    int processedFeatures = 0;
+    QgsFeatureIds::const_iterator it = selection.constBegin();
+    for ( ; it != selection.constEnd(); ++it )
+    {
+      if ( p )
       {
-        provider->select( allAttrs, QgsRectangle(), true );
-        first = true;
-        while ( provider->nextFeature( inFeat ) )
-        {
-          if ( inFeat.attributeMap()[ index ].toString().trimmed() == it.toString().trimmed() )
-          {
-            if (first)
-            {
-              atMap = inFeat.attributeMap();
-              first = false;
-            }
-            inGeom = inFeat.geometry();
-            multiGeom << inGeom.asGeometryCollection()
-          }
-            outFeat.setAttributeMap( atMap );
-            outGeom = convertGeometry( multifeature, vtype );
-            outFeat.setGeometry( outGeom );
-            writer.addFeature( outFeat );
-        }
+        p->setValue( processedFeatures );
       }
-      delete writer;
-      return true;
-  */
-}
 
-bool QgsGeometryAnalyzer::multipartToSingleparts( QgsVectorLayer* layer,
-    const QString& shapefileName,
-    const QString& fileEncoding )
-{
-  return false;
-  /*
-  QgsVectorDataProvider* provider = layer->dataProvider();
-  QgsAttributeList allAttrs = provider->attributeIndexes();
-  provider->select( allAttrs, QgsRectangle(), true );
-  const QgsCoordinateReferenceSystem* outputCRS;
-  outputCRS = &layer->srs();
-  QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName,
-  fileEncoding, provider->fields(), provider->geometryType(), outputCRS );
-    inFeat = QgsFeature()
-    outFeat = QgsFeature()
-    inGeom = QgsGeometry()
-    outGeom = QgsGeometry()
-    nFeat = vprovider.featureCount()
-    nElement = 0
-    self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 0 )
-    self.emit( SIGNAL( "runRange(PyQt_PyObject)" ), ( 0, nFeat ) )
-    while vprovider.nextFeature( inFeat )
-      nElement += 1
-      self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement )
-      inGeom = inFeat.geometry()
-      atMap = inFeat.attributeMap()
-      featList = self.extractAsSingle( inGeom )
-      outFeat.setAttributeMap( atMap )
-      for i in featList:
-        outFeat.setGeometry( i )
-        writer.addFeature( outFeat )
-    del writer
-    return True
+      if ( p && p->wasCanceled() )
+      {
+        break;
+      }
+      if ( !layer->featureAtId( *it, currentFeature, true, true ) )
+      {
+        continue;
+      }
+      simplifyFeature( currentFeature, &vWriter, tolerance );
+      ++processedFeatures;
+    }
 
-  */
-}
+    if ( p )
+    {
+      p->setValue( selection.size() );
+    }
+  }
+  //take all features
+  else
+  {
+    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
 
-bool QgsGeometryAnalyzer::extractNodes( QgsVectorLayer* layer,
-                                        const QString& shapefileName,
-                                        const QString& fileEncoding )
-{
-  return false;
-  /*
-    QgsVectorDataProvider* provider = layer->dataProvider();
-    QgsAttributeList allAttrs = provider->attributeIndexes();
-    provider->select( allAttrs, QgsRectangle(), true );
-    const QgsCoordinateReferenceSystem* outputCRS;
-    outputCRS = &layer->srs();
-    QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName,
-    fileEncoding, provider->fields(), provider->geometryType(), outputCRS );
 
-    QgsFeature inFeat;
-    QgsFeature outFeat;
+    int featureCount = layer->featureCount();
+    if ( p )
+    {
+      p->setMaximum( featureCount );
+    }
+    int processedFeatures = 0;
 
-    QgsGeometry outGeom;
-    QList<QgsPoint> pointList;
-    QgsPoint geomPoint;
-    QList<QgsPoint>::iterator it;
-    while ( provider->nextFeature( inFeat ) )
+    while ( layer->nextFeature( currentFeature ) )
     {
-      pointList = extractPoints( inFeat.geometry() );
-      outFeat.setAttributeMap( inFeat.attributeMap() );
-      for (it = pointList.begin(); it != pointList.end(); ++it )
+      if ( p )
       {
-        geomPoint = QgsGeometry::fromPoint( it );
-        outFeat.setGeometry( geomPoint );
-        writer.addFeature( outFeat );
+        p->setValue( processedFeatures );
       }
+      if ( p && p->wasCanceled() )
+      {
+        break;
+      }
+      simplifyFeature( currentFeature, &vWriter, tolerance );
+      ++processedFeatures;
     }
-    delete writer;
-    return true;
-  */
+    if ( p )
+    {
+      p->setValue( featureCount );
+    }
+  }
+
+  return true;
 }
 
-bool QgsGeometryAnalyzer::polygonsToLines( QgsVectorLayer* layer,
-    const QString& shapefileName,
-    const QString& fileEncoding )
+void QgsGeometryAnalyzer::simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance )
 {
-  return false;
-  /*
-    QgsVectorDataProvider* provider = layer->dataProvider();
-    QgsAttributeList allAttrs = provider->attributeIndexes();
-    provider->select( allAttrs, QgsRectangle(), true );
-    QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName,
-        fileEncoding, provider->fields(), QGis::WKBPoint, provider->crs() );
+  QgsGeometry* featureGeometry = f.geometry();
+  QgsGeometry* tmpGeometry = 0;
 
+  if ( !featureGeometry )
+  {
+    return;
+  }
+  // simplify feature
+  tmpGeometry = featureGeometry->simplify( tolerance );
 
+  QgsFeature newFeature;
+  newFeature.setGeometry( tmpGeometry );
+  newFeature.setAttributeMap( f.attributeMap() );
 
-    QgsFeature inFeat;
-    QgsFeature outFeat;
-    QgsGeometry inGeom;
-    QgsGeometry outGeom;
-    QList<QgsPolyline> lineList;
+  //add it to vector file writer
+  if ( vfw )
+  {
+    vfw->addFeature( newFeature );
+  }
+}
 
-    while ( provider->nextFeature( inFeat ) )
+bool QgsGeometryAnalyzer::centroids( QgsVectorLayer* layer, const QString& shapefileName, \
+                                  bool onlySelectedFeatures, QProgressDialog* p )
+{
+  if ( !layer )
+  {
+    return false;
+  }
+
+  QgsVectorDataProvider* dp = layer->dataProvider();
+  if ( !dp )
+  {
+    return false;
+  }
+
+  QGis::WkbType outputType = QGis::WKBPoint;
+  const QgsCoordinateReferenceSystem crs = layer->srs();
+
+  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
+  QgsFeature currentFeature;
+
+  //take only selection
+  if ( onlySelectedFeatures )
+  {
+    //use QgsVectorLayer::featureAtId
+    const QgsFeatureIds selection = layer->selectedFeaturesIds();
+    if ( p )
     {
-      lineList = QgsGeometryAnalyzer::extractLines( inFeat.geometry() );
-      outFeat.setAttributeMap( inFeat.attributeMap() );
-      for ( line = lineList.begin(); line != lineList.end(); line++ )
+      p->setMaximum( selection.size() );
+    }
+
+    int processedFeatures = 0;
+    QgsFeatureIds::const_iterator it = selection.constBegin();
+    for ( ; it != selection.constEnd(); ++it )
+    {
+      if ( p )
       {
-        outFeat.setGeometry( outGeom.fromPolyline( line ) );
-        writer.addFeature( outFeat );
+        p->setValue( processedFeatures );
       }
+
+      if ( p && p->wasCanceled() )
+      {
+        break;
+      }
+      if ( !layer->featureAtId( *it, currentFeature, true, true ) )
+      {
+        continue;
+      }
+      centroidFeature( currentFeature, &vWriter );
+      ++processedFeatures;
     }
-    delete writer;
-    return true;
-    */
-}
 
-bool QgsGeometryAnalyzer::exportGeometryInformation( QgsVectorLayer* layer,
-    const QString& shapefileName,
-    const QString& fileEncoding )
-{
-  return false;
-#if 0
-  QgsVectorDataProvider* provider = layer->dataProvider();
-  QgsAttributeList allAttrs = provider->attributeIndexes();
-  provider->select( allAttrs, QgsRectangle(), true );
-  QgsCoordinateReferenceSystem outputCRS = layer->srs();
-  int index1;
-  int index2;
-  //( fields, index1, index2 ) = self.checkGeometryFields( self.vlayer )
+    if ( p )
+    {
+      p->setValue( selection.size() );
+    }
+  }
+  //take all features
+  else
+  {
+    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
 
-  QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName,
-                               fileEncoding, provider->fields(), provider->geometryType(), &outputCRS );
+    int featureCount = layer->featureCount();
+    if ( p )
+    {
+      p->setMaximum( featureCount );
+    }
+    int processedFeatures = 0;
 
-  QgsFeature inFeat;
-  QgsFeature outFeat;
-  QgsGeometry* inGeom;
-  QList<double> attrs;
+    while ( layer->nextFeature( currentFeature ) )
+    {
+      if ( p )
+      {
+        p->setValue( processedFeatures );
+      }
+      if ( p && p->wasCanceled() )
+      {
+        break;
+      }
+      centroidFeature( currentFeature, &vWriter );
+      ++processedFeatures;
+    }
+    if ( p )
+    {
+      p->setValue( featureCount );
+    }
+  }
 
-  while ( provider->nextFeature( inFeat ) )
-  {
-    inGeom = inFeat.geometry();
-    outFeat.setAttributeMap( inFeat.attributeMap() );
-    attrs = QgsGeometryAnalyzer::simpleMeasure( inGeom );
-    outFeat.setGeometry( inGeom );
-    outFeat.setAttributeMap( inFeat.attributeMap() );
-    outFeat.addAttribute( index1, QVariant( attrs[0] ) ); // FIXME: index1 unset
-    outFeat.addAttribute( index2, QVariant( attrs[1] ) ); // FIXME: index2 unset
-    writer.addFeature( outFeat );
-  }
   return true;
-#endif
 }
-bool QgsGeometryAnalyzer::simplifyGeometry( QgsVectorLayer* layer,
-    const QString shapefileName,
-    const QString fileEncoding,
-    const double tolerance )
+
+
+void QgsGeometryAnalyzer::centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw )
 {
-  QgsVectorDataProvider* provider = layer->dataProvider();
-  QgsAttributeList allAttrs = provider->attributeIndexes();
-  provider->select( allAttrs, QgsRectangle(), true );
-  QgsCoordinateReferenceSystem outputCRS = layer->srs();
-  QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName,
-                               fileEncoding, provider->fields(), provider->geometryType(), &outputCRS );
+  QgsGeometry* featureGeometry = f.geometry();
+  QgsGeometry* tmpGeometry = 0;
 
-  QgsFeature inFeat;
-  QgsFeature outFeat;
-  QgsGeometry* inGeom;
-
-  while ( provider->nextFeature( inFeat ) )
+  if ( !featureGeometry )
   {
-    inGeom = inFeat.geometry();
-    outFeat.setAttributeMap( inFeat.attributeMap() );
-    outFeat.setGeometry( inGeom->simplify( tolerance ) );
-    writer.addFeature( outFeat );
+    return;
   }
 
-  return true;
+  tmpGeometry = featureGeometry->centroid();
 
+  QgsFeature newFeature;
+  newFeature.setGeometry( tmpGeometry );
+  newFeature.setAttributeMap( f.attributeMap() );
+
+  //add it to vector file writer
+  if ( vfw )
+  {
+    vfw->addFeature( newFeature );
+  }
 }
 
-bool QgsGeometryAnalyzer::polygonCentroids( QgsVectorLayer* layer,
-    const QString& shapefileName,
-    const QString& fileEncoding )
+bool QgsGeometryAnalyzer::extent( QgsVectorLayer* layer, const QString& shapefileName, \
+                                  bool onlySelectedFeatures, QProgressDialog* p )
 {
-  QgsVectorDataProvider* provider = layer->dataProvider();
-  QgsAttributeList allAttrs = provider->attributeIndexes();
-  provider->select( allAttrs, QgsRectangle(), true );
-  QgsCoordinateReferenceSystem outputCRS = layer->srs();
-  QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName,
-                               fileEncoding, provider->fields(), provider->geometryType(), &outputCRS );
+  if ( !layer )
+  {
+    return false;
+  }
 
-  QgsFeature inFeat;
-  QgsFeature outFeat;
-  QgsGeometry* inGeom;
-
-  while ( provider->nextFeature( inFeat ) )
+  QgsVectorDataProvider* dp = layer->dataProvider();
+  if ( !dp )
   {
-    inGeom = inFeat.geometry();
-    outFeat.setAttributeMap( inFeat.attributeMap() );
-    outFeat.setGeometry( inGeom->centroid() );
-    writer.addFeature( outFeat );
+    return false;
   }
-  return true;
-}
 
-bool QgsGeometryAnalyzer::layerExtent( QgsVectorLayer* layer,
-                                       const QString& shapefileName,
-                                       const QString& fileEncoding )
-{
+  QGis::WkbType outputType = QGis::WKBPolygon;
+  const QgsCoordinateReferenceSystem crs = layer->srs();
+
   QgsFieldMap fields;
   fields.insert( 0 , QgsField( QString( "MINX" ), QVariant::Double ) );
   fields.insert( 1 , QgsField( QString( "MINY" ), QVariant::Double ) );
@@ -296,40 +285,44 @@
   fields.insert( 8 , QgsField( QString( "HEIGHT" ), QVariant::Double ) );
   fields.insert( 9 , QgsField( QString( "WIDTH" ), QVariant::Double ) );
 
-  QgsVectorDataProvider* provider = layer->dataProvider();
-  QgsCoordinateReferenceSystem outputCRS = layer->srs();
-  QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName,
-                               fileEncoding, provider->fields(), provider->geometryType(), &outputCRS );
+  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs );
 
   QgsRectangle rect;
-  rect = layer->extent();
+  if ( onlySelectedFeatures )  // take only selection
+  {
+    rect = layer->boundingBoxOfSelected();
+  }
+  else
+  {
+    rect = layer->extent();
+  }
+
   double minx = rect.xMinimum();
   double miny = rect.yMinimum();
   double maxx = rect.xMaximum();
   double maxy = rect.yMaximum();
   double height = rect.height();
   double width = rect.width();
-
   double cntx = minx + ( width / 2.0 );
   double cnty = miny + ( height / 2.0 );
   double area = width * height;
   double perim = ( 2 * width ) + ( 2 * height );
 
   QgsFeature feat;
-  QgsAttributeMap atMap;
-  atMap.insert( 0 , QVariant( minx ) );
-  atMap.insert( 1 , QVariant( miny ) );
-  atMap.insert( 2 , QVariant( maxx ) );
-  atMap.insert( 3 , QVariant( maxy ) );
-  atMap.insert( 4 , QVariant( cntx ) );
-  atMap.insert( 5 , QVariant( cnty ) );
-  atMap.insert( 6 , QVariant( area ) );
-  atMap.insert( 7 , QVariant( perim ) );
-  atMap.insert( 8 , QVariant( height ) );
-  atMap.insert( 9 , QVariant( width ) );
-  feat.setAttributeMap( atMap );
+  QgsAttributeMap map;
+  map.insert( 0 , QVariant( minx ) );
+  map.insert( 1 , QVariant( miny ) );
+  map.insert( 2 , QVariant( maxx ) );
+  map.insert( 3 , QVariant( maxy ) );
+  map.insert( 4 , QVariant( cntx ) );
+  map.insert( 5 , QVariant( cnty ) );
+  map.insert( 6 , QVariant( area ) );
+  map.insert( 7 , QVariant( perim ) );
+  map.insert( 8 , QVariant( height ) );
+  map.insert( 9 , QVariant( width ) );
+  feat.setAttributeMap( map );
   feat.setGeometry( QgsGeometry::fromRect( rect ) );
-  writer.addFeature( feat );
+  vWriter.addFeature( feat );
   return true;
 }
 
@@ -383,234 +376,279 @@
   return value;
 }
 
-QgsFieldMap QgsGeometryAnalyzer::checkGeometryFields( QgsVectorLayer* layer, int& index1, int& index2 )
+bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName,
+                                      bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
 {
-  return QgsFieldMap();
-  /*  QgsVectorDataProvider* provider = layer->dataProvider();
-    QgsAttributeList allAttrs = provider->attributeIndexes();
-  //  provider->select( allAttrs, QgsRectangle(), true );
-    QgsFieldMap fields = provider->fields()
-    QGis::GeometryType geomType = layer->geometryType();
+  if ( !layer )
+  {
+    return false;
+  }
 
-    for i in fieldList.keys()
-      nameList.append( fieldList[ i ].name().toLower() )
-    if geomType == QGis.Polygon:
-      plp = "Poly"
-      ( found, index1 ) = self.checkForField( nameList, "AREA" )
-      if not found:
-        field = QgsField( "AREA", QVariant.Double, "double", 10, 6, "Polygon area" )
-        index1 = len( fieldList.keys() )
-        fieldList[ index1 ] = field
-      ( found, index2 ) = self.checkForField( nameList, "PERIMETER" )
+  QgsVectorDataProvider* dp = layer->dataProvider();
+  if ( !dp )
+  {
+    return false;
+  }
 
-      if not found:
-        field = QgsField( "PERIMETER", QVariant.Double, "double", 10, 6, "Polygon perimeter" )
-        index2 = len( fieldList.keys() )
-        fieldList[ index2 ] = field
-    elif geomType == QGis.Line:
-      plp = "Line"
-      (found, index1) = self.checkForField(nameList, "LENGTH")
-      if not found:
-        field = QgsField("LENGTH", QVariant.Double, "double", 10, 6, "Line length")
-        index1 = len(fieldList.keys())
-        fieldList[index1] = field
-      index2 = index1
-    else:
-      plp = "Point"
-      (found, index1) = self.checkForField(nameList, "XCOORD")
-      if not found:
-        field = QgsField("XCOORD", QVariant.Double, "double", 10, 6, "Point x coordinate")
-        index1 = len(fieldList.keys())
-        fieldList[index1] = field
-      (found, index2) = self.checkForField(nameList, "YCOORD")
-      if not found:
-        field = QgsField("YCOORD", QVariant.Double, "double", 10, 6, "Point y coordinate")
-        index2 = len(fieldList.keys())
-        fieldList[index2] = field
-    return (fieldList, index1, index2)
-    */
-}
+  QGis::WkbType outputType = QGis::WKBPolygon;
+  const QgsCoordinateReferenceSystem crs = layer->srs();
 
-QgsGeometry* QgsGeometryAnalyzer::extractLines( QgsGeometry* geometry )
-{
-  return NULL;
-  /*
-    QGis::WkbType wkbType = geometry.wkbType();
-    QList<QgsPolyline> lineList;
-    QgsMultiPolygon polyList
-    if ( geometry.type() == QGis::Polygon )
+  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
+  QgsFeature currentFeature;
+  QgsGeometry* dissolveGeometry; //dissolve geometry
+  QMultiMap<QString, int> map;
+  bool useField = false;
+
+  if ( uniqueIdField == -1 )
+  {
+    uniqueIdField = 0;
+  }
+  else
+  {
+    useField = true;
+    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
+    while ( layer->nextFeature( currentFeature ) )
     {
-      if ( geometry.isMultipart() )
-      {
-        polyList = geometry.asMultiPolygon();
-        for ( polygon = polyList.begin(); polygon != polyList.end(); polygon++ )
+      map.insert( currentFeature.attributeMap()[uniqueIdField].toString(), currentFeature.id() );
+    }
+  }
+  QMultiMap<QString, int>::const_iterator jt;
+  for (jt = map.constBegin(); jt != map.constEnd(); ++jt)
+  {
+    QString currentKey = jt.key();
+    int processedFeatures = 0;
+    //take only selection
+    if ( onlySelectedFeatures )
+    {
+        //use QgsVectorLayer::featureAtId
+        const QgsFeatureIds selection = layer->selectedFeaturesIds();
+        if ( p )
         {
-          for ( lines = polygon.begin(); lines != polygon.end(); lines++ )
+            p->setMaximum( selection.size() );
+        }
+        processedFeatures = 0;
+        while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
+        {
+          if ( p && p->wasCanceled() )
           {
-            lineList << lines;
+            break;
           }
+          if ( selection.contains( jt.value() ) )
+          {
+            if ( p )
+            {
+                p->setValue( processedFeatures );
+            }
+            if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
+            {
+                continue;
+            }
+            convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
+            ++processedFeatures;
+          }
+          ++jt;
         }
-        else
+        QgsFeature dissolveFeature;
+        dissolveFeature.setGeometry( dissolveGeometry );
+        vWriter.addFeature( dissolveFeature );
+    }
+    //take all features
+    else
+    {
+      int featureCount = layer->featureCount();
+      if ( p )
+      {
+        p->setMaximum( featureCount );
+      }
+      processedFeatures = 0;
+      while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
+      {
+        if ( p )
         {
-          lineList = geometry.asPolygon();
+          p->setValue( processedFeatures );
         }
+
+        if ( p && p->wasCanceled() )
+        {
+          break;
+        }
+        if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
+        {
+          continue;
+        }
+        convexFeature( currentFeature, processedFeatures, &dissolveGeometry );
+        ++processedFeatures;
+        ++jt;
       }
+      QgsFeature dissolveFeature;
+      dissolveFeature.setGeometry( dissolveGeometry );
+      vWriter.addFeature( dissolveFeature );
     }
-    return lineList
-    */
+  }
+  return true;
 }
-QgsGeometry* QgsGeometryAnalyzer::extractAsSingle( QgsGeometry* geometry )
-{
-  return NULL;
-  /*
-      multi_geom = QgsGeometry()
-      temp_geom = []
-      if geom.type() == 0:
-        if geom.isMultipart()
-          multi_geom = geom.asMultiPoint()
-          for i in multi_geom:
-            temp_geom.append( QgsGeometry().fromPoint ( i ) )
-        else:
-          temp_geom.append( geom )
-      elif geom.type() == 1:
-        if geom.isMultipart()
-          multi_geom = geom.asMultiPolyline()
-          for i in multi_geom:
-            temp_geom.append( QgsGeometry().fromPolyline( i ) )
-        else:
-          temp_geom.append( geom )
-      elif geom.type() == 2:
-        if geom.isMultipart()
-          multi_geom = geom.asMultiPolygon()
-          for i in multi_geom:
-            temp_geom.append( QgsGeometry().fromPolygon( i ) )
-        else:
-          temp_geom.append( geom )
-      return temp_geom
 
-  */
-}
 
-QgsGeometry* QgsGeometryAnalyzer::extractAsMulti( QgsGeometry* geometry )
+void QgsGeometryAnalyzer::convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry)
 {
-  return NULL;
-  /*
-    if ( geometry->mGeos == NULL )
-    {
-      geometry->exportWkbToGeos();
-    }
-    if ( !geometry->mGeos )
-    {
-      return 0;
-    }
-      return fromGeosGeom( GEOSIntersection( mGeos, geometry->mGeos ) );
+  QgsGeometry* featureGeometry = f.geometry();
+  QgsGeometry* tmpGeometry = 0;
+  QgsGeometry* convexGeometry = 0;
 
-    for ( int i = 0; i < geometry.size(); i++ )
-      geomarr[i] = geometry->mGeos[i];
+  if ( !featureGeometry )
+  {
+    return;
+  }
 
-    GEOSGeometry *geom = 0;
+  convexGeometry = featureGeometry->convexHull();
 
-    try
-    {
-      geom = GEOSGeom_createCollection( typeId, geomarr, geoms.size() );
-    }
-    catch ( GEOSException &e )
-    {
-      Q_UNUSED( e );
-    }
+  if ( nProcessedFeatures == 0 )
+  {
+    *dissolveGeometry = convexGeometry;
+  }
+  else
+  {
+    tmpGeometry = *dissolveGeometry;
+    *dissolveGeometry = ( *dissolveGeometry )->combine( convexGeometry );
+    delete tmpGeometry;
+    delete convexGeometry;
+  }
+}
 
-    delete [] geomarr;
+bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName,
+                                      bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p )
+{
+  if ( !layer )
+  {
+    return false;
+  }
 
-    return geom;
+  QgsVectorDataProvider* dp = layer->dataProvider();
+  if ( !dp )
+  {
+    return false;
   }
 
-      temp_geom = []
-      if geom.type() == 0:
-        if geom.isMultipart()
-          return geom.asMultiPoint()
-        else:
-          return [ geom.asPoint() ]
-      elif geom.type() == 1:
-        if geom.isMultipart()
-          return geom.asMultiPolyline()
-        else:
-          return [ geom.asPolyline() ]
-      else:
-        if geom.isMultipart()
-          return geom.asMultiPolygon()
-        else:
-          return [ geom.asPolygon() ]
+  QGis::WkbType outputType = dp->geometryType();
+  const QgsCoordinateReferenceSystem crs = layer->srs();
 
-  */
+  QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs );
+  QgsFeature currentFeature;
+  QgsGeometry* dissolveGeometry; //dissolve geometry
+  QMultiMap<QString, int> map;
+  bool useField = false;
 
-}
-
-QgsGeometry* QgsGeometryAnalyzer::convertGeometry( QgsGeometry* geometry )
-{
-  return NULL;
-  /*
-    if vType == 0:
-      return QgsGeometry().fromMultiPoint(geom_list)
-    elif vType == 1:
-      return QgsGeometry().fromMultiPolyline(geom_list)
-    else:
-      return QgsGeometry().fromMultiPolygon(geom_list)
-  */
-}
-
-QList<QgsPoint> QgsGeometryAnalyzer::extractPoints( QgsGeometry* geometry )
-{
-  return QList<QgsPoint>();
-  /*  QGis::WkbType wkbType = geometry.wkbType();
-    QList<QgsPoint> pointList;
-    QList<QgsPolyline> lineList;
-    switch ( wkbType )
+  if ( uniqueIdField == -1 )
+  {
+    uniqueIdField = 0;
+  }
+  else
+  {
+    useField = true;
+    layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false );
+    while ( layer->nextFeature( currentFeature ) )
     {
-      case QGis::WKBPoint25D:
-      case QGis::WKBPoint:
-      case QGis::WKBMultiLineString25D:
-      case QGis::WKBMultiLineString:
+      map.insert( currentFeature.attributeMap()[uniqueIdField].toString(), currentFeature.id() );
+    }
+  }
+  QMultiMap<QString, int>::const_iterator jt;
+  for (jt = map.constBegin(); jt != map.constEnd(); ++jt)
+  {
+    QString currentKey = jt.key();
+    int processedFeatures = 0;
+    //take only selection
+    if ( onlySelectedFeatures )
+    {
+        //use QgsVectorLayer::featureAtId
+        const QgsFeatureIds selection = layer->selectedFeaturesIds();
+        if ( p )
+        {
+            p->setMaximum( selection.size() );
+        }
+        processedFeatures = 0;
+        while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
+        {
+          if ( p && p->wasCanceled() )
+          {
+            break;
+          }
+          if ( selection.contains( jt.value() ) )
+          {
+            if ( p )
+            {
+                p->setValue( processedFeatures );
+            }
+            if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
+            {
+                continue;
+            }
+            dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
+            ++processedFeatures;
+          }
+          ++jt;
+        }
+        QgsFeature dissolveFeature;
+        dissolveFeature.setGeometry( dissolveGeometry );
+        vWriter.addFeature( dissolveFeature );
+    }
+    //take all features
+    else
+    {
+      int featureCount = layer->featureCount();
+      if ( p )
       {
-        geometry->convertToMultitype();
-        pointList = geometry.asMultiPoint();
-        break;
+        p->setMaximum( featureCount );
       }
-      case QGis::WKBLineString25D:
-      case QGis::WKBLineString:
-      case QGis::WKBMultiLineString25D:
-      case QGis::WKBMultiLineString:
+      processedFeatures = 0;
+      while ( jt != map.end() && ( jt.key() == currentKey || !useField ) )
       {
-        geometry->convertToMultitype();
-        lineList = geometry.asMultiPolyline();
-        for ( line = lineList.begin(); line != lineList.end(); line++ )
+        if ( p )
         {
-          pointList << line;
+          p->setValue( processedFeatures );
         }
-        break;
-      }
-      case QGis::WKBPolygon25D:
-      case QGis::WKBPolygon:
-      case QGis::WKBMultiPolygon25D:
-      case QGis::WKBMultiPolygon:
-      {
-        geometry->convertToMultitype();
-        QgsPolygon polyList = geometry.asMultiPolygon();
-        for ( lineList = polyList.begin(); lineList != polyList.end(); lineList++ )
+
+        if ( p && p->wasCanceled() )
         {
-          for ( line = lineList.begin(); line != lineList.end(); line++ )
-          {
-            pointList << line;
-          }
+          break;
         }
-        break;
+        if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) )
+        {
+          continue;
+        }
+        dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry );
+        ++processedFeatures;
+        ++jt;
       }
-      default:
-        break;
+      QgsFeature dissolveFeature;
+      dissolveFeature.setGeometry( dissolveGeometry );
+      vWriter.addFeature( dissolveFeature );
     }
-    return pointList;
-    */
+  }
+  return true;
 }
 
+void QgsGeometryAnalyzer::dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry )
+{
+  QgsGeometry* featureGeometry = f.geometry();
+  QgsGeometry* tmpGeometry = 0;
+
+  if ( !featureGeometry )
+  {
+    return;
+  }
+
+  if ( nProcessedFeatures == 0 )
+  {
+    *dissolveGeometry = featureGeometry;
+  }
+  else
+  {
+    tmpGeometry = *dissolveGeometry;
+    *dissolveGeometry = ( *dissolveGeometry )->combine( featureGeometry );
+    delete tmpGeometry;
+  }
+}
+
 bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance, \
                                   bool onlySelectedFeatures, bool dissolve, int bufferDistanceField, QProgressDialog* p )
 {

Modified: trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.h
===================================================================
--- trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.h	2009-11-07 19:20:35 UTC (rev 11975)
+++ trunk/qgis/src/analysis/vector/qgsgeometryanalyzer.h	2009-11-07 19:22:27 UTC (rev 11976)
@@ -38,73 +38,38 @@
 {
   public:
 
-    /**
-     * Convert a vector layer from single part geometry
-     * to multipart geometry for a given field
-     *
-     * */
-    bool singlepartsToMultipart( QgsVectorLayer* layer,
-                                 const QString& shapefileName,
-                                 const QString& fileEncoding,
-                                 const int fieldIndex );
+    /**Simplify vector layer using (a modified) Douglas-Peucker algorithm
+     and write it to a new shape file
+      @param layer input vector layer
+      @param shapefileName path to the output shp
+      @param fileEncoding encoding of the output file
+      @param tolerance (level of simplification)
+      @param onlySelectedFeatures if true, only selected features are considered, else all the features
+      @param p progress dialog (or 0 if no progress dialog is to be shown)
+      @note: added in version 1.4*/
+    bool simplify( QgsVectorLayer* layer, const QString& shapefileName, double tolerance, \
+                 bool onlySelectedFeatures = false, QProgressDialog* p = 0 );
 
-    /**
-     * Convert multipart features to multiple singlepart features. Creates
-     * simple polygons and lines.
-     */
-    bool multipartToSingleparts( QgsVectorLayer* layer,
-                                 const QString& shapefileName,
-                                 const QString& fileEncoding );
+    /**Calculate the true centroids, or 'center of mass' for a vector layer and 
+       write it to a new shape file
+      @param layer input vector layer
+      @param shapefileName path to the output shp
+      @param fileEncoding encoding of the output file
+      @param onlySelectedFeatures if true, only selected features are considered, else all the features
+      @param p progress dialog (or 0 if no progress dialog is to be shown)
+      @note: added in version 1.4*/
+    bool centroids( QgsVectorLayer* layer, const QString& shapefileName, \
+                 bool onlySelectedFeatures = false, QProgressDialog* p = 0 );
 
-    /**
-     * Extract nodes from line and polygon vector layers and output them as
-     * points.
-     * */
-    bool extractNodes( QgsVectorLayer* layer,
-                       const QString& shapefileName,
-                       const QString& fileEncoding );
+    /**Create a polygon based on the extent of all (selected) features and write it to a new shape file
+      @param layer input vector layer
+      @param shapefileName path to the output shp
+      @param fileEncoding encoding of the output file
+      @param onlySelectedFeatures if true, only selected features are considered, else all the features
+      @param p progress dialog (or 0 if no progress dialog is to be shown)
+      @note: added in version 1.4*/
+    bool extent( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures = false, QProgressDialog* p = 0 );
 
-    /**
-     * Convert polygon features to line features. Multipart polygons are
-     * converted to multiple singlepart lines.
-     */
-    bool polygonsToLines( QgsVectorLayer* layer,
-                          const QString& shapefileName,
-                          const QString& fileEncoding );
-
-    /**
-     * Add vector layer geometry info to point (XCOORD, YCOORD), line (LENGTH),
-     * or polygon (AREA, PERIMETER) layer.
-     */
-    bool exportGeometryInformation( QgsVectorLayer* layer,
-                                    const QString& shapefileName,
-                                    const QString& fileEncoding );
-
-    /**
-     * Simplify (generalise) line or polygon vector layers using (a modified)
-     * Douglas-Peucker algorithm.
-     */
-    bool simplifyGeometry( QgsVectorLayer* layer,
-                           const QString shapefileName,
-                           const QString fileEncoding,
-                           const double tolerance );
-
-    /**
-     * Calculate the true centroids, or 'center of mass' for each polygon in an
-     * input polygon layer.
-     */
-    bool polygonCentroids( QgsVectorLayer* layer,
-                           const QString& shapefileName,
-                           const QString& fileEncoding );
-
-    /**
-     * Create a polygon based on the extents of all features (or all
-     * selected features if applicable) and write it out to a shp.
-     */
-    bool layerExtent( QgsVectorLayer* layer,
-                      const QString& shapefileName,
-                      const QString& fileEncoding );
-
     /**Create buffers for a vector layer and write it to a new shape file
       @param layer input vector layer
       @param shapefileName path to the output shp
@@ -118,19 +83,45 @@
     bool buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance, \
                  bool onlySelectedFeatures = false, bool dissolve = false, int bufferDistanceField = -1, QProgressDialog* p = 0 );
 
+    /**Create convex hull(s) of a vector layer and write it to a new shape file
+      @param layer input vector layer
+      @param shapefileName path to the output shp
+      @param fileEncoding encoding of the output file
+      @param onlySelectedFeatures if true, only selected features are considered, else all the features
+      @param uniqueIdField index of the attribute field that contains the unique convex hull id (or -1 if
+      all features have the same buffer distance)
+      @param p progress dialog (or 0 if no progress dialog is to be shown)
+      @note: added in version 1.4*/
+    bool convexHull( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures = false, \
+                     int uniqueIdField = -1, QProgressDialog* p = 0 );
+
+    /**Dissolve a vector layer and write it to a new shape file
+      @param layer input vector layer
+      @param shapefileName path to the output shp
+      @param fileEncoding encoding of the output file
+      @param onlySelectedFeatures if true, only selected features are considered, else all the features
+      @param uniqueIdField index of the attribute field that contains the unique id to dissolve on (or -1 if
+      all features should be dissolved together)
+      @param p progress dialog (or 0 if no progress dialog is to be shown)
+      @note: added in version 1.4*/
+    bool dissolve( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures = false, \
+                     int uniqueIdField = -1, QProgressDialog* p = 0 );
+
   private:
 
     QList<double> simpleMeasure( QgsGeometry* geometry );
     double perimeterMeasure( QgsGeometry* geometry, QgsDistanceArea& measure );
-    QgsFieldMap checkGeometryFields( QgsVectorLayer* layer, int& index1, int& index2 );
-    QgsGeometry* extractLines( QgsGeometry* geometry );
-    QgsGeometry* extractAsSingle( QgsGeometry* geometry );
-    QgsGeometry* extractAsMulti( QgsGeometry* geometry );
-    QgsGeometry* convertGeometry( QgsGeometry* geometry );
-    QList<QgsPoint> extractPoints( QgsGeometry* geometry );
+    /**Helper function to simplify an individual feature*/
+    void simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance );
+    /**Helper function to get the cetroid of an individual feature*/
+    void centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw );
     /**Helper function to buffer an individual feature*/
     void bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, bool dissolve, QgsGeometry** dissolveGeometry, \
                         double bufferDistance, int bufferDistanceField );
+    /**Helper function to get the convex hull of feature(s)*/
+    void convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry );
+    /**Helper function to dissolve feature(s)*/
+    void dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry );
 
 };
 #endif //QGSVECTORANALYZER



More information about the QGIS-commit mailing list