Skip to content

Commit 096f689

Browse files
committed
[bugfix] Do no add binding line in both side in reshape map tool
1 parent aa68a9f commit 096f689

File tree

4 files changed

+107
-56
lines changed

4 files changed

+107
-56
lines changed

src/app/qgsmaptoolreshape.cpp

Lines changed: 96 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -74,74 +74,116 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
7474
stopCapturing();
7575
return;
7676
}
77-
QgsPointXY firstPoint = points().at( 0 );
78-
QgsRectangle bbox( firstPoint.x(), firstPoint.y(), firstPoint.x(), firstPoint.y() );
79-
for ( int i = 1; i < size(); ++i )
77+
78+
reshape( vlayer );
79+
80+
stopCapturing();
81+
}
82+
}
83+
84+
bool QgsMapToolReshape::isBindingLine( QgsVectorLayer *vlayer, const QgsRectangle &bbox ) const
85+
{
86+
if ( vlayer->geometryType() != QgsWkbTypes::LineGeometry )
87+
return false;
88+
89+
bool begin = false;
90+
bool end = false;
91+
const QgsPointXY beginPoint = points().first();
92+
const QgsPointXY endPoint = points().last();
93+
94+
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bbox ).setSubsetOfAttributes( QgsAttributeList() ) );
95+
QgsFeature f;
96+
97+
// check that extremities of the new line are contained by features
98+
while ( fit.nextFeature( f ) )
99+
{
100+
const QgsGeometry geom = f.geometry();
101+
if ( !geom.isNull() )
80102
{
81-
bbox.combineExtentWith( points().at( i ).x(), points().at( i ).y() );
103+
const QgsPolylineXY line = geom.asPolyline();
104+
105+
if ( line.contains( beginPoint ) )
106+
begin = true;
107+
else if ( line.contains( endPoint ) )
108+
end = true;
82109
}
110+
}
83111

84-
QgsLineString reshapeLineString( points() );
85-
if ( QgsWkbTypes::hasZ( vlayer->wkbType() ) )
86-
reshapeLineString.addZValue( defaultZValue() );
112+
return end && begin;
113+
}
114+
115+
void QgsMapToolReshape::reshape( QgsVectorLayer *vlayer )
116+
{
117+
QgsPointXY firstPoint = points().at( 0 );
118+
QgsRectangle bbox( firstPoint.x(), firstPoint.y(), firstPoint.x(), firstPoint.y() );
119+
for ( int i = 1; i < size(); ++i )
120+
{
121+
bbox.combineExtentWith( points().at( i ).x(), points().at( i ).y() );
122+
}
87123

88-
//query all the features that intersect bounding box of capture line
89-
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bbox ).setSubsetOfAttributes( QgsAttributeList() ) );
90-
QgsFeature f;
91-
int reshapeReturn;
92-
bool reshapeDone = false;
124+
QgsLineString reshapeLineString( points() );
125+
if ( QgsWkbTypes::hasZ( vlayer->wkbType() ) )
126+
reshapeLineString.addZValue( defaultZValue() );
93127

