Skip to content

Commit cbc57dc

Browse files
author
wonder
committedMay 2, 2009
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). git-svn-id: http://svn.osgeo.org/qgis/trunk@10700 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent fac6117 commit cbc57dc

16 files changed

+1237
-2
lines changed
 
1.96 KB
Loading
1.92 KB
Loading
1.29 KB
Loading

‎python/core/qgsgeometry.sip

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,5 +289,16 @@ not disjoint with existing polygons of the feature*/
289289
// TODO: destruction of created geometries??
290290
QList<QgsGeometry*> asGeometryCollection() /Factory/;
291291

292+
/** delete a hole in polygon or multipolygon.
293+
Ring 0 is outer ring and can't be deleted.
294+
@return TRUE on success
295+
@note added in version 1.2 */
296+
bool deleteHole( int ringNum, int partNum = 0 );
297+
298+
/** delete part identified by the part number
299+
@return TRUE on success
300+
@note added in version 1.2 */
301+
bool deletePart( int partNum );
302+
292303
}; // class QgsGeometry
293304

‎src/app/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ SET(QGIS_APP_SRCS
2727
qgsmaptooladdisland.cpp
2828
qgsmaptooladdring.cpp
2929
qgsmaptoolcapture.cpp
30+
qgsmaptooldeletehole.cpp
31+
qgsmaptooldeletepart.cpp
3032
qgsmaptooldeletevertex.cpp
3133
qgsmaptooledit.cpp
3234
qgsmaptoolidentify.cpp
3335
qgsmaptoolmovefeature.cpp
3436
qgsmaptoolmovevertex.cpp
3537
qgsmaptoolselect.cpp
38+
qgsmaptoolsimplify.cpp
3639
qgsmaptoolsplitfeatures.cpp
3740
qgsmaptoolvertexedit.cpp
3841
qgsmeasuredialog.cpp
@@ -115,6 +118,7 @@ SET (QGIS_APP_MOC_HDRS
115118
qgsmaptooladdring.h
116119
qgsmaptoolmovefeature.h
117120
qgsmaptoolselect.h
121+
qgsmaptoolsimplify.h
118122

119123
qgsmeasuretool.h
120124
qgsmeasuredialog.h

‎src/app/qgisapp.cpp

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@
157157
#include "qgsmaptooladdisland.h"
158158
#include "qgsmaptooladdring.h"
159159
#include "qgsmaptooladdvertex.h"
160+
#include "qgsmaptooldeletehole.h"
161+
#include "qgsmaptooldeletepart.h"
160162
#include "qgsmaptooldeletevertex.h"
161163
#include "qgsmaptoolidentify.h"
162164
#include "qgsmaptoolmovefeature.h"
@@ -166,6 +168,7 @@
166168
#include "qgsmaptoolsplitfeatures.h"
167169
#include "qgsmaptoolvertexedit.h"
168170
#include "qgsmaptoolzoom.h"
171+
#include "qgsmaptoolsimplify.h"
169172
#include "qgsmeasuretool.h"
170173

171174
//
@@ -465,6 +468,9 @@ QgisApp::~QgisApp()
465468
delete mMapTools.mVertexMove;
466469
delete mMapTools.mVertexDelete;
467470
delete mMapTools.mAddRing;
471+
delete mMapTools.mSimplifyFeature;
472+
delete mMapTools.mDeleteHole;
473+
delete mMapTools.mDeletePart;
468474
delete mMapTools.mAddIsland;
469475

470476
delete mPythonConsole;
@@ -667,6 +673,22 @@ void QgisApp::createActions()
667673
connect( mActionAddIsland, SIGNAL( triggered() ), this, SLOT( addIsland() ) );
668674
mActionAddIsland->setEnabled( false );
669675

676+
mActionSimplifyFeature = new QAction( getThemeIcon( "mActionSimplify.png" ), tr( "Simplify Feature" ), this );
677+
mActionSimplifyFeature->setStatusTip( tr( "Simplify Feature" ) );
678+
connect( mActionSimplifyFeature, SIGNAL( triggered() ), this, SLOT( simplifyFeature() ) );
679+
mActionSimplifyFeature->setEnabled( false );
680+
681+
mActionDeleteHole = new QAction( getThemeIcon( "mActionDeleteHole.png" ), tr( "Delete Hole" ), this );
682+
mActionDeleteHole->setStatusTip( tr( "Delete Hole" ) );
683+
connect( mActionDeleteHole, SIGNAL( triggered() ), this, SLOT( deleteHole() ) );
684+
mActionDeleteHole->setEnabled( false );
685+
686+
mActionDeletePart = new QAction( getThemeIcon( "mActionDeletePart.png" ), tr( "Delete Part" ), this );
687+
mActionDeletePart->setStatusTip( tr( "Delete Part" ) );
688+
connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
689+
mActionDeletePart->setEnabled( false );
690+
691+
670692
// View Menu Items
671693

672694
mActionPan = new QAction( getThemeIcon( "mActionPan.png" ), tr( "Pan Map" ), this );
@@ -990,6 +1012,12 @@ void QgisApp::createActionGroups()
9901012
mMapToolGroup->addAction( mActionAddRing );
9911013
mActionAddIsland->setCheckable( true );
9921014
mMapToolGroup->addAction( mActionAddIsland );
1015+
mActionSimplifyFeature->setCheckable( true );
1016+
mMapToolGroup->addAction( mActionSimplifyFeature );
1017+
mActionDeleteHole->setCheckable( true );
1018+
mMapToolGroup->addAction( mActionDeleteHole );
1019+
mActionDeletePart->setCheckable( true );
1020+
mMapToolGroup->addAction( mActionDeletePart );
9931021
}
9941022

9951023
void QgisApp::createMenus()
@@ -1073,9 +1101,15 @@ void QgisApp::createMenus()
10731101
mEditMenu->addAction( mActionAddRing );
10741102
mEditMenu->addAction( mActionAddIsland );
10751103

1104+
mActionEditSeparator2 = mEditMenu->addSeparator();
1105+
1106+
mEditMenu->addAction( mActionSimplifyFeature );
1107+
mEditMenu->addAction( mActionDeleteHole );
1108+
mEditMenu->addAction( mActionDeletePart );
1109+
10761110
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
10771111
{
1078-
mActionEditSeparator2 = mEditMenu->addSeparator();
1112+
mActionEditSeparator3 = mEditMenu->addSeparator();
10791113
mEditMenu->addAction( mActionOptions );
10801114
mEditMenu->addAction( mActionCustomProjection );
10811115
}
@@ -1267,6 +1301,16 @@ void QgisApp::createToolBars()
12671301
mDigitizeToolBar->addAction( mActionCopyFeatures );
12681302
mDigitizeToolBar->addAction( mActionPasteFeatures );
12691303
mToolbarMenu->addAction( mDigitizeToolBar->toggleViewAction() );
1304+
1305+
mAdvancedDigitizeToolBar = addToolBar( tr( "Advanced Digitizing" ) );
1306+
mAdvancedDigitizeToolBar->setIconSize( myIconSize );
1307+
mAdvancedDigitizeToolBar->setObjectName( "Advanced Digitizing" );
1308+
mAdvancedDigitizeToolBar->addAction( mActionSimplifyFeature );
1309+
mAdvancedDigitizeToolBar->addAction( mActionDeleteHole );
1310+
mAdvancedDigitizeToolBar->addAction( mActionDeletePart );
1311+
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
1312+
1313+
12701314
//
12711315
// Map Navigation Toolbar
12721316
mMapNavToolBar = addToolBar( tr( "Map Navigation" ) );
@@ -1606,6 +1650,12 @@ void QgisApp::createCanvas()
16061650
mMapTools.mAddRing = new QgsMapToolAddRing( mMapCanvas );
16071651
mMapTools.mAddRing->setAction( mActionAddRing );
16081652
mMapTools.mAddIsland = new QgsMapToolAddIsland( mMapCanvas );
1653+
mMapTools.mSimplifyFeature = new QgsMapToolSimplify( mMapCanvas );
1654+
mMapTools.mSimplifyFeature->setAction( mActionSimplifyFeature );
1655+
mMapTools.mDeleteHole = new QgsMapToolDeleteHole( mMapCanvas );
1656+
mMapTools.mDeleteHole->setAction( mActionDeleteHole );
1657+
mMapTools.mDeletePart = new QgsMapToolDeletePart( mMapCanvas );
1658+
mMapTools.mDeletePart->setAction( mActionDeletePart );
16091659
//ensure that non edit tool is initialised or we will get crashes in some situations
16101660
mNonEditMapTool = mMapTools.mPan;
16111661
}
@@ -3979,6 +4029,21 @@ void QgisApp::moveFeature()
39794029
mMapCanvas->setMapTool( mMapTools.mMoveFeature );
39804030
}
39814031

