[QGIS Commit] r10700 - in trunk/qgis: images/themes/default python/core src/app src/core src/ui

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sat May 2 11:37:35 EDT 2009


Author: wonder
Date: 2009-05-02 11:37:35 -0400 (Sat, 02 May 2009)
New Revision: 10700

Added:
   trunk/qgis/images/themes/default/mActionDeleteHole.png
   trunk/qgis/images/themes/default/mActionDeletePart.png
   trunk/qgis/images/themes/default/mActionSimplify.png
   trunk/qgis/src/app/qgsmaptooldeletehole.cpp
   trunk/qgis/src/app/qgsmaptooldeletehole.h
   trunk/qgis/src/app/qgsmaptooldeletepart.cpp
   trunk/qgis/src/app/qgsmaptooldeletepart.h
   trunk/qgis/src/app/qgsmaptoolsimplify.cpp
   trunk/qgis/src/app/qgsmaptoolsimplify.h
   trunk/qgis/src/ui/qgssimplifytolerancedialog.ui
Modified:
   trunk/qgis/python/core/qgsgeometry.sip
   trunk/qgis/src/app/CMakeLists.txt
   trunk/qgis/src/app/qgisapp.cpp
   trunk/qgis/src/app/qgisapp.h
   trunk/qgis/src/core/qgsgeometry.cpp
   trunk/qgis/src/core/qgsgeometry.h
Log:
New vector editing tools:
- delete part of multipart feature
- delete hole from polygon
- simplify feature

These tools are in the new "advanced" editing toolbar.
Contributed by Richard Kostecky (qgis-mapper project).


Added: trunk/qgis/images/themes/default/mActionDeleteHole.png
===================================================================
(Binary files differ)


Property changes on: trunk/qgis/images/themes/default/mActionDeleteHole.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/qgis/images/themes/default/mActionDeletePart.png
===================================================================
(Binary files differ)


Property changes on: trunk/qgis/images/themes/default/mActionDeletePart.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/qgis/images/themes/default/mActionSimplify.png
===================================================================
(Binary files differ)


Property changes on: trunk/qgis/images/themes/default/mActionSimplify.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/qgis/python/core/qgsgeometry.sip
===================================================================
--- trunk/qgis/python/core/qgsgeometry.sip	2009-05-02 14:27:25 UTC (rev 10699)
+++ trunk/qgis/python/core/qgsgeometry.sip	2009-05-02 15:37:35 UTC (rev 10700)
@@ -289,5 +289,16 @@
     // TODO: destruction of created geometries??
     QList<QgsGeometry*> asGeometryCollection() /Factory/;
 
+    /** delete a hole in polygon or multipolygon.
+      Ring 0 is outer ring and can't be deleted.
+      @return TRUE on success
+      @note added in version 1.2 */
+    bool deleteHole( int ringNum, int partNum = 0 );
+
+    /** delete part identified by the part number
+      @return TRUE on success
+      @note added in version 1.2 */
+    bool deletePart( int partNum );
+
 }; // class QgsGeometry
 

Modified: trunk/qgis/src/app/CMakeLists.txt
===================================================================
--- trunk/qgis/src/app/CMakeLists.txt	2009-05-02 14:27:25 UTC (rev 10699)
+++ trunk/qgis/src/app/CMakeLists.txt	2009-05-02 15:37:35 UTC (rev 10700)
@@ -27,12 +27,15 @@
   qgsmaptooladdisland.cpp
   qgsmaptooladdring.cpp
   qgsmaptoolcapture.cpp
+  qgsmaptooldeletehole.cpp
+  qgsmaptooldeletepart.cpp
   qgsmaptooldeletevertex.cpp
   qgsmaptooledit.cpp
   qgsmaptoolidentify.cpp
   qgsmaptoolmovefeature.cpp
   qgsmaptoolmovevertex.cpp
   qgsmaptoolselect.cpp
+  qgsmaptoolsimplify.cpp
   qgsmaptoolsplitfeatures.cpp
   qgsmaptoolvertexedit.cpp
   qgsmeasuredialog.cpp
@@ -115,6 +118,7 @@
   qgsmaptooladdring.h
   qgsmaptoolmovefeature.h
   qgsmaptoolselect.h
+  qgsmaptoolsimplify.h
 
   qgsmeasuretool.h
   qgsmeasuredialog.h

Modified: trunk/qgis/src/app/qgisapp.cpp
===================================================================
--- trunk/qgis/src/app/qgisapp.cpp	2009-05-02 14:27:25 UTC (rev 10699)
+++ trunk/qgis/src/app/qgisapp.cpp	2009-05-02 15:37:35 UTC (rev 10700)
@@ -157,6 +157,8 @@
 #include "qgsmaptooladdisland.h"
 #include "qgsmaptooladdring.h"
 #include "qgsmaptooladdvertex.h"
+#include "qgsmaptooldeletehole.h"
+#include "qgsmaptooldeletepart.h"
 #include "qgsmaptooldeletevertex.h"
 #include "qgsmaptoolidentify.h"
 #include "qgsmaptoolmovefeature.h"
@@ -166,6 +168,7 @@
 #include "qgsmaptoolsplitfeatures.h"
 #include "qgsmaptoolvertexedit.h"
 #include "qgsmaptoolzoom.h"
+#include "qgsmaptoolsimplify.h"
 #include "qgsmeasuretool.h"
 
 //
@@ -465,6 +468,9 @@
   delete mMapTools.mVertexMove;
   delete mMapTools.mVertexDelete;
   delete mMapTools.mAddRing;
+  delete mMapTools.mSimplifyFeature;
+  delete mMapTools.mDeleteHole;
+  delete mMapTools.mDeletePart;
   delete mMapTools.mAddIsland;
 
   delete mPythonConsole;
@@ -667,6 +673,22 @@
   connect( mActionAddIsland, SIGNAL( triggered() ), this, SLOT( addIsland() ) );
   mActionAddIsland->setEnabled( false );
 
