Branch data Line data Source code
1 : : /***************************************************************************
2 : : testqgsgeometrysnapper.cpp
3 : : --------------------------
4 : : Date : November 2016
5 : : Copyright : (C) 2016 by Nyall Dawson
6 : : Email : nyall dot dawson at gmail dot com
7 : : ***************************************************************************
8 : : * *
9 : : * This program is free software; you can redistribute it and/or modify *
10 : : * it under the terms of the GNU General Public License as published by *
11 : : * the Free Software Foundation; either version 2 of the License, or *
12 : : * (at your option) any later version. *
13 : : * *
14 : : ***************************************************************************/
15 : : #include "qgstest.h"
16 : :
17 : : //header for class being tested
18 : : #include "qgsgeometrysnapper.h"
19 : : #include "qgsgeometry.h"
20 : : #include <qgsapplication.h>
21 : : #include "qgsvectordataprovider.h"
22 : : #include "qgsvectorlayer.h"
23 : :
24 : :
25 : 2 : class TestQgsGeometrySnapper : public QObject
26 : : {
27 : : Q_OBJECT
28 : :
29 : : public:
30 : :
31 : :
32 : : private slots:
33 : : void initTestCase();// will be called before the first testfunction is executed.
34 : : void cleanupTestCase();// will be called after the last testfunction was executed.
35 : : void init() ;// will be called before each testfunction is executed.
36 : : void cleanup() ;// will be called after every testfunction.
37 : : //! Our tests proper begin here
38 : : void snapPolygonToPolygon();
39 : : void snapPolygonToLine();
40 : : void snapPolygonToPoint();
41 : : void snapLineToLine();
42 : : void snapLineToPolygon();
43 : : void snapLineToPoint();
44 : : void snapPointToPoint();
45 : : void snapPointToLine();
46 : : void snapPointToLinePreferNearest();
47 : : void snapPointToPolygon();
48 : : void endPointSnap();
49 : : void endPointToEndPoint();
50 : : void internalSnapper();
51 : : void insertExtra();
52 : : void duplicateNodes();
53 : : void snapMultiPolygonToPolygon();
54 : : };
55 : :
56 : 1 : void TestQgsGeometrySnapper::initTestCase()
57 : : {
58 : : //
59 : : // Runs once before any tests are run
60 : : //
61 : : // init QGIS's paths - true means that all path will be inited from prefix
62 : 1 : QgsApplication::init();
63 : 1 : QgsApplication::initQgis();
64 : 1 : }
65 : 1 : void TestQgsGeometrySnapper::cleanupTestCase()
66 : : {
67 : 1 : QgsApplication::exitQgis();
68 : 1 : }
69 : 16 : void TestQgsGeometrySnapper::init()
70 : : {
71 : :
72 : 16 : }
73 : 16 : void TestQgsGeometrySnapper::cleanup()
74 : : {
75 : :
76 : 16 : }
77 : :
78 : 1 : void TestQgsGeometrySnapper::snapPolygonToPolygon()
79 : : {
80 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
81 : 1 : QgsFeature ff( 0 );
82 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
83 : 1 : ff.setGeometry( refGeom );
84 : 1 : QgsFeatureList flist;
85 : 1 : flist << ff;
86 : 1 : rl->dataProvider()->addFeatures( flist );
87 : :
88 : 2 : QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1))" ) );
89 : 1 : QgsGeometrySnapper snapper( rl );
90 : 1 : QgsGeometry result = snapper.snapGeometry( polygonGeom, 1 );
91 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
92 : :
93 : 2 : QgsGeometry polygonGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1))" ) );
94 : 1 : result = snapper.snapGeometry( polygonGeom2, 1 );
95 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 0 10, 0 0))" ) );
96 : :
97 : : // insert new vertex
98 : 2 : QgsGeometry polygonGeom3 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1))" ) );
99 : 1 : result = snapper.snapGeometry( polygonGeom3, 1 );
100 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0))" ) );
101 : :
102 : : // remove vertex
103 : 2 : QgsGeometry polygonGeom4 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1))" ) );
104 : 1 : result = snapper.snapGeometry( polygonGeom4, 1 );
105 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
106 : 1 : }
107 : :
108 : 1 : void TestQgsGeometrySnapper::snapLineToLine()
109 : : {
110 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
111 : 1 : QgsFeature ff( 0 );
112 : :
113 : : // closed linestrings
114 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
115 : 1 : ff.setGeometry( refGeom );
116 : 1 : QgsFeatureList flist;
117 : 1 : flist << ff;
118 : 1 : rl->dataProvider()->addFeatures( flist );
119 : :
120 : 2 : QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1)" ) );
121 : 1 : QgsGeometrySnapper snapper( rl );
122 : 1 : QgsGeometry result = snapper.snapGeometry( lineGeom, 1 );
123 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
124 : :
125 : 2 : QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1)" ) );
126 : 1 : result = snapper.snapGeometry( lineGeom2, 1 );
127 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10, 0 0)" ) );
128 : :
129 : : // insert new vertex
130 : 2 : QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1)" ) );
131 : 1 : result = snapper.snapGeometry( lineGeom3, 1 );
132 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0)" ) );
133 : :
134 : : // remove vertex
135 : 2 : QgsGeometry lineGeom4 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1)" ) );
136 : 1 : result = snapper.snapGeometry( lineGeom4, 1 );
137 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
138 : :
139 : :
140 : : // unclosed linestrings
141 : 2 : QgsGeometry lineGeom5 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10)" ) );
142 : 1 : result = snapper.snapGeometry( lineGeom5, 1 );
143 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
144 : :
145 : 2 : QgsGeometry lineGeom6 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10)" ) );
146 : 1 : result = snapper.snapGeometry( lineGeom6, 1 );
147 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10)" ) );
148 : :
149 : : // insert new vertex
150 : 2 : QgsGeometry lineGeom7 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9)" ) );
151 : 1 : result = snapper.snapGeometry( lineGeom7, 1 );
152 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10)" ) );
153 : :
154 : : // remove vertex
155 : 2 : QgsGeometry lineGeom8 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10)" ) );
156 : 1 : result = snapper.snapGeometry( lineGeom8, 1 );
157 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
158 : 1 : }
159 : :
160 : 1 : void TestQgsGeometrySnapper::snapLineToPolygon()
161 : : {
162 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
163 : 1 : QgsFeature ff( 0 );
164 : :
165 : : // closed linestrings
166 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
167 : 1 : ff.setGeometry( refGeom );
168 : 1 : QgsFeatureList flist;
169 : 1 : flist << ff;
170 : 1 : rl->dataProvider()->addFeatures( flist );
171 : :
172 : 2 : QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1)" ) );
173 : 1 : QgsGeometrySnapper snapper( rl );
174 : 1 : QgsGeometry result = snapper.snapGeometry( lineGeom, 1 );
175 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
176 : :
177 : 2 : QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1)" ) );
178 : 1 : result = snapper.snapGeometry( lineGeom2, 1 );
179 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10, 0 0)" ) );
180 : :
181 : : // insert new vertex
182 : 2 : QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1)" ) );
183 : 1 : result = snapper.snapGeometry( lineGeom3, 1 );
184 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0)" ) );
185 : :
186 : : // remove vertex
187 : 2 : QgsGeometry lineGeom4 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1)" ) );
188 : 1 : result = snapper.snapGeometry( lineGeom4, 1 );
189 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10, 0 0)" ) );
190 : :
191 : :
192 : : // unclosed linestrings
193 : 2 : QgsGeometry lineGeom5 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 0 10)" ) );
194 : 1 : result = snapper.snapGeometry( lineGeom5, 1 );
195 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
196 : :
197 : 2 : QgsGeometry lineGeom6 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10)" ) );
198 : 1 : result = snapper.snapGeometry( lineGeom6, 1 );
199 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10)" ) );
200 : :
201 : : // insert new vertex
202 : 2 : QgsGeometry lineGeom7 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.5 0.5, 20 10, 0 9.9)" ) );
203 : 1 : result = snapper.snapGeometry( lineGeom7, 1 );
204 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10)" ) );
205 : :
206 : : // remove vertex
207 : 2 : QgsGeometry lineGeom8 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10)" ) );
208 : 1 : result = snapper.snapGeometry( lineGeom8, 1 );
209 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
210 : 1 : }
211 : :
212 : 1 : void TestQgsGeometrySnapper::snapLineToPoint()
213 : : {
214 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
215 : :
216 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) );
217 : 1 : QgsFeature ff( 0 );
218 : 1 : ff.setGeometry( refGeom );
219 : 2 : QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Point(10 0)" ) );
220 : 1 : QgsFeature ff2( 2 );
221 : 1 : ff2.setGeometry( refGeom2 );
222 : 1 : QgsFeatureList flist;
223 : 1 : flist << ff << ff2;
224 : 1 : rl->dataProvider()->addFeatures( flist );
225 : :
226 : 2 : QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 10 10, 0 10)" ) );
227 : 1 : QgsGeometrySnapper snapper( rl );
228 : 1 : QgsGeometry result = snapper.snapGeometry( lineGeom, 1 );
229 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 10 10, 0 10)" ) );
230 : :
231 : 2 : QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 10.1 0, 0 10)" ) );
232 : 1 : result = snapper.snapGeometry( lineGeom2, 1 );
233 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 0 10)" ) );
234 : :
235 : : // insert new vertex
236 : 2 : QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(0.1 -0.1, 20.0 0.0, 20 10, 0 10)" ) );
237 : 1 : result = snapper.snapGeometry( lineGeom3, 1 );
238 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 10 0, 20 0, 20 10, 0 10)" ) );
239 : 1 : }
240 : :
241 : 1 : void TestQgsGeometrySnapper::snapPolygonToLine()
242 : : {
243 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
244 : :
245 : : // closed linestring
246 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
247 : 1 : QgsFeature ff( 0 );
248 : 1 : ff.setGeometry( refGeom );
249 : : // unclosed linestring
250 : 2 : QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(100 0, 110 0, 110 10, 100 10)" ) );
251 : 1 : QgsFeature ff2( 2 );
252 : 1 : ff2.setGeometry( refGeom2 );
253 : 1 : QgsFeatureList flist;
254 : 1 : flist << ff << ff2;
255 : 1 : rl->dataProvider()->addFeatures( flist );
256 : :
257 : :
258 : : // snapping to closed linestring
259 : 2 : QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 0 10, 0.1 -0.1))" ) );
260 : 1 : QgsGeometrySnapper snapper( rl );
261 : 1 : QgsGeometry result = snapper.snapGeometry( polygonGeom, 1 );
262 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
263 : :
264 : 2 : QgsGeometry polygonGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1))" ) );
265 : 1 : result = snapper.snapGeometry( polygonGeom2, 1 );
266 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 0 10, 0 0))" ) );
267 : :
268 : : // insert new vertex
269 : 2 : QgsGeometry polygonGeom3 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 20.5 0.5, 20 10, 0 9.9, 0.1 -0.1))" ) );
270 : 1 : result = snapper.snapGeometry( polygonGeom3, 1 );
271 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 20.5 0.5, 20 10, 10 10, 0 10, 0 0))" ) );
272 : :
273 : : // remove vertex
274 : 2 : QgsGeometry polygonGeom4 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 9.9 10.1, 5 10, 0 10, 0.1 -0.1))" ) );
275 : 1 : result = snapper.snapGeometry( polygonGeom4, 1 );
276 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
277 : :
278 : :
279 : : // snapping to unclosed linestring
280 : 2 : QgsGeometry polygonGeom5 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 110.1 0, 109.9 10.1, 100 10, 100.1 -0.1))" ) );
281 : 1 : result = snapper.snapGeometry( polygonGeom5, 1 );
282 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 110 10, 100 10, 100 0))" ) );
283 : :
284 : 2 : QgsGeometry polygonGeom6 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 110.1 0, 100 10, 100.1 -0.1))" ) );
285 : 1 : result = snapper.snapGeometry( polygonGeom6, 1 );
286 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 100 10, 100 0))" ) );
287 : :
288 : : // insert new vertex
289 : 2 : QgsGeometry polygonGeom7 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 120.5 0.5, 120 10, 100 9.9, 100.1 -0.1))" ) );
290 : 1 : result = snapper.snapGeometry( polygonGeom7, 1 );
291 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 120.5 0.5, 120 10, 110 10, 100 10, 100 0))" ) );
292 : :
293 : : // remove vertex
294 : 2 : QgsGeometry polygonGeom8 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((100.1 -0.1, 110.1 0, 109.9 10.1, 105 10, 100 10, 100.1 -0.1))" ) );
295 : 1 : result = snapper.snapGeometry( polygonGeom8, 1 );
296 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((100 0, 110 0, 110 10, 100 10, 100 0))" ) );
297 : 1 : }
298 : :
299 : 1 : void TestQgsGeometrySnapper::snapPolygonToPoint()
300 : : {
301 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
302 : :
303 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) );
304 : 1 : QgsFeature ff( 0 );
305 : 1 : ff.setGeometry( refGeom );
306 : 2 : QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Point(10 0)" ) );
307 : 1 : QgsFeature ff2( 2 );
308 : 1 : ff2.setGeometry( refGeom2 );
309 : 1 : QgsFeatureList flist;
310 : 1 : flist << ff << ff2;
311 : 1 : rl->dataProvider()->addFeatures( flist );
312 : :
313 : 2 : QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 10 10, 0 10, 0.1 -0.1))" ) );
314 : 1 : QgsGeometrySnapper snapper( rl );
315 : 1 : QgsGeometry result = snapper.snapGeometry( polygonGeom, 1 );
316 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
317 : :
318 : 2 : QgsGeometry polygonGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 10.1 0, 0 10, 0.1 -0.1))" ) );
319 : 1 : result = snapper.snapGeometry( polygonGeom2, 1 );
320 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 0 10, 0 0))" ) );
321 : :
322 : : // insert new vertex
323 : 2 : QgsGeometry polygonGeom3 = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0.1 -0.1, 20.0 0.0, 20 10, 0 10, 0.1 -0.1))" ) );
324 : 1 : result = snapper.snapGeometry( polygonGeom3, 1 );
325 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Polygon ((0 0, 10 0, 20 0, 20 10, 0 10, 0 0))" ) );
326 : 1 : }
327 : :
328 : 1 : void TestQgsGeometrySnapper::snapPointToPoint()
329 : : {
330 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Point" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
331 : :
332 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) );
333 : 1 : QgsFeature ff( 0 );
334 : 1 : ff.setGeometry( refGeom );
335 : 2 : QgsGeometry refGeom2 = QgsGeometry::fromWkt( QStringLiteral( "Point(1 0)" ) );
336 : 1 : QgsFeature ff2( 2 );
337 : 1 : ff2.setGeometry( refGeom2 );
338 : 1 : QgsFeatureList flist;
339 : 1 : flist << ff << ff2;
340 : 1 : rl->dataProvider()->addFeatures( flist );
341 : :
342 : 2 : QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.1 -0.1)" ) );
343 : 1 : QgsGeometrySnapper snapper( rl );
344 : 1 : QgsGeometry result = snapper.snapGeometry( pointGeom, 1 );
345 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (0 0)" ) );
346 : :
347 : 2 : pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.6 -0.1)" ) );
348 : 1 : result = snapper.snapGeometry( pointGeom, 1 );
349 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (1 0)" ) );
350 : 1 : }
351 : :
352 : 1 : void TestQgsGeometrySnapper::snapPointToLine()
353 : : {
354 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
355 : :
356 : : // closed linestring
357 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
358 : 1 : QgsFeature ff( 0 );
359 : 1 : ff.setGeometry( refGeom );
360 : 1 : QgsFeatureList flist;
361 : 1 : flist << ff;
362 : 1 : rl->dataProvider()->addFeatures( flist );
363 : :
364 : 2 : QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.1 -0.1)" ) );
365 : 1 : QgsGeometrySnapper snapper( rl );
366 : 1 : QgsGeometry result = snapper.snapGeometry( pointGeom, 1 );
367 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (0 0)" ) );
368 : :
369 : 2 : pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(10.6 -0.1)" ) );
370 : 1 : result = snapper.snapGeometry( pointGeom, 1 );
371 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (10 0)" ) );
372 : :
373 : 2 : pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.5 0.5)" ) );
374 : 1 : result = snapper.snapGeometry( pointGeom, 1 );
375 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (0 0)" ) );
376 : 1 : }
377 : :
378 : 1 : void TestQgsGeometrySnapper::snapPointToLinePreferNearest()
379 : : {
380 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
381 : :
382 : : // closed linestring
383 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10, 0 10, 0 0)" ) );
384 : 1 : QgsFeature ff( 0 );
385 : 1 : ff.setGeometry( refGeom );
386 : 1 : QgsFeatureList flist;
387 : 1 : flist << ff;
388 : 1 : rl->dataProvider()->addFeatures( flist );
389 : :
390 : 2 : QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.5 0.5)" ) );
391 : 1 : QgsGeometrySnapper snapper( rl );
392 : 1 : QgsGeometry result = snapper.snapGeometry( pointGeom, 1, QgsGeometrySnapper::PreferClosest );
393 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (0.5 0)" ) );
394 : 1 : }
395 : :
396 : 1 : void TestQgsGeometrySnapper::snapPointToPolygon()
397 : : {
398 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
399 : :
400 : : // closed linestring
401 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
402 : 1 : QgsFeature ff( 0 );
403 : 1 : ff.setGeometry( refGeom );
404 : 1 : QgsFeatureList flist;
405 : 1 : flist << ff;
406 : 1 : rl->dataProvider()->addFeatures( flist );
407 : :
408 : 2 : QgsGeometry pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(0.1 -0.1)" ) );
409 : 1 : QgsGeometrySnapper snapper( rl );
410 : 1 : QgsGeometry result = snapper.snapGeometry( pointGeom, 1 );
411 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (0 0)" ) );
412 : :
413 : 2 : pointGeom = QgsGeometry::fromWkt( QStringLiteral( "Point(10.6 -0.1)" ) );
414 : 1 : result = snapper.snapGeometry( pointGeom, 1 );
415 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "Point (10 0)" ) );
416 : 1 : }
417 : :
418 : 1 : void TestQgsGeometrySnapper::endPointSnap()
419 : : {
420 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
421 : 1 : QgsFeature ff( 0 );
422 : :
423 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 100 0, 100 100, 0 100)" ) );
424 : 1 : ff.setGeometry( refGeom );
425 : 1 : QgsFeatureList flist;
426 : 1 : flist << ff;
427 : 1 : rl->dataProvider()->addFeatures( flist );
428 : :
429 : 2 : QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(1 -1, 102 0, 98 102, 0 101)" ) );
430 : 1 : QgsGeometrySnapper snapper( rl );
431 : 1 : QgsGeometry result = snapper.snapGeometry( lineGeom, 10, QgsGeometrySnapper::EndPointPreferNodes );
432 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 102 0, 98 102, 0 100)" ) );
433 : :
434 : 2 : QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(50 0, 102 0, 98 102, 0 50)" ) );
435 : 1 : result = snapper.snapGeometry( lineGeom2, 1, QgsGeometrySnapper::EndPointPreferNodes );
436 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (50 0, 102 0, 98 102, 0 50)" ) );
437 : :
438 : 2 : QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(50 -10, 50 -1)" ) );
439 : 1 : result = snapper.snapGeometry( lineGeom3, 2, QgsGeometrySnapper::EndPointPreferNodes );
440 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (50 -10, 50 0)" ) );
441 : 1 : }
442 : :
443 : 1 : void TestQgsGeometrySnapper::endPointToEndPoint()
444 : : {
445 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Linestring" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
446 : 1 : QgsFeature ff( 0 );
447 : :
448 : : // closed linestrings
449 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 100 0, 100 100, 0 100)" ) );
450 : 1 : ff.setGeometry( refGeom );
451 : 1 : QgsFeatureList flist;
452 : 1 : flist << ff;
453 : 1 : rl->dataProvider()->addFeatures( flist );
454 : :
455 : 2 : QgsGeometry lineGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(1 -1, 102 0, 98 102, 0 101)" ) );
456 : 1 : QgsGeometrySnapper snapper( rl );
457 : 1 : QgsGeometry result = snapper.snapGeometry( lineGeom, 10, QgsGeometrySnapper::EndPointToEndPoint );
458 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 102 0, 98 102, 0 100)" ) );
459 : :
460 : 2 : QgsGeometry lineGeom2 = QgsGeometry::fromWkt( QStringLiteral( "LineString(50 0, 102 0, 98 102)" ) );
461 : 1 : result = snapper.snapGeometry( lineGeom2, 1, QgsGeometrySnapper::EndPointToEndPoint );
462 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (50 0, 102 0, 98 102)" ) );
463 : :
464 : 2 : QgsGeometry lineGeom3 = QgsGeometry::fromWkt( QStringLiteral( "LineString(50 -10, 50 -1)" ) );
465 : 1 : result = snapper.snapGeometry( lineGeom3, 2, QgsGeometrySnapper::EndPointToEndPoint );
466 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (50 -10, 50 -1)" ) );
467 : 1 : }
468 : :
469 : 1 : void TestQgsGeometrySnapper::internalSnapper()
470 : : {
471 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 10 0, 10 10)" ) );
472 : 1 : QgsFeature f1( 1 );
473 : 1 : f1.setGeometry( refGeom );
474 : :
475 : 1 : QgsInternalGeometrySnapper snapper( 2 );
476 : 1 : QgsGeometry result = snapper.snapFeature( f1 );
477 : 1 : QCOMPARE( result.asWkt(), f1.geometry().asWkt() );
478 : :
479 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(5 5, 10 11, 15 15)" ) );
480 : 1 : QgsFeature f2( 2 );
481 : 1 : f2.setGeometry( refGeom );
482 : 1 : result = snapper.snapFeature( f2 );
483 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (5 5, 10 10, 15 15)" ) );
484 : :
485 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(20 20, 30 20)" ) );
486 : 1 : QgsFeature f3( 3 );
487 : 1 : f3.setGeometry( refGeom );
488 : 1 : result = snapper.snapFeature( f3 );
489 : 1 : QCOMPARE( result.asWkt(), f3.geometry().asWkt() );
490 : :
491 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 -1, 5.5 5, 9.8 10, 14.5 14.8)" ) );
492 : 1 : QgsFeature f4( 4 );
493 : 1 : f4.setGeometry( refGeom );
494 : 1 : result = snapper.snapFeature( f4 );
495 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineString (0 0, 5 5, 10 10, 15 15)" ) );
496 : :
497 : 1 : QgsGeometryMap res = snapper.snappedGeometries();
498 : 1 : QCOMPARE( res.count(), 4 );
499 : 1 : QCOMPARE( res.value( 1 ).asWkt(), f1.geometry().asWkt() );
500 : 2 : QCOMPARE( res.value( 2 ).asWkt(), QStringLiteral( "LineString (5 5, 10 10, 15 15)" ) );
501 : 1 : QCOMPARE( res.value( 3 ).asWkt(), f3.geometry().asWkt() );
502 : 2 : QCOMPARE( res.value( 4 ).asWkt(), QStringLiteral( "LineString (0 0, 5 5, 10 10, 15 15)" ) );
503 : 1 : }
504 : :
505 : 1 : void TestQgsGeometrySnapper::insertExtra()
506 : : {
507 : : // test extra node insertion behavior
508 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 0.1 0, 0.2 0, 9.8 0, 9.9 0, 10 0, 10.1 0, 10.2 0, 20 0)" ) );
509 : 1 : QgsFeature f1( 1 );
510 : 1 : f1.setGeometry( refGeom );
511 : :
512 : : // inserting extra nodes
513 : 1 : QgsInternalGeometrySnapper snapper( 2, QgsGeometrySnapper::PreferNodes );
514 : 1 : QgsGeometry result = snapper.snapFeature( f1 );
515 : 1 : QCOMPARE( result.asWkt(), f1.geometry().asWkt() );
516 : :
517 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(8 -5, 9 0, 10 5)" ) );
518 : 1 : QgsFeature f2( 2 );
519 : 1 : f2.setGeometry( refGeom );
520 : 1 : result = snapper.snapFeature( f2 );
521 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (8 -5, 9.8 0, 9.9 0, 10 0, 10.1 0, 10 5)" ) );
522 : :
523 : : // reset snapper
524 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::PreferNodes );
525 : 1 : result = snapper.snapFeature( f1 );
526 : :
527 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(7 -2, 10 0)" ) );
528 : 1 : f2.setGeometry( refGeom );
529 : 1 : result = snapper.snapFeature( f2 );
530 : : // should 'follow' line for a bit
531 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (7 -2, 9.8 0, 9.9 0, 10 0)" ) );
532 : :
533 : : // using PreferNodesNoExtraVertices mode, no extra vertices should be inserted
534 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::PreferNodesNoExtraVertices );
535 : 1 : result = snapper.snapFeature( f1 );
536 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(8 -5, 9 0.1, 10 5)" ) );
537 : 1 : f2.setGeometry( refGeom );
538 : 1 : result = snapper.snapFeature( f2 );
539 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (8 -5, 9.8 0, 10 5)" ) );
540 : :
541 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::PreferNodesNoExtraVertices );
542 : 1 : result = snapper.snapFeature( f1 );
543 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(7 -2, 10.1 0.1)" ) );
544 : 1 : f2.setGeometry( refGeom );
545 : 1 : result = snapper.snapFeature( f2 );
546 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (7 -2, 10.1 0)" ) );
547 : :
548 : : // using PreferClosestNoExtraVertices mode, no extra vertices should be inserted
549 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::PreferClosestNoExtraVertices );
550 : 1 : result = snapper.snapFeature( f1 );
551 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(8 -5, 9 0.1, 10 5)" ) );
552 : 1 : f2.setGeometry( refGeom );
553 : 1 : result = snapper.snapFeature( f2 );
554 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (8 -5, 9 0, 10 5)" ) );
555 : :
556 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::PreferClosestNoExtraVertices );
557 : 1 : result = snapper.snapFeature( f1 );
558 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(7 -2, 10.1 0.1)" ) );
559 : 1 : f2.setGeometry( refGeom );
560 : 1 : result = snapper.snapFeature( f2 );
561 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (7 -2, 10.1 0)" ) );
562 : :
563 : : // using EndPointPreferNodes mode, no extra vertices should be inserted
564 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::EndPointPreferNodes );
565 : 1 : result = snapper.snapFeature( f1 );
566 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(7 -2, 10.02 0)" ) );
567 : 1 : f2.setGeometry( refGeom );
568 : 1 : result = snapper.snapFeature( f2 );
569 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (7 -2, 10 0)" ) );
570 : :
571 : : // using EndPointPreferClosest mode, no extra vertices should be inserted
572 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::EndPointPreferClosest );
573 : 1 : result = snapper.snapFeature( f1 );
574 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(7 -2, 10.02 0)" ) );
575 : 1 : f2.setGeometry( refGeom );
576 : 1 : result = snapper.snapFeature( f2 );
577 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (7 -2, 10 0)" ) );
578 : :
579 : : // using EndPointToEndPoint mode, no extra vertices should be inserted
580 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::EndPointToEndPoint );
581 : 1 : result = snapper.snapFeature( f1 );
582 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(-7 -2, 0.12 0)" ) );
583 : 1 : f2.setGeometry( refGeom );
584 : 1 : result = snapper.snapFeature( f2 );
585 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (-7 -2, 0 0)" ) );
586 : :
587 : 1 : }
588 : :
589 : 1 : void TestQgsGeometrySnapper::duplicateNodes()
590 : : {
591 : : // test that snapper does not result in duplicate nodes
592 : :
593 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(0 0, 20 0)" ) );
594 : 1 : QgsFeature f1( 1 );
595 : 1 : f1.setGeometry( refGeom );
596 : :
597 : 1 : QgsInternalGeometrySnapper snapper( 2, QgsGeometrySnapper::PreferNodes );
598 : 1 : QgsGeometry result = snapper.snapFeature( f1 );
599 : 1 : QCOMPARE( result.asWkt(), f1.geometry().asWkt() );
600 : :
601 : 2 : refGeom = QgsGeometry::fromWkt( QStringLiteral( "LineString(10 10, 19 0, 19.5 1, 20 0.1)" ) );
602 : 1 : QgsFeature f2( 2 );
603 : 1 : f2.setGeometry( refGeom );
604 : 1 : result = snapper.snapFeature( f2 );
605 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (10 10, 20 0)" ) );
606 : :
607 : 1 : snapper = QgsInternalGeometrySnapper( 2, QgsGeometrySnapper::PreferNodesNoExtraVertices );
608 : 1 : result = snapper.snapFeature( f1 );
609 : 1 : QCOMPARE( result.asWkt(), f1.geometry().asWkt() );
610 : :
611 : 1 : result = snapper.snapFeature( f2 );
612 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "LineString (10 10, 20 0)" ) );
613 : :
614 : 1 : }
615 : :
616 : 1 : void TestQgsGeometrySnapper::snapMultiPolygonToPolygon()
617 : : {
618 : 4 : QgsVectorLayer *rl = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
619 : 1 : QgsFeature ff( 0 );
620 : 2 : QgsGeometry refGeom = QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 10 0, 10 10, 0 10, 0 0))" ) );
621 : 1 : ff.setGeometry( refGeom );
622 : 1 : QgsFeatureList flist;
623 : 1 : flist << ff;
624 : 1 : rl->dataProvider()->addFeatures( flist );
625 : :
626 : : // test MultiPolygon that could be removed in the process https://github.com/qgis/QGIS/issues/26385
627 : 2 : QgsGeometry polygonGeom = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon(((0.1 -0.1, 5 0.1, 9.9 0.1, 0.1 -0.1)))" ) );
628 : 1 : QgsGeometrySnapper snapper( rl );
629 : 1 : QgsGeometry result = snapper.snapGeometry( polygonGeom, 1 );
630 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 5 0, 10 0, 0 0)))" ) );
631 : :
632 : 1 : }
633 : :
634 : :
635 : 1 : QGSTEST_MAIN( TestQgsGeometrySnapper )
636 : : #include "testqgsgeometrysnapper.moc"
|