4032+
void QgisApp::simplifyFeature()
4033+
{
4034+
mMapCanvas->setMapTool( mMapTools.mSimplifyFeature );
4035+
}
4036+
4037+
void QgisApp::deleteHole()
4038+
{
4039+
mMapCanvas->setMapTool( mMapTools.mDeleteHole );
4040+
}
4041+
4042+
void QgisApp::deletePart()
4043+
{
4044+
mMapCanvas->setMapTool( mMapTools.mDeletePart );
4045+
}
4046+
39824047
void QgisApp::splitFeatures()
39834048
{
39844049
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
@@ -5215,11 +5280,13 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
52155280
{
52165281
mActionCapturePoint->setEnabled( true );
52175282
mActionCapturePoint->setVisible( true );
5283+
mActionDeletePart->setEnabled( true );
52185284
}
52195285
else
52205286
{
52215287
mActionCapturePoint->setEnabled( false );
52225288
mActionCapturePoint->setVisible( false );
5289+
mActionDeletePart->setEnabled( false );
52235290
}
52245291
mActionCaptureLine->setEnabled( false );
52255292
mActionCapturePolygon->setEnabled( false );
@@ -5231,6 +5298,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
52315298
mActionAddRing->setEnabled( false );
52325299
mActionAddIsland->setEnabled( false );
52335300
mActionSplitFeatures->setEnabled( false );
5301+
mActionSimplifyFeature->setEnabled( false );
5302+
mActionDeleteHole->setEnabled( false );
5303+
52345304
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
52355305
{
52365306
mActionMoveVertex->setEnabled( true );
@@ -5244,19 +5314,24 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
52445314
mActionCaptureLine->setEnabled( true );
52455315
mActionCaptureLine->setVisible( true );
52465316
mActionSplitFeatures->setEnabled( true );
5317+
mActionSimplifyFeature->setEnabled( true );
5318+
mActionDeletePart->setEnabled( true );
52475319
}
52485320
else
52495321
{
52505322
mActionCaptureLine->setEnabled( false );
52515323
mActionCaptureLine->setVisible( false );
52525324
mActionSplitFeatures->setEnabled( false );
5325+
mActionSimplifyFeature->setEnabled( false );
5326+
mActionDeletePart->setEnabled( false );
52535327
}
52545328
mActionCapturePoint->setEnabled( false );
52555329
mActionCapturePolygon->setEnabled( false );
52565330
mActionCapturePoint->setVisible( false );
52575331
mActionCapturePolygon->setVisible( false );
52585332
mActionAddRing->setEnabled( false );
52595333
mActionAddIsland->setEnabled( false );
5334+
mActionDeleteHole->setEnabled( false );
52605335
}
52615336
else if ( vlayer->geometryType() == QGis::Polygon )
52625337
{
@@ -5267,6 +5342,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
52675342
mActionAddRing->setEnabled( true );
52685343
mActionAddIsland->setEnabled( true );
52695344
mActionSplitFeatures->setEnabled( true );
5345+
mActionSimplifyFeature->setEnabled( true );
5346+
mActionDeleteHole->setEnabled( true );
5347+
mActionDeletePart->setEnabled( true );
52705348
}
52715349
else
52725350
{
@@ -5275,6 +5353,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
52755353
mActionAddRing->setEnabled( false );
52765354
mActionAddIsland->setEnabled( false );
52775355
mActionSplitFeatures->setEnabled( false );
5356+
mActionSimplifyFeature->setEnabled( false );
5357+
mActionDeleteHole->setEnabled( false );
5358+
mActionDeletePart->setEnabled( false );
52785359
}
52795360
mActionCapturePoint->setEnabled( false );
52805361
mActionCaptureLine->setEnabled( false );

‎src/app/qgisapp.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class QgisAppInterface;
4242
class QgsClipboard;
4343
class QgsComposer;
4444
class QgsHelpViewer;
45+
class QgsFeature;
46+
4547
class QgsLegend;
4648
class QgsMapCanvas;
4749
class QgsMapLayer;
@@ -63,7 +65,6 @@ class QgsVectorLayer;
6365
#include "qgsconfig.h"
6466
#include "qgspoint.h"
6567