94-
vlayer->beginEditCommand( tr( "Reshape" ) );
95-
while ( fit.nextFeature( f ) )
128+
//query all the features that intersect bounding box of capture line
129+
QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bbox ).setSubsetOfAttributes( QgsAttributeList() ) );
130+
QgsFeature f;
131+
int reshapeReturn;
132+
bool reshapeDone = false;
133+
bool isBinding = isBindingLine( vlayer, bbox );
134+
135+
vlayer->beginEditCommand( tr( "Reshape" ) );
136+
while ( fit.nextFeature( f ) )
137+
{
138+
//query geometry
139+
//call geometry->reshape(mCaptureList)
140+
//register changed geometry in vector layer
141+
QgsGeometry geom = f.geometry();
142+
if ( !geom.isNull() )
96143
{
97-
//query geometry
98-
//call geometry->reshape(mCaptureList)
99-
//register changed geometry in vector layer
100-
QgsGeometry geom = f.geometry();
101-
if ( !geom.isNull() )
144+
// in case of a binding line, we just want to update the line from
145+
// the starting point and not both side
146+
if ( isBinding && !geom.asPolyline().contains( points().first() ) )
147+
continue;
148+
149+
reshapeReturn = geom.reshapeGeometry( reshapeLineString );
150+
if ( reshapeReturn == 0 )
102151
{
103-
reshapeReturn = geom.reshapeGeometry( reshapeLineString );
104-
if ( reshapeReturn == 0 )
152+
//avoid intersections on polygon layers
153+
if ( vlayer->geometryType() == QgsWkbTypes::PolygonGeometry )
105154
{
106-
//avoid intersections on polygon layers
107-
if ( vlayer->geometryType() == QgsWkbTypes::PolygonGeometry )
155+
//ignore all current layer features as they should be reshaped too
156+
QHash<QgsVectorLayer *, QSet<QgsFeatureId> > ignoreFeatures;
157+
ignoreFeatures.insert( vlayer, vlayer->allFeatureIds() );
158+
159+
if ( geom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers(), ignoreFeatures ) != 0 )
108160
{
109-
//ignore all current layer features as they should be reshaped too
110-
QHash<QgsVectorLayer *, QSet<QgsFeatureId> > ignoreFeatures;
111-
ignoreFeatures.insert( vlayer, vlayer->allFeatureIds() );
112-
113-
if ( geom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers(), ignoreFeatures ) != 0 )
114-
{
115-
emit messageEmitted( tr( "An error was reported during intersection removal" ), QgsMessageBar::CRITICAL );
116-
vlayer->destroyEditCommand();
117-
stopCapturing();
118-
return;
119-
}
120-
121-
if ( geom.isEmpty() ) //intersection removal might have removed the whole geometry
122-
{
123-
emit messageEmitted( tr( "The feature cannot be reshaped because the resulting geometry is empty" ), QgsMessageBar::CRITICAL );
124-
vlayer->destroyEditCommand();
125-
stopCapturing();
126-
return;
127-
}
161+
emit messageEmitted( tr( "An error was reported during intersection removal" ), QgsMessageBar::CRITICAL );
162+
vlayer->destroyEditCommand();
163+
stopCapturing();
164+
return;
128165
}
129166

130-
vlayer->changeGeometry( f.id(), geom );
131-
reshapeDone = true;
167+
if ( geom.isEmpty() ) //intersection removal might have removed the whole geometry
168+
{
169+
emit messageEmitted( tr( "The feature cannot be reshaped because the resulting geometry is empty" ), QgsMessageBar::CRITICAL );
170+
vlayer->destroyEditCommand();
171+
return;
172+
}
132173
}
133-
}
134-
}
135174

136-
if ( reshapeDone )
137-
{
138-
vlayer->endEditCommand();
139-
}
140-
else
141-
{
142-
vlayer->destroyEditCommand();
175+
vlayer->changeGeometry( f.id(), geom );
176+
reshapeDone = true;
177+
}
143178
}
179+
}
144180

145-
stopCapturing();
181+
if ( reshapeDone )
182+
{
183+
vlayer->endEditCommand();
184+
}
185+
else
186+
{
187+
vlayer->destroyEditCommand();
146188
}
147189
}

src/app/qgsmaptoolreshape.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ class APP_EXPORT QgsMapToolReshape: public QgsMapToolCapture
2727
public:
2828
QgsMapToolReshape( QgsMapCanvas *canvas );
2929
void cadCanvasReleaseEvent( QgsMapMouseEvent *e ) override;
30+
31+
private:
32+
void reshape( QgsVectorLayer *vlayer );
33+
34+
bool isBindingLine( QgsVectorLayer *vlayer, const QgsRectangle &bbox ) const;
35+
36+
friend class TestQgsMapToolReshape;
3037
};
3138

3239
#endif

src/gui/qgsmaptoolcapture.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ int QgsMapToolCapture::size()
763763
return mCaptureCurve.numPoints();
764764
}
765765

766-
QVector<QgsPointXY> QgsMapToolCapture::points()
766+
QVector<QgsPointXY> QgsMapToolCapture::points() const
767767
{
768768
QgsPointSequence pts;
769769
QVector<QgsPointXY> points;

src/gui/qgsmaptoolcapture.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
192192
* List of digitized points
193193
* \returns List of points
194194
*/
195-
QVector<QgsPointXY> points();
195+
QVector<QgsPointXY> points() const;
196196

197197
/**
198198
* Set the points on which to work
@@ -259,6 +259,8 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
259259
*/
260260
QgsPointXY mTracingStartPoint;
261261

262+
friend class TestQgsMapToolReshape;
263+
262264
#ifdef Q_OS_WIN
263265
int mSkipNextContextMenuEvent;
264266
#endif

0 commit comments

Comments
 (0)