+  mActionSimplifyFeature = new QAction( getThemeIcon( "mActionSimplify.png" ), tr( "Simplify Feature" ), this );
+  mActionSimplifyFeature->setStatusTip( tr( "Simplify Feature" ) );
+  connect( mActionSimplifyFeature, SIGNAL( triggered() ), this, SLOT( simplifyFeature() ) );
+  mActionSimplifyFeature->setEnabled( false );
+
+  mActionDeleteHole = new QAction( getThemeIcon( "mActionDeleteHole.png" ), tr( "Delete Hole" ), this );
+  mActionDeleteHole->setStatusTip( tr( "Delete Hole" ) );
+  connect( mActionDeleteHole, SIGNAL( triggered() ), this, SLOT( deleteHole() ) );
+  mActionDeleteHole->setEnabled( false );
+
+  mActionDeletePart = new QAction( getThemeIcon( "mActionDeletePart.png" ), tr( "Delete Part" ), this );
+  mActionDeletePart->setStatusTip( tr( "Delete Part" ) );
+  connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
+  mActionDeletePart->setEnabled( false );
+
+
   // View Menu Items
 
   mActionPan = new QAction( getThemeIcon( "mActionPan.png" ), tr( "Pan Map" ), this );
@@ -990,6 +1012,12 @@
   mMapToolGroup->addAction( mActionAddRing );
   mActionAddIsland->setCheckable( true );
   mMapToolGroup->addAction( mActionAddIsland );
+  mActionSimplifyFeature->setCheckable( true );
+  mMapToolGroup->addAction( mActionSimplifyFeature );
+  mActionDeleteHole->setCheckable( true );
+  mMapToolGroup->addAction( mActionDeleteHole );
+  mActionDeletePart->setCheckable( true );
+  mMapToolGroup->addAction( mActionDeletePart );
 }
 
 void QgisApp::createMenus()
@@ -1073,9 +1101,15 @@
   mEditMenu->addAction( mActionAddRing );
   mEditMenu->addAction( mActionAddIsland );
 
+  mActionEditSeparator2 = mEditMenu->addSeparator();
+
+  mEditMenu->addAction( mActionSimplifyFeature );
+  mEditMenu->addAction( mActionDeleteHole );
+  mEditMenu->addAction( mActionDeletePart );
+
   if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
   {
-    mActionEditSeparator2 = mEditMenu->addSeparator();
+    mActionEditSeparator3 = mEditMenu->addSeparator();
     mEditMenu->addAction( mActionOptions );
     mEditMenu->addAction( mActionCustomProjection );
   }
@@ -1267,6 +1301,16 @@
   mDigitizeToolBar->addAction( mActionCopyFeatures );
   mDigitizeToolBar->addAction( mActionPasteFeatures );
   mToolbarMenu->addAction( mDigitizeToolBar->toggleViewAction() );
+
+  mAdvancedDigitizeToolBar = addToolBar( tr( "Advanced Digitizing" ) );
+  mAdvancedDigitizeToolBar->setIconSize( myIconSize );
+  mAdvancedDigitizeToolBar->setObjectName( "Advanced Digitizing" );
+  mAdvancedDigitizeToolBar->addAction( mActionSimplifyFeature );
+  mAdvancedDigitizeToolBar->addAction( mActionDeleteHole );
+  mAdvancedDigitizeToolBar->addAction( mActionDeletePart );
+  mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
+
+
   //
   // Map Navigation Toolbar
   mMapNavToolBar = addToolBar( tr( "Map Navigation" ) );
@@ -1606,6 +1650,12 @@
   mMapTools.mAddRing = new QgsMapToolAddRing( mMapCanvas );
   mMapTools.mAddRing->setAction( mActionAddRing );
   mMapTools.mAddIsland = new QgsMapToolAddIsland( mMapCanvas );
+  mMapTools.mSimplifyFeature = new QgsMapToolSimplify( mMapCanvas );
+  mMapTools.mSimplifyFeature->setAction( mActionSimplifyFeature );
+  mMapTools.mDeleteHole = new QgsMapToolDeleteHole( mMapCanvas );
+  mMapTools.mDeleteHole->setAction( mActionDeleteHole );
+  mMapTools.mDeletePart = new QgsMapToolDeletePart( mMapCanvas );
+  mMapTools.mDeletePart->setAction( mActionDeletePart );
   //ensure that non edit tool is initialised or we will get crashes in some situations
   mNonEditMapTool = mMapTools.mPan;
 }
@@ -3979,6 +4029,21 @@
   mMapCanvas->setMapTool( mMapTools.mMoveFeature );
 }
 
+void QgisApp::simplifyFeature()
+{
+  mMapCanvas->setMapTool( mMapTools.mSimplifyFeature );
+}
+
+void QgisApp::deleteHole()
+{
+  mMapCanvas->setMapTool( mMapTools.mDeleteHole );
+}
+
+void QgisApp::deletePart()
+{
+  mMapCanvas->setMapTool( mMapTools.mDeletePart );
+}
+
 void QgisApp::splitFeatures()
 {
   mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
@@ -5215,11 +5280,13 @@
         {
           mActionCapturePoint->setEnabled( true );
           mActionCapturePoint->setVisible( true );
+          mActionDeletePart->setEnabled( true );
         }
         else
         {
           mActionCapturePoint->setEnabled( false );
           mActionCapturePoint->setVisible( false );
+          mActionDeletePart->setEnabled( false );
         }
         mActionCaptureLine->setEnabled( false );
         mActionCapturePolygon->setEnabled( false );
@@ -5231,6 +5298,9 @@
         mActionAddRing->setEnabled( false );
         mActionAddIsland->setEnabled( false );
         mActionSplitFeatures->setEnabled( false );
+        mActionSimplifyFeature->setEnabled( false );
+        mActionDeleteHole->setEnabled( false );
+
         if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
         {
           mActionMoveVertex->setEnabled( true );
@@ -5244,12 +5314,16 @@
           mActionCaptureLine->setEnabled( true );
           mActionCaptureLine->setVisible( true );
           mActionSplitFeatures->setEnabled( true );
+          mActionSimplifyFeature->setEnabled( true );
+          mActionDeletePart->setEnabled( true );
         }
         else
         {
           mActionCaptureLine->setEnabled( false );
           mActionCaptureLine->setVisible( false );
           mActionSplitFeatures->setEnabled( false );
+          mActionSimplifyFeature->setEnabled( false );
+          mActionDeletePart->setEnabled( false );
         }
         mActionCapturePoint->setEnabled( false );
         mActionCapturePolygon->setEnabled( false );
@@ -5257,6 +5331,7 @@
         mActionCapturePolygon->setVisible( false );
         mActionAddRing->setEnabled( false );
         mActionAddIsland->setEnabled( false );
+        mActionDeleteHole->setEnabled( false );
       }
       else if ( vlayer->geometryType() == QGis::Polygon )
       {
@@ -5267,6 +5342,9 @@
           mActionAddRing->setEnabled( true );
           mActionAddIsland->setEnabled( true );
           mActionSplitFeatures->setEnabled( true );
+          mActionSimplifyFeature->setEnabled( true );
+          mActionDeleteHole->setEnabled( true );
+          mActionDeletePart->setEnabled( true );
         }
         else
         {
@@ -5275,6 +5353,9 @@
           mActionAddRing->setEnabled( false );
           mActionAddIsland->setEnabled( false );
           mActionSplitFeatures->setEnabled( false );
+          mActionSimplifyFeature->setEnabled( false );
+          mActionDeleteHole->setEnabled( false );
+          mActionDeletePart->setEnabled( false );
         }
         mActionCapturePoint->setEnabled( false );
         mActionCaptureLine->setEnabled( false );