66-
6768
/*! \class QgisApp
6869
* \brief Main window for the Qgis application
6970
*/
@@ -221,6 +222,9 @@ class QgisApp : public QMainWindow
221222
QAction *actionMoveVertex() { return mActionMoveVertex; }
222223
QAction *actionAddRing() { return mActionAddRing; }
223224
QAction *actionAddIsland() { return mActionAddIsland; }
225+
QAction *actionSimplifyFeature() { return mActionSimplifyFeature; }
226+
QAction *actionDeleteHole() { return mActionDeleteHole; }
227+
QAction *actionDeletePart() { return mActionDeletePart; }
224228
QAction *actionEditSeparator2() { return mActionEditSeparator2; }
225229

226230
QAction *actionPan() { return mActionPan; }
@@ -318,6 +322,7 @@ class QgisApp : public QMainWindow
318322
QToolBar *layerToolBar() { return mLayerToolBar; }
319323
QToolBar *mapNavToolToolBar() { return mMapNavToolBar; }
320324
QToolBar *digitizeToolBar() { return mDigitizeToolBar; }
325+
QToolBar *advancedDigitizeToolBar() { return mAdvancedDigitizeToolBar; }
321326
QToolBar *attributesToolBar() { return mAttributesToolBar; }
322327
QToolBar *pluginToolBar() { return mPluginToolBar; }
323328
QToolBar *helpToolBar() { return mHelpToolBar; }
@@ -495,6 +500,12 @@ class QgisApp : public QMainWindow
495500
void addRing();
496501
//! activates the add island tool
497502
void addIsland();
503+
//! simplifies feature
504+
void simplifyFeature();
505+
//! deletes hole in polygon
506+
void deleteHole();
507+
//! deletes part of polygon
508+
void deletePart();
498509

499510
//! activates the selection tool
500511
void select();
@@ -666,6 +677,7 @@ class QgisApp : public QMainWindow
666677
QToolBar *mLayerToolBar;
667678
QToolBar *mMapNavToolBar;
668679
QToolBar *mDigitizeToolBar;
680+
QToolBar *mAdvancedDigitizeToolBar;
669681
QToolBar *mAttributesToolBar;
670682
QToolBar *mPluginToolBar;
671683
QToolBar *mHelpToolBar;
@@ -701,6 +713,10 @@ class QgisApp : public QMainWindow
701713
QAction *mActionAddRing;
702714
QAction *mActionAddIsland;
703715
QAction *mActionEditSeparator2;
716+
QAction *mActionSimplifyFeature;
717+
QAction *mActionDeleteHole;
718+
QAction *mActionDeletePart;
719+
QAction *mActionEditSeparator3;
704720

705721
QAction *mActionPan;
706722
QAction *mActionZoomIn;
@@ -816,6 +832,9 @@ class QgisApp : public QMainWindow
816832
QgsMapTool* mVertexDelete;
817833
QgsMapTool* mAddRing;
818834
QgsMapTool* mAddIsland;
835+
QgsMapTool* mSimplifyFeature;
836+
QgsMapTool* mDeleteHole;
837+
QgsMapTool* mDeletePart;
819838
} mMapTools;
820839

821840
QgsMapTool *mNonEditMapTool;
@@ -921,6 +940,7 @@ class QgisApp : public QMainWindow
921940
QgsPythonUtils* mPythonUtils;
922941

923942
static QgisApp *smInstance;
943+
924944
};
925945

926946
#endif

