Skip to content

Commit 052b2eb

Browse files
committed
Merge pull request #1030 from alexbruy/fill-ring
[FEATURE] fill ring digitinzing tool
2 parents ba9936e + dbb48f2 commit 052b2eb

8 files changed

+267
-2
lines changed

images/images.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
<file>themes/default/mActionAddPart.png</file>
133133
<file>themes/default/mActionAddRasterLayer.svg</file>
134134
<file>themes/default/mActionAddRing.png</file>
135+
<file>themes/default/mActionFillRing.png</file>
135136
<file>themes/default/mActionAddSpatiaLiteLayer.svg</file>
136137
<file>themes/default/mActionAddVertex.png</file>
137138
<file>themes/default/mActionAddWcsLayer.svg</file>
1.23 KB
Loading

src/app/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ SET(QGIS_APP_SRCS
4949
qgsmaptooladdfeature.cpp
5050
qgsmaptooladdpart.cpp
5151
qgsmaptooladdring.cpp
52+
qgsmaptoolfillring.cpp
5253
qgsmaptoolannotation.cpp
5354
qgsmaptoolcapture.cpp
5455
qgsmaptoolchangelabelproperties.cpp
@@ -210,6 +211,7 @@ SET (QGIS_APP_MOC_HDRS
210211
qgsmaptoolcapture.h
211212
qgsmaptooladdpart.h
212213
qgsmaptooladdring.h
214+
qgsmaptoolfillring.h
213215
qgsmaptoolchangelabelproperties.h
214216
qgsmaptooldeletepart.h
215217
qgsmaptooldeletering.h

src/app/qgisapp.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
#include "qgsmaptooladdfeature.h"
226226
#include "qgsmaptooladdpart.h"
227227
#include "qgsmaptooladdring.h"
228+
#include "qgsmaptoolfillring.h"
228229
#include "qgsmaptoolannotation.h"
229230
#include "qgsmaptooldeletering.h"
230231
#include "qgsmaptooldeletepart.h"
@@ -793,6 +794,7 @@ QgisApp::~QgisApp()
793794
delete mMapTools.mAddFeature;
794795
delete mMapTools.mAddPart;
795796
delete mMapTools.mAddRing;
797+
delete mMapTools.mFillRing;
796798
delete mMapTools.mAnnotation;
797799
delete mMapTools.mChangeLabelProperties;
798800
delete mMapTools.mDeletePart;
@@ -982,6 +984,7 @@ void QgisApp::createActions()
982984
connect( mActionSplitParts, SIGNAL( triggered() ), this, SLOT( splitParts() ) );
983985
connect( mActionDeleteSelected, SIGNAL( triggered() ), this, SLOT( deleteSelected() ) );
984986
connect( mActionAddRing, SIGNAL( triggered() ), this, SLOT( addRing() ) );
987+
connect( mActionFillRing, SIGNAL( triggered() ), this, SLOT( fillRing() ) );
985988
connect( mActionAddPart, SIGNAL( triggered() ), this, SLOT( addPart() ) );
986989
connect( mActionSimplifyFeature, SIGNAL( triggered() ), this, SLOT( simplifyFeature() ) );
987990
connect( mActionDeleteRing, SIGNAL( triggered() ), this, SLOT( deleteRing() ) );
@@ -1253,6 +1256,7 @@ void QgisApp::createActionGroups()
12531256
mMapToolGroup->addAction( mActionSplitParts );
12541257
mMapToolGroup->addAction( mActionDeleteSelected );
12551258
mMapToolGroup->addAction( mActionAddRing );
1259+
mMapToolGroup->addAction( mActionFillRing );
12561260
mMapToolGroup->addAction( mActionAddPart );
12571261
mMapToolGroup->addAction( mActionSimplifyFeature );
12581262
mMapToolGroup->addAction( mActionDeleteRing );
@@ -1799,6 +1803,7 @@ void QgisApp::setTheme( QString theThemeName )
17991803
mActionUndo->setIcon( QgsApplication::getThemeIcon( "/mActionUndo.png" ) );
18001804
mActionRedo->setIcon( QgsApplication::getThemeIcon( "/mActionRedo.png" ) );
18011805
mActionAddRing->setIcon( QgsApplication::getThemeIcon( "/mActionAddRing.png" ) );
1806+
mActionFillRing->setIcon( QgsApplication::getThemeIcon( "/mActionFillRing.png" ) );
18021807
mActionAddPart->setIcon( QgsApplication::getThemeIcon( "/mActionAddPart.png" ) );
18031808
mActionDeleteRing->setIcon( QgsApplication::getThemeIcon( "/mActionDeleteRing.png" ) );
18041809
mActionDeletePart->setIcon( QgsApplication::getThemeIcon( "/mActionDeletePart.png" ) );
@@ -2030,6 +2035,8 @@ void QgisApp::createCanvasTools()
20302035
mMapTools.mSelectRadius->setAction( mActionSelectRadius );
20312036
mMapTools.mAddRing = new QgsMapToolAddRing( mMapCanvas );
20322037
mMapTools.mAddRing->setAction( mActionAddRing );
2038+
mMapTools.mFillRing = new QgsMapToolFillRing( mMapCanvas );
2039+
mMapTools.mFillRing->setAction( mActionFillRing );
20332040
mMapTools.mAddPart = new QgsMapToolAddPart( mMapCanvas );
20342041
mMapTools.mSimplifyFeature = new QgsMapToolSimplify( mMapCanvas );
20352042
mMapTools.mSimplifyFeature->setAction( mActionSimplifyFeature );
@@ -5573,6 +5580,16 @@ void QgisApp::addRing()
55735580
mMapCanvas->setMapTool( mMapTools.mAddRing );
55745581
}
55755582

5583+
void QgisApp::fillRing()
5584+
{
5585+
if ( mMapCanvas && mMapCanvas->isDrawing() )
5586+
{
5587+
return;
5588+
}
5589+
mMapCanvas->setMapTool( mMapTools.mFillRing );
5590+
}
5591+
5592+
55765593
void QgisApp::addPart()
55775594
{
55785595
if ( mMapCanvas && mMapCanvas->isDrawing() )
@@ -8382,6 +8399,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
83828399
mActionRedo->setEnabled( false );
83838400
mActionSimplifyFeature->setEnabled( false );
83848401
mActionAddRing->setEnabled( false );
8402+
mActionFillRing->setEnabled( false );
83858403
mActionAddPart->setEnabled( false );
83868404
mActionDeleteRing->setEnabled( false );
83878405
mActionDeletePart->setEnabled( false );
@@ -8514,6 +8532,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
85148532
mActionAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionCapturePoint.png" ) );
85158533

85168534
mActionAddRing->setEnabled( false );
8535+
mActionFillRing->setEnabled( false );
85178536
mActionReshapeFeatures->setEnabled( false );
85188537
mActionSplitFeatures->setEnabled( false );
85198538
mActionSplitParts->setEnabled( false );
@@ -8541,13 +8560,15 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
85418560
mActionOffsetCurve->setEnabled( isEditable && canAddFeatures && canChangeAttributes );
85428561

85438562
mActionAddRing->setEnabled( false );
8563+
mActionFillRing->setEnabled( false );
85448564
mActionDeleteRing->setEnabled( false );
85458565
}
85468566
else if ( vlayer->geometryType() == QGis::Polygon )
85478567
{
85488568
mActionAddFeature->setIcon( QgsApplication::getThemeIcon( "/mActionCapturePolygon.png" ) );
85498569

85508570
mActionAddRing->setEnabled( isEditable && canAddFeatures );
8571+
mActionFillRing->setEnabled( isEditable && canAddFeatures );
85518572
mActionReshapeFeatures->setEnabled( isEditable && canAddFeatures );
85528573
mActionSplitFeatures->setEnabled( isEditable && canAddFeatures );
85538574
mActionSplitParts->setEnabled( isEditable && canAddFeatures );
@@ -8621,6 +8642,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
86218642
mActionAddFeature->setEnabled( false );
86228643
mActionDeleteSelected->setEnabled( false );
86238644
mActionAddRing->setEnabled( false );
8645+
mActionFillRing->setEnabled( false );
86248646
mActionAddPart->setEnabled( false );
86258647
mActionNodeTool->setEnabled( false );
86268648
mActionMoveFeature->setEnabled( false );

src/app/qgisapp.h

+4
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
272272
QAction *actionSplitFeatures() { return mActionSplitFeatures; }
273273
QAction *actionSplitParts() { return mActionSplitParts; }
274274
QAction *actionAddRing() { return mActionAddRing; }
275+
QAction *actionFillRing() { return mActionFillRing; }
275276
QAction *actionAddPart() { return mActionAddPart; }
276277
QAction *actionSimplifyFeature() { return mActionSimplifyFeature; }
277278
QAction *actionDeleteRing() { return mActionDeleteRing; }
@@ -937,6 +938,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
937938
void splitParts();
938939
//! activates the add ring tool
939940
void addRing();
941+
//! activates the fill ring tool
942+
void fillRing();
940943
//! activates the add part tool
941944
void addPart();
942945
//! simplifies feature
@@ -1358,6 +1361,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
13581361
QgsMapTool* mVertexMove;
13591362
QgsMapTool* mVertexDelete;
13601363
QgsMapTool* mAddRing;
1364+
QgsMapTool* mFillRing;
13611365
QgsMapTool* mAddPart;
13621366
QgsMapTool* mSimplifyFeature;
13631367
QgsMapTool* mDeleteRing;

src/app/qgsmaptoolfillring.cpp

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/***************************************************************************
2+
qgsmaptoolfillring.h - map tool to cut rings in polygon and multipolygon
3+
features and fill them with new feature
4+
---------------------
5+
begin : December 2013
6+
copyright : (C) 2013 by Alexander Bruy
7+
email : alexander dot bruy at gmail dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
#include "qgsmaptoolfillring.h"
18+
#include "qgsgeometry.h"
19+
#include "qgsmapcanvas.h"
20+
#include "qgsvectorlayer.h"
21+
#include "qgsattributedialog.h"
22+
#include <qgsapplication.h>
23+
24+
#include <QMessageBox>
25+
#include <QMouseEvent>
26+
27+
#include <limits>
28+
29+
QgsMapToolFillRing::QgsMapToolFillRing( QgsMapCanvas* canvas ): QgsMapToolCapture( canvas, QgsMapToolCapture::CapturePolygon )
30+
{
31+
32+
}
33+
34+
QgsMapToolFillRing::~QgsMapToolFillRing()
35+
{
36+
37+
}
38+
39+
void QgsMapToolFillRing::canvasReleaseEvent( QMouseEvent * e )
40+
{
41+
//check if we operate on a vector layer
42+
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
43+
44+
if ( !vlayer )
45+
{
46+
notifyNotVectorLayer();
47+
return;
48+
}
49+
50+
if ( !vlayer->isEditable() )
51+
{
52+
notifyNotEditableLayer();
53+
return;
54+
}
55+
56+
//add point to list and to rubber band
57+
if ( e->button() == Qt::LeftButton )
58+
{
59+
int error = addVertex( e->pos() );
60+
if ( error == 1 )
61+
{
62+
//current layer is not a vector layer
63+
return;
64+
}
65+
else if ( error == 2 )
66+
{
67+
//problem with coordinate transformation
68+
QMessageBox::information( 0, tr( "Coordinate transform error" ),
69+
tr( "Cannot transform the point to the layers coordinate system" ) );
70+
return;
71+
}
72+
73+
startCapturing();
74+
}
75+
else if ( e->button() == Qt::RightButton )
76+
{
77+
deleteTempRubberBand();
78+
79+
closePolygon();
80+
81+
vlayer->beginEditCommand( tr( "Ring added and filled" ) );
82+
int addRingReturnCode = vlayer->addRing( points() );
83+
if ( addRingReturnCode != 0 )
84+
{
85+
QString errorMessage;
86+
//todo: open message box to communicate errors
87+
if ( addRingReturnCode == 1 )
88+
{
89+
errorMessage = tr( "A problem with geometry type occured" );
90+
}
91+
else if ( addRingReturnCode == 2 )
92+
{
93+
errorMessage = tr( "The inserted Ring is not closed" );
94+
}
95+
else if ( addRingReturnCode == 3 )
96+
{
97+
errorMessage = tr( "The inserted Ring is not a valid geometry" );
98+
}
99+
else if ( addRingReturnCode == 4 )
100+
{
101+
errorMessage = tr( "The inserted Ring crosses existing rings" );
102+
}
103+
else if ( addRingReturnCode == 5 )
104+
{
105+
errorMessage = tr( "The inserted Ring is not contained in a feature" );
106+
}
107+
else
108+
{
109+
errorMessage = tr( "An unknown error occured" );
110+
}
111+
QMessageBox::critical( 0, tr( "Error, could not add ring" ), errorMessage );
112+
vlayer->destroyEditCommand();
113+
}
114+
else
115+
{
116+
// find parent feature and get it attributes
117+
double xMin, xMax, yMin, yMax;
118+
QgsRectangle bBox;
119+
120+
xMin = std::numeric_limits<double>::max();
121+
xMax = -std::numeric_limits<double>::max();
122+
yMin = std::numeric_limits<double>::max();
123+
yMax = -std::numeric_limits<double>::max();
124+
125+
for ( QList<QgsPoint>::const_iterator it = points().constBegin(); it != points().constEnd(); ++it )
126+
{
127+
if ( it->x() < xMin )
128+
{
129+
xMin = it->x();
130+
}
131+
if ( it->x() > xMax )
132+
{
133+
xMax = it->x();
134+
}
135+
if ( it->y() < yMin )
136+
{
137+
yMin = it->y();
138+
}
139+
if ( it->y() > yMax )
140+
{
141+
yMax = it->y();
142+
}
143+
}
144+
bBox.setXMinimum( xMin );
145+
bBox.setYMinimum( yMin );
146+
bBox.setXMaximum( xMax );
147+
bBox.setYMaximum( yMax );
148+
149+
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
150+
151+
QgsFeature f;
152+
bool res = false;
153+
while ( fit.nextFeature( f ) )
154+
{
155+
//create QgsFeature with wkb representation
156+
QgsFeature* ft = new QgsFeature( vlayer->pendingFields(), 0 );
157+
158+
QgsGeometry *g;
159+
g = QgsGeometry::fromPolygon( QgsPolygon() << points().toVector() );
160+
ft->setGeometry( g );
161+
ft->setAttributes( f.attributes() );
162+
163+
if ( QgsApplication::keyboardModifiers() == Qt::ControlModifier )
164+
{
165+
res = vlayer->addFeature( *ft );
166+
}
167+
else
168+
{
169+
QgsAttributeDialog *dialog = new QgsAttributeDialog( vlayer, ft, false, NULL, true );
170+
if ( dialog->exec() )
171+
{
172+
res = vlayer->addFeature( *ft );
173+
}
174+
}
175+
176+
if ( res )
177+
{
178+
vlayer->endEditCommand();
179+
}
180+
else
181+
{
182+
delete ft;
183+
vlayer->destroyEditCommand();
184+
}
185+
res = false;
186+
}
187+
}
188+
stopCapturing();
189+
}
190+
}

src/app/qgsmaptoolfillring.h

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/***************************************************************************
2+
qgsmaptoolfillring.h - map tool to cut rings in polygon and multipolygon
3+
features and fill them with new feature
4+
---------------------
5+
begin : December 2013
6+
copyright : (C) 2013 by Alexander Bruy
7+
email : alexander dot bruy at gmail dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
#include "qgsmaptoolcapture.h"
18+
19+
/** A tool to cut holes into polygon and multipolygon features and fill them
20+
* with new feature. Attributes are copied from parent feature.
21+
* */
22+
class APP_EXPORT QgsMapToolFillRing: public QgsMapToolCapture
23+
{
24+
Q_OBJECT
25+
public:
26+
QgsMapToolFillRing( QgsMapCanvas* canvas );
27+
virtual ~QgsMapToolFillRing();
28+
void canvasReleaseEvent( QMouseEvent * e );
29+
};

0 commit comments

Comments
 (0)