Modified: trunk/qgis/src/app/qgisapp.h
===================================================================
--- trunk/qgis/src/app/qgisapp.h	2009-05-02 14:27:25 UTC (rev 10699)
+++ trunk/qgis/src/app/qgisapp.h	2009-05-02 15:37:35 UTC (rev 10700)
@@ -42,6 +42,8 @@
 class QgsClipboard;
 class QgsComposer;
 class QgsHelpViewer;
+class QgsFeature;
+
 class QgsLegend;
 class QgsMapCanvas;
 class QgsMapLayer;
@@ -63,7 +65,6 @@
 #include "qgsconfig.h"
 #include "qgspoint.h"
 
-
 /*! \class QgisApp
  * \brief Main window for the Qgis application
  */
@@ -221,6 +222,9 @@
     QAction *actionMoveVertex() { return mActionMoveVertex; }
     QAction *actionAddRing() { return mActionAddRing; }
     QAction *actionAddIsland() { return mActionAddIsland; }
+    QAction *actionSimplifyFeature() { return mActionSimplifyFeature; }
+    QAction *actionDeleteHole() { return mActionDeleteHole; }
+    QAction *actionDeletePart() { return mActionDeletePart; }
     QAction *actionEditSeparator2() { return mActionEditSeparator2; }
 
     QAction *actionPan() { return mActionPan; }
@@ -318,6 +322,7 @@
     QToolBar *layerToolBar() { return mLayerToolBar; }
     QToolBar *mapNavToolToolBar() { return mMapNavToolBar; }
     QToolBar *digitizeToolBar() { return mDigitizeToolBar; }
+    QToolBar *advancedDigitizeToolBar() { return mAdvancedDigitizeToolBar; }
     QToolBar *attributesToolBar() { return mAttributesToolBar; }
     QToolBar *pluginToolBar() { return mPluginToolBar; }
     QToolBar *helpToolBar() { return mHelpToolBar; }
@@ -495,6 +500,12 @@
     void addRing();
     //! activates the add island tool
     void addIsland();
+    //! simplifies feature
+    void simplifyFeature();
+    //! deletes hole in polygon
+    void deleteHole();
+    //! deletes part of polygon
+    void deletePart();
 
     //! activates the selection tool
     void select();
@@ -666,6 +677,7 @@
     QToolBar *mLayerToolBar;
     QToolBar *mMapNavToolBar;
     QToolBar *mDigitizeToolBar;
+    QToolBar *mAdvancedDigitizeToolBar;
     QToolBar *mAttributesToolBar;
     QToolBar *mPluginToolBar;
     QToolBar *mHelpToolBar;
@@ -701,6 +713,10 @@
     QAction *mActionAddRing;
     QAction *mActionAddIsland;
     QAction *mActionEditSeparator2;
+    QAction *mActionSimplifyFeature;
+    QAction *mActionDeleteHole;
+    QAction *mActionDeletePart;
+    QAction *mActionEditSeparator3;
 
     QAction *mActionPan;
     QAction *mActionZoomIn;
@@ -816,6 +832,9 @@
         QgsMapTool* mVertexDelete;
         QgsMapTool* mAddRing;
         QgsMapTool* mAddIsland;
+        QgsMapTool* mSimplifyFeature;
+        QgsMapTool* mDeleteHole;
+        QgsMapTool* mDeletePart;
     } mMapTools;
 
     QgsMapTool *mNonEditMapTool;
@@ -921,6 +940,7 @@
     QgsPythonUtils* mPythonUtils;
 
     static QgisApp *smInstance;
+
 };
 
 #endif