‎src/app/qgsmaptooldeletehole.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/***************************************************************************
2+
qgsmaptooldeletehole.h - delete a hole from polygon
3+
---------------------
4+
begin : April 2009
5+
copyright : (C) 2009 by Richard Kostecky
6+
email : csf dot kostej at mail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsmaptooldeletehole.h"
17+
18+
#include "qgsmapcanvas.h"
19+
#include "qgsvertexmarker.h"
20+
#include "qgsvectorlayer.h"
21+
22+
#include <QMouseEvent>
23+
#include <QMessageBox>
24+
25+
QgsMapToolDeleteHole::QgsMapToolDeleteHole( QgsMapCanvas* canvas )
26+
: QgsMapToolVertexEdit( canvas ), mCross( 0 )
27+
{
28+
}
29+
30+
QgsMapToolDeleteHole::~QgsMapToolDeleteHole()
31+
{
32+
delete mCross;
33+
}
34+
35+
void QgsMapToolDeleteHole::canvasMoveEvent( QMouseEvent * e )
36+
{
37+
//nothing to do
38+
}
39+
40+
void QgsMapToolDeleteHole::canvasPressEvent( QMouseEvent * e )
41+
{
42+
delete mCross;
43+
mCross = 0;
44+
45+
mRecentSnappingResults.clear();
46+
//do snap -> new recent snapping results
47+
if ( mSnapper.snapToCurrentLayer( e->pos(), mRecentSnappingResults, QgsSnapper::SnapToVertex ) != 0 )
48+
{
49+
//error
50+
}
51+
52+
if ( mRecentSnappingResults.size() > 0 )
53+
{
54+
QgsPoint markerPoint = mRecentSnappingResults.begin()->snappedVertex;
55+
56+
//show vertex marker
57+
mCross = new QgsVertexMarker( mCanvas );
58+
mCross->setIconType( QgsVertexMarker::ICON_X );
59+
mCross->setCenter( markerPoint );
60+
}
61+
else
62+
{
63+
displaySnapToleranceWarning();
64+
}
65+
}
66+
67+
void QgsMapToolDeleteHole::canvasReleaseEvent( QMouseEvent * e )
68+
{
69+
delete mCross;
70+
mCross = 0;
71+
72+
QgsMapLayer* currentLayer = mCanvas->currentLayer();
73+
if ( !currentLayer )
74+
return;
75+
76+
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
77+
if ( !vlayer )
78+
return;
79+
80+
81+
if ( mRecentSnappingResults.size() > 0 )
82+
{
83+
QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
84+
for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
85+
{
86+
deleteHole( sr_it->snappedAtGeometry, sr_it->snappedVertexNr, vlayer);
87+
}
88+
}
89+
}
90+
91+
92+
void QgsMapToolDeleteHole::deleteHole( int fId, int beforeVertexNr, QgsVectorLayer* vlayer)
93+
{
94+
QgsFeature f;
95+
vlayer->featureAtId( fId, f );
96+
97+
QgsGeometry* g = f.geometry();
98+
QGis::WkbType wkbtype = g->wkbType();
99+
int ringNum, partNum = 0;
100+
101+
if (wkbtype == QGis::WKBPolygon || wkbtype == QGis::WKBPolygon25D)
102+
{
103+
ringNum = ringNumInPolygon( g, beforeVertexNr );
104+
}
105+
else if (wkbtype == QGis::WKBMultiPolygon || wkbtype == QGis::WKBMultiPolygon25D)
106+
{
107+
ringNum = ringNumInMultiPolygon( g, beforeVertexNr, partNum );
108+
}
109+
else
110+
return;
111+
112+
if (g->deleteHole( ringNum, partNum ))
113+
{
114+
vlayer->deleteFeature( fId );
115+
vlayer->addFeature(f);
116+
mCanvas->refresh();
117+
}
118+
119+
}
120+
121+
int QgsMapToolDeleteHole::ringNumInPolygon( QgsGeometry* g, int vertexNr )
122+
{
123+
QgsPolygon polygon = g->asPolygon();
124+
for (int ring = 0; ring < polygon.count(); ring++)
125+
{
126+
if (vertexNr < polygon[ring].count())
127+
return ring;
128+
129+
vertexNr -= polygon[ring].count();
130+
}
131+
return -1;
132+
}
133+
134+
int QgsMapToolDeleteHole::ringNumInMultiPolygon( QgsGeometry* g, int vertexNr, int& partNum )
135+
{
136+
QgsMultiPolygon mpolygon = g->asMultiPolygon();
137+
for (int part = 0; part < mpolygon.count(); part++)
138+
{
139+
const QgsPolygon& polygon = mpolygon[part];
140+
for (int ring = 0; ring < polygon.count(); ring++)
141+
{
142+
if (vertexNr < polygon[ring].count())
143+
{
144+
partNum = part;
145+
return ring;
146+
}
147+
148+
vertexNr -= polygon[ring].count();
149+
}
150+
}
151+
return -1;
152+
}
153+
154+
155+
void QgsMapToolDeleteHole::deactivate()
156+
{
157+
delete mCross;
158+
mCross = 0;
159+
160+
QgsMapTool::deactivate();
161+
}

‎src/app/qgsmaptooldeletehole.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/***************************************************************************
2+
qgsmaptooldeletehole.h - delete a hole from polygon
3+
---------------------
4+
begin : April 2009
5+
copyright : (C) 2009 by Richard Kostecky
6+
email : csf dot kostej at mail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSMAPTOOLDELETEHOLE_H
17+
#define QGSMAPTOOLDELETEHOLE_H
18+
19+
#include "qgsmaptoolvertexedit.h"
20+
#include <QUndoCommand>
21+
22+
class QgsVertexMarker;
23+
/**Map tool to delete vertices from line/polygon features*/
24+
25+
class QgsMapToolDeleteHole: public QgsMapToolVertexEdit
26+
{
27+
public:
28+
QgsMapToolDeleteHole( QgsMapCanvas* canvas );
29+
virtual ~QgsMapToolDeleteHole();
30+
31+
void canvasMoveEvent( QMouseEvent * e );
32+
33+
void canvasPressEvent( QMouseEvent * e );
34+
35+
void canvasReleaseEvent( QMouseEvent * e );
36+
37+
//! called when map tool is being deactivated
38+
void deactivate();
39+
40+
private:
41+
QgsVertexMarker* mCross;
42+
43+
//! delete hole from the geometry
44+
void deleteHole( int fId, int beforeVertexNr, QgsVectorLayer* vlayer);
45+
46+
//! return ring number in polygon
47+
int ringNumInPolygon( QgsGeometry* g, int vertexNr );
48+
49+
//! return ring number in multipolygon and set parNum to index of the part
50+
int ringNumInMultiPolygon( QgsGeometry* g, int vertexNr, int& partNum );
51+
};
52+
53+
#endif

