@@ -164,55 +164,33 @@ class OneFeatureFilter : public QgsPointLocator::MatchFilter
164
164
};
165
165
166
166
167
- // ! a filter just to gather all matches at the same place
167
+ /* *
168
+ * For polygons we need to filter out the last vertex, because it will have
169
+ * the same coordinates than the first and we would have a duplicate match which
170
+ * would make topology editing mode behave incorrectly
171
+ */
168
172
class MatchCollectingFilter : public QgsPointLocator ::MatchFilter
169
173
{
170
174
public:
171
- QList<QgsPointLocator::Match> matches;
172
175
QgsVertexTool *vertextool = nullptr ;
173
176
174
177
MatchCollectingFilter ( QgsVertexTool *vertextool )
175
178
: vertextool( vertextool ) {}
176
179
177
180
bool acceptMatch ( const QgsPointLocator::Match &match ) override
178
181
{
179
- if ( match.distance () > 0 )
180
- return false ;
182
+ if ( match.layer ()-> geometryType () != Qgis::GeometryType::Polygon )
183
+ return true ;
181
184
182
- // there may be multiple points at the same location, but we get only one
183
- // result... the locator API needs a new method verticesInRect()
184
- QgsGeometry matchGeom = vertextool->cachedGeometry ( match.layer (), match.featureId () );
185
- bool isPolygon = matchGeom.type () == Qgis::GeometryType::Polygon;
186
- QgsVertexId polygonRingVid;
187
185
QgsVertexId vid;
188
- QgsPoint pt;
189
- while ( matchGeom.constGet ()->nextVertex ( vid, pt ) )
190
- {
191
- int vindex = matchGeom.vertexNrFromVertexId ( vid );
192
- if ( pt.x () == match.point ().x () && pt.y () == match.point ().y () )
193
- {
194
- if ( isPolygon )
195
- {
196
- // for polygons we need to handle the case where the first vertex is matching because the
197
- // last point will have the same coordinates and we would have a duplicate match which
198
- // would make subsequent code behave incorrectly (topology editing mode would add a single
199
- // vertex twice)
200
- if ( vid.vertex == 0 )
201
- {
202
- polygonRingVid = vid;
203
- }
204
- else if ( vid.ringEqual ( polygonRingVid ) && vid.vertex == matchGeom.constGet ()->vertexCount ( vid.part , vid.ring ) - 1 )
205
- {
206
- continue ;
207
- }
208
- }
186
+ QgsGeometry matchGeom = vertextool->cachedGeometry ( match.layer (), match.featureId () );
187
+ if ( !matchGeom.vertexIdFromVertexNr ( match.vertexIndex (), vid ) )
188
+ // should not happen because vertex index in match object was created with vertexNrFromVertexId
189
+ // so the methods are reversible and we will have a vid
190
+ return false ;
209
191
210
- QgsPointLocator::Match extra_match ( match.type (), match.layer (), match.featureId (),
211
- 0 , match.point (), vindex );
212
- matches.append ( extra_match );
213
- }
214
- }
215
- return true ;
192
+ // filter out the vertex if it is the last one (of its ring, in its part)
193
+ return vid.vertex != matchGeom.constGet ()->vertexCount ( vid.part , vid.ring ) - 1 ;
216
194
}
217
195
};
218
196
@@ -1013,7 +991,7 @@ QgsPointLocator::Match QgsVertexTool::snapToPolygonInterior( QgsMapMouseEvent *e
1013
991
}
1014
992
1015
993
1016
- QList< QgsPointLocator::Match> QgsVertexTool::findEditableLayerMatches ( const QgsPointXY &mapPoint, QgsVectorLayer *layer )
994
+ QgsPointLocator::MatchList QgsVertexTool::findEditableLayerMatches ( const QgsPointXY &mapPoint, QgsVectorLayer *layer )
1017
995
{
1018
996
QgsPointLocator::MatchList matchList;
1019
997
@@ -1936,29 +1914,29 @@ void QgsVertexTool::buildDragBandsForVertices( const QSet<Vertex> &movingVertice
1936
1914
}
1937
1915
}
1938
1916
1939
- QList< QgsPointLocator::Match> QgsVertexTool::layerVerticesSnappedToPoint ( QgsVectorLayer *layer, const QgsPointXY &mapPoint )
1917
+ QgsPointLocator::MatchList QgsVertexTool::layerVerticesSnappedToPoint ( QgsVectorLayer *layer, const QgsPointXY &mapPoint )
1940
1918
{
1941
1919
MatchCollectingFilter myfilter ( this );
1942
1920
QgsPointLocator *loc = canvas ()->snappingUtils ()->locatorForLayer ( layer );
1943
- loc-> nearestVertex ( mapPoint, 0 , &myfilter, true );
1944
- return myfilter. matches ;
1921
+ double tol = QgsTolerance::vertexSearchRadius ( canvas ()-> mapSettings () );
1922
+ return loc-> verticesInRect ( mapPoint, tol, & myfilter, true ) ;
1945
1923
}
1946
1924
1947
- QList< QgsPointLocator::Match> QgsVertexTool::layerSegmentsSnappedToSegment ( QgsVectorLayer *layer, const QgsPointXY &mapPoint1, const QgsPointXY &mapPoint2 )
1925
+ QgsPointLocator::MatchList QgsVertexTool::layerSegmentsSnappedToSegment ( QgsVectorLayer *layer, const QgsPointXY &mapPoint1, const QgsPointXY &mapPoint2 )
1948
1926
{
1949
- QList< QgsPointLocator::Match> finalMatches;
1927
+ QgsPointLocator::MatchList finalMatches;
1950
1928
// we want segment matches that have exactly the same vertices as the given segment (mapPoint1, mapPoint2)
1951
1929
// so rather than doing nearest edge search which could return any segment within a tolerance,
1952
1930
// we first find matches for one endpoint and then see if there is a matching other endpoint.
1953
- const QList< QgsPointLocator::Match> matches1 = layerVerticesSnappedToPoint ( layer, mapPoint1 );
1931
+ const QgsPointLocator::MatchList matches1 = layerVerticesSnappedToPoint ( layer, mapPoint1 );
1954
1932
for ( const QgsPointLocator::Match &m : matches1 )
1955
1933
{
1956
1934
QgsGeometry g = cachedGeometry ( layer, m.featureId () );
1957
1935
int v0, v1;
1958
1936
g.adjacentVertices ( m.vertexIndex (), v0, v1 );
1959
- if ( v0 != -1 && QgsPointXY ( g.vertexAt ( v0 ) ) == mapPoint2 )
1937
+ if ( v0 != -1 && toMapCoordinates ( layer, QgsPointXY ( g.vertexAt ( v0 ) ) ) == mapPoint2 )
1960
1938
finalMatches << QgsPointLocator::Match ( QgsPointLocator::Edge, layer, m.featureId (), 0 , m.point (), v0 );
1961
- else if ( v1 != -1 && QgsPointXY ( g.vertexAt ( v1 ) ) == mapPoint2 )
1939
+ else if ( v1 != -1 && toMapCoordinates ( layer, QgsPointXY ( g.vertexAt ( v1 ) ) ) == mapPoint2 )
1962
1940
finalMatches << QgsPointLocator::Match ( QgsPointLocator::Edge, layer, m.featureId (), 0 , m.point (), m.vertexIndex () );
1963
1941
}
1964
1942
return finalMatches;
0 commit comments