Skip to content

Commit 6b0796e

Browse files
committedApr 30, 2014
Allow to delete ring by clicking inside the ring
1 parent 717ef84 commit 6b0796e

File tree

3 files changed

+107
-49
lines changed

3 files changed

+107
-49
lines changed
 

‎src/app/qgsmaptooldeletepart.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
#include <QMessageBox>
2727

2828
QgsMapToolDeletePart::QgsMapToolDeletePart( QgsMapCanvas* canvas )
29-
: QgsMapToolEdit( canvas ), mCross( 0 )
29+
: QgsMapToolEdit( canvas )
3030
{
3131
}
3232

@@ -88,10 +88,10 @@ void QgsMapToolDeletePart::canvasReleaseEvent( QMouseEvent *e )
8888
g = f.geometry();
8989
if ( !g )
9090
return;
91-
if ( ( g->type() == QGis::Point && g->asMultiPoint().size() == 1) ||
92-
( g->type() == QGis::Line && g->asMultiPolyline().size() == 1 ) )
91+
if ( g->wkbType() == QGis::WKBPoint25D || g->wkbType() == QGis::WKBPoint ||
92+
g->wkbType() == QGis::WKBLineString25D || g->wkbType() == QGis::WKBLineString)
9393
{
94-
notifySinglePart();
94+
emit messageEmitted( tr( "The Delete part tool cannot be used on single part features." ) );
9595
return;
9696
}
9797
int vertex = sr.snappedVertexNr;
@@ -110,9 +110,10 @@ void QgsMapToolDeletePart::canvasReleaseEvent( QMouseEvent *e )
110110
g = f.geometry();
111111
if ( !g )
112112
return;
113-
if ( g->asMultiPolygon().size() == 1 )
113+
114+
if ( g->wkbType() == QGis::WKBPolygon25D || g->wkbType() == QGis::WKBPolygon)
114115
{
115-
notifySinglePart();
116+
emit messageEmitted( tr( "The Delete part tool cannot be used on single part features." ) );
116117
return;
117118
}
118119
partNum = partNumberOfPoint( g, p );
@@ -135,11 +136,7 @@ void QgsMapToolDeletePart::canvasReleaseEvent( QMouseEvent *e )
135136
}
136137
else
137138
{
138-
QgisApp::instance()->messageBar()->pushMessage(
139-
tr( "Delete part" ),
140-
tr( "Couldn't remove the selected part." ),
141-
QgsMessageBar::WARNING,
142-
QgisApp::instance()->messageTimeout() );
139+
emit messageEmitted( tr( "Couldn't remove the selected part." ) );
143140
}
144141
return;
145142
}

‎src/app/qgsmaptooldeletering.cpp

Lines changed: 94 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@
1818
#include "qgsmapcanvas.h"
1919
#include "qgsvertexmarker.h"
2020
#include "qgsvectorlayer.h"
21+
#include "qgsmessagebar.h"
22+
#include "qgisapp.h"
2123

2224
#include <QMouseEvent>
2325
#include <QMessageBox>
2426

2527
QgsMapToolDeleteRing::QgsMapToolDeleteRing( QgsMapCanvas* canvas )
2628
: QgsMapToolVertexEdit( canvas )
27-
, mCross( 0 )
2829
{
2930
mToolName = tr( "Delete ring" );
3031
}
3132

3233
QgsMapToolDeleteRing::~QgsMapToolDeleteRing()
3334
{
34-
delete mCross;
3535
}
3636

3737
void QgsMapToolDeleteRing::canvasMoveEvent( QMouseEvent *e )
@@ -42,62 +42,110 @@ void QgsMapToolDeleteRing::canvasMoveEvent( QMouseEvent *e )
4242