‎src/app/qgsmaptooldeletepart.cpp

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/***************************************************************************
2+
qgsmaptooldeletepart.cpp - delete a part from multipart geometry
3+
---------------------
4+
begin : April 2009
5+
copyright : (C) 2009 by Richard Kostecky
6+
email : csf dot kostej at mail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsmaptooldeletepart.h"
17+
18+
#include "qgsmapcanvas.h"
19+
#include "qgsvertexmarker.h"
20+
#include "qgsvectorlayer.h"
21+
22+
#include <QMouseEvent>
23+
#include <QMessageBox>
24+
25+
QgsMapToolDeletePart::QgsMapToolDeletePart( QgsMapCanvas* canvas )
26+
: QgsMapToolVertexEdit( canvas ), mCross( 0 )
27+
{
28+
}
29+
30+
QgsMapToolDeletePart::~QgsMapToolDeletePart()
31+
{
32+
delete mCross;
33+
}
34+
35+
void QgsMapToolDeletePart::canvasMoveEvent( QMouseEvent * e )
36+
{
37+
//nothing to do
38+
}
39+
40+
void QgsMapToolDeletePart::canvasPressEvent( QMouseEvent * e )
41+
{
42+
delete mCross;
43+
mCross = 0;
44+
45+
mRecentSnappingResults.clear();
46+
//do snap -> new recent snapping results
47+
if ( mSnapper.snapToCurrentLayer( e->pos(), mRecentSnappingResults, QgsSnapper::SnapToVertex ) != 0 )
48+
{
49+
//error
50+
}
51+
52+
if ( mRecentSnappingResults.size() > 0 )
53+
{
54+
QgsPoint markerPoint = mRecentSnappingResults.begin()->snappedVertex;
55+
56+
//show vertex marker
57+
mCross = new QgsVertexMarker( mCanvas );
58+
mCross->setIconType( QgsVertexMarker::ICON_X );
59+
mCross->setCenter( markerPoint );
60+
}
61+
else
62+
{
63+
displaySnapToleranceWarning();
64+
}
65+
}
66+
67+
void QgsMapToolDeletePart::canvasReleaseEvent( QMouseEvent * e )
68+
{
69+
delete mCross;
70+
mCross = 0;
71+
72+
QgsMapLayer* currentLayer = mCanvas->currentLayer();
73+
if ( !currentLayer )
74+
return;
75+
76+
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
77+
if ( !vlayer )
78+
return;
79+
80+
if ( mRecentSnappingResults.size() > 0 )
81+
{
82+
QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
83+
for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
84+
{
85+
deletePart( sr_it->snappedAtGeometry, sr_it->snappedVertexNr, vlayer);
86+
}
87+
}
88+
89+
}
90+
91+
92+
void QgsMapToolDeletePart::deletePart( int fId, int beforeVertexNr, QgsVectorLayer* vlayer)
93+
{
94+
QgsFeature f;
95+
vlayer->featureAtId( fId, f );
96+
97+
// find out the part number
98+
QgsGeometry* g = f.geometry();
99+
if ( !g->isMultipart() )
100+
{
101+
QMessageBox::information(mCanvas, tr("Delete part"), tr("This isn't a multipart geometry."));
102+
return;
103+
}
104+
105+
int partNum = partNumberOfVertex( g, beforeVertexNr );
106+
107+
if (g->deletePart( partNum ))
108+
{
109+
vlayer->deleteFeature( fId );
110+
vlayer->addFeature(f);
111+
mCanvas->refresh();
112+
}
113+
else
114+
{
115+
QMessageBox::information(mCanvas, tr("Delete part"), tr("Couldn't remove the selected part."));
116+
}
117+
118+
}
119+
120+
int QgsMapToolDeletePart::partNumberOfVertex( QgsGeometry* g, int beforeVertexNr )
121+
{
122+
int part;
123+
124+
switch ( g->wkbType() )
125+
{
126+
case QGis::WKBMultiPoint25D:
127+
case QGis::WKBMultiPoint:
128+
if ( beforeVertexNr < g->asMultiPoint().count() )
129+
return beforeVertexNr;
130+
else
131+
return -1;
132+
133+
case QGis::WKBMultiLineString25D:
134+
case QGis::WKBMultiLineString:
135+
{
136+
QgsMultiPolyline mline = g->asMultiPolyline();
137+
for (part = 0; part < mline.count(); part++)
138+
{
139+
if (beforeVertexNr < mline[part].count())
140+
return part;
141+
142+
beforeVertexNr -= mline[part].count();
143+
}
144+
return -1; // not found
145+
}
146+
147+
case QGis::WKBMultiPolygon25D:
148+
case QGis::WKBMultiPolygon:
149+
{
150+
QgsMultiPolygon mpolygon = g->asMultiPolygon();
151+
for (part = 0; part < mpolygon.count(); part++) // go through the polygons
152+
{
153+
const QgsPolygon& polygon = mpolygon[part];
154+
for (int ring = 0; ring < polygon.count(); ring++) // go through the rings
155+
{
156+
if (beforeVertexNr < polygon[ring].count())
157+
return part;
158+
159+
beforeVertexNr -= polygon[ring].count();
160+
}
161+
}
162+
return -1; // not found
163+
}
164+
165+
default:
166+
return -1;
167+
}
168+
}
169+
170+
171+
void QgsMapToolDeletePart::deactivate()
172+
{
173+
delete mCross;
174+
mCross = 0;
175+
176+
QgsMapTool::deactivate();
177+
}
178+

‎src/app/qgsmaptooldeletepart.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/***************************************************************************
2+
qgsmaptooldeletepart.h - delete a part from multipart geometry
3+
---------------------
4+
begin : April 2009
5+
copyright : (C) 2009 by Richard Kostecky
6+
email : csf dot kostej at mail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSMAPTOOLDELETEPART_H
17+
#define QGSMAPTOOLDELETEPART_H
18+
19+
#include "qgsmaptoolvertexedit.h"
20+
21+
class QgsVertexMarker;
22+
23+
/**Map tool to delete vertices from line/polygon features*/
24+
class QgsMapToolDeletePart: public QgsMapToolVertexEdit
25+
{
26+
public:
27+
QgsMapToolDeletePart( QgsMapCanvas* canvas );
28+
virtual ~QgsMapToolDeletePart();
29+
30+
void canvasMoveEvent( QMouseEvent * e );
31+
32+
void canvasPressEvent( QMouseEvent * e );
33+
34+
void canvasReleaseEvent( QMouseEvent * e );
35+
36+
//! called when map tool is being deactivated
37+
void deactivate();
38+
39+
private:
40+
QgsVertexMarker* mCross;
41+
42+
//! delete part of a geometry
43+
void deletePart( int fId, int beforeVertexNr, QgsVectorLayer* vlayer);
44+
45+
//! find out part number of geometry given the snapped vertex number
46+
int partNumberOfVertex( QgsGeometry* g, int beforeVertexNr );
47+
48+
};
49+
50+
#endif

‎src/app/qgsmaptoolsimplify.cpp