Added: trunk/qgis/src/app/qgsmaptooldeletehole.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletehole.cpp	                        (rev 0)
+++ trunk/qgis/src/app/qgsmaptooldeletehole.cpp	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,161 @@
+/***************************************************************************
+    qgsmaptooldeletehole.h  - delete a hole from polygon
+    ---------------------
+    begin                : April 2009
+    copyright            : (C) 2009 by Richard Kostecky
+    email                : csf dot kostej at mail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "qgsmaptooldeletehole.h"
+
+#include "qgsmapcanvas.h"
+#include "qgsvertexmarker.h"
+#include "qgsvectorlayer.h"
+
+#include <QMouseEvent>
+#include <QMessageBox>
+
+QgsMapToolDeleteHole::QgsMapToolDeleteHole( QgsMapCanvas* canvas )
+  : QgsMapToolVertexEdit( canvas ), mCross( 0 )
+{
+}
+
+QgsMapToolDeleteHole::~QgsMapToolDeleteHole()
+{
+  delete mCross;
+}
+
+void QgsMapToolDeleteHole::canvasMoveEvent( QMouseEvent * e )
+{
+  //nothing to do
+}
+
+void QgsMapToolDeleteHole::canvasPressEvent( QMouseEvent * e )
+{
+  delete mCross;
+  mCross = 0;
+
+  mRecentSnappingResults.clear();
+  //do snap -> new recent snapping results
+  if ( mSnapper.snapToCurrentLayer( e->pos(), mRecentSnappingResults, QgsSnapper::SnapToVertex ) != 0 )
+  {
+    //error
+  }
+
+  if ( mRecentSnappingResults.size() > 0 )
+  {
+    QgsPoint markerPoint = mRecentSnappingResults.begin()->snappedVertex;
+
+    //show vertex marker
+    mCross = new QgsVertexMarker( mCanvas );
+    mCross->setIconType( QgsVertexMarker::ICON_X );
+    mCross->setCenter( markerPoint );
+  }
+  else
+  {
+    displaySnapToleranceWarning();
+  }
+}
+
+void QgsMapToolDeleteHole::canvasReleaseEvent( QMouseEvent * e )
+{
+  delete mCross;
+  mCross = 0;
+
+  QgsMapLayer* currentLayer = mCanvas->currentLayer();
+  if ( !currentLayer )
+    return;
+
+  QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+  if ( !vlayer )
+    return;
+
+
+  if ( mRecentSnappingResults.size() > 0 )
+  {
+    QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
+    for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
+    {
+      deleteHole( sr_it->snappedAtGeometry, sr_it->snappedVertexNr, vlayer);
+    }
+  }
+}
+
+
+void QgsMapToolDeleteHole::deleteHole( int fId, int beforeVertexNr, QgsVectorLayer* vlayer)
+{
+  QgsFeature f;
+  vlayer->featureAtId( fId, f );
+
+  QgsGeometry* g = f.geometry();
+  QGis::WkbType wkbtype = g->wkbType();
+  int ringNum, partNum = 0;
+
+  if (wkbtype == QGis::WKBPolygon || wkbtype == QGis::WKBPolygon25D)
+  {
+    ringNum = ringNumInPolygon( g, beforeVertexNr );
+  }
+  else if (wkbtype == QGis::WKBMultiPolygon || wkbtype == QGis::WKBMultiPolygon25D)
+  {
+    ringNum = ringNumInMultiPolygon( g, beforeVertexNr, partNum );
+  }
+  else
+    return;
+
+  if (g->deleteHole( ringNum, partNum ))
+  {
+    vlayer->deleteFeature( fId );
+    vlayer->addFeature(f);
+    mCanvas->refresh();
+  }
+  
+}
+
+int QgsMapToolDeleteHole::ringNumInPolygon( QgsGeometry* g, int vertexNr )
+{
+  QgsPolygon polygon = g->asPolygon();
+  for (int ring = 0; ring < polygon.count(); ring++)
+  {
+    if (vertexNr < polygon[ring].count())
+      return ring;
+
+    vertexNr -= polygon[ring].count();
+  }
+  return -1;
+}
+
+int QgsMapToolDeleteHole::ringNumInMultiPolygon( QgsGeometry* g, int vertexNr, int& partNum )
+{
+  QgsMultiPolygon mpolygon = g->asMultiPolygon();
+  for (int part = 0; part < mpolygon.count(); part++)
+  {
+    const QgsPolygon& polygon = mpolygon[part];
+    for (int ring = 0; ring < polygon.count(); ring++)
+    {
+      if (vertexNr < polygon[ring].count())
+      {
+        partNum = part;
+        return ring;
+      }
+
+      vertexNr -= polygon[ring].count();
+    }
+  }
+  return -1;
+}
+
+
+void QgsMapToolDeleteHole::deactivate()
+{
+  delete mCross;
+  mCross = 0;
+
+  QgsMapTool::deactivate();
+}

Added: trunk/qgis/src/app/qgsmaptooldeletehole.h
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletehole.h	                        (rev 0)
+++ trunk/qgis/src/app/qgsmaptooldeletehole.h	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,53 @@
+/***************************************************************************
+    qgsmaptooldeletehole.h  - delete a hole from polygon
+    ---------------------
+    begin                : April 2009
+    copyright            : (C) 2009 by Richard Kostecky
+    email                : csf dot kostej at mail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef QGSMAPTOOLDELETEHOLE_H
+#define QGSMAPTOOLDELETEHOLE_H
+
+#include "qgsmaptoolvertexedit.h"
+#include <QUndoCommand>
+
+class QgsVertexMarker;
+/**Map tool to delete vertices from line/polygon features*/
+
+class QgsMapToolDeleteHole: public QgsMapToolVertexEdit
+{
+  public:
+    QgsMapToolDeleteHole( QgsMapCanvas* canvas );
+    virtual ~QgsMapToolDeleteHole();
+
+    void canvasMoveEvent( QMouseEvent * e );
+
+    void canvasPressEvent( QMouseEvent * e );
+
+    void canvasReleaseEvent( QMouseEvent * e );
+
+    //! called when map tool is being deactivated
+    void deactivate();
+
+  private:
+    QgsVertexMarker* mCross;
+
+    //! delete hole from the geometry
+    void deleteHole( int fId, int beforeVertexNr, QgsVectorLayer* vlayer);
+
+    //! return ring number in polygon
+    int ringNumInPolygon( QgsGeometry* g, int vertexNr );
+
+    //! return ring number in multipolygon and set parNum to index of the part
+    int ringNumInMultiPolygon( QgsGeometry* g, int vertexNr, int& partNum );
+};
+
+#endif

