@@ -74,74 +74,116 @@ void QgsMapToolReshape::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
74
74
stopCapturing ();
75
75
return ;
76
76
}
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 () )
80
102
{
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 ;
82
109
}
110
+ }
83
111
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
+ }
87
123
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 () );
93
127
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 () )
96
143
{
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 )
102
151
{
103
- reshapeReturn = geom. reshapeGeometry ( reshapeLineString );
104
- if ( reshapeReturn == 0 )
152
+ // avoid intersections on polygon layers
153
+ if ( vlayer-> geometryType () == QgsWkbTypes::PolygonGeometry )
105
154
{
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 )
108
160
{
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 ;
128
165
}
129
166
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
+ }
132
173
}
133
- }
134
- }
135
174
136
- if ( reshapeDone )
137
- {
138
- vlayer->endEditCommand ();
139
- }
140
- else
141
- {
142
- vlayer->destroyEditCommand ();
175
+ vlayer->changeGeometry ( f.id (), geom );
176
+ reshapeDone = true ;
177
+ }
143
178
}
179
+ }
144
180
145
- stopCapturing ();
181
+ if ( reshapeDone )
182
+ {
183
+ vlayer->endEditCommand ();
184
+ }
185
+ else
186
+ {
187
+ vlayer->destroyEditCommand ();
146
188
}
147
189
}
0 commit comments