Lines changed: 381 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,381 @@
1+
/***************************************************************************
2+
qgsmaptoolsimplify.cpp - simplify vector layer features
3+
---------------------
4+
begin : April 2009
5+
copyright : (C) 2009 by Richard Kostecky
6+
email : csf dot kostej at mail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgsmaptoolsimplify.h"
17+
18+
#include "qgsgeometry.h"
19+
#include "qgsmapcanvas.h"
20+
#include "qgsrubberband.h"
21+
#include "qgsvectorlayer.h"
22+
#include "qgstolerance.h"
23+
24+
#include <QMouseEvent>
25+
26+
#include <math.h>
27+
28+
QgsSimplifyDialog::QgsSimplifyDialog(QWidget* parent)
29+
: QDialog( parent )
30+
{
31+
setupUi(this);
32+
connect( horizontalSlider, SIGNAL( valueChanged( int ) ),
33+
this, SLOT( valueChanged( int ) ) );
34+
connect( okButton, SIGNAL(clicked()),
35+
this, SLOT(simplify()));
36+
37+
}
38+
39+
void QgsSimplifyDialog::valueChanged(int value)
40+
{
41+
emit toleranceChanged(value);
42+
}
43+
44+
void QgsSimplifyDialog::simplify()
45+
{
46+
emit storeSimplified();
47+
}
48+
49+
void QgsSimplifyDialog::setRange(int minValue, int maxValue)
50+
{
51+
horizontalSlider->setMinimum(minValue);
52+
horizontalSlider->setMaximum(maxValue);
53+
54+
// let's have 20 page steps
55+
horizontalSlider->setPageStep( (maxValue - minValue) / 20 );
56+
}
57+
58+
59+
QgsMapToolSimplify::QgsMapToolSimplify( QgsMapCanvas* canvas )
60+
: QgsMapToolEdit( canvas), mRubberBand( 0 )
61+
{
62+
mSimplifyDialog = new QgsSimplifyDialog( canvas->topLevelWidget() );
63+
connect( mSimplifyDialog, SIGNAL( toleranceChanged( int ) ),
64+
this, SLOT( toleranceChanged( int ) ) );
65+
connect( mSimplifyDialog, SIGNAL( storeSimplified() ),
66+
this, SLOT(storeSimplified()));
67+
connect( mSimplifyDialog, SIGNAL(finished(int)),
68+
this, SLOT(removeRubberBand()) );
69+
}
70+
71+
QgsMapToolSimplify::~QgsMapToolSimplify()
72+
{
73+
removeRubberBand();
74+
delete mSimplifyDialog;
75+
}
76+
77+
78+
void QgsMapToolSimplify::toleranceChanged(int tolerance)
79+
{
80+
mTolerance = double(tolerance)/toleranceDivider;
81+
82+
// create a copy of selected feature and do the simplification
83+
QgsFeature f = mSelectedFeature;
84+
QgsSimplifyFeature::simplifyLine(f, mTolerance);
85+
mRubberBand->setToGeometry(f.geometry(), false);
86+
}
87+
88+
89+
void QgsMapToolSimplify::storeSimplified()
90+
{
91+
QgsVectorLayer * vlayer = currentVectorLayer();
92+
QgsSimplifyFeature::simplifyLine(mSelectedFeature, mTolerance);
93+
// TODO(md): change geometry of feature instead of delete+add
94+
vlayer->deleteFeature( mSelectedFeature.id() );
95+
vlayer->addFeature(mSelectedFeature);
96+
97+
mCanvas->refresh();
98+
}
99+
100+
int QgsMapToolSimplify::calculateDivider(double num)
101+
{
102+
double tmp = num;
103+
int i = 1;
104+
while (tmp < 1)
105+
{
106+
tmp = tmp*10;
107+
i = i *10;
108+
}
109+
return i;
110+
}
111+
112+
void QgsMapToolSimplify::calculateSliderBoudaries()
113+
{
114+
double minTolerance, maxTolerance;
115+
116+
double tol = 0.0000001;
117+
bool found = false;
118+
bool isLine = mSelectedFeature.geometry()->type() == QGis::Line;
119+
QVector<QgsPoint> pts = getPointList(mSelectedFeature);
120+
int size = pts.size();
121+
if (size == 0 || (isLine && size < 2) || (!isLine && size < 3) )
122+
{
123+
return;
124+
}
125+
126+
// calculate min
127+
while (!found)
128+
{
129+
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < size)
130+
{
131+
found = true;
132+
minTolerance = tol/2;
133+
} else {
134+
tol = tol * 2;
135+
}
136+
}
137+
138+
found = false;
139+
int requiredCnt = (isLine ? 2 : 3);
140+
// calculate max
141+
while (!found)
142+
{
143+
if (QgsSimplifyFeature::simplifyPoints(pts, tol).size() < requiredCnt + 1)
144+
{
145+
//TODO: fix for polygon
146+
found = true;
147+
maxTolerance = tol;
148+
} else {
149+
tol = tol * 2;
150+
}
151+
}
152+
toleranceDivider = calculateDivider(minTolerance);
153+
// set min and max
154+
mSimplifyDialog->setRange( int(minTolerance * toleranceDivider),
155+
int(maxTolerance * toleranceDivider) );
156+
}
157+
158+
159+
void QgsMapToolSimplify::canvasPressEvent( QMouseEvent * e )
160+
{
161+
QgsVectorLayer * vlayer = currentVectorLayer();
162+
QgsPoint layerCoords = mCanvas->getCoordinateTransform()->toMapPoint( e->pos().x(), e->pos().y() );
163+
164+
double r = QgsTolerance::vertexSearchRadius(vlayer, mCanvas->mapRenderer());
165+
QgsRectangle selectRect = QgsRectangle( layerCoords.x() - r, layerCoords.y() - r,
166+
layerCoords.x() + r, layerCoords.y() + r);
167+
vlayer->select( QgsAttributeList(), selectRect, true );
168+
169+
QgsGeometry* geometry = QgsGeometry::fromPoint( layerCoords );
170+
double minDistance = 10000000;
171+
double currentDistance;
172+
QgsFeature f;
173+
174+
mSelectedFeature.setValid(FALSE);
175+
176+
while (vlayer->nextFeature(f))
177+
{
178+
currentDistance = geometry->distance( *(f.geometry()) );
179+
if ( currentDistance < minDistance )
180+
{
181+
minDistance = currentDistance;
182+
mSelectedFeature = f;
183+
}
184+
}
185+
186+
// delete previous rubberband (if any)
187+
removeRubberBand();
188+
189+
if (mSelectedFeature.isValid())
190+
{
191+
mRubberBand = new QgsRubberBand(mCanvas);
192+
mRubberBand->setToGeometry(mSelectedFeature.geometry(), false);
193+
mRubberBand->setColor(Qt::red);
194+
mRubberBand->setWidth(2);
195+
mRubberBand->show();
196+
//calculate boudaries for slidebar
197+
calculateSliderBoudaries();
198+
199+
// show dialog as a non-modal window
200+
mSimplifyDialog->show();
201+
}
202+
}
203+
204+
void QgsMapToolSimplify::removeRubberBand()
205+
{
206+
delete mRubberBand;
207+
mRubberBand = 0;
208+
}
209+
210+
void QgsMapToolSimplify::deactivate()
211+
{
212+
if (mSimplifyDialog->isVisible())
213+
mSimplifyDialog->close();
214+
removeRubberBand();
215+
QgsMapTool::deactivate();
216+
}
217+
218+
219+
QVector<QgsPoint> QgsMapToolSimplify::getPointList(QgsFeature& f)
220+
{
221+
QgsGeometry* line = f.geometry();
222+
if ((line->type() != QGis::Line && line->type() != QGis::Polygon ) || line->isMultipart())
223+
{
224+
return QVector<QgsPoint>();
225+
}
226+
if ((line->type() == QGis::Line))
227+
{
228+
return line->asPolyline();
229+
}
230+
else
231+
{
232+
if (line->asPolygon().size() > 1)
233+
{
234+
return QVector<QgsPoint>();
235+
}
236+
return line->asPolygon()[0];
237+
}
238+
239+
}
240+
241+
242+
243+
244+
245+
bool QgsSimplifyFeature::simplifyLine(QgsFeature& lineFeature, double tolerance)
246+
{
247+
QgsGeometry* line = lineFeature.geometry();
248+
if (line->type() != QGis::Line)
249+
{
250+
return FALSE;
251+
}
252+
253+
QVector<QgsPoint> resultPoints = simplifyPoints(line->asPolyline(), tolerance);
254+
lineFeature.setGeometry( QgsGeometry::fromPolyline( resultPoints ) );
255+
return TRUE;
256+
}
257+
258+
259+
//TODO: change to correct structure after
260+
bool QgsSimplifyFeature::simplifyPartOfLine(QgsFeature& lineFeature, int fromVertexNr, int toVertexNr, double tolerance)
261+
{
262+
QgsGeometry* line = lineFeature.geometry();
263+
if (line->type() != QGis::Line)
264+
{
265+
return FALSE;
266+
}
267+
268+
QVector<QgsPoint> resultPoints = simplifyPoints(line->asPolyline(), tolerance);
269+
lineFeature.setGeometry( QgsGeometry::fromPolyline( resultPoints ) );
270+
return TRUE;
271+
}
272+
273+
274+
275+
QVector<QgsPoint> QgsSimplifyFeature::simplifyPoints (const QVector<QgsPoint>& pts, double tolerance)
276+
{
277+
// Douglas-Peucker simplification algorithm
278+
279+
int anchor = 0;
280+
int floater = pts.size() - 1;
281+
282+
QList<StackEntry> stack;
283+
StackEntry temporary;
284+
StackEntry entry = {anchor, floater};
285+
stack.append(entry);
286+
287+
QSet<int> keep;
288+
double anchorX;
289+
double anchorY;
290+
double seg_len;
291+
double max_dist;
292+
int farthest;
293+
double dist_to_seg;
294+
double vecX;
295+
double vecY;
296+
297+
while (!stack.empty())
298+
{
299+
temporary = stack.takeLast();
300+
anchor = temporary.anchor;
301+
floater = temporary.floater;
302+
// initialize line segment
303+
if (pts[floater] != pts[anchor])
304+
{
305+
anchorX = pts[floater].x() - pts[anchor].x();
306+
anchorY = pts[floater].y() - pts[anchor].y();
307+
seg_len = sqrt(anchorX * anchorX + anchorY * anchorY);
308+
// get the unit vector
309+
anchorX /= seg_len;
310+
anchorY /= seg_len;
311+
}
312+
else
313+
{
314+
anchorX = anchorY = seg_len = 0.0;
315+
}
316+
// inner loop:
317+
max_dist = 0.0;
318+
farthest = anchor + 1;
319+
for (int i = anchor + 1; i < floater; i++)
320+
{
321+
dist_to_seg = 0.0;
322+
// compare to anchor
323+
vecX = pts[i].x() - pts[anchor].x();
324+
vecY = pts[i].y() - pts[anchor].y();
325+
seg_len = sqrt( vecX * vecX + vecY * vecY );
326+
// dot product:
327+
double proj = vecX * anchorX + vecY * anchorY;
328+
if (proj < 0.0)
329+
{
330+
dist_to_seg = seg_len;
331+
}
332+
else
333+
{
334+
// compare to floater
335+
vecX = pts[i].x() - pts[floater].x();
336+
vecY = pts[i].y() - pts[floater].y();
337+
seg_len = sqrt( vecX * vecX + vecY *vecY );
338+
// dot product:
339+
proj = vecX * (-anchorX) + vecY * (-anchorY);
340+
if (proj < 0.0)
341+
{
342+
dist_to_seg = seg_len;
343+
}
344+
else
345+
{ // calculate perpendicular distance to line (pythagorean theorem):
346+
dist_to_seg = sqrt(fabs(seg_len * seg_len - proj * proj));
347+
}
348+
if (max_dist < dist_to_seg)
349+
{
350+
max_dist = dist_to_seg;
351+
farthest = i;
352+
}
353+
}
354+
}
355+
if (max_dist <= tolerance)
356+
{ // # use line segment
357+
keep.insert(anchor);
358+
keep.insert(floater);
359+
}
360+
else
361+
{
362+
StackEntry s = {anchor, farthest};
363+
stack.append(s);
364+
365+
StackEntry r = {farthest, floater};
366+
stack.append(r);
367+
}
368+
}
369+
370+
QList<int> keep2 = keep.toList();
371+
qSort(keep2);
372+
373+
QVector<QgsPoint> result;
374+
int position;
375+
while (!keep2.empty())
376+
{
377+
position = keep2.takeFirst();
378+
result.append(pts[position]);
379+
}
380+
return result;
381+
}

‎src/app/qgsmaptoolsimplify.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/***************************************************************************
2+
qgsmaptoolsimplify.h - simplify vector layer features
3+
---------------------
4+
begin : April 2009
5+
copyright : (C) 2009 by Richard Kostecky
6+
email : csf dot kostej at mail dot com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSMAPTOOLSIMPLIFY_H
17+
#define QGSMAPTOOLSIMPLIFY_H
18+
19+
#include "qgsmaptooledit.h"
20+
#include "ui_qgssimplifytolerancedialog.h"
21+
22+
#include <QVector>
23+
#include "qgsfeature.h"
24+
25+
class QgsRubberBand;
26+
27+
28+
class QgsSimplifyDialog : public QDialog, private Ui::SimplifyLineDialog
29+
{
30+
Q_OBJECT
31+
32+
public:
33+
QgsSimplifyDialog( QWidget* parent = NULL );
34+
35+
void setRange(int minValue, int maxValue);
36+
37+
signals:
38+
void toleranceChanged( int tol );
39+
void storeSimplified();
40+
41+
private slots:
42+
void valueChanged( int value );
43+
void simplify();
44+
};
45+
46+
47+
/**Map tool to add vertices to line/polygon features*/
48+
class QgsMapToolSimplify: public QgsMapToolEdit
49+
{
50+
Q_OBJECT
51+
52+
public:
53+
QgsMapToolSimplify( QgsMapCanvas* canvas );
54+
virtual ~QgsMapToolSimplify();
55+
56+
void canvasPressEvent( QMouseEvent * e );
57+
58+
//! called when map tool is being deactivated
59+
void deactivate();
60+
61+
public slots:
62+
void removeRubberBand();
63+
64+
private:
65+
66+
int calculateDivider(double num);
67+
68+
void calculateSliderBoudaries();
69+
70+
QVector<QgsPoint> getPointList(QgsFeature& f);
71+
72+
// data
73+
74+
QgsSimplifyDialog* mSimplifyDialog;
75+
76+
QgsRubberBand* mRubberBand;
77+
78+
QgsFeature mSelectedFeature;
79+
80+
int toleranceDivider;
81+
82+
double mTolerance;
83+
84+
private slots:
85+
void toleranceChanged(int tolerance);
86+
void storeSimplified();
87+
88+
};
89+
90+
/**
91+
Implementation of Douglas-Peucker simplification algorithm.
92+
*/
93+
class QgsSimplifyFeature
94+
{
95+
struct StackEntry {
96+
int anchor;
97+
int floater;
98+
};
99+
100+
public:
101+
/** simplify line feature with specified tolerance. Returns TRUE on success */
102+
static bool simplifyLine(QgsFeature &lineFeature, double tolerance);
103+
/** simplify a part of line feature specified by range of vertices with given tolerance. Returns TRUE on success */
104+
static bool simplifyPartOfLine(QgsFeature &lineFeature, int fromVertexNr, int toVertexNr, double tolerance);
105+
/** simplify a line given by a vector of points and tolerance. Returns simplified vector of points */
106+
static QVector<QgsPoint> simplifyPoints (const QVector<QgsPoint>& pts, double tolerance);
107+
108+
109+
};
110+
111+
#endif