Added: trunk/qgis/src/app/qgsmaptooldeletepart.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletepart.cpp	                        (rev 0)
+++ trunk/qgis/src/app/qgsmaptooldeletepart.cpp	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,178 @@
+/***************************************************************************
+    qgsmaptooldeletepart.cpp  - delete a part from multipart geometry
+    ---------------------
+    begin                : April 2009
+    copyright            : (C) 2009 by Richard Kostecky
+    email                : csf dot kostej at mail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "qgsmaptooldeletepart.h"
+
+#include "qgsmapcanvas.h"
+#include "qgsvertexmarker.h"
+#include "qgsvectorlayer.h"
+
+#include <QMouseEvent>
+#include <QMessageBox>
+
+QgsMapToolDeletePart::QgsMapToolDeletePart( QgsMapCanvas* canvas )
+  : QgsMapToolVertexEdit( canvas ), mCross( 0 )
+{
+}
+
+QgsMapToolDeletePart::~QgsMapToolDeletePart()
+{
+  delete mCross;
+}
+
+void QgsMapToolDeletePart::canvasMoveEvent( QMouseEvent * e )
+{
+  //nothing to do
+}
+
+void QgsMapToolDeletePart::canvasPressEvent( QMouseEvent * e )
+{
+  delete mCross;
+  mCross = 0;
+
+  mRecentSnappingResults.clear();
+  //do snap -> new recent snapping results
+  if ( mSnapper.snapToCurrentLayer( e->pos(), mRecentSnappingResults, QgsSnapper::SnapToVertex ) != 0 )
+  {
+    //error
+  }
+
+  if ( mRecentSnappingResults.size() > 0 )
+  {
+    QgsPoint markerPoint = mRecentSnappingResults.begin()->snappedVertex;
+
+    //show vertex marker
+    mCross = new QgsVertexMarker( mCanvas );
+    mCross->setIconType( QgsVertexMarker::ICON_X );
+    mCross->setCenter( markerPoint );
+  }
+  else
+  {
+    displaySnapToleranceWarning();
+  }
+}
+
+void QgsMapToolDeletePart::canvasReleaseEvent( QMouseEvent * e )
+{
+  delete mCross;
+  mCross = 0;
+
+  QgsMapLayer* currentLayer = mCanvas->currentLayer();
+  if ( !currentLayer )
+    return;
+
+  QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
+  if ( !vlayer )
+    return;
+
+  if ( mRecentSnappingResults.size() > 0 )
+  {
+    QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
+    for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
+    {
+      deletePart( sr_it->snappedAtGeometry, sr_it->snappedVertexNr, vlayer);
+    }
+  }
+
+}
+
+
+void QgsMapToolDeletePart::deletePart( int fId, int beforeVertexNr, QgsVectorLayer* vlayer)
+{
+  QgsFeature f;
+  vlayer->featureAtId( fId, f );
+
+  // find out the part number
+  QgsGeometry* g = f.geometry();
+  if ( !g->isMultipart() )
+  {
+    QMessageBox::information(mCanvas, tr("Delete part"), tr("This isn't a multipart geometry."));
+    return;
+  }
+
+  int partNum = partNumberOfVertex( g, beforeVertexNr );
+
+  if (g->deletePart( partNum ))
+  {
+    vlayer->deleteFeature( fId );
+    vlayer->addFeature(f);
+    mCanvas->refresh();
+  }
+  else
+  {
+    QMessageBox::information(mCanvas, tr("Delete part"), tr("Couldn't remove the selected part."));
+  }
+  
+}
+
+int QgsMapToolDeletePart::partNumberOfVertex( QgsGeometry* g, int beforeVertexNr )
+{
+  int part;
+
+  switch ( g->wkbType() )
+  {
+    case QGis::WKBMultiPoint25D:
+    case QGis::WKBMultiPoint:
+      if ( beforeVertexNr < g->asMultiPoint().count() )
+        return beforeVertexNr;
+      else
+        return -1;
+
+    case QGis::WKBMultiLineString25D:
+    case QGis::WKBMultiLineString:
+    {
+      QgsMultiPolyline mline = g->asMultiPolyline();
+      for (part = 0; part < mline.count(); part++)
+      {
+        if (beforeVertexNr < mline[part].count())
+          return part;
+
+        beforeVertexNr -= mline[part].count();
+      }
+      return -1; // not found
+    }
+
+    case QGis::WKBMultiPolygon25D:
+    case QGis::WKBMultiPolygon:
+    {
+      QgsMultiPolygon mpolygon = g->asMultiPolygon();
+      for (part = 0; part < mpolygon.count(); part++) // go through the polygons
+      {
+        const QgsPolygon& polygon = mpolygon[part];
+        for (int ring = 0; ring < polygon.count(); ring++) // go through the rings
+        {
+          if (beforeVertexNr < polygon[ring].count())
+            return part;
+
+          beforeVertexNr -= polygon[ring].count();
+        }
+      }
+      return -1; // not found
+    }
+
+    default:
+      return -1;
+  }
+}
+
+
+void QgsMapToolDeletePart::deactivate()
+{
+  delete mCross;
+  mCross = 0;
+
+  QgsMapTool::deactivate();
+}
+

Added: trunk/qgis/src/app/qgsmaptooldeletepart.h
===================================================================
--- trunk/qgis/src/app/qgsmaptooldeletepart.h	                        (rev 0)
+++ trunk/qgis/src/app/qgsmaptooldeletepart.h	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,50 @@
+/***************************************************************************
+    qgsmaptooldeletepart.h  - delete a part from multipart geometry
+    ---------------------
+    begin                : April 2009
+    copyright            : (C) 2009 by Richard Kostecky
+    email                : csf dot kostej at mail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef QGSMAPTOOLDELETEPART_H
+#define QGSMAPTOOLDELETEPART_H
+
+#include "qgsmaptoolvertexedit.h"
+
+class QgsVertexMarker;
+
+/**Map tool to delete vertices from line/polygon features*/
+class QgsMapToolDeletePart: public QgsMapToolVertexEdit
+{
+  public:
+    QgsMapToolDeletePart( QgsMapCanvas* canvas );
+    virtual ~QgsMapToolDeletePart();
+
+    void canvasMoveEvent( QMouseEvent * e );
+
+    void canvasPressEvent( QMouseEvent * e );
+
+    void canvasReleaseEvent( QMouseEvent * e );
+
+    //! called when map tool is being deactivated
+    void deactivate();
+
+  private:
+    QgsVertexMarker* mCross;
+
+    //! delete part of a geometry
+    void deletePart( int fId, int beforeVertexNr, QgsVectorLayer* vlayer);
+
+    //! find out part number of geometry given the snapped vertex number
+    int partNumberOfVertex( QgsGeometry* g, int beforeVertexNr );
+
+};
+
+#endif