4343
void QgsMapToolDeleteRing::canvasPressEvent( QMouseEvent *e )
4444
{
45-
delete mCross;
46-
mCross = 0;
47-
48-
mRecentSnappingResults.clear();
4945
//do snap -> new recent snapping results
5046
if ( mSnapper.snapToCurrentLayer( e->pos(), mRecentSnappingResults, QgsSnapper::SnapToVertexAndSegment ) != 0 )
5147
{
5248
//error
5349
}
54-
55-
if ( mRecentSnappingResults.size() > 0 )
56-
{
57-
// remove previous warning
58-
emit messageDiscarded();
59-
60-
QgsPoint markerPoint = mRecentSnappingResults.begin()->snappedVertex;
61-
62-
//show vertex marker
63-
mCross = new QgsVertexMarker( mCanvas );
64-
mCross->setIconType( QgsVertexMarker::ICON_X );
65-
mCross->setCenter( markerPoint );
66-
}
67-
else
68-
{
69-
emit messageEmitted( tr( "could not snap to a ring on the current layer." ) );
70-
}
7150
}
7251

7352
void QgsMapToolDeleteRing::canvasReleaseEvent( QMouseEvent *e )
7453
{
7554
Q_UNUSED( e );
76-
delete mCross;
77-
mCross = 0;
7855

7956
QgsMapLayer* currentLayer = mCanvas->currentLayer();
8057
if ( !currentLayer )
8158
return;
8259

83-
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( currentLayer );
60+
vlayer = qobject_cast<QgsVectorLayer *>( currentLayer );
8461
if ( !vlayer )
62+
{
63+
notifyNotVectorLayer();
64+
return;
65+
}
66+
67+
if ( vlayer->geometryType() != QGis::Polygon )
68+
{
69+
emit messageEmitted( tr( "Delete ring can only be used in a polygon layer." ) );
70+
return;
71+
}
72+
73+
if ( !vlayer->isEditable() )
74+
{
75+
notifyNotEditableLayer();
8576
return;
77+
}
8678

79+
QgsPoint p = mCanvas->getCoordinateTransform()->toMapCoordinates( e->x(),e->y());
80+
p = toLayerCoordinates(vlayer, p);
8781

88-
if ( mRecentSnappingResults.size() > 0 )
82+
//There is no easy way to find if we are inside the ring of a feature,
83+
//so we iterate over all the features visible in the canvas
84+
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( mCanvas->extent() ) );
85+
QgsFeature f;
86+
QgsGeometry* g;
87+
QgsMultiPolygon pol;
88+
QgsPolygon tempPol;
89+
QgsGeometry* tempGeom;
90+
int fid, partNum, ringNum;
91+
double area = std::numeric_limits<double>::max();
92+
while ( fit.nextFeature( f ) )
8993
{
90-
QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
91-
for ( ; sr_it != mRecentSnappingResults.end(); ++sr_it )
94+
QgsDebugMsg(QString("Feature %1").arg(f.id()));
95+
g = f.geometry();
96+
if ( !g )
97+
continue;
98+
if ( g->wkbType() == QGis::WKBPolygon || g->wkbType() == QGis::WKBPolygon25D )
99+
{
100+
pol = QgsMultiPolygon() << g->asPolygon();
101+
}
102+
else
92103
{
93-
if ( sr_it->snappedVertexNr != -1 )
94-
deleteRing( sr_it->snappedAtGeometry, sr_it->snappedVertexNr, vlayer );
95-
else if ( sr_it->beforeVertexNr != -1 )
96-
deleteRing( sr_it->snappedAtGeometry, sr_it->beforeVertexNr, vlayer );
97-
else if ( sr_it->afterVertexNr != -1 )
98-
deleteRing( sr_it->snappedAtGeometry, sr_it->afterVertexNr, vlayer );
104+
pol = g->asMultiPolygon();
99105
}
106+
107+
for (int i = 0; i < pol.size() ; ++i)
108+
{//for each part
109+
QgsDebugMsg(QString("Feature %1 part %2").arg(f.id()).arg(i));
110+
if ( pol[i].size() > 1 )
111+
{
112+
QgsDebugMsg(QString("%1 has a ring in part %2").arg(f.id()).arg(i));
113+
for ( int j = 1; j<pol[i].size();++j)
114+
{
115+
tempPol = QgsPolygon()<<pol[i][j];
116+
tempGeom = QgsGeometry::fromPolygon( tempPol );
117+
if (tempGeom->area() < area && tempGeom->contains(&p) )
118+
{
119+
QgsDebugMsg(QString("%1, part %2, ring %3 contains the cursor").arg(f.id()).arg(i).arg(j));
120+
fid=f.id();
121+
partNum=i;
122+
ringNum=j;
123+
area=tempGeom->area();
124+
}
125+
}
126+
}
127+
}
128+
}
129+
130+
vlayer->getFeatures( QgsFeatureRequest().setFilterFid( fid ) ).nextFeature( f );
131+
132+
g = f.geometry();
133+
if ( g->deleteRing( ringNum, partNum ) )
134+
{
135+
vlayer->beginEditCommand( tr( "Ring deleted" ) );
136+
vlayer->changeGeometry( fid, g );
137+
vlayer->endEditCommand();
138+
mCanvas->refresh();
100139
}
140+
/*
141+
if ( g->deleteRing( ringNum, partNum ) )
142+
{
143+
vlayer->beginEditCommand( tr( "Ring deleted" ) );
144+
vlayer->changeGeometry( f.id(), g );
145+
vlayer->endEditCommand();
146+
mCanvas->refresh();
147+
}
148+
*/
101149
}
102150