‎src/core/qgsgeometry.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5540,3 +5540,117 @@ QList<QgsGeometry*> QgsGeometry::asGeometryCollection()
55405540

55415541
return geomCollection;
55425542
}
5543+
5544+
5545+
bool QgsGeometry::deleteHole( int ringNum, int partNum )
5546+
{
5547+
if (ringNum <= 0 || partNum < 0)
5548+
return FALSE;
5549+
5550+
switch ( wkbType() )
5551+
{
5552+
case QGis::WKBPolygon25D:
5553+
case QGis::WKBPolygon:
5554+
{
5555+
if (partNum != 0)
5556+
return FALSE;
5557+
5558+
QgsPolygon polygon = asPolygon();
5559+
if ( ringNum >= polygon.count() )
5560+
return FALSE;
5561+
5562+
polygon.remove( ringNum );
5563+
5564+
QgsGeometry* g2 = QgsGeometry::fromPolygon( polygon );
5565+
*this = *g2;
5566+
delete g2;
5567+
return TRUE;
5568+
}
5569+
5570+
case QGis::WKBMultiPolygon25D:
5571+
case QGis::WKBMultiPolygon:
5572+
{
5573+
QgsMultiPolygon mpolygon = asMultiPolygon();
5574+
5575+
if (partNum >= mpolygon.count())
5576+
return FALSE;
5577+
5578+
if ( ringNum >= mpolygon[partNum].count() )
5579+
return FALSE;
5580+
5581+
mpolygon[partNum].remove( ringNum );
5582+
5583+
QgsGeometry* g2 = QgsGeometry::fromMultiPolygon( mpolygon );
5584+
*this = *g2;
5585+
delete g2;
5586+
return TRUE;
5587+
}
5588+
5589+
default:
5590+
return FALSE; // only makes sense with polygons and multipolygons
5591+
}
5592+
}
5593+
5594+
5595+
bool QgsGeometry::deletePart( int partNum )
5596+
{
5597+
if (partNum < 0)
5598+
return FALSE;
5599+
5600+
switch ( wkbType() )
5601+
{
5602+
case QGis::WKBMultiPoint25D:
5603+
case QGis::WKBMultiPoint:
5604+
{
5605+
QgsMultiPoint mpoint = asMultiPoint();
5606+
5607+
if (partNum >= mpoint.size() || mpoint.size() == 1)
5608+
return FALSE;
5609+
5610+
mpoint.remove( partNum );
5611+
5612+
QgsGeometry* g2 = QgsGeometry::fromMultiPoint( mpoint );
5613+
*this = *g2;
5614+
delete g2;
5615+
break;
5616+
}
5617+
5618+
case QGis::WKBMultiLineString25D:
5619+
case QGis::WKBMultiLineString:
5620+
{
5621+
QgsMultiPolyline mline = asMultiPolyline();
5622+
5623+
if (partNum >= mline.size() || mline.size() == 1)
5624+
return FALSE;
5625+
5626+
mline.remove( partNum );
5627+
5628+
QgsGeometry* g2 = QgsGeometry::fromMultiPolyline( mline );
5629+
*this = *g2;
5630+
delete g2;
5631+
break;
5632+
}
5633+
5634+
case QGis::WKBMultiPolygon25D:
5635+
case QGis::WKBMultiPolygon:
5636+
{
5637+
QgsMultiPolygon mpolygon = asMultiPolygon();
5638+
5639+
if (partNum >= mpolygon.size() || mpolygon.size() == 1)
5640+
return FALSE;
5641+
5642+
mpolygon.remove( partNum );
5643+
5644+
QgsGeometry* g2 = QgsGeometry::fromMultiPolygon( mpolygon );
5645+
*this = *g2;
5646+
delete g2;
5647+
break;
5648+
}
5649+
5650+
default:
5651+
// single part geometries are ignored
5652+
return FALSE;
5653+
}
5654+
5655+
return TRUE;
5656+
}