Added: trunk/qgis/src/app/qgsmaptoolsimplify.cpp
===================================================================
--- trunk/qgis/src/app/qgsmaptoolsimplify.cpp	                        (rev 0)
+++ trunk/qgis/src/app/qgsmaptoolsimplify.cpp	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,381 @@
+/***************************************************************************
+    qgsmaptoolsimplify.cpp  - simplify vector layer features
+    ---------------------
+    begin                : April 2009
+    copyright            : (C) 2009 by Richard Kostecky
+    email                : csf dot kostej at mail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "qgsmaptoolsimplify.h"
+
+#include "qgsgeometry.h"
+#include "qgsmapcanvas.h"
+#include "qgsrubberband.h"
+#include "qgsvectorlayer.h"
+#include "qgstolerance.h"
+
+#include <QMouseEvent>
+
+#include <math.h>
+
+QgsSimplifyDialog::QgsSimplifyDialog(QWidget* parent)
+  : QDialog( parent )
+{
+   setupUi(this);
+   connect( horizontalSlider, SIGNAL( valueChanged( int ) ),
+           this, SLOT( valueChanged( int ) ) );
+   connect( okButton, SIGNAL(clicked()), 
+           this, SLOT(simplify()));
+
+}
+
+void QgsSimplifyDialog::valueChanged(int value)
+{
+  emit toleranceChanged(value);
+}
+
+void QgsSimplifyDialog::simplify()
+{
+  emit storeSimplified();
+}
+
+void QgsSimplifyDialog::setRange(int minValue, int maxValue)
+{
+  horizontalSlider->setMinimum(minValue);
+  horizontalSlider->setMaximum(maxValue);
+
+  // let's have 20 page steps
+  horizontalSlider->setPageStep( (maxValue - minValue) / 20 );
+}
+
+
+QgsMapToolSimplify::QgsMapToolSimplify( QgsMapCanvas* canvas )
+  : QgsMapToolEdit( canvas), mRubberBand( 0 )
+{
+  mSimplifyDialog = new QgsSimplifyDialog( canvas->topLevelWidget() );
+  connect( mSimplifyDialog, SIGNAL( toleranceChanged( int ) ),
+           this, SLOT( toleranceChanged( int ) ) );
+  connect( mSimplifyDialog, SIGNAL( storeSimplified() ), 
+           this, SLOT(storeSimplified()));
+  connect( mSimplifyDialog, SIGNAL(finished(int)),
+           this, SLOT(removeRubberBand()) );
+}
+
+QgsMapToolSimplify::~QgsMapToolSimplify()
+{
+  removeRubberBand();
+  delete mSimplifyDialog;
+}
+
+
+void QgsMapToolSimplify::toleranceChanged(int tolerance)
+{
+  mTolerance = double(tolerance)/toleranceDivider;
+
+  // create a copy of selected feature and do the simplification
+  QgsFeature f = mSelectedFeature;
+  QgsSimplifyFeature::simplifyLine(f, mTolerance);
+  mRubberBand->setToGeometry(f.geometry(), false);
+}
+
+
+void QgsMapToolSimplify::storeSimplified()
+{
+  QgsVectorLayer * vlayer = currentVectorLayer();
+  QgsSimplifyFeature::simplifyLine(mSelectedFeature, mTolerance);
+  // TODO(md): change geometry of feature instead of delete+add
+  vlayer->deleteFeature( mSelectedFeature.id() );
+  vlayer->addFeature(mSelectedFeature);
+
+  mCanvas->refresh();
+}
+
+int QgsMapToolSimplify::calculateDivider(double num)
+{
+  double tmp = num;
+  int i = 1;
+  while (tmp < 1) 
+  {
+    tmp = tmp*10;
+    i = i *10;
+  }
+  return i;
+}
+
+void QgsMapToolSimplify::calculateSliderBoudaries()
+{
+  double minTolerance, maxTolerance;
+
+  double tol = 0.0000001;
+  bool found = false;
+  bool isLine = mSelectedFeature.geometry()->type() == QGis::Line;
+  QVector<QgsPoint> pts = getPointList(mSelectedFeature);
+  int size = pts.size();
+  if (size == 0 || (isLine && size < 2) || (!isLine && size < 3) )
+  {
+    return;
+  }
+
+  // calculate min
+  while (!found)
+  {
+    if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
+    {
+      found = true;
+      minTolerance = tol/2;
+    } else {
+      tol = tol * 2;
+    }
+  }
+
+  found = false;
+  int requiredCnt = (isLine ? 2 : 3);
+  // calculate max
+  while (!found)
+  {
+    if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < requiredCnt + 1)
+    {
+//TODO: fix for polygon
+      found = true;
+      maxTolerance = tol;
+    } else {
+      tol = tol * 2;
+    }
+  }
+  toleranceDivider = calculateDivider(minTolerance);
+  // set min and max
+  mSimplifyDialog->setRange( int(minTolerance * toleranceDivider),
+                             int(maxTolerance * toleranceDivider) );
+}
+
+
+void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
+{
+  QgsVectorLayer * vlayer = currentVectorLayer();
+  QgsPoint layerCoords = mCanvas->getCoordinateTransform()->toMapPoint( e->pos().x(), e->pos().y() );
+
+  double r = QgsTolerance::vertexSearchRadius(vlayer, mCanvas->mapRenderer());
+  QgsRectangle selectRect = QgsRectangle( layerCoords.x() - r, layerCoords.y() - r,
+                                          layerCoords.x() + r, layerCoords.y() + r);
+  vlayer->select( QgsAttributeList(), selectRect, true );
+
+  QgsGeometry* geometry = QgsGeometry::fromPoint( layerCoords );
+  double minDistance = 10000000;
+  double currentDistance;
+  QgsFeature f;
+
+  mSelectedFeature.setValid(FALSE);
+
+  while (vlayer->nextFeature(f))
+  {
+    currentDistance = geometry->distance( *(f.geometry()) );
+    if ( currentDistance < minDistance )
+    {
+      minDistance = currentDistance;
+      mSelectedFeature = f;
+    }
+  }
+
+  // delete previous rubberband (if any)
+  removeRubberBand();
+
+  if (mSelectedFeature.isValid())
+  {
+    mRubberBand = new QgsRubberBand(mCanvas);
+    mRubberBand->setToGeometry(mSelectedFeature.geometry(), false);
+    mRubberBand->setColor(Qt::red);
+    mRubberBand->setWidth(2);
+    mRubberBand->show();
+    //calculate boudaries for slidebar
+    calculateSliderBoudaries();
+
+    // show dialog as a non-modal window
+    mSimplifyDialog->show();
+  }
+}
+
+void QgsMapToolSimplify::removeRubberBand()
+{
+  delete mRubberBand;
+  mRubberBand = 0;
+}
+
+void QgsMapToolSimplify::deactivate()
+{
+  if (mSimplifyDialog->isVisible())
+    mSimplifyDialog->close();
+  removeRubberBand();
+  QgsMapTool::deactivate();
+}
+
+
+QVector<QgsPoint> QgsMapToolSimplify::getPointList(QgsFeature& f)
+{
+  QgsGeometry* line = f.geometry();
+  if ((line->type() != QGis::Line && line->type() != QGis::Polygon ) || line->isMultipart())
+  {
+    return QVector<QgsPoint>();
+  }
+  if ((line->type() == QGis::Line))
+  {
+    return line->asPolyline();
+  } 
+  else
+  {
+    if (line->asPolygon().size() > 1) 
+    {
+      return QVector<QgsPoint>();
+    }
+    return line->asPolygon()[0];
+  }
+
+}
+
+
+
+
+
+bool QgsSimplifyFeature::simplifyLine(QgsFeature& lineFeature,  double tolerance)
+{
+  QgsGeometry* line = lineFeature.geometry();
+  if (line->type() != QGis::Line)
+  {
+    return FALSE;
+  }
+
+  QVector<QgsPoint> resultPoints = simplifyPoints(line->asPolyline(), tolerance);
+  lineFeature.setGeometry( QgsGeometry::fromPolyline( resultPoints ) );
+  return TRUE;
+}
+
+
+//TODO: change to correct structure after
+bool QgsSimplifyFeature::simplifyPartOfLine(QgsFeature& lineFeature, int fromVertexNr, int toVertexNr, double tolerance)
+{
+  QgsGeometry* line = lineFeature.geometry();
+  if (line->type() != QGis::Line)
+  {
+    return FALSE;
+  }
+        
+  QVector<QgsPoint> resultPoints = simplifyPoints(line->asPolyline(), tolerance);
+  lineFeature.setGeometry( QgsGeometry::fromPolyline( resultPoints ) );
+  return TRUE;
+}
+
+
+
+QVector<QgsPoint> QgsSimplifyFeature::simplifyPoints (const QVector<QgsPoint>& pts, double tolerance)
+{
+  // Douglas-Peucker simplification algorithm
+
+  int anchor  = 0;
+  int floater = pts.size() - 1;
+  
+  QList<StackEntry> stack;
+  StackEntry temporary;
+  StackEntry entry = {anchor, floater};
+  stack.append(entry);
+
+  QSet<int> keep;
+  double anchorX;
+  double anchorY;
+  double seg_len;
+  double max_dist;
+  int farthest;
+  double dist_to_seg;
+  double vecX;
+  double vecY;
+
+  while (!stack.empty())
+  {
+     temporary = stack.takeLast();
+     anchor = temporary.anchor;
+     floater = temporary.floater;
+     // initialize line segment
+     if (pts[floater] != pts[anchor])
+     {
+       anchorX = pts[floater].x() - pts[anchor].x();
+       anchorY = pts[floater].y() - pts[anchor].y();
+       seg_len = sqrt(anchorX * anchorX + anchorY * anchorY);
+       // get the unit vector
+       anchorX /= seg_len;
+       anchorY /= seg_len;
+      }
+      else
+      {
+        anchorX = anchorY = seg_len = 0.0;
+      }  
+      // inner loop:
+      max_dist = 0.0;
+      farthest = anchor + 1;
+      for (int i = anchor + 1; i < floater; i++)
+      {
+        dist_to_seg = 0.0;
+        // compare to anchor
+        vecX = pts[i].x() - pts[anchor].x();
+        vecY = pts[i].y() - pts[anchor].y();
+        seg_len = sqrt( vecX * vecX + vecY * vecY );
+        // dot product:
+        double proj = vecX * anchorX + vecY * anchorY;
+        if (proj < 0.0)
+        {
+          dist_to_seg = seg_len;
+        }
+        else
+        {
+          // compare to floater
+          vecX = pts[i].x() - pts[floater].x();
+          vecY = pts[i].y() - pts[floater].y();
+          seg_len = sqrt( vecX * vecX + vecY *vecY );
+          // dot product:
+          proj = vecX * (-anchorX) + vecY * (-anchorY);
+          if (proj < 0.0)
+          {
+            dist_to_seg = seg_len;
+          }
+          else
+          {  // calculate perpendicular distance to line (pythagorean theorem):
+            dist_to_seg = sqrt(fabs(seg_len * seg_len - proj * proj));
+          }
+          if (max_dist < dist_to_seg)
+          {
+            max_dist = dist_to_seg;
+            farthest = i;
+          }
+         }
+      }
+      if (max_dist <= tolerance)
+      { // # use line segment
+        keep.insert(anchor);
+        keep.insert(floater);
+      }
+      else
+      {
+        StackEntry s = {anchor, farthest};
+        stack.append(s);
+
+        StackEntry r = {farthest, floater};
+        stack.append(r);
+      }
+    }
+
+    QList<int> keep2 = keep.toList();
+    qSort(keep2);
+
+    QVector<QgsPoint> result;
+    int position;
+    while (!keep2.empty())
+    {
+      position = keep2.takeFirst();
+      result.append(pts[position]);
+    }
+    return result;
+}

Added: trunk/qgis/src/app/qgsmaptoolsimplify.h
===================================================================
--- trunk/qgis/src/app/qgsmaptoolsimplify.h	                        (rev 0)
+++ trunk/qgis/src/app/qgsmaptoolsimplify.h	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,111 @@
+/***************************************************************************
+    qgsmaptoolsimplify.h  - simplify vector layer features
+    ---------------------
+    begin                : April 2009
+    copyright            : (C) 2009 by Richard Kostecky
+    email                : csf dot kostej at mail dot com
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef QGSMAPTOOLSIMPLIFY_H
+#define QGSMAPTOOLSIMPLIFY_H
+
+#include "qgsmaptooledit.h"
+#include "ui_qgssimplifytolerancedialog.h"
+
+#include <QVector>
+#include "qgsfeature.h"
+
+class QgsRubberBand;
+
+
+class QgsSimplifyDialog : public QDialog, private Ui::SimplifyLineDialog
+{
+  Q_OBJECT
+
+public:
+  QgsSimplifyDialog( QWidget* parent = NULL );
+
+  void setRange(int minValue, int maxValue);
+
+signals:
+  void toleranceChanged( int tol );
+  void storeSimplified();
+
+private slots:
+  void valueChanged( int value );
+  void simplify();
+};
+
+
+/**Map tool to add vertices to line/polygon features*/
+class QgsMapToolSimplify: public QgsMapToolEdit
+{
+  Q_OBJECT
+
+public:
+  QgsMapToolSimplify( QgsMapCanvas* canvas );
+  virtual ~QgsMapToolSimplify();
+
+  void canvasPressEvent( QMouseEvent * e );
+
+  //! called when map tool is being deactivated
+  void deactivate();
+
+public slots:
+  void removeRubberBand();
+
+private:
+
+  int calculateDivider(double num);
+
+  void calculateSliderBoudaries();
+
+  QVector<QgsPoint> getPointList(QgsFeature& f);
+
+  // data
+
+  QgsSimplifyDialog* mSimplifyDialog;
+
+  QgsRubberBand* mRubberBand;
+
+  QgsFeature mSelectedFeature;
+
+  int toleranceDivider;
+
+  double mTolerance;
+
+private slots:
+  void toleranceChanged(int tolerance);
+  void storeSimplified();
+
+};
+
+/**
+  Implementation of Douglas-Peucker simplification algorithm.
+ */
+class QgsSimplifyFeature
+{
+   struct StackEntry {
+     int anchor;
+     int floater;
+  };
+
+public:
+  /** simplify line feature with specified tolerance. Returns TRUE on success */
+  static bool simplifyLine(QgsFeature &lineFeature, double tolerance);
+  /** simplify a part of line feature specified by range of vertices with given tolerance. Returns TRUE on success */
+  static bool simplifyPartOfLine(QgsFeature &lineFeature, int fromVertexNr, int toVertexNr, double tolerance);
+  /** simplify a line given by a vector of points and tolerance. Returns simplified vector of points */
+  static QVector<QgsPoint> simplifyPoints (const QVector<QgsPoint>& pts, double tolerance);
+
+
+};
+
+#endif