103151
void QgsMapToolDeleteRing::deleteRing( QgsFeatureId fId, int beforeVertexNr, QgsVectorLayer* vlayer )
@@ -130,6 +178,17 @@ void QgsMapToolDeleteRing::deleteRing( QgsFeatureId fId, int beforeVertexNr, Qgs
130178

131179
}
132180

181+
int QgsMapToolDeleteRing::partNumberOfPoint(QgsGeometry* g, QgsPoint p)
182+
{
183+
return 0;
184+
}
185+
186+
int QgsMapToolDeleteRing::ringNumberOfPoint(QgsGeometry* g, QgsPoint p, int partNum)
187+
{
188+
return 0;
189+
}
190+
191+
133192
int QgsMapToolDeleteRing::ringNumInPolygon( QgsGeometry* g, int vertexNr )
134193
{
135194
QgsPolygon polygon = g->asPolygon();
@@ -166,8 +225,6 @@ int QgsMapToolDeleteRing::ringNumInMultiPolygon( QgsGeometry* g, int vertexNr, i
166225

167226
void QgsMapToolDeleteRing::deactivate()
168227
{
169-
delete mCross;
170-
mCross = 0;
171228

172229
QgsMapTool::deactivate();
173230
}

‎src/app/qgsmaptooldeletering.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class APP_EXPORT QgsMapToolDeleteRing : public QgsMapToolVertexEdit
3939
void deactivate();
4040

4141
private:
42-
QgsVertexMarker* mCross;
42+
QgsVectorLayer* vlayer;
4343

4444
//! delete inner ring from the geometry
4545
void deleteRing( QgsFeatureId fId, int beforeVertexNr, QgsVectorLayer* vlayer );
@@ -49,6 +49,10 @@ class APP_EXPORT QgsMapToolDeleteRing : public QgsMapToolVertexEdit
4949

5050
//! return ring number in multipolygon and set parNum to index of the part
5151
int ringNumInMultiPolygon( QgsGeometry* g, int vertexNr, int& partNum );
52+
53+
int partNumberOfPoint(QgsGeometry* g, QgsPoint point );
54+
int ringNumberOfPoint(QgsGeometry* g, QgsPoint point, int part );
55+
5256
};
5357

5458
#endif

0 commit comments

Comments
 (0)
Please sign in to comment.