‎src/core/qgsgeometry.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,18 @@ class CORE_EXPORT QgsGeometry
332332
@note added in version 1.1 */
333333
QList<QgsGeometry*> asGeometryCollection();
334334

335+
/** delete a hole in polygon or multipolygon.
336+
Ring 0 is outer ring and can't be deleted.
337+
@return TRUE on success
338+
@note added in version 1.2 */
339+
bool deleteHole( int ringNum, int partNum = 0 );
340+
341+
/** delete part identified by the part number
342+
@return TRUE on success
343+
@note added in version 1.2 */
344+
bool deletePart( int partNum );
345+
346+
335347
private:
336348
// Private variables
337349

‎src/ui/qgssimplifytolerancedialog.ui

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>SimplifyLineDialog</class>
4+
<widget class="QDialog" name="SimplifyLineDialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>431</width>
10+
<height>54</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>Simplify line tolerance</string>
15+
</property>
16+
<layout class="QHBoxLayout">
17+
<item>
18+
<widget class="QLabel" name="label">
19+
<property name="text">
20+
<string>Set tolerance</string>
21+
</property>
22+
</widget>
23+
</item>
24+
<item>
25+
<widget class="QSlider" name="horizontalSlider">
26+
<property name="orientation">
27+
<enum>Qt::Horizontal</enum>
28+
</property>
29+
</widget>
30+
</item>
31+
<item>
32+
<widget class="QPushButton" name="okButton">
33+
<property name="text">
34+
<string>OK</string>
35+
</property>
36+
</widget>
37+
</item>
38+
</layout>
39+
</widget>
40+
<resources/>
41+
<connections>
42+
<connection>
43+
<sender>okButton</sender>
44+
<signal>clicked()</signal>
45+
<receiver>SimplifyLineDialog</receiver>
46+
<slot>accept()</slot>
47+
<hints>
48+
<hint type="sourcelabel">
49+
<x>390</x>
50+
<y>24</y>
51+
</hint>
52+
<hint type="destinationlabel">
53+
<x>236</x>
54+
<y>30</y>
55+
</hint>
56+
</hints>
57+
</connection>
58+
</connections>
59+
</ui>

0 commit comments

Comments
 (0)
Please sign in to comment.