Modified: trunk/qgis/src/core/qgsgeometry.cpp
===================================================================
--- trunk/qgis/src/core/qgsgeometry.cpp	2009-05-02 14:27:25 UTC (rev 10699)
+++ trunk/qgis/src/core/qgsgeometry.cpp	2009-05-02 15:37:35 UTC (rev 10700)
@@ -5540,3 +5540,117 @@
 
   return geomCollection;
 }
+
+
+bool QgsGeometry::deleteHole( int ringNum, int partNum )
+{
+  if (ringNum <= 0 || partNum < 0)
+    return FALSE;
+
+  switch ( wkbType() )
+  {
+    case QGis::WKBPolygon25D:
+    case QGis::WKBPolygon:
+    {
+      if (partNum != 0)
+        return FALSE;
+
+      QgsPolygon polygon = asPolygon();
+      if ( ringNum >= polygon.count() )
+        return FALSE;
+
+      polygon.remove( ringNum );
+
+      QgsGeometry* g2 = QgsGeometry::fromPolygon( polygon );
+      *this = *g2;
+      delete g2;
+      return TRUE;
+    }
+
+    case QGis::WKBMultiPolygon25D:
+    case QGis::WKBMultiPolygon:
+    {
+      QgsMultiPolygon mpolygon = asMultiPolygon();
+
+      if (partNum >= mpolygon.count())
+        return FALSE;
+
+      if ( ringNum >= mpolygon[partNum].count() )
+        return FALSE;
+
+      mpolygon[partNum].remove( ringNum );
+
+      QgsGeometry* g2 = QgsGeometry::fromMultiPolygon( mpolygon );
+      *this = *g2;
+      delete g2;
+      return TRUE;
+    }
+
+    default:
+      return FALSE; // only makes sense with polygons and multipolygons
+  }
+}
+
+
+bool QgsGeometry::deletePart( int partNum )
+{
+  if (partNum < 0)
+    return FALSE;
+
+  switch ( wkbType() )
+  {
+    case QGis::WKBMultiPoint25D:
+    case QGis::WKBMultiPoint:
+    {
+      QgsMultiPoint mpoint = asMultiPoint();
+
+      if (partNum >= mpoint.size() || mpoint.size() == 1)
+        return FALSE;
+
+      mpoint.remove( partNum );
+
+      QgsGeometry* g2 = QgsGeometry::fromMultiPoint( mpoint );
+      *this = *g2;
+      delete g2;
+      break;
+    }
+
+    case QGis::WKBMultiLineString25D:
+    case QGis::WKBMultiLineString:
+    {
+      QgsMultiPolyline mline = asMultiPolyline();
+
+      if (partNum >= mline.size() || mline.size() == 1)
+        return FALSE;
+
+      mline.remove( partNum );
+
+      QgsGeometry* g2 = QgsGeometry::fromMultiPolyline( mline );
+      *this = *g2;
+      delete g2;
+      break;
+    }
+
+    case QGis::WKBMultiPolygon25D:
+    case QGis::WKBMultiPolygon:
+    {
+      QgsMultiPolygon mpolygon = asMultiPolygon();
+
+      if (partNum >= mpolygon.size() || mpolygon.size() == 1)
+        return FALSE;
+
+      mpolygon.remove( partNum );
+
+      QgsGeometry* g2 = QgsGeometry::fromMultiPolygon( mpolygon );
+      *this = *g2;
+      delete g2;
+      break;
+    }
+
+    default:
+      // single part geometries are ignored
+      return FALSE;
+  }
+
+  return TRUE;
+}

Modified: trunk/qgis/src/core/qgsgeometry.h
===================================================================
--- trunk/qgis/src/core/qgsgeometry.h	2009-05-02 14:27:25 UTC (rev 10699)
+++ trunk/qgis/src/core/qgsgeometry.h	2009-05-02 15:37:35 UTC (rev 10700)
@@ -332,6 +332,18 @@
      @note added in version 1.1 */
     QList<QgsGeometry*> asGeometryCollection();
 
+    /** delete a hole in polygon or multipolygon.
+      Ring 0 is outer ring and can't be deleted.
+      @return TRUE on success
+      @note added in version 1.2 */
+    bool deleteHole( int ringNum, int partNum = 0 );
+
+    /** delete part identified by the part number
+      @return TRUE on success
+      @note added in version 1.2 */
+    bool deletePart( int partNum );
+
+
   private:
     // Private variables
 

Added: trunk/qgis/src/ui/qgssimplifytolerancedialog.ui
===================================================================
--- trunk/qgis/src/ui/qgssimplifytolerancedialog.ui	                        (rev 0)
+++ trunk/qgis/src/ui/qgssimplifytolerancedialog.ui	2009-05-02 15:37:35 UTC (rev 10700)
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SimplifyLineDialog</class>
+ <widget class="QDialog" name="SimplifyLineDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>431</width>
+    <height>54</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Simplify line tolerance</string>
+  </property>
+  <layout class="QHBoxLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Set tolerance</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QSlider" name="horizontalSlider">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="okButton">
+     <property name="text">
+      <string>OK</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>okButton</sender>
+   <signal>clicked()</signal>
+   <receiver>SimplifyLineDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>390</x>
+     <y>24</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>236</x>
+     <y>30</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>



More information about the QGIS-commit mailing list