Branch data Line data Source code
1 : : /***************************************************************************
2 : : testqgsgeometry.cpp
3 : : --------------------------------------
4 : : Date : 20 Jan 2008
5 : : Copyright : (C) 2008 by Tim Sutton
6 : : Email : tim @ linfiniti.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 : : #include <cmath>
17 : : #include <memory>
18 : : #include <limits>
19 : : #include <QObject>
20 : : #include <QString>
21 : : #include <QStringList>
22 : : #include <QApplication>
23 : : #include <QFileInfo>
24 : : #include <QDir>
25 : : #include <QDesktopServices>
26 : : #include <QVector>
27 : : #include <QPointF>
28 : : #include <QImage>
29 : : #include <QPainter>
30 : :
31 : : //qgis includes...
32 : : #include <qgsapplication.h>
33 : : #include "qgscompoundcurve.h"
34 : : #include <qgsgeometry.h>
35 : : #include "qgsgeometryutils.h"
36 : : #include <qgspoint.h>
37 : : #include "qgspoint.h"
38 : : #include "qgslinestring.h"
39 : : #include "qgspolygon.h"
40 : : #include "qgstriangle.h"
41 : : #include "qgsgeometryengine.h"
42 : : #include "qgscircle.h"
43 : : #include "qgsellipse.h"
44 : : #include "qgsquadrilateral.h"
45 : : #include "qgsregularpolygon.h"
46 : : #include "qgsmultipoint.h"
47 : : #include "qgsmultilinestring.h"
48 : : #include "qgsmultipolygon.h"
49 : : #include "qgscircularstring.h"
50 : : #include "qgsgeometrycollection.h"
51 : : #include "qgsgeometryfactory.h"
52 : : #include "qgscurvepolygon.h"
53 : : #include "qgsproject.h"
54 : : #include "qgslinesegment.h"
55 : : #include "qgsgeos.h"
56 : : #include "qgsreferencedgeometry.h"
57 : : #include "qgsgeometrytransformer.h"
58 : :
59 : : //qgs unit test utility class
60 : : #include "qgsrenderchecker.h"
61 : :
62 : 12 : class TestTransformer : public QgsAbstractGeometryTransformer
63 : : {
64 : : public:
65 : :
66 : 50 : bool transformPoint( double &x, double &y, double &z, double &m ) override
67 : : {
68 : 50 : x *= 3;
69 : 50 : y += 14;
70 : 50 : z += 5;
71 : 50 : m -= 1;
72 : 50 : return true;
73 : : }
74 : : };
75 : :
76 : :
77 : 12 : class TestFailTransformer : public QgsAbstractGeometryTransformer
78 : : {
79 : : public:
80 : :
81 : 6 : bool transformPoint( double &x, double &y, double &z, double &m ) override
82 : : {
83 : 6 : x *= 3;
84 : 6 : y += 14;
85 : 6 : z += 5;
86 : 6 : m -= 1;
87 : 6 : return false;
88 : : }
89 : : };
90 : :
91 : :
92 : : /**
93 : : * \ingroup UnitTests
94 : : * This is a unit test for the different geometry operations on vector features.
95 : : */
96 : 1 : class TestQgsGeometry : public QObject
97 : : {
98 : : Q_OBJECT
99 : :
100 : : public:
101 : : TestQgsGeometry();
102 : :
103 : 12 : static QgsAbstractGeometry *createEmpty( QgsAbstractGeometry *geom )
104 : : {
105 : 12 : return geom->createEmptyWithSameType();
106 : : }
107 : :
108 : : private slots:
109 : : void initTestCase();// will be called before the first testfunction is executed.
110 : : void cleanupTestCase();// will be called after the last testfunction was executed.
111 : : void cleanup();// will be called after every testfunction.
112 : : void copy();
113 : : void assignment();
114 : : void asVariant(); //test conversion to and from a QVariant
115 : : void referenced();
116 : : void isEmpty();
117 : : void isValid();
118 : : void equality();
119 : : void vertexIterator();
120 : : void partIterator();
121 : :
122 : : void geos();
123 : :
124 : : // geometry types
125 : : void point(); //test QgsPointV2
126 : : void lineString(); //test QgsLineString
127 : : void circularString();
128 : : void polygon(); //test QgsPolygon
129 : : void curvePolygon();
130 : : void triangle();
131 : : void circle();
132 : : void ellipse();
133 : : void quadrilateral();
134 : : void regularPolygon();
135 : : void compoundCurve(); //test QgsCompoundCurve
136 : : void multiPoint();
137 : : void multiLineString();
138 : : void multiCurve();
139 : : void multiSurface();
140 : : void multiPolygon();
141 : : void geometryCollection();
142 : :
143 : : void fromQgsPointXY();
144 : : void fromQPoint();
145 : : void fromQPolygonF();
146 : : void fromPolyline();
147 : : void asQPointF();
148 : : void asQPolygonF();
149 : :
150 : : void comparePolylines();
151 : : void comparePolygons();
152 : :
153 : : void createEmptyWithSameType();
154 : :
155 : : // MK, Disabled 14.11.2014
156 : : // Too unclear what exactly should be tested and which variations are allowed for the line
157 : : #if 0
158 : : void simplifyCheck1();
159 : : #endif
160 : :
161 : : void intersectionCheck1();
162 : : void intersectionCheck2();
163 : : void translateCheck1();
164 : : void rotateCheck1();
165 : : void unionCheck1();
166 : : void unionCheck2();
167 : : void differenceCheck1();
168 : : void differenceCheck2();
169 : : void bufferCheck();
170 : : void smoothCheck();
171 : : void shortestLineEmptyGeometry();
172 : :
173 : : void unaryUnion();
174 : :
175 : : void dataStream();
176 : :
177 : : void exportToGeoJSON();
178 : :
179 : : void wkbInOut();
180 : :
181 : : void directionNeutralSegmentation();
182 : : void poleOfInaccessibility();
183 : :
184 : : void makeValid();
185 : :
186 : : void isSimple_data();
187 : : void isSimple();
188 : :
189 : : void reshapeGeometryLineMerge();
190 : : void createCollectionOfType();
191 : :
192 : : void orientedMinimumBoundingBox( );
193 : : void minimalEnclosingCircle( );
194 : : void splitGeometry();
195 : : void snappedToGrid();
196 : :
197 : : void convertGeometryCollectionToSubclass();
198 : :
199 : : void emptyJson();
200 : :
201 : : void testRandomPointsInPolygon();
202 : :
203 : : void wktParser();
204 : :
205 : : private:
206 : : //! Must be called before each render test
207 : : void initPainterTest();
208 : :
209 : : //! A helper method to do a render check to see if the geometry op is as expected
210 : : bool renderCheck( const QString &testName, const QString &comment = QString(), int mismatchCount = 0 );
211 : : //! A helper method to dump to qdebug the geometry of a multipolygon
212 : : void dumpMultiPolygon( QgsMultiPolygonXY &multiPolygon );
213 : : void paintMultiPolygon( QgsMultiPolygonXY &multiPolygon );
214 : : //! A helper method to dump to qdebug the geometry of a polygon
215 : : void dumpPolygon( QgsPolygonXY &polygon );
216 : : void paintPolygon( QgsPolygonXY &polygon );
217 : : //! A helper method to dump to qdebug the geometry of a polyline
218 : : void dumpPolyline( QgsPolylineXY &polyline );
219 : :
220 : : // Release return with delete []
221 : 2 : unsigned char *hex2bytes( const char *hex, int *size )
222 : : {
223 : 2 : QByteArray ba = QByteArray::fromHex( hex );
224 : 2 : unsigned char *out = new unsigned char[ba.size()];
225 : 2 : memcpy( out, ba.data(), ba.size() );
226 : 2 : *size = ba.size();
227 : 2 : return out;
228 : 2 : }
229 : :
230 : : QString bytes2hex( const unsigned char *bytes, int size )
231 : : {
232 : : QByteArray ba( ( const char * )bytes, size );
233 : : QString out = ba.toHex();
234 : : return out;
235 : : }
236 : :
237 : :
238 : : QString elemToString( const QDomElement &elem ) const;
239 : :
240 : : QgsPointXY mPoint1;
241 : : QgsPointXY mPoint2;
242 : : QgsPointXY mPoint3;
243 : : QgsPointXY mPoint4;
244 : : QgsPointXY mPointA;
245 : : QgsPointXY mPointB;
246 : : QgsPointXY mPointC;
247 : : QgsPointXY mPointD;
248 : : QgsPointXY mPointW;
249 : : QgsPointXY mPointX;
250 : : QgsPointXY mPointY;
251 : : QgsPointXY mPointZ;
252 : : QgsPolylineXY mPolylineA;
253 : : QgsPolylineXY mPolylineB;
254 : : QgsPolylineXY mPolylineC;
255 : : QgsGeometry mpPolylineGeometryD;
256 : : QgsPolygonXY mPolygonA;
257 : : QgsPolygonXY mPolygonB;
258 : : QgsPolygonXY mPolygonC;
259 : : QgsGeometry mpPolygonGeometryA;
260 : : QgsGeometry mpPolygonGeometryB;
261 : : QgsGeometry mpPolygonGeometryC;
262 : : QString mWktLine;
263 : : QString mTestDataDir;
264 : : QImage mImage;
265 : 1 : QPainter *mpPainter = nullptr;
266 : : QPen mPen1;
267 : : QPen mPen2;
268 : : QString mReport;
269 : :
270 : : };
271 : :
272 : 3 : TestQgsGeometry::TestQgsGeometry()
273 : 1 : : mpPolylineGeometryD( nullptr )
274 : 1 : , mpPolygonGeometryA( nullptr )
275 : 1 : , mpPolygonGeometryB( nullptr )
276 : 1 : , mpPolygonGeometryC( nullptr )
277 : 2 : {
278 : :
279 : 1 : }
280 : :
281 : 1 : void TestQgsGeometry::initTestCase()
282 : : {
283 : : // Runs once before any tests are run
284 : : // init QGIS's paths - true means that all path will be inited from prefix
285 : 1 : QgsApplication::init();
286 : 1 : QgsApplication::initQgis();
287 : 1 : QgsApplication::showSettings();
288 : 1 : mReport += QLatin1String( "<h1>Geometry Tests</h1>\n" );
289 : 1 : mReport += QLatin1String( "<p><font color=\"green\">Green = polygonA</font></p>\n" );
290 : 1 : mReport += QLatin1String( "<p><font color=\"red\">Red = polygonB</font></p>\n" );
291 : 1 : mReport += QLatin1String( "<p><font color=\"blue\">Blue = polygonC</font></p>\n" );
292 : 1 : }
293 : :
294 : :
295 : 1 : void TestQgsGeometry::cleanupTestCase()
296 : : {
297 : 1 : delete mpPainter;
298 : 1 : mpPainter = nullptr;
299 : :
300 : : // Runs once after all tests are run
301 : 1 : QString myReportFile = QDir::tempPath() + "/qgistest.html";
302 : 1 : QFile myFile( myReportFile );
303 : 1 : if ( myFile.open( QIODevice::WriteOnly | QIODevice::Append ) )
304 : : {
305 : 1 : QTextStream myQTextStream( &myFile );
306 : 1 : myQTextStream << mReport;
307 : 1 : myFile.close();
308 : : //QDesktopServices::openUrl( "file:///" + myReportFile );
309 : 1 : }
310 : :
311 : 1 : QgsApplication::exitQgis();
312 : 1 : }
313 : :
314 : 6 : void TestQgsGeometry::initPainterTest()
315 : : {
316 : 6 : delete mpPainter;
317 : 6 : mpPainter = nullptr;
318 : : //
319 : : // Reset / reinitialize the geometries before each test is run
320 : : //
321 : 6 : mPoint1 = QgsPointXY( 20.0, 20.0 );
322 : 6 : mPoint2 = QgsPointXY( 80.0, 20.0 );
323 : 6 : mPoint3 = QgsPointXY( 80.0, 80.0 );
324 : 6 : mPoint4 = QgsPointXY( 20.0, 80.0 );
325 : 6 : mPointA = QgsPointXY( 40.0, 40.0 );
326 : 6 : mPointB = QgsPointXY( 100.0, 40.0 );
327 : 6 : mPointC = QgsPointXY( 100.0, 100.0 );
328 : 6 : mPointD = QgsPointXY( 40.0, 100.0 );
329 : 6 : mPointW = QgsPointXY( 200.0, 200.0 );
330 : 6 : mPointX = QgsPointXY( 240.0, 200.0 );
331 : 6 : mPointY = QgsPointXY( 240.0, 240.0 );
332 : 6 : mPointZ = QgsPointXY( 200.0, 240.0 );
333 : :
334 : 12 : mWktLine = QStringLiteral( "LINESTRING(117.623198 35.198654, 117.581274 35.198654, 117.078178 35.324427, 116.868555 35.534051, 116.617007 35.869448, 116.491233 35.953297, 116.155836 36.288694, 116.071987 36.372544, 115.443117 36.749865, 114.814247 37.043338, 114.311152 37.169112, 113.388810 37.378735, 113.095337 37.378735, 112.592241 37.378735, 111.753748 37.294886, 111.502201 37.252961, 111.082954 37.127187, 110.747557 37.127187, 110.160612 36.917564, 110.034838 36.833715, 109.741366 36.749865, 109.573667 36.666016, 109.238270 36.498317, 109.070571 36.414468, 108.819023 36.288694, 108.693250 36.246770, 108.483626 36.162920, 107.645134 35.911372, 106.597017 35.869448, 106.051997 35.701749, 105.800449 35.617900, 105.590826 35.575975, 105.297354 35.575975, 104.961956 35.575975, 104.710409 35.534051, 104.458861 35.492126, 103.871916 35.492126, 103.788066 35.492126, 103.326895 35.408277, 102.949574 35.408277, 102.488402 35.450201, 102.069156 35.450201, 101.482211 35.450201, 100.937191 35.659825, 100.308321 35.869448, 100.056773 36.037146, 99.050582 36.079071, 97.667069 35.743674, 97.163973 35.617900, 96.115857 35.534051, 95.612761 35.534051, 94.396947 35.911372, 93.684228 36.288694, 92.929584 36.833715, 92.258790 37.169112, 91.629920 37.504509, 90.414105 37.881831, 90.414105 37.881831, 90.246407 37.923755, 89.491763 37.839906, 89.156366 37.672207, 88.485572 37.504509, 87.814778 37.252961, 87.563230 37.169112, 87.143983 37.043338, 85.970093 36.875639, 85.802395 36.875639, 84.083484 36.959489, 84.041560 37.043338, 82.951519 37.546433, 82.699971 37.630283)" );
335 : :
336 : 6 : mPolygonA.clear();
337 : 6 : mPolygonB.clear();
338 : 6 : mPolygonC.clear();
339 : 6 : mPolylineA.clear();
340 : 6 : mPolylineB.clear();
341 : 6 : mPolylineC.clear();
342 : 6 : mPolylineA << mPoint1 << mPoint2 << mPoint3 << mPoint4 << mPoint1;
343 : 6 : mPolygonA << mPolylineA;
344 : : //Polygon B intersects Polygon A
345 : 6 : mPolylineB << mPointA << mPointB << mPointC << mPointD << mPointA;
346 : 6 : mPolygonB << mPolylineB;
347 : : // Polygon C should intersect no other polys
348 : 6 : mPolylineC << mPointW << mPointX << mPointY << mPointZ << mPointW;
349 : 6 : mPolygonC << mPolylineC;
350 : :
351 : 6 : mpPolylineGeometryD = QgsGeometry::fromWkt( mWktLine );
352 : :
353 : : //polygon: first item of the list is outer ring,
354 : : // inner rings (if any) start from second item
355 : 6 : mpPolygonGeometryA = QgsGeometry::fromPolygonXY( mPolygonA );
356 : 6 : mpPolygonGeometryB = QgsGeometry::fromPolygonXY( mPolygonB );
357 : 6 : mpPolygonGeometryC = QgsGeometry::fromPolygonXY( mPolygonC );
358 : :
359 : 6 : mImage = QImage( 250, 250, QImage::Format_RGB32 );
360 : 6 : mImage.fill( qRgb( 152, 219, 249 ) );
361 : 6 : mpPainter = new QPainter( &mImage );
362 : :
363 : : // Draw the test shapes first
364 : 6 : mPen1 = QPen();
365 : 6 : mPen1.setWidth( 5 );
366 : 6 : mPen1.setBrush( Qt::green );
367 : 6 : mpPainter->setPen( mPen1 );
368 : 6 : paintPolygon( mPolygonA );
369 : 6 : mPen1.setBrush( Qt::red );
370 : 6 : mpPainter->setPen( mPen1 );
371 : 6 : paintPolygon( mPolygonB );
372 : 6 : mPen1.setBrush( Qt::blue );
373 : 6 : mpPainter->setPen( mPen1 );
374 : 6 : paintPolygon( mPolygonC );
375 : :
376 : 6 : mPen2 = QPen();
377 : 6 : mPen2.setWidth( 1 );
378 : 6 : mPen2.setBrush( Qt::black );
379 : 6 : QBrush myBrush( Qt::DiagCrossPattern );
380 : :
381 : :
382 : : //set the pen to a different color -
383 : : //any test outs will be drawn in pen2
384 : 6 : mpPainter->setPen( mPen2 );
385 : 6 : mpPainter->setBrush( myBrush );
386 : 6 : }
387 : :
388 : 74 : void TestQgsGeometry::cleanup()
389 : : {
390 : : // will be called after every testfunction.
391 : 74 : }
392 : :
393 : 1 : void TestQgsGeometry::copy()
394 : : {
395 : : //create a point geometry
396 : 1 : QgsGeometry original( new QgsPoint( 1.0, 2.0 ) );
397 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
398 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
399 : :
400 : : //implicitly shared copy
401 : 1 : QgsGeometry copy( original );
402 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
403 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
404 : :
405 : : //trigger a detach
406 : 1 : copy.set( new QgsPoint( 3.0, 4.0 ) );
407 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 3.0 );
408 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 4.0 );
409 : :
410 : : //make sure original was untouched
411 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
412 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
413 : 1 : }
414 : :
415 : 1 : void TestQgsGeometry::assignment()
416 : : {
417 : : //create a point geometry
418 : 1 : QgsGeometry original( new QgsPoint( 1.0, 2.0 ) );
419 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
420 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
421 : :
422 : : //assign to implicitly shared copy
423 : 1 : QgsGeometry copy;
424 : 1 : copy = original;
425 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
426 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
427 : :
428 : : //trigger a detach
429 : 1 : copy.set( new QgsPoint( 3.0, 4.0 ) );
430 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 3.0 );
431 : 1 : QCOMPARE( copy.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 4.0 );
432 : :
433 : : //make sure original was untouched
434 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
435 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
436 : 1 : }
437 : :
438 : 1 : void TestQgsGeometry::asVariant()
439 : : {
440 : : //create a point geometry
441 : 1 : QgsGeometry original( new QgsPoint( 1.0, 2.0 ) );
442 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
443 : 1 : QCOMPARE( original.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
444 : :
445 : : //convert to and from a QVariant
446 : 1 : QVariant var = QVariant::fromValue( original );
447 : 1 : QVERIFY( var.isValid() );
448 : 1 : QVERIFY( !var.canConvert< QgsReferencedGeometry >() );
449 : :
450 : 1 : QgsGeometry fromVar = qvariant_cast<QgsGeometry>( var );
451 : 1 : QCOMPARE( fromVar.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
452 : 1 : QCOMPARE( fromVar.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
453 : :
454 : : //also check copying variant
455 : 1 : QVariant var2 = var;
456 : 1 : QVERIFY( var2.isValid() );
457 : 1 : QgsGeometry fromVar2 = qvariant_cast<QgsGeometry>( var2 );
458 : 1 : QCOMPARE( fromVar2.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
459 : 1 : QCOMPARE( fromVar2.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
460 : :
461 : : //modify original and check detachment
462 : 1 : original.set( new QgsPoint( 3.0, 4.0 ) );
463 : 1 : QgsGeometry fromVar3 = qvariant_cast<QgsGeometry>( var );
464 : 1 : QCOMPARE( fromVar3.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).x(), 1.0 );
465 : 1 : QCOMPARE( fromVar3.constGet()->vertexAt( QgsVertexId( 0, 0, 0 ) ).y(), 2.0 );
466 : 1 : }
467 : :
468 : :
469 : 1 : void TestQgsGeometry::referenced()
470 : : {
471 : 2 : QgsReferencedGeometry geom1 = QgsReferencedGeometry( QgsGeometry::fromPointXY( QgsPointXY( 1, 2 ) ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) );
472 : 2 : QCOMPARE( geom1.crs().authid(), QStringLiteral( "EPSG:3111" ) );
473 : 2 : geom1.setCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:28356" ) ) );
474 : 2 : QCOMPARE( geom1.crs().authid(), QStringLiteral( "EPSG:28356" ) );
475 : :
476 : : //convert to and from a QVariant
477 : 1 : QVariant var = QVariant::fromValue( geom1 );
478 : 1 : QVERIFY( var.isValid() );
479 : :
480 : 1 : QVERIFY( var.canConvert< QgsReferencedGeometry >() );
481 : :
482 : 1 : QgsReferencedGeometry geom2 = qvariant_cast<QgsReferencedGeometry>( var );
483 : 1 : QCOMPARE( geom2.asWkt(), geom1.asWkt() );
484 : 2 : QCOMPARE( geom2.crs().authid(), QStringLiteral( "EPSG:28356" ) );
485 : 1 : }
486 : :
487 : :
488 : 1 : void TestQgsGeometry::isEmpty()
489 : : {
490 : 1 : QgsGeometry geom;
491 : 1 : QVERIFY( geom.isNull() );
492 : :
493 : 1 : geom.set( new QgsPoint() );
494 : 1 : QVERIFY( geom.isEmpty() );
495 : :
496 : 1 : geom.set( new QgsPoint( 1.0, 2.0 ) );
497 : 1 : QVERIFY( !geom.isNull() );
498 : :
499 : 1 : geom.set( nullptr );
500 : 1 : QVERIFY( geom.isNull() );
501 : :
502 : 1 : QgsGeometryCollection collection;
503 : 1 : QVERIFY( collection.isEmpty() );
504 : 1 : }
505 : :
506 : 1 : void TestQgsGeometry::isValid()
507 : : {
508 : 1 : QString error;
509 : : // LineString
510 : 1 : QgsLineString line;
511 : 1 : QVERIFY( line.isValid( error ) );
512 : 1 : line.addVertex( QgsPoint( 0, 0 ) );
513 : 1 : QVERIFY( !line.isValid( error ) );
514 : 2 : QCOMPARE( error, QStringLiteral( "LineString has less than 2 points and is not empty." ) );
515 : 1 : line.addVertex( QgsPoint( 1, 1 ) );
516 : 1 : QVERIFY( line.isValid( error ) );
517 : :
518 : : // CircularString
519 : 1 : QgsCircularString circ;
520 : 1 : QVERIFY( circ.isValid( error ) );
521 : 1 : QgsPointSequence pts = QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2.5, 2.3 );
522 : 1 : circ.setPoints( pts );
523 : 1 : QVERIFY( !circ.isValid( error ) );
524 : 2 : QCOMPARE( error, QStringLiteral( "CircularString has less than 3 points and is not empty." ) );
525 : 1 : pts.append( QgsPoint( 5, 5 ) );
526 : 1 : circ.setPoints( pts );
527 : 1 : QVERIFY( circ.isValid( error ) );
528 : :
529 : : // CompoundCurve
530 : 1 : QgsCompoundCurve curve;
531 : 1 : QVERIFY( curve.isValid( error ) );
532 : 1 : curve.addCurve( line.clone() );
533 : 1 : QVERIFY( curve.isValid( error ) );
534 : 1 : curve.addCurve( circ.clone() );
535 : 1 : QVERIFY( curve.isValid( error ) );
536 : 1 : QgsLineString invalidLine;
537 : 1 : invalidLine.addVertex( QgsPoint( 0, 0 ) );
538 : 1 : curve.addCurve( invalidLine.clone() );
539 : 1 : QVERIFY( !curve.isValid( error ) );
540 : 2 : QCOMPARE( error, QStringLiteral( "Curve[3]: LineString has less than 2 points and is not empty." ) );
541 : 1 : }
542 : :
543 : 1 : void TestQgsGeometry::equality()
544 : : {
545 : : // null geometries
546 : 1 : QVERIFY( !QgsGeometry().equals( QgsGeometry() ) );
547 : :
548 : : // compare to null
549 : 1 : QgsGeometry g1( std::make_unique< QgsPoint >( 1.0, 2.0 ) );
550 : 1 : QVERIFY( !g1.equals( QgsGeometry() ) );
551 : 1 : QVERIFY( !QgsGeometry().equals( g1 ) );
552 : :
553 : : // compare implicitly shared copies
554 : 1 : QgsGeometry g2( g1 );
555 : 1 : QVERIFY( g2.equals( g1 ) );
556 : 1 : QVERIFY( g1.equals( g2 ) );
557 : 1 : QVERIFY( g1.equals( g1 ) );
558 : :
559 : : // equal geometry, but different internal data
560 : 1 : g2 = QgsGeometry::fromWkt( "Point( 1.0 2.0 )" );
561 : 1 : QVERIFY( g2.equals( g1 ) );
562 : 1 : QVERIFY( g1.equals( g2 ) );
563 : :
564 : : // different dimensionality
565 : 1 : g2 = QgsGeometry::fromWkt( "PointM( 1.0 2.0 3.0)" );
566 : 1 : QVERIFY( !g2.equals( g1 ) );
567 : 1 : QVERIFY( !g1.equals( g2 ) );
568 : :
569 : : // different type
570 : 1 : g2 = QgsGeometry::fromWkt( "LineString( 1.0 2.0, 3.0 4.0 )" );
571 : 1 : QVERIFY( !g2.equals( g1 ) );
572 : 1 : QVERIFY( !g1.equals( g2 ) );
573 : :
574 : : // different direction
575 : 1 : g1 = QgsGeometry::fromWkt( "LineString( 3.0 4.0, 1.0 2.0 )" );
576 : 1 : QVERIFY( !g2.equals( g1 ) );
577 : 1 : QVERIFY( !g1.equals( g2 ) );
578 : 1 : }
579 : :
580 : 1 : void TestQgsGeometry::vertexIterator()
581 : : {
582 : 1 : QgsGeometry geom;
583 : 1 : QgsVertexIterator it = geom.vertices();
584 : 1 : QVERIFY( !it.hasNext() );
585 : :
586 : 1 : QgsPolylineXY polyline;
587 : 1 : polyline << QgsPoint( 1, 2 ) << QgsPoint( 3, 4 );
588 : 1 : QgsGeometry geom2 = QgsGeometry::fromPolylineXY( polyline );
589 : 1 : QgsVertexIterator it2 = geom2.vertices();
590 : 1 : QVERIFY( it2.hasNext() );
591 : 1 : QCOMPARE( it2.next(), QgsPoint( 1, 2 ) );
592 : 1 : QVERIFY( it2.hasNext() );
593 : 1 : QCOMPARE( it2.next(), QgsPoint( 3, 4 ) );
594 : 1 : QVERIFY( !it2.hasNext() );
595 : :
596 : 1 : QgsGeometry emptyGeom = QgsGeometry::fromWkt( "LINESTRING EMPTY" );
597 : 1 : QgsVertexIterator it3 = emptyGeom.vertices();
598 : 1 : QVERIFY( !it3.hasNext() );
599 : 1 : emptyGeom = QgsGeometry::fromWkt( "POINT EMPTY" );
600 : 1 : QgsVertexIterator it4 = emptyGeom.vertices();
601 : 1 : QVERIFY( !it4.hasNext() );
602 : 1 : }
603 : :
604 : 1 : void TestQgsGeometry::partIterator()
605 : : {
606 : 1 : QgsGeometry geom;
607 : 1 : QgsGeometryPartIterator it = geom.parts();
608 : 1 : QVERIFY( !it.hasNext() );
609 : :
610 : 2 : geom = QgsGeometry::fromWkt( QStringLiteral( "Point( 1 2 )" ) );
611 : 1 : QgsGeometryConstPartIterator it2 = geom.constParts();
612 : 1 : QVERIFY( it2.hasNext() );
613 : 2 : QCOMPARE( it2.next()->asWkt(), QStringLiteral( "Point (1 2)" ) );
614 : 1 : QVERIFY( !it2.hasNext() );
615 : :
616 : : // test that non-const iterator detaches
617 : 1 : QgsGeometry geom2 = geom;
618 : 1 : it = geom2.parts();
619 : 1 : QVERIFY( it.hasNext() );
620 : 1 : QgsAbstractGeometry *part = it.next();
621 : 2 : QCOMPARE( part->asWkt(), QStringLiteral( "Point (1 2)" ) );
622 : 1 : static_cast< QgsPoint * >( part )->setX( 100 );
623 : 2 : QCOMPARE( geom2.asWkt(), QStringLiteral( "Point (100 2)" ) );
624 : 1 : QVERIFY( !it.hasNext() );
625 : : // geom2 should have adetached, geom should be unaffected by change
626 : 2 : QCOMPARE( geom.asWkt(), QStringLiteral( "Point (1 2)" ) );
627 : :
628 : : // See test_qgsgeometry.py for geometry-type specific checks!
629 : 1 : }
630 : :
631 : 1 : void TestQgsGeometry::geos()
632 : : {
633 : : // test GEOS conversion utils
634 : :
635 : : // empty parts should NOT be added to a GEOS collection -- it can cause crashes in GEOS
636 : 1 : QgsMultiPolygon polyWithEmptyParts;
637 : 1 : geos::unique_ptr asGeos( QgsGeos::asGeos( &polyWithEmptyParts ) );
638 : 1 : QgsGeometry res( QgsGeos::fromGeos( asGeos.get() ) );
639 : 2 : QCOMPARE( res.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) );
640 : 1 : polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString() ) );
641 : 1 : polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString( QVector< QgsPoint >() << QgsPoint( 0, 0 ) << QgsPoint( 0, 1 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) ) ) );
642 : 1 : polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString() ) );
643 : 1 : polyWithEmptyParts.addGeometry( new QgsPolygon( new QgsLineString( QVector< QgsPoint >() << QgsPoint( 10, 0 ) << QgsPoint( 10, 1 ) << QgsPoint( 11, 1 ) << QgsPoint( 10, 0 ) ) ) );
644 : 1 : asGeos = QgsGeos::asGeos( &polyWithEmptyParts );
645 : 1 : QCOMPARE( GEOSGetNumGeometries_r( QgsGeos::getGEOSHandler(), asGeos.get() ), 2 );
646 : 1 : res = QgsGeometry( QgsGeos::fromGeos( asGeos.get() ) );
647 : 2 : QCOMPARE( res.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((10 0, 10 1, 11 1, 10 0)))" ) );
648 : :
649 : : // Empty geometry
650 : 1 : QgsPoint point;
651 : 1 : asGeos = QgsGeos::asGeos( &point );
652 : : // should be treated as a null geometry, not an empty point in order to maintain api compatibility with
653 : : // earlier QGIS 3.x releases
654 : 1 : QVERIFY( !QgsGeos::fromGeos( asGeos.get() ) );
655 : 1 : }
656 : :
657 : 1 : void TestQgsGeometry::point()
658 : : {
659 : : //test QgsPointV2
660 : 1 : QgsPoint pEmpty;
661 : 1 : QVERIFY( pEmpty.isEmpty() );
662 : 1 : QCOMPARE( pEmpty.wkbType(), QgsWkbTypes::Point );
663 : 2 : QCOMPARE( pEmpty.asWkt(), QStringLiteral( "Point EMPTY" ) );
664 : 1 : pEmpty.setX( 1.0 );
665 : 1 : QVERIFY( pEmpty.isEmpty() );
666 : 1 : QCOMPARE( pEmpty.wkbType(), QgsWkbTypes::Point );
667 : 2 : QCOMPARE( pEmpty.asWkt(), QStringLiteral( "Point EMPTY" ) );
668 : 1 : pEmpty.setY( 2.0 );
669 : 1 : QVERIFY( !pEmpty.isEmpty() );
670 : 1 : QCOMPARE( pEmpty.wkbType(), QgsWkbTypes::Point );
671 : 2 : QCOMPARE( pEmpty.asWkt(), QStringLiteral( "Point (1 2)" ) );
672 : :
673 : : //test constructors
674 : 1 : QgsPoint p1( 5.0, 6.0 );
675 : 1 : QCOMPARE( p1.x(), 5.0 );
676 : 1 : QCOMPARE( p1.y(), 6.0 );
677 : 1 : QVERIFY( !p1.isEmpty() );
678 : 1 : QVERIFY( !p1.is3D() );
679 : 1 : QVERIFY( !p1.isMeasure() );
680 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::Point );
681 : 1 : QCOMPARE( p1.wktTypeStr(), QString( "Point" ) );
682 : :
683 : 1 : QgsPoint p2( QgsPointXY( 3.0, 4.0 ) );
684 : 1 : QCOMPARE( p2.x(), 3.0 );
685 : 1 : QCOMPARE( p2.y(), 4.0 );
686 : 1 : QVERIFY( !p2.isEmpty() );
687 : 1 : QVERIFY( !p2.is3D() );
688 : 1 : QVERIFY( !p2.isMeasure() );
689 : 1 : QCOMPARE( p2.wkbType(), QgsWkbTypes::Point );
690 : :
691 : 1 : QgsPoint p3( QPointF( 7.0, 9.0 ) );
692 : 1 : QCOMPARE( p3.x(), 7.0 );
693 : 1 : QCOMPARE( p3.y(), 9.0 );
694 : 1 : QVERIFY( !p3.isEmpty() );
695 : 1 : QVERIFY( !p3.is3D() );
696 : 1 : QVERIFY( !p3.isMeasure() );
697 : 1 : QCOMPARE( p3.wkbType(), QgsWkbTypes::Point );
698 : :
699 : 1 : QgsPoint p4( QgsWkbTypes::Point, 11.0, 13.0 );
700 : 1 : QCOMPARE( p4.x(), 11.0 );
701 : 1 : QCOMPARE( p4.y(), 13.0 );
702 : 1 : QVERIFY( !p4.isEmpty() );
703 : 1 : QVERIFY( !p4.is3D() );
704 : 1 : QVERIFY( !p4.isMeasure() );
705 : 1 : QCOMPARE( p4.wkbType(), QgsWkbTypes::Point );
706 : :
707 : 1 : QgsPoint p5( QgsWkbTypes::PointZ, 11.0, 13.0, 15.0 );
708 : 1 : QCOMPARE( p5.x(), 11.0 );
709 : 1 : QCOMPARE( p5.y(), 13.0 );
710 : 1 : QCOMPARE( p5.z(), 15.0 );
711 : 1 : QVERIFY( !p5.isEmpty() );
712 : 1 : QVERIFY( p5.is3D() );
713 : 1 : QVERIFY( !p5.isMeasure() );
714 : 1 : QCOMPARE( p5.wkbType(), QgsWkbTypes::PointZ );
715 : 1 : QCOMPARE( p5.wktTypeStr(), QString( "PointZ" ) );
716 : :
717 : 1 : QgsPoint p6( QgsWkbTypes::PointM, 11.0, 13.0, 0.0, 17.0 );
718 : 1 : QCOMPARE( p6.x(), 11.0 );
719 : 1 : QCOMPARE( p6.y(), 13.0 );
720 : 1 : QCOMPARE( p6.m(), 17.0 );
721 : 1 : QVERIFY( !p6.isEmpty() );
722 : 1 : QVERIFY( !p6.is3D() );
723 : 1 : QVERIFY( p6.isMeasure() );
724 : 1 : QCOMPARE( p6.wkbType(), QgsWkbTypes::PointM );
725 : 1 : QCOMPARE( p6.wktTypeStr(), QString( "PointM" ) );
726 : :
727 : 1 : QgsPoint p7( QgsWkbTypes::PointZM, 11.0, 13.0, 0.0, 17.0 );
728 : 1 : QCOMPARE( p7.x(), 11.0 );
729 : 1 : QCOMPARE( p7.y(), 13.0 );
730 : 1 : QCOMPARE( p7.m(), 17.0 );
731 : 1 : QVERIFY( !p7.isEmpty() );
732 : 1 : QVERIFY( p7.is3D() );
733 : 1 : QVERIFY( p7.isMeasure() );
734 : 1 : QCOMPARE( p7.wkbType(), QgsWkbTypes::PointZM );
735 : 1 : QCOMPARE( p7.wktTypeStr(), QString( "PointZM" ) );
736 : :
737 : 1 : QgsPoint noZ( QgsWkbTypes::PointM, 11.0, 13.0, 15.0, 17.0 );
738 : 1 : QCOMPARE( noZ.x(), 11.0 );
739 : 1 : QCOMPARE( noZ.y(), 13.0 );
740 : 1 : QVERIFY( std::isnan( noZ.z() ) );
741 : 1 : QCOMPARE( noZ.m(), 17.0 );
742 : 1 : QCOMPARE( noZ.wkbType(), QgsWkbTypes::PointM );
743 : :
744 : 1 : QgsPoint noM( QgsWkbTypes::PointZ, 11.0, 13.0, 17.0, 18.0 );
745 : 1 : QCOMPARE( noM.x(), 11.0 );
746 : 1 : QCOMPARE( noM.y(), 13.0 );
747 : 1 : QVERIFY( std::isnan( noM.m() ) );
748 : 1 : QCOMPARE( noM.z(), 17.0 );
749 : 1 : QCOMPARE( noM.wkbType(), QgsWkbTypes::PointZ );
750 : :
751 : 1 : QgsPoint p8( QgsWkbTypes::Point25D, 21.0, 23.0, 25.0 );
752 : 1 : QCOMPARE( p8.x(), 21.0 );
753 : 1 : QCOMPARE( p8.y(), 23.0 );
754 : 1 : QCOMPARE( p8.z(), 25.0 );
755 : 1 : QVERIFY( !p8.isEmpty() );
756 : 1 : QVERIFY( p8.is3D() );
757 : 1 : QVERIFY( !p8.isMeasure() );
758 : 1 : QCOMPARE( p8.wkbType(), QgsWkbTypes::Point25D );
759 : :
760 : 1 : QgsPoint pp( QgsWkbTypes::Point );
761 : 1 : QVERIFY( !pp.is3D() );
762 : 1 : QVERIFY( !pp.isMeasure() );
763 : :
764 : 1 : QgsPoint ppz( QgsWkbTypes::PointZ );
765 : 1 : QVERIFY( ppz.is3D() );
766 : 1 : QVERIFY( !ppz.isMeasure() );
767 : :
768 : 1 : QgsPoint ppm( QgsWkbTypes::PointM );
769 : 1 : QVERIFY( !ppm.is3D() );
770 : 1 : QVERIFY( ppm.isMeasure() );
771 : :
772 : 1 : QgsPoint ppzm( QgsWkbTypes::PointZM );
773 : 1 : QVERIFY( ppzm.is3D() );
774 : 1 : QVERIFY( ppzm.isMeasure() );
775 : :
776 : : #if 0 //should trigger an assert
777 : : //try creating a point with a nonsense WKB type
778 : : QgsPoint p9( QgsWkbTypes::PolygonZM, 11.0, 13.0, 9.0, 17.0 );
779 : : QCOMPARE( p9.wkbType(), QgsWkbTypes::Unknown );
780 : : #endif
781 : :
782 : : //test equality operator
783 : :
784 : 1 : QgsPoint pRight, pLeft;
785 : 1 : QVERIFY( pRight.isEmpty() );
786 : 1 : QVERIFY( pLeft.isEmpty() );
787 : 1 : QVERIFY( pLeft == pRight );
788 : 1 : pRight.setX( 1 );
789 : 1 : pLeft.setY( 1 );
790 : 1 : QVERIFY( pRight.isEmpty() );
791 : 1 : QVERIFY( pLeft.isEmpty() );
792 : 1 : QVERIFY( pLeft != pRight );
793 : 1 : pRight.setY( 1 );
794 : 1 : pLeft.setX( 1 );
795 : 1 : QVERIFY( !pRight.isEmpty() );
796 : 1 : QVERIFY( !pLeft.isEmpty() );
797 : 1 : QVERIFY( pLeft == pRight );
798 : :
799 : :
800 : 1 : QVERIFY( QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) );
801 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::PointZ, 2 / 3.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) ) );
802 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::Point, 1 / 3.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) ) );
803 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 2 / 3.0 ) == QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) ) );
804 : 1 : QVERIFY( QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 1 / 3.0 ) );
805 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::PointZM, 3.0, 4.0, 1 / 3.0 ) ) );
806 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 2 / 3.0 ) == QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 1 / 3.0 ) ) );
807 : 1 : QVERIFY( QgsPoint( QgsWkbTypes::PointM, 3.0, 4.0, 0.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::PointM, 3.0, 4.0, 0.0, 1 / 3.0 ) );
808 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::PointM, 3.0, 4.0, 0.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 0.0, 1 / 3.0 ) ) );
809 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::PointM, 3.0, 4.0, 0.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::PointM, 3.0, 4.0, 0.0, 2 / 3.0 ) ) );
810 : 1 : QVERIFY( QgsPoint( QgsWkbTypes::PointZM, 3.0, 4.0, 2 / 3.0, 1 / 3.0 ) == QgsPoint( QgsWkbTypes::PointZM, 3.0, 4.0, 2 / 3.0, 1 / 3.0 ) );
811 : 1 : QVERIFY( QgsPoint( QgsWkbTypes::Point25D, 3.0, 4.0, 2 / 3.0 ) == QgsPoint( QgsWkbTypes::Point25D, 3.0, 4.0, 2 / 3.0 ) );
812 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::Point25D, 3.0, 4.0, 2 / 3.0 ) == QgsPoint( QgsWkbTypes::PointZ, 3.0, 4.0, 2 / 3.0 ) ) );
813 : : //test inequality operator
814 : 1 : QVERIFY( !( QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) != QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) ) );
815 : 1 : QVERIFY( QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 1 / 3.0 ) != QgsPoint( QgsWkbTypes::PointZ, 2 / 3.0, 1 / 3.0 ) );
816 : :
817 : 1 : QgsLineString nonPoint;
818 : 1 : QVERIFY( p8 != nonPoint );
819 : 1 : QVERIFY( !( p8 == nonPoint ) );
820 : :
821 : : //test setters and getters
822 : : //x
823 : 1 : QgsPoint p10( QgsWkbTypes::PointZM );
824 : 1 : p10.setX( 5.0 );
825 : 1 : QCOMPARE( p10.x(), 5.0 );
826 : 1 : QCOMPARE( p10.rx(), 5.0 );
827 : 1 : p10.rx() = 9.0;
828 : 1 : QCOMPARE( p10.x(), 9.0 );
829 : : //y
830 : 1 : p10.setY( 7.0 );
831 : 1 : QCOMPARE( p10.y(), 7.0 );
832 : 1 : QCOMPARE( p10.ry(), 7.0 );
833 : 1 : p10.ry() = 3.0;
834 : 1 : QCOMPARE( p10.y(), 3.0 );
835 : : //z
836 : 1 : p10.setZ( 17.0 );
837 : 1 : QCOMPARE( p10.is3D(), true );
838 : 1 : QCOMPARE( p10.z(), 17.0 );
839 : 1 : QCOMPARE( p10.rz(), 17.0 );
840 : 1 : p10.rz() = 13.0;
841 : 1 : QCOMPARE( p10.z(), 13.0 );
842 : : //m
843 : 1 : p10.setM( 27.0 );
844 : 1 : QCOMPARE( p10.m(), 27.0 );
845 : 1 : QCOMPARE( p10.rm(), 27.0 );
846 : 1 : p10.rm() = 23.0;
847 : 1 : QCOMPARE( p10.m(), 23.0 );
848 : :
849 : : //other checks
850 : 1 : QCOMPARE( p10.geometryType(), QString( "Point" ) );
851 : 1 : QCOMPARE( p10.dimension(), 0 );
852 : :
853 : : //clone
854 : 1 : std::unique_ptr< QgsPoint >clone( p10.clone() );
855 : 1 : QVERIFY( p10 == *clone );
856 : :
857 : : //toCurveType
858 : 1 : clone.reset( p10.toCurveType() );
859 : 1 : QVERIFY( p10 == *clone );
860 : :
861 : : //assignment
862 : 1 : QgsPoint original( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, -4.0 );
863 : 1 : QgsPoint assigned( 6.0, 7.0 );
864 : 1 : assigned = original;
865 : 1 : QVERIFY( assigned == original );
866 : :
867 : : //clear
868 : 1 : QgsPoint p11( 5.0, 6.0 );
869 : 1 : p11.clear();
870 : 1 : QCOMPARE( p11.wkbType(), QgsWkbTypes::Point );
871 : 1 : QVERIFY( std::isnan( p11.x() ) );
872 : 1 : QVERIFY( std::isnan( p11.y() ) );
873 : :
874 : : //toQPointF
875 : 1 : QgsPoint p11a( 5.0, 9.0 );
876 : 1 : QPointF result = p11a.toQPointF();
877 : 1 : QGSCOMPARENEAR( result.x(), 5.0, 4 * std::numeric_limits<double>::epsilon() );
878 : 1 : QGSCOMPARENEAR( result.y(), 9.0, 4 * std::numeric_limits<double>::epsilon() );
879 : :
880 : : //to/from WKB
881 : 1 : QgsPoint p12( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, -4.0 );
882 : 1 : QByteArray wkb12 = p12.asWkb();
883 : 1 : QCOMPARE( wkb12.size(), p12.wkbSize() );
884 : 1 : QgsPoint p13;
885 : 1 : QgsConstWkbPtr wkb12ptr( wkb12 );
886 : 1 : p13.fromWkb( wkb12ptr );
887 : 1 : QVERIFY( p13 == p12 );
888 : :
889 : : //bad WKB - check for no crash
890 : 1 : p13 = QgsPoint( 1, 2 );
891 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
892 : 1 : QVERIFY( !p13.fromWkb( nullPtr ) );
893 : 1 : QCOMPARE( p13.wkbType(), QgsWkbTypes::Point );
894 : 1 : QgsLineString line;
895 : 1 : p13 = QgsPoint( 1, 2 );
896 : 1 : QByteArray wkbLine = line.asWkb();
897 : 1 : QCOMPARE( wkbLine.size(), line.wkbSize() );
898 : 1 : QgsConstWkbPtr wkbLinePtr( wkbLine );
899 : 1 : QVERIFY( !p13.fromWkb( wkbLinePtr ) );
900 : 1 : QCOMPARE( p13.wkbType(), QgsWkbTypes::Point );
901 : :
902 : : //to/from WKT
903 : 1 : p13 = QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, -4.0 );
904 : 1 : QString wkt = p13.asWkt();
905 : 1 : QVERIFY( !wkt.isEmpty() );
906 : 1 : QgsPoint p14;
907 : 1 : QVERIFY( p14.fromWkt( wkt ) );
908 : 1 : QVERIFY( p14 == p13 );
909 : :
910 : : //bad WKT
911 : 1 : QVERIFY( !p14.fromWkt( "Polygon()" ) );
912 : 1 : QVERIFY( !p14.fromWkt( "Point(1 )" ) );
913 : :
914 : : //asGML2
915 : 1 : QgsPoint exportPoint( 1, 2 );
916 : 1 : QgsPoint exportPointFloat( 1 / 3.0, 2 / 3.0 );
917 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
918 : 2 : QString expectedGML2( QStringLiteral( "<Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1,2</coordinates></Point>" ) );
919 : 3 : QGSCOMPAREGML( elemToString( exportPoint.asGml2( doc ) ), expectedGML2 );
920 : 2 : QString expectedGML2prec3( QStringLiteral( "<Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.333,0.667</coordinates></Point>" ) );
921 : 3 : QGSCOMPAREGML( elemToString( exportPointFloat.asGml2( doc, 3 ) ), expectedGML2prec3 );
922 : :
923 : : //asGML3
924 : 2 : QString expectedGML3( QStringLiteral( "<Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">1 2</pos></Point>" ) );
925 : 1 : QCOMPARE( elemToString( exportPoint.asGml3( doc ) ), expectedGML3 );
926 : 2 : QString expectedGML3prec3( QStringLiteral( "<Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">0.333 0.667</pos></Point>" ) );
927 : 1 : QCOMPARE( elemToString( exportPointFloat.asGml3( doc, 3 ) ), expectedGML3prec3 );
928 : 1 : QgsPoint exportPointZ( 1, 2, 3 );
929 : 2 : QString expectedGML3Z( QStringLiteral( "<Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"3\">1 2 3</pos></Point>" ) );
930 : 3 : QGSCOMPAREGML( elemToString( exportPointZ.asGml3( doc, 3 ) ), expectedGML3Z );
931 : :
932 : : //asGML2 inverted axis
933 : 1 : QgsPoint exportPointInvertedAxis( 1, 2 );
934 : 1 : QgsPoint exportPointFloatInvertedAxis( 1 / 3.0, 2 / 3.0 );
935 : 2 : QDomDocument docInvertedAxis( QStringLiteral( "gml" ) );
936 : 2 : QString expectedGML2InvertedAxis( QStringLiteral( "<Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">2,1</coordinates></Point>" ) );
937 : 4 : QGSCOMPAREGML( elemToString( exportPointInvertedAxis.asGml2( docInvertedAxis, 17, QStringLiteral( "gml" ), QgsAbstractGeometry::AxisOrder::YX ) ), expectedGML2InvertedAxis );
938 : 2 : QString expectedGML2prec3InvertedAxis( QStringLiteral( "<Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.667,0.333</coordinates></Point>" ) );
939 : 4 : QGSCOMPAREGML( elemToString( exportPointFloatInvertedAxis.asGml2( docInvertedAxis, 3, QStringLiteral( "gml" ), QgsAbstractGeometry::AxisOrder::YX ) ), expectedGML2prec3InvertedAxis );
940 : :
941 : : //asGML3 inverted axis
942 : 2 : QString expectedGML3InvertedAxis( QStringLiteral( "<Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">2 1</pos></Point>" ) );
943 : 2 : QCOMPARE( elemToString( exportPointInvertedAxis.asGml3( docInvertedAxis, 17, QStringLiteral( "gml" ), QgsAbstractGeometry::AxisOrder::YX ) ), expectedGML3InvertedAxis );
944 : 2 : QString expectedGML3prec3InvertedAxis( QStringLiteral( "<Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">0.667 0.333</pos></Point>" ) );
945 : 2 : QCOMPARE( elemToString( exportPointFloatInvertedAxis.asGml3( docInvertedAxis, 3, QStringLiteral( "gml" ), QgsAbstractGeometry::AxisOrder::YX ) ), expectedGML3prec3InvertedAxis );
946 : 1 : QgsPoint exportPointZInvertedAxis( 1, 2, 3 );
947 : 2 : QString expectedGML3ZInvertedAxis( QStringLiteral( "<Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"3\">2 1 3</pos></Point>" ) );
948 : 4 : QGSCOMPAREGML( elemToString( exportPointZInvertedAxis.asGml3( docInvertedAxis, 3, QStringLiteral( "gml" ), QgsAbstractGeometry::AxisOrder::YX ) ), expectedGML3ZInvertedAxis );
949 : :
950 : :
951 : : //asJSON
952 : 2 : QString expectedJson( QStringLiteral( "{\"coordinates\":[1.0,2.0],\"type\":\"Point\"}" ) );
953 : 1 : QCOMPARE( exportPoint.asJson(), expectedJson );
954 : 2 : QString expectedJsonPrec3( QStringLiteral( "{\"coordinates\":[0.333,0.667],\"type\":\"Point\"}" ) );
955 : 1 : QCOMPARE( exportPointFloat.asJson( 3 ), expectedJsonPrec3 );
956 : :
957 : : //asKML
958 : 2 : QString expectedKml( QStringLiteral( "<Point><coordinates>1,2</coordinates></Point>" ) );
959 : 1 : QCOMPARE( exportPoint.asKml(), expectedKml );
960 : 2 : QString expectedKmlPrec3( QStringLiteral( "<Point><coordinates>0.333,0.667</coordinates></Point>" ) );
961 : 1 : QCOMPARE( exportPointFloat.asKml( 3 ), expectedKmlPrec3 );
962 : :
963 : : //bounding box
964 : 1 : QgsPoint p15( 1.0, 2.0 );
965 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 1.0, 2.0, 1.0, 2.0 ) );
966 : : //modify points and test that bounding box is updated accordingly
967 : 1 : p15.setX( 3.0 );
968 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 3.0, 2.0, 3.0, 2.0 ) );
969 : 1 : p15.setY( 6.0 );
970 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 3.0, 6.0, 3.0, 6.0 ) );
971 : 1 : p15.rx() = 4.0;
972 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 4.0, 6.0, 4.0, 6.0 ) );
973 : 1 : p15.ry() = 9.0;
974 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 4.0, 9.0, 4.0, 9.0 ) );
975 : 1 : p15.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 11.0, 13.0 ) );
976 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 11.0, 13.0, 11.0, 13.0 ) );
977 : 1 : p15 = QgsPoint( 21.0, 23.0 );
978 : 1 : QCOMPARE( p15.boundingBox(), QgsRectangle( 21.0, 23.0, 21.0, 23.0 ) );
979 : :
980 : : //CRS transform
981 : 2 : QgsCoordinateReferenceSystem sourceSrs( QStringLiteral( "EPSG:3994" ) );
982 : 2 : QgsCoordinateReferenceSystem destSrs( QStringLiteral( "EPSG:4202" ) ); // want a transform with ellipsoid change
983 : 1 : QgsCoordinateTransform tr( sourceSrs, destSrs, QgsProject::instance() );
984 : 1 : QgsPoint p16( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 );
985 : 1 : p16.transform( tr, QgsCoordinateTransform::ForwardTransform );
986 : 1 : QGSCOMPARENEAR( p16.x(), 175.771, 0.001 );
987 : 1 : QGSCOMPARENEAR( p16.y(), -39.724, 0.001 );
988 : 1 : QGSCOMPARENEAR( p16.z(), 1.0, 0.001 );
989 : 1 : QCOMPARE( p16.m(), 2.0 );
990 : 1 : p16.transform( tr, QgsCoordinateTransform::ReverseTransform );
991 : 1 : QGSCOMPARENEAR( p16.x(), 6374985, 1 );
992 : 1 : QGSCOMPARENEAR( p16.y(), -3626584, 1 );
993 : 1 : QGSCOMPARENEAR( p16.z(), 1.0, 0.001 );
994 : 1 : QCOMPARE( p16.m(), 2.0 );
995 : : #if PROJ_VERSION_MAJOR<6 // note - z value transform doesn't currently work with proj 6+, because we don't yet support compound CRS definitions
996 : : //test with z transform
997 : : p16.transform( tr, QgsCoordinateTransform::ForwardTransform, true );
998 : : QGSCOMPARENEAR( p16.z(), -19.249, 0.001 );
999 : : p16.transform( tr, QgsCoordinateTransform::ReverseTransform, true );
1000 : : QGSCOMPARENEAR( p16.z(), 1.0, 0.001 );
1001 : : #endif
1002 : : //QTransform transform
1003 : 1 : QTransform qtr = QTransform::fromScale( 2, 3 );
1004 : 1 : QgsPoint p17( QgsWkbTypes::PointZM, 10, 20, 30, 40 );
1005 : 1 : p17.transform( qtr );
1006 : 1 : QVERIFY( p17 == QgsPoint( QgsWkbTypes::PointZM, 20, 60, 30, 40 ) );
1007 : 1 : p17.transform( QTransform::fromScale( 1, 1 ), 11, 2, 3, 4 );
1008 : 1 : QVERIFY( p17 == QgsPoint( QgsWkbTypes::PointZM, 20, 60, 71, 163 ) );
1009 : :
1010 : : //coordinateSequence
1011 : 1 : QgsPoint p18( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 );
1012 : 1 : QgsCoordinateSequence coord = p18.coordinateSequence();
1013 : 1 : QCOMPARE( coord.count(), 1 );
1014 : 1 : QCOMPARE( coord.at( 0 ).count(), 1 );
1015 : 1 : QCOMPARE( coord.at( 0 ).at( 0 ).count(), 1 );
1016 : 1 : QCOMPARE( coord.at( 0 ).at( 0 ).at( 0 ), p18 );
1017 : :
1018 : : //low level editing
1019 : : //insertVertex should have no effect
1020 : 1 : QgsPoint p19( QgsWkbTypes::PointZM, 3.0, 4.0, 6.0, 7.0 );
1021 : 1 : p19.insertVertex( QgsVertexId( 1, 2, 3 ), QgsPoint( 6.0, 7.0 ) );
1022 : 1 : QCOMPARE( p19, QgsPoint( QgsWkbTypes::PointZM, 3.0, 4.0, 6.0, 7.0 ) );
1023 : :
1024 : : //moveVertex
1025 : 1 : p19.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
1026 : 1 : QCOMPARE( p19, QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
1027 : : //invalid vertex id, should not crash
1028 : 1 : p19.moveVertex( QgsVertexId( 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZM, 2.0, 3.0, 1.0, 2.0 ) );
1029 : 1 : QCOMPARE( p19, QgsPoint( QgsWkbTypes::PointZM, 2.0, 3.0, 1.0, 2.0 ) );
1030 : : //move PointZM using Point
1031 : 1 : p19.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::Point, 11.0, 12.0 ) );
1032 : 1 : QCOMPARE( p19, QgsPoint( QgsWkbTypes::PointZM, 11.0, 12.0, 1.0, 2.0 ) );
1033 : : //move PointZM using PointZ
1034 : 1 : p19.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZ, 21.0, 22.0, 23.0 ) );
1035 : 1 : QCOMPARE( p19, QgsPoint( QgsWkbTypes::PointZM, 21.0, 22.0, 23.0, 2.0 ) );
1036 : : //move PointZM using PointM
1037 : 1 : p19.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointM, 31.0, 32.0, 0.0, 43.0 ) );
1038 : 1 : QCOMPARE( p19, QgsPoint( QgsWkbTypes::PointZM, 31.0, 32.0, 23.0, 43.0 ) );
1039 : : //move Point using PointZM (z/m should be ignored)
1040 : 1 : QgsPoint p20( 3.0, 4.0 );
1041 : 1 : p20.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 2.0, 3.0, 1.0, 2.0 ) );
1042 : 1 : QCOMPARE( p20, QgsPoint( 2.0, 3.0 ) );
1043 : :
1044 : : //deleteVertex - should do nothing, but not crash
1045 : 1 : p20.deleteVertex( QgsVertexId( 0, 0, 0 ) );
1046 : 1 : QCOMPARE( p20, QgsPoint( 2.0, 3.0 ) );
1047 : :
1048 : : // closestSegment
1049 : 1 : QgsPoint closest;
1050 : 1 : QgsVertexId after;
1051 : : // return error - points have no segments
1052 : 1 : QVERIFY( p20.closestSegment( QgsPoint( 4.0, 6.0 ), closest, after ) < 0 );
1053 : :
1054 : : //nextVertex
1055 : 1 : QgsPoint p21( 3.0, 4.0 );
1056 : 1 : QgsPoint p22;
1057 : 1 : QgsVertexId v( 0, 0, -1 );
1058 : 1 : QVERIFY( p21.nextVertex( v, p22 ) );
1059 : 1 : QCOMPARE( p22, p21 );
1060 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
1061 : : //no more vertices
1062 : 1 : QVERIFY( !p21.nextVertex( v, p22 ) );
1063 : 1 : v = QgsVertexId( 0, 1, -1 ); //test that ring number is maintained
1064 : 1 : QVERIFY( p21.nextVertex( v, p22 ) );
1065 : 1 : QCOMPARE( p22, p21 );
1066 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 0 ) );
1067 : 1 : v = QgsVertexId( 1, 0, -1 ); //test that part number is maintained
1068 : 1 : QVERIFY( p21.nextVertex( v, p22 ) );
1069 : 1 : QCOMPARE( p22, p21 );
1070 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 0 ) );
1071 : :
1072 : : //adjacent vertices - both should be invalid
1073 : 1 : QgsVertexId prev( 1, 2, 3 ); // start with something
1074 : 1 : QgsVertexId next( 4, 5, 6 );
1075 : 1 : p21.adjacentVertices( v, prev, next );
1076 : 1 : QCOMPARE( prev, QgsVertexId() );
1077 : 1 : QCOMPARE( next, QgsVertexId() );
1078 : :
1079 : : // vertex iterator
1080 : 1 : QgsAbstractGeometry::vertex_iterator it1 = p21.vertices_begin();
1081 : 1 : QgsAbstractGeometry::vertex_iterator it1end = p21.vertices_end();
1082 : 1 : QCOMPARE( *it1, p21 );
1083 : 1 : QCOMPARE( it1.vertexId(), QgsVertexId( 0, 0, 0 ) );
1084 : 1 : ++it1;
1085 : 1 : QCOMPARE( it1, it1end );
1086 : :
1087 : : // Java-style iterator
1088 : 1 : QgsVertexIterator it2( &p21 );
1089 : 1 : QVERIFY( it2.hasNext() );
1090 : 1 : QCOMPARE( it2.next(), p21 );
1091 : 1 : QVERIFY( !it2.hasNext() );
1092 : :
1093 : : //vertexAt - will always be same as point
1094 : 1 : QCOMPARE( p21.vertexAt( QgsVertexId() ), p21 );
1095 : 1 : QCOMPARE( p21.vertexAt( QgsVertexId( 0, 0, 0 ) ), p21 );
1096 : :
1097 : : //vertexAngle - undefined, but check that it doesn't crash
1098 : 1 : ( void )p21.vertexAngle( QgsVertexId() );
1099 : :
1100 : : //counts
1101 : 1 : QCOMPARE( p20.vertexCount(), 1 );
1102 : 1 : QCOMPARE( p20.ringCount(), 1 );
1103 : 1 : QCOMPARE( p20.partCount(), 1 );
1104 : :
1105 : : //measures and other abstract geometry methods
1106 : 1 : QCOMPARE( p20.length(), 0.0 );
1107 : 1 : QCOMPARE( p20.perimeter(), 0.0 );
1108 : 1 : QCOMPARE( p20.area(), 0.0 );
1109 : 1 : QCOMPARE( p20.centroid(), p20 );
1110 : 1 : QVERIFY( !p20.hasCurvedSegments() );
1111 : 1 : std::unique_ptr< QgsPoint >segmented( static_cast< QgsPoint *>( p20.segmentize() ) );
1112 : 1 : QCOMPARE( *segmented, p20 );
1113 : :
1114 : : //addZValue
1115 : 1 : QgsPoint p23( 1.0, 2.0 );
1116 : 1 : QVERIFY( p23.addZValue( 5.0 ) );
1117 : 1 : QCOMPARE( p23, QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 5.0 ) );
1118 : 1 : QVERIFY( !p23.addZValue( 6.0 ) );
1119 : :
1120 : : //addMValue
1121 : 1 : QgsPoint p24( 1.0, 2.0 );
1122 : 1 : QVERIFY( p24.addMValue( 5.0 ) );
1123 : 1 : QCOMPARE( p24, QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 5.0 ) );
1124 : 1 : QVERIFY( !p24.addMValue( 6.0 ) );
1125 : :
1126 : : //dropZ
1127 : 1 : QgsPoint p25( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 );
1128 : 1 : QVERIFY( p25.dropZValue() );
1129 : 1 : QCOMPARE( p25, QgsPoint( 1.0, 2.0 ) );
1130 : 1 : QVERIFY( !p25.dropZValue() );
1131 : 1 : QgsPoint p26( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 );
1132 : 1 : QVERIFY( p26.dropZValue() );
1133 : 1 : QCOMPARE( p26, QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 4.0 ) );
1134 : 1 : QVERIFY( !p26.dropZValue() );
1135 : 1 : QgsPoint p26a( QgsWkbTypes::Point25D, 1.0, 2.0, 3.0 );
1136 : 1 : QVERIFY( p26a.dropZValue() );
1137 : 1 : QCOMPARE( p26a, QgsPoint( QgsWkbTypes::Point, 1.0, 2.0 ) );
1138 : 1 : QVERIFY( !p26a.dropZValue() );
1139 : :
1140 : : //dropM
1141 : 1 : QgsPoint p27( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 );
1142 : 1 : QVERIFY( p27.dropMValue() );
1143 : 1 : QCOMPARE( p27, QgsPoint( 1.0, 2.0 ) );
1144 : 1 : QVERIFY( !p27.dropMValue() );
1145 : 1 : QgsPoint p28( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 );
1146 : 1 : QVERIFY( p28.dropMValue() );
1147 : 1 : QCOMPARE( p28, QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0, 0.0 ) );
1148 : 1 : QVERIFY( !p28.dropMValue() );
1149 : :
1150 : : //convertTo
1151 : 1 : QgsPoint p29( 1.0, 2.0 );
1152 : 1 : QVERIFY( p29.convertTo( QgsWkbTypes::Point ) );
1153 : 1 : QCOMPARE( p29.wkbType(), QgsWkbTypes::Point );
1154 : 1 : QVERIFY( p29.convertTo( QgsWkbTypes::PointZ ) );
1155 : 1 : QCOMPARE( p29.wkbType(), QgsWkbTypes::PointZ );
1156 : 1 : p29.setZ( 5.0 );
1157 : 1 : QVERIFY( p29.convertTo( QgsWkbTypes::Point25D ) );
1158 : 1 : QCOMPARE( p29.wkbType(), QgsWkbTypes::Point25D );
1159 : 1 : QCOMPARE( p29.z(), 5.0 );
1160 : 1 : QVERIFY( p29.convertTo( QgsWkbTypes::PointZM ) );
1161 : 1 : QCOMPARE( p29.wkbType(), QgsWkbTypes::PointZM );
1162 : 1 : QCOMPARE( p29.z(), 5.0 );
1163 : 1 : p29.setM( 9.0 );
1164 : 1 : QVERIFY( p29.convertTo( QgsWkbTypes::PointM ) );
1165 : 1 : QCOMPARE( p29.wkbType(), QgsWkbTypes::PointM );
1166 : 1 : QVERIFY( std::isnan( p29.z() ) );
1167 : 1 : QCOMPARE( p29.m(), 9.0 );
1168 : 1 : QVERIFY( p29.convertTo( QgsWkbTypes::Point ) );
1169 : 1 : QCOMPARE( p29.wkbType(), QgsWkbTypes::Point );
1170 : 1 : QVERIFY( std::isnan( p29.z() ) );
1171 : 1 : QVERIFY( std::isnan( p29.m() ) );
1172 : 1 : QVERIFY( !p29.convertTo( QgsWkbTypes::Polygon ) );
1173 : :
1174 : : //boundary
1175 : 1 : QgsPoint p30( 1.0, 2.0 );
1176 : 1 : QVERIFY( !p30.boundary() );
1177 : :
1178 : : // distance
1179 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( QgsPoint( 2, 2 ) ), 1.0 );
1180 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( 2, 2 ), 1.0 );
1181 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( QgsPoint( 3, 2 ) ), 2.0 );
1182 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( 3, 2 ), 2.0 );
1183 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( QgsPoint( 1, 3 ) ), 1.0 );
1184 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( 1, 3 ), 1.0 );
1185 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( QgsPoint( 1, 4 ) ), 2.0 );
1186 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distance( 1, 4 ), 2.0 );
1187 : 1 : QCOMPARE( QgsPoint( 1, -2 ).distance( QgsPoint( 1, -4 ) ), 2.0 );
1188 : 1 : QCOMPARE( QgsPoint( 1, -2 ).distance( 1, -4 ), 2.0 );
1189 : :
1190 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( QgsPoint( 2, 2 ) ), 1.0 );
1191 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( 2, 2 ), 1.0 );
1192 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( QgsPoint( 3, 2 ) ), 4.0 );
1193 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( 3, 2 ), 4.0 );
1194 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( QgsPoint( 1, 3 ) ), 1.0 );
1195 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( 1, 3 ), 1.0 );
1196 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( QgsPoint( 1, 4 ) ), 4.0 );
1197 : 1 : QCOMPARE( QgsPoint( 1, 2 ).distanceSquared( 1, 4 ), 4.0 );
1198 : 1 : QCOMPARE( QgsPoint( 1, -2 ).distanceSquared( QgsPoint( 1, -4 ) ), 4.0 );
1199 : 1 : QCOMPARE( QgsPoint( 1, -2 ).distanceSquared( 1, -4 ), 4.0 );
1200 : :
1201 : : // distance 3D
1202 : 1 : QCOMPARE( QgsPoint( 0, 0 ).distanceSquared3D( QgsPoint( 1, 1 ) ), 2.0 );
1203 : 1 : QVERIFY( std::isnan( QgsPoint( 0, 0 ).distanceSquared3D( 1, 1, 0 ) ) );
1204 : 1 : QVERIFY( std::isnan( QgsPoint( 0, 0 ).distanceSquared3D( QgsPoint( QgsWkbTypes::PointZ, 2, 2, 2, 0 ) ) ) );
1205 : 1 : QVERIFY( std::isnan( QgsPoint( 0, 0 ).distanceSquared3D( 2, 2, 2 ) ) );
1206 : 1 : QVERIFY( std::isnan( QgsPoint( QgsWkbTypes::PointZ, 2, 2, 2, 0 ).distanceSquared3D( QgsPoint( 1, 1 ) ) ) );
1207 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 2, 2, 2, 0 ).distanceSquared3D( 1, 1, 0 ), 6.0 );
1208 : 1 : QVERIFY( std::isnan( QgsPoint( QgsWkbTypes::PointZ, -2, -2, -2, 0 ).distanceSquared3D( QgsPoint( 0, 0 ) ) ) );
1209 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, -2, -2, -2, 0 ).distanceSquared3D( 0, 0, 0 ), 12.0 );
1210 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, -2, -2, -2, 0 ).distanceSquared3D( QgsPoint( QgsWkbTypes::PointZ, 2, 2, 2, 0 ) ), 48.0 );
1211 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, -2, -2, -2, 0 ).distanceSquared3D( 2, 2, 2 ), 48.0 );
1212 : :
1213 : :
1214 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2, 0 ).distance3D( QgsPoint( QgsWkbTypes::PointZ, 1, 3, 2, 0 ) ), 2.0 );
1215 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2, 0 ).distance3D( 1, 3, 2 ), 2.0 );
1216 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2, 0 ).distance3D( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 4, 0 ) ), 2.0 );
1217 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2, 0 ).distance3D( 1, 1, 4 ), 2.0 );
1218 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, -2, 0 ).distance3D( QgsPoint( QgsWkbTypes::PointZ, 1, 1, -4, 0 ) ), 2.0 );
1219 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, -2, 0 ).distance3D( 1, 1, -4 ), 2.0 );
1220 : :
1221 : : // azimuth
1222 : 1 : QCOMPARE( QgsPoint( 1, 2 ).azimuth( QgsPoint( 1, 2 ) ), 0.0 );
1223 : 1 : QCOMPARE( QgsPoint( 1, 2 ).azimuth( QgsPoint( 1, 3 ) ), 0.0 );
1224 : 1 : QCOMPARE( QgsPoint( 1, 2 ).azimuth( QgsPoint( 2, 2 ) ), 90.0 );
1225 : 1 : QCOMPARE( QgsPoint( 1, 2 ).azimuth( QgsPoint( 1, 0 ) ), 180.0 );
1226 : 1 : QCOMPARE( QgsPoint( 1, 2 ).azimuth( QgsPoint( 0, 2 ) ), -90.0 );
1227 : :
1228 : : // operators
1229 : 1 : QgsPoint p31( 1, 2 );
1230 : 1 : QgsPoint p32( 3, 5 );
1231 : 1 : QCOMPARE( p32 - p31, QgsVector( 2, 3 ) );
1232 : 1 : QCOMPARE( p31 - p32, QgsVector( -2, -3 ) );
1233 : :
1234 : 1 : p31 = QgsPoint( 1, 2 );
1235 : 1 : QCOMPARE( p31 + QgsVector( 3, 5 ), QgsPoint( 4, 7 ) );
1236 : 1 : p31 += QgsVector( 3, 5 );
1237 : 1 : QCOMPARE( p31, QgsPoint( 4, 7 ) );
1238 : :
1239 : 1 : QCOMPARE( p31 - QgsVector( 3, 5 ), QgsPoint( 1, 2 ) );
1240 : 1 : p31 -= QgsVector( 3, 5 );
1241 : 1 : QCOMPARE( p31, QgsPoint( 1, 2 ) );
1242 : :
1243 : : // test projecting a point
1244 : : // 2D
1245 : 1 : QgsPoint p33 = QgsPoint( 1, 2 );
1246 : 1 : QCOMPARE( p33.project( 1, 0 ), QgsPoint( 1, 3 ) );
1247 : 1 : QCOMPARE( p33.project( 1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2 ) );
1248 : 1 : QCOMPARE( p33.project( 1.5, 90 ), QgsPoint( 2.5, 2 ) );
1249 : 1 : QCOMPARE( p33.project( 1.5, 90, 90 ), QgsPoint( 2.5, 2 ) ); // stay QgsWkbTypes::Point
1250 : 1 : QCOMPARE( p33.project( 2, 180 ), QgsPoint( 1, 0 ) );
1251 : 1 : QCOMPARE( p33.project( 5, 270 ), QgsPoint( -4, 2 ) );
1252 : 1 : QCOMPARE( p33.project( 6, 360 ), QgsPoint( 1, 8 ) );
1253 : 1 : QCOMPARE( p33.project( 5, 450 ), QgsPoint( 6, 2 ) );
1254 : 1 : QCOMPARE( p33.project( 5, 450, 450 ), QgsPoint( 6, 2 ) ); // stay QgsWkbTypes::Point
1255 : 1 : QCOMPARE( p33.project( -1, 0 ), QgsPoint( 1, 1 ) );
1256 : 1 : QCOMPARE( p33.project( 1.5, -90 ), QgsPoint( -0.5, 2 ) );
1257 : 1 : p33.addZValue( 0 );
1258 : 1 : QCOMPARE( p33.project( 1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 1 ) );
1259 : 1 : QCOMPARE( p33.project( 2, 180, 180 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, -2 ) );
1260 : 1 : QCOMPARE( p33.project( 5, 270, 270 ), QgsPoint( QgsWkbTypes::PointZ, 6, 2, 0 ) );
1261 : 1 : QCOMPARE( p33.project( 6, 360, 360 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 6 ) );
1262 : 1 : QCOMPARE( p33.project( -1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, -1 ) );
1263 : 1 : QCOMPARE( p33.project( 1.5, -90, -90 ), QgsPoint( QgsWkbTypes::PointZ, 2.5, 2, 0 ) );
1264 : :
1265 : : // PointM
1266 : 1 : p33.dropZValue();
1267 : 1 : p33.addMValue( 5.0 );
1268 : 1 : QCOMPARE( p33.project( 1, 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 3, 0, 5 ) );
1269 : 1 : QCOMPARE( p33.project( 5, 450, 450 ), QgsPoint( QgsWkbTypes::PointM, 6, 2, 0, 5 ) );
1270 : :
1271 : 1 : p33.addZValue( 0 );
1272 : 1 : QCOMPARE( p33.project( 1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 1, 5 ) );
1273 : :
1274 : : // 3D
1275 : 1 : QgsPoint p34 = QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 );
1276 : 1 : QCOMPARE( p34.project( 1, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 3, 2 ) );
1277 : 1 : QCOMPARE( p34.project( 1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
1278 : 1 : QCOMPARE( p34.project( 1.5, 90 ), QgsPoint( QgsWkbTypes::PointZ, 2.5, 2, 2 ) );
1279 : 1 : QCOMPARE( p34.project( 1.5, 90, 90 ), QgsPoint( QgsWkbTypes::PointZ, 2.5, 2, 2 ) );
1280 : 1 : QCOMPARE( p34.project( 2, 180 ), QgsPoint( QgsWkbTypes::PointZ, 1, 0, 2 ) );
1281 : 1 : QCOMPARE( p34.project( 2, 180, 180 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 0 ) );
1282 : 1 : QCOMPARE( p34.project( 5, 270 ), QgsPoint( QgsWkbTypes::PointZ, -4, 2, 2 ) );
1283 : 1 : QCOMPARE( p34.project( 5, 270, 270 ), QgsPoint( QgsWkbTypes::PointZ, 6, 2, 2 ) );
1284 : 1 : QCOMPARE( p34.project( 6, 360 ), QgsPoint( QgsWkbTypes::PointZ, 1, 8, 2 ) );
1285 : 1 : QCOMPARE( p34.project( 6, 360, 360 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 8 ) );
1286 : 1 : QCOMPARE( p34.project( 5, 450 ), QgsPoint( QgsWkbTypes::PointZ, 6, 2, 2 ) );
1287 : 1 : QCOMPARE( p34.project( 5, 450, 450 ), QgsPoint( QgsWkbTypes::PointZ, 6, 2, 2 ) );
1288 : 1 : QCOMPARE( p34.project( -1, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2 ) );
1289 : 1 : QCOMPARE( p34.project( -1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 1 ) );
1290 : 1 : QCOMPARE( p34.project( 1.5, -90 ), QgsPoint( QgsWkbTypes::PointZ, -0.5, 2, 2 ) );
1291 : 1 : QCOMPARE( p34.project( 1.5, -90, -90 ), QgsPoint( QgsWkbTypes::PointZ, 2.5, 2, 2 ) );
1292 : : // PointM
1293 : 1 : p34.addMValue( 5.0 );
1294 : 1 : QCOMPARE( p34.project( 1, 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 3, 2, 5 ) );
1295 : 1 : QCOMPARE( p34.project( 1, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 5 ) );
1296 : 1 : QCOMPARE( p34.project( 5, 450 ), QgsPoint( QgsWkbTypes::PointZM, 6, 2, 2, 5 ) );
1297 : 1 : QCOMPARE( p34.project( 5, 450, 450 ), QgsPoint( QgsWkbTypes::PointZM, 6, 2, 2, 5 ) );
1298 : :
1299 : : // inclination
1300 : 1 : QCOMPARE( QgsPoint( 1, 2 ).inclination( QgsPoint( 1, 2 ) ), 90.0 );
1301 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2, 0 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 1, 2, 0 ) ), 90.0 );
1302 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, 90 ) ), 90.0 );
1303 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, -90 ) ), 90.0 );
1304 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, 0 ) ), 0.0 );
1305 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, 180 ) ), 180.0 );
1306 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, -180 ) ), 180.0 );
1307 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, 720 ) ), 0.0 );
1308 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, 45 ) ), 45.0 );
1309 : 1 : QCOMPARE( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).inclination( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ).project( 5, 90, 135 ) ), 135.0 );
1310 : :
1311 : : // vertex number
1312 : 1 : QCOMPARE( QgsPoint( 1, 2 ).vertexNumberFromVertexId( QgsVertexId( 0, 0, -1 ) ), -1 );
1313 : 1 : QCOMPARE( QgsPoint( 1, 2 ).vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), -1 );
1314 : 1 : QCOMPARE( QgsPoint( 1, 2 ).vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
1315 : :
1316 : : //segmentLength
1317 : 1 : QCOMPARE( QgsPoint( 1, 2 ).segmentLength( QgsVertexId() ), 0.0 );
1318 : 1 : QCOMPARE( QgsPoint( 1, 2 ).segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
1319 : 1 : QCOMPARE( QgsPoint( 1, 2 ).segmentLength( QgsVertexId( -1, 0, 1 ) ), 0.0 );
1320 : 1 : QCOMPARE( QgsPoint( 1, 2 ).segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
1321 : 1 : QCOMPARE( QgsPoint( 1, 2 ).segmentLength( QgsVertexId( 0, 0, 0 ) ), 0.0 );
1322 : :
1323 : : // remove duplicate points
1324 : 1 : QgsPoint p = QgsPoint( 1, 2 );
1325 : 1 : QVERIFY( !p.removeDuplicateNodes() );
1326 : 1 : QCOMPARE( p.x(), 1.0 );
1327 : 1 : QCOMPARE( p.y(), 2.0 );
1328 : :
1329 : : // swap xy
1330 : 1 : p = QgsPoint( 1.1, 2.2, 3.3, 4.4, QgsWkbTypes::PointZM );
1331 : 1 : p.swapXy();
1332 : 1 : QCOMPARE( p.x(), 2.2 );
1333 : 1 : QCOMPARE( p.y(), 1.1 );
1334 : 1 : QCOMPARE( p.z(), 3.3 );
1335 : 1 : QCOMPARE( p.m(), 4.4 );
1336 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZM );
1337 : :
1338 : : // filter vertex
1339 : 1 : p = QgsPoint( 1.1, 2.2, 3.3, 4.4, QgsWkbTypes::PointZM );
1340 : 1 : p.filterVertices( []( const QgsPoint & )-> bool { return false; } );
1341 : 1 : QCOMPARE( p.x(), 1.1 );
1342 : 1 : QCOMPARE( p.y(), 2.2 );
1343 : 1 : QCOMPARE( p.z(), 3.3 );
1344 : 1 : QCOMPARE( p.m(), 4.4 );
1345 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZM );
1346 : :
1347 : : // transform vertex
1348 : 1 : p = QgsPoint( 1.1, 2.2, 3.3, 4.4, QgsWkbTypes::PointZM );
1349 : 2 : p.transformVertices( []( const QgsPoint & p )-> QgsPoint
1350 : : {
1351 : 1 : return QgsPoint( p.x() + 2, p.y() + 3, p.z() + 1, p.m() + 8 );
1352 : : } );
1353 : 1 : QCOMPARE( p.x(), 3.1 );
1354 : 1 : QCOMPARE( p.y(), 5.2 );
1355 : 1 : QCOMPARE( p.z(), 4.3 );
1356 : 1 : QCOMPARE( p.m(), 12.4 );
1357 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZM );
1358 : : // no dimensionality change allowed
1359 : 2 : p.transformVertices( []( const QgsPoint & p )-> QgsPoint
1360 : : {
1361 : 1 : return QgsPoint( p.x() + 2, p.y() + 3 );
1362 : : } );
1363 : 1 : QCOMPARE( p.x(), 5.1 );
1364 : 1 : QCOMPARE( p.y(), 8.2 );
1365 : 1 : QVERIFY( std::isnan( p.z() ) );
1366 : 1 : QVERIFY( std::isnan( p.m() ) );
1367 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZM );
1368 : 1 : p = QgsPoint( 2, 3 );
1369 : 2 : p.transformVertices( []( const QgsPoint & p )-> QgsPoint
1370 : : {
1371 : 1 : return QgsPoint( p.x() + 2, p.y() + 3, 7, 8 );
1372 : : } );
1373 : 1 : QCOMPARE( p.x(), 4.0 );
1374 : 1 : QCOMPARE( p.y(), 6.0 );
1375 : 1 : QVERIFY( std::isnan( p.z() ) );
1376 : 1 : QVERIFY( std::isnan( p.m() ) );
1377 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::Point );
1378 : :
1379 : : // transform using class
1380 : 1 : p = QgsPoint( 1.1, 2.2, 3.3, 4.4, QgsWkbTypes::PointZM );
1381 : 1 : TestTransformer transformer;
1382 : 1 : QVERIFY( p.transform( &transformer ) );
1383 : 1 : QCOMPARE( p.x(), 3.3 );
1384 : 1 : QCOMPARE( p.y(), 16.2 );
1385 : 1 : QCOMPARE( p.z(), 8.3 );
1386 : 1 : QCOMPARE( p.m(), 3.4 );
1387 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZM );
1388 : :
1389 : 1 : TestFailTransformer failTransformer;
1390 : 1 : QVERIFY( !p.transform( &failTransformer ) );
1391 : :
1392 : : // test bounding box intersects
1393 : 1 : QVERIFY( QgsPoint( 1, 2 ).boundingBoxIntersects( QgsRectangle( 0, 0.5, 1.5, 3 ) ) );
1394 : 1 : QVERIFY( !QgsPoint( 1, 2 ).boundingBoxIntersects( QgsRectangle( 3, 0.5, 3.5, 3 ) ) );
1395 : 1 : QVERIFY( !QgsPoint().boundingBoxIntersects( QgsRectangle( 0, 0.5, 3.5, 3 ) ) );
1396 : 1 : }
1397 : :
1398 : 1 : void TestQgsGeometry::circularString()
1399 : : {
1400 : : //test constructors
1401 : 1 : QgsCircularString l1;
1402 : 1 : QVERIFY( l1.isEmpty() );
1403 : 1 : QCOMPARE( l1.numPoints(), 0 );
1404 : 1 : QCOMPARE( l1.vertexCount(), 0 );
1405 : 1 : QCOMPARE( l1.nCoordinates(), 0 );
1406 : 1 : QCOMPARE( l1.ringCount(), 0 );
1407 : 1 : QCOMPARE( l1.partCount(), 0 );
1408 : 1 : QVERIFY( !l1.is3D() );
1409 : 1 : QVERIFY( !l1.isMeasure() );
1410 : 1 : QCOMPARE( l1.wkbType(), QgsWkbTypes::CircularString );
1411 : 1 : QCOMPARE( l1.wktTypeStr(), QString( "CircularString" ) );
1412 : 1 : QCOMPARE( l1.geometryType(), QString( "CircularString" ) );
1413 : 1 : QCOMPARE( l1.dimension(), 1 );
1414 : 1 : QVERIFY( l1.hasCurvedSegments() );
1415 : 1 : QCOMPARE( l1.area(), 0.0 );
1416 : 1 : QCOMPARE( l1.perimeter(), 0.0 );
1417 : 1 : QgsPointSequence pts;
1418 : 1 : l1.points( pts );
1419 : 1 : QVERIFY( pts.empty() );
1420 : :
1421 : : // from 3 points
1422 : 1 : QgsCircularString from3Pts( QgsPoint( 1, 2 ), QgsPoint( 21, 22 ), QgsPoint( 31, 2 ) );
1423 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
1424 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1425 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1426 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1427 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1428 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1429 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1430 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1431 : 2 : from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 21, 22, 23 ),
1432 : 1 : QgsPoint( QgsWkbTypes::PointZ, 31, 2, 33 ) );
1433 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZ );
1434 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1435 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1436 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1437 : 1 : QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1438 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1439 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1440 : 1 : QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1441 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1442 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1443 : 1 : QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1444 : 2 : from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 23 ),
1445 : 1 : QgsPoint( QgsWkbTypes::PointM, 31, 2, 0, 33 ) );
1446 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringM );
1447 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1448 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1449 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1450 : 1 : QCOMPARE( from3Pts.pointN( 0 ).m(), 3.0 );
1451 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1452 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1453 : 1 : QCOMPARE( from3Pts.pointN( 1 ).m(), 23.0 );
1454 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1455 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1456 : 1 : QCOMPARE( from3Pts.pointN( 2 ).m(), 33.0 );
1457 : 2 : from3Pts = QgsCircularString( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ),
1458 : 1 : QgsPoint( QgsWkbTypes::PointZM, 31, 2, 33, 34 ) );
1459 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZM );
1460 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1461 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1462 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1463 : 1 : QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1464 : 1 : QCOMPARE( from3Pts.pointN( 0 ).m(), 4.0 );
1465 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1466 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1467 : 1 : QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1468 : 1 : QCOMPARE( from3Pts.pointN( 1 ).m(), 24.0 );
1469 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1470 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1471 : 1 : QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1472 : 1 : QCOMPARE( from3Pts.pointN( 2 ).m(), 34.0 );
1473 : :
1474 : : // from 2 points and center
1475 : 1 : from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( 1, 2 ), QgsPoint( 31, 2 ), QgsPoint( 21, 2 ) );
1476 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
1477 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1478 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1479 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1480 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1481 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1482 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1483 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1484 : 1 : from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( 1, 2 ), QgsPoint( 31, 2 ), QgsPoint( 21, 2 ), false );
1485 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularString );
1486 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1487 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1488 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1489 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1490 : 1 : QCOMPARE( from3Pts.yAt( 1 ), -18.0 );
1491 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1492 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1493 : 2 : from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 32, 2, 33 ),
1494 : 1 : QgsPoint( QgsWkbTypes::PointZ, 21, 2, 23 ) );
1495 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZ );
1496 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1497 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1498 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1499 : 1 : QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1500 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1501 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1502 : 1 : QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1503 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 32.0 );
1504 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1505 : 1 : QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1506 : 2 : from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 31, 2, 0, 33 ),
1507 : 1 : QgsPoint( QgsWkbTypes::PointM, 21, 2, 0, 23 ) );
1508 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringM );
1509 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1510 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1511 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1512 : 1 : QCOMPARE( from3Pts.pointN( 0 ).m(), 3.0 );
1513 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1514 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1515 : 1 : QCOMPARE( from3Pts.pointN( 1 ).m(), 23.0 );
1516 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1517 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1518 : 1 : QCOMPARE( from3Pts.pointN( 2 ).m(), 33.0 );
1519 : 2 : from3Pts = QgsCircularString::fromTwoPointsAndCenter( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 31, 2, 33, 34 ),
1520 : 1 : QgsPoint( QgsWkbTypes::PointZM, 21, 2, 23, 24 ) );
1521 : 1 : QCOMPARE( from3Pts.wkbType(), QgsWkbTypes::CircularStringZM );
1522 : 1 : QCOMPARE( from3Pts.numPoints(), 3 );
1523 : 1 : QCOMPARE( from3Pts.xAt( 0 ), 1.0 );
1524 : 1 : QCOMPARE( from3Pts.yAt( 0 ), 2.0 );
1525 : 1 : QCOMPARE( from3Pts.pointN( 0 ).z(), 3.0 );
1526 : 1 : QCOMPARE( from3Pts.pointN( 0 ).m(), 4.0 );
1527 : 1 : QCOMPARE( from3Pts.xAt( 1 ), 21.0 );
1528 : 1 : QCOMPARE( from3Pts.yAt( 1 ), 22.0 );
1529 : 1 : QCOMPARE( from3Pts.pointN( 1 ).z(), 23.0 );
1530 : 1 : QCOMPARE( from3Pts.pointN( 1 ).m(), 24.0 );
1531 : 1 : QCOMPARE( from3Pts.xAt( 2 ), 31.0 );
1532 : 1 : QCOMPARE( from3Pts.yAt( 2 ), 2.0 );
1533 : 1 : QCOMPARE( from3Pts.pointN( 2 ).z(), 33.0 );
1534 : 1 : QCOMPARE( from3Pts.pointN( 2 ).m(), 34.0 );
1535 : :
1536 : : //setPoints
1537 : 1 : QgsCircularString l2;
1538 : 1 : l2.setPoints( QgsPointSequence() << QgsPoint( 1.0, 2.0 ) );
1539 : 1 : QVERIFY( !l2.isEmpty() );
1540 : 1 : QCOMPARE( l2.numPoints(), 1 );
1541 : 1 : QCOMPARE( l2.vertexCount(), 1 );
1542 : 1 : QCOMPARE( l2.nCoordinates(), 1 );
1543 : 1 : QCOMPARE( l2.ringCount(), 1 );
1544 : 1 : QCOMPARE( l2.partCount(), 1 );
1545 : 1 : QVERIFY( !l2.is3D() );
1546 : 1 : QVERIFY( !l2.isMeasure() );
1547 : 1 : QCOMPARE( l2.wkbType(), QgsWkbTypes::CircularString );
1548 : 1 : QVERIFY( l2.hasCurvedSegments() );
1549 : 1 : QCOMPARE( l2.area(), 0.0 );
1550 : 1 : QCOMPARE( l2.perimeter(), 0.0 );
1551 : 1 : l2.points( pts );
1552 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1.0, 2.0 ) );
1553 : :
1554 : : //setting first vertex should set linestring z/m type
1555 : 1 : QgsCircularString l3;
1556 : 1 : l3.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) );
1557 : 1 : QVERIFY( !l3.isEmpty() );
1558 : 1 : QVERIFY( l3.is3D() );
1559 : 1 : QVERIFY( !l3.isMeasure() );
1560 : 1 : QCOMPARE( l3.wkbType(), QgsWkbTypes::CircularStringZ );
1561 : 1 : QCOMPARE( l3.wktTypeStr(), QString( "CircularStringZ" ) );
1562 : 1 : l3.points( pts );
1563 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) );
1564 : :
1565 : 1 : QgsCircularString l4;
1566 : 1 : l4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 ) );
1567 : 1 : QVERIFY( !l4.isEmpty() );
1568 : 1 : QVERIFY( !l4.is3D() );
1569 : 1 : QVERIFY( l4.isMeasure() );
1570 : 1 : QCOMPARE( l4.wkbType(), QgsWkbTypes::CircularStringM );
1571 : 1 : QCOMPARE( l4.wktTypeStr(), QString( "CircularStringM" ) );
1572 : 1 : l4.points( pts );
1573 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 ) );
1574 : :
1575 : 1 : QgsCircularString l5;
1576 : 1 : l5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
1577 : 1 : QVERIFY( !l5.isEmpty() );
1578 : 1 : QVERIFY( l5.is3D() );
1579 : 1 : QVERIFY( l5.isMeasure() );
1580 : 1 : QCOMPARE( l5.wkbType(), QgsWkbTypes::CircularStringZM );
1581 : 1 : QCOMPARE( l5.wktTypeStr(), QString( "CircularStringZM" ) );
1582 : 1 : l5.points( pts );
1583 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
1584 : :
1585 : : //clear
1586 : 1 : l5.clear();
1587 : 1 : QVERIFY( l5.isEmpty() );
1588 : 1 : QCOMPARE( l5.numPoints(), 0 );
1589 : 1 : QCOMPARE( l5.vertexCount(), 0 );
1590 : 1 : QCOMPARE( l5.nCoordinates(), 0 );
1591 : 1 : QCOMPARE( l5.ringCount(), 0 );
1592 : 1 : QCOMPARE( l5.partCount(), 0 );
1593 : 1 : QVERIFY( !l5.is3D() );
1594 : 1 : QVERIFY( !l5.isMeasure() );
1595 : 1 : QCOMPARE( l5.wkbType(), QgsWkbTypes::CircularString );
1596 : :
1597 : : //setPoints
1598 : 1 : QgsCircularString l8;
1599 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
1600 : 1 : QVERIFY( !l8.isEmpty() );
1601 : 1 : QCOMPARE( l8.numPoints(), 3 );
1602 : 1 : QCOMPARE( l8.vertexCount(), 3 );
1603 : 1 : QCOMPARE( l8.nCoordinates(), 3 );
1604 : 1 : QCOMPARE( l8.ringCount(), 1 );
1605 : 1 : QCOMPARE( l8.partCount(), 1 );
1606 : 1 : QVERIFY( !l8.is3D() );
1607 : 1 : QVERIFY( !l8.isMeasure() );
1608 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::CircularString );
1609 : 1 : QVERIFY( l8.hasCurvedSegments() );
1610 : 1 : l8.points( pts );
1611 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
1612 : :
1613 : : //setPoints with empty list, should clear linestring
1614 : 1 : l8.setPoints( QgsPointSequence() );
1615 : 1 : QVERIFY( l8.isEmpty() );
1616 : 1 : QCOMPARE( l8.numPoints(), 0 );
1617 : 1 : QCOMPARE( l8.vertexCount(), 0 );
1618 : 1 : QCOMPARE( l8.nCoordinates(), 0 );
1619 : 1 : QCOMPARE( l8.ringCount(), 0 );
1620 : 1 : QCOMPARE( l8.partCount(), 0 );
1621 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::CircularString );
1622 : 1 : l8.points( pts );
1623 : 1 : QVERIFY( pts.empty() );
1624 : :
1625 : : //setPoints with z
1626 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) );
1627 : 1 : QCOMPARE( l8.numPoints(), 2 );
1628 : 1 : QVERIFY( l8.is3D() );
1629 : 1 : QVERIFY( !l8.isMeasure() );
1630 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::CircularStringZ );
1631 : 1 : l8.points( pts );
1632 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) );
1633 : :
1634 : : //setPoints with m
1635 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) );
1636 : 1 : QCOMPARE( l8.numPoints(), 2 );
1637 : 1 : QVERIFY( !l8.is3D() );
1638 : 1 : QVERIFY( l8.isMeasure() );
1639 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::CircularStringM );
1640 : 1 : l8.points( pts );
1641 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) );
1642 : :
1643 : : //setPoints with zm
1644 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 4, 5 ) );
1645 : 1 : QCOMPARE( l8.numPoints(), 2 );
1646 : 1 : QVERIFY( l8.is3D() );
1647 : 1 : QVERIFY( l8.isMeasure() );
1648 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::CircularStringZM );
1649 : 1 : l8.points( pts );
1650 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 4, 5 ) );
1651 : :
1652 : : //setPoints with MIXED dimensionality of points
1653 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 5 ) );
1654 : 1 : QCOMPARE( l8.numPoints(), 2 );
1655 : 1 : QVERIFY( l8.is3D() );
1656 : 1 : QVERIFY( l8.isMeasure() );
1657 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::CircularStringZM );
1658 : 1 : l8.points( pts );
1659 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 0, 5 ) );
1660 : :
1661 : : //test point
1662 : 1 : QCOMPARE( l8.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) );
1663 : 1 : QCOMPARE( l8.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 2, 3, 0, 5 ) );
1664 : :
1665 : : //out of range - just want no crash here
1666 : 1 : QgsPoint bad = l8.pointN( -1 );
1667 : 1 : bad = l8.pointN( 100 );
1668 : :
1669 : : //test getters/setters
1670 : 1 : QgsCircularString l9;
1671 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
1672 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 )
1673 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ) );
1674 : 1 : QCOMPARE( l9.xAt( 0 ), 1.0 );
1675 : 1 : QCOMPARE( l9.xAt( 1 ), 11.0 );
1676 : 1 : QCOMPARE( l9.xAt( 2 ), 21.0 );
1677 : 1 : QCOMPARE( l9.xAt( -1 ), 0.0 ); //out of range
1678 : 1 : QCOMPARE( l9.xAt( 11 ), 0.0 ); //out of range
1679 : :
1680 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 51.0, 2 ) );
1681 : 1 : QCOMPARE( l9.xAt( 0 ), 51.0 );
1682 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 61.0, 12 ) );
1683 : 1 : QCOMPARE( l9.xAt( 1 ), 61.0 );
1684 : 1 : l9.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 71.0, 2 ) ); //out of range
1685 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 11 ), QgsPoint( 71.0, 2 ) ); //out of range
1686 : :
1687 : 1 : QCOMPARE( l9.yAt( 0 ), 2.0 );
1688 : 1 : QCOMPARE( l9.yAt( 1 ), 12.0 );
1689 : 1 : QCOMPARE( l9.yAt( 2 ), 22.0 );
1690 : 1 : QCOMPARE( l9.yAt( -1 ), 0.0 ); //out of range
1691 : 1 : QCOMPARE( l9.yAt( 11 ), 0.0 ); //out of range
1692 : :
1693 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 51.0, 52 ) );
1694 : 1 : QCOMPARE( l9.yAt( 0 ), 52.0 );
1695 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 61.0, 62 ) );
1696 : 1 : QCOMPARE( l9.yAt( 1 ), 62.0 );
1697 : :
1698 : 1 : QCOMPARE( l9.pointN( 0 ).z(), 3.0 );
1699 : 1 : QCOMPARE( l9.pointN( 1 ).z(), 13.0 );
1700 : 1 : QCOMPARE( l9.pointN( 2 ).z(), 23.0 );
1701 : :
1702 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 71.0, 2, 53 ) );
1703 : 1 : QCOMPARE( l9.pointN( 0 ).z(), 53.0 );
1704 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 71.0, 2, 63 ) );
1705 : 1 : QCOMPARE( l9.pointN( 1 ).z(), 63.0 );
1706 : :
1707 : 1 : QCOMPARE( l9.pointN( 0 ).m(), 4.0 );
1708 : 1 : QCOMPARE( l9.pointN( 1 ).m(), 14.0 );
1709 : 1 : QCOMPARE( l9.pointN( 2 ).m(), 24.0 );
1710 : :
1711 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 71.0, 2, 53, 54 ) );
1712 : 1 : QCOMPARE( l9.pointN( 0 ).m(), 54.0 );
1713 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 71.0, 2, 53, 64 ) );
1714 : 1 : QCOMPARE( l9.pointN( 1 ).m(), 64.0 );
1715 : :
1716 : : //check zAt/setZAt with non-3d linestring
1717 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 )
1718 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 )
1719 : 1 : << QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 24 ) );
1720 : :
1721 : : //basically we just don't want these to crash
1722 : 1 : QVERIFY( std::isnan( l9.pointN( 0 ).z() ) );
1723 : 1 : QVERIFY( std::isnan( l9.pointN( 1 ).z() ) );
1724 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 71.0, 2, 53 ) );
1725 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 71.0, 2, 63 ) );
1726 : :
1727 : : //check mAt/setMAt with non-measure linestring
1728 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
1729 : 1 : << QgsPoint( 11, 12 )
1730 : 1 : << QgsPoint( 21, 22 ) );
1731 : :
1732 : : //basically we just don't want these to crash
1733 : 1 : QVERIFY( std::isnan( l9.pointN( 0 ).m() ) );
1734 : 1 : QVERIFY( std::isnan( l9.pointN( 1 ).m() ) );
1735 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 71.0, 2, 0, 53 ) );
1736 : 1 : l9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 71.0, 2, 0, 63 ) );
1737 : :
1738 : : //equality
1739 : 1 : QgsCircularString e1;
1740 : 1 : QgsCircularString e2;
1741 : 1 : QVERIFY( e1 == e2 );
1742 : 1 : QVERIFY( !( e1 != e2 ) );
1743 : 1 : e1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) );
1744 : 1 : QVERIFY( !( e1 == e2 ) ); //different number of vertices
1745 : 1 : QVERIFY( e1 != e2 );
1746 : 1 : e2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) );
1747 : 1 : QVERIFY( e1 == e2 );
1748 : 1 : QVERIFY( !( e1 != e2 ) );
1749 : 1 : e1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 1 / 3.0, 4 / 3.0 ) );
1750 : 1 : e2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2 / 6.0, 8 / 6.0 ) );
1751 : 1 : QVERIFY( e1 == e2 ); //check non-integer equality
1752 : 1 : QVERIFY( !( e1 != e2 ) );
1753 : 1 : e1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 1 / 3.0, 4 / 3.0 ) << QgsPoint( 7, 8 ) );
1754 : 1 : e2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2 / 6.0, 8 / 6.0 ) << QgsPoint( 6, 9 ) );
1755 : 1 : QVERIFY( !( e1 == e2 ) ); //different coordinates
1756 : 1 : QVERIFY( e1 != e2 );
1757 : 1 : QgsCircularString e3;
1758 : 2 : e3.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 0 )
1759 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1 / 3.0, 4 / 3.0, 0 )
1760 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 7, 8, 0 ) );
1761 : 1 : QVERIFY( !( e1 == e3 ) ); //different dimension
1762 : 1 : QVERIFY( e1 != e3 );
1763 : 1 : QgsCircularString e4;
1764 : 2 : e4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 )
1765 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1 / 3.0, 4 / 3.0, 3 )
1766 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 7, 8, 4 ) );
1767 : 1 : QVERIFY( !( e3 == e4 ) ); //different z coordinates
1768 : 1 : QVERIFY( e3 != e4 );
1769 : 1 : QgsCircularString e5;
1770 : 2 : e5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 1 )
1771 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1 / 3.0, 4 / 3.0, 0, 2 )
1772 : 1 : << QgsPoint( QgsWkbTypes::PointM, 7, 8, 0, 3 ) );
1773 : 1 : QgsCircularString e6;
1774 : 2 : e6.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 11 )
1775 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1 / 3.0, 4 / 3.0, 0, 12 )
1776 : 1 : << QgsPoint( QgsWkbTypes::PointM, 7, 8, 0, 13 ) );
1777 : 1 : QVERIFY( !( e5 == e6 ) ); //different m values
1778 : 1 : QVERIFY( e5 != e6 );
1779 : :
1780 : 1 : QVERIFY( e6 != QgsLineString() );
1781 : :
1782 : : //isClosed
1783 : 1 : QgsCircularString l11;
1784 : 1 : QVERIFY( !l11.isClosed() );
1785 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
1786 : 1 : << QgsPoint( 11, 2 )
1787 : 1 : << QgsPoint( 11, 22 )
1788 : 1 : << QgsPoint( 1, 22 ) );
1789 : 1 : QVERIFY( !l11.isClosed() );
1790 : 1 : QCOMPARE( l11.numPoints(), 4 );
1791 : 1 : QCOMPARE( l11.area(), 0.0 );
1792 : 1 : QCOMPARE( l11.perimeter(), 0.0 );
1793 : :
1794 : : //test that m values aren't considered when testing for closedness
1795 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 )
1796 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 2, 0, 4 )
1797 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 22, 0, 5 )
1798 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 6 ) );
1799 : 1 : QVERIFY( l11.isClosed() );
1800 : :
1801 : : //polygonf
1802 : 1 : QgsCircularString l13;
1803 : 2 : l13.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
1804 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
1805 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 ) );
1806 : :
1807 : 1 : QPolygonF poly = l13.asQPolygonF();
1808 : 1 : QCOMPARE( poly.count(), 181 );
1809 : 1 : QCOMPARE( poly.at( 0 ).x(), 1.0 );
1810 : 1 : QCOMPARE( poly.at( 0 ).y(), 2.0 );
1811 : 1 : QCOMPARE( poly.at( 180 ).x(), 11.0 );
1812 : 1 : QCOMPARE( poly.at( 180 ).y(), 22.0 );
1813 : :
1814 : : // clone tests
1815 : 1 : QgsCircularString l14;
1816 : 2 : l14.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
1817 : 1 : << QgsPoint( 11, 2 )
1818 : 1 : << QgsPoint( 11, 22 )
1819 : 1 : << QgsPoint( 1, 22 ) );
1820 : 1 : std::unique_ptr<QgsCircularString> cloned( l14.clone() );
1821 : 1 : QCOMPARE( cloned->numPoints(), 4 );
1822 : 1 : QCOMPARE( cloned->vertexCount(), 4 );
1823 : 1 : QCOMPARE( cloned->ringCount(), 1 );
1824 : 1 : QCOMPARE( cloned->partCount(), 1 );
1825 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::CircularString );
1826 : 1 : QVERIFY( !cloned->is3D() );
1827 : 1 : QVERIFY( !cloned->isMeasure() );
1828 : 1 : QCOMPARE( cloned->pointN( 0 ), l14.pointN( 0 ) );
1829 : 1 : QCOMPARE( cloned->pointN( 1 ), l14.pointN( 1 ) );
1830 : 1 : QCOMPARE( cloned->pointN( 2 ), l14.pointN( 2 ) );
1831 : 1 : QCOMPARE( cloned->pointN( 3 ), l14.pointN( 3 ) );
1832 : :
1833 : : //clone with Z/M
1834 : 2 : l14.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
1835 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
1836 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
1837 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
1838 : 1 : cloned.reset( l14.clone() );
1839 : 1 : QCOMPARE( cloned->numPoints(), 4 );
1840 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::CircularStringZM );
1841 : 1 : QVERIFY( cloned->is3D() );
1842 : 1 : QVERIFY( cloned->isMeasure() );
1843 : 1 : QCOMPARE( cloned->pointN( 0 ), l14.pointN( 0 ) );
1844 : 1 : QCOMPARE( cloned->pointN( 1 ), l14.pointN( 1 ) );
1845 : 1 : QCOMPARE( cloned->pointN( 2 ), l14.pointN( 2 ) );
1846 : 1 : QCOMPARE( cloned->pointN( 3 ), l14.pointN( 3 ) );
1847 : :
1848 : : //clone an empty line
1849 : 1 : l14.clear();
1850 : 1 : cloned.reset( l14.clone() );
1851 : 1 : QVERIFY( cloned->isEmpty() );
1852 : 1 : QCOMPARE( cloned->numPoints(), 0 );
1853 : 1 : QVERIFY( !cloned->is3D() );
1854 : 1 : QVERIFY( !cloned->isMeasure() );
1855 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::CircularString );
1856 : :
1857 : : //segmentize tests
1858 : 1 : QgsCircularString toSegment;
1859 : 2 : toSegment.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
1860 : 1 : << QgsPoint( 11, 10 ) << QgsPoint( 21, 2 ) );
1861 : 1 : std::unique_ptr<QgsLineString> segmentized( static_cast< QgsLineString * >( toSegment.segmentize() ) );
1862 : 1 : QCOMPARE( segmentized->numPoints(), 156 );
1863 : 1 : QCOMPARE( segmentized->vertexCount(), 156 );
1864 : 1 : QCOMPARE( segmentized->ringCount(), 1 );
1865 : 1 : QCOMPARE( segmentized->partCount(), 1 );
1866 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineString );
1867 : 1 : QVERIFY( !segmentized->is3D() );
1868 : 1 : QVERIFY( !segmentized->isMeasure() );
1869 : 1 : QCOMPARE( segmentized->pointN( 0 ), toSegment.pointN( 0 ) );
1870 : 1 : QCOMPARE( segmentized->pointN( segmentized->numPoints() - 1 ), toSegment.pointN( toSegment.numPoints() - 1 ) );
1871 : :
1872 : : //segmentize with Z/M
1873 : 2 : toSegment.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
1874 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 10, 11, 14 )
1875 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 2, 21, 24 ) );
1876 : 1 : segmentized.reset( static_cast< QgsLineString * >( toSegment.segmentize() ) );
1877 : 1 : QCOMPARE( segmentized->numPoints(), 156 );
1878 : 1 : QCOMPARE( segmentized->vertexCount(), 156 );
1879 : 1 : QCOMPARE( segmentized->ringCount(), 1 );
1880 : 1 : QCOMPARE( segmentized->partCount(), 1 );
1881 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineStringZM );
1882 : 1 : QVERIFY( segmentized->is3D() );
1883 : 1 : QVERIFY( segmentized->isMeasure() );
1884 : 1 : QCOMPARE( segmentized->pointN( 0 ), toSegment.pointN( 0 ) );
1885 : 1 : QCOMPARE( segmentized->pointN( segmentized->numPoints() - 1 ), toSegment.pointN( toSegment.numPoints() - 1 ) );
1886 : :
1887 : : //segmentize an empty line
1888 : 1 : toSegment.clear();
1889 : 1 : segmentized.reset( static_cast< QgsLineString * >( toSegment.segmentize() ) );
1890 : 1 : QVERIFY( segmentized->isEmpty() );
1891 : 1 : QCOMPARE( segmentized->numPoints(), 0 );
1892 : 1 : QVERIFY( !segmentized->is3D() );
1893 : 1 : QVERIFY( !segmentized->isMeasure() );
1894 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineString );
1895 : :
1896 : : //to/from WKB
1897 : 1 : QgsCircularString l15;
1898 : 2 : l15.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
1899 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
1900 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
1901 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
1902 : 1 : QByteArray wkb15 = l15.asWkb();
1903 : 1 : QCOMPARE( wkb15.size(), l15.wkbSize() );
1904 : 1 : QgsCircularString l16;
1905 : 1 : QgsConstWkbPtr wkb15ptr( wkb15 );
1906 : 1 : l16.fromWkb( wkb15ptr );
1907 : 1 : QCOMPARE( l16.numPoints(), 4 );
1908 : 1 : QCOMPARE( l16.vertexCount(), 4 );
1909 : 1 : QCOMPARE( l16.nCoordinates(), 4 );
1910 : 1 : QCOMPARE( l16.ringCount(), 1 );
1911 : 1 : QCOMPARE( l16.partCount(), 1 );
1912 : 1 : QCOMPARE( l16.wkbType(), QgsWkbTypes::CircularStringZM );
1913 : 1 : QVERIFY( l16.is3D() );
1914 : 1 : QVERIFY( l16.isMeasure() );
1915 : 1 : QCOMPARE( l16.pointN( 0 ), l15.pointN( 0 ) );
1916 : 1 : QCOMPARE( l16.pointN( 1 ), l15.pointN( 1 ) );
1917 : 1 : QCOMPARE( l16.pointN( 2 ), l15.pointN( 2 ) );
1918 : 1 : QCOMPARE( l16.pointN( 3 ), l15.pointN( 3 ) );
1919 : :
1920 : : //bad WKB - check for no crash
1921 : 1 : l16.clear();
1922 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
1923 : 1 : QVERIFY( !l16.fromWkb( nullPtr ) );
1924 : 1 : QCOMPARE( l16.wkbType(), QgsWkbTypes::CircularString );
1925 : 1 : QgsPoint point( 1, 2 );
1926 : 1 : QByteArray wkb16 = point.asWkb();
1927 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
1928 : 1 : QVERIFY( !l16.fromWkb( wkb16ptr ) );
1929 : 1 : QCOMPARE( l16.wkbType(), QgsWkbTypes::CircularString );
1930 : :
1931 : : //to/from WKT
1932 : 1 : QgsCircularString l17;
1933 : 2 : l17.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
1934 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
1935 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
1936 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
1937 : :
1938 : 1 : QString wkt = l17.asWkt();
1939 : 1 : QVERIFY( !wkt.isEmpty() );
1940 : 1 : QgsCircularString l18;
1941 : 1 : QVERIFY( l18.fromWkt( wkt ) );
1942 : 1 : QCOMPARE( l18.numPoints(), 4 );
1943 : 1 : QCOMPARE( l18.wkbType(), QgsWkbTypes::CircularStringZM );
1944 : 1 : QVERIFY( l18.is3D() );
1945 : 1 : QVERIFY( l18.isMeasure() );
1946 : 1 : QCOMPARE( l18.pointN( 0 ), l17.pointN( 0 ) );
1947 : 1 : QCOMPARE( l18.pointN( 1 ), l17.pointN( 1 ) );
1948 : 1 : QCOMPARE( l18.pointN( 2 ), l17.pointN( 2 ) );
1949 : 1 : QCOMPARE( l18.pointN( 3 ), l17.pointN( 3 ) );
1950 : :
1951 : : //bad WKT
1952 : 1 : QVERIFY( !l18.fromWkt( "Polygon()" ) );
1953 : 1 : QVERIFY( l18.isEmpty() );
1954 : 1 : QCOMPARE( l18.numPoints(), 0 );
1955 : 1 : QVERIFY( !l18.is3D() );
1956 : 1 : QVERIFY( !l18.isMeasure() );
1957 : 1 : QCOMPARE( l18.wkbType(), QgsWkbTypes::CircularString );
1958 : :
1959 : : //asGML2
1960 : 1 : QgsCircularString exportLine;
1961 : 2 : exportLine.setPoints( QgsPointSequence() << QgsPoint( 31, 32 )
1962 : 1 : << QgsPoint( 41, 42 )
1963 : 1 : << QgsPoint( 51, 52 ) );
1964 : 1 : QgsCircularString exportLineFloat;
1965 : 2 : exportLineFloat.setPoints( QgsPointSequence() << QgsPoint( 1 / 3.0, 2 / 3.0 )
1966 : 1 : << QgsPoint( 1 + 1 / 3.0, 1 + 2 / 3.0 )
1967 : 1 : << QgsPoint( 2 + 1 / 3.0, 2 + 2 / 3.0 ) );
1968 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
1969 : 2 : QString expectedGML2( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">31,32 41,42 51,52</coordinates></LineString>" ) );
1970 : 3 : QGSCOMPAREGML( elemToString( exportLine.asGml2( doc ) ), expectedGML2 );
1971 : 2 : QString expectedGML2prec3( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.333,0.667 1.333,1.667 2.333,2.667</coordinates></LineString>" ) );
1972 : 3 : QGSCOMPAREGML( elemToString( exportLineFloat.asGml2( doc, 3 ) ), expectedGML2prec3 );
1973 : 2 : QString expectedGML2empty( QStringLiteral( "<LineString xmlns=\"gml\"/>" ) );
1974 : 3 : QGSCOMPAREGML( elemToString( QgsCircularString().asGml2( doc ) ), expectedGML2empty );
1975 : :
1976 : : //asGML3
1977 : 2 : QString expectedGML3( QStringLiteral( "<Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">31 32 41 42 51 52</posList></ArcString></segments></Curve>" ) );
1978 : 1 : QCOMPARE( elemToString( exportLine.asGml3( doc ) ), expectedGML3 );
1979 : 2 : QString expectedGML3prec3( QStringLiteral( "<Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0.333 0.667 1.333 1.667 2.333 2.667</posList></ArcString></segments></Curve>" ) );
1980 : 1 : QCOMPARE( elemToString( exportLineFloat.asGml3( doc, 3 ) ), expectedGML3prec3 );
1981 : 2 : QString expectedGML3empty( QStringLiteral( "<Curve xmlns=\"gml\"/>" ) );
1982 : 3 : QGSCOMPAREGML( elemToString( QgsCircularString().asGml3( doc ) ), expectedGML3empty );
1983 : :
1984 : : //asJSON
1985 : 2 : QString expectedJson( QStringLiteral( "{\"coordinates\":[[31.0,32.0],[41.0,42.0],[51.0,52.0]],\"type\":\"LineString\"}" ) );
1986 : 1 : QCOMPARE( exportLine.asJson(), expectedJson );
1987 : 2 : QString expectedJsonPrec3( QStringLiteral( "{\"coordinates\":[[0.333,0.667],[1.333,1.667],[2.333,2.667]],\"type\":\"LineString\"}" ) );
1988 : 1 : QCOMPARE( exportLineFloat.asJson( 3 ), expectedJsonPrec3 );
1989 : :
1990 : : //asKML
1991 : 2 : QString expectedKml( QStringLiteral( "<LineString><altitudeMode>clampToGround</altitudeMode><coordinates>31,32,0 41,42,0 51,52,0</coordinates></LineString>" ) );
1992 : 1 : QCOMPARE( exportLine.asKml(), expectedKml );
1993 : 2 : QString expectedKmlPrec3( QStringLiteral( "<LineString><altitudeMode>clampToGround</altitudeMode><coordinates>0.333,0.667,0 1.333,1.667,0 2.333,2.667,0</coordinates></LineString>" ) );
1994 : 1 : QCOMPARE( exportLineFloat.asKml( 3 ), expectedKmlPrec3 );
1995 : :
1996 : : //length
1997 : 1 : QgsCircularString l19;
1998 : 1 : QCOMPARE( l19.length(), 0.0 );
1999 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
2000 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
2001 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2002 : 1 : QGSCOMPARENEAR( l19.length(), 26.1433, 0.001 );
2003 : :
2004 : : //startPoint
2005 : 1 : QCOMPARE( l19.startPoint(), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 ) );
2006 : :
2007 : : //endPoint
2008 : 1 : QCOMPARE( l19.endPoint(), QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2009 : :
2010 : : //bad start/end points. Test that this doesn't crash.
2011 : 1 : l19.clear();
2012 : 1 : QVERIFY( l19.startPoint().isEmpty() );
2013 : 1 : QVERIFY( l19.endPoint().isEmpty() );
2014 : :
2015 : : //curveToLine - no segmentation required, so should return a clone
2016 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
2017 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
2018 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2019 : 1 : segmentized.reset( l19.curveToLine() );
2020 : 1 : QCOMPARE( segmentized->numPoints(), 181 );
2021 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineStringZM );
2022 : 1 : QVERIFY( segmentized->is3D() );
2023 : 1 : QVERIFY( segmentized->isMeasure() );
2024 : 1 : QCOMPARE( segmentized->pointN( 0 ), l19.pointN( 0 ) );
2025 : 1 : QCOMPARE( segmentized->pointN( segmentized->numPoints() - 1 ), l19.pointN( l19.numPoints() - 1 ) );
2026 : :
2027 : : // points
2028 : 1 : QgsCircularString l20;
2029 : 1 : QgsPointSequence points;
2030 : 1 : l20.points( points );
2031 : 1 : QVERIFY( l20.isEmpty() );
2032 : 2 : l20.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
2033 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
2034 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2035 : 1 : l20.points( points );
2036 : 1 : QCOMPARE( points.count(), 3 );
2037 : 1 : QCOMPARE( points.at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 ) );
2038 : 1 : QCOMPARE( points.at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 ) );
2039 : 1 : QCOMPARE( points.at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2040 : :
2041 : : //CRS transform
2042 : 2 : QgsCoordinateReferenceSystem sourceSrs( QStringLiteral( "EPSG:3994" ) );
2043 : 2 : QgsCoordinateReferenceSystem destSrs( QStringLiteral( "EPSG:4202" ) );// want a transform with ellipsoid change
2044 : 1 : QgsCoordinateTransform tr( sourceSrs, destSrs, QgsProject::instance() );
2045 : :
2046 : : // 2d CRS transform
2047 : 1 : QgsCircularString l21;
2048 : 2 : l21.setPoints( QgsPointSequence() << QgsPoint( 6374985, -3626584 )
2049 : 1 : << QgsPoint( 6474985, -3526584 ) );
2050 : 1 : l21.transform( tr, QgsCoordinateTransform::ForwardTransform );
2051 : 1 : QGSCOMPARENEAR( l21.pointN( 0 ).x(), 175.771, 0.001 );
2052 : 1 : QGSCOMPARENEAR( l21.pointN( 0 ).y(), -39.724, 0.001 );
2053 : 1 : QGSCOMPARENEAR( l21.pointN( 1 ).x(), 176.959, 0.001 );
2054 : 1 : QGSCOMPARENEAR( l21.pointN( 1 ).y(), -38.7999, 0.001 );
2055 : 1 : QGSCOMPARENEAR( l21.boundingBox().xMinimum(), 175.771, 0.001 );
2056 : 1 : QGSCOMPARENEAR( l21.boundingBox().yMinimum(), -39.724, 0.001 );
2057 : 1 : QGSCOMPARENEAR( l21.boundingBox().xMaximum(), 176.959, 0.001 );
2058 : 1 : QGSCOMPARENEAR( l21.boundingBox().yMaximum(), -38.7999, 0.001 );
2059 : :
2060 : : //3d CRS transform
2061 : 1 : QgsCircularString l22;
2062 : 2 : l22.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 )
2063 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6474985, -3526584, 3, 4 ) );
2064 : 1 : l22.transform( tr, QgsCoordinateTransform::ForwardTransform );
2065 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).x(), 175.771, 0.001 );
2066 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).y(), -39.724, 0.001 );
2067 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).z(), 1.0, 0.001 );
2068 : 1 : QCOMPARE( l22.pointN( 0 ).m(), 2.0 );
2069 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).x(), 176.959, 0.001 );
2070 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).y(), -38.7999, 0.001 );
2071 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).z(), 3.0, 0.001 );
2072 : 1 : QCOMPARE( l22.pointN( 1 ).m(), 4.0 );
2073 : :
2074 : : //reverse transform
2075 : 1 : l22.transform( tr, QgsCoordinateTransform::ReverseTransform );
2076 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).x(), 6374985, 0.01 );
2077 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).y(), -3626584, 0.01 );
2078 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).z(), 1, 0.001 );
2079 : 1 : QCOMPARE( l22.pointN( 0 ).m(), 2.0 );
2080 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).x(), 6474985, 0.01 );
2081 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).y(), -3526584, 0.01 );
2082 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).z(), 3, 0.001 );
2083 : 1 : QCOMPARE( l22.pointN( 1 ).m(), 4.0 );
2084 : :
2085 : : #if PROJ_VERSION_MAJOR<6 // note - z value transform doesn't currently work with proj 6+, because we don't yet support compound CRS definitions
2086 : : //z value transform
2087 : : l22.transform( tr, QgsCoordinateTransform::ForwardTransform, true );
2088 : : QGSCOMPARENEAR( l22.pointN( 0 ).z(), -19.249066, 0.001 );
2089 : : QGSCOMPARENEAR( l22.pointN( 1 ).z(), -21.092128, 0.001 );
2090 : : l22.transform( tr, QgsCoordinateTransform::ReverseTransform, true );
2091 : : QGSCOMPARENEAR( l22.pointN( 0 ).z(), 1.0, 0.001 );
2092 : : QGSCOMPARENEAR( l22.pointN( 1 ).z(), 3.0, 0.001 );
2093 : : #endif
2094 : :
2095 : : //QTransform transform
2096 : 1 : QTransform qtr = QTransform::fromScale( 2, 3 );
2097 : 1 : QgsCircularString l23;
2098 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
2099 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2100 : 1 : l23.transform( qtr );
2101 : 1 : QCOMPARE( l23.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 2, 6, 3, 4 ) );
2102 : 1 : QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 22, 36, 13, 14 ) );
2103 : 1 : QCOMPARE( l23.boundingBox(), QgsRectangle( 2, 6, 22, 36 ) );
2104 : :
2105 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
2106 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2107 : 1 : l23.transform( QTransform::fromScale( 1, 1 ), 3, 2, 4, 3 );
2108 : 1 : QCOMPARE( l23.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 9, 16 ) );
2109 : 1 : QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 29, 46 ) );
2110 : :
2111 : : //insert vertex
2112 : : //cannot insert vertex in empty line
2113 : 1 : QgsCircularString l24;
2114 : 1 : QVERIFY( !l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
2115 : 1 : QCOMPARE( l24.numPoints(), 0 );
2116 : :
2117 : : //2d line
2118 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
2119 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
2120 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 4.0, 7.0 ) ) );
2121 : 1 : QCOMPARE( l24.numPoints(), 5 );
2122 : 1 : QVERIFY( !l24.is3D() );
2123 : 1 : QVERIFY( !l24.isMeasure() );
2124 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::CircularString );
2125 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
2126 : 1 : QCOMPARE( l24.pointN( 1 ), QgsPoint( 4.0, 7.0 ) );
2127 : 1 : QGSCOMPARENEAR( l24.pointN( 2 ).x(), 7.192236, 0.01 );
2128 : 1 : QGSCOMPARENEAR( l24.pointN( 2 ).y(), 9.930870, 0.01 );
2129 : 1 : QCOMPARE( l24.pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
2130 : 1 : QCOMPARE( l24.pointN( 4 ), QgsPoint( 1.0, 22.0 ) );
2131 : :
2132 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 8.0, 9.0 ) ) );
2133 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 18.0, 16.0 ) ) );
2134 : 1 : QCOMPARE( l24.numPoints(), 9 );
2135 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
2136 : 1 : QGSCOMPARENEAR( l24.pointN( 1 ).x(), 4.363083, 0.01 );
2137 : 1 : QGSCOMPARENEAR( l24.pointN( 1 ).y(), 5.636917, 0.01 );
2138 : 1 : QCOMPARE( l24.pointN( 2 ), QgsPoint( 8.0, 9.0 ) );
2139 : 1 : QCOMPARE( l24.pointN( 3 ), QgsPoint( 18.0, 16.0 ) );
2140 : 1 : QGSCOMPARENEAR( l24.pointN( 4 ).x(), 5.876894, 0.01 );
2141 : 1 : QGSCOMPARENEAR( l24.pointN( 4 ).y(), 8.246211, 0.01 );
2142 : 1 : QCOMPARE( l24.pointN( 5 ), QgsPoint( 4.0, 7.0 ) );
2143 : 1 : QGSCOMPARENEAR( l24.pointN( 6 ).x(), 7.192236, 0.01 );
2144 : 1 : QGSCOMPARENEAR( l24.pointN( 6 ).y(), 9.930870, 0.01 );
2145 : 1 : QCOMPARE( l24.pointN( 7 ), QgsPoint( 11.0, 12.0 ) );
2146 : 1 : QCOMPARE( l24.pointN( 8 ), QgsPoint( 1.0, 22.0 ) );
2147 : :
2148 : : //insert vertex at end
2149 : 1 : QVERIFY( !l24.insertVertex( QgsVertexId( 0, 0, 9 ), QgsPoint( 31.0, 32.0 ) ) );
2150 : :
2151 : : //insert vertex past end
2152 : 1 : QVERIFY( !l24.insertVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 41.0, 42.0 ) ) );
2153 : 1 : QCOMPARE( l24.numPoints(), 9 );
2154 : :
2155 : : //insert vertex before start
2156 : 1 : QVERIFY( !l24.insertVertex( QgsVertexId( 0, 0, -18 ), QgsPoint( 41.0, 42.0 ) ) );
2157 : 1 : QCOMPARE( l24.numPoints(), 9 );
2158 : :
2159 : : //insert 4d vertex in 4d line
2160 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
2161 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
2162 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2163 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) ) );
2164 : 1 : QCOMPARE( l24.numPoints(), 5 );
2165 : 1 : QCOMPARE( l24.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2166 : :
2167 : : //insert 2d vertex in 4d line
2168 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 101, 102 ) ) );
2169 : 1 : QCOMPARE( l24.numPoints(), 7 );
2170 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::CircularStringZM );
2171 : 1 : QCOMPARE( l24.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 101, 102 ) );
2172 : :
2173 : : //insert 4d vertex in 2d line
2174 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
2175 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
2176 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 2, 4, 103, 104 ) ) );
2177 : 1 : QCOMPARE( l24.numPoints(), 5 );
2178 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::CircularString );
2179 : 1 : QCOMPARE( l24.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 2, 4 ) );
2180 : :
2181 : : //move vertex
2182 : :
2183 : : //empty line
2184 : 1 : QgsCircularString l25;
2185 : 1 : QVERIFY( !l25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
2186 : 1 : QVERIFY( l25.isEmpty() );
2187 : :
2188 : : //valid line
2189 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
2190 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
2191 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
2192 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
2193 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
2194 : 1 : QCOMPARE( l25.pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
2195 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
2196 : 1 : QCOMPARE( l25.pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
2197 : :
2198 : : //out of range
2199 : 1 : QVERIFY( !l25.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
2200 : 1 : QVERIFY( !l25.moveVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
2201 : 1 : QCOMPARE( l25.pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
2202 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
2203 : 1 : QCOMPARE( l25.pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
2204 : :
2205 : : //move 4d point in 4d line
2206 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
2207 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
2208 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
2209 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 7, 12, 13 ) ) );
2210 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 7, 12, 13 ) );
2211 : :
2212 : : //move 2d point in 4d line, existing z/m should be maintained
2213 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 34, 35 ) ) );
2214 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 34, 35, 12, 13 ) );
2215 : :
2216 : : //move 4d point in 2d line
2217 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
2218 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
2219 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 3, 4, 2, 3 ) ) );
2220 : 1 : QCOMPARE( l25.pointN( 0 ), QgsPoint( 3, 4 ) );
2221 : :
2222 : :
2223 : : //delete vertex
2224 : :
2225 : : //empty line
2226 : 1 : QgsCircularString l26;
2227 : 1 : QVERIFY( l26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
2228 : 1 : QVERIFY( l26.isEmpty() );
2229 : :
2230 : : //valid line
2231 : 2 : l26.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
2232 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
2233 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 )
2234 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 31, 32, 6, 7 ) );
2235 : : //out of range vertices
2236 : 1 : QVERIFY( !l26.deleteVertex( QgsVertexId( 0, 0, -1 ) ) );
2237 : 1 : QVERIFY( !l26.deleteVertex( QgsVertexId( 0, 0, 100 ) ) );
2238 : :
2239 : : //valid vertices
2240 : 1 : QVERIFY( l26.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
2241 : 1 : QCOMPARE( l26.numPoints(), 2 );
2242 : 1 : QCOMPARE( l26.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
2243 : 1 : QCOMPARE( l26.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 31, 32, 6, 7 ) );
2244 : :
2245 : : //removing the next vertex removes all remaining vertices
2246 : 1 : QVERIFY( l26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
2247 : 1 : QCOMPARE( l26.numPoints(), 0 );
2248 : 1 : QVERIFY( l26.isEmpty() );
2249 : 1 : QVERIFY( l26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
2250 : 1 : QVERIFY( l26.isEmpty() );
2251 : :
2252 : : //reversed
2253 : 1 : QgsCircularString l27;
2254 : 1 : std::unique_ptr< QgsCircularString > reversed( l27.reversed() );
2255 : 1 : QVERIFY( reversed->isEmpty() );
2256 : 2 : l27.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
2257 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
2258 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
2259 : 1 : reversed.reset( l27.reversed() );
2260 : 1 : QCOMPARE( reversed->numPoints(), 3 );
2261 : 1 : QCOMPARE( reversed->wkbType(), QgsWkbTypes::CircularStringZM );
2262 : 1 : QVERIFY( reversed->is3D() );
2263 : 1 : QVERIFY( reversed->isMeasure() );
2264 : 1 : QCOMPARE( reversed->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
2265 : 1 : QCOMPARE( reversed->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
2266 : 1 : QCOMPARE( reversed->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
2267 : :
2268 : : //addZValue
2269 : :
2270 : 1 : QgsCircularString l28;
2271 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::CircularString );
2272 : 1 : QVERIFY( l28.addZValue() );
2273 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::CircularStringZ );
2274 : 1 : l28.clear();
2275 : 1 : QVERIFY( l28.addZValue() );
2276 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::CircularStringZ );
2277 : : //2d line
2278 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
2279 : 1 : QVERIFY( l28.addZValue( 2 ) );
2280 : 1 : QVERIFY( l28.is3D() );
2281 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::CircularStringZ );
2282 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ) );
2283 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 2 ) );
2284 : 1 : QVERIFY( !l28.addZValue( 4 ) ); //already has z value, test that existing z is unchanged
2285 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ) );
2286 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 2 ) );
2287 : : //linestring with m
2288 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) );
2289 : 1 : QVERIFY( l28.addZValue( 5 ) );
2290 : 1 : QVERIFY( l28.is3D() );
2291 : 1 : QVERIFY( l28.isMeasure() );
2292 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::CircularStringZM );
2293 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 5, 3 ) );
2294 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 5, 4 ) );
2295 : :
2296 : : //addMValue
2297 : :
2298 : 1 : QgsCircularString l29;
2299 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::CircularString );
2300 : 1 : QVERIFY( l29.addMValue() );
2301 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::CircularStringM );
2302 : 1 : l29.clear();
2303 : 1 : QVERIFY( l29.addMValue() );
2304 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::CircularStringM );
2305 : : //2d line
2306 : 1 : l29.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
2307 : 1 : QVERIFY( l29.addMValue( 2 ) );
2308 : 1 : QVERIFY( !l29.is3D() );
2309 : 1 : QVERIFY( l29.isMeasure() );
2310 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::CircularStringM );
2311 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 2 ) );
2312 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 2 ) );
2313 : 1 : QVERIFY( !l29.addMValue( 4 ) ); //already has m value, test that existing m is unchanged
2314 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 2 ) );
2315 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 2 ) );
2316 : : //linestring with z
2317 : 1 : l29.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 4 ) );
2318 : 1 : QVERIFY( l29.addMValue( 5 ) );
2319 : 1 : QVERIFY( l29.is3D() );
2320 : 1 : QVERIFY( l29.isMeasure() );
2321 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::CircularStringZM );
2322 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 5 ) );
2323 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
2324 : :
2325 : : //dropZValue
2326 : 1 : QgsCircularString l28d;
2327 : 1 : QVERIFY( !l28d.dropZValue() );
2328 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
2329 : 1 : QVERIFY( !l28d.dropZValue() );
2330 : 1 : l28d.addZValue( 1.0 );
2331 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringZ );
2332 : 1 : QVERIFY( l28d.is3D() );
2333 : 1 : QVERIFY( l28d.dropZValue() );
2334 : 1 : QVERIFY( !l28d.is3D() );
2335 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularString );
2336 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
2337 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
2338 : 1 : QVERIFY( !l28d.dropZValue() ); //already dropped
2339 : : //linestring with m
2340 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) );
2341 : 1 : QVERIFY( l28d.dropZValue() );
2342 : 1 : QVERIFY( !l28d.is3D() );
2343 : 1 : QVERIFY( l28d.isMeasure() );
2344 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringM );
2345 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
2346 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) );
2347 : :
2348 : : //dropMValue
2349 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
2350 : 1 : QVERIFY( !l28d.dropMValue() );
2351 : 1 : l28d.addMValue( 1.0 );
2352 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringM );
2353 : 1 : QVERIFY( l28d.isMeasure() );
2354 : 1 : QVERIFY( l28d.dropMValue() );
2355 : 1 : QVERIFY( !l28d.isMeasure() );
2356 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularString );
2357 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
2358 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
2359 : 1 : QVERIFY( !l28d.dropMValue() ); //already dropped
2360 : : //linestring with z
2361 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) );
2362 : 1 : QVERIFY( l28d.dropMValue() );
2363 : 1 : QVERIFY( !l28d.isMeasure() );
2364 : 1 : QVERIFY( l28d.is3D() );
2365 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringZ );
2366 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3, 0 ) );
2367 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 3, 0 ) );
2368 : :
2369 : : //convertTo
2370 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
2371 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::CircularString ) );
2372 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularString );
2373 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::CircularStringZ ) );
2374 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringZ );
2375 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2 ) );
2376 : :
2377 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::CircularStringZM ) );
2378 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringZM );
2379 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2 ) );
2380 : 1 : l28d.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 1, 2, 5 ) );
2381 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 5.0 ) );
2382 : : //l28d.setMAt( 0, 6.0 );
2383 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::CircularStringM ) );
2384 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularStringM );
2385 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2 ) );
2386 : 1 : l28d.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 1, 2, 0, 6 ) );
2387 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0.0, 6.0 ) );
2388 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::CircularString ) );
2389 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::CircularString );
2390 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( 1, 2 ) );
2391 : 1 : QVERIFY( !l28d.convertTo( QgsWkbTypes::Polygon ) );
2392 : :
2393 : : //isRing
2394 : 1 : QgsCircularString l30;
2395 : 1 : QVERIFY( !l30.isRing() );
2396 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 2 ) );
2397 : 1 : QVERIFY( !l30.isRing() ); //<4 points
2398 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 31, 32 ) );
2399 : 1 : QVERIFY( !l30.isRing() ); //not closed
2400 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
2401 : 1 : QVERIFY( l30.isRing() );
2402 : :
2403 : : //coordinateSequence
2404 : 1 : QgsCircularString l31;
2405 : 1 : QgsCoordinateSequence coords = l31.coordinateSequence();
2406 : 1 : QCOMPARE( coords.count(), 1 );
2407 : 1 : QCOMPARE( coords.at( 0 ).count(), 1 );
2408 : 1 : QVERIFY( coords.at( 0 ).at( 0 ).isEmpty() );
2409 : 2 : l31.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
2410 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
2411 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
2412 : 1 : coords = l31.coordinateSequence();
2413 : 1 : QCOMPARE( coords.count(), 1 );
2414 : 1 : QCOMPARE( coords.at( 0 ).count(), 1 );
2415 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).count(), 3 );
2416 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
2417 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
2418 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
2419 : :
2420 : : //nextVertex
2421 : :
2422 : 1 : QgsCircularString l32;
2423 : 1 : QgsVertexId v;
2424 : 1 : QgsPoint p;
2425 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2426 : 1 : v = QgsVertexId( 0, 0, -2 );
2427 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2428 : 1 : v = QgsVertexId( 0, 0, 10 );
2429 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2430 : :
2431 : : //CircularString
2432 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
2433 : 1 : v = QgsVertexId( 0, 0, 2 ); //out of range
2434 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2435 : 1 : v = QgsVertexId( 0, 0, -5 );
2436 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2437 : 1 : v = QgsVertexId( 0, 0, -1 );
2438 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2439 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
2440 : 1 : QCOMPARE( p, QgsPoint( 1, 2 ) );
2441 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2442 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2443 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
2444 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2445 : 1 : v = QgsVertexId( 0, 1, 0 );
2446 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2447 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 1 ) ); //test that ring number is maintained
2448 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
2449 : 1 : v = QgsVertexId( 1, 0, 0 );
2450 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2451 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 1 ) ); //test that part number is maintained
2452 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
2453 : :
2454 : : //CircularStringZ
2455 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
2456 : 1 : v = QgsVertexId( 0, 0, -1 );
2457 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2458 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
2459 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
2460 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2461 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2462 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
2463 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2464 : : //CircularStringM
2465 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
2466 : 1 : v = QgsVertexId( 0, 0, -1 );
2467 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2468 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
2469 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
2470 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2471 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2472 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
2473 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2474 : : //CircularStringZM
2475 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2476 : 1 : v = QgsVertexId( 0, 0, -1 );
2477 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2478 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
2479 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
2480 : 1 : QVERIFY( l32.nextVertex( v, p ) );
2481 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2482 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2483 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
2484 : :
2485 : : //vertexAt and pointAt
2486 : 1 : QgsCircularString l33;
2487 : 1 : l33.vertexAt( QgsVertexId( 0, 0, -10 ) ); //out of bounds, check for no crash
2488 : 1 : l33.vertexAt( QgsVertexId( 0, 0, 10 ) ); //out of bounds, check for no crash
2489 : : QgsVertexId::VertexType type;
2490 : 1 : QVERIFY( !l33.pointAt( -10, p, type ) );
2491 : 1 : QVERIFY( !l33.pointAt( 10, p, type ) );
2492 : : //CircularString
2493 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
2494 : 1 : l33.vertexAt( QgsVertexId( 0, 0, -10 ) );
2495 : 1 : l33.vertexAt( QgsVertexId( 0, 0, 10 ) ); //out of bounds, check for no crash
2496 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
2497 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
2498 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 1, 22 ) );
2499 : 1 : QVERIFY( !l33.pointAt( -10, p, type ) );
2500 : 1 : QVERIFY( !l33.pointAt( 10, p, type ) );
2501 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
2502 : 1 : QCOMPARE( p, QgsPoint( 1, 2 ) );
2503 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2504 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
2505 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
2506 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
2507 : 1 : QVERIFY( l33.pointAt( 2, p, type ) );
2508 : 1 : QCOMPARE( p, QgsPoint( 1, 22 ) );
2509 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2510 : : //CircularStringZ
2511 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 22, 23 ) );
2512 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
2513 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
2514 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZ, 1, 22, 23 ) );
2515 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
2516 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
2517 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2518 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
2519 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
2520 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
2521 : 1 : QVERIFY( l33.pointAt( 2, p, type ) );
2522 : 1 : QCOMPARE( p, QgsPoint( 1, 22, 23 ) );
2523 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2524 : : //CircularStringM
2525 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) << QgsPoint( QgsWkbTypes::PointM, 1, 22, 0, 24 ) );
2526 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
2527 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
2528 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointM, 1, 22, 0, 24 ) );
2529 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
2530 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
2531 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2532 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
2533 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
2534 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
2535 : 1 : QVERIFY( l33.pointAt( 2, p, type ) );
2536 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 22, 0, 24 ) );
2537 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2538 : : //CircularStringZM
2539 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 23, 24 ) );
2540 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
2541 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2542 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 22, 23, 24 ) );
2543 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
2544 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
2545 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2546 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
2547 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
2548 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
2549 : 1 : QVERIFY( l33.pointAt( 2, p, type ) );
2550 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 22, 23, 24 ) );
2551 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
2552 : :
2553 : : //centroid
2554 : 1 : QgsCircularString l34;
2555 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 0, 0 ) );
2556 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
2557 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 5, 10 ) );
2558 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 20, 10 ) << QgsPoint( 2, 9 ) );
2559 : 1 : QgsPoint centroid = l34.centroid();
2560 : 1 : QGSCOMPARENEAR( centroid.x(), 7.333, 0.001 );
2561 : 1 : QGSCOMPARENEAR( centroid.y(), 6.333, 0.001 );
2562 : :
2563 : : //closest segment
2564 : 1 : QgsCircularString l35;
2565 : 1 : int leftOf = 0;
2566 : 1 : p = QgsPoint( 0, 0 ); // reset all coords to zero
2567 : 1 : ( void )l35.closestSegment( QgsPoint( 1, 2 ), p, v ); //empty line, just want no crash
2568 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
2569 : 1 : QVERIFY( l35.closestSegment( QgsPoint( 5, 10 ), p, v ) < 0 );
2570 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 7, 12 ) << QgsPoint( 5, 15 ) );
2571 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 4, 11 ), p, v, &leftOf ), 2.0, 0.0001 );
2572 : 1 : QCOMPARE( p, QgsPoint( 5, 10 ) );
2573 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2574 : 1 : QCOMPARE( leftOf, -1 );
2575 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 8, 11 ), p, v, &leftOf ), 1.583512, 0.0001 );
2576 : 1 : QGSCOMPARENEAR( p.x(), 6.84, 0.01 );
2577 : 1 : QGSCOMPARENEAR( p.y(), 11.49, 0.01 );
2578 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2579 : 1 : QCOMPARE( leftOf, 1 );
2580 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 5.5, 11.5 ), p, v, &leftOf ), 1.288897, 0.0001 );
2581 : 1 : QGSCOMPARENEAR( p.x(), 6.302776, 0.01 );
2582 : 1 : QGSCOMPARENEAR( p.y(), 10.7, 0.01 );
2583 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2584 : 1 : QCOMPARE( leftOf, -1 );
2585 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 7, 16 ), p, v, &leftOf ), 3.068288, 0.0001 );
2586 : 1 : QGSCOMPARENEAR( p.x(), 5.981872, 0.01 );
2587 : 1 : QGSCOMPARENEAR( p.y(), 14.574621, 0.01 );
2588 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
2589 : 1 : QCOMPARE( leftOf, 1 );
2590 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 5.5, 13.5 ), p, v, &leftOf ), 1.288897, 0.0001 );
2591 : 1 : QGSCOMPARENEAR( p.x(), 6.302776, 0.01 );
2592 : 1 : QGSCOMPARENEAR( p.y(), 14.3, 0.01 );
2593 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
2594 : 1 : QCOMPARE( leftOf, -1 );
2595 : : // point directly on segment
2596 : 1 : QCOMPARE( l35.closestSegment( QgsPoint( 5, 15 ), p, v, &leftOf ), 0.0 );
2597 : 1 : QCOMPARE( p, QgsPoint( 5, 15 ) );
2598 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
2599 : 1 : QCOMPARE( leftOf, 0 );
2600 : :
2601 : : //clockwise string
2602 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 15 ) << QgsPoint( 7, 12 ) << QgsPoint( 5, 10 ) );
2603 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 4, 11 ), p, v, &leftOf ), 2, 0.0001 );
2604 : 1 : QGSCOMPARENEAR( p.x(), 5, 0.01 );
2605 : 1 : QGSCOMPARENEAR( p.y(), 10, 0.01 );
2606 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
2607 : 1 : QCOMPARE( leftOf, 1 );
2608 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 8, 11 ), p, v, &leftOf ), 1.583512, 0.0001 );
2609 : 1 : QGSCOMPARENEAR( p.x(), 6.84, 0.01 );
2610 : 1 : QGSCOMPARENEAR( p.y(), 11.49, 0.01 );
2611 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
2612 : 1 : QCOMPARE( leftOf, -1 );
2613 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 5.5, 11.5 ), p, v, &leftOf ), 1.288897, 0.0001 );
2614 : 1 : QGSCOMPARENEAR( p.x(), 6.302776, 0.01 );
2615 : 1 : QGSCOMPARENEAR( p.y(), 10.7, 0.01 );
2616 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
2617 : 1 : QCOMPARE( leftOf, 1 );
2618 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 7, 16 ), p, v, &leftOf ), 3.068288, 0.0001 );
2619 : 1 : QGSCOMPARENEAR( p.x(), 5.981872, 0.01 );
2620 : 1 : QGSCOMPARENEAR( p.y(), 14.574621, 0.01 );
2621 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2622 : 1 : QCOMPARE( leftOf, -1 );
2623 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 5.5, 13.5 ), p, v, &leftOf ), 1.288897, 0.0001 );
2624 : 1 : QGSCOMPARENEAR( p.x(), 6.302776, 0.01 );
2625 : 1 : QGSCOMPARENEAR( p.y(), 14.3, 0.01 );
2626 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2627 : 1 : QCOMPARE( leftOf, 1 );
2628 : : // point directly on segment
2629 : 1 : QCOMPARE( l35.closestSegment( QgsPoint( 5, 15 ), p, v, &leftOf ), 0.0 );
2630 : 1 : QCOMPARE( p, QgsPoint( 5, 15 ) );
2631 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
2632 : 1 : QCOMPARE( leftOf, 0 );
2633 : :
2634 : : //sumUpArea
2635 : 1 : QgsCircularString l36;
2636 : 1 : double area = 1.0; //sumUpArea adds to area, so start with non-zero value
2637 : 1 : l36.sumUpArea( area );
2638 : 1 : QCOMPARE( area, 1.0 );
2639 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
2640 : 1 : l36.sumUpArea( area );
2641 : 1 : QCOMPARE( area, 1.0 );
2642 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 10 ) );
2643 : 1 : l36.sumUpArea( area );
2644 : 1 : QCOMPARE( area, 1.0 );
2645 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2, 0 ) << QgsPoint( 2, 2 ) );
2646 : 1 : l36.sumUpArea( area );
2647 : 1 : QGSCOMPARENEAR( area, 4.141593, 0.0001 );
2648 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2, 0 ) << QgsPoint( 2, 2 ) << QgsPoint( 0, 2 ) );
2649 : 1 : l36.sumUpArea( area );
2650 : 1 : QGSCOMPARENEAR( area, 7.283185, 0.0001 );
2651 : : // full circle
2652 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 4, 0 ) << QgsPoint( 0, 0 ) );
2653 : 1 : area = 0.0;
2654 : 1 : l36.sumUpArea( area );
2655 : 1 : QGSCOMPARENEAR( area, 12.566370614359172, 0.0001 );
2656 : :
2657 : : //boundingBox - test that bounding box is updated after every modification to the circular string
2658 : 1 : QgsCircularString l37;
2659 : 1 : QVERIFY( l37.boundingBox().isNull() );
2660 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 15 ) );
2661 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 5, 10, 10, 15 ) );
2662 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( -5, -10 ) << QgsPoint( -6, -10 ) << QgsPoint( -5.5, -9 ) );
2663 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6.125, -10.25, -5, -9 ) );
2664 : 1 : QByteArray wkbToAppend = l37.asWkb();
2665 : 1 : l37.clear();
2666 : 1 : QVERIFY( l37.boundingBox().isNull() );
2667 : 1 : QgsConstWkbPtr wkbToAppendPtr( wkbToAppend );
2668 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 15 ) );
2669 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 5, 10, 10, 15 ) );
2670 : 1 : l37.fromWkb( wkbToAppendPtr );
2671 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6.125, -10.25, -5, -9 ) );
2672 : 2 : l37.fromWkt( QStringLiteral( "CircularString( 5 10, 6 10, 5.5 9 )" ) );
2673 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 5, 9, 6.125, 10.25 ) );
2674 : 1 : l37.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( -1, 7 ) );
2675 : 1 : QgsRectangle r = l37.boundingBox();
2676 : 1 : QGSCOMPARENEAR( r.xMinimum(), -3.014, 0.01 );
2677 : 1 : QGSCOMPARENEAR( r.xMaximum(), 14.014, 0.01 );
2678 : 1 : QGSCOMPARENEAR( r.yMinimum(), -7.0146, 0.01 );
2679 : 1 : QGSCOMPARENEAR( r.yMaximum(), 12.4988, 0.01 );
2680 : 1 : l37.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( -3, 10 ) );
2681 : 1 : r = l37.boundingBox();
2682 : 1 : QGSCOMPARENEAR( r.xMinimum(), -10.294, 0.01 );
2683 : 1 : QGSCOMPARENEAR( r.xMaximum(), 12.294, 0.01 );
2684 : 1 : QGSCOMPARENEAR( r.yMinimum(), 9, 0.01 );
2685 : 1 : QGSCOMPARENEAR( r.yMaximum(), 31.856, 0.01 );
2686 : 1 : l37.deleteVertex( QgsVertexId( 0, 0, 1 ) );
2687 : 1 : r = l37.boundingBox();
2688 : 1 : QGSCOMPARENEAR( r.xMinimum(), 5, 0.01 );
2689 : 1 : QGSCOMPARENEAR( r.xMaximum(), 6.125, 0.01 );
2690 : 1 : QGSCOMPARENEAR( r.yMinimum(), 9, 0.01 );
2691 : 1 : QGSCOMPARENEAR( r.yMaximum(), 10.25, 0.01 );
2692 : :
2693 : : //angle
2694 : 1 : QgsCircularString l38;
2695 : 1 : ( void )l38.vertexAngle( QgsVertexId() ); //just want no crash
2696 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash
2697 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) );
2698 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash, any answer is meaningless
2699 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) );
2700 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash, any answer is meaningless
2701 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ); //just want no crash, any answer is meaningless
2702 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 ) );
2703 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
2704 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 0, 0.0001 );
2705 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 4.712389, 0.0001 );
2706 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 2 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
2707 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
2708 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.141593, 0.0001 );
2709 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 4.712389, 0.0001 );
2710 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 20 ) ); // no crash
2711 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 )
2712 : 1 : << QgsPoint( -1, 3 ) << QgsPoint( 0, 4 ) );
2713 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
2714 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 0, 0.0001 );
2715 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 4.712389, 0.0001 );
2716 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 0, 0.0001 );
2717 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 1.5708, 0.0001 );
2718 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 4 ) << QgsPoint( -1, 3 ) << QgsPoint( 0, 2 )
2719 : 1 : << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
2720 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 4.712389, 0.0001 );
2721 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.141592, 0.0001 );
2722 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 1.5708, 0.0001 );
2723 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 3.141592, 0.0001 );
2724 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 4.712389, 0.0001 );
2725 : :
2726 : : //closed circular string
2727 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 0, 0 ) );
2728 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 0, 0.00001 );
2729 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.141592, 0.00001 );
2730 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 0, 0.00001 );
2731 : :
2732 : : //removing a vertex from a 3 point circular string should remove the whole line
2733 : 1 : QgsCircularString l39;
2734 : 1 : l39.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 ) );
2735 : 1 : QCOMPARE( l39.numPoints(), 3 );
2736 : 1 : l39.deleteVertex( QgsVertexId( 0, 0, 2 ) );
2737 : 1 : QCOMPARE( l39.numPoints(), 0 );
2738 : :
2739 : : //boundary
2740 : 1 : QgsCircularString boundary1;
2741 : 1 : QVERIFY( !boundary1.boundary() );
2742 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
2743 : 1 : QgsAbstractGeometry *boundary = boundary1.boundary();
2744 : 1 : QgsMultiPoint *mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
2745 : 1 : QVERIFY( mpBoundary );
2746 : 1 : QCOMPARE( mpBoundary->pointN( 0 )->x(), 0.0 );
2747 : 1 : QCOMPARE( mpBoundary->pointN( 0 )->y(), 0.0 );
2748 : 1 : QCOMPARE( mpBoundary->pointN( 1 )->x(), 1.0 );
2749 : 1 : QCOMPARE( mpBoundary->pointN( 1 )->y(), 1.0 );
2750 : 1 : delete boundary;
2751 : :
2752 : : // closed string = no boundary
2753 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
2754 : 1 : QVERIFY( !boundary1.boundary() );
2755 : :
2756 : : //boundary with z
2757 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) );
2758 : 1 : boundary = boundary1.boundary();
2759 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
2760 : 1 : QVERIFY( mpBoundary );
2761 : 1 : QCOMPARE( mpBoundary->pointN( 0 )->wkbType(), QgsWkbTypes::PointZ );
2762 : 1 : QCOMPARE( mpBoundary->pointN( 0 )->x(), 0.0 );
2763 : 1 : QCOMPARE( mpBoundary->pointN( 0 )->y(), 0.0 );
2764 : 1 : QCOMPARE( mpBoundary->pointN( 0 )->z(), 10.0 );
2765 : 1 : QCOMPARE( mpBoundary->pointN( 1 )->wkbType(), QgsWkbTypes::PointZ );
2766 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
2767 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
2768 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
2769 : 1 : delete boundary;
2770 : :
2771 : : // addToPainterPath (note most tests are in test_qgsgeometry.py)
2772 : 1 : QgsCircularString path;
2773 : 1 : QPainterPath pPath;
2774 : 1 : path.addToPainterPath( pPath );
2775 : 1 : QVERIFY( pPath.isEmpty() );
2776 : 2 : path.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 )
2777 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 21, 2, 3 ) );
2778 : 1 : path.addToPainterPath( pPath );
2779 : 1 : QGSCOMPARENEAR( pPath.currentPosition().x(), 21.0, 0.01 );
2780 : 1 : QGSCOMPARENEAR( pPath.currentPosition().y(), 2.0, 0.01 );
2781 : 1 : QVERIFY( !pPath.isEmpty() );
2782 : :
2783 : : // even number of points - should still work
2784 : 1 : pPath = QPainterPath();
2785 : 1 : path.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
2786 : 1 : path.addToPainterPath( pPath );
2787 : 1 : QGSCOMPARENEAR( pPath.currentPosition().x(), 11.0, 0.01 );
2788 : 1 : QGSCOMPARENEAR( pPath.currentPosition().y(), 12.0, 0.01 );
2789 : 1 : QVERIFY( !pPath.isEmpty() );
2790 : :
2791 : : // toCurveType
2792 : 1 : QgsCircularString curveLine1;
2793 : 1 : curveLine1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
2794 : 1 : std::unique_ptr< QgsCurve > curveType( curveLine1.toCurveType() );
2795 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::CircularString );
2796 : 1 : QCOMPARE( curveType->numPoints(), 3 );
2797 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
2798 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
2799 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 1, 22 ) );
2800 : :
2801 : : //segmentLength
2802 : 1 : QgsCircularString curveLine2;
2803 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
2804 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, 0 ) ), 0.0 );
2805 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 1, 0, 0 ) ), 0.0 );
2806 : 1 : curveLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
2807 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId() ), 0.0 );
2808 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
2809 : 1 : QGSCOMPARENEAR( curveLine2.segmentLength( QgsVertexId( 0, 0, 0 ) ), 31.4159, 0.001 );
2810 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, 1 ) ), 0.0 );
2811 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, 2 ) ), 0.0 );
2812 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
2813 : 1 : QGSCOMPARENEAR( curveLine2.segmentLength( QgsVertexId( -1, 0, 0 ) ), 31.4159, 0.001 );
2814 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 1, 0, 1 ) ), 0.0 );
2815 : 1 : QGSCOMPARENEAR( curveLine2.segmentLength( QgsVertexId( 1, 1, 0 ) ), 31.4159, 0.001 );
2816 : 1 : curveLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) << QgsPoint( -9, 32 ) << QgsPoint( 1, 42 ) );
2817 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId() ), 0.0 );
2818 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
2819 : 1 : QGSCOMPARENEAR( curveLine2.segmentLength( QgsVertexId( 0, 0, 0 ) ), 31.4159, 0.001 );
2820 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, 1 ) ), 0.0 );
2821 : 1 : QGSCOMPARENEAR( curveLine2.segmentLength( QgsVertexId( 0, 0, 2 ) ), 31.4159, 0.001 );
2822 : 1 : QCOMPARE( curveLine2.segmentLength( QgsVertexId( 0, 0, 3 ) ), 0.0 );
2823 : :
2824 : : //removeDuplicateNodes
2825 : 1 : QgsCircularString nodeLine;
2826 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
2827 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
2828 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
2829 : 2 : QCOMPARE( nodeLine.asWkt(), QStringLiteral( "CircularString (11 2, 11 12, 111 12)" ) );
2830 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 11, 2 ) );
2831 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
2832 : 2 : QCOMPARE( nodeLine.asWkt(), QStringLiteral( "CircularString (11 2, 11 12, 11 2)" ) );
2833 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 10, 3 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 9, 3 )
2834 : 1 : << QgsPoint( 11, 2 ) );
2835 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
2836 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularString (11 2, 10 3, 11.01 1.99, 9 3, 11 2)" ) );
2837 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
2838 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) << QgsPoint( 111.01, 11.99 ) );
2839 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
2840 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularString (11 2, 11.01 1.99, 11.02 2.01, 11 12, 111 12, 111.01 11.99)" ) );
2841 : 1 : QVERIFY( nodeLine.removeDuplicateNodes( 0.02 ) );
2842 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
2843 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularString (11 2, 11 12, 111 12, 111.01 11.99)" ) );
2844 : :
2845 : : // don't create degenerate lines
2846 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) );
2847 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
2848 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularString (11 2)" ) );
2849 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) );
2850 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
2851 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularString (11 2, 11.01 1.99)" ) );
2852 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11, 2 ) );
2853 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
2854 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularString (11 2, 11.01 1.99, 11 2)" ) );
2855 : :
2856 : : // with z
2857 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 1 ) << QgsPoint( 11.01, 1.99, 2 ) << QgsPoint( 11.02, 2.01, 3 )
2858 : 1 : << QgsPoint( 11, 12, 4 ) << QgsPoint( 111, 12, 5 ) );
2859 : 1 : QVERIFY( nodeLine.removeDuplicateNodes( 0.02 ) );
2860 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularStringZ (11 2 1, 11 12 4, 111 12 5)" ) );
2861 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 1 ) << QgsPoint( 11.01, 1.99, 2 ) << QgsPoint( 11.02, 2.01, 3 )
2862 : 1 : << QgsPoint( 11, 12, 4 ) << QgsPoint( 111, 12, 5 ) );
2863 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02, true ) );
2864 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "CircularStringZ (11 2 1, 11.01 1.99 2, 11.02 2.01 3, 11 12 4, 111 12 5)" ) );
2865 : :
2866 : : //swap xy
2867 : 1 : QgsCircularString swapLine;
2868 : 1 : swapLine.swapXy(); // no crash
2869 : 1 : swapLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
2870 : 1 : swapLine.swapXy();
2871 : 2 : QCOMPARE( swapLine.asWkt(), QStringLiteral( "CircularStringZM (2 11 3 4, 12 11 13 14, 12 111 23 24)" ) );
2872 : :
2873 : : // filter vertex
2874 : 1 : QgsCircularString filterLine;
2875 : 3 : auto filter = []( const QgsPoint & point )-> bool
2876 : : {
2877 : 3 : return point.x() < 5;
2878 : : };
2879 : 1 : filterLine.filterVertices( filter ); // no crash
2880 : 1 : filterLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
2881 : 1 : filterLine.filterVertices( filter );
2882 : 2 : QCOMPARE( filterLine.asWkt( 2 ), QStringLiteral( "CircularStringZM (1 2 3 4, 4 12 13 14)" ) );
2883 : :
2884 : : // transform vertex
2885 : 1 : QgsCircularString transformLine;
2886 : 3 : auto transform = []( const QgsPoint & point )-> QgsPoint
2887 : : {
2888 : 3 : return QgsPoint( point.x() + 2, point.y() + 3, point.z() + 4, point.m() + 7 );
2889 : : };
2890 : 1 : transformLine.transformVertices( transform ); // no crash
2891 : 1 : transformLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
2892 : 1 : transformLine.transformVertices( transform );
2893 : 2 : QCOMPARE( transformLine.asWkt( 2 ), QStringLiteral( "CircularStringZM (3 5 7 11, 6 15 17 21, 113 15 27 31)" ) );
2894 : :
2895 : : // transform using class
2896 : 1 : QgsCircularString transformLine2;
2897 : 1 : TestTransformer transformer;
2898 : : // no crash
2899 : 1 : QVERIFY( transformLine2.transform( &transformer ) );
2900 : 1 : transformLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
2901 : 1 : QVERIFY( transformLine2.transform( &transformer ) );
2902 : 2 : QCOMPARE( transformLine2.asWkt( 2 ), QStringLiteral( "CircularStringZM (3 16 8 3, 12 26 18 13, 333 26 28 23)" ) );
2903 : :
2904 : 1 : TestFailTransformer failTransformer;
2905 : 1 : QVERIFY( !transformLine2.transform( &failTransformer ) );
2906 : :
2907 : : // substring
2908 : 1 : QgsCircularString substring;
2909 : 1 : std::unique_ptr< QgsCircularString > substringResult( substring.curveSubstring( 1, 2 ) ); // no crash
2910 : 1 : QVERIFY( substringResult.get() );
2911 : 1 : QVERIFY( substringResult->isEmpty() );
2912 : : // CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14)
2913 : 1 : substring.setPoints( QgsPointSequence() << QgsPoint( 10, 0, 1, 2 ) << QgsPoint( 11, 1, 3, 4 ) << QgsPoint( 12, 0, 13, 14 ) );
2914 : 1 : substringResult.reset( substring.curveSubstring( 0, 0 ) );
2915 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10 0 1 2, 10 0 1 2, 10 0 1 2)" ) );
2916 : 1 : substringResult.reset( substring.curveSubstring( -1, -0.1 ) );
2917 : 1 : QVERIFY( substringResult->isEmpty() );
2918 : 1 : substringResult.reset( substring.curveSubstring( 100000, 10000 ) );
2919 : 1 : QVERIFY( substringResult->isEmpty() );
2920 : 1 : substringResult.reset( substring.curveSubstring( -1, 1 ) );
2921 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10 0 1 2, 10.12 0.48 1.64 2.64, 10.46 0.84 2.27 3.27)" ) );
2922 : 1 : substringResult.reset( substring.curveSubstring( 1, -1 ) );
2923 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 10.46 0.84 2.27 3.27, 10.46 0.84 2.27 3.27)" ) );
2924 : 1 : substringResult.reset( substring.curveSubstring( -1, 10000 ) );
2925 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14)" ) );
2926 : 1 : substringResult.reset( substring.curveSubstring( 1, 10000 ) );
2927 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 11.48 0.88 6.18 7.18, 12 0 13 14)" ) );
2928 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
2929 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 11.48 0.88 6.18 7.18, 12 0 13 14)" ) );
2930 : 1 : substringResult.reset( substring.curveSubstring( 1, 1.5 ) );
2931 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 10.68 0.95 2.59 3.59, 10.93 1 2.91 3.91)" ) );
2932 : : // CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14, 14 -1 13 14, 16 1 23 24 )
2933 : 2 : substring.setPoints( QgsPointSequence() << QgsPoint( 10, 0, 1, 2 ) << QgsPoint( 11, 1, 3, 4 ) << QgsPoint( 12, 0, 13, 14 )
2934 : 1 : << QgsPoint( 14, -1, 13, 14 ) << QgsPoint( 16, 1, 23, 24 ) );
2935 : 1 : substringResult.reset( substring.curveSubstring( 1, 1.5 ) );
2936 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 10.68 0.95 2.59 3.59, 10.93 1 2.91 3.91)" ) );
2937 : 1 : substringResult.reset( substring.curveSubstring( 1, 10 ) );
2938 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 11.48 0.88 6.18 7.18, 12 0 13 14, 14 -1 13 14, 16 1 23 24)" ) );
2939 : 1 : substringResult.reset( substring.curveSubstring( 1, 6 ) );
2940 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10.46 0.84 2.27 3.27, 11.48 0.88 6.18 7.18, 12 0 13 14, 13.1 -0.88 13 14, 14.5 -0.9 14.65 15.65)" ) );
2941 : 1 : substringResult.reset( substring.curveSubstring( 0, 6 ) );
2942 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14, 13.1 -0.88 13 14, 14.5 -0.9 14.65 15.65)" ) );
2943 : 1 : substringResult.reset( substring.curveSubstring( 5, 6 ) );
2944 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (13.51 -0.98 13 14, 14.01 -1 13.03 14.03, 14.5 -0.9 14.65 15.65)" ) );
2945 : 1 : substringResult.reset( substring.curveSubstring( 5, 1000 ) );
2946 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (13.51 -0.98 13 14, 15.19 -0.53 17.2 18.2, 16 1 23 24)" ) );
2947 : 1 : substringResult.reset( substring.curveSubstring( QgsGeometryUtils::distanceToVertex( substring, QgsVertexId( 0, 0, 2 ) ), QgsGeometryUtils::distanceToVertex( substring, QgsVertexId( 0, 0, 4 ) ) ) );
2948 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZM (12 0 13 14, 14.36 -0.94 14.19 15.19, 16 1 23 24)" ) );
2949 : :
2950 : 2 : substring.setPoints( QgsPointSequence() << QgsPoint( 10, 0, 1 ) << QgsPoint( 11, 1, 3 ) << QgsPoint( 12, 0, 13 )
2951 : 1 : << QgsPoint( 14, -1, 13 ) << QgsPoint( 16, 1, 23 ) );
2952 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
2953 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringZ (10.46 0.84 2.27, 11.48 0.88 6.18, 12 0 13, 14 -1 13, 16 1 23)" ) );
2954 : 2 : substring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 11, 1, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 12, 0, 0, 13 )
2955 : 1 : << QgsPoint( QgsWkbTypes::PointM, 14, -1, 0, 13 ) << QgsPoint( QgsWkbTypes::PointM, 16, 1, 0, 23 ) );
2956 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
2957 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularStringM (10.46 0.84 2.27, 11.48 0.88 6.18, 12 0 13, 14 -1 13, 16 1 23)" ) );
2958 : 2 : substring.setPoints( QgsPointSequence() << QgsPoint( 10, 0 ) << QgsPoint( 11, 1 ) << QgsPoint( 12, 0 )
2959 : 1 : << QgsPoint( 14, -1 ) << QgsPoint( 16, 1 ) );
2960 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
2961 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CircularString (10.46 0.84, 11.48 0.88, 12 0, 14 -1, 16 1)" ) );
2962 : :
2963 : : // interpolate
2964 : 1 : QgsCircularString interpolate;
2965 : 1 : std::unique_ptr< QgsPoint > interpolateResult( interpolate.interpolatePoint( 1 ) ); // no crash
2966 : 1 : QVERIFY( !interpolateResult.get() );
2967 : : // CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14)
2968 : 1 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 10, 0, 1, 2 ) << QgsPoint( 11, 1, 3, 4 ) << QgsPoint( 12, 0, 13, 14 ) );
2969 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 0 ) );
2970 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (10 0 1 2)" ) );
2971 : 1 : interpolateResult.reset( interpolate.interpolatePoint( -1 ) );
2972 : 1 : QVERIFY( !interpolateResult.get() );
2973 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 100000 ) );
2974 : 1 : QVERIFY( !interpolateResult.get() );
2975 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
2976 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (10.46 0.84 2.27 3.27)" ) );
2977 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1.5 ) );
2978 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (10.93 1 2.91 3.91)" ) );
2979 : 1 : interpolateResult.reset( interpolate.interpolatePoint( interpolate.length() ) );
2980 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (12 0 13 14)" ) );
2981 : : // CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14, 14 -1 13 14, 16 1 23 24 )
2982 : 2 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 10, 0, 1, 2 ) << QgsPoint( 11, 1, 3, 4 ) << QgsPoint( 12, 0, 13, 14 )
2983 : 1 : << QgsPoint( 14, -1, 13, 14 ) << QgsPoint( 16, 1, 23, 24 ) );
2984 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
2985 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (10.46 0.84 2.27 3.27)" ) );
2986 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1.5 ) );
2987 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (10.93 1 2.91 3.91)" ) );
2988 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 10 ) );
2989 : 1 : QVERIFY( !interpolateResult.get() );
2990 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 6 ) );
2991 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (14.5 -0.9 14.65 15.65)" ) );
2992 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 5 ) );
2993 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (13.51 -0.98 13 14)" ) );
2994 : :
2995 : 2 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 10, 0, 1 ) << QgsPoint( 11, 1, 3 ) << QgsPoint( 12, 0, 13 )
2996 : 1 : << QgsPoint( 14, -1, 13 ) << QgsPoint( 16, 1, 23 ) );
2997 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
2998 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZ (10.46 0.84 2.27)" ) );
2999 : 2 : interpolate.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 11, 1, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 12, 0, 0, 13 )
3000 : 1 : << QgsPoint( QgsWkbTypes::PointM, 14, -1, 0, 13 ) << QgsPoint( QgsWkbTypes::PointM, 16, 1, 0, 23 ) );
3001 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
3002 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointM (10.46 0.84 2.27)" ) );
3003 : 2 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 10, 0 ) << QgsPoint( 11, 1 ) << QgsPoint( 12, 0 )
3004 : 1 : << QgsPoint( 14, -1 ) << QgsPoint( 16, 1 ) );
3005 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
3006 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "Point (10.46 0.84)" ) );
3007 : :
3008 : : // orientation
3009 : 1 : QgsCircularString orientation;
3010 : 1 : ( void )orientation.orientation(); // no crash
3011 : 1 : orientation.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 1 ) << QgsPoint( 1, 1 ) << QgsPoint( 1, 0 ) << QgsPoint( 0, 0 ) );
3012 : 1 : QCOMPARE( orientation.orientation(), QgsCurve::Clockwise );
3013 : 1 : orientation.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 1 ) << QgsPoint( 0, 0 ) );
3014 : 1 : QCOMPARE( orientation.orientation(), QgsCurve::CounterClockwise );
3015 : 1 : }
3016 : :
3017 : :
3018 : 1 : void TestQgsGeometry::lineString()
3019 : : {
3020 : : //test constructors
3021 : 1 : QgsLineString l1;
3022 : 1 : QVERIFY( l1.isEmpty() );
3023 : 1 : QCOMPARE( l1.numPoints(), 0 );
3024 : 1 : QCOMPARE( l1.vertexCount(), 0 );
3025 : 1 : QCOMPARE( l1.nCoordinates(), 0 );
3026 : 1 : QCOMPARE( l1.ringCount(), 0 );
3027 : 1 : QCOMPARE( l1.partCount(), 0 );
3028 : 1 : QVERIFY( !l1.is3D() );
3029 : 1 : QVERIFY( !l1.isMeasure() );
3030 : 1 : QCOMPARE( l1.wkbType(), QgsWkbTypes::LineString );
3031 : 1 : QCOMPARE( l1.wktTypeStr(), QString( "LineString" ) );
3032 : 1 : QCOMPARE( l1.geometryType(), QString( "LineString" ) );
3033 : 1 : QCOMPARE( l1.dimension(), 1 );
3034 : 1 : QVERIFY( !l1.hasCurvedSegments() );
3035 : 1 : QCOMPARE( l1.area(), 0.0 );
3036 : 1 : QCOMPARE( l1.perimeter(), 0.0 );
3037 : :
3038 : : // from array
3039 : 1 : QVector< double > xx;
3040 : 1 : xx << 1 << 2 << 3;
3041 : 1 : QVector< double > yy;
3042 : 1 : yy << 11 << 12 << 13;
3043 : 1 : QgsLineString fromArray( xx, yy );
3044 : 1 : QCOMPARE( fromArray.wkbType(), QgsWkbTypes::LineString );
3045 : 1 : QCOMPARE( fromArray.numPoints(), 3 );
3046 : 1 : QCOMPARE( fromArray.xAt( 0 ), 1.0 );
3047 : 1 : QCOMPARE( fromArray.yAt( 0 ), 11.0 );
3048 : 1 : QCOMPARE( fromArray.xAt( 1 ), 2.0 );
3049 : 1 : QCOMPARE( fromArray.yAt( 1 ), 12.0 );
3050 : 1 : QCOMPARE( fromArray.xAt( 2 ), 3.0 );
3051 : 1 : QCOMPARE( fromArray.yAt( 2 ), 13.0 );
3052 : 1 : QCOMPARE( *fromArray.xData(), 1.0 );
3053 : 1 : QCOMPARE( *( fromArray.xData() + 1 ), 2.0 );
3054 : 1 : QCOMPARE( *( fromArray.xData() + 2 ), 3.0 );
3055 : 1 : QCOMPARE( *fromArray.yData(), 11.0 );
3056 : 1 : QCOMPARE( *( fromArray.yData() + 1 ), 12.0 );
3057 : 1 : QCOMPARE( *( fromArray.yData() + 2 ), 13.0 );
3058 : :
3059 : : // unbalanced
3060 : 1 : xx = QVector< double >() << 1 << 2;
3061 : 1 : yy = QVector< double >() << 11 << 12 << 13;
3062 : 1 : QgsLineString fromArray2( xx, yy );
3063 : 1 : QCOMPARE( fromArray2.wkbType(), QgsWkbTypes::LineString );
3064 : 1 : QCOMPARE( fromArray2.numPoints(), 2 );
3065 : 1 : QCOMPARE( fromArray2.xAt( 0 ), 1.0 );
3066 : 1 : QCOMPARE( fromArray2.yAt( 0 ), 11.0 );
3067 : 1 : QCOMPARE( fromArray2.xAt( 1 ), 2.0 );
3068 : 1 : QCOMPARE( fromArray2.yAt( 1 ), 12.0 );
3069 : 1 : xx = QVector< double >() << 1 << 2 << 3;
3070 : 1 : yy = QVector< double >() << 11 << 12;
3071 : 1 : QgsLineString fromArray3( xx, yy );
3072 : 1 : QCOMPARE( fromArray3.wkbType(), QgsWkbTypes::LineString );
3073 : 1 : QCOMPARE( fromArray3.numPoints(), 2 );
3074 : 1 : QCOMPARE( fromArray3.xAt( 0 ), 1.0 );
3075 : 1 : QCOMPARE( fromArray3.yAt( 0 ), 11.0 );
3076 : 1 : QCOMPARE( fromArray3.xAt( 1 ), 2.0 );
3077 : 1 : QCOMPARE( fromArray3.yAt( 1 ), 12.0 );
3078 : : // with z
3079 : 1 : QVector< double > zz;
3080 : 1 : xx = QVector< double >() << 1 << 2 << 3;
3081 : 1 : yy = QVector< double >() << 11 << 12 << 13;
3082 : 1 : zz = QVector< double >() << 21 << 22 << 23;
3083 : 1 : QgsLineString fromArray4( xx, yy, zz );
3084 : 1 : QCOMPARE( fromArray4.wkbType(), QgsWkbTypes::LineStringZ );
3085 : 1 : QCOMPARE( fromArray4.numPoints(), 3 );
3086 : 1 : QCOMPARE( fromArray4.xAt( 0 ), 1.0 );
3087 : 1 : QCOMPARE( fromArray4.yAt( 0 ), 11.0 );
3088 : 1 : QCOMPARE( fromArray4.zAt( 0 ), 21.0 );
3089 : 1 : QCOMPARE( fromArray4.xAt( 1 ), 2.0 );
3090 : 1 : QCOMPARE( fromArray4.yAt( 1 ), 12.0 );
3091 : 1 : QCOMPARE( fromArray4.zAt( 1 ), 22.0 );
3092 : 1 : QCOMPARE( fromArray4.xAt( 2 ), 3.0 );
3093 : 1 : QCOMPARE( fromArray4.yAt( 2 ), 13.0 );
3094 : 1 : QCOMPARE( fromArray4.zAt( 2 ), 23.0 );
3095 : 1 : fromArray4 = QgsLineString( xx, yy, zz, QVector< double >(), true ); // LineString25D
3096 : 1 : QCOMPARE( fromArray4.wkbType(), QgsWkbTypes::LineString25D );
3097 : 1 : QCOMPARE( fromArray4.numPoints(), 3 );
3098 : 1 : QCOMPARE( fromArray4.xAt( 0 ), 1.0 );
3099 : 1 : QCOMPARE( fromArray4.yAt( 0 ), 11.0 );
3100 : 1 : QCOMPARE( fromArray4.zAt( 0 ), 21.0 );
3101 : 1 : QCOMPARE( fromArray4.xAt( 1 ), 2.0 );
3102 : 1 : QCOMPARE( fromArray4.yAt( 1 ), 12.0 );
3103 : 1 : QCOMPARE( fromArray4.zAt( 1 ), 22.0 );
3104 : 1 : QCOMPARE( fromArray4.xAt( 2 ), 3.0 );
3105 : 1 : QCOMPARE( fromArray4.yAt( 2 ), 13.0 );
3106 : 1 : QCOMPARE( fromArray4.zAt( 2 ), 23.0 );
3107 : :
3108 : : // unbalanced -> z ignored
3109 : 1 : zz = QVector< double >() << 21 << 22;
3110 : 1 : QgsLineString fromArray5( xx, yy, zz );
3111 : 1 : QCOMPARE( fromArray5.wkbType(), QgsWkbTypes::LineString );
3112 : 1 : QCOMPARE( fromArray5.numPoints(), 3 );
3113 : 1 : QCOMPARE( fromArray5.xAt( 0 ), 1.0 );
3114 : 1 : QCOMPARE( fromArray5.yAt( 0 ), 11.0 );
3115 : 1 : QCOMPARE( fromArray5.xAt( 1 ), 2.0 );
3116 : 1 : QCOMPARE( fromArray5.yAt( 1 ), 12.0 );
3117 : 1 : QCOMPARE( fromArray5.xAt( 2 ), 3.0 );
3118 : 1 : QCOMPARE( fromArray5.yAt( 2 ), 13.0 );
3119 : : // unbalanced -> z truncated
3120 : 1 : zz = QVector< double >() << 21 << 22 << 23 << 24;
3121 : 1 : fromArray5 = QgsLineString( xx, yy, zz );
3122 : 1 : QCOMPARE( fromArray5.wkbType(), QgsWkbTypes::LineStringZ );
3123 : 1 : QCOMPARE( fromArray5.numPoints(), 3 );
3124 : 1 : QCOMPARE( fromArray5.xAt( 0 ), 1.0 );
3125 : 1 : QCOMPARE( fromArray5.yAt( 0 ), 11.0 );
3126 : 1 : QCOMPARE( fromArray5.zAt( 0 ), 21.0 );
3127 : 1 : QCOMPARE( fromArray5.xAt( 1 ), 2.0 );
3128 : 1 : QCOMPARE( fromArray5.yAt( 1 ), 12.0 );
3129 : 1 : QCOMPARE( fromArray5.zAt( 1 ), 22.0 );
3130 : 1 : QCOMPARE( fromArray5.xAt( 2 ), 3.0 );
3131 : 1 : QCOMPARE( fromArray5.yAt( 2 ), 13.0 );
3132 : 1 : QCOMPARE( fromArray5.zAt( 2 ), 23.0 );
3133 : : // with m
3134 : 1 : QVector< double > mm;
3135 : 1 : xx = QVector< double >() << 1 << 2 << 3;
3136 : 1 : yy = QVector< double >() << 11 << 12 << 13;
3137 : 1 : mm = QVector< double >() << 21 << 22 << 23;
3138 : 1 : QgsLineString fromArray6( xx, yy, QVector< double >(), mm );
3139 : 1 : QCOMPARE( fromArray6.wkbType(), QgsWkbTypes::LineStringM );
3140 : 1 : QCOMPARE( fromArray6.numPoints(), 3 );
3141 : 1 : QCOMPARE( fromArray6.xAt( 0 ), 1.0 );
3142 : 1 : QCOMPARE( fromArray6.yAt( 0 ), 11.0 );
3143 : 1 : QCOMPARE( fromArray6.mAt( 0 ), 21.0 );
3144 : 1 : QCOMPARE( fromArray6.xAt( 1 ), 2.0 );
3145 : 1 : QCOMPARE( fromArray6.yAt( 1 ), 12.0 );
3146 : 1 : QCOMPARE( fromArray6.mAt( 1 ), 22.0 );
3147 : 1 : QCOMPARE( fromArray6.xAt( 2 ), 3.0 );
3148 : 1 : QCOMPARE( fromArray6.yAt( 2 ), 13.0 );
3149 : 1 : QCOMPARE( fromArray6.mAt( 2 ), 23.0 );
3150 : : // unbalanced -> m ignored
3151 : 1 : mm = QVector< double >() << 21 << 22;
3152 : 1 : QgsLineString fromArray7( xx, yy, QVector< double >(), mm );
3153 : 1 : QCOMPARE( fromArray7.wkbType(), QgsWkbTypes::LineString );
3154 : 1 : QCOMPARE( fromArray7.numPoints(), 3 );
3155 : 1 : QCOMPARE( fromArray7.xAt( 0 ), 1.0 );
3156 : 1 : QCOMPARE( fromArray7.yAt( 0 ), 11.0 );
3157 : 1 : QCOMPARE( fromArray7.xAt( 1 ), 2.0 );
3158 : 1 : QCOMPARE( fromArray7.yAt( 1 ), 12.0 );
3159 : 1 : QCOMPARE( fromArray7.xAt( 2 ), 3.0 );
3160 : 1 : QCOMPARE( fromArray7.yAt( 2 ), 13.0 );
3161 : : // unbalanced -> m truncated
3162 : 1 : mm = QVector< double >() << 21 << 22 << 23 << 24;
3163 : 1 : fromArray7 = QgsLineString( xx, yy, QVector< double >(), mm );
3164 : 1 : QCOMPARE( fromArray7.wkbType(), QgsWkbTypes::LineStringM );
3165 : 1 : QCOMPARE( fromArray7.numPoints(), 3 );
3166 : 1 : QCOMPARE( fromArray7.xAt( 0 ), 1.0 );
3167 : 1 : QCOMPARE( fromArray7.yAt( 0 ), 11.0 );
3168 : 1 : QCOMPARE( fromArray7.mAt( 0 ), 21.0 );
3169 : 1 : QCOMPARE( fromArray7.xAt( 1 ), 2.0 );
3170 : 1 : QCOMPARE( fromArray7.yAt( 1 ), 12.0 );
3171 : 1 : QCOMPARE( fromArray7.mAt( 1 ), 22.0 );
3172 : 1 : QCOMPARE( fromArray7.xAt( 2 ), 3.0 );
3173 : 1 : QCOMPARE( fromArray7.yAt( 2 ), 13.0 );
3174 : 1 : QCOMPARE( fromArray7.mAt( 2 ), 23.0 );
3175 : : // zm
3176 : 1 : xx = QVector< double >() << 1 << 2 << 3;
3177 : 1 : yy = QVector< double >() << 11 << 12 << 13;
3178 : 1 : zz = QVector< double >() << 21 << 22 << 23;
3179 : 1 : mm = QVector< double >() << 31 << 32 << 33;
3180 : 1 : QgsLineString fromArray8( xx, yy, zz, mm );
3181 : 1 : QCOMPARE( fromArray8.wkbType(), QgsWkbTypes::LineStringZM );
3182 : 1 : QCOMPARE( fromArray8.numPoints(), 3 );
3183 : 1 : QCOMPARE( fromArray8.xAt( 0 ), 1.0 );
3184 : 1 : QCOMPARE( fromArray8.yAt( 0 ), 11.0 );
3185 : 1 : QCOMPARE( fromArray8.zAt( 0 ), 21.0 );
3186 : 1 : QCOMPARE( fromArray8.mAt( 0 ), 31.0 );
3187 : 1 : QCOMPARE( fromArray8.xAt( 1 ), 2.0 );
3188 : 1 : QCOMPARE( fromArray8.yAt( 1 ), 12.0 );
3189 : 1 : QCOMPARE( fromArray8.zAt( 1 ), 22.0 );
3190 : 1 : QCOMPARE( fromArray8.mAt( 1 ), 32.0 );
3191 : 1 : QCOMPARE( fromArray8.xAt( 2 ), 3.0 );
3192 : 1 : QCOMPARE( fromArray8.yAt( 2 ), 13.0 );
3193 : 1 : QCOMPARE( fromArray8.zAt( 2 ), 23.0 );
3194 : 1 : QCOMPARE( fromArray8.mAt( 2 ), 33.0 );
3195 : :
3196 : 1 : QCOMPARE( *fromArray8.xData(), 1.0 );
3197 : 1 : QCOMPARE( *( fromArray8.xData() + 1 ), 2.0 );
3198 : 1 : QCOMPARE( *( fromArray8.xData() + 2 ), 3.0 );
3199 : 1 : QCOMPARE( *fromArray8.yData(), 11.0 );
3200 : 1 : QCOMPARE( *( fromArray8.yData() + 1 ), 12.0 );
3201 : 1 : QCOMPARE( *( fromArray8.yData() + 2 ), 13.0 );
3202 : 1 : QCOMPARE( *fromArray8.zData(), 21.0 );
3203 : 1 : QCOMPARE( *( fromArray8.zData() + 1 ), 22.0 );
3204 : 1 : QCOMPARE( *( fromArray8.zData() + 2 ), 23.0 );
3205 : 1 : QCOMPARE( *fromArray8.mData(), 31.0 );
3206 : 1 : QCOMPARE( *( fromArray8.mData() + 1 ), 32.0 );
3207 : 1 : QCOMPARE( *( fromArray8.mData() + 2 ), 33.0 );
3208 : :
3209 : : // from QList<QgsPointXY>
3210 : 1 : QgsLineString fromPtsA = QgsLineString( QgsPointSequence() );
3211 : 1 : QVERIFY( fromPtsA.isEmpty() );
3212 : 1 : QCOMPARE( fromPtsA.wkbType(), QgsWkbTypes::LineString );
3213 : :
3214 : 1 : fromPtsA = QgsLineString( QgsPointSequence() << QgsPoint( 1, 2, 0, 4, QgsWkbTypes::PointM ) );
3215 : 1 : QCOMPARE( fromPtsA.numPoints(), 1 );
3216 : 1 : QCOMPARE( fromPtsA.wkbType(), QgsWkbTypes::LineStringM );
3217 : :
3218 : 1 : QVector<QgsPointXY> ptsA;
3219 : 1 : ptsA << QgsPointXY( 1, 2 ) << QgsPointXY( 11, 12 ) << QgsPointXY( 21, 22 );
3220 : 1 : QgsLineString fromPts( ptsA );
3221 : 1 : QCOMPARE( fromPts.wkbType(), QgsWkbTypes::LineString );
3222 : 1 : QCOMPARE( fromPts.numPoints(), 3 );
3223 : 1 : QCOMPARE( fromPts.xAt( 0 ), 1.0 );
3224 : 1 : QCOMPARE( fromPts.yAt( 0 ), 2.0 );
3225 : 1 : QCOMPARE( fromPts.xAt( 1 ), 11.0 );
3226 : 1 : QCOMPARE( fromPts.yAt( 1 ), 12.0 );
3227 : 1 : QCOMPARE( fromPts.xAt( 2 ), 21.0 );
3228 : 1 : QCOMPARE( fromPts.yAt( 2 ), 22.0 );
3229 : :
3230 : : // from QgsPointSequence
3231 : 1 : QgsPointSequence ptsVector;
3232 : 1 : ptsVector << QgsPoint( 10, 20 ) << QgsPoint( 30, 40 );
3233 : 1 : QgsLineString fromVector( ptsVector );
3234 : 1 : QCOMPARE( fromVector.wkbType(), QgsWkbTypes::LineString );
3235 : 1 : QCOMPARE( fromVector.numPoints(), 2 );
3236 : 1 : QCOMPARE( fromVector.xAt( 0 ), 10.0 );
3237 : 1 : QCOMPARE( fromVector.yAt( 0 ), 20.0 );
3238 : 1 : QCOMPARE( fromVector.xAt( 1 ), 30.0 );
3239 : 1 : QCOMPARE( fromVector.yAt( 1 ), 40.0 );
3240 : 1 : QgsPointSequence ptsVector3D;
3241 : 1 : ptsVector3D << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 40, 200 );
3242 : 1 : QgsLineString fromVector3D( ptsVector3D );
3243 : 1 : QCOMPARE( fromVector3D.wkbType(), QgsWkbTypes::LineStringZ );
3244 : 1 : QCOMPARE( fromVector3D.numPoints(), 2 );
3245 : 1 : QCOMPARE( fromVector3D.xAt( 0 ), 10.0 );
3246 : 1 : QCOMPARE( fromVector3D.yAt( 0 ), 20.0 );
3247 : 1 : QCOMPARE( fromVector3D.zAt( 0 ), 100.0 );
3248 : 1 : QCOMPARE( fromVector3D.xAt( 1 ), 30.0 );
3249 : 1 : QCOMPARE( fromVector3D.yAt( 1 ), 40.0 );
3250 : 1 : QCOMPARE( fromVector3D.zAt( 1 ), 200.0 );
3251 : :
3252 : : // from 2 points
3253 : 1 : QgsLineString from2Pts( QgsPoint( 1, 2 ), QgsPoint( 21, 22 ) );
3254 : 1 : QCOMPARE( from2Pts.wkbType(), QgsWkbTypes::LineString );
3255 : 1 : QCOMPARE( from2Pts.numPoints(), 2 );
3256 : 1 : QCOMPARE( from2Pts.xAt( 0 ), 1.0 );
3257 : 1 : QCOMPARE( from2Pts.yAt( 0 ), 2.0 );
3258 : 1 : QCOMPARE( from2Pts.xAt( 1 ), 21.0 );
3259 : 1 : QCOMPARE( from2Pts.yAt( 1 ), 22.0 );
3260 : 1 : from2Pts = QgsLineString( QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ), QgsPoint( QgsWkbTypes::PointZ, 21, 22, 23 ) );
3261 : 1 : QCOMPARE( from2Pts.wkbType(), QgsWkbTypes::LineStringZ );
3262 : 1 : QCOMPARE( from2Pts.numPoints(), 2 );
3263 : 1 : QCOMPARE( from2Pts.xAt( 0 ), 1.0 );
3264 : 1 : QCOMPARE( from2Pts.yAt( 0 ), 2.0 );
3265 : 1 : QCOMPARE( from2Pts.zAt( 0 ), 3.0 );
3266 : 1 : QCOMPARE( from2Pts.xAt( 1 ), 21.0 );
3267 : 1 : QCOMPARE( from2Pts.yAt( 1 ), 22.0 );
3268 : 1 : QCOMPARE( from2Pts.zAt( 1 ), 23.0 );
3269 : 1 : from2Pts = QgsLineString( QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ), QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 23 ) );
3270 : 1 : QCOMPARE( from2Pts.wkbType(), QgsWkbTypes::LineStringM );
3271 : 1 : QCOMPARE( from2Pts.numPoints(), 2 );
3272 : 1 : QCOMPARE( from2Pts.xAt( 0 ), 1.0 );
3273 : 1 : QCOMPARE( from2Pts.yAt( 0 ), 2.0 );
3274 : 1 : QCOMPARE( from2Pts.mAt( 0 ), 3.0 );
3275 : 1 : QCOMPARE( from2Pts.xAt( 1 ), 21.0 );
3276 : 1 : QCOMPARE( from2Pts.yAt( 1 ), 22.0 );
3277 : 1 : QCOMPARE( from2Pts.mAt( 1 ), 23.0 );
3278 : 1 : from2Pts = QgsLineString( QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ) );
3279 : 1 : QCOMPARE( from2Pts.wkbType(), QgsWkbTypes::LineStringZM );
3280 : 1 : QCOMPARE( from2Pts.numPoints(), 2 );
3281 : 1 : QCOMPARE( from2Pts.xAt( 0 ), 1.0 );
3282 : 1 : QCOMPARE( from2Pts.yAt( 0 ), 2.0 );
3283 : 1 : QCOMPARE( from2Pts.zAt( 0 ), 3.0 );
3284 : 1 : QCOMPARE( from2Pts.mAt( 0 ), 4.0 );
3285 : 1 : QCOMPARE( from2Pts.xAt( 1 ), 21.0 );
3286 : 1 : QCOMPARE( from2Pts.yAt( 1 ), 22.0 );
3287 : 1 : QCOMPARE( from2Pts.zAt( 1 ), 23.0 );
3288 : 1 : QCOMPARE( from2Pts.mAt( 1 ), 24.0 );
3289 : :
3290 : : // from lineSegment
3291 : 1 : QgsLineString fromSegment( QgsLineSegment2D( QgsPointXY( 1, 2 ), QgsPointXY( 3, 4 ) ) );
3292 : 1 : QCOMPARE( fromSegment.wkbType(), QgsWkbTypes::LineString );
3293 : 1 : QCOMPARE( fromSegment.numPoints(), 2 );
3294 : 1 : QCOMPARE( fromSegment.xAt( 0 ), 1.0 );
3295 : 1 : QCOMPARE( fromSegment.yAt( 0 ), 2.0 );
3296 : 1 : QCOMPARE( fromSegment.xAt( 1 ), 3.0 );
3297 : 1 : QCOMPARE( fromSegment.yAt( 1 ), 4.0 );
3298 : :
3299 : : //addVertex
3300 : 1 : QgsLineString l2;
3301 : 1 : l2.addVertex( QgsPoint( 1.0, 2.0 ) );
3302 : 1 : QVERIFY( !l2.isEmpty() );
3303 : 1 : QCOMPARE( l2.numPoints(), 1 );
3304 : 1 : QCOMPARE( l2.vertexCount(), 1 );
3305 : 1 : QCOMPARE( l2.nCoordinates(), 1 );
3306 : 1 : QCOMPARE( l2.ringCount(), 1 );
3307 : 1 : QCOMPARE( l2.partCount(), 1 );
3308 : 1 : QVERIFY( !l2.is3D() );
3309 : 1 : QVERIFY( !l2.isMeasure() );
3310 : 1 : QCOMPARE( l2.wkbType(), QgsWkbTypes::LineString );
3311 : 1 : QVERIFY( !l2.hasCurvedSegments() );
3312 : 1 : QCOMPARE( l2.area(), 0.0 );
3313 : 1 : QCOMPARE( l2.perimeter(), 0.0 );
3314 : :
3315 : : //adding first vertex should set linestring z/m type
3316 : 1 : QgsLineString l3;
3317 : 1 : l3.addVertex( QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) );
3318 : 1 : QVERIFY( !l3.isEmpty() );
3319 : 1 : QVERIFY( l3.is3D() );
3320 : 1 : QVERIFY( !l3.isMeasure() );
3321 : 1 : QCOMPARE( l3.wkbType(), QgsWkbTypes::LineStringZ );
3322 : 1 : QCOMPARE( l3.wktTypeStr(), QString( "LineStringZ" ) );
3323 : :
3324 : 1 : QgsLineString l4;
3325 : 1 : l4.addVertex( QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 ) );
3326 : 1 : QVERIFY( !l4.isEmpty() );
3327 : 1 : QVERIFY( !l4.is3D() );
3328 : 1 : QVERIFY( l4.isMeasure() );
3329 : 1 : QCOMPARE( l4.wkbType(), QgsWkbTypes::LineStringM );
3330 : 1 : QCOMPARE( l4.wktTypeStr(), QString( "LineStringM" ) );
3331 : :
3332 : 1 : QgsLineString l5;
3333 : 1 : l5.addVertex( QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
3334 : 1 : QVERIFY( !l5.isEmpty() );
3335 : 1 : QVERIFY( l5.is3D() );
3336 : 1 : QVERIFY( l5.isMeasure() );
3337 : 1 : QCOMPARE( l5.wkbType(), QgsWkbTypes::LineStringZM );
3338 : 1 : QCOMPARE( l5.wktTypeStr(), QString( "LineStringZM" ) );
3339 : :
3340 : 1 : QgsLineString l25d;
3341 : 1 : l25d.addVertex( QgsPoint( QgsWkbTypes::Point25D, 1.0, 2.0, 3.0 ) );
3342 : 1 : QVERIFY( !l25d.isEmpty() );
3343 : 1 : QVERIFY( l25d.is3D() );
3344 : 1 : QVERIFY( !l25d.isMeasure() );
3345 : 1 : QCOMPARE( l25d.wkbType(), QgsWkbTypes::LineString25D );
3346 : 1 : QCOMPARE( l25d.wktTypeStr(), QString( "LineStringZ" ) );
3347 : :
3348 : : //adding subsequent vertices should not alter z/m type, regardless of points type
3349 : 1 : QgsLineString l6;
3350 : 1 : l6.addVertex( QgsPoint( QgsWkbTypes::Point, 1.0, 2.0 ) ); //2d type
3351 : 1 : QCOMPARE( l6.wkbType(), QgsWkbTypes::LineString );
3352 : 1 : l6.addVertex( QgsPoint( QgsWkbTypes::PointZ, 11.0, 12.0, 13.0 ) ); // add 3d point
3353 : 1 : QCOMPARE( l6.numPoints(), 2 );
3354 : 1 : QCOMPARE( l6.vertexCount(), 2 );
3355 : 1 : QCOMPARE( l6.nCoordinates(), 2 );
3356 : 1 : QCOMPARE( l6.ringCount(), 1 );
3357 : 1 : QCOMPARE( l6.partCount(), 1 );
3358 : 1 : QCOMPARE( l6.wkbType(), QgsWkbTypes::LineString ); //should still be 2d
3359 : 1 : QVERIFY( !l6.is3D() );
3360 : 1 : QCOMPARE( l6.area(), 0.0 );
3361 : 1 : QCOMPARE( l6.perimeter(), 0.0 );
3362 : :
3363 : 1 : QgsLineString l7;
3364 : 1 : l7.addVertex( QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) ); //3d type
3365 : 1 : QCOMPARE( l7.wkbType(), QgsWkbTypes::LineStringZ );
3366 : 1 : l7.addVertex( QgsPoint( QgsWkbTypes::Point, 11.0, 12.0 ) ); //add 2d point
3367 : 1 : QCOMPARE( l7.wkbType(), QgsWkbTypes::LineStringZ ); //should still be 3d
3368 : 1 : QCOMPARE( l7.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11.0, 12.0 ) );
3369 : 1 : QVERIFY( l7.is3D() );
3370 : 1 : QCOMPARE( l7.numPoints(), 2 );
3371 : 1 : QCOMPARE( l7.vertexCount(), 2 );
3372 : 1 : QCOMPARE( l7.nCoordinates(), 2 );
3373 : 1 : QCOMPARE( l7.ringCount(), 1 );
3374 : 1 : QCOMPARE( l7.partCount(), 1 );
3375 : :
3376 : : //clear
3377 : 1 : l7.clear();
3378 : 1 : QVERIFY( l7.isEmpty() );
3379 : 1 : QCOMPARE( l7.numPoints(), 0 );
3380 : 1 : QCOMPARE( l7.vertexCount(), 0 );
3381 : 1 : QCOMPARE( l7.nCoordinates(), 0 );
3382 : 1 : QCOMPARE( l7.ringCount(), 0 );
3383 : 1 : QCOMPARE( l7.partCount(), 0 );
3384 : 1 : QVERIFY( !l7.is3D() );
3385 : 1 : QVERIFY( !l7.isMeasure() );
3386 : 1 : QCOMPARE( l7.wkbType(), QgsWkbTypes::LineString );
3387 : :
3388 : : //setPoints
3389 : 1 : QgsLineString l8;
3390 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
3391 : 1 : QVERIFY( !l8.isEmpty() );
3392 : 1 : QCOMPARE( l8.numPoints(), 3 );
3393 : 1 : QCOMPARE( l8.vertexCount(), 3 );
3394 : 1 : QCOMPARE( l8.nCoordinates(), 3 );
3395 : 1 : QCOMPARE( l8.ringCount(), 1 );
3396 : 1 : QCOMPARE( l8.partCount(), 1 );
3397 : 1 : QVERIFY( !l8.is3D() );
3398 : 1 : QVERIFY( !l8.isMeasure() );
3399 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineString );
3400 : 1 : QVERIFY( !l8.hasCurvedSegments() );
3401 : 1 : QgsPointSequence pts;
3402 : 1 : l8.points( pts );
3403 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
3404 : 1 : QCOMPARE( *l8.xData(), 1.0 );
3405 : 1 : QCOMPARE( *( l8.xData() + 1 ), 2.0 );
3406 : 1 : QCOMPARE( *( l8.xData() + 2 ), 3.0 );
3407 : 1 : QCOMPARE( *l8.yData(), 2.0 );
3408 : 1 : QCOMPARE( *( l8.yData() + 1 ), 3.0 );
3409 : 1 : QCOMPARE( *( l8.yData() + 2 ), 4.0 );
3410 : :
3411 : : //setPoints with empty list, should clear linestring
3412 : 1 : l8.setPoints( QgsPointSequence() );
3413 : 1 : QVERIFY( l8.isEmpty() );
3414 : 1 : QCOMPARE( l8.numPoints(), 0 );
3415 : 1 : QCOMPARE( l8.vertexCount(), 0 );
3416 : 1 : QCOMPARE( l8.nCoordinates(), 0 );
3417 : 1 : QCOMPARE( l8.ringCount(), 0 );
3418 : 1 : QCOMPARE( l8.partCount(), 0 );
3419 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineString );
3420 : 1 : l8.points( pts );
3421 : 1 : QVERIFY( pts.isEmpty() );
3422 : :
3423 : : //setPoints with z
3424 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) );
3425 : 1 : QCOMPARE( l8.numPoints(), 2 );
3426 : 1 : QVERIFY( l8.is3D() );
3427 : 1 : QVERIFY( !l8.isMeasure() );
3428 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineStringZ );
3429 : 1 : l8.points( pts );
3430 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) );
3431 : :
3432 : : //setPoints with 25d
3433 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 4 ) << QgsPoint( QgsWkbTypes::Point25D, 2, 3, 4 ) );
3434 : 1 : QCOMPARE( l8.numPoints(), 2 );
3435 : 1 : QVERIFY( l8.is3D() );
3436 : 1 : QVERIFY( !l8.isMeasure() );
3437 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineString25D );
3438 : 1 : QCOMPARE( l8.pointN( 0 ), QgsPoint( QgsWkbTypes::Point25D, 1, 2, 4 ) );
3439 : 1 : l8.points( pts );
3440 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 4 ) << QgsPoint( QgsWkbTypes::Point25D, 2, 3, 4 ) );
3441 : :
3442 : : //setPoints with m
3443 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) );
3444 : 1 : QCOMPARE( l8.numPoints(), 2 );
3445 : 1 : QVERIFY( !l8.is3D() );
3446 : 1 : QVERIFY( l8.isMeasure() );
3447 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineStringM );
3448 : 1 : l8.points( pts );
3449 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) );
3450 : :
3451 : : //setPoints with zm
3452 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 4, 5 ) );
3453 : 1 : QCOMPARE( l8.numPoints(), 2 );
3454 : 1 : QVERIFY( l8.is3D() );
3455 : 1 : QVERIFY( l8.isMeasure() );
3456 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineStringZM );
3457 : 1 : l8.points( pts );
3458 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 4, 5 ) );
3459 : :
3460 : : //setPoints with MIXED dimensionality of points
3461 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 5 ) );
3462 : 1 : QCOMPARE( l8.numPoints(), 2 );
3463 : 1 : QVERIFY( l8.is3D() );
3464 : 1 : QVERIFY( l8.isMeasure() );
3465 : 1 : QCOMPARE( l8.wkbType(), QgsWkbTypes::LineStringZM );
3466 : 1 : l8.points( pts );
3467 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 0, 5 ) );
3468 : :
3469 : : //test point
3470 : 1 : QCOMPARE( l8.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) );
3471 : 1 : QCOMPARE( l8.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 2, 3, 0, 5 ) );
3472 : :
3473 : : //out of range - just want no crash here
3474 : 1 : QgsPoint bad = l8.pointN( -1 );
3475 : 1 : bad = l8.pointN( 100 );
3476 : :
3477 : : //test getters/setters
3478 : 1 : QgsLineString l9;
3479 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
3480 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 )
3481 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ) );
3482 : 1 : QCOMPARE( l9.xAt( 0 ), 1.0 );
3483 : 1 : QCOMPARE( l9.xAt( 1 ), 11.0 );
3484 : 1 : QCOMPARE( l9.xAt( 2 ), 21.0 );
3485 : 1 : QCOMPARE( l9.xAt( -1 ), 0.0 ); //out of range
3486 : 1 : QCOMPARE( l9.xAt( 11 ), 0.0 ); //out of range
3487 : :
3488 : 1 : l9.setXAt( 0, 51.0 );
3489 : 1 : QCOMPARE( l9.xAt( 0 ), 51.0 );
3490 : 1 : l9.setXAt( 1, 61.0 );
3491 : 1 : QCOMPARE( l9.xAt( 1 ), 61.0 );
3492 : 1 : l9.setXAt( -1, 51.0 ); //out of range
3493 : 1 : l9.setXAt( 11, 51.0 ); //out of range
3494 : :
3495 : 1 : QCOMPARE( l9.yAt( 0 ), 2.0 );
3496 : 1 : QCOMPARE( l9.yAt( 1 ), 12.0 );
3497 : 1 : QCOMPARE( l9.yAt( 2 ), 22.0 );
3498 : 1 : QCOMPARE( l9.yAt( -1 ), 0.0 ); //out of range
3499 : 1 : QCOMPARE( l9.yAt( 11 ), 0.0 ); //out of range
3500 : :
3501 : 1 : l9.setYAt( 0, 52.0 );
3502 : 1 : QCOMPARE( l9.yAt( 0 ), 52.0 );
3503 : 1 : l9.setYAt( 1, 62.0 );
3504 : 1 : QCOMPARE( l9.yAt( 1 ), 62.0 );
3505 : 1 : l9.setYAt( -1, 52.0 ); //out of range
3506 : 1 : l9.setYAt( 11, 52.0 ); //out of range
3507 : :
3508 : 1 : QCOMPARE( l9.zAt( 0 ), 3.0 );
3509 : 1 : QCOMPARE( l9.zAt( 1 ), 13.0 );
3510 : 1 : QCOMPARE( l9.zAt( 2 ), 23.0 );
3511 : 1 : QVERIFY( std::isnan( l9.zAt( -1 ) ) ); //out of range
3512 : 1 : QVERIFY( std::isnan( l9.zAt( 11 ) ) ); //out of range
3513 : :
3514 : 1 : l9.setZAt( 0, 53.0 );
3515 : 1 : QCOMPARE( l9.zAt( 0 ), 53.0 );
3516 : 1 : l9.setZAt( 1, 63.0 );
3517 : 1 : QCOMPARE( l9.zAt( 1 ), 63.0 );
3518 : 1 : l9.setZAt( -1, 53.0 ); //out of range
3519 : 1 : l9.setZAt( 11, 53.0 ); //out of range
3520 : :
3521 : 1 : QCOMPARE( l9.mAt( 0 ), 4.0 );
3522 : 1 : QCOMPARE( l9.mAt( 1 ), 14.0 );
3523 : 1 : QCOMPARE( l9.mAt( 2 ), 24.0 );
3524 : 1 : QVERIFY( std::isnan( l9.mAt( -1 ) ) ); //out of range
3525 : 1 : QVERIFY( std::isnan( l9.mAt( 11 ) ) ); //out of range
3526 : :
3527 : 1 : l9.setMAt( 0, 54.0 );
3528 : 1 : QCOMPARE( l9.mAt( 0 ), 54.0 );
3529 : 1 : l9.setMAt( 1, 64.0 );
3530 : 1 : QCOMPARE( l9.mAt( 1 ), 64.0 );
3531 : 1 : l9.setMAt( -1, 54.0 ); //out of range
3532 : 1 : l9.setMAt( 11, 54.0 ); //out of range
3533 : :
3534 : : //check zAt/setZAt with non-3d linestring
3535 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 )
3536 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 )
3537 : 1 : << QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 24 ) );
3538 : :
3539 : : //basically we just don't want these to crash
3540 : 1 : QVERIFY( std::isnan( l9.zAt( 0 ) ) );
3541 : 1 : QVERIFY( std::isnan( l9.zAt( 1 ) ) );
3542 : 1 : l9.setZAt( 0, 53.0 );
3543 : 1 : l9.setZAt( 1, 63.0 );
3544 : :
3545 : : //check mAt/setMAt with non-measure linestring
3546 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
3547 : 1 : << QgsPoint( 11, 12 )
3548 : 1 : << QgsPoint( 21, 22 ) );
3549 : :
3550 : : //basically we just don't want these to crash
3551 : 1 : QVERIFY( std::isnan( l9.mAt( 0 ) ) );
3552 : 1 : QVERIFY( std::isnan( l9.mAt( 1 ) ) );
3553 : 1 : l9.setMAt( 0, 53.0 );
3554 : 1 : l9.setMAt( 1, 63.0 );
3555 : :
3556 : : //append linestring
3557 : :
3558 : : //append to empty
3559 : 1 : QgsLineString l10;
3560 : 1 : l10.append( nullptr );
3561 : 1 : QVERIFY( l10.isEmpty() );
3562 : 1 : QCOMPARE( l10.numPoints(), 0 );
3563 : :
3564 : 1 : std::unique_ptr<QgsLineString> toAppend( new QgsLineString() );
3565 : 2 : toAppend->setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
3566 : 1 : << QgsPoint( 11, 12 )
3567 : 1 : << QgsPoint( 21, 22 ) );
3568 : 1 : l10.append( toAppend.get() );
3569 : 1 : QVERIFY( !l10.is3D() );
3570 : 1 : QVERIFY( !l10.isMeasure() );
3571 : 1 : QCOMPARE( l10.numPoints(), 3 );
3572 : 1 : QCOMPARE( l10.vertexCount(), 3 );
3573 : 1 : QCOMPARE( l10.nCoordinates(), 3 );
3574 : 1 : QCOMPARE( l10.ringCount(), 1 );
3575 : 1 : QCOMPARE( l10.partCount(), 1 );
3576 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineString );
3577 : 1 : QCOMPARE( l10.pointN( 0 ), toAppend->pointN( 0 ) );
3578 : 1 : QCOMPARE( l10.pointN( 1 ), toAppend->pointN( 1 ) );
3579 : 1 : QCOMPARE( l10.pointN( 2 ), toAppend->pointN( 2 ) );
3580 : :
3581 : : //add more points
3582 : 1 : toAppend.reset( new QgsLineString() );
3583 : 2 : toAppend->setPoints( QgsPointSequence() << QgsPoint( 31, 32 )
3584 : 1 : << QgsPoint( 41, 42 )
3585 : 1 : << QgsPoint( 51, 52 ) );
3586 : 1 : l10.append( toAppend.get() );
3587 : 1 : QCOMPARE( l10.numPoints(), 6 );
3588 : 1 : QCOMPARE( l10.vertexCount(), 6 );
3589 : 1 : QCOMPARE( l10.nCoordinates(), 6 );
3590 : 1 : QCOMPARE( l10.ringCount(), 1 );
3591 : 1 : QCOMPARE( l10.partCount(), 1 );
3592 : 1 : QCOMPARE( l10.pointN( 3 ), toAppend->pointN( 0 ) );
3593 : 1 : QCOMPARE( l10.pointN( 4 ), toAppend->pointN( 1 ) );
3594 : 1 : QCOMPARE( l10.pointN( 5 ), toAppend->pointN( 2 ) );
3595 : :
3596 : : //check dimensionality is inherited from append line if initially empty
3597 : 1 : l10.clear();
3598 : 1 : toAppend.reset( new QgsLineString() );
3599 : 2 : toAppend->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 31, 32, 33, 34 )
3600 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 41, 42, 43, 44 )
3601 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 51, 52, 53, 54 ) );
3602 : 1 : l10.append( toAppend.get() );
3603 : 1 : QVERIFY( l10.is3D() );
3604 : 1 : QVERIFY( l10.isMeasure() );
3605 : 1 : QCOMPARE( l10.numPoints(), 3 );
3606 : 1 : QCOMPARE( l10.ringCount(), 1 );
3607 : 1 : QCOMPARE( l10.partCount(), 1 );
3608 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineStringZM );
3609 : 1 : QCOMPARE( l10.pointN( 0 ), toAppend->pointN( 0 ) );
3610 : 1 : QCOMPARE( l10.pointN( 1 ), toAppend->pointN( 1 ) );
3611 : 1 : QCOMPARE( l10.pointN( 2 ), toAppend->pointN( 2 ) );
3612 : :
3613 : : //append points with z to non z linestring
3614 : 1 : l10.clear();
3615 : 1 : l10.addVertex( QgsPoint( 1.0, 2.0 ) );
3616 : 1 : QVERIFY( !l10.is3D() );
3617 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineString );
3618 : 1 : toAppend.reset( new QgsLineString() );
3619 : 2 : toAppend->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 31, 32, 33, 34 )
3620 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 41, 42, 43, 44 )
3621 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 51, 52, 53, 54 ) );
3622 : 1 : l10.append( toAppend.get() );
3623 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineString );
3624 : 1 : QCOMPARE( l10.pointN( 0 ), QgsPoint( 1, 2 ) );
3625 : 1 : QCOMPARE( l10.pointN( 1 ), QgsPoint( 31, 32 ) );
3626 : 1 : QCOMPARE( l10.pointN( 2 ), QgsPoint( 41, 42 ) );
3627 : 1 : QCOMPARE( l10.pointN( 3 ), QgsPoint( 51, 52 ) );
3628 : :
3629 : : //append points without z/m to linestring with z & m
3630 : 1 : l10.clear();
3631 : 1 : l10.addVertex( QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
3632 : 1 : QVERIFY( l10.is3D() );
3633 : 1 : QVERIFY( l10.isMeasure() );
3634 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineStringZM );
3635 : 1 : toAppend.reset( new QgsLineString() );
3636 : 2 : toAppend->setPoints( QgsPointSequence() << QgsPoint( 31, 32 )
3637 : 1 : << QgsPoint( 41, 42 )
3638 : 1 : << QgsPoint( 51, 52 ) );
3639 : 1 : l10.append( toAppend.get() );
3640 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineStringZM );
3641 : 1 : QCOMPARE( l10.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
3642 : 1 : QCOMPARE( l10.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 31, 32 ) );
3643 : 1 : QCOMPARE( l10.pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 41, 42 ) );
3644 : 1 : QCOMPARE( l10.pointN( 3 ), QgsPoint( QgsWkbTypes::PointZM, 51, 52 ) );
3645 : :
3646 : : //25d append
3647 : 1 : l10.clear();
3648 : 1 : toAppend.reset( new QgsLineString() );
3649 : 2 : toAppend->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 31, 32, 33 )
3650 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 41, 42, 43 ) );
3651 : 1 : l10.append( toAppend.get() );
3652 : 1 : QVERIFY( l10.is3D() );
3653 : 1 : QVERIFY( !l10.isMeasure() );
3654 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineString25D );
3655 : 1 : QCOMPARE( l10.pointN( 0 ), QgsPoint( QgsWkbTypes::Point25D, 31, 32, 33 ) );
3656 : 1 : QCOMPARE( l10.pointN( 1 ), QgsPoint( QgsWkbTypes::Point25D, 41, 42, 43 ) );
3657 : 1 : l10.clear();
3658 : 1 : l10.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 11, 12, 33 ) );
3659 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineString25D );
3660 : 1 : l10.append( toAppend.get() );
3661 : 1 : QVERIFY( l10.is3D() );
3662 : 1 : QVERIFY( !l10.isMeasure() );
3663 : 1 : QCOMPARE( l10.wkbType(), QgsWkbTypes::LineString25D );
3664 : 1 : QCOMPARE( l10.pointN( 0 ), QgsPoint( QgsWkbTypes::Point25D, 11, 12, 33 ) );
3665 : 1 : QCOMPARE( l10.pointN( 1 ), QgsPoint( QgsWkbTypes::Point25D, 31, 32, 33 ) );
3666 : 1 : QCOMPARE( l10.pointN( 2 ), QgsPoint( QgsWkbTypes::Point25D, 41, 42, 43 ) );
3667 : :
3668 : : //append another line the closes the original geometry.
3669 : : //Make sure there are not duplicit points except start and end point
3670 : 1 : l10.clear();
3671 : 1 : toAppend.reset( new QgsLineString() );
3672 : 2 : toAppend->setPoints( QgsPointSequence()
3673 : 1 : << QgsPoint( 1, 1 )
3674 : 1 : << QgsPoint( 5, 5 )
3675 : 1 : << QgsPoint( 10, 1 ) );
3676 : 1 : l10.append( toAppend.get() );
3677 : 1 : QCOMPARE( l10.numPoints(), 3 );
3678 : 1 : QCOMPARE( l10.vertexCount(), 3 );
3679 : 1 : toAppend.reset( new QgsLineString() );
3680 : 2 : toAppend->setPoints( QgsPointSequence()
3681 : 1 : << QgsPoint( 10, 1 )
3682 : 1 : << QgsPoint( 1, 1 ) );
3683 : 1 : l10.append( toAppend.get() );
3684 : :
3685 : 1 : QVERIFY( l10.isClosed() );
3686 : 1 : QCOMPARE( l10.numPoints(), 4 );
3687 : 1 : QCOMPARE( l10.vertexCount(), 4 );
3688 : :
3689 : : //equality
3690 : 1 : QgsLineString e1;
3691 : 1 : QgsLineString e2;
3692 : 1 : QVERIFY( e1 == e2 );
3693 : 1 : QVERIFY( !( e1 != e2 ) );
3694 : 1 : e1.addVertex( QgsPoint( 1, 2 ) );
3695 : 1 : QVERIFY( !( e1 == e2 ) ); //different number of vertices
3696 : 1 : QVERIFY( e1 != e2 );
3697 : 1 : e2.addVertex( QgsPoint( 1, 2 ) );
3698 : 1 : QVERIFY( e1 == e2 );
3699 : 1 : QVERIFY( !( e1 != e2 ) );
3700 : 1 : e1.addVertex( QgsPoint( 1 / 3.0, 4 / 3.0 ) );
3701 : 1 : e2.addVertex( QgsPoint( 2 / 6.0, 8 / 6.0 ) );
3702 : 1 : QVERIFY( e1 == e2 ); //check non-integer equality
3703 : 1 : QVERIFY( !( e1 != e2 ) );
3704 : 1 : e1.addVertex( QgsPoint( 7, 8 ) );
3705 : 1 : e2.addVertex( QgsPoint( 6, 9 ) );
3706 : 1 : QVERIFY( !( e1 == e2 ) ); //different coordinates
3707 : 1 : QVERIFY( e1 != e2 );
3708 : 1 : QgsLineString e3;
3709 : 2 : e3.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 0 )
3710 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1 / 3.0, 4 / 3.0, 0 )
3711 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 7, 8, 0 ) );
3712 : 1 : QVERIFY( !( e1 == e3 ) ); //different dimension
3713 : 1 : QVERIFY( e1 != e3 );
3714 : 1 : QgsLineString e4;
3715 : 2 : e4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 )
3716 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1 / 3.0, 4 / 3.0, 3 )
3717 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 7, 8, 4 ) );
3718 : 1 : QVERIFY( !( e3 == e4 ) ); //different z coordinates
3719 : 1 : QVERIFY( e3 != e4 );
3720 : 1 : QgsLineString e5;
3721 : 2 : e5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 1 )
3722 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1 / 3.0, 4 / 3.0, 0, 2 )
3723 : 1 : << QgsPoint( QgsWkbTypes::PointM, 7, 8, 0, 3 ) );
3724 : 1 : QgsLineString e6;
3725 : 2 : e6.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 11 )
3726 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1 / 3.0, 4 / 3.0, 0, 12 )
3727 : 1 : << QgsPoint( QgsWkbTypes::PointM, 7, 8, 0, 13 ) );
3728 : 1 : QVERIFY( !( e5 == e6 ) ); //different m values
3729 : 1 : QVERIFY( e5 != e6 );
3730 : :
3731 : 1 : QVERIFY( e6 != QgsCircularString() );
3732 : 1 : QgsPoint p1;
3733 : 1 : QVERIFY( !( e6 == p1 ) );
3734 : 1 : QVERIFY( e6 != p1 );
3735 : 1 : QVERIFY( e6 == e6 );
3736 : :
3737 : : //close/isClosed
3738 : 1 : QgsLineString l11;
3739 : 1 : QVERIFY( !l11.isClosed() );
3740 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
3741 : 1 : << QgsPoint( 11, 2 )
3742 : 1 : << QgsPoint( 11, 22 )
3743 : 1 : << QgsPoint( 1, 22 ) );
3744 : 1 : QVERIFY( !l11.isClosed() );
3745 : 1 : QCOMPARE( l11.numPoints(), 4 );
3746 : 1 : QCOMPARE( l11.area(), 0.0 );
3747 : 1 : QCOMPARE( l11.perimeter(), 0.0 );
3748 : 1 : l11.close();
3749 : 1 : QVERIFY( l11.isClosed() );
3750 : 1 : QCOMPARE( l11.numPoints(), 5 );
3751 : 1 : QCOMPARE( l11.vertexCount(), 5 );
3752 : 1 : QCOMPARE( l11.nCoordinates(), 5 );
3753 : 1 : QCOMPARE( l11.ringCount(), 1 );
3754 : 1 : QCOMPARE( l11.partCount(), 1 );
3755 : 1 : QCOMPARE( l11.pointN( 4 ), QgsPoint( 1, 2 ) );
3756 : 1 : QCOMPARE( l11.area(), 0.0 );
3757 : 1 : QCOMPARE( l11.perimeter(), 0.0 );
3758 : : //try closing already closed line, should be no change
3759 : 1 : l11.close();
3760 : 1 : QVERIFY( l11.isClosed() );
3761 : 1 : QCOMPARE( l11.numPoints(), 5 );
3762 : 1 : QCOMPARE( l11.pointN( 4 ), QgsPoint( 1, 2 ) );
3763 : :
3764 : : // tiny differences
3765 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( 0.000000000000001, 0.000000000000002 )
3766 : 1 : << QgsPoint( 0.000000000000011, 0.000000000000002 )
3767 : 1 : << QgsPoint( 0.000000000000011, 0.000000000000022 )
3768 : 1 : << QgsPoint( 0.000000000000001, 0.000000000000022 ) );
3769 : 1 : QVERIFY( !l11.isClosed() );
3770 : 1 : l11.close();
3771 : 1 : QVERIFY( l11.isClosed() );
3772 : 1 : QCOMPARE( l11.numPoints(), 5 );
3773 : 1 : QGSCOMPARENEAR( l11.pointN( 4 ).x(), 0.000000000000001, 0.00000000000000001 );
3774 : 1 : QGSCOMPARENEAR( l11.pointN( 4 ).y(), 0.000000000000002, 0.00000000000000001 );
3775 : :
3776 : : //test that m values aren't considered when testing for closedness
3777 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 )
3778 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 2, 0, 4 )
3779 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 22, 0, 5 )
3780 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 6 ) );
3781 : 1 : QVERIFY( l11.isClosed() );
3782 : :
3783 : : //close with z and m
3784 : 1 : QgsLineString l12;
3785 : 2 : l12.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
3786 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
3787 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
3788 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
3789 : 1 : l12.close();
3790 : 1 : QCOMPARE( l12.pointN( 4 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
3791 : :
3792 : :
3793 : : //polygonf
3794 : 1 : QgsLineString l13;
3795 : 2 : l13.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
3796 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
3797 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
3798 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
3799 : :
3800 : 1 : QPolygonF poly = l13.asQPolygonF();
3801 : 1 : QCOMPARE( poly.count(), 4 );
3802 : 1 : QCOMPARE( poly.at( 0 ).x(), 1.0 );
3803 : 1 : QCOMPARE( poly.at( 0 ).y(), 2.0 );
3804 : 1 : QCOMPARE( poly.at( 1 ).x(), 11.0 );
3805 : 1 : QCOMPARE( poly.at( 1 ).y(), 2.0 );
3806 : 1 : QCOMPARE( poly.at( 2 ).x(), 11.0 );
3807 : 1 : QCOMPARE( poly.at( 2 ).y(), 22.0 );
3808 : 1 : QCOMPARE( poly.at( 3 ).x(), 1.0 );
3809 : 1 : QCOMPARE( poly.at( 3 ).y(), 22.0 );
3810 : :
3811 : : // clone tests. At the same time, check segmentize as the result should
3812 : : // be equal to a clone for LineStrings
3813 : 1 : QgsLineString l14;
3814 : 2 : l14.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
3815 : 1 : << QgsPoint( 11, 2 )
3816 : 1 : << QgsPoint( 11, 22 )
3817 : 1 : << QgsPoint( 1, 22 ) );
3818 : 1 : std::unique_ptr<QgsLineString> cloned( l14.clone() );
3819 : 1 : QCOMPARE( cloned->numPoints(), 4 );
3820 : 1 : QCOMPARE( cloned->vertexCount(), 4 );
3821 : 1 : QCOMPARE( cloned->ringCount(), 1 );
3822 : 1 : QCOMPARE( cloned->partCount(), 1 );
3823 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::LineString );
3824 : 1 : QVERIFY( !cloned->is3D() );
3825 : 1 : QVERIFY( !cloned->isMeasure() );
3826 : 1 : QCOMPARE( cloned->pointN( 0 ), l14.pointN( 0 ) );
3827 : 1 : QCOMPARE( cloned->pointN( 1 ), l14.pointN( 1 ) );
3828 : 1 : QCOMPARE( cloned->pointN( 2 ), l14.pointN( 2 ) );
3829 : 1 : QCOMPARE( cloned->pointN( 3 ), l14.pointN( 3 ) );
3830 : 1 : std::unique_ptr< QgsLineString > segmentized( static_cast< QgsLineString * >( l14.segmentize() ) );
3831 : 1 : QCOMPARE( segmentized->numPoints(), 4 );
3832 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineString );
3833 : 1 : QVERIFY( !segmentized->is3D() );
3834 : 1 : QVERIFY( !segmentized->isMeasure() );
3835 : 1 : QCOMPARE( segmentized->pointN( 0 ), l14.pointN( 0 ) );
3836 : 1 : QCOMPARE( segmentized->pointN( 1 ), l14.pointN( 1 ) );
3837 : 1 : QCOMPARE( segmentized->pointN( 2 ), l14.pointN( 2 ) );
3838 : 1 : QCOMPARE( segmentized->pointN( 3 ), l14.pointN( 3 ) );
3839 : :
3840 : : //clone with Z/M
3841 : 2 : l14.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
3842 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
3843 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
3844 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
3845 : 1 : cloned.reset( l14.clone() );
3846 : 1 : QCOMPARE( cloned->numPoints(), 4 );
3847 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::LineStringZM );
3848 : 1 : QVERIFY( cloned->is3D() );
3849 : 1 : QVERIFY( cloned->isMeasure() );
3850 : 1 : QCOMPARE( cloned->pointN( 0 ), l14.pointN( 0 ) );
3851 : 1 : QCOMPARE( cloned->pointN( 1 ), l14.pointN( 1 ) );
3852 : 1 : QCOMPARE( cloned->pointN( 2 ), l14.pointN( 2 ) );
3853 : 1 : QCOMPARE( cloned->pointN( 3 ), l14.pointN( 3 ) );
3854 : 1 : segmentized.reset( static_cast< QgsLineString * >( l14.segmentize() ) );
3855 : 1 : QCOMPARE( segmentized->numPoints(), 4 );
3856 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineStringZM );
3857 : 1 : QVERIFY( segmentized->is3D() );
3858 : 1 : QVERIFY( segmentized->isMeasure() );
3859 : 1 : QCOMPARE( segmentized->pointN( 0 ), l14.pointN( 0 ) );
3860 : 1 : QCOMPARE( segmentized->pointN( 1 ), l14.pointN( 1 ) );
3861 : 1 : QCOMPARE( segmentized->pointN( 2 ), l14.pointN( 2 ) );
3862 : 1 : QCOMPARE( segmentized->pointN( 3 ), l14.pointN( 3 ) );
3863 : :
3864 : : //clone an empty line
3865 : 1 : l14.clear();
3866 : 1 : cloned.reset( l14.clone() );
3867 : 1 : QVERIFY( cloned->isEmpty() );
3868 : 1 : QCOMPARE( cloned->numPoints(), 0 );
3869 : 1 : QVERIFY( !cloned->is3D() );
3870 : 1 : QVERIFY( !cloned->isMeasure() );
3871 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::LineString );
3872 : 1 : segmentized.reset( static_cast< QgsLineString * >( l14.segmentize() ) );
3873 : 1 : QVERIFY( segmentized->isEmpty() );
3874 : 1 : QCOMPARE( segmentized->numPoints(), 0 );
3875 : 1 : QVERIFY( !segmentized->is3D() );
3876 : 1 : QVERIFY( !segmentized->isMeasure() );
3877 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineString );
3878 : :
3879 : : //to/from WKB
3880 : 1 : QgsLineString l15;
3881 : 2 : l15.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
3882 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
3883 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
3884 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
3885 : 1 : QByteArray wkb15 = l15.asWkb();
3886 : 1 : QCOMPARE( wkb15.size(), l15.wkbSize() );
3887 : 1 : QgsLineString l16;
3888 : 1 : QgsConstWkbPtr wkb15ptr( wkb15 );
3889 : 1 : l16.fromWkb( wkb15ptr );
3890 : 1 : QCOMPARE( l16.numPoints(), 4 );
3891 : 1 : QCOMPARE( l16.vertexCount(), 4 );
3892 : 1 : QCOMPARE( l16.nCoordinates(), 4 );
3893 : 1 : QCOMPARE( l16.ringCount(), 1 );
3894 : 1 : QCOMPARE( l16.partCount(), 1 );
3895 : 1 : QCOMPARE( l16.wkbType(), QgsWkbTypes::LineStringZM );
3896 : 1 : QVERIFY( l16.is3D() );
3897 : 1 : QVERIFY( l16.isMeasure() );
3898 : 1 : QCOMPARE( l16.pointN( 0 ), l15.pointN( 0 ) );
3899 : 1 : QCOMPARE( l16.pointN( 1 ), l15.pointN( 1 ) );
3900 : 1 : QCOMPARE( l16.pointN( 2 ), l15.pointN( 2 ) );
3901 : 1 : QCOMPARE( l16.pointN( 3 ), l15.pointN( 3 ) );
3902 : :
3903 : : //bad WKB - check for no crash
3904 : 1 : l16.clear();
3905 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
3906 : 1 : QVERIFY( !l16.fromWkb( nullPtr ) );
3907 : 1 : QCOMPARE( l16.wkbType(), QgsWkbTypes::LineString );
3908 : 1 : QgsPoint point( 1, 2 );
3909 : 1 : QByteArray wkb16 = point.asWkb();
3910 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
3911 : 1 : QVERIFY( !l16.fromWkb( wkb16ptr ) );
3912 : 1 : QCOMPARE( l16.wkbType(), QgsWkbTypes::LineString );
3913 : :
3914 : : //to/from WKT
3915 : 1 : QgsLineString l17;
3916 : 2 : l17.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
3917 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
3918 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
3919 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
3920 : :
3921 : 1 : QString wkt = l17.asWkt();
3922 : 1 : QVERIFY( !wkt.isEmpty() );
3923 : 1 : QgsLineString l18;
3924 : 1 : QVERIFY( l18.fromWkt( wkt ) );
3925 : 1 : QCOMPARE( l18.numPoints(), 4 );
3926 : 1 : QCOMPARE( l18.wkbType(), QgsWkbTypes::LineStringZM );
3927 : 1 : QVERIFY( l18.is3D() );
3928 : 1 : QVERIFY( l18.isMeasure() );
3929 : 1 : QCOMPARE( l18.pointN( 0 ), l17.pointN( 0 ) );
3930 : 1 : QCOMPARE( l18.pointN( 1 ), l17.pointN( 1 ) );
3931 : 1 : QCOMPARE( l18.pointN( 2 ), l17.pointN( 2 ) );
3932 : 1 : QCOMPARE( l18.pointN( 3 ), l17.pointN( 3 ) );
3933 : :
3934 : : //bad WKT
3935 : 1 : QVERIFY( !l18.fromWkt( "Polygon()" ) );
3936 : 1 : QVERIFY( l18.isEmpty() );
3937 : 1 : QCOMPARE( l18.numPoints(), 0 );
3938 : 1 : QVERIFY( !l18.is3D() );
3939 : 1 : QVERIFY( !l18.isMeasure() );
3940 : 1 : QCOMPARE( l18.wkbType(), QgsWkbTypes::LineString );
3941 : :
3942 : : //asGML2
3943 : 1 : QgsLineString exportLine;
3944 : 2 : exportLine.setPoints( QgsPointSequence() << QgsPoint( 31, 32 )
3945 : 1 : << QgsPoint( 41, 42 )
3946 : 1 : << QgsPoint( 51, 52 ) );
3947 : 1 : QgsLineString exportLineFloat;
3948 : 2 : exportLineFloat.setPoints( QgsPointSequence() << QgsPoint( 1 / 3.0, 2 / 3.0 )
3949 : 1 : << QgsPoint( 1 + 1 / 3.0, 1 + 2 / 3.0 )
3950 : 1 : << QgsPoint( 2 + 1 / 3.0, 2 + 2 / 3.0 ) );
3951 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
3952 : 2 : QString expectedGML2( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">31,32 41,42 51,52</coordinates></LineString>" ) );
3953 : 3 : QGSCOMPAREGML( elemToString( exportLine.asGml2( doc ) ), expectedGML2 );
3954 : 2 : QString expectedGML2prec3( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.333,0.667 1.333,1.667 2.333,2.667</coordinates></LineString>" ) );
3955 : 3 : QGSCOMPAREGML( elemToString( exportLineFloat.asGml2( doc, 3 ) ), expectedGML2prec3 );
3956 : 2 : QString expectedGML2empty( QStringLiteral( "<LineString xmlns=\"gml\"/>" ) );
3957 : 3 : QGSCOMPAREGML( elemToString( QgsLineString().asGml2( doc ) ), expectedGML2empty );
3958 : :
3959 : : //asGML3
3960 : 2 : QString expectedGML3( QStringLiteral( "<LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">31 32 41 42 51 52</posList></LineString>" ) );
3961 : 1 : QCOMPARE( elemToString( exportLine.asGml3( doc ) ), expectedGML3 );
3962 : 2 : QString expectedGML3prec3( QStringLiteral( "<LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0.333 0.667 1.333 1.667 2.333 2.667</posList></LineString>" ) );
3963 : 1 : QCOMPARE( elemToString( exportLineFloat.asGml3( doc, 3 ) ), expectedGML3prec3 );
3964 : 2 : QString expectedGML3empty( QStringLiteral( "<LineString xmlns=\"gml\"/>" ) );
3965 : 3 : QGSCOMPAREGML( elemToString( QgsLineString().asGml3( doc ) ), expectedGML3empty );
3966 : :
3967 : : //asJSON
3968 : 1 : QString expectedJson( "{\"coordinates\":[[31.0,32.0],[41.0,42.0],[51.0,52.0]],\"type\":\"LineString\"}" );
3969 : 1 : QCOMPARE( exportLine.asJson(), expectedJson );
3970 : 1 : QString expectedJsonPrec3( "{\"coordinates\":[[0.333,0.667],[1.333,1.667],[2.333,2.667]],\"type\":\"LineString\"}" );
3971 : 1 : QCOMPARE( exportLineFloat.asJson( 3 ), expectedJsonPrec3 );
3972 : :
3973 : : //asKML
3974 : 2 : QString expectedKml( QStringLiteral( "<LineString><altitudeMode>clampToGround</altitudeMode><coordinates>31,32,0 41,42,0 51,52,0</coordinates></LineString>" ) );
3975 : 1 : QCOMPARE( exportLine.asKml(), expectedKml );
3976 : 2 : QString expectedKmlPrec3( QStringLiteral( "<LineString><altitudeMode>clampToGround</altitudeMode><coordinates>0.333,0.667,0 1.333,1.667,0 2.333,2.667,0</coordinates></LineString>" ) );
3977 : 1 : QCOMPARE( exportLineFloat.asKml( 3 ), expectedKmlPrec3 );
3978 : :
3979 : : //length
3980 : 1 : QgsLineString l19;
3981 : 1 : QCOMPARE( l19.length(), 0.0 );
3982 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
3983 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
3984 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
3985 : 1 : QCOMPARE( l19.length(), 23.0 );
3986 : :
3987 : : //startPoint
3988 : 1 : QCOMPARE( l19.startPoint(), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 ) );
3989 : :
3990 : : //endPoint
3991 : 1 : QCOMPARE( l19.endPoint(), QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
3992 : :
3993 : : //test 3d length
3994 : : // without vertices
3995 : 1 : l19.clear();
3996 : 1 : QCOMPARE( l19.length3D(), 0.0 );
3997 : :
3998 : : // without Z
3999 : 1 : l19.clear();
4000 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 0, 0 )
4001 : 1 : << QgsPoint( QgsWkbTypes::Point, 3, 4 )
4002 : 1 : << QgsPoint( QgsWkbTypes::Point, 8, 16 ) );
4003 : 1 : QCOMPARE( l19.length3D(), 18.0 );
4004 : :
4005 : : // with z
4006 : 1 : l19.clear();
4007 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 0 )
4008 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 )
4009 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 4, 6, 2 ) );
4010 : 1 : QCOMPARE( l19.length3D(), 8.0 );
4011 : :
4012 : : // with z and m
4013 : 1 : l19.clear();
4014 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 0, 0 )
4015 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 13 )
4016 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 4, 6, 2, 7 ) );
4017 : 1 : QCOMPARE( l19.length3D(), 8.0 );
4018 : :
4019 : : //bad start/end points. Test that this doesn't crash.
4020 : 1 : l19.clear();
4021 : 1 : QVERIFY( l19.startPoint().isEmpty() );
4022 : 1 : QVERIFY( l19.endPoint().isEmpty() );
4023 : :
4024 : : //curveToLine - no segmentation required, so should return a clone
4025 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
4026 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
4027 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
4028 : 1 : segmentized.reset( l19.curveToLine() );
4029 : 1 : QCOMPARE( segmentized->numPoints(), 3 );
4030 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineStringZM );
4031 : 1 : QVERIFY( segmentized->is3D() );
4032 : 1 : QVERIFY( segmentized->isMeasure() );
4033 : 1 : QCOMPARE( segmentized->pointN( 0 ), l19.pointN( 0 ) );
4034 : 1 : QCOMPARE( segmentized->pointN( 1 ), l19.pointN( 1 ) );
4035 : 1 : QCOMPARE( segmentized->pointN( 2 ), l19.pointN( 2 ) );
4036 : :
4037 : : // points
4038 : 1 : QgsLineString l20;
4039 : 1 : QgsPointSequence points;
4040 : 1 : l20.points( points );
4041 : 1 : QVERIFY( l20.isEmpty() );
4042 : 2 : l20.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
4043 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
4044 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
4045 : 1 : l20.points( points );
4046 : 1 : QCOMPARE( points.count(), 3 );
4047 : 1 : QCOMPARE( points.at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 ) );
4048 : 1 : QCOMPARE( points.at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 ) );
4049 : 1 : QCOMPARE( points.at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
4050 : :
4051 : : //CRS transform
4052 : 2 : QgsCoordinateReferenceSystem sourceSrs( QStringLiteral( "EPSG:3994" ) );
4053 : 2 : QgsCoordinateReferenceSystem destSrs( QStringLiteral( "EPSG:4202" ) );// want a transform with ellipsoid change
4054 : 1 : QgsCoordinateTransform tr( sourceSrs, destSrs, QgsProject::instance() );
4055 : :
4056 : : // 2d CRS transform
4057 : 1 : QgsLineString l21;
4058 : 2 : l21.setPoints( QgsPointSequence() << QgsPoint( 6374985, -3626584 )
4059 : 1 : << QgsPoint( 6474985, -3526584 ) );
4060 : 1 : l21.transform( tr, QgsCoordinateTransform::ForwardTransform );
4061 : 1 : QGSCOMPARENEAR( l21.pointN( 0 ).x(), 175.771, 0.001 );
4062 : 1 : QGSCOMPARENEAR( l21.pointN( 0 ).y(), -39.724, 0.001 );
4063 : 1 : QGSCOMPARENEAR( l21.pointN( 1 ).x(), 176.959, 0.001 );
4064 : 1 : QGSCOMPARENEAR( l21.pointN( 1 ).y(), -38.7999, 0.001 );
4065 : 1 : QGSCOMPARENEAR( l21.boundingBox().xMinimum(), 175.771, 0.001 );
4066 : 1 : QGSCOMPARENEAR( l21.boundingBox().yMinimum(), -39.724, 0.001 );
4067 : 1 : QGSCOMPARENEAR( l21.boundingBox().xMaximum(), 176.959, 0.001 );
4068 : 1 : QGSCOMPARENEAR( l21.boundingBox().yMaximum(), -38.7999, 0.001 );
4069 : :
4070 : : //3d CRS transform
4071 : 1 : QgsLineString l22;
4072 : 2 : l22.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 )
4073 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6474985, -3526584, 3, 4 ) );
4074 : 1 : l22.transform( tr, QgsCoordinateTransform::ForwardTransform );
4075 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).x(), 175.771, 0.001 );
4076 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).y(), -39.724, 0.001 );
4077 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).z(), 1.0, 0.001 );
4078 : 1 : QCOMPARE( l22.pointN( 0 ).m(), 2.0 );
4079 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).x(), 176.959, 0.001 );
4080 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).y(), -38.7999, 0.001 );
4081 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).z(), 3.0, 0.001 );
4082 : 1 : QCOMPARE( l22.pointN( 1 ).m(), 4.0 );
4083 : :
4084 : : //reverse transform
4085 : 1 : l22.transform( tr, QgsCoordinateTransform::ReverseTransform );
4086 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).x(), 6374985, 0.01 );
4087 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).y(), -3626584, 0.01 );
4088 : 1 : QGSCOMPARENEAR( l22.pointN( 0 ).z(), 1, 0.001 );
4089 : 1 : QCOMPARE( l22.pointN( 0 ).m(), 2.0 );
4090 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).x(), 6474985, 0.01 );
4091 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).y(), -3526584, 0.01 );
4092 : 1 : QGSCOMPARENEAR( l22.pointN( 1 ).z(), 3, 0.001 );
4093 : 1 : QCOMPARE( l22.pointN( 1 ).m(), 4.0 );
4094 : :
4095 : : #if PROJ_VERSION_MAJOR<6 // note - z value transform doesn't currently work with proj 6+, because we don't yet support compound CRS definitions
4096 : : //z value transform
4097 : : l22.transform( tr, QgsCoordinateTransform::ForwardTransform, true );
4098 : : QGSCOMPARENEAR( l22.pointN( 0 ).z(), -19.249066, 0.001 );
4099 : : QGSCOMPARENEAR( l22.pointN( 1 ).z(), -21.092128, 0.001 );
4100 : : l22.transform( tr, QgsCoordinateTransform::ReverseTransform, true );
4101 : : QGSCOMPARENEAR( l22.pointN( 0 ).z(), 1.0, 0.001 );
4102 : : QGSCOMPARENEAR( l22.pointN( 1 ).z(), 3.0, 0.001 );
4103 : : #endif
4104 : :
4105 : : //QTransform transform
4106 : 1 : QTransform qtr = QTransform::fromScale( 2, 3 );
4107 : 1 : QgsLineString l23;
4108 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
4109 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4110 : 1 : l23.transform( qtr );
4111 : 1 : QCOMPARE( l23.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 2, 6, 3, 4 ) );
4112 : 1 : QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 22, 36, 13, 14 ) );
4113 : 1 : QCOMPARE( l23.boundingBox(), QgsRectangle( 2, 6, 22, 36 ) );
4114 : :
4115 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
4116 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4117 : 1 : l23.transform( QTransform::fromScale( 1, 1 ), 3, 2, 4, 3 );
4118 : 1 : QCOMPARE( l23.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 9, 16 ) );
4119 : 1 : QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 29, 46 ) );
4120 : :
4121 : : //insert vertex
4122 : :
4123 : : //insert vertex in empty line
4124 : 1 : QgsLineString l24;
4125 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
4126 : 1 : QCOMPARE( l24.numPoints(), 1 );
4127 : 1 : QVERIFY( !l24.is3D() );
4128 : 1 : QVERIFY( !l24.isMeasure() );
4129 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::LineString );
4130 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
4131 : :
4132 : : //insert 4d vertex in empty line, should set line to 4d
4133 : 1 : l24.clear();
4134 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 6.0, 7.0, 1.0, 2.0 ) ) );
4135 : 1 : QCOMPARE( l24.numPoints(), 1 );
4136 : 1 : QVERIFY( l24.is3D() );
4137 : 1 : QVERIFY( l24.isMeasure() );
4138 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::LineStringZM );
4139 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 6.0, 7.0, 1.0, 2.0 ) );
4140 : :
4141 : : //2d line
4142 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
4143 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
4144 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
4145 : 1 : QCOMPARE( l24.numPoints(), 4 );
4146 : 1 : QVERIFY( !l24.is3D() );
4147 : 1 : QVERIFY( !l24.isMeasure() );
4148 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::LineString );
4149 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 8.0, 9.0 ) ) );
4150 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 18.0, 19.0 ) ) );
4151 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
4152 : 1 : QCOMPARE( l24.pointN( 1 ), QgsPoint( 8.0, 9.0 ) );
4153 : 1 : QCOMPARE( l24.pointN( 2 ), QgsPoint( 18.0, 19.0 ) );
4154 : 1 : QCOMPARE( l24.pointN( 3 ), QgsPoint( 1.0, 2.0 ) );
4155 : 1 : QCOMPARE( l24.pointN( 4 ), QgsPoint( 11.0, 12.0 ) );
4156 : 1 : QCOMPARE( l24.pointN( 5 ), QgsPoint( 21.0, 22.0 ) );
4157 : : //insert vertex at end
4158 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 6 ), QgsPoint( 31.0, 32.0 ) ) );
4159 : 1 : QCOMPARE( l24.pointN( 6 ), QgsPoint( 31.0, 32.0 ) );
4160 : 1 : QCOMPARE( l24.numPoints(), 7 );
4161 : :
4162 : : //insert vertex past end
4163 : 1 : QVERIFY( !l24.insertVertex( QgsVertexId( 0, 0, 8 ), QgsPoint( 41.0, 42.0 ) ) );
4164 : 1 : QCOMPARE( l24.numPoints(), 7 );
4165 : :
4166 : : //insert vertex before start
4167 : 1 : QVERIFY( !l24.insertVertex( QgsVertexId( 0, 0, -18 ), QgsPoint( 41.0, 42.0 ) ) );
4168 : 1 : QCOMPARE( l24.numPoints(), 7 );
4169 : :
4170 : : //insert 4d vertex in 4d line
4171 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
4172 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
4173 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
4174 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) ) );
4175 : 1 : QCOMPARE( l24.numPoints(), 4 );
4176 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4177 : :
4178 : : //insert 2d vertex in 4d line
4179 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 101, 102 ) ) );
4180 : 1 : QCOMPARE( l24.numPoints(), 5 );
4181 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::LineStringZM );
4182 : 1 : QCOMPARE( l24.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 101, 102 ) );
4183 : :
4184 : : //insert 4d vertex in 2d line
4185 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
4186 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
4187 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 101, 102, 103, 104 ) ) );
4188 : 1 : QCOMPARE( l24.numPoints(), 4 );
4189 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::LineString );
4190 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, 101, 102 ) );
4191 : :
4192 : : //insert first vertex as Point25D
4193 : 1 : l24.clear();
4194 : 1 : QVERIFY( l24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::Point25D, 101, 102, 103 ) ) );
4195 : 1 : QCOMPARE( l24.wkbType(), QgsWkbTypes::LineString25D );
4196 : 1 : QCOMPARE( l24.pointN( 0 ), QgsPoint( QgsWkbTypes::Point25D, 101, 102, 103 ) );
4197 : :
4198 : : //move vertex
4199 : :
4200 : : //empty line
4201 : 1 : QgsLineString l25;
4202 : 1 : QVERIFY( !l25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
4203 : 1 : QVERIFY( l25.isEmpty() );
4204 : :
4205 : : //valid line
4206 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
4207 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
4208 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
4209 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
4210 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
4211 : 1 : QCOMPARE( l25.pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
4212 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
4213 : 1 : QCOMPARE( l25.pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
4214 : :
4215 : : //out of range
4216 : 1 : QVERIFY( !l25.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
4217 : 1 : QVERIFY( !l25.moveVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
4218 : 1 : QCOMPARE( l25.pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
4219 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
4220 : 1 : QCOMPARE( l25.pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
4221 : :
4222 : : //move 4d point in 4d line
4223 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
4224 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
4225 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
4226 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 7, 12, 13 ) ) );
4227 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 7, 12, 13 ) );
4228 : :
4229 : : //move 2d point in 4d line, existing z/m should be maintained
4230 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 34, 35 ) ) );
4231 : 1 : QCOMPARE( l25.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 34, 35, 12, 13 ) );
4232 : :
4233 : : //move 4d point in 2d line
4234 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
4235 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
4236 : 1 : QVERIFY( l25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 3, 4, 2, 3 ) ) );
4237 : 1 : QCOMPARE( l25.pointN( 0 ), QgsPoint( 3, 4 ) );
4238 : :
4239 : :
4240 : : //delete vertex
4241 : :
4242 : : //empty line
4243 : 1 : QgsLineString l26;
4244 : 1 : QVERIFY( !l26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
4245 : 1 : QVERIFY( l26.isEmpty() );
4246 : :
4247 : : //valid line
4248 : 2 : l26.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
4249 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
4250 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
4251 : : //out of range vertices
4252 : 1 : QVERIFY( !l26.deleteVertex( QgsVertexId( 0, 0, -1 ) ) );
4253 : 1 : QVERIFY( !l26.deleteVertex( QgsVertexId( 0, 0, 100 ) ) );
4254 : :
4255 : : //valid vertices
4256 : 1 : QVERIFY( l26.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
4257 : 1 : QCOMPARE( l26.numPoints(), 2 );
4258 : 1 : QCOMPARE( l26.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
4259 : 1 : QCOMPARE( l26.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
4260 : : //removing the second to last vertex removes both remaining vertices
4261 : 1 : QVERIFY( l26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
4262 : 1 : QCOMPARE( l26.numPoints(), 0 );
4263 : 1 : QVERIFY( !l26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
4264 : 1 : QVERIFY( l26.isEmpty() );
4265 : :
4266 : : //reversed
4267 : 1 : QgsLineString l27;
4268 : 1 : std::unique_ptr< QgsLineString > reversed( l27.reversed() );
4269 : 1 : QVERIFY( reversed->isEmpty() );
4270 : 2 : l27.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
4271 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
4272 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
4273 : 1 : reversed.reset( l27.reversed() );
4274 : 1 : QCOMPARE( reversed->numPoints(), 3 );
4275 : 1 : QCOMPARE( reversed->wkbType(), QgsWkbTypes::LineStringZM );
4276 : 1 : QVERIFY( reversed->is3D() );
4277 : 1 : QVERIFY( reversed->isMeasure() );
4278 : 1 : QCOMPARE( reversed->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
4279 : 1 : QCOMPARE( reversed->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
4280 : 1 : QCOMPARE( reversed->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
4281 : :
4282 : : //addZValue
4283 : :
4284 : 1 : QgsLineString l28;
4285 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineString );
4286 : 1 : QVERIFY( l28.addZValue() );
4287 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineStringZ );
4288 : 1 : l28.clear();
4289 : 1 : QVERIFY( l28.addZValue() );
4290 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineStringZ );
4291 : : //2d line
4292 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4293 : 1 : QVERIFY( l28.addZValue( 2 ) );
4294 : 1 : QVERIFY( l28.is3D() );
4295 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineStringZ );
4296 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ) );
4297 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 2 ) );
4298 : 1 : QVERIFY( !l28.addZValue( 4 ) ); //already has z value, test that existing z is unchanged
4299 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ) );
4300 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 2 ) );
4301 : : //linestring with m
4302 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) );
4303 : 1 : QVERIFY( l28.addZValue( 5 ) );
4304 : 1 : QVERIFY( l28.is3D() );
4305 : 1 : QVERIFY( l28.isMeasure() );
4306 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineStringZM );
4307 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 5, 3 ) );
4308 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 5, 4 ) );
4309 : : //linestring25d
4310 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::Point25D, 11, 12, 4 ) );
4311 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineString25D );
4312 : 1 : QVERIFY( !l28.addZValue( 5 ) );
4313 : 1 : QCOMPARE( l28.wkbType(), QgsWkbTypes::LineString25D );
4314 : 1 : QCOMPARE( l28.pointN( 0 ), QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) );
4315 : 1 : QCOMPARE( l28.pointN( 1 ), QgsPoint( QgsWkbTypes::Point25D, 11, 12, 4 ) );
4316 : :
4317 : : //addMValue
4318 : :
4319 : 1 : QgsLineString l29;
4320 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineString );
4321 : 1 : QVERIFY( l29.addMValue() );
4322 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineStringM );
4323 : 1 : l29.clear();
4324 : 1 : QVERIFY( l29.addMValue() );
4325 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineStringM );
4326 : : //2d line
4327 : 1 : l29.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4328 : 1 : QVERIFY( l29.addMValue( 2 ) );
4329 : 1 : QVERIFY( !l29.is3D() );
4330 : 1 : QVERIFY( l29.isMeasure() );
4331 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineStringM );
4332 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 2 ) );
4333 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 2 ) );
4334 : 1 : QVERIFY( !l29.addMValue( 4 ) ); //already has m value, test that existing m is unchanged
4335 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 2 ) );
4336 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 2 ) );
4337 : : //linestring with z
4338 : 1 : l29.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 4 ) );
4339 : 1 : QVERIFY( l29.addMValue( 5 ) );
4340 : 1 : QVERIFY( l29.is3D() );
4341 : 1 : QVERIFY( l29.isMeasure() );
4342 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineStringZM );
4343 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 5 ) );
4344 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
4345 : : //linestring25d, should become LineStringZM
4346 : 1 : l29.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::Point25D, 11, 12, 4 ) );
4347 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineString25D );
4348 : 1 : QVERIFY( l29.addMValue( 5 ) );
4349 : 1 : QVERIFY( l29.is3D() );
4350 : 1 : QVERIFY( l29.isMeasure() );
4351 : 1 : QCOMPARE( l29.wkbType(), QgsWkbTypes::LineStringZM );
4352 : 1 : QCOMPARE( l29.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 5 ) );
4353 : 1 : QCOMPARE( l29.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
4354 : :
4355 : :
4356 : : //dropZValue
4357 : 1 : QgsLineString l28d;
4358 : 1 : QVERIFY( !l28d.dropZValue() );
4359 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4360 : 1 : QVERIFY( !l28d.dropZValue() );
4361 : 1 : l28d.addZValue( 1.0 );
4362 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringZ );
4363 : 1 : QVERIFY( l28d.is3D() );
4364 : 1 : QVERIFY( l28d.dropZValue() );
4365 : 1 : QVERIFY( !l28d.is3D() );
4366 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString );
4367 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
4368 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
4369 : 1 : QVERIFY( !l28d.dropZValue() ); //already dropped
4370 : : //linestring with m
4371 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) );
4372 : 1 : QVERIFY( l28d.dropZValue() );
4373 : 1 : QVERIFY( !l28d.is3D() );
4374 : 1 : QVERIFY( l28d.isMeasure() );
4375 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringM );
4376 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
4377 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) );
4378 : : //linestring25d
4379 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::Point25D, 11, 12, 4 ) );
4380 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString25D );
4381 : 1 : QVERIFY( l28d.dropZValue() );
4382 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString );
4383 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
4384 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
4385 : :
4386 : : //dropMValue
4387 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4388 : 1 : QVERIFY( !l28d.dropMValue() );
4389 : 1 : l28d.addMValue( 1.0 );
4390 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringM );
4391 : 1 : QVERIFY( l28d.isMeasure() );
4392 : 1 : QVERIFY( l28d.dropMValue() );
4393 : 1 : QVERIFY( !l28d.isMeasure() );
4394 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString );
4395 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
4396 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
4397 : 1 : QVERIFY( !l28d.dropMValue() ); //already dropped
4398 : : //linestring with z
4399 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) );
4400 : 1 : QVERIFY( l28d.dropMValue() );
4401 : 1 : QVERIFY( !l28d.isMeasure() );
4402 : 1 : QVERIFY( l28d.is3D() );
4403 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringZ );
4404 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3, 0 ) );
4405 : 1 : QCOMPARE( l28d.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 3, 0 ) );
4406 : :
4407 : : //convertTo
4408 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4409 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::LineString ) );
4410 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString );
4411 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::LineStringZ ) );
4412 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringZ );
4413 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2 ) );
4414 : 1 : l28d.setZAt( 0, 5.0 );
4415 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::LineString25D ) );
4416 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString25D );
4417 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::Point25D, 1, 2, 5.0 ) );
4418 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::LineStringZM ) );
4419 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringZM );
4420 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 5.0 ) );
4421 : 1 : l28d.setMAt( 0, 6.0 );
4422 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::LineStringM ) );
4423 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineStringM );
4424 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0.0, 6.0 ) );
4425 : 1 : QVERIFY( l28d.convertTo( QgsWkbTypes::LineString ) );
4426 : 1 : QCOMPARE( l28d.wkbType(), QgsWkbTypes::LineString );
4427 : 1 : QCOMPARE( l28d.pointN( 0 ), QgsPoint( 1, 2 ) );
4428 : 1 : QVERIFY( !l28d.convertTo( QgsWkbTypes::Polygon ) );
4429 : :
4430 : : //isRing
4431 : 1 : QgsLineString l30;
4432 : 1 : QVERIFY( !l30.isRing() );
4433 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 2 ) );
4434 : 1 : QVERIFY( !l30.isRing() ); //<4 points
4435 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 31, 32 ) );
4436 : 1 : QVERIFY( !l30.isRing() ); //not closed
4437 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
4438 : 1 : QVERIFY( l30.isRing() );
4439 : :
4440 : : //coordinateSequence
4441 : 1 : QgsLineString l31;
4442 : 1 : QgsCoordinateSequence coords = l31.coordinateSequence();
4443 : 1 : QCOMPARE( coords.count(), 1 );
4444 : 1 : QCOMPARE( coords.at( 0 ).count(), 1 );
4445 : 1 : QVERIFY( coords.at( 0 ).at( 0 ).isEmpty() );
4446 : 2 : l31.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
4447 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
4448 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
4449 : 1 : coords = l31.coordinateSequence();
4450 : 1 : QCOMPARE( coords.count(), 1 );
4451 : 1 : QCOMPARE( coords.at( 0 ).count(), 1 );
4452 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).count(), 3 );
4453 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
4454 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
4455 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
4456 : :
4457 : : //nextVertex
4458 : :
4459 : 1 : QgsLineString l32;
4460 : 1 : QgsVertexId v;
4461 : 1 : QgsPoint p;
4462 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4463 : 1 : v = QgsVertexId( 0, 0, -2 );
4464 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4465 : 1 : v = QgsVertexId( 0, 0, 10 );
4466 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4467 : :
4468 : : // vertex iterator on empty linestring
4469 : 1 : QgsAbstractGeometry::vertex_iterator it1 = l32.vertices_begin();
4470 : 1 : QCOMPARE( it1, l32.vertices_end() );
4471 : :
4472 : : // Java-style iterator on empty linetring
4473 : 1 : QgsVertexIterator it1x( &l32 );
4474 : 1 : QVERIFY( !it1x.hasNext() );
4475 : :
4476 : : //LineString
4477 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4478 : 1 : v = QgsVertexId( 0, 0, 2 ); //out of range
4479 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4480 : 1 : v = QgsVertexId( 0, 0, -5 );
4481 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4482 : 1 : v = QgsVertexId( 0, 0, -1 );
4483 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4484 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
4485 : 1 : QCOMPARE( p, QgsPoint( 1, 2 ) );
4486 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4487 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4488 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
4489 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4490 : 1 : v = QgsVertexId( 0, 1, 0 );
4491 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4492 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 1 ) ); //test that ring number is maintained
4493 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
4494 : 1 : v = QgsVertexId( 1, 0, 0 );
4495 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4496 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 1 ) ); //test that part number is maintained
4497 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
4498 : :
4499 : : // vertex iterator
4500 : 1 : QgsAbstractGeometry::vertex_iterator it2 = l32.vertices_begin();
4501 : 1 : QCOMPARE( *it2, QgsPoint( 1, 2 ) );
4502 : 1 : QCOMPARE( it2.vertexId(), QgsVertexId( 0, 0, 0 ) );
4503 : 1 : ++it2;
4504 : 1 : QCOMPARE( *it2, QgsPoint( 11, 12 ) );
4505 : 1 : QCOMPARE( it2.vertexId(), QgsVertexId( 0, 0, 1 ) );
4506 : 1 : ++it2;
4507 : 1 : QCOMPARE( it2, l32.vertices_end() );
4508 : :
4509 : : // Java-style iterator
4510 : 1 : QgsVertexIterator it2x( &l32 );
4511 : 1 : QVERIFY( it2x.hasNext() );
4512 : 1 : QCOMPARE( it2x.next(), QgsPoint( 1, 2 ) );
4513 : 1 : QVERIFY( it2x.hasNext() );
4514 : 1 : QCOMPARE( it2x.next(), QgsPoint( 11, 12 ) );
4515 : 1 : QVERIFY( !it2x.hasNext() );
4516 : :
4517 : : //LineStringZ
4518 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
4519 : 1 : v = QgsVertexId( 0, 0, -1 );
4520 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4521 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
4522 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
4523 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4524 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4525 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
4526 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4527 : :
4528 : : //LineStringM
4529 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
4530 : 1 : v = QgsVertexId( 0, 0, -1 );
4531 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4532 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
4533 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
4534 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4535 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4536 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
4537 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4538 : : //LineStringZM
4539 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4540 : 1 : v = QgsVertexId( 0, 0, -1 );
4541 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4542 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
4543 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
4544 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4545 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4546 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4547 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4548 : : //LineString25D
4549 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::Point25D, 11, 12, 13 ) );
4550 : 1 : v = QgsVertexId( 0, 0, -1 );
4551 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4552 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
4553 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) );
4554 : 1 : QVERIFY( l32.nextVertex( v, p ) );
4555 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4556 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::Point25D, 11, 12, 13 ) );
4557 : 1 : QVERIFY( !l32.nextVertex( v, p ) );
4558 : :
4559 : : //vertexAt and pointAt
4560 : 1 : QgsLineString l33;
4561 : 1 : l33.vertexAt( QgsVertexId( 0, 0, -10 ) ); //out of bounds, check for no crash
4562 : 1 : l33.vertexAt( QgsVertexId( 0, 0, 10 ) ); //out of bounds, check for no crash
4563 : : QgsVertexId::VertexType type;
4564 : 1 : QVERIFY( !l33.pointAt( -10, p, type ) );
4565 : 1 : QVERIFY( !l33.pointAt( 10, p, type ) );
4566 : : //LineString
4567 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4568 : 1 : l33.vertexAt( QgsVertexId( 0, 0, -10 ) );
4569 : 1 : l33.vertexAt( QgsVertexId( 0, 0, 10 ) ); //out of bounds, check for no crash
4570 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
4571 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
4572 : 1 : QVERIFY( !l33.pointAt( -10, p, type ) );
4573 : 1 : QVERIFY( !l33.pointAt( 10, p, type ) );
4574 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
4575 : 1 : QCOMPARE( p, QgsPoint( 1, 2 ) );
4576 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4577 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
4578 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
4579 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4580 : : //LineStringZ
4581 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
4582 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
4583 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
4584 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
4585 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
4586 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4587 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
4588 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
4589 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4590 : : //LineStringM
4591 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
4592 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
4593 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
4594 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
4595 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
4596 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4597 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
4598 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
4599 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4600 : : //LineStringZM
4601 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4602 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
4603 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4604 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
4605 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
4606 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4607 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
4608 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
4609 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4610 : : //LineString25D
4611 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::Point25D, 11, 12, 13 ) );
4612 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) );
4613 : 1 : QCOMPARE( l33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::Point25D, 11, 12, 13 ) );
4614 : 1 : QVERIFY( l33.pointAt( 0, p, type ) );
4615 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::Point25D, 1, 2, 3 ) );
4616 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4617 : 1 : QVERIFY( l33.pointAt( 1, p, type ) );
4618 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::Point25D, 11, 12, 13 ) );
4619 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
4620 : :
4621 : : //centroid
4622 : 1 : QgsLineString l34;
4623 : 1 : QVERIFY( l34.centroid().isEmpty() );
4624 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
4625 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 5, 10 ) );
4626 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 20, 10 ) );
4627 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 10, 5 ) );
4628 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 9 ) << QgsPoint( 2, 9 ) << QgsPoint( 2, 0 ) );
4629 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 1, 4.95 ) );
4630 : : //linestring with 0 length segment
4631 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 9 ) << QgsPoint( 2, 9 ) << QgsPoint( 2, 9 ) << QgsPoint( 2, 0 ) );
4632 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 1, 4.95 ) );
4633 : : //linestring with 0 total length segment
4634 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 5, 4 ) << QgsPoint( 5, 4 ) << QgsPoint( 5, 4 ) );
4635 : 1 : QCOMPARE( l34.centroid(), QgsPoint( 5, 4 ) );
4636 : :
4637 : : //closest segment
4638 : 1 : QgsLineString l35;
4639 : 1 : int leftOf = 0;
4640 : 1 : p = QgsPoint( 0, 0 ); // reset all coords to zero
4641 : 1 : ( void )l35.closestSegment( QgsPoint( 1, 2 ), p, v ); //empty line, just want no crash
4642 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
4643 : 1 : QVERIFY( l35.closestSegment( QgsPoint( 5, 10 ), p, v ) < 0 );
4644 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 10 ) );
4645 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 4, 11 ), p, v, &leftOf ), 2.0, 4 * std::numeric_limits<double>::epsilon() );
4646 : 1 : QCOMPARE( p, QgsPoint( 5, 10 ) );
4647 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4648 : 1 : QCOMPARE( leftOf, -1 );
4649 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 8, 11 ), p, v, &leftOf ), 1.0, 4 * std::numeric_limits<double>::epsilon() );
4650 : 1 : QCOMPARE( p, QgsPoint( 8, 10 ) );
4651 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4652 : 1 : QCOMPARE( leftOf, -1 );
4653 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 8, 9 ), p, v, &leftOf ), 1.0, 4 * std::numeric_limits<double>::epsilon() );
4654 : 1 : QCOMPARE( p, QgsPoint( 8, 10 ) );
4655 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4656 : 1 : QCOMPARE( leftOf, 1 );
4657 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 11, 9 ), p, v, &leftOf ), 2.0, 4 * std::numeric_limits<double>::epsilon() );
4658 : 1 : QCOMPARE( p, QgsPoint( 10, 10 ) );
4659 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4660 : 1 : QCOMPARE( leftOf, 1 );
4661 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 )
4662 : 1 : << QgsPoint( 10, 10 )
4663 : 1 : << QgsPoint( 10, 15 ) );
4664 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 11, 12 ), p, v, &leftOf ), 1.0, 4 * std::numeric_limits<double>::epsilon() );
4665 : 1 : QCOMPARE( p, QgsPoint( 10, 12 ) );
4666 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
4667 : 1 : QCOMPARE( leftOf, 1 );
4668 : :
4669 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 5 )
4670 : 1 : << QgsPoint( 6, 4 )
4671 : 1 : << QgsPoint( 4, 4 )
4672 : 1 : << QgsPoint( 5, 5 ) );
4673 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 2.35, 4 ), p, v, &leftOf ), 2.7225, 4 * std::numeric_limits<double>::epsilon() );
4674 : 1 : QCOMPARE( p, QgsPoint( 4, 4 ) );
4675 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
4676 : 1 : QCOMPARE( leftOf, -1 );
4677 : :
4678 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 5 )
4679 : 1 : << QgsPoint( 4, 4 )
4680 : 1 : << QgsPoint( 6, 4 )
4681 : 1 : << QgsPoint( 5, 5 ) );
4682 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 2.35, 4 ), p, v, &leftOf ), 2.7225, 4 * std::numeric_limits<double>::epsilon() );
4683 : 1 : QCOMPARE( p, QgsPoint( 4, 4 ) );
4684 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4685 : 1 : QCOMPARE( leftOf, 1 );
4686 : :
4687 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 5 )
4688 : 1 : << QgsPoint( 6, 4 )
4689 : 1 : << QgsPoint( 4, 4 )
4690 : 1 : << QgsPoint( 5, 5 ) );
4691 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 3.5, 2 ), p, v, &leftOf ), 4.250000, 4 * std::numeric_limits<double>::epsilon() );
4692 : 1 : QCOMPARE( p, QgsPoint( 4, 4 ) );
4693 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
4694 : 1 : QCOMPARE( leftOf, -1 );
4695 : :
4696 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 5 )
4697 : 1 : << QgsPoint( 4, 4 )
4698 : 1 : << QgsPoint( 6, 4 )
4699 : 1 : << QgsPoint( 5, 5 ) );
4700 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 3.5, 2 ), p, v, &leftOf ), 4.250000, 4 * std::numeric_limits<double>::epsilon() );
4701 : 1 : QCOMPARE( p, QgsPoint( 4, 4 ) );
4702 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4703 : 1 : QCOMPARE( leftOf, 1 );
4704 : :
4705 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 1, 1 )
4706 : 1 : << QgsPoint( 1, 4 )
4707 : 1 : << QgsPoint( 2, 2 )
4708 : 1 : << QgsPoint( 1, 1 ) );
4709 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 1, 0 ), p, v, &leftOf ), 1, 4 * std::numeric_limits<double>::epsilon() );
4710 : 1 : QCOMPARE( p, QgsPoint( 1, 1 ) );
4711 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4712 : 1 : QCOMPARE( leftOf, -1 );
4713 : :
4714 : 2 : l35.setPoints( QgsPointSequence() << QgsPoint( 1, 1 )
4715 : 1 : << QgsPoint( 2, 2 )
4716 : 1 : << QgsPoint( 1, 4 )
4717 : 1 : << QgsPoint( 1, 1 ) );
4718 : 1 : QGSCOMPARENEAR( l35.closestSegment( QgsPoint( 1, 0 ), p, v, &leftOf ), 1, 4 * std::numeric_limits<double>::epsilon() );
4719 : 1 : QCOMPARE( p, QgsPoint( 1, 1 ) );
4720 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
4721 : 1 : QCOMPARE( leftOf, 1 );
4722 : :
4723 : : //sumUpArea
4724 : 1 : QgsLineString l36;
4725 : 1 : double area = 1.0; //sumUpArea adds to area, so start with non-zero value
4726 : 1 : l36.sumUpArea( area );
4727 : 1 : QCOMPARE( area, 1.0 );
4728 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
4729 : 1 : l36.sumUpArea( area );
4730 : 1 : QCOMPARE( area, 1.0 );
4731 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 10 ) );
4732 : 1 : l36.sumUpArea( area );
4733 : 1 : QGSCOMPARENEAR( area, -24, 4 * std::numeric_limits<double>::epsilon() );
4734 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2, 0 ) << QgsPoint( 2, 2 ) );
4735 : 1 : l36.sumUpArea( area );
4736 : 1 : QGSCOMPARENEAR( area, -22, 4 * std::numeric_limits<double>::epsilon() );
4737 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2, 0 ) << QgsPoint( 2, 2 ) << QgsPoint( 0, 2 ) );
4738 : 1 : l36.sumUpArea( area );
4739 : 1 : QGSCOMPARENEAR( area, -18, 4 * std::numeric_limits<double>::epsilon() );
4740 : :
4741 : : //boundingBox - test that bounding box is updated after every modification to the line string
4742 : 1 : QgsLineString l37;
4743 : 1 : QVERIFY( l37.boundingBox().isNull() );
4744 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 15 ) );
4745 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 5, 10, 10, 15 ) );
4746 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( -5, -10 ) << QgsPoint( -6, -10 ) << QgsPoint( -5.5, -9 ) );
4747 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6, -10, -5, -9 ) );
4748 : : //setXAt
4749 : 1 : l37.setXAt( 2, -4 );
4750 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6, -10, -4, -9 ) );
4751 : : //setYAt
4752 : 1 : l37.setYAt( 1, -15 );
4753 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6, -15, -4, -9 ) );
4754 : : //append
4755 : 1 : toAppend.reset( new QgsLineString() );
4756 : 1 : toAppend->setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 4, 0 ) );
4757 : 1 : l37.append( toAppend.get() );
4758 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6, -15, 4, 2 ) );
4759 : 1 : l37.addVertex( QgsPoint( 6, 3 ) );
4760 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -6, -15, 6, 3 ) );
4761 : 1 : l37.clear();
4762 : 1 : QVERIFY( l37.boundingBox().isNull() );
4763 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 15 ) );
4764 : 1 : QByteArray wkbToAppend = toAppend->asWkb();
4765 : 1 : QgsConstWkbPtr wkbToAppendPtr( wkbToAppend );
4766 : 1 : l37.fromWkb( wkbToAppendPtr );
4767 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 1, 0, 4, 2 ) );
4768 : 2 : l37.fromWkt( QStringLiteral( "LineString( 1 5, 3 4, 6 3 )" ) );
4769 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 1, 3, 6, 5 ) );
4770 : 1 : l37.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( -1, 7 ) );
4771 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -1, 3, 6, 7 ) );
4772 : 1 : l37.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( -3, 10 ) );
4773 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( -3, 3, 6, 10 ) );
4774 : 1 : l37.deleteVertex( QgsVertexId( 0, 0, 1 ) );
4775 : 1 : QCOMPARE( l37.boundingBox(), QgsRectangle( 1, 3, 6, 5 ) );
4776 : :
4777 : : //angle
4778 : 1 : QgsLineString l38;
4779 : 1 : ( void )l38.vertexAngle( QgsVertexId() ); //just want no crash
4780 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash
4781 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) );
4782 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash, any answer is meaningless
4783 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) );
4784 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
4785 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 1.5708, 0.0001 );
4786 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ); //no crash
4787 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 1 ) );
4788 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 0.0, 4 * std::numeric_limits<double>::epsilon() );
4789 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 0.0, 4 * std::numeric_limits<double>::epsilon() );
4790 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 0 ) << QgsPoint( 0, 0 ) );
4791 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 4.71239, 0.0001 );
4792 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 4.71239, 0.0001 );
4793 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 1 ) << QgsPoint( 0, 0 ) );
4794 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 3.1416, 0.0001 );
4795 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.1416, 0.0001 );
4796 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
4797 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
4798 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 0.7854, 0.0001 );
4799 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 0.0, 0.0001 );
4800 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
4801 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) );
4802 : 1 : ( void )l38.vertexAngle( QgsVertexId( 0, 0, 20 ) );
4803 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
4804 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 1.5708, 0.0001 );
4805 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 1.17809, 0.00001 );
4806 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 0.0, 0.00001 );
4807 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 5.10509, 0.00001 );
4808 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 5 ) ), 4.71239, 0.00001 );
4809 : : //closed line string
4810 : 1 : l38.close();
4811 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 5 ) ), 3.92699, 0.00001 );
4812 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 2.35619, 0.00001 );
4813 : 1 : QGSCOMPARENEAR( l38.vertexAngle( QgsVertexId( 0, 0, 6 ) ), 2.35619, 0.00001 );
4814 : :
4815 : : //removing the second to last vertex should remove the whole line
4816 : 1 : QgsLineString l39;
4817 : 1 : l39.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) );
4818 : 1 : QVERIFY( l39.numPoints() == 2 );
4819 : 1 : l39.deleteVertex( QgsVertexId( 0, 0, 1 ) );
4820 : 1 : QVERIFY( l39.numPoints() == 0 );
4821 : :
4822 : : //boundary
4823 : 1 : QgsLineString boundary1;
4824 : 1 : QVERIFY( !boundary1.boundary() );
4825 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
4826 : 1 : QgsAbstractGeometry *boundary = boundary1.boundary();
4827 : 1 : QgsMultiPoint *mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
4828 : 1 : QVERIFY( mpBoundary );
4829 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
4830 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
4831 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
4832 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
4833 : 1 : delete boundary;
4834 : :
4835 : : // closed string = no boundary
4836 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
4837 : 1 : QVERIFY( !boundary1.boundary() );
4838 : : \
4839 : :
4840 : : //boundary with z
4841 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) );
4842 : 1 : boundary = boundary1.boundary();
4843 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
4844 : 1 : QVERIFY( mpBoundary );
4845 : 1 : QCOMPARE( mpBoundary->geometryN( 0 )->wkbType(), QgsWkbTypes::PointZ );
4846 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
4847 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
4848 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->z(), 10.0 );
4849 : 1 : QCOMPARE( mpBoundary->geometryN( 1 )->wkbType(), QgsWkbTypes::PointZ );
4850 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
4851 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
4852 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
4853 : 1 : delete boundary;
4854 : :
4855 : : //extend
4856 : 1 : QgsLineString extend1;
4857 : 1 : extend1.extend( 10, 10 ); //test no crash
4858 : 1 : extend1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
4859 : 1 : extend1.extend( 1, 2 );
4860 : 1 : QCOMPARE( extend1.pointN( 0 ), QgsPoint( QgsWkbTypes::Point, -1, 0 ) );
4861 : 1 : QCOMPARE( extend1.pointN( 1 ), QgsPoint( QgsWkbTypes::Point, 1, 0 ) );
4862 : 1 : QCOMPARE( extend1.pointN( 2 ), QgsPoint( QgsWkbTypes::Point, 1, 3 ) );
4863 : :
4864 : : // addToPainterPath (note most tests are in test_qgsgeometry.py)
4865 : 1 : QgsLineString path;
4866 : 1 : QPainterPath pPath;
4867 : 1 : path.addToPainterPath( pPath );
4868 : 1 : QVERIFY( pPath.isEmpty() );
4869 : 1 : path.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
4870 : 1 : path.addToPainterPath( pPath );
4871 : 1 : QVERIFY( !pPath.isEmpty() );
4872 : :
4873 : : // toCurveType
4874 : 1 : QgsLineString curveLine1;
4875 : 1 : curveLine1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
4876 : 1 : std::unique_ptr< QgsCompoundCurve > curveType( curveLine1.toCurveType() );
4877 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::CompoundCurve );
4878 : 1 : QCOMPARE( curveType->numPoints(), 2 );
4879 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
4880 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
4881 : :
4882 : : //adjacent vertices
4883 : 1 : QgsLineString vertexLine1;
4884 : 1 : vertexLine1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 112 ) );
4885 : 1 : QgsVertexId prev( 1, 2, 3 ); // start with something
4886 : 1 : QgsVertexId next( 4, 5, 6 );
4887 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, -1 ), prev, next );
4888 : 1 : QCOMPARE( prev, QgsVertexId() );
4889 : 1 : QCOMPARE( next, QgsVertexId() );
4890 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, 3 ), prev, next );
4891 : 1 : QCOMPARE( prev, QgsVertexId() );
4892 : 1 : QCOMPARE( next, QgsVertexId() );
4893 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, 0 ), prev, next );
4894 : 1 : QCOMPARE( prev, QgsVertexId() );
4895 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
4896 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, 1 ), prev, next );
4897 : 1 : QCOMPARE( prev, QgsVertexId( 0, 0, 0 ) );
4898 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
4899 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, 2 ), prev, next );
4900 : 1 : QCOMPARE( prev, QgsVertexId( 0, 0, 1 ) );
4901 : 1 : QCOMPARE( next, QgsVertexId() );
4902 : : // ring, part should be maintained
4903 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 1, 0, 1 ), prev, next );
4904 : 1 : QCOMPARE( prev, QgsVertexId( 1, 0, 0 ) );
4905 : 1 : QCOMPARE( next, QgsVertexId( 1, 0, 2 ) );
4906 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 1, 2, 1 ), prev, next );
4907 : 1 : QCOMPARE( prev, QgsVertexId( 1, 2, 0 ) );
4908 : 1 : QCOMPARE( next, QgsVertexId( 1, 2, 2 ) );
4909 : : // closed ring
4910 : 1 : vertexLine1.close();
4911 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, 0 ), prev, next );
4912 : 1 : QCOMPARE( prev, QgsVertexId() );
4913 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
4914 : 1 : vertexLine1.adjacentVertices( QgsVertexId( 0, 0, 3 ), prev, next );
4915 : 1 : QCOMPARE( prev, QgsVertexId( 0, 0, 2 ) );
4916 : 1 : QCOMPARE( next, QgsVertexId() );
4917 : :
4918 : : // vertex number
4919 : 1 : QgsLineString vertexLine2;
4920 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
4921 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), -1 );
4922 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
4923 : 1 : vertexLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 112 ) );
4924 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
4925 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
4926 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, -1, 0 ) ), -1 );
4927 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), -1 );
4928 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 0, -1 ) ), -1 );
4929 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
4930 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), 1 );
4931 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 0, 2 ) ), 2 );
4932 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( 0, 0, 3 ) ), -1 );
4933 : :
4934 : : //segmentLength
4935 : 1 : QgsLineString vertexLine3;
4936 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
4937 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 0, 0, 0 ) ), 0.0 );
4938 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 1, 0, 0 ) ), 0.0 );
4939 : 1 : vertexLine3.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
4940 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId() ), 0.0 );
4941 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
4942 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 0, 0, 0 ) ), 10.0 );
4943 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 0, 0, 1 ) ), 100.0 );
4944 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 0, 0, 2 ) ), 0.0 );
4945 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
4946 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( -1, 0, 0 ) ), 10.0 );
4947 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 1, 0, 1 ) ), 100.0 );
4948 : 1 : QCOMPARE( vertexLine3.segmentLength( QgsVertexId( 1, 1, 1 ) ), 100.0 );
4949 : :
4950 : : //removeDuplicateNodes
4951 : 1 : QgsLineString nodeLine;
4952 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
4953 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
4954 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
4955 : 2 : QCOMPARE( nodeLine.asWkt(), QStringLiteral( "LineString (11 2, 11 12, 111 12)" ) );
4956 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
4957 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) << QgsPoint( 111.01, 11.99 ) );
4958 : 1 : QVERIFY( nodeLine.removeDuplicateNodes( 0.02 ) );
4959 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
4960 : 2 : QCOMPARE( nodeLine.asWkt(), QStringLiteral( "LineString (11 2, 11 12, 111 12)" ) );
4961 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
4962 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) << QgsPoint( 111.01, 11.99 ) );
4963 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes() );
4964 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "LineString (11 2, 11.01 1.99, 11.02 2.01, 11 12, 111 12, 111.01 11.99)" ) );
4965 : : // don't create degenerate lines
4966 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) );
4967 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
4968 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "LineString (11 2)" ) );
4969 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) );
4970 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02 ) );
4971 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "LineString (11 2, 11.01 1.99)" ) );
4972 : : // with z
4973 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 1 ) << QgsPoint( 11.01, 1.99, 2 ) << QgsPoint( 11.02, 2.01, 3 )
4974 : 1 : << QgsPoint( 11, 12, 4 ) << QgsPoint( 111, 12, 5 ) << QgsPoint( 111.01, 11.99, 6 ) );
4975 : 1 : QVERIFY( nodeLine.removeDuplicateNodes( 0.02 ) );
4976 : 2 : QCOMPARE( nodeLine.asWkt(), QStringLiteral( "LineStringZ (11 2 1, 11 12 4, 111 12 5)" ) );
4977 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 1 ) << QgsPoint( 11.01, 1.99, 2 ) << QgsPoint( 11.02, 2.01, 3 )
4978 : 1 : << QgsPoint( 11, 12, 4 ) << QgsPoint( 111, 12, 5 ) << QgsPoint( 111.01, 11.99, 6 ) );
4979 : 1 : QVERIFY( !nodeLine.removeDuplicateNodes( 0.02, true ) );
4980 : 2 : QCOMPARE( nodeLine.asWkt( 2 ), QStringLiteral( "LineStringZ (11 2 1, 11.01 1.99 2, 11.02 2.01 3, 11 12 4, 111 12 5, 111.01 11.99 6)" ) );
4981 : :
4982 : : // swap xy
4983 : 1 : QgsLineString swapLine;
4984 : 1 : swapLine.swapXy(); // no crash
4985 : 1 : swapLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
4986 : 1 : swapLine.swapXy();
4987 : 2 : QCOMPARE( swapLine.asWkt( 2 ), QStringLiteral( "LineStringZM (2 11 3 4, 12 11 13 14, 12 111 23 24)" ) );
4988 : :
4989 : : // filter vertex
4990 : 1 : QgsLineString filterLine;
4991 : 4 : auto filter = []( const QgsPoint & point )-> bool
4992 : : {
4993 : 4 : return point.x() < 5;
4994 : : };
4995 : 1 : filterLine.filterVertices( filter ); // no crash
4996 : 1 : filterLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
4997 : 1 : filterLine.filterVertices( filter );
4998 : 2 : QCOMPARE( filterLine.asWkt( 2 ), QStringLiteral( "LineStringZM (1 2 3 4, 4 12 13 14)" ) );
4999 : :
5000 : : // transform vertex
5001 : 1 : QgsLineString transformLine;
5002 : 4 : auto transform = []( const QgsPoint & point )-> QgsPoint
5003 : : {
5004 : 4 : return QgsPoint( point.x() + 5, point.y() + 6, point.z() + 7, point.m() + 8 );
5005 : : };
5006 : 1 : transformLine.transformVertices( transform ); // no crash
5007 : 1 : transformLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
5008 : 1 : transformLine.transformVertices( transform );
5009 : 2 : QCOMPARE( transformLine.asWkt( 2 ), QStringLiteral( "LineStringZM (16 8 10 12, 6 8 10 12, 9 18 20 22, 116 18 30 32)" ) );
5010 : :
5011 : : // transform using class
5012 : 1 : QgsLineString transformLine2;
5013 : 1 : TestTransformer transformer;
5014 : : // no crash
5015 : 1 : QVERIFY( transformLine2.transform( &transformer ) );
5016 : 1 : transformLine2.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
5017 : 1 : QVERIFY( transformLine2.transform( &transformer ) );
5018 : 2 : QCOMPARE( transformLine2.asWkt( 2 ), QStringLiteral( "LineStringZM (33 16 8 3, 3 16 8 3, 12 26 18 13, 333 26 28 23)" ) );
5019 : :
5020 : 1 : TestFailTransformer failTransformer;
5021 : 1 : QVERIFY( !transformLine2.transform( &failTransformer ) );
5022 : :
5023 : : // substring
5024 : 1 : QgsLineString substring;
5025 : 1 : std::unique_ptr< QgsLineString > substringResult( substring.curveSubstring( 1, 2 ) ); // no crash
5026 : 1 : QVERIFY( substringResult.get() );
5027 : 1 : QVERIFY( substringResult->isEmpty() );
5028 : 1 : substring.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
5029 : 1 : substringResult.reset( substring.curveSubstring( 0, 0 ) );
5030 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 2 3 4, 11 2 3 4)" ) );
5031 : 1 : substringResult.reset( substring.curveSubstring( -1, -0.1 ) );
5032 : 1 : QVERIFY( substringResult->isEmpty() );
5033 : 1 : substringResult.reset( substring.curveSubstring( 100000, 10000 ) );
5034 : 1 : QVERIFY( substringResult->isEmpty() );
5035 : 1 : substringResult.reset( substring.curveSubstring( -1, 1 ) );
5036 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 2 3 4, 11 3 4 5)" ) );
5037 : 1 : substringResult.reset( substring.curveSubstring( 1, -1 ) );
5038 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 3 4 5, 11 3 4 5)" ) );
5039 : 1 : substringResult.reset( substring.curveSubstring( -1, 10000 ) );
5040 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 2 3 4, 11 12 13 14, 111 12 23 24)" ) );
5041 : 1 : substringResult.reset( substring.curveSubstring( 1, 10000 ) );
5042 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 3 4 5, 11 12 13 14, 111 12 23 24)" ) );
5043 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
5044 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 3 4 5, 11 12 13 14, 21 12 14 15)" ) );
5045 : 1 : substringResult.reset( substring.curveSubstring( QgsGeometryUtils::distanceToVertex( substring, QgsVertexId( 0, 0, 1 ) ), QgsGeometryUtils::distanceToVertex( substring, QgsVertexId( 0, 0, 2 ) ) ) );
5046 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZM (11 12 13 14, 111 12 23 24)" ) );
5047 : 1 : substring.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 0, QgsWkbTypes::PointZ ) << QgsPoint( 11, 12, 13, 0, QgsWkbTypes::PointZ ) << QgsPoint( 111, 12, 23, 0, QgsWkbTypes::PointZ ) );
5048 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
5049 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringZ (11 3 4, 11 12 13, 21 12 14)" ) );
5050 : 1 : substring.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 0, 3, QgsWkbTypes::PointM ) << QgsPoint( 11, 12, 0, 13, QgsWkbTypes::PointM ) << QgsPoint( 111, 12, 0, 23, QgsWkbTypes::PointM ) );
5051 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
5052 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineStringM (11 3 4, 11 12 13, 21 12 14)" ) );
5053 : 1 : substring.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
5054 : 1 : substringResult.reset( substring.curveSubstring( 1, 20 ) );
5055 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "LineString (11 3, 11 12, 21 12)" ) );
5056 : :
5057 : : //interpolate point
5058 : 1 : QgsLineString interpolate;
5059 : 1 : std::unique_ptr< QgsPoint > interpolateResult( interpolate.interpolatePoint( 1 ) ); // no crash
5060 : 1 : QVERIFY( !interpolateResult.get() );
5061 : 1 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
5062 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 0 ) );
5063 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (11 2 3 4)" ) );
5064 : 1 : interpolateResult.reset( interpolate.interpolatePoint( -1 ) );
5065 : 1 : QVERIFY( !interpolateResult.get() );
5066 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 100000 ) );
5067 : 1 : QVERIFY( !interpolateResult.get() );
5068 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
5069 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (11 3 4 5)" ) );
5070 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 20 ) );
5071 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (21 12 14 15)" ) );
5072 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 110 ) );
5073 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (111 12 23 24)" ) );
5074 : 1 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 0, QgsWkbTypes::PointZ ) << QgsPoint( 11, 12, 13, 0, QgsWkbTypes::PointZ ) << QgsPoint( 111, 12, 23, 0, QgsWkbTypes::PointZ ) );
5075 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
5076 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZ (11 3 4)" ) );
5077 : 1 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 0, 3, QgsWkbTypes::PointM ) << QgsPoint( 11, 12, 0, 13, QgsWkbTypes::PointM ) << QgsPoint( 111, 12, 0, 23, QgsWkbTypes::PointM ) );
5078 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
5079 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointM (11 3 4)" ) );
5080 : 1 : interpolate.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
5081 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
5082 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "Point (11 3)" ) );
5083 : :
5084 : : // visit points
5085 : 1 : QgsLineString visitLine;
5086 : 1 : visitLine.visitPointsByRegularDistance( 1, [ = ]( double, double, double, double, double, double, double, double, double, double, double, double )->bool
5087 : : {
5088 : 0 : return true;
5089 : : } ); // no crash
5090 : 1 : visitLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
5091 : 1 : int visitCount = 0;
5092 : 1 : xx.clear();
5093 : 1 : yy.clear();
5094 : 1 : zz.clear();
5095 : 1 : mm.clear();
5096 : 1 : QVector<double> pX, pY, pZ, pM, nX, nY, nZ, nM;
5097 : 5 : auto visitor = [ & ]( double x, double y, double z, double m, double ppx, double ppy, double ppz, double ppm, double nnx, double nny, double nnz, double nnm )->bool
5098 : : {
5099 : 4 : xx << x;
5100 : 4 : yy << y;
5101 : 4 : zz << z;
5102 : 4 : mm << m;
5103 : 4 : pX << ppx;
5104 : 4 : pY << ppy;
5105 : 4 : pZ << ppz;
5106 : 4 : pM << ppm;
5107 : 4 : nX << nnx;
5108 : 4 : nY << nny;
5109 : 4 : nZ << nnz;
5110 : 4 : nM << nnm;
5111 : 4 : visitCount++;
5112 : 4 : return true;
5113 : : };
5114 : 1 : visitLine.visitPointsByRegularDistance( 0, visitor );
5115 : 1 : QCOMPARE( visitCount, 1 );
5116 : 1 : QCOMPARE( xx.at( 0 ), 11.0 );
5117 : 1 : QCOMPARE( yy.at( 0 ), 2.0 );
5118 : 1 : QCOMPARE( zz.at( 0 ), 3.0 );
5119 : 1 : QCOMPARE( mm.at( 0 ), 4.0 );
5120 : 1 : xx.clear();
5121 : 1 : yy.clear();
5122 : 1 : zz.clear();
5123 : 1 : mm.clear();
5124 : 1 : pX.clear();
5125 : 1 : pY.clear();
5126 : 1 : pZ.clear();
5127 : 1 : pM.clear();
5128 : 1 : nX.clear();
5129 : 1 : nY.clear();
5130 : 1 : nZ.clear();
5131 : 1 : nM.clear();
5132 : 1 : visitCount = 0;
5133 : 1 : visitLine.visitPointsByRegularDistance( -1, visitor );
5134 : 1 : QCOMPARE( visitCount, 0 );
5135 : 1 : visitLine.visitPointsByRegularDistance( 10000, visitor );
5136 : 1 : QCOMPARE( visitCount, 0 );
5137 : 1 : visitLine.visitPointsByRegularDistance( 30, visitor );
5138 : 1 : QCOMPARE( visitCount, 3 );
5139 : 1 : QCOMPARE( xx.at( 0 ), 31.0 );
5140 : 1 : QCOMPARE( yy.at( 0 ), 12.0 );
5141 : 1 : QCOMPARE( zz.at( 0 ), 15.0 );
5142 : 1 : QCOMPARE( mm.at( 0 ), 16.0 );
5143 : 1 : QCOMPARE( pX.at( 0 ), 11.0 );
5144 : 1 : QCOMPARE( pY.at( 0 ), 12.0 );
5145 : 1 : QCOMPARE( pZ.at( 0 ), 13.0 );
5146 : 1 : QCOMPARE( pM.at( 0 ), 14.0 );
5147 : 1 : QCOMPARE( nX.at( 0 ), 111.0 );
5148 : 1 : QCOMPARE( nY.at( 0 ), 12.0 );
5149 : 1 : QCOMPARE( nZ.at( 0 ), 23.0 );
5150 : 1 : QCOMPARE( nM.at( 0 ), 24.0 );
5151 : 1 : QCOMPARE( xx.at( 1 ), 61.0 );
5152 : 1 : QCOMPARE( yy.at( 1 ), 12.0 );
5153 : 1 : QCOMPARE( zz.at( 1 ), 18.0 );
5154 : 1 : QCOMPARE( mm.at( 1 ), 19.0 );
5155 : 1 : QCOMPARE( pX.at( 1 ), 11.0 );
5156 : 1 : QCOMPARE( pY.at( 1 ), 12.0 );
5157 : 1 : QCOMPARE( pZ.at( 1 ), 13.0 );
5158 : 1 : QCOMPARE( pM.at( 1 ), 14.0 );
5159 : 1 : QCOMPARE( nX.at( 1 ), 111.0 );
5160 : 1 : QCOMPARE( nY.at( 1 ), 12.0 );
5161 : 1 : QCOMPARE( nZ.at( 1 ), 23.0 );
5162 : 1 : QCOMPARE( nM.at( 1 ), 24.0 );
5163 : 1 : QCOMPARE( xx.at( 2 ), 91.0 );
5164 : 1 : QCOMPARE( yy.at( 2 ), 12.0 );
5165 : 1 : QCOMPARE( zz.at( 2 ), 21.0 );
5166 : 1 : QCOMPARE( mm.at( 2 ), 22.0 );
5167 : 1 : QCOMPARE( pX.at( 2 ), 11.0 );
5168 : 1 : QCOMPARE( pY.at( 2 ), 12.0 );
5169 : 1 : QCOMPARE( pZ.at( 2 ), 13.0 );
5170 : 1 : QCOMPARE( pM.at( 2 ), 14.0 );
5171 : 1 : QCOMPARE( nX.at( 2 ), 111.0 );
5172 : 1 : QCOMPARE( nY.at( 2 ), 12.0 );
5173 : 1 : QCOMPARE( nZ.at( 2 ), 23.0 );
5174 : 1 : QCOMPARE( nM.at( 2 ), 24.0 );
5175 : :
5176 : : // orientation
5177 : 1 : QgsLineString orientation;
5178 : 1 : ( void )orientation.orientation(); // no crash
5179 : 1 : orientation.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 1 ) << QgsPoint( 1, 1 ) << QgsPoint( 1, 0 ) << QgsPoint( 0, 0 ) );
5180 : 1 : QCOMPARE( orientation.orientation(), QgsCurve::Clockwise );
5181 : 1 : orientation.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 1 ) << QgsPoint( 0, 0 ) );
5182 : 1 : QCOMPARE( orientation.orientation(), QgsCurve::CounterClockwise );
5183 : :
5184 : : // test bounding box intersects
5185 : 1 : QgsLineString bb;
5186 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
5187 : 1 : bb.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 13, -10 ) );
5188 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 12, 3, 16, 9 ) ) );
5189 : : // double test because of cache
5190 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 12, 3, 16, 9 ) ) );
5191 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
5192 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
5193 : 1 : QCOMPARE( bb.boundingBox(), QgsRectangle( 11, -10, 13, 12 ) );
5194 : : // clear cache
5195 : 1 : bb.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 13, -10 ) );
5196 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
5197 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
5198 : 1 : QCOMPARE( bb.boundingBox(), QgsRectangle( 11, -10, 13, 12 ) );
5199 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 12, 3, 16, 9 ) ) );
5200 : 1 : }
5201 : :
5202 : 1 : void TestQgsGeometry::polygon()
5203 : : {
5204 : : //test constructor
5205 : 1 : QgsPolygon p1;
5206 : 1 : QVERIFY( p1.isEmpty() );
5207 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
5208 : 1 : QCOMPARE( p1.nCoordinates(), 0 );
5209 : 1 : QCOMPARE( p1.ringCount(), 0 );
5210 : 1 : QCOMPARE( p1.partCount(), 0 );
5211 : 1 : QVERIFY( !p1.is3D() );
5212 : 1 : QVERIFY( !p1.isMeasure() );
5213 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::Polygon );
5214 : 1 : QCOMPARE( p1.wktTypeStr(), QString( "Polygon" ) );
5215 : 1 : QCOMPARE( p1.geometryType(), QString( "Polygon" ) );
5216 : 1 : QCOMPARE( p1.dimension(), 2 );
5217 : 1 : QVERIFY( !p1.hasCurvedSegments() );
5218 : 1 : QCOMPARE( p1.area(), 0.0 );
5219 : 1 : QCOMPARE( p1.perimeter(), 0.0 );
5220 : 1 : QVERIFY( !p1.exteriorRing() );
5221 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
5222 : :
5223 : : //set exterior ring
5224 : :
5225 : : //try with no ring
5226 : 1 : QgsLineString *ext = nullptr;
5227 : 1 : p1.setExteriorRing( ext );
5228 : 1 : QVERIFY( p1.isEmpty() );
5229 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
5230 : 1 : QCOMPARE( p1.nCoordinates(), 0 );
5231 : 1 : QCOMPARE( p1.ringCount(), 0 );
5232 : 1 : QCOMPARE( p1.partCount(), 0 );
5233 : 1 : QVERIFY( !p1.exteriorRing() );
5234 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
5235 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::Polygon );
5236 : :
5237 : : // empty exterior ring
5238 : 1 : ext = new QgsLineString();
5239 : 1 : p1.setExteriorRing( ext );
5240 : 1 : QVERIFY( p1.isEmpty() );
5241 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
5242 : 1 : QCOMPARE( p1.nCoordinates(), 0 );
5243 : 1 : QCOMPARE( p1.ringCount(), 1 );
5244 : 1 : QCOMPARE( p1.partCount(), 1 );
5245 : 1 : QVERIFY( p1.exteriorRing() );
5246 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
5247 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::Polygon );
5248 : :
5249 : : //valid exterior ring
5250 : 1 : ext = new QgsLineString();
5251 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5252 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5253 : 1 : p1.setExteriorRing( ext );
5254 : 1 : QVERIFY( !p1.isEmpty() );
5255 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
5256 : 1 : QCOMPARE( p1.nCoordinates(), 5 );
5257 : 1 : QCOMPARE( p1.ringCount(), 1 );
5258 : 1 : QCOMPARE( p1.partCount(), 1 );
5259 : 1 : QVERIFY( !p1.is3D() );
5260 : 1 : QVERIFY( !p1.isMeasure() );
5261 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::Polygon );
5262 : 1 : QCOMPARE( p1.wktTypeStr(), QString( "Polygon" ) );
5263 : 1 : QCOMPARE( p1.geometryType(), QString( "Polygon" ) );
5264 : 1 : QCOMPARE( p1.dimension(), 2 );
5265 : 1 : QVERIFY( !p1.hasCurvedSegments() );
5266 : 1 : QCOMPARE( p1.area(), 100.0 );
5267 : 1 : QCOMPARE( p1.perimeter(), 40.0 );
5268 : 1 : QVERIFY( p1.exteriorRing() );
5269 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
5270 : :
5271 : : //retrieve exterior ring and check
5272 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( p1.exteriorRing() ) ), *ext );
5273 : :
5274 : : //test that a non closed exterior ring will be automatically closed
5275 : 1 : ext = new QgsLineString();
5276 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5277 : 1 : << QgsPoint( 10, 0 ) );
5278 : 1 : QVERIFY( !ext->isClosed() );
5279 : 1 : p1.setExteriorRing( ext );
5280 : 1 : QVERIFY( !p1.isEmpty() );
5281 : 1 : QVERIFY( p1.exteriorRing()->isClosed() );
5282 : 1 : QCOMPARE( p1.nCoordinates(), 5 );
5283 : :
5284 : : //initial setting of exterior ring should set z/m type
5285 : 1 : QgsPolygon p2;
5286 : 1 : ext = new QgsLineString();
5287 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
5288 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
5289 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
5290 : 1 : p2.setExteriorRing( ext );
5291 : 1 : QVERIFY( p2.is3D() );
5292 : 1 : QVERIFY( !p2.isMeasure() );
5293 : 1 : QCOMPARE( p2.wkbType(), QgsWkbTypes::PolygonZ );
5294 : 1 : QCOMPARE( p2.wktTypeStr(), QString( "PolygonZ" ) );
5295 : 1 : QCOMPARE( p2.geometryType(), QString( "Polygon" ) );
5296 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( p2.exteriorRing() ) ), *ext );
5297 : 1 : QgsPolygon p3;
5298 : 1 : ext = new QgsLineString();
5299 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 )
5300 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0, 10, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 )
5301 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
5302 : 1 : p3.setExteriorRing( ext );
5303 : 1 : QVERIFY( !p3.is3D() );
5304 : 1 : QVERIFY( p3.isMeasure() );
5305 : 1 : QCOMPARE( p3.wkbType(), QgsWkbTypes::PolygonM );
5306 : 1 : QCOMPARE( p3.wktTypeStr(), QString( "PolygonM" ) );
5307 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( p3.exteriorRing() ) ), *ext );
5308 : 1 : QgsPolygon p4;
5309 : 1 : ext = new QgsLineString();
5310 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 2, 1 )
5311 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 3, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 5, 3 )
5312 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 2, 1 ) );
5313 : 1 : p4.setExteriorRing( ext );
5314 : 1 : QVERIFY( p4.is3D() );
5315 : 1 : QVERIFY( p4.isMeasure() );
5316 : 1 : QCOMPARE( p4.wkbType(), QgsWkbTypes::PolygonZM );
5317 : 1 : QCOMPARE( p4.wktTypeStr(), QString( "PolygonZM" ) );
5318 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( p4.exteriorRing() ) ), *ext );
5319 : 1 : QgsPolygon p5;
5320 : 1 : ext = new QgsLineString();
5321 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 0, 0, 1 )
5322 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::Point25D, 10, 10, 3 )
5323 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::Point25D, 0, 0, 1 ) );
5324 : 1 : p5.setExteriorRing( ext );
5325 : 1 : QVERIFY( p5.is3D() );
5326 : 1 : QVERIFY( !p5.isMeasure() );
5327 : 1 : QCOMPARE( p5.wkbType(), QgsWkbTypes::Polygon25D );
5328 : 1 : QCOMPARE( p5.wktTypeStr(), QString( "PolygonZ" ) );
5329 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( p5.exteriorRing() ) ), *ext );
5330 : :
5331 : : //setting curved exterior ring should be segmentized
5332 : 1 : QgsCircularString *circularRing = new QgsCircularString();
5333 : 2 : circularRing->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5334 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5335 : 1 : QVERIFY( circularRing->hasCurvedSegments() );
5336 : 1 : p5.setExteriorRing( circularRing );
5337 : 1 : QVERIFY( !p5.exteriorRing()->hasCurvedSegments() );
5338 : 1 : QCOMPARE( p5.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
5339 : :
5340 : : //addInteriorRing
5341 : 1 : QgsPolygon p6;
5342 : 1 : ext = new QgsLineString();
5343 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5344 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5345 : 1 : p6.setExteriorRing( ext );
5346 : : //empty ring
5347 : 1 : QCOMPARE( p6.numInteriorRings(), 0 );
5348 : 1 : QVERIFY( !p6.interiorRing( -1 ) );
5349 : 1 : QVERIFY( !p6.interiorRing( 0 ) );
5350 : 1 : p6.addInteriorRing( nullptr );
5351 : 1 : QCOMPARE( p6.numInteriorRings(), 0 );
5352 : 1 : QgsLineString *ring = new QgsLineString();
5353 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
5354 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) );
5355 : 1 : p6.addInteriorRing( ring );
5356 : 1 : QCOMPARE( p6.numInteriorRings(), 1 );
5357 : 1 : QCOMPARE( p6.interiorRing( 0 ), ring );
5358 : 1 : QVERIFY( !p6.interiorRing( 1 ) );
5359 : :
5360 : 1 : QgsCoordinateSequence seq = p6.coordinateSequence();
5361 : 1 : QCOMPARE( seq, QgsCoordinateSequence() << ( QgsRingSequence() << ( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5362 : : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) )
5363 : : << ( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
5364 : : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) ) ) );
5365 : 1 : QCOMPARE( p6.nCoordinates(), 10 );
5366 : :
5367 : : //add non-closed interior ring, should be closed automatically
5368 : 1 : ring = new QgsLineString();
5369 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 ) << QgsPoint( 0.1, 0.9 ) << QgsPoint( 0.9, 0.9 )
5370 : 1 : << QgsPoint( 0.9, 0.1 ) );
5371 : 1 : QVERIFY( !ring->isClosed() );
5372 : 1 : p6.addInteriorRing( ring );
5373 : 1 : QCOMPARE( p6.numInteriorRings(), 2 );
5374 : 1 : QVERIFY( p6.interiorRing( 1 )->isClosed() );
5375 : :
5376 : : //try adding an interior ring with z to a 2d polygon, z should be dropped
5377 : 1 : ring = new QgsLineString();
5378 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
5379 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
5380 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
5381 : 1 : p6.addInteriorRing( ring );
5382 : 1 : QCOMPARE( p6.numInteriorRings(), 3 );
5383 : 1 : QVERIFY( !p6.is3D() );
5384 : 1 : QVERIFY( !p6.isMeasure() );
5385 : 1 : QCOMPARE( p6.wkbType(), QgsWkbTypes::Polygon );
5386 : 1 : QVERIFY( p6.interiorRing( 2 ) );
5387 : 1 : QVERIFY( !p6.interiorRing( 2 )->is3D() );
5388 : 1 : QVERIFY( !p6.interiorRing( 2 )->isMeasure() );
5389 : 1 : QCOMPARE( p6.interiorRing( 2 )->wkbType(), QgsWkbTypes::LineString );
5390 : :
5391 : : //try adding an interior ring with m to a 2d polygon, m should be dropped
5392 : 1 : ring = new QgsLineString();
5393 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.1, 0, 1 )
5394 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.2, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 0.2, 0.2, 0, 3 )
5395 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.2, 0.1, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.1, 0, 1 ) );
5396 : 1 : p6.addInteriorRing( ring );
5397 : 1 : QCOMPARE( p6.numInteriorRings(), 4 );
5398 : 1 : QVERIFY( !p6.is3D() );
5399 : 1 : QVERIFY( !p6.isMeasure() );
5400 : 1 : QCOMPARE( p6.wkbType(), QgsWkbTypes::Polygon );
5401 : 1 : QVERIFY( p6.interiorRing( 3 ) );
5402 : 1 : QVERIFY( !p6.interiorRing( 3 )->is3D() );
5403 : 1 : QVERIFY( !p6.interiorRing( 3 )->isMeasure() );
5404 : 1 : QCOMPARE( p6.interiorRing( 3 )->wkbType(), QgsWkbTypes::LineString );
5405 : :
5406 : : //addInteriorRing without z/m to PolygonZM
5407 : 1 : QgsPolygon p6b;
5408 : 1 : ext = new QgsLineString();
5409 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1 )
5410 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3 )
5411 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1 ) );
5412 : 1 : p6b.setExteriorRing( ext );
5413 : 1 : QVERIFY( p6b.is3D() );
5414 : 1 : QVERIFY( p6b.isMeasure() );
5415 : 1 : QCOMPARE( p6b.wkbType(), QgsWkbTypes::PolygonZM );
5416 : : //ring has no z
5417 : 1 : ring = new QgsLineString();
5418 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 1, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 1, 9 ) << QgsPoint( QgsWkbTypes::PointM, 9, 9 )
5419 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 1 ) << QgsPoint( QgsWkbTypes::PointM, 1, 1 ) );
5420 : 1 : p6b.addInteriorRing( ring );
5421 : 1 : QVERIFY( p6b.interiorRing( 0 ) );
5422 : 1 : QVERIFY( p6b.interiorRing( 0 )->is3D() );
5423 : 1 : QVERIFY( p6b.interiorRing( 0 )->isMeasure() );
5424 : 1 : QCOMPARE( p6b.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineStringZM );
5425 : 1 : QCOMPARE( p6b.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 0, 2 ) );
5426 : : //ring has no m
5427 : 1 : ring = new QgsLineString();
5428 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
5429 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
5430 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
5431 : 1 : p6b.addInteriorRing( ring );
5432 : 1 : QVERIFY( p6b.interiorRing( 1 ) );
5433 : 1 : QVERIFY( p6b.interiorRing( 1 )->is3D() );
5434 : 1 : QVERIFY( p6b.interiorRing( 1 )->isMeasure() );
5435 : 1 : QCOMPARE( p6b.interiorRing( 1 )->wkbType(), QgsWkbTypes::LineStringZM );
5436 : 1 : QCOMPARE( p6b.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 0.1, 0.1, 1, 0 ) );
5437 : : //test handling of 25D rings/polygons
5438 : 1 : QgsPolygon p6c;
5439 : 1 : ext = new QgsLineString();
5440 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 0, 0, 1 )
5441 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::Point25D, 10, 10, 3 )
5442 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::Point25D, 0, 0, 1 ) );
5443 : 1 : p6c.setExteriorRing( ext );
5444 : 1 : QVERIFY( p6c.is3D() );
5445 : 1 : QVERIFY( !p6c.isMeasure() );
5446 : 1 : QCOMPARE( p6c.wkbType(), QgsWkbTypes::Polygon25D );
5447 : : //adding a LineStringZ, should become LineString25D
5448 : 1 : ring = new QgsLineString();
5449 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
5450 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
5451 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
5452 : 1 : QCOMPARE( ring->wkbType(), QgsWkbTypes::LineStringZ );
5453 : 1 : p6c.addInteriorRing( ring );
5454 : 1 : QVERIFY( p6c.interiorRing( 0 ) );
5455 : 1 : QVERIFY( p6c.interiorRing( 0 )->is3D() );
5456 : 1 : QVERIFY( !p6c.interiorRing( 0 )->isMeasure() );
5457 : 1 : QCOMPARE( p6c.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString25D );
5458 : 1 : QCOMPARE( p6c.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point25D, 0.1, 0.1, 1 ) );
5459 : : //add a LineStringM, should become LineString25D
5460 : 1 : ring = new QgsLineString();
5461 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.1, 0, 1 )
5462 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.2, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 0.2, 0.2, 0, 3 )
5463 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.2, 0.1, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.1, 0, 1 ) );
5464 : 1 : QCOMPARE( ring->wkbType(), QgsWkbTypes::LineStringM );
5465 : 1 : p6c.addInteriorRing( ring );
5466 : 1 : QVERIFY( p6c.interiorRing( 1 ) );
5467 : 1 : QVERIFY( p6c.interiorRing( 1 )->is3D() );
5468 : 1 : QVERIFY( !p6c.interiorRing( 1 )->isMeasure() );
5469 : 1 : QCOMPARE( p6c.interiorRing( 1 )->wkbType(), QgsWkbTypes::LineString25D );
5470 : 1 : QCOMPARE( p6c.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point25D, 0.1, 0.1 ) );
5471 : :
5472 : : //add curved ring to polygon
5473 : 1 : circularRing = new QgsCircularString();
5474 : 2 : circularRing->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5475 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5476 : 1 : QVERIFY( circularRing->hasCurvedSegments() );
5477 : 1 : p6c.addInteriorRing( circularRing );
5478 : 1 : QVERIFY( p6c.interiorRing( 2 ) );
5479 : 1 : QVERIFY( !p6c.interiorRing( 2 )->hasCurvedSegments() );
5480 : 1 : QVERIFY( p6c.interiorRing( 2 )->is3D() );
5481 : 1 : QVERIFY( !p6c.interiorRing( 2 )->isMeasure() );
5482 : 1 : QCOMPARE( p6c.interiorRing( 2 )->wkbType(), QgsWkbTypes::LineString25D );
5483 : :
5484 : : // alternate constructor
5485 : 2 : QgsPolygon pc6( new QgsLineString( QVector<QgsPoint>() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 ) << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) ),
5486 : 1 : QList< QgsLineString *>() << new QgsLineString( QVector< QgsPoint >() << QgsPoint( 1, 1 ) << QgsPoint( 2, 1 ) << QgsPoint( 2, 2 ) << QgsPoint( 1, 2 ) << QgsPoint( 1, 1 ) )
5487 : 1 : << new QgsLineString( QVector< QgsPoint >() << QgsPoint( 3, 1 ) << QgsPoint( 4, 1 ) << QgsPoint( 4, 2 ) << QgsPoint( 3, 2 ) << QgsPoint( 3, 1 ) ) );
5488 : 2 : QCOMPARE( pc6.asWkt(), QStringLiteral( "Polygon ((0 0, 0 10, 10 10, 10 0, 0 0),(1 1, 2 1, 2 2, 1 2, 1 1),(3 1, 4 1, 4 2, 3 2, 3 1))" ) );
5489 : :
5490 : : //set interior rings
5491 : 1 : QgsPolygon p7;
5492 : 1 : ext = new QgsLineString();
5493 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5494 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5495 : 1 : p7.setExteriorRing( ext );
5496 : : //add a list of rings with mixed types
5497 : 1 : QVector< QgsCurve * > rings;
5498 : 1 : rings << new QgsLineString();
5499 : 2 : static_cast< QgsLineString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
5500 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
5501 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
5502 : 1 : rings << new QgsLineString();
5503 : 2 : static_cast< QgsLineString *>( rings[1] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0.3, 0.3, 0, 1 )
5504 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.3, 0.4, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 0.4, 0.4, 0, 3 )
5505 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.4, 0.3, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0.3, 0.3, 0, 1 ) );
5506 : : //throw an empty ring in too
5507 : 1 : rings << 0;
5508 : 1 : rings << new QgsCircularString();
5509 : 2 : static_cast< QgsCircularString *>( rings[3] )->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5510 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5511 : 1 : p7.setInteriorRings( rings );
5512 : 1 : QCOMPARE( p7.numInteriorRings(), 3 );
5513 : 1 : QVERIFY( p7.interiorRing( 0 ) );
5514 : 1 : QVERIFY( !p7.interiorRing( 0 )->is3D() );
5515 : 1 : QVERIFY( !p7.interiorRing( 0 )->isMeasure() );
5516 : 1 : QCOMPARE( p7.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
5517 : 1 : QCOMPARE( p7.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point, 0.1, 0.1 ) );
5518 : 1 : QVERIFY( p7.interiorRing( 1 ) );
5519 : 1 : QVERIFY( !p7.interiorRing( 1 )->is3D() );
5520 : 1 : QVERIFY( !p7.interiorRing( 1 )->isMeasure() );
5521 : 1 : QCOMPARE( p7.interiorRing( 1 )->wkbType(), QgsWkbTypes::LineString );
5522 : 1 : QCOMPARE( p7.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point, 0.3, 0.3 ) );
5523 : 1 : QVERIFY( p7.interiorRing( 2 ) );
5524 : 1 : QVERIFY( !p7.interiorRing( 2 )->is3D() );
5525 : 1 : QVERIFY( !p7.interiorRing( 2 )->isMeasure() );
5526 : 1 : QCOMPARE( p7.interiorRing( 2 )->wkbType(), QgsWkbTypes::LineString );
5527 : :
5528 : : //set rings with existing
5529 : 1 : rings.clear();
5530 : 1 : rings << new QgsLineString();
5531 : 2 : static_cast< QgsLineString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( 0.8, 0.8 )
5532 : 1 : << QgsPoint( 0.8, 0.9 ) << QgsPoint( 0.9, 0.9 )
5533 : 1 : << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.8, 0.8 ) );
5534 : 1 : p7.setInteriorRings( rings );
5535 : 1 : QCOMPARE( p7.numInteriorRings(), 1 );
5536 : 1 : QVERIFY( p7.interiorRing( 0 ) );
5537 : 1 : QVERIFY( !p7.interiorRing( 0 )->is3D() );
5538 : 1 : QVERIFY( !p7.interiorRing( 0 )->isMeasure() );
5539 : 1 : QCOMPARE( p7.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
5540 : 1 : QCOMPARE( p7.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point, 0.8, 0.8 ) );
5541 : 1 : rings.clear();
5542 : 1 : p7.setInteriorRings( rings );
5543 : 1 : QCOMPARE( p7.numInteriorRings(), 0 );
5544 : :
5545 : : //change dimensionality of interior rings using setExteriorRing
5546 : 1 : QgsPolygon p7a;
5547 : 1 : ext = new QgsLineString();
5548 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 )
5549 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
5550 : 1 : p7a.setExteriorRing( ext );
5551 : 1 : rings.clear();
5552 : 1 : rings << new QgsLineString();
5553 : 2 : static_cast< QgsLineString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
5554 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
5555 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
5556 : 1 : rings << new QgsLineString();
5557 : 2 : static_cast< QgsLineString *>( rings[1] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.3, 0.3, 1 )
5558 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.3, 0.4, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.4, 0.4, 3 )
5559 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.4, 0.3, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.3, 0.3, 1 ) );
5560 : 1 : p7a.setInteriorRings( rings );
5561 : 1 : QVERIFY( p7a.is3D() );
5562 : 1 : QVERIFY( !p7a.isMeasure() );
5563 : 1 : QVERIFY( p7a.interiorRing( 0 )->is3D() );
5564 : 1 : QVERIFY( !p7a.interiorRing( 0 )->isMeasure() );
5565 : 1 : QVERIFY( p7a.interiorRing( 1 )->is3D() );
5566 : 1 : QVERIFY( !p7a.interiorRing( 1 )->isMeasure() );
5567 : : //reset exterior ring to 2d
5568 : 1 : ext = new QgsLineString();
5569 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 )
5570 : 1 : << QgsPoint( 10, 10 ) << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5571 : 1 : p7a.setExteriorRing( ext );
5572 : 1 : QVERIFY( !p7a.is3D() );
5573 : 1 : QVERIFY( !p7a.interiorRing( 0 )->is3D() ); //rings should also be made 2D
5574 : 1 : QVERIFY( !p7a.interiorRing( 1 )->is3D() );
5575 : : //reset exterior ring to LineStringM
5576 : 1 : ext = new QgsLineString();
5577 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0 ) << QgsPoint( QgsWkbTypes::PointM, 0, 10 )
5578 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 10 ) << QgsPoint( QgsWkbTypes::PointM, 10, 0 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0 ) );
5579 : 1 : p7a.setExteriorRing( ext );
5580 : 1 : QVERIFY( p7a.isMeasure() );
5581 : 1 : QVERIFY( p7a.interiorRing( 0 )->isMeasure() ); //rings should also gain measure
5582 : 1 : QVERIFY( p7a.interiorRing( 1 )->isMeasure() );
5583 : : //25D exterior ring
5584 : 1 : ext = new QgsLineString();
5585 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 0, 0 ) << QgsPoint( QgsWkbTypes::Point25D, 0, 10 )
5586 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 10, 10 ) << QgsPoint( QgsWkbTypes::Point25D, 10, 0 ) << QgsPoint( QgsWkbTypes::Point25D, 0, 0 ) );
5587 : 1 : p7a.setExteriorRing( ext );
5588 : 1 : QVERIFY( p7a.is3D() );
5589 : 1 : QVERIFY( !p7a.isMeasure() );
5590 : 1 : QVERIFY( p7a.interiorRing( 0 )->is3D() ); //rings should also be made 25D
5591 : 1 : QVERIFY( !p7a.interiorRing( 0 )->isMeasure() );
5592 : 1 : QVERIFY( p7a.interiorRing( 1 )->is3D() );
5593 : 1 : QVERIFY( !p7a.interiorRing( 1 )->isMeasure() );
5594 : 1 : QCOMPARE( p7a.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString25D );
5595 : 1 : QCOMPARE( p7a.interiorRing( 1 )->wkbType(), QgsWkbTypes::LineString25D );
5596 : :
5597 : :
5598 : : //removeInteriorRing
5599 : 1 : QgsPolygon p8;
5600 : 1 : ext = new QgsLineString();
5601 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5602 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5603 : 1 : p8.setExteriorRing( ext );
5604 : 1 : QVERIFY( !p8.removeInteriorRing( -1 ) );
5605 : 1 : QVERIFY( !p8.removeInteriorRing( 0 ) );
5606 : 1 : rings.clear();
5607 : 1 : rings << new QgsLineString();
5608 : 2 : static_cast< QgsLineString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 )
5609 : 1 : << QgsPoint( 0.1, 0.2 ) << QgsPoint( 0.2, 0.2 )
5610 : 1 : << QgsPoint( 0.2, 0.1 ) << QgsPoint( 0.1, 0.1 ) );
5611 : 1 : rings << new QgsLineString();
5612 : 2 : static_cast< QgsLineString *>( rings[1] )->setPoints( QgsPointSequence() << QgsPoint( 0.3, 0.3 )
5613 : 1 : << QgsPoint( 0.3, 0.4 ) << QgsPoint( 0.4, 0.4 )
5614 : 1 : << QgsPoint( 0.4, 0.3 ) << QgsPoint( 0.3, 0.3 ) );
5615 : 1 : rings << new QgsLineString();
5616 : 2 : static_cast< QgsLineString *>( rings[2] )->setPoints( QgsPointSequence() << QgsPoint( 0.8, 0.8 )
5617 : 1 : << QgsPoint( 0.8, 0.9 ) << QgsPoint( 0.9, 0.9 )
5618 : 1 : << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.8, 0.8 ) );
5619 : 1 : p8.setInteriorRings( rings );
5620 : 1 : QCOMPARE( p8.numInteriorRings(), 3 );
5621 : 1 : QVERIFY( p8.removeInteriorRing( 0 ) );
5622 : 1 : QCOMPARE( p8.numInteriorRings(), 2 );
5623 : 1 : QCOMPARE( p8.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0.3, 0.3 ) );
5624 : 1 : QCOMPARE( p8.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0.8, 0.8 ) );
5625 : 1 : QVERIFY( p8.removeInteriorRing( 1 ) );
5626 : 1 : QCOMPARE( p8.numInteriorRings(), 1 );
5627 : 1 : QCOMPARE( p8.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0.3, 0.3 ) );
5628 : 1 : QVERIFY( p8.removeInteriorRing( 0 ) );
5629 : 1 : QCOMPARE( p8.numInteriorRings(), 0 );
5630 : 1 : QVERIFY( !p8.removeInteriorRing( 0 ) );
5631 : :
5632 : : //clear
5633 : 1 : QgsPolygon p9;
5634 : 1 : ext = new QgsLineString();
5635 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
5636 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
5637 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
5638 : 1 : p9.setExteriorRing( ext );
5639 : 1 : ring = new QgsLineString();
5640 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 )
5641 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 9, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 9, 9, 3 )
5642 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 ) );
5643 : 1 : p9.addInteriorRing( ring );
5644 : 1 : QCOMPARE( p9.numInteriorRings(), 1 );
5645 : 1 : p9.clear();
5646 : 1 : QVERIFY( p9.isEmpty() );
5647 : 1 : QCOMPARE( p9.numInteriorRings(), 0 );
5648 : 1 : QCOMPARE( p9.nCoordinates(), 0 );
5649 : 1 : QCOMPARE( p9.ringCount(), 0 );
5650 : 1 : QCOMPARE( p9.partCount(), 0 );
5651 : 1 : QVERIFY( !p9.is3D() );
5652 : 1 : QVERIFY( !p9.isMeasure() );
5653 : 1 : QCOMPARE( p9.wkbType(), QgsWkbTypes::Polygon );
5654 : :
5655 : : //equality operator
5656 : 1 : QgsPolygon p10;
5657 : 1 : QgsPolygon p10b;
5658 : 1 : QVERIFY( p10 == p10b );
5659 : 1 : QVERIFY( !( p10 != p10b ) );
5660 : 1 : ext = new QgsLineString();
5661 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5662 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5663 : 1 : p10.setExteriorRing( ext );
5664 : 1 : QVERIFY( !( p10 == p10b ) );
5665 : 1 : QVERIFY( p10 != p10b );
5666 : 1 : ext = new QgsLineString();
5667 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
5668 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
5669 : 1 : p10b.setExteriorRing( ext );
5670 : 1 : QVERIFY( p10 == p10b );
5671 : 1 : QVERIFY( !( p10 != p10b ) );
5672 : 1 : ext = new QgsLineString();
5673 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 9 ) << QgsPoint( 9, 9 )
5674 : 1 : << QgsPoint( 9, 0 ) << QgsPoint( 0, 0 ) );
5675 : 1 : p10b.setExteriorRing( ext );
5676 : 1 : QVERIFY( !( p10 == p10b ) );
5677 : 1 : QVERIFY( p10 != p10b );
5678 : 1 : ext = new QgsLineString();
5679 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 )
5680 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
5681 : 1 : p10b.setExteriorRing( ext );
5682 : 1 : QVERIFY( !( p10 == p10b ) );
5683 : 1 : QVERIFY( p10 != p10b );
5684 : 1 : p10b.setExteriorRing( p10.exteriorRing()->clone() );
5685 : 1 : QVERIFY( p10 == p10b );
5686 : 1 : QVERIFY( !( p10 != p10b ) );
5687 : 1 : ring = new QgsLineString();
5688 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 1, 1 )
5689 : 1 : << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
5690 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) );
5691 : 1 : p10.addInteriorRing( ring );
5692 : 1 : QVERIFY( !( p10 == p10b ) );
5693 : 1 : QVERIFY( p10 != p10b );
5694 : :
5695 : 1 : ring = new QgsLineString();
5696 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 2, 1 )
5697 : 1 : << QgsPoint( 2, 9 ) << QgsPoint( 9, 9 )
5698 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 2, 1 ) );
5699 : 1 : p10b.addInteriorRing( ring );
5700 : 1 : QVERIFY( !( p10 == p10b ) );
5701 : 1 : QVERIFY( p10 != p10b );
5702 : 1 : p10b.removeInteriorRing( 0 );
5703 : 1 : p10b.addInteriorRing( p10.interiorRing( 0 )->clone() );
5704 : 1 : QVERIFY( p10 == p10b );
5705 : 1 : QVERIFY( !( p10 != p10b ) );
5706 : :
5707 : 1 : QgsLineString nonPolygon;
5708 : 1 : QVERIFY( p10 != nonPolygon );
5709 : 1 : QVERIFY( !( p10 == nonPolygon ) );
5710 : :
5711 : : //clone
5712 : :
5713 : 1 : QgsPolygon p11;
5714 : 1 : std::unique_ptr< QgsPolygon >cloned( p11.clone() );
5715 : 1 : QCOMPARE( p11, *cloned );
5716 : 1 : ext = new QgsLineString();
5717 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
5718 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
5719 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
5720 : 1 : p11.setExteriorRing( ext );
5721 : 1 : ring = new QgsLineString();
5722 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
5723 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
5724 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
5725 : 1 : p11.addInteriorRing( ring );
5726 : 1 : cloned.reset( p11.clone() );
5727 : 1 : QCOMPARE( p11, *cloned );
5728 : :
5729 : : //copy constructor
5730 : 1 : QgsPolygon p12;
5731 : 1 : QgsPolygon p13( p12 );
5732 : 1 : QCOMPARE( p12, p13 );
5733 : 1 : ext = new QgsLineString();
5734 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
5735 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
5736 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
5737 : 1 : p12.setExteriorRing( ext );
5738 : 1 : ring = new QgsLineString();
5739 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
5740 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
5741 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
5742 : 1 : p12.addInteriorRing( ring );
5743 : 1 : QgsPolygon p14( p12 );
5744 : 1 : QCOMPARE( p12, p14 );
5745 : :
5746 : : //assignment operator
5747 : 1 : QgsPolygon p15;
5748 : 1 : p15 = p13;
5749 : 1 : QCOMPARE( p13, p15 );
5750 : 1 : p15 = p12;
5751 : 1 : QCOMPARE( p12, p15 );
5752 : :
5753 : : //surfaceToPolygon - should be identical given polygon has no curves
5754 : 1 : std::unique_ptr< QgsPolygon > surface( p12.surfaceToPolygon() );
5755 : 1 : QCOMPARE( *surface, p12 );
5756 : : //toPolygon - should be identical given polygon has no curves
5757 : 1 : std::unique_ptr< QgsPolygon > toP( p12.toPolygon() );
5758 : 1 : QCOMPARE( *toP, p12 );
5759 : :
5760 : : //toCurveType
5761 : 1 : std::unique_ptr< QgsCurvePolygon > curveType( p12.toCurveType() );
5762 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::CurvePolygonZM );
5763 : 1 : QCOMPARE( curveType->exteriorRing()->numPoints(), 5 );
5764 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 ) );
5765 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) );
5766 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 ) );
5767 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
5768 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 4 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
5769 : 1 : QCOMPARE( curveType->numInteriorRings(), 1 );
5770 : 1 : QCOMPARE( curveType->interiorRing( 0 )->numPoints(), 5 );
5771 : 1 : QCOMPARE( curveType->interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 ) );
5772 : 1 : QCOMPARE( curveType->interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) );
5773 : 1 : QCOMPARE( curveType->interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 ) );
5774 : 1 : QCOMPARE( curveType->interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) );
5775 : 1 : QCOMPARE( curveType->interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 4 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
5776 : :
5777 : : //to/fromWKB
5778 : 1 : QgsPolygon p16;
5779 : 1 : ext = new QgsLineString();
5780 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 0, 0 )
5781 : 1 : << QgsPoint( QgsWkbTypes::Point, 0, 10 ) << QgsPoint( QgsWkbTypes::Point, 10, 10 )
5782 : 1 : << QgsPoint( QgsWkbTypes::Point, 10, 0 ) << QgsPoint( QgsWkbTypes::Point, 0, 0 ) );
5783 : 1 : p16.setExteriorRing( ext );
5784 : 1 : ring = new QgsLineString();
5785 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 1 )
5786 : 1 : << QgsPoint( QgsWkbTypes::Point, 1, 9 ) << QgsPoint( QgsWkbTypes::Point, 9, 9 )
5787 : 1 : << QgsPoint( QgsWkbTypes::Point, 9, 1 ) << QgsPoint( QgsWkbTypes::Point, 1, 1 ) );
5788 : 1 : p16.addInteriorRing( ring );
5789 : 1 : QByteArray wkb16 = p16.asWkb();
5790 : 1 : QCOMPARE( wkb16.size(), p16.wkbSize() );
5791 : 1 : QgsPolygon p17;
5792 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
5793 : 1 : p17.fromWkb( wkb16ptr );
5794 : 1 : QCOMPARE( p16, p17 );
5795 : : //PolygonZ
5796 : 1 : p16.clear();
5797 : 1 : p17.clear();
5798 : 1 : ext = new QgsLineString();
5799 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
5800 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
5801 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
5802 : 1 : p16.setExteriorRing( ext );
5803 : 1 : ring = new QgsLineString();
5804 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 )
5805 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 9, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 9, 9, 3 )
5806 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 ) );
5807 : 1 : p16.addInteriorRing( ring );
5808 : 1 : wkb16 = p16.asWkb();
5809 : 1 : QCOMPARE( wkb16.size(), p16.wkbSize() );
5810 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
5811 : 1 : p17.fromWkb( wkb16ptr2 );
5812 : 1 : QCOMPARE( p16, p17 );
5813 : : //PolygonM
5814 : 1 : p16.clear();
5815 : 1 : p17.clear();
5816 : 1 : ext = new QgsLineString();
5817 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 )
5818 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0, 10, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 )
5819 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
5820 : 1 : p16.setExteriorRing( ext );
5821 : 1 : ring = new QgsLineString();
5822 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 1, 0, 1 )
5823 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1, 9, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 9, 9, 0, 3 )
5824 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 1, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 1, 1, 0, 1 ) );
5825 : 1 : p16.addInteriorRing( ring );
5826 : 1 : wkb16 = p16.asWkb();
5827 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
5828 : 1 : p17.fromWkb( wkb16ptr3 );
5829 : 1 : QCOMPARE( p16, p17 );
5830 : : //PolygonZM
5831 : 1 : p16.clear();
5832 : 1 : p17.clear();
5833 : 1 : ext = new QgsLineString();
5834 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
5835 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
5836 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
5837 : 1 : p16.setExteriorRing( ext );
5838 : 1 : ring = new QgsLineString();
5839 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
5840 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
5841 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
5842 : 1 : p16.addInteriorRing( ring );
5843 : 1 : wkb16 = p16.asWkb();
5844 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
5845 : 1 : p17.fromWkb( wkb16ptr4 );
5846 : 1 : QCOMPARE( p16, p17 );
5847 : : //Polygon25D
5848 : 1 : p16.clear();
5849 : 1 : p17.clear();
5850 : 1 : ext = new QgsLineString();
5851 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 0, 0, 1 )
5852 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::Point25D, 10, 10, 3 )
5853 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::Point25D, 0, 0, 1 ) );
5854 : 1 : p16.setExteriorRing( ext );
5855 : 1 : ring = new QgsLineString();
5856 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point25D, 1, 1, 1 )
5857 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 1, 9, 2 ) << QgsPoint( QgsWkbTypes::Point25D, 9, 9, 3 )
5858 : 1 : << QgsPoint( QgsWkbTypes::Point25D, 9, 1, 4 ) << QgsPoint( QgsWkbTypes::Point25D, 1, 1, 1 ) );
5859 : 1 : p16.addInteriorRing( ring );
5860 : 1 : wkb16 = p16.asWkb();
5861 : 1 : p17.clear();
5862 : 1 : QgsConstWkbPtr wkb16ptr5( wkb16 );
5863 : 1 : p17.fromWkb( wkb16ptr5 );
5864 : 1 : QCOMPARE( p16, p17 );
5865 : :
5866 : : //bad WKB - check for no crash
5867 : 1 : p17.clear();
5868 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
5869 : 1 : QVERIFY( !p17.fromWkb( nullPtr ) );
5870 : 1 : QCOMPARE( p17.wkbType(), QgsWkbTypes::Polygon );
5871 : 1 : QgsPoint point( 1, 2 );
5872 : 1 : QByteArray wkbPoint = point.asWkb();
5873 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
5874 : 1 : QVERIFY( !p17.fromWkb( wkbPointPtr ) );
5875 : 1 : QCOMPARE( p17.wkbType(), QgsWkbTypes::Polygon );
5876 : :
5877 : : //to/from WKT
5878 : 1 : QgsPolygon p18;
5879 : 1 : ext = new QgsLineString();
5880 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
5881 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
5882 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
5883 : 1 : p18.setExteriorRing( ext );
5884 : 1 : ring = new QgsLineString();
5885 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
5886 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
5887 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
5888 : 1 : p18.addInteriorRing( ring );
5889 : :
5890 : 1 : QString wkt = p18.asWkt();
5891 : 1 : QVERIFY( !wkt.isEmpty() );
5892 : 1 : QgsPolygon p19;
5893 : 1 : QVERIFY( p19.fromWkt( wkt ) );
5894 : 1 : QCOMPARE( p18, p19 );
5895 : :
5896 : : //bad WKT
5897 : 1 : QVERIFY( !p19.fromWkt( "Point()" ) );
5898 : 1 : QVERIFY( p19.isEmpty() );
5899 : 1 : QVERIFY( !p19.exteriorRing() );
5900 : 1 : QCOMPARE( p19.numInteriorRings(), 0 );
5901 : 1 : QVERIFY( !p19.is3D() );
5902 : 1 : QVERIFY( !p19.isMeasure() );
5903 : 1 : QCOMPARE( p19.wkbType(), QgsWkbTypes::Polygon );
5904 : :
5905 : : //as JSON
5906 : 1 : QgsPolygon exportPolygon;
5907 : 1 : ext = new QgsLineString();
5908 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 0, 0 )
5909 : 1 : << QgsPoint( QgsWkbTypes::Point, 0, 10 ) << QgsPoint( QgsWkbTypes::Point, 10, 10 )
5910 : 1 : << QgsPoint( QgsWkbTypes::Point, 10, 0 ) << QgsPoint( QgsWkbTypes::Point, 0, 0 ) );
5911 : 1 : exportPolygon.setExteriorRing( ext );
5912 : :
5913 : : // GML document for compare
5914 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
5915 : :
5916 : : // as GML2
5917 : 2 : QString expectedSimpleGML2( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 0,10 10,10 10,0 0,0</coordinates></LinearRing></outerBoundaryIs></Polygon>" ) );
5918 : 3 : QGSCOMPAREGML( elemToString( exportPolygon.asGml2( doc ) ), expectedSimpleGML2 );
5919 : 2 : QString expectedGML2empty( QStringLiteral( "<Polygon xmlns=\"gml\"/>" ) );
5920 : 3 : QGSCOMPAREGML( elemToString( QgsPolygon().asGml2( doc ) ), expectedGML2empty );
5921 : :
5922 : : //as GML3
5923 : 2 : QString expectedSimpleGML3( QStringLiteral( "<Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0 0 0 10 10 10 10 0 0 0</posList></LinearRing></exterior></Polygon>" ) );
5924 : 1 : QCOMPARE( elemToString( exportPolygon.asGml3( doc ) ), expectedSimpleGML3 );
5925 : 2 : QString expectedGML3empty( QStringLiteral( "<Polygon xmlns=\"gml\"/>" ) );
5926 : 3 : QGSCOMPAREGML( elemToString( QgsPolygon().asGml3( doc ) ), expectedGML3empty );
5927 : :
5928 : : // as JSON
5929 : 2 : QString expectedSimpleJson( QStringLiteral( "{\"coordinates\":[[[0.0,0.0],[0.0,10.0],[10.0,10.0],[10.0,0.0],[0.0,0.0]]],\"type\":\"Polygon\"}" ) );
5930 : 1 : QCOMPARE( exportPolygon.asJson(), expectedSimpleJson );
5931 : :
5932 : 1 : ring = new QgsLineString();
5933 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 1 )
5934 : 1 : << QgsPoint( QgsWkbTypes::Point, 1, 9 ) << QgsPoint( QgsWkbTypes::Point, 9, 9 )
5935 : 1 : << QgsPoint( QgsWkbTypes::Point, 9, 1 ) << QgsPoint( QgsWkbTypes::Point, 1, 1 ) );
5936 : 1 : exportPolygon.addInteriorRing( ring );
5937 : :
5938 : 2 : QString expectedJson( QStringLiteral( "{\"coordinates\":[[[0.0,0.0],[0.0,10.0],[10.0,10.0],[10.0,0.0],[0.0,0.0]],[[1.0,1.0],[1.0,9.0],[9.0,9.0],[9.0,1.0],[1.0,1.0]]],\"type\":\"Polygon\"}" ) );
5939 : 1 : QCOMPARE( exportPolygon.asJson(), expectedJson );
5940 : :
5941 : 1 : QgsPolygon exportPolygonFloat;
5942 : 1 : ext = new QgsLineString();
5943 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 10 / 9.0 )
5944 : 1 : << QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 100 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 100 / 9.0, 100 / 9.0 )
5945 : 1 : << QgsPoint( QgsWkbTypes::Point, 100 / 9.0, 10 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 10 / 9.0 ) );
5946 : 1 : exportPolygonFloat.setExteriorRing( ext );
5947 : 1 : ring = new QgsLineString();
5948 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 2 / 3.0 )
5949 : 1 : << QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 4 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 4 / 3.0, 4 / 3.0 )
5950 : 1 : << QgsPoint( QgsWkbTypes::Point, 4 / 3.0, 2 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 2 / 3.0 ) );
5951 : 1 : exportPolygonFloat.addInteriorRing( ring );
5952 : :
5953 : 2 : QString expectedJsonPrec3( QStringLiteral( "{\"coordinates\":[[[1.111,1.111],[1.111,11.111],[11.111,11.111],[11.111,1.111],[1.111,1.111]],[[0.667,0.667],[0.667,1.333],[1.333,1.333],[1.333,0.667],[0.667,0.667]]],\"type\":\"Polygon\"}" ) );
5954 : 1 : QCOMPARE( exportPolygonFloat.asJson( 3 ), expectedJsonPrec3 );
5955 : :
5956 : : // as GML2
5957 : 2 : QString expectedGML2( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 0,10 10,10 10,0 0,0</coordinates></LinearRing></outerBoundaryIs>" ) );
5958 : 1 : expectedGML2 += QLatin1String( "<innerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1,1 1,9 9,9 9,1 1,1</coordinates></LinearRing></innerBoundaryIs></Polygon>" );
5959 : 3 : QGSCOMPAREGML( elemToString( exportPolygon.asGml2( doc ) ), expectedGML2 );
5960 : 2 : QString expectedGML2prec3( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1.111,1.111 1.111,11.111 11.111,11.111 11.111,1.111 1.111,1.111</coordinates></LinearRing></outerBoundaryIs>" ) );
5961 : 1 : expectedGML2prec3 += QLatin1String( "<innerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.667,0.667 0.667,1.333 1.333,1.333 1.333,0.667 0.667,0.667</coordinates></LinearRing></innerBoundaryIs></Polygon>" );
5962 : 3 : QGSCOMPAREGML( elemToString( exportPolygonFloat.asGml2( doc, 3 ) ), expectedGML2prec3 );
5963 : :
5964 : : //as GML3
5965 : 2 : QString expectedGML3( QStringLiteral( "<Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0 0 0 10 10 10 10 0 0 0</posList></LinearRing></exterior>" ) );
5966 : 1 : expectedGML3 += QLatin1String( "<interior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1 1 1 9 9 9 9 1 1 1</posList></LinearRing></interior></Polygon>" );
5967 : :
5968 : 1 : QCOMPARE( elemToString( exportPolygon.asGml3( doc ) ), expectedGML3 );
5969 : 2 : QString expectedGML3prec3( QStringLiteral( "<Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1.111 1.111 1.111 11.111 11.111 11.111 11.111 1.111 1.111 1.111</posList></LinearRing></exterior>" ) );
5970 : 1 : expectedGML3prec3 += QLatin1String( "<interior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0.667 0.667 0.667 1.333 1.333 1.333 1.333 0.667 0.667 0.667</posList></LinearRing></interior></Polygon>" );
5971 : 1 : QCOMPARE( elemToString( exportPolygonFloat.asGml3( doc, 3 ) ), expectedGML3prec3 );
5972 : :
5973 : : //asKML
5974 : 2 : QString expectedKml( QStringLiteral( "<Polygon><outerBoundaryIs><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>0,0,0 0,10,0 10,10,0 10,0,0 0,0,0</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>1,1,0 1,9,0 9,9,0 9,1,0 1,1,0</coordinates></LinearRing></innerBoundaryIs></Polygon>" ) );
5975 : 1 : QCOMPARE( exportPolygon.asKml(), expectedKml );
5976 : 2 : QString expectedKmlPrec3( QStringLiteral( "<Polygon><outerBoundaryIs><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>1.111,1.111,0 1.111,11.111,0 11.111,11.111,0 11.111,1.111,0 1.111,1.111,0</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>0.667,0.667,0 0.667,1.333,0 1.333,1.333,0 1.333,0.667,0 0.667,0.667,0</coordinates></LinearRing></innerBoundaryIs></Polygon>" ) );
5977 : 1 : QCOMPARE( exportPolygonFloat.asKml( 3 ), expectedKmlPrec3 );
5978 : :
5979 : : //removing the fourth to last vertex removes the whole ring
5980 : 1 : QgsPolygon p20;
5981 : 1 : QgsLineString *p20ExteriorRing = new QgsLineString();
5982 : 1 : p20ExteriorRing->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
5983 : 1 : p20.setExteriorRing( p20ExteriorRing );
5984 : 1 : QVERIFY( p20.exteriorRing() );
5985 : 1 : p20.deleteVertex( QgsVertexId( 0, 0, 2 ) );
5986 : 1 : QVERIFY( !p20.exteriorRing() );
5987 : :
5988 : : //boundary
5989 : 1 : QgsLineString boundary1;
5990 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
5991 : 1 : QgsPolygon boundaryPolygon;
5992 : 1 : QVERIFY( !boundaryPolygon.boundary() );
5993 : :
5994 : 1 : boundaryPolygon.setExteriorRing( boundary1.clone() );
5995 : 1 : QgsAbstractGeometry *boundary = boundaryPolygon.boundary();
5996 : 1 : QgsLineString *lineBoundary = dynamic_cast< QgsLineString * >( boundary );
5997 : 1 : QVERIFY( lineBoundary );
5998 : 1 : QCOMPARE( lineBoundary->numPoints(), 4 );
5999 : 1 : QCOMPARE( lineBoundary->xAt( 0 ), 0.0 );
6000 : 1 : QCOMPARE( lineBoundary->xAt( 1 ), 1.0 );
6001 : 1 : QCOMPARE( lineBoundary->xAt( 2 ), 1.0 );
6002 : 1 : QCOMPARE( lineBoundary->xAt( 3 ), 0.0 );
6003 : 1 : QCOMPARE( lineBoundary->yAt( 0 ), 0.0 );
6004 : 1 : QCOMPARE( lineBoundary->yAt( 1 ), 0.0 );
6005 : 1 : QCOMPARE( lineBoundary->yAt( 2 ), 1.0 );
6006 : 1 : QCOMPARE( lineBoundary->yAt( 3 ), 0.0 );
6007 : 1 : delete boundary;
6008 : :
6009 : : // add interior rings
6010 : 1 : QgsLineString boundaryRing1;
6011 : 1 : boundaryRing1.setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 ) << QgsPoint( 0.2, 0.1 ) << QgsPoint( 0.2, 0.2 ) << QgsPoint( 0.1, 0.1 ) );
6012 : 1 : QgsLineString boundaryRing2;
6013 : 1 : boundaryRing2.setPoints( QgsPointSequence() << QgsPoint( 0.8, 0.8 ) << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.9, 0.9 ) << QgsPoint( 0.8, 0.8 ) );
6014 : 1 : boundaryPolygon.setInteriorRings( QVector< QgsCurve * >() << boundaryRing1.clone() << boundaryRing2.clone() );
6015 : 1 : boundary = boundaryPolygon.boundary();
6016 : 1 : QgsMultiLineString *multiLineBoundary = dynamic_cast< QgsMultiLineString * >( boundary );
6017 : 1 : QVERIFY( multiLineBoundary );
6018 : 1 : QCOMPARE( multiLineBoundary->numGeometries(), 3 );
6019 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->numPoints(), 4 );
6020 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
6021 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
6022 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 2 ), 1.0 );
6023 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 3 ), 0.0 );
6024 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
6025 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
6026 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 2 ), 1.0 );
6027 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.0 );
6028 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->numPoints(), 4 );
6029 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 0 ), 0.1 );
6030 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 1 ), 0.2 );
6031 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 2 ), 0.2 );
6032 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 3 ), 0.1 );
6033 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 0 ), 0.1 );
6034 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 1 ), 0.1 );
6035 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 2 ), 0.2 );
6036 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 3 ), 0.1 );
6037 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->numPoints(), 4 );
6038 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 0 ), 0.8 );
6039 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 1 ), 0.9 );
6040 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 2 ), 0.9 );
6041 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 3 ), 0.8 );
6042 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 0 ), 0.8 );
6043 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 1 ), 0.8 );
6044 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 2 ), 0.9 );
6045 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 3 ), 0.8 );
6046 : 1 : boundaryPolygon.setInteriorRings( QVector< QgsCurve * >() );
6047 : 1 : delete boundary;
6048 : :
6049 : : //test boundary with z
6050 : 2 : boundary1.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 )
6051 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) );
6052 : 1 : boundaryPolygon.setExteriorRing( boundary1.clone() );
6053 : 1 : boundary = boundaryPolygon.boundary();
6054 : 1 : lineBoundary = dynamic_cast< QgsLineString * >( boundary );
6055 : 1 : QVERIFY( lineBoundary );
6056 : 1 : QCOMPARE( lineBoundary->numPoints(), 4 );
6057 : 1 : QCOMPARE( lineBoundary->wkbType(), QgsWkbTypes::LineStringZ );
6058 : 1 : QCOMPARE( lineBoundary->zAt( 0 ), 10.0 );
6059 : 1 : QCOMPARE( lineBoundary->zAt( 1 ), 15.0 );
6060 : 1 : QCOMPARE( lineBoundary->zAt( 2 ), 20.0 );
6061 : 1 : QCOMPARE( lineBoundary->zAt( 3 ), 10.0 );
6062 : 1 : delete boundary;
6063 : :
6064 : : // point distance to boundary
6065 : :
6066 : 1 : QgsLineString pd1;
6067 : 1 : pd1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 1 ) << QgsPoint( 0, 0 ) );
6068 : 1 : QgsPolygon pd;
6069 : : // no meaning, but let's not crash
6070 : 1 : ( void )pd.pointDistanceToBoundary( 0, 0 );
6071 : :
6072 : 1 : pd.setExteriorRing( pd1.clone() );
6073 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0, 0.5 ), 0.0, 0.0000000001 );
6074 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0.1, 0.5 ), 0.1, 0.0000000001 );
6075 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( -0.1, 0.5 ), -0.1, 0.0000000001 );
6076 : : // with a ring
6077 : 1 : QgsLineString pdRing1;
6078 : 1 : pdRing1.setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 ) << QgsPoint( 0.2, 0.1 ) << QgsPoint( 0.2, 0.6 ) << QgsPoint( 0.1, 0.6 ) << QgsPoint( 0.1, 0.1 ) );
6079 : 1 : pd.setInteriorRings( QVector< QgsCurve * >() << pdRing1.clone() );
6080 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0, 0.5 ), 0.0, 0.0000000001 );
6081 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0.1, 0.5 ), 0.0, 0.0000000001 );
6082 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0.01, 0.5 ), 0.01, 0.0000000001 );
6083 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0.08, 0.5 ), 0.02, 0.0000000001 );
6084 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( 0.12, 0.5 ), -0.02, 0.0000000001 );
6085 : 1 : QGSCOMPARENEAR( pd.pointDistanceToBoundary( -0.1, 0.5 ), -0.1, 0.0000000001 );
6086 : :
6087 : : // remove interior rings
6088 : 1 : QgsLineString removeRingsExt;
6089 : 1 : removeRingsExt.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
6090 : 1 : QgsPolygon removeRings1;
6091 : 1 : removeRings1.removeInteriorRings();
6092 : :
6093 : 1 : removeRings1.setExteriorRing( boundary1.clone() );
6094 : 1 : removeRings1.removeInteriorRings();
6095 : 1 : QCOMPARE( removeRings1.numInteriorRings(), 0 );
6096 : :
6097 : : // add interior rings
6098 : 1 : QgsLineString removeRingsRing1;
6099 : 1 : removeRingsRing1.setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 ) << QgsPoint( 0.2, 0.1 ) << QgsPoint( 0.2, 0.2 ) << QgsPoint( 0.1, 0.1 ) );
6100 : 1 : QgsLineString removeRingsRing2;
6101 : 1 : removeRingsRing2.setPoints( QgsPointSequence() << QgsPoint( 0.6, 0.8 ) << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.9, 0.9 ) << QgsPoint( 0.6, 0.8 ) );
6102 : 1 : removeRings1.setInteriorRings( QVector< QgsCurve * >() << removeRingsRing1.clone() << removeRingsRing2.clone() );
6103 : :
6104 : : // remove ring with size filter
6105 : 1 : removeRings1.removeInteriorRings( 0.0075 );
6106 : 1 : QCOMPARE( removeRings1.numInteriorRings(), 1 );
6107 : :
6108 : : // remove ring with no size filter
6109 : 1 : removeRings1.removeInteriorRings();
6110 : 1 : QCOMPARE( removeRings1.numInteriorRings(), 0 );
6111 : :
6112 : : // cast
6113 : 1 : QVERIFY( !QgsPolygon().cast( nullptr ) );
6114 : 1 : QgsPolygon pCast;
6115 : 1 : QVERIFY( QgsPolygon().cast( &pCast ) );
6116 : 1 : QgsPolygon pCast2;
6117 : 2 : pCast2.fromWkt( QStringLiteral( "PolygonZ((0 0 0, 0 1 1, 1 0 2, 0 0 0))" ) );
6118 : 1 : QVERIFY( QgsPolygon().cast( &pCast2 ) );
6119 : 2 : pCast2.fromWkt( QStringLiteral( "PolygonM((0 0 1, 0 1 2, 1 0 3, 0 0 1))" ) );
6120 : 1 : QVERIFY( QgsPolygon().cast( &pCast2 ) );
6121 : 2 : pCast2.fromWkt( QStringLiteral( "PolygonZM((0 0 0 1, 0 1 1 2, 1 0 2 3, 0 0 0 1))" ) );
6122 : 1 : QVERIFY( QgsPolygon().cast( &pCast2 ) );
6123 : :
6124 : : //transform
6125 : : //CRS transform
6126 : 2 : QgsCoordinateReferenceSystem sourceSrs( QStringLiteral( "EPSG:3994" ) );
6127 : 2 : QgsCoordinateReferenceSystem destSrs( QStringLiteral( "EPSG:4202" ) ); // want a transform with ellipsoid change
6128 : 1 : QgsCoordinateTransform tr( sourceSrs, destSrs, QgsProject::instance() );
6129 : :
6130 : : // 2d CRS transform
6131 : 1 : QgsPolygon pTransform;
6132 : 1 : QgsLineString l21;
6133 : 2 : l21.setPoints( QgsPointSequence() << QgsPoint( 6374985, -3626584 )
6134 : 1 : << QgsPoint( 6274985, -3526584 )
6135 : 1 : << QgsPoint( 6474985, -3526584 )
6136 : 1 : << QgsPoint( 6374985, -3626584 ) );
6137 : 1 : pTransform.setExteriorRing( l21.clone() );
6138 : 1 : pTransform.addInteriorRing( l21.clone() );
6139 : 1 : pTransform.transform( tr, QgsCoordinateTransform::ForwardTransform );
6140 : 1 : const QgsLineString *extR = static_cast< const QgsLineString * >( pTransform.exteriorRing() );
6141 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 175.771, 0.001 );
6142 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), -39.724, 0.001 );
6143 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 174.581448, 0.001 );
6144 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), -38.7999, 0.001 );
6145 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 176.958633, 0.001 );
6146 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), -38.7999, 0.001 );
6147 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 175.771, 0.001 );
6148 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), -39.724, 0.001 );
6149 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().xMinimum(), 174.581448, 0.001 );
6150 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().yMinimum(), -39.724, 0.001 );
6151 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().xMaximum(), 176.959, 0.001 );
6152 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().yMaximum(), -38.7999, 0.001 );
6153 : 1 : const QgsLineString *intR = static_cast< const QgsLineString * >( pTransform.interiorRing( 0 ) );
6154 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 175.771, 0.001 );
6155 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), -39.724, 0.001 );
6156 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 174.581448, 0.001 );
6157 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), -38.7999, 0.001 );
6158 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 176.958633, 0.001 );
6159 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), -38.7999, 0.001 );
6160 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 175.771, 0.001 );
6161 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), -39.724, 0.001 );
6162 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().xMinimum(), 174.581448, 0.001 );
6163 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().yMinimum(), -39.724, 0.001 );
6164 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().xMaximum(), 176.959, 0.001 );
6165 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().yMaximum(), -38.7999, 0.001 );
6166 : :
6167 : : //3d CRS transform
6168 : 1 : QgsLineString l22;
6169 : 2 : l22.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 )
6170 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6274985, -3526584, 3, 4 )
6171 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6474985, -3526584, 5, 6 )
6172 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 ) );
6173 : 1 : pTransform.clear();
6174 : 1 : pTransform.setExteriorRing( l22.clone() );
6175 : 1 : pTransform.addInteriorRing( l22.clone() );
6176 : 1 : pTransform.transform( tr, QgsCoordinateTransform::ForwardTransform );
6177 : 1 : extR = static_cast< const QgsLineString * >( pTransform.exteriorRing() );
6178 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 175.771, 0.001 );
6179 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), -39.724, 0.001 );
6180 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 1.0, 0.001 );
6181 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).m(), 2.0, 0.001 );
6182 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 174.581448, 0.001 );
6183 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), -38.7999, 0.001 );
6184 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 3.0, 0.001 );
6185 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).m(), 4.0, 0.001 );
6186 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 176.958633, 0.001 );
6187 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), -38.7999, 0.001 );
6188 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 5.0, 0.001 );
6189 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).m(), 6.0, 0.001 );
6190 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 175.771, 0.001 );
6191 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), -39.724, 0.001 );
6192 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 1.0, 0.001 );
6193 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).m(), 2.0, 0.001 );
6194 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().xMinimum(), 174.581448, 0.001 );
6195 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().yMinimum(), -39.724, 0.001 );
6196 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().xMaximum(), 176.959, 0.001 );
6197 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().yMaximum(), -38.7999, 0.001 );
6198 : 1 : intR = static_cast< const QgsLineString * >( pTransform.interiorRing( 0 ) );
6199 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 175.771, 0.001 );
6200 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), -39.724, 0.001 );
6201 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 1.0, 0.001 );
6202 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).m(), 2.0, 0.001 );
6203 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 174.581448, 0.001 );
6204 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), -38.7999, 0.001 );
6205 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 3.0, 0.001 );
6206 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).m(), 4.0, 0.001 );
6207 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 176.958633, 0.001 );
6208 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), -38.7999, 0.001 );
6209 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 5.0, 0.001 );
6210 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).m(), 6.0, 0.001 );
6211 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 175.771, 0.001 );
6212 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), -39.724, 0.001 );
6213 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 1.0, 0.001 );
6214 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).m(), 2.0, 0.001 );
6215 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().xMinimum(), 174.581448, 0.001 );
6216 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().yMinimum(), -39.724, 0.001 );
6217 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().xMaximum(), 176.959, 0.001 );
6218 : 1 : QGSCOMPARENEAR( pTransform.interiorRing( 0 )->boundingBox().yMaximum(), -38.7999, 0.001 );
6219 : :
6220 : : //reverse transform
6221 : 1 : pTransform.transform( tr, QgsCoordinateTransform::ReverseTransform );
6222 : 1 : extR = static_cast< const QgsLineString * >( pTransform.exteriorRing() );
6223 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 6374984, 100 );
6224 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), -3626584, 100 );
6225 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 1.0, 0.001 );
6226 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).m(), 2.0, 0.001 );
6227 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 6274984, 100 );
6228 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), -3526584, 100 );
6229 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 3.0, 0.001 );
6230 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).m(), 4.0, 0.001 );
6231 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 6474984, 100 );
6232 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), -3526584, 100 );
6233 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 5.0, 0.001 );
6234 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).m(), 6.0, 0.001 );
6235 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 6374984, 100 );
6236 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), -3626584, 100 );
6237 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 1.0, 0.001 );
6238 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).m(), 2.0, 0.001 );
6239 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().xMinimum(), 6274984, 100 );
6240 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().yMinimum(), -3626584, 100 );
6241 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().xMaximum(), 6474984, 100 );
6242 : 1 : QGSCOMPARENEAR( pTransform.exteriorRing()->boundingBox().yMaximum(), -3526584, 100 );
6243 : 1 : intR = static_cast< const QgsLineString * >( pTransform.interiorRing( 0 ) );
6244 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 6374984, 100 );
6245 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), -3626584, 100 );
6246 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 1.0, 0.001 );
6247 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).m(), 2.0, 0.001 );
6248 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 6274984, 100 );
6249 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), -3526584, 100 );
6250 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 3.0, 0.001 );
6251 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).m(), 4.0, 0.001 );
6252 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 6474984, 100 );
6253 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), -3526584, 100 );
6254 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 5.0, 0.001 );
6255 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).m(), 6.0, 0.001 );
6256 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 6374984, 100 );
6257 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), -3626584, 100 );
6258 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 1.0, 0.001 );
6259 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).m(), 2.0, 0.001 );
6260 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 6274984, 100 );
6261 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMinimum(), -3626584, 100 );
6262 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 6474984, 100 );
6263 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMaximum(), -3526584, 100 );
6264 : :
6265 : : #if PROJ_VERSION_MAJOR<6 // note - z value transform doesn't currently work with proj 6+, because we don't yet support compound CRS definitions
6266 : : //z value transform
6267 : : pTransform.transform( tr, QgsCoordinateTransform::ForwardTransform, true );
6268 : : extR = static_cast< const QgsLineString * >( pTransform.exteriorRing() );
6269 : : QGSCOMPARENEAR( extR->pointN( 0 ).z(), -19.249066, 0.001 );
6270 : : QGSCOMPARENEAR( extR->pointN( 1 ).z(), -19.148357, 0.001 );
6271 : : QGSCOMPARENEAR( extR->pointN( 2 ).z(), -19.092128, 0.001 );
6272 : : QGSCOMPARENEAR( extR->pointN( 3 ).z(), -19.249066, 0.001 );
6273 : : intR = static_cast< const QgsLineString * >( pTransform.interiorRing( 0 ) );
6274 : : QGSCOMPARENEAR( intR->pointN( 0 ).z(), -19.249066, 0.001 );
6275 : : QGSCOMPARENEAR( intR->pointN( 1 ).z(), -19.148357, 0.001 );
6276 : : QGSCOMPARENEAR( intR->pointN( 2 ).z(), -19.092128, 0.001 );
6277 : : QGSCOMPARENEAR( intR->pointN( 3 ).z(), -19.249066, 0.001 );
6278 : : pTransform.transform( tr, QgsCoordinateTransform::ReverseTransform, true );
6279 : : extR = static_cast< const QgsLineString * >( pTransform.exteriorRing() );
6280 : : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 1, 0.001 );
6281 : : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 3, 0.001 );
6282 : : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 5, 0.001 );
6283 : : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 1, 0.001 );
6284 : : intR = static_cast< const QgsLineString * >( pTransform.interiorRing( 0 ) );
6285 : : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 1, 0.001 );
6286 : : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 3, 0.001 );
6287 : : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 5, 0.001 );
6288 : : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 1, 0.001 );
6289 : : #endif
6290 : :
6291 : : //QTransform transform
6292 : 1 : QTransform qtr = QTransform::fromScale( 2, 3 );
6293 : 1 : QgsLineString l23;
6294 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
6295 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 )
6296 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 12, 23, 24 )
6297 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
6298 : 1 : QgsPolygon pTransform2;
6299 : 1 : pTransform2.setExteriorRing( l23.clone() );
6300 : 1 : pTransform2.addInteriorRing( l23.clone() );
6301 : 1 : pTransform2.transform( qtr, 2, 3, 4, 5 );
6302 : :
6303 : 1 : extR = static_cast< const QgsLineString * >( pTransform2.exteriorRing() );
6304 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 2, 100 );
6305 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), 6, 100 );
6306 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 11.0, 0.001 );
6307 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).m(), 24.0, 0.001 );
6308 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 22, 100 );
6309 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), 36, 100 );
6310 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 41.0, 0.001 );
6311 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).m(), 74.0, 0.001 );
6312 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 2, 100 );
6313 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), 36, 100 );
6314 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 71.0, 0.001 );
6315 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).m(), 124.0, 0.001 );
6316 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 2, 100 );
6317 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), 6, 100 );
6318 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 11.0, 0.001 );
6319 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).m(), 24.0, 0.001 );
6320 : 1 : QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().xMinimum(), 2, 0.001 );
6321 : 1 : QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().yMinimum(), 6, 0.001 );
6322 : 1 : QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().xMaximum(), 22, 0.001 );
6323 : 1 : QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().yMaximum(), 36, 0.001 );
6324 : 1 : intR = static_cast< const QgsLineString * >( pTransform2.interiorRing( 0 ) );
6325 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 2, 100 );
6326 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), 6, 100 );
6327 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 11.0, 0.001 );
6328 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).m(), 24.0, 0.001 );
6329 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 22, 100 );
6330 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), 36, 100 );
6331 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 41.0, 0.001 );
6332 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).m(), 74.0, 0.001 );
6333 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 2, 100 );
6334 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), 36, 100 );
6335 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 71.0, 0.001 );
6336 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).m(), 124.0, 0.001 );
6337 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 2, 100 );
6338 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), 6, 100 );
6339 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 11.0, 0.001 );
6340 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).m(), 24.0, 0.001 );
6341 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 2, 0.001 );
6342 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMinimum(), 6, 0.001 );
6343 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 22, 0.001 );
6344 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMaximum(), 36, 0.001 );
6345 : :
6346 : : // closestSegment
6347 : 1 : QgsPoint pt;
6348 : 1 : QgsVertexId v;
6349 : 1 : int leftOf = 0;
6350 : 1 : QgsPolygon empty;
6351 : 1 : ( void )empty.closestSegment( QgsPoint( 1, 2 ), pt, v ); // empty polygon, just want no crash
6352 : :
6353 : 1 : QgsPolygon p21;
6354 : 1 : QgsLineString p21ls;
6355 : 1 : p21ls.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 7, 12 ) << QgsPoint( 5, 15 ) << QgsPoint( 5, 10 ) );
6356 : 1 : p21.setExteriorRing( p21ls.clone() );
6357 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 4, 11 ), pt, v, &leftOf ), 1.0, 0.0001 );
6358 : 1 : QGSCOMPARENEAR( pt.x(), 5, 0.01 );
6359 : 1 : QGSCOMPARENEAR( pt.y(), 11, 0.01 );
6360 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
6361 : 1 : QCOMPARE( leftOf, 1 );
6362 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 8, 11 ), pt, v, &leftOf ), 2.0, 0.0001 );
6363 : 1 : QGSCOMPARENEAR( pt.x(), 7, 0.01 );
6364 : 1 : QGSCOMPARENEAR( pt.y(), 12, 0.01 );
6365 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
6366 : 1 : QCOMPARE( leftOf, 1 );
6367 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 6, 11.5 ), pt, v, &leftOf ), 0.125000, 0.0001 );
6368 : 1 : QGSCOMPARENEAR( pt.x(), 6.25, 0.01 );
6369 : 1 : QGSCOMPARENEAR( pt.y(), 11.25, 0.01 );
6370 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
6371 : 1 : QCOMPARE( leftOf, -1 );
6372 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 7, 16 ), pt, v, &leftOf ), 4.923077, 0.0001 );
6373 : 1 : QGSCOMPARENEAR( pt.x(), 5.153846, 0.01 );
6374 : 1 : QGSCOMPARENEAR( pt.y(), 14.769231, 0.01 );
6375 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
6376 : 1 : QCOMPARE( leftOf, 1 );
6377 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 5.5, 13.5 ), pt, v, &leftOf ), 0.173077, 0.0001 );
6378 : 1 : QGSCOMPARENEAR( pt.x(), 5.846154, 0.01 );
6379 : 1 : QGSCOMPARENEAR( pt.y(), 13.730769, 0.01 );
6380 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
6381 : 1 : QCOMPARE( leftOf, -1 );
6382 : : // point directly on segment
6383 : 1 : QCOMPARE( p21.closestSegment( QgsPoint( 5, 15 ), pt, v, &leftOf ), 0.0 );
6384 : 1 : QCOMPARE( pt, QgsPoint( 5, 15 ) );
6385 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
6386 : : // with interior ring
6387 : 1 : p21ls.setPoints( QgsPointSequence() << QgsPoint( 6, 11.5 ) << QgsPoint( 6.5, 12 ) << QgsPoint( 6, 13 ) << QgsPoint( 6, 11.5 ) );
6388 : 1 : p21.addInteriorRing( p21ls.clone() );
6389 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 4, 11 ), pt, v, &leftOf ), 1.0, 0.0001 );
6390 : 1 : QGSCOMPARENEAR( pt.x(), 5, 0.01 );
6391 : 1 : QGSCOMPARENEAR( pt.y(), 11, 0.01 );
6392 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
6393 : 1 : QCOMPARE( leftOf, 1 );
6394 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 8, 11 ), pt, v, &leftOf ), 2.0, 0.0001 );
6395 : 1 : QGSCOMPARENEAR( pt.x(), 7, 0.01 );
6396 : 1 : QGSCOMPARENEAR( pt.y(), 12, 0.01 );
6397 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
6398 : 1 : QCOMPARE( leftOf, 1 );
6399 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 6, 11.4 ), pt, v, &leftOf ), 0.01, 0.0001 );
6400 : 1 : QGSCOMPARENEAR( pt.x(), 6.0, 0.01 );
6401 : 1 : QGSCOMPARENEAR( pt.y(), 11.5, 0.01 );
6402 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 1 ) );
6403 : 1 : QCOMPARE( leftOf, 1 );
6404 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 7, 16 ), pt, v, &leftOf ), 4.923077, 0.0001 );
6405 : 1 : QGSCOMPARENEAR( pt.x(), 5.153846, 0.01 );
6406 : 1 : QGSCOMPARENEAR( pt.y(), 14.769231, 0.01 );
6407 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
6408 : 1 : QCOMPARE( leftOf, 1 );
6409 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 5.5, 13.5 ), pt, v, &leftOf ), 0.173077, 0.0001 );
6410 : 1 : QGSCOMPARENEAR( pt.x(), 5.846154, 0.01 );
6411 : 1 : QGSCOMPARENEAR( pt.y(), 13.730769, 0.01 );
6412 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
6413 : 1 : QCOMPARE( leftOf, -1 );
6414 : : // point directly on segment
6415 : 1 : QCOMPARE( p21.closestSegment( QgsPoint( 6, 13 ), pt, v, &leftOf ), 0.0 );
6416 : 1 : QCOMPARE( pt, QgsPoint( 6, 13 ) );
6417 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 2 ) );
6418 : 1 : QCOMPARE( leftOf, 0 );
6419 : :
6420 : : //nextVertex
6421 : 1 : QgsPolygon p22;
6422 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6423 : 1 : v = QgsVertexId( 0, 0, -2 );
6424 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6425 : 1 : v = QgsVertexId( 0, 0, 10 );
6426 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6427 : 1 : QgsLineString lp22;
6428 : 1 : lp22.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
6429 : 1 : p22.setExteriorRing( lp22.clone() );
6430 : 1 : v = QgsVertexId( 0, 0, 4 ); //out of range
6431 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6432 : 1 : v = QgsVertexId( 0, 0, -5 );
6433 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6434 : 1 : v = QgsVertexId( 0, 0, -1 );
6435 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6436 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
6437 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
6438 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6439 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
6440 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
6441 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6442 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
6443 : 1 : QCOMPARE( pt, QgsPoint( 1, 12 ) );
6444 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6445 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
6446 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
6447 : 1 : v = QgsVertexId( 0, 1, 0 );
6448 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6449 : 1 : v = QgsVertexId( 1, 0, 0 );
6450 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6451 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 1 ) ); //test that part number is maintained
6452 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
6453 : : // add interior ring
6454 : 1 : lp22.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 11, 22 ) << QgsPoint( 11, 12 ) );
6455 : 1 : p22.addInteriorRing( lp22.clone() );
6456 : 1 : v = QgsVertexId( 0, 1, 4 ); //out of range
6457 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6458 : 1 : v = QgsVertexId( 0, 1, -5 );
6459 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6460 : 1 : v = QgsVertexId( 0, 1, -1 );
6461 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6462 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 0 ) );
6463 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
6464 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6465 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 1 ) );
6466 : 1 : QCOMPARE( pt, QgsPoint( 21, 22 ) );
6467 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6468 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 2 ) );
6469 : 1 : QCOMPARE( pt, QgsPoint( 11, 22 ) );
6470 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6471 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 3 ) );
6472 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
6473 : 1 : v = QgsVertexId( 0, 2, 0 );
6474 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
6475 : 1 : v = QgsVertexId( 1, 1, 0 );
6476 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
6477 : 1 : QCOMPARE( v, QgsVertexId( 1, 1, 1 ) ); //test that part number is maintained
6478 : 1 : QCOMPARE( pt, QgsPoint( 21, 22 ) );
6479 : :
6480 : : // dropZValue
6481 : 1 : QgsPolygon p23;
6482 : 1 : p23.dropZValue();
6483 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6484 : 1 : QgsLineString lp23;
6485 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
6486 : 1 : p23.setExteriorRing( lp23.clone() );
6487 : 1 : p23.addInteriorRing( lp23.clone() );
6488 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6489 : 1 : p23.dropZValue(); // not z
6490 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6491 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
6492 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
6493 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
6494 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
6495 : : // with z
6496 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3 ) << QgsPoint( 11, 12, 13 ) << QgsPoint( 1, 12, 23 ) << QgsPoint( 1, 2, 3 ) );
6497 : 1 : p23.clear();
6498 : 1 : p23.setExteriorRing( lp23.clone() );
6499 : 1 : p23.addInteriorRing( lp23.clone() );
6500 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::PolygonZ );
6501 : 1 : p23.dropZValue();
6502 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6503 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
6504 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
6505 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
6506 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
6507 : : // with zm
6508 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
6509 : 1 : p23.clear();
6510 : 1 : p23.setExteriorRing( lp23.clone() );
6511 : 1 : p23.addInteriorRing( lp23.clone() );
6512 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::PolygonZM );
6513 : 1 : p23.dropZValue();
6514 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::PolygonM );
6515 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineStringM );
6516 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
6517 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineStringM );
6518 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
6519 : :
6520 : : // dropMValue
6521 : 1 : p23.clear();
6522 : 1 : p23.dropMValue();
6523 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6524 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
6525 : 1 : p23.setExteriorRing( lp23.clone() );
6526 : 1 : p23.addInteriorRing( lp23.clone() );
6527 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6528 : 1 : p23.dropMValue(); // not zm
6529 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6530 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
6531 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
6532 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
6533 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
6534 : : // with m
6535 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 13 ) << QgsPoint( QgsWkbTypes::PointM, 1, 12, 0, 23 ) << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) );
6536 : 1 : p23.clear();
6537 : 1 : p23.setExteriorRing( lp23.clone() );
6538 : 1 : p23.addInteriorRing( lp23.clone() );
6539 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::PolygonM );
6540 : 1 : p23.dropMValue();
6541 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::Polygon );
6542 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
6543 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
6544 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
6545 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
6546 : : // with zm
6547 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
6548 : 1 : p23.clear();
6549 : 1 : p23.setExteriorRing( lp23.clone() );
6550 : 1 : p23.addInteriorRing( lp23.clone() );
6551 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::PolygonZM );
6552 : 1 : p23.dropMValue();
6553 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::PolygonZ );
6554 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineStringZ );
6555 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
6556 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineStringZ );
6557 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
6558 : :
6559 : : //vertexAngle
6560 : 1 : QgsPolygon p24;
6561 : 1 : ( void )p24.vertexAngle( QgsVertexId() ); //just want no crash
6562 : 1 : ( void )p24.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash
6563 : 1 : ( void )p24.vertexAngle( QgsVertexId( 0, 1, 0 ) ); //just want no crash
6564 : 1 : QgsLineString l38;
6565 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
6566 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ) );
6567 : 1 : p24.setExteriorRing( l38.clone() );
6568 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 2.35619, 0.00001 );
6569 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 1.5708, 0.0001 );
6570 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 1.17809, 0.00001 );
6571 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 0.0, 0.00001 );
6572 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 5.10509, 0.00001 );
6573 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 5 ) ), 3.92699, 0.00001 );
6574 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 6 ) ), 2.35619, 0.00001 );
6575 : 1 : p24.addInteriorRing( l38.clone() );
6576 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 0 ) ), 2.35619, 0.00001 );
6577 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 1 ) ), 1.5708, 0.0001 );
6578 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 2 ) ), 1.17809, 0.00001 );
6579 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 3 ) ), 0.0, 0.00001 );
6580 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 4 ) ), 5.10509, 0.00001 );
6581 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 5 ) ), 3.92699, 0.00001 );
6582 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 1, 6 ) ), 2.35619, 0.00001 );
6583 : :
6584 : : //insert vertex
6585 : :
6586 : : //insert vertex in empty polygon
6587 : 1 : QgsPolygon p25;
6588 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6589 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 6.0, 7.0 ) ) );
6590 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6591 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6592 : 1 : QVERIFY( p25.isEmpty() );
6593 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
6594 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ) );
6595 : 1 : p25.setExteriorRing( l38.clone() );
6596 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 0.3, 0 ) ) );
6597 : 1 : QCOMPARE( p25.nCoordinates(), 8 );
6598 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 0 ), QgsPoint( 0, 0 ) );
6599 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 1 ), QgsPoint( 0.3, 0 ) );
6600 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 2 ), QgsPoint( 0.5, 0 ) );
6601 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 6.0, 7.0 ) ) );
6602 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 100 ), QgsPoint( 6.0, 7.0 ) ) );
6603 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6604 : : // first vertex
6605 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 0, 0.1 ) ) );
6606 : 1 : QCOMPARE( p25.nCoordinates(), 9 );
6607 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
6608 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 1 ), QgsPoint( 0, 0 ) );
6609 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
6610 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
6611 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 7 ), QgsPoint( 0, 2 ) );
6612 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
6613 : : // last vertex
6614 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 9 ), QgsPoint( 0.1, 0.1 ) ) );
6615 : 1 : QCOMPARE( p25.nCoordinates(), 10 );
6616 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 0 ), QgsPoint( 0.1, 0.1 ) );
6617 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 1 ), QgsPoint( 0, 0 ) );
6618 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
6619 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
6620 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
6621 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 9 ), QgsPoint( 0.1, 0.1 ) );
6622 : : // with interior ring
6623 : 1 : p25.addInteriorRing( l38.clone() );
6624 : 1 : QCOMPARE( p25.nCoordinates(), 17 );
6625 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 1, 1 ), QgsPoint( 0.3, 0 ) ) );
6626 : 1 : QCOMPARE( p25.nCoordinates(), 18 );
6627 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 0, 0 ) );
6628 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 0.3, 0 ) );
6629 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 0.5, 0 ) );
6630 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, -1 ), QgsPoint( 6.0, 7.0 ) ) );
6631 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 100 ), QgsPoint( 6.0, 7.0 ) ) );
6632 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 2, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6633 : : // first vertex in interior ring
6634 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 0, 0.1 ) ) );
6635 : 1 : QCOMPARE( p25.nCoordinates(), 19 );
6636 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
6637 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
6638 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
6639 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
6640 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 7 ), QgsPoint( 0, 2 ) );
6641 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
6642 : : // last vertex in interior ring
6643 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 1, 9 ), QgsPoint( 0.1, 0.1 ) ) );
6644 : 1 : QCOMPARE( p25.nCoordinates(), 20 );
6645 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 0.1, 0.1 ) );
6646 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
6647 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
6648 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
6649 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
6650 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 9 ), QgsPoint( 0.1, 0.1 ) );
6651 : :
6652 : : //move vertex
6653 : :
6654 : : //empty polygon
6655 : 1 : QgsPolygon p26;
6656 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6657 : 1 : QVERIFY( p26.isEmpty() );
6658 : :
6659 : : //valid polygon
6660 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
6661 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
6662 : 1 : p26.setExteriorRing( l38.clone() );
6663 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6664 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
6665 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
6666 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
6667 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
6668 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
6669 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 3 ), QgsPoint( 6.0, 7.0 ) );
6670 : :
6671 : : //out of range
6672 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
6673 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
6674 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 3.0, 4.0 ) ) );
6675 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
6676 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
6677 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
6678 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 3 ), QgsPoint( 6.0, 7.0 ) );
6679 : :
6680 : : // with interior ring
6681 : 1 : p26.addInteriorRing( l38.clone() );
6682 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
6683 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 1, 1 ), QgsPoint( 16.0, 17.0 ) ) );
6684 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 1, 2 ), QgsPoint( 26.0, 27.0 ) ) );
6685 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
6686 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
6687 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
6688 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 6.0, 7.0 ) );
6689 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 1, -1 ), QgsPoint( 3.0, 4.0 ) ) );
6690 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 1, 10 ), QgsPoint( 3.0, 4.0 ) ) );
6691 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 2, 0 ), QgsPoint( 3.0, 4.0 ) ) );
6692 : :
6693 : : //delete vertex
6694 : :
6695 : : //empty polygon
6696 : 1 : QgsPolygon p27;
6697 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
6698 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 0 ) ) );
6699 : 1 : QVERIFY( p27.isEmpty() );
6700 : :
6701 : : //valid polygon
6702 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 5, 2 ) << QgsPoint( 6, 2 ) << QgsPoint( 7, 2 )
6703 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
6704 : :
6705 : 1 : p27.setExteriorRing( l38.clone() );
6706 : : //out of range vertices
6707 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, -1 ) ) );
6708 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, 100 ) ) );
6709 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 1 ) ) );
6710 : :
6711 : : //valid vertices
6712 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
6713 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
6714 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 1 ), QgsPoint( 6.0, 2.0 ) );
6715 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 2 ), QgsPoint( 7.0, 2.0 ) );
6716 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
6717 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 5 ), QgsPoint( 1.0, 2.0 ) );
6718 : :
6719 : : // delete first vertex
6720 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
6721 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
6722 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
6723 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
6724 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
6725 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 4 ), QgsPoint( 6.0, 2.0 ) );
6726 : :
6727 : : // delete last vertex
6728 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 4 ) ) );
6729 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 0 ), QgsPoint( 21.0, 22.0 ) );
6730 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
6731 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
6732 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
6733 : :
6734 : : // delete another vertex - should remove ring
6735 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
6736 : 1 : QVERIFY( !p27.exteriorRing() );
6737 : :
6738 : : // with interior ring
6739 : 1 : p27.setExteriorRing( l38.clone() );
6740 : 1 : p27.addInteriorRing( l38.clone() );
6741 : :
6742 : : //out of range vertices
6743 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, -1 ) ) );
6744 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 100 ) ) );
6745 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 2, 1 ) ) );
6746 : :
6747 : : //valid vertices
6748 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 1 ) ) );
6749 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
6750 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 6.0, 2.0 ) );
6751 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 7.0, 2.0 ) );
6752 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
6753 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 5 ), QgsPoint( 1.0, 2.0 ) );
6754 : :
6755 : : // delete first vertex
6756 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 0 ) ) );
6757 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
6758 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
6759 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
6760 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
6761 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 4 ), QgsPoint( 6.0, 2.0 ) );
6762 : :
6763 : : // delete last vertex
6764 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 4 ) ) );
6765 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 21.0, 22.0 ) );
6766 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
6767 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
6768 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
6769 : :
6770 : : // delete another vertex - should remove ring
6771 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 1 ) ) );
6772 : 1 : QCOMPARE( p27.numInteriorRings(), 0 );
6773 : 1 : QVERIFY( p27.exteriorRing() );
6774 : :
6775 : : // test that interior ring is "promoted" when exterior is removed
6776 : 1 : p27.addInteriorRing( l38.clone() );
6777 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
6778 : 1 : QCOMPARE( p27.numInteriorRings(), 1 );
6779 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
6780 : 1 : QCOMPARE( p27.numInteriorRings(), 1 );
6781 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
6782 : 1 : QCOMPARE( p27.numInteriorRings(), 1 );
6783 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
6784 : 1 : QCOMPARE( p27.numInteriorRings(), 0 );
6785 : 1 : QVERIFY( p27.exteriorRing() );
6786 : :
6787 : : // test adjacent vertices - should wrap around!
6788 : 1 : QgsLineString *closedRing1 = new QgsLineString();
6789 : 1 : closedRing1->setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) );
6790 : 1 : QgsPolygon p28;
6791 : 1 : QgsVertexId previous( 1, 2, 3 );
6792 : 1 : QgsVertexId next( 4, 5, 6 );
6793 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 0 ), previous, next );
6794 : 1 : QCOMPARE( previous, QgsVertexId( ) );
6795 : 1 : QCOMPARE( next, QgsVertexId( ) );
6796 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 0 ), previous, next );
6797 : 1 : QCOMPARE( previous, QgsVertexId( ) );
6798 : 1 : QCOMPARE( next, QgsVertexId( ) );
6799 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 1 ), previous, next );
6800 : 1 : QCOMPARE( previous, QgsVertexId( ) );
6801 : 1 : QCOMPARE( next, QgsVertexId( ) );
6802 : :
6803 : 1 : p28.setExteriorRing( closedRing1 );
6804 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 0 ), previous, next );
6805 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
6806 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
6807 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 1 ), previous, next );
6808 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
6809 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
6810 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 2 ), previous, next );
6811 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
6812 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
6813 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 3 ), previous, next );
6814 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
6815 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
6816 : 1 : p28.adjacentVertices( QgsVertexId( 0, 0, 4 ), previous, next );
6817 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
6818 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
6819 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 0 ), previous, next );
6820 : 1 : QCOMPARE( previous, QgsVertexId( ) );
6821 : 1 : QCOMPARE( next, QgsVertexId( ) );
6822 : : // part number should be retained
6823 : 1 : p28.adjacentVertices( QgsVertexId( 1, 0, 0 ), previous, next );
6824 : 1 : QCOMPARE( previous, QgsVertexId( 1, 0, 3 ) );
6825 : 1 : QCOMPARE( next, QgsVertexId( 1, 0, 1 ) );
6826 : :
6827 : : // interior ring
6828 : 1 : p28.addInteriorRing( closedRing1->clone() );
6829 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 0 ), previous, next );
6830 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 3 ) );
6831 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 1 ) );
6832 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 1 ), previous, next );
6833 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 0 ) );
6834 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 2 ) );
6835 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 2 ), previous, next );
6836 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 1 ) );
6837 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 3 ) );
6838 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 3 ), previous, next );
6839 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 2 ) );
6840 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 4 ) );
6841 : 1 : p28.adjacentVertices( QgsVertexId( 0, 1, 4 ), previous, next );
6842 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 3 ) );
6843 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 1 ) );
6844 : 1 : p28.adjacentVertices( QgsVertexId( 0, 2, 0 ), previous, next );
6845 : 1 : QCOMPARE( previous, QgsVertexId( ) );
6846 : 1 : QCOMPARE( next, QgsVertexId( ) );
6847 : :
6848 : : // vertex number
6849 : 1 : QgsLineString vertexLine2;
6850 : 1 : QCOMPARE( vertexLine2.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
6851 : :
6852 : 1 : QgsLineString *closedRing2 = new QgsLineString();
6853 : 1 : closedRing2->setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) );
6854 : 1 : QgsPolygon p29;
6855 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
6856 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
6857 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, -1, 0 ) ), -1 );
6858 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), -1 );
6859 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, -1 ) ), -1 );
6860 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), -1 );
6861 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), -1 );
6862 : 1 : p29.setExteriorRing( closedRing2 );
6863 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
6864 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
6865 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, -1, 0 ) ), -1 );
6866 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), -1 );
6867 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, -1 ) ), -1 );
6868 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
6869 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), 1 );
6870 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 2 ) ), 2 );
6871 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 3 ) ), 3 );
6872 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 4 ) ), 4 );
6873 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 5 ) ), -1 );
6874 : 1 : p29.addInteriorRing( closedRing2->clone() );
6875 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
6876 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), 1 );
6877 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 2 ) ), 2 );
6878 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 3 ) ), 3 );
6879 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 4 ) ), 4 );
6880 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 0, 5 ) ), -1 );
6881 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), 5 );
6882 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 1 ) ), 6 );
6883 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 2 ) ), 7 );
6884 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 3 ) ), 8 );
6885 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 4 ) ), 9 );
6886 : 1 : QCOMPARE( p29.vertexNumberFromVertexId( QgsVertexId( 0, 1, 5 ) ), -1 );
6887 : :
6888 : :
6889 : : //segmentLength
6890 : 1 : QgsPolygon p30;
6891 : 1 : QgsLineString vertexLine3;
6892 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
6893 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 0 ) ), 0.0 );
6894 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 1, 0, 0 ) ), 0.0 );
6895 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, -1, 0 ) ), 0.0 );
6896 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 0 ) ), 0.0 );
6897 : 2 : vertexLine3.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 )
6898 : 1 : << QgsPoint( 111, 2 ) << QgsPoint( 11, 2 ) );
6899 : 1 : p30.setExteriorRing( vertexLine3.clone() );
6900 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId() ), 0.0 );
6901 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
6902 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 0 ) ), 10.0 );
6903 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 1 ) ), 100.0 );
6904 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 2 ) ), 10.0 );
6905 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 3 ) ), 100.0 );
6906 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 4 ) ), 0.0 );
6907 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
6908 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( -1, 0, 0 ) ), 10.0 );
6909 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, -1, 0 ) ), 0.0 );
6910 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 0 ) ), 0.0 );
6911 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 1 ) ), 0.0 );
6912 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 1, 0, 1 ) ), 100.0 );
6913 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 1, 1, 1 ) ), 0.0 );
6914 : :
6915 : : // add interior ring
6916 : 2 : vertexLine3.setPoints( QgsPointSequence() << QgsPoint( 30, 6 ) << QgsPoint( 34, 6 ) << QgsPoint( 34, 8 )
6917 : 1 : << QgsPoint( 30, 8 ) << QgsPoint( 30, 6 ) );
6918 : 1 : p30.addInteriorRing( vertexLine3.clone() );
6919 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId() ), 0.0 );
6920 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
6921 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 0 ) ), 10.0 );
6922 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 1 ) ), 100.0 );
6923 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 2 ) ), 10.0 );
6924 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 3 ) ), 100.0 );
6925 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 0, 4 ) ), 0.0 );
6926 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
6927 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( -1, 0, 0 ) ), 10.0 );
6928 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, -1, 0 ) ), 0.0 );
6929 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, -1 ) ), 0.0 );
6930 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 0 ) ), 4.0 );
6931 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 1 ) ), 2.0 );
6932 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 2 ) ), 4.0 );
6933 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 3 ) ), 2.0 );
6934 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 0, 1, 4 ) ), 0.0 );
6935 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 1, 0, 1 ) ), 100.0 );
6936 : 1 : QCOMPARE( p30.segmentLength( QgsVertexId( 1, 1, 1 ) ), 2.0 );
6937 : :
6938 : : //removeDuplicateNodes
6939 : 1 : QgsPolygon nodePolygon;
6940 : 1 : QgsLineString nodeLine;
6941 : 1 : QVERIFY( !nodePolygon.removeDuplicateNodes() );
6942 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 11, 22 ) << QgsPoint( 11, 2 ) );
6943 : 1 : nodePolygon.setExteriorRing( nodeLine.clone() );
6944 : 1 : QVERIFY( !nodePolygon.removeDuplicateNodes() );
6945 : 2 : QCOMPARE( nodePolygon.asWkt(), QStringLiteral( "Polygon ((11 2, 11 12, 11 22, 11 2))" ) );
6946 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
6947 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 11, 22 ) << QgsPoint( 11.01, 21.99 ) << QgsPoint( 10.99, 1.99 ) << QgsPoint( 11, 2 ) );
6948 : 1 : nodePolygon.setExteriorRing( nodeLine.clone() );
6949 : 1 : QVERIFY( nodePolygon.removeDuplicateNodes( 0.02 ) );
6950 : 1 : QVERIFY( !nodePolygon.removeDuplicateNodes( 0.02 ) );
6951 : 2 : QCOMPARE( nodePolygon.asWkt( 2 ), QStringLiteral( "Polygon ((11 2, 11 12, 11 22, 11 2))" ) );
6952 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
6953 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 11, 22 ) << QgsPoint( 11.01, 21.99 ) << QgsPoint( 10.99, 1.99 ) << QgsPoint( 11, 2 ) );
6954 : 1 : nodePolygon.setExteriorRing( nodeLine.clone() );
6955 : 1 : QVERIFY( !nodePolygon.removeDuplicateNodes() );
6956 : 2 : QCOMPARE( nodePolygon.asWkt( 2 ), QStringLiteral( "Polygon ((11 2, 11.01 1.99, 11.02 2.01, 11 12, 11 22, 11.01 21.99, 10.99 1.99, 11 2))" ) );
6957 : : // don't create degenerate rings
6958 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 2.01 ) << QgsPoint( 11, 2.01 ) << QgsPoint( 11, 2 ) );
6959 : 1 : nodePolygon.addInteriorRing( nodeLine.clone() );
6960 : 1 : QVERIFY( nodePolygon.removeDuplicateNodes( 0.02 ) );
6961 : 2 : QCOMPARE( nodePolygon.asWkt( 2 ), QStringLiteral( "Polygon ((11 2, 11 12, 11 22, 11 2),(11 2, 11.01 2.01, 11 2.01, 11 2))" ) );
6962 : :
6963 : : // swap XY
6964 : 1 : QgsPolygon swapPolygon;
6965 : 1 : swapPolygon.swapXy(); //no crash
6966 : 1 : QgsLineString swapLine;
6967 : 1 : swapLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 22, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) );
6968 : 1 : swapPolygon.setExteriorRing( swapLine.clone() );
6969 : 1 : swapPolygon.swapXy();
6970 : 2 : QCOMPARE( swapPolygon.asWkt(), QStringLiteral( "PolygonZM ((2 11 3 4, 12 11 13 14, 22 11 23 24, 2 11 3 4))" ) );
6971 : 1 : swapLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) );
6972 : 1 : swapPolygon.addInteriorRing( swapLine.clone() );
6973 : 1 : swapPolygon.swapXy();
6974 : 2 : QCOMPARE( swapPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((11 2 3 4, 11 12 13 14, 11 22 23 24, 11 2 3 4),(2 1 5 6, 2.01 11.01 15 16, 2.01 11 25 26, 2 11 5 6, 2 1 5 6))" ) );
6975 : :
6976 : : // filter vertex
6977 : 1 : QgsPolygon filterPolygon;
6978 : 19 : auto filter = []( const QgsPoint & point )-> bool
6979 : : {
6980 : 19 : return point.x() > 5;
6981 : : };
6982 : 1 : filterPolygon.filterVertices( filter ); // no crash
6983 : 1 : QgsLineString filterPolygonRing;
6984 : 1 : filterPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 22, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) );
6985 : 1 : filterPolygon.setExteriorRing( filterPolygonRing.clone() );
6986 : 1 : filterPolygon.filterVertices( filter );
6987 : 2 : QCOMPARE( filterPolygon.asWkt(), QStringLiteral( "PolygonZM ((11 2 3 4, 11 12 13 14, 11 22 23 24, 11 2 3 4))" ) );
6988 : 1 : filterPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) );
6989 : 1 : filterPolygon.addInteriorRing( filterPolygonRing.clone() );
6990 : 1 : filterPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) );
6991 : 1 : filterPolygon.addInteriorRing( filterPolygonRing.clone() );
6992 : 1 : filterPolygon.filterVertices( filter );
6993 : 2 : QCOMPARE( filterPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((11 2 3 4, 11 12 13 14, 11 22 23 24, 11 2 3 4),(10 2 5 6, 11.01 2.01 15 16, 11 2.01 25 26, 11 2 5 6, 10 2 5 6),(11.01 2.01 15 16, 11 2.01 25 26))" ) );
6994 : :
6995 : : // transform vertex
6996 : 1 : QgsPolygon transformPolygon;
6997 : 20 : auto transform = []( const QgsPoint & point )-> QgsPoint
6998 : : {
6999 : 20 : return QgsPoint( point.x() + 2, point.y() + 3, point.z() + 4, point.m() + 5 );
7000 : : };
7001 : 1 : transformPolygon.transformVertices( transform ); // no crash
7002 : 1 : QgsLineString transformPolygonRing;
7003 : 1 : transformPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 22, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) );
7004 : 1 : transformPolygon.setExteriorRing( transformPolygonRing.clone() );
7005 : 1 : transformPolygon.transformVertices( transform );
7006 : 2 : QCOMPARE( transformPolygon.asWkt(), QStringLiteral( "PolygonZM ((13 5 7 9, 6 15 17 19, 13 15 17 19, 13 25 27 29, 13 5 7 9))" ) );
7007 : 1 : transformPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) );
7008 : 1 : transformPolygon.addInteriorRing( transformPolygonRing.clone() );
7009 : 1 : transformPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) );
7010 : 1 : transformPolygon.addInteriorRing( transformPolygonRing.clone() );
7011 : 1 : transformPolygon.transformVertices( transform );
7012 : 2 : QCOMPARE( transformPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((15 8 11 14, 8 18 21 24, 15 18 21 24, 15 28 31 34, 15 8 11 14),(12 5 9 11, 6 15 17 19, 13.01 5.01 19 21, 13 5.01 29 31, 13 5 9 11, 12 5 9 11),(3 5 9 11, 13.01 5.01 19 21, 13 5.01 29 31, 3 5 9 11))" ) );
7013 : :
7014 : : // transform using class
7015 : 1 : QgsPolygon transformPolygon2;
7016 : 1 : TestTransformer transformer;
7017 : : // no crash
7018 : 1 : QVERIFY( transformPolygon2.transform( &transformer ) );
7019 : 1 : transformPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 22, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) );
7020 : 1 : transformPolygon2.setExteriorRing( transformPolygonRing.clone() );
7021 : 1 : QVERIFY( transformPolygon2.transform( &transformer ) );
7022 : 2 : QCOMPARE( transformPolygon2.asWkt( 2 ), QStringLiteral( "PolygonZM ((33 16 8 3, 12 26 18 13, 33 26 18 13, 33 36 28 23, 33 16 8 3))" ) );
7023 : 1 : transformPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) );
7024 : 1 : transformPolygon2.addInteriorRing( transformPolygonRing.clone() );
7025 : 1 : transformPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) );
7026 : 1 : transformPolygon2.addInteriorRing( transformPolygonRing.clone() );
7027 : 1 : QVERIFY( transformPolygon2.transform( &transformer ) );
7028 : 2 : QCOMPARE( transformPolygon2.asWkt( 2 ), QStringLiteral( "PolygonZM ((99 30 13 2, 36 40 23 12, 99 40 23 12, 99 50 33 22, 99 30 13 2),(30 16 10 5, 12 26 18 13, 33.03 16.01 20 15, 33 16.01 30 25, 33 16 10 5, 30 16 10 5),(3 16 10 5, 33.03 16.01 20 15, 33 16.01 30 25, 3 16 10 5))" ) );
7029 : :
7030 : 1 : TestFailTransformer failTransformer;
7031 : 1 : QVERIFY( !transformPolygon2.transform( &failTransformer ) );
7032 : :
7033 : : // remove invalid rings
7034 : 1 : QgsPolygon invalidRingPolygon;
7035 : 1 : invalidRingPolygon.removeInvalidRings(); // no crash
7036 : 1 : QgsLineString removeInvalidPolygonRing;
7037 : 1 : removeInvalidPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 4, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 11, 22, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) );
7038 : 1 : invalidRingPolygon.setExteriorRing( removeInvalidPolygonRing.clone() );
7039 : 1 : invalidRingPolygon.removeInvalidRings();
7040 : 2 : QCOMPARE( invalidRingPolygon.asWkt(), QStringLiteral( "PolygonZM ((11 2 3 4, 4 12 13 14, 11 12 13 14, 11 22 23 24, 11 2 3 4))" ) );
7041 : 1 : removeInvalidPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 10, 2, 5, 6, QgsWkbTypes::PointZM ) );
7042 : 1 : invalidRingPolygon.addInteriorRing( removeInvalidPolygonRing.clone() );
7043 : 1 : removeInvalidPolygonRing.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 2.01, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2.01, 25, 26, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 5, 6, QgsWkbTypes::PointZM ) );
7044 : 1 : invalidRingPolygon.addInteriorRing( removeInvalidPolygonRing.clone() );
7045 : 1 : invalidRingPolygon.removeInvalidRings();
7046 : 2 : QCOMPARE( invalidRingPolygon.asWkt( 2 ), QStringLiteral( "PolygonZM ((11 2 3 4, 4 12 13 14, 11 12 13 14, 11 22 23 24, 11 2 3 4),(1 2 5 6, 11.01 2.01 15 16, 11 2.01 25 26, 1 2 5 6))" ) );
7047 : :
7048 : : // force RHR
7049 : 1 : QgsPolygon rhr;
7050 : 1 : rhr.forceRHR(); // no crash
7051 : 2 : rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4))" ) );
7052 : 1 : rhr.forceRHR();
7053 : 2 : QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4))" ) );
7054 : 2 : rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 100 0 13 14, 100 100 23 24, 0 100 23 24, 0 0 3 4))" ) );
7055 : 1 : rhr.forceRHR();
7056 : 2 : QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 23 24, 100 100 23 24, 100 0 13 14, 0 0 3 4))" ) );
7057 : 2 : rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 20 10 3 4, 20 20 4, 5, 10 20 6 8, 10 10 1 2))" ) );
7058 : 1 : rhr.forceRHR();
7059 : 2 : QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 20 10 3 4, 10 20 6 8, 10 10 1 2))" ) );
7060 : 2 : rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 100 0 13 14, 100 100 13 14, 0 100 23 24, 0 0 3 4),(10 10 1 2, 20 10 3 4, 20 20 4, 5, 10 20 6 8, 10 10 1 2))" ) );
7061 : 1 : rhr.forceRHR();
7062 : 2 : QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 23 24, 100 100 13 14, 100 0 13 14, 0 0 3 4),(10 10 1 2, 20 10 3 4, 10 20 6 8, 10 10 1 2))" ) );
7063 : 2 : rhr.fromWkt( QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 10 20 3 4, 20 10 6 8, 10 10 1 2))" ) );
7064 : 1 : rhr.forceRHR();
7065 : 2 : QCOMPARE( rhr.asWkt( 2 ), QStringLiteral( "PolygonZM ((0 0 3 4, 0 100 13 14, 100 100 13 14, 100 0 23 24, 0 0 3 4),(10 10 1 2, 20 10 6 8, 10 20 3 4, 10 10 1 2))" ) );
7066 : :
7067 : : // test bounding box intersects
7068 : 1 : QgsPolygon bb;
7069 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7070 : 1 : QgsLineString bbR;
7071 : 1 : bbR.setPoints( QgsPointSequence() << QgsPoint( 0, 2 ) << QgsPoint( 4, 2 ) << QgsPoint( 4, 4 ) << QgsPoint( 0, 2 ) );
7072 : 1 : bb.setExteriorRing( bbR.clone() );
7073 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7074 : : // double test because of cache
7075 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7076 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 11, 3, 6, 9 ) ) );
7077 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 11, 3, 6, 9 ) ) );
7078 : 1 : QCOMPARE( bb.boundingBox(), QgsRectangle( 0, 2, 4, 4 ) );
7079 : : // clear cache
7080 : 1 : bbR.setPoints( QgsPointSequence() << QgsPoint( 10, 2 ) << QgsPoint( 14, 2 ) << QgsPoint( 15, 4 ) << QgsPoint( 10, 2 ) );
7081 : 1 : bb.setExteriorRing( bbR.clone() );
7082 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7083 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7084 : 1 : QCOMPARE( bb.boundingBox(), QgsRectangle( 10, 2, 15, 4 ) );
7085 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 11, 3, 16, 9 ) ) );
7086 : : // technically invalid -- the interior ring is outside the exterior, but we want boundingBoxIntersects to be tolerant to
7087 : : // cases like this!
7088 : 1 : bbR.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 4, 2 ) << QgsPoint( 5, 4 ) << QgsPoint( 1, 2 ) );
7089 : 1 : bb.addInteriorRing( bbR.clone() );
7090 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7091 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 1, 3, 6, 9 ) ) );
7092 : 1 : QVERIFY( bb.boundingBoxIntersects( QgsRectangle( 11, 3, 16, 9 ) ) );
7093 : 1 : QVERIFY( !bb.boundingBoxIntersects( QgsRectangle( 21, 3, 26, 9 ) ) );
7094 : 1 : QCOMPARE( bb.boundingBox(), QgsRectangle( 10, 2, 15, 4 ) );
7095 : 1 : }
7096 : :
7097 : 1 : void TestQgsGeometry::triangle()
7098 : : {
7099 : : //test constructor
7100 : 1 : QgsTriangle t1;
7101 : 1 : QVERIFY( t1.isEmpty() );
7102 : 1 : QCOMPARE( t1.numInteriorRings(), 0 );
7103 : 1 : QCOMPARE( t1.nCoordinates(), 0 );
7104 : 1 : QCOMPARE( t1.ringCount(), 0 );
7105 : 1 : QCOMPARE( t1.partCount(), 0 );
7106 : 1 : QVERIFY( !t1.is3D() );
7107 : 1 : QVERIFY( !t1.isMeasure() );
7108 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::Triangle );
7109 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "Triangle" ) );
7110 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7111 : 1 : QCOMPARE( t1.dimension(), 2 );
7112 : 1 : QVERIFY( !t1.hasCurvedSegments() );
7113 : 1 : QCOMPARE( t1.area(), 0.0 );
7114 : 1 : QCOMPARE( t1.perimeter(), 0.0 );
7115 : 1 : QVERIFY( !t1.exteriorRing() );
7116 : 1 : QVERIFY( !t1.interiorRing( 0 ) );
7117 : :
7118 : : // degenerate triangles
7119 : 1 : QgsTriangle invalid( QgsPointXY( 0, 0 ), QgsPointXY( 0, 0 ), QgsPointXY( 10, 10 ) );
7120 : 1 : QVERIFY( !invalid.isEmpty() );
7121 : 1 : invalid = QgsTriangle( QPointF( 0, 0 ), QPointF( 0, 0 ), QPointF( 10, 10 ) );
7122 : 1 : QVERIFY( !invalid.isEmpty() );
7123 : : //set exterior ring
7124 : :
7125 : : //try with no ring
7126 : 1 : std::unique_ptr< QgsLineString > ext;
7127 : 1 : t1.setExteriorRing( nullptr );
7128 : 1 : QVERIFY( t1.isEmpty() );
7129 : 1 : QCOMPARE( t1.numInteriorRings(), 0 );
7130 : 1 : QCOMPARE( t1.nCoordinates(), 0 );
7131 : 1 : QCOMPARE( t1.ringCount(), 0 );
7132 : 1 : QCOMPARE( t1.partCount(), 0 );
7133 : 1 : QVERIFY( !t1.exteriorRing() );
7134 : 1 : QVERIFY( !t1.interiorRing( 0 ) );
7135 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::Triangle );
7136 : :
7137 : : //valid exterior ring
7138 : 1 : ext.reset( new QgsLineString() );
7139 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
7140 : 1 : << QgsPoint( 0, 0 ) );
7141 : 1 : QVERIFY( ext->isClosed() );
7142 : 1 : t1.setExteriorRing( ext->clone() );
7143 : 1 : QVERIFY( !t1.isEmpty() );
7144 : 1 : QCOMPARE( t1.numInteriorRings(), 0 );
7145 : 1 : QCOMPARE( t1.nCoordinates(), 4 );
7146 : 1 : QCOMPARE( t1.ringCount(), 1 );
7147 : 1 : QCOMPARE( t1.partCount(), 1 );
7148 : 1 : QVERIFY( !t1.is3D() );
7149 : 1 : QVERIFY( !t1.isMeasure() );
7150 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::Triangle );
7151 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "Triangle" ) );
7152 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7153 : 1 : QCOMPARE( t1.dimension(), 2 );
7154 : 1 : QVERIFY( !t1.hasCurvedSegments() );
7155 : 1 : QCOMPARE( t1.area(), 50.0 );
7156 : 1 : QGSCOMPARENEAR( t1.perimeter(), 34.1421, 0.001 );
7157 : 1 : QVERIFY( t1.exteriorRing() );
7158 : 1 : QVERIFY( !t1.interiorRing( 0 ) );
7159 : :
7160 : : //retrieve exterior ring and check
7161 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( t1.exteriorRing() ) ), *ext );
7162 : :
7163 : : //set new ExteriorRing
7164 : 1 : ext.reset( new QgsLineString() );
7165 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 10 ) << QgsPoint( 5, 5 ) << QgsPoint( 10, 10 )
7166 : 1 : << QgsPoint( 0, 10 ) );
7167 : 1 : QVERIFY( ext->isClosed() );
7168 : 1 : t1.setExteriorRing( ext->clone() );
7169 : 1 : QVERIFY( !t1.isEmpty() );
7170 : 1 : QCOMPARE( t1.numInteriorRings(), 0 );
7171 : 1 : QCOMPARE( t1.nCoordinates(), 4 );
7172 : 1 : QCOMPARE( t1.ringCount(), 1 );
7173 : 1 : QCOMPARE( t1.partCount(), 1 );
7174 : 1 : QVERIFY( !t1.is3D() );
7175 : 1 : QVERIFY( !t1.isMeasure() );
7176 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::Triangle );
7177 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "Triangle" ) );
7178 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7179 : 1 : QCOMPARE( t1.dimension(), 2 );
7180 : 1 : QVERIFY( !t1.hasCurvedSegments() );
7181 : 1 : QCOMPARE( t1.area(), 25.0 );
7182 : 1 : QGSCOMPARENEAR( t1.perimeter(), 24.1421, 0.001 );
7183 : 1 : QVERIFY( t1.exteriorRing() );
7184 : 1 : QVERIFY( !t1.interiorRing( 0 ) );
7185 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( t1.exteriorRing() ) ), *ext );
7186 : :
7187 : : // AddZ
7188 : 1 : QgsLineString lz;
7189 : 1 : lz.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3 ) << QgsPoint( 11, 12, 13 ) << QgsPoint( 1, 12, 23 ) << QgsPoint( 1, 2, 3 ) );
7190 : 1 : t1.setExteriorRing( lz.clone() );
7191 : 1 : QVERIFY( t1.is3D() );
7192 : 1 : QVERIFY( !t1.isMeasure() );
7193 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::TriangleZ );
7194 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "TriangleZ" ) );
7195 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7196 : 1 : QCOMPARE( t1.dimension(), 2 );
7197 : 1 : QCOMPARE( t1.vertexAt( 0 ).z(), 3.0 );
7198 : 1 : QCOMPARE( t1.vertexAt( 1 ).z(), 13.0 );
7199 : 1 : QCOMPARE( t1.vertexAt( 2 ).z(), 23.0 );
7200 : : // AddM
7201 : 1 : QgsLineString lzm;
7202 : 1 : lzm.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
7203 : 1 : t1.setExteriorRing( lzm.clone() );
7204 : 1 : QVERIFY( t1.is3D() );
7205 : 1 : QVERIFY( t1.isMeasure() );
7206 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::TriangleZM );
7207 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "TriangleZM" ) );
7208 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7209 : 1 : QCOMPARE( t1.dimension(), 2 );
7210 : 1 : QCOMPARE( t1.vertexAt( 0 ).m(), 4.0 );
7211 : 1 : QCOMPARE( t1.vertexAt( 1 ).m(), 14.0 );
7212 : 1 : QCOMPARE( t1.vertexAt( 2 ).m(), 24.0 );
7213 : : // dropZ
7214 : 1 : t1.dropZValue();
7215 : 1 : QVERIFY( !t1.is3D() );
7216 : 1 : QVERIFY( t1.isMeasure() );
7217 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::TriangleM );
7218 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "TriangleM" ) );
7219 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7220 : 1 : QCOMPARE( t1.dimension(), 2 );
7221 : 1 : QVERIFY( std::isnan( t1.vertexAt( 0 ).z() ) );
7222 : 1 : QVERIFY( std::isnan( t1.vertexAt( 1 ).z() ) );
7223 : 1 : QVERIFY( std::isnan( t1.vertexAt( 2 ).z() ) );
7224 : : // dropM
7225 : 1 : t1.dropMValue();
7226 : 1 : QVERIFY( !t1.is3D() );
7227 : 1 : QVERIFY( !t1.isMeasure() );
7228 : 1 : QCOMPARE( t1.wkbType(), QgsWkbTypes::Triangle );
7229 : 1 : QCOMPARE( t1.wktTypeStr(), QString( "Triangle" ) );
7230 : 1 : QCOMPARE( t1.geometryType(), QString( "Triangle" ) );
7231 : 1 : QCOMPARE( t1.dimension(), 2 );
7232 : 1 : QVERIFY( std::isnan( t1.vertexAt( 0 ).m() ) );
7233 : 1 : QVERIFY( std::isnan( t1.vertexAt( 1 ).m() ) );
7234 : 1 : QVERIFY( std::isnan( t1.vertexAt( 2 ).m() ) );
7235 : :
7236 : : //test that a non closed exterior ring will be automatically closed
7237 : 1 : QgsTriangle t2;
7238 : 1 : ext.reset( new QgsLineString() );
7239 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 ) );
7240 : 1 : QVERIFY( !ext->isClosed() );
7241 : 1 : t2.setExteriorRing( ext.release() );
7242 : 1 : QVERIFY( !t2.isEmpty() );
7243 : 1 : QVERIFY( t2.exteriorRing()->isClosed() );
7244 : 1 : QCOMPARE( t2.nCoordinates(), 4 );
7245 : :
7246 : : // invalid number of points
7247 : 1 : ext.reset( new QgsLineString() );
7248 : 1 : t2.clear();
7249 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) );
7250 : 1 : t2.setExteriorRing( ext.release() );
7251 : 1 : QVERIFY( t2.isEmpty() );
7252 : :
7253 : 1 : ext.reset( new QgsLineString() );
7254 : 1 : t2.clear();
7255 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 ) << QgsPoint( 5, 10 ) << QgsPoint( 8, 10 ) );
7256 : 1 : t2.setExteriorRing( ext.release() );
7257 : 1 : QVERIFY( t2.isEmpty() );
7258 : :
7259 : : // invalid exterior ring
7260 : 1 : ext.reset( new QgsLineString() );
7261 : 1 : t2.clear();
7262 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 ) << QgsPoint( 5, 10 ) );
7263 : 1 : t2.setExteriorRing( ext.release() );
7264 : 1 : QVERIFY( t2.isEmpty() );
7265 : :
7266 : 1 : ext.reset( new QgsLineString() );
7267 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 0, 0 ) );
7268 : 1 : t2.setExteriorRing( ext.release() );
7269 : 1 : QVERIFY( t2.isEmpty() );
7270 : :
7271 : : // degenerate case
7272 : 1 : ext.reset( new QgsLineString() );
7273 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 0, 0 ) );
7274 : 1 : t2.setExteriorRing( ext.release() );
7275 : 1 : QVERIFY( !t2.isEmpty() );
7276 : :
7277 : : // circular ring
7278 : 1 : QgsCircularString *circularRing = new QgsCircularString();
7279 : 1 : t2.clear();
7280 : 1 : circularRing->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 ) );
7281 : 1 : QVERIFY( circularRing->hasCurvedSegments() );
7282 : 1 : t2.setExteriorRing( circularRing );
7283 : 1 : QVERIFY( t2.isEmpty() );
7284 : :
7285 : : //constructor with 3 points
7286 : : // double points
7287 : 1 : QgsTriangle t3( QgsPoint( 0, 0 ), QgsPoint( 0, 0 ), QgsPoint( 10, 10 ) );
7288 : 1 : QVERIFY( !t3.isEmpty() );
7289 : 1 : QCOMPARE( t3.numInteriorRings(), 0 );
7290 : 1 : QCOMPARE( t3.nCoordinates(), 4 );
7291 : 1 : QCOMPARE( t3.ringCount(), 1 );
7292 : 1 : QCOMPARE( t3.partCount(), 1 );
7293 : 1 : QVERIFY( !t3.is3D() );
7294 : 1 : QVERIFY( !t3.isMeasure() );
7295 : 1 : QCOMPARE( t3.wkbType(), QgsWkbTypes::Triangle );
7296 : 1 : QCOMPARE( t3.wktTypeStr(), QString( "Triangle" ) );
7297 : 1 : QCOMPARE( t3.geometryType(), QString( "Triangle" ) );
7298 : 1 : QCOMPARE( t3.dimension(), 2 );
7299 : 1 : QVERIFY( !t3.hasCurvedSegments() );
7300 : 1 : QCOMPARE( t3.area(), 0.0 );
7301 : 1 : QGSCOMPARENEAR( t3.perimeter(), 28.284271, 0.001 );
7302 : 1 : QVERIFY( t3.exteriorRing() );
7303 : 1 : QVERIFY( !t3.interiorRing( 0 ) );
7304 : :
7305 : : // colinear
7306 : 1 : t3 = QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 10 ) );
7307 : 1 : QVERIFY( !t3.isEmpty() );
7308 : 1 : QCOMPARE( t3.numInteriorRings(), 0 );
7309 : 1 : QCOMPARE( t3.nCoordinates(), 4 );
7310 : 1 : QCOMPARE( t3.ringCount(), 1 );
7311 : 1 : QCOMPARE( t3.partCount(), 1 );
7312 : 1 : QVERIFY( !t3.is3D() );
7313 : 1 : QVERIFY( !t3.isMeasure() );
7314 : 1 : QCOMPARE( t3.wkbType(), QgsWkbTypes::Triangle );
7315 : 1 : QCOMPARE( t3.wktTypeStr(), QString( "Triangle" ) );
7316 : 1 : QCOMPARE( t3.geometryType(), QString( "Triangle" ) );
7317 : 1 : QCOMPARE( t3.dimension(), 2 );
7318 : 1 : QVERIFY( !t3.hasCurvedSegments() );
7319 : 1 : QCOMPARE( t3.area(), 0.0 );
7320 : 1 : QGSCOMPARENEAR( t3.perimeter(), 10.0 * 2, 0.001 );
7321 : 1 : QVERIFY( t3.exteriorRing() );
7322 : 1 : QVERIFY( !t3.interiorRing( 0 ) );
7323 : :
7324 : 1 : t3 = QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 0, 10 ), QgsPoint( 10, 10 ) );
7325 : 1 : QVERIFY( !t3.isEmpty() );
7326 : 1 : QCOMPARE( t3.numInteriorRings(), 0 );
7327 : 1 : QCOMPARE( t3.nCoordinates(), 4 );
7328 : 1 : QCOMPARE( t3.ringCount(), 1 );
7329 : 1 : QCOMPARE( t3.partCount(), 1 );
7330 : 1 : QVERIFY( !t3.is3D() );
7331 : 1 : QVERIFY( !t3.isMeasure() );
7332 : 1 : QCOMPARE( t3.wkbType(), QgsWkbTypes::Triangle );
7333 : 1 : QCOMPARE( t3.wktTypeStr(), QString( "Triangle" ) );
7334 : 1 : QCOMPARE( t3.geometryType(), QString( "Triangle" ) );
7335 : 1 : QCOMPARE( t3.dimension(), 2 );
7336 : 1 : QVERIFY( !t3.hasCurvedSegments() );
7337 : 1 : QCOMPARE( t3.area(), 50.0 );
7338 : 1 : QGSCOMPARENEAR( t3.perimeter(), 34.1421, 0.001 );
7339 : 1 : QVERIFY( t3.exteriorRing() );
7340 : 1 : QVERIFY( !t3.interiorRing( 0 ) );
7341 : :
7342 : : // equality
7343 : 1 : QVERIFY( QgsTriangle() == QgsTriangle() ); // empty
7344 : 1 : QVERIFY( QgsTriangle() != QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 10 ) ) ); // empty
7345 : 1 : QVERIFY( QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 10 ) ) != QgsTriangle() ); // empty
7346 : 1 : QVERIFY( QgsTriangle() != QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 0, 10 ) ) );
7347 : 1 : QVERIFY( QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 0, 10 ) ) != QgsTriangle() );
7348 : 1 : QVERIFY( QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 0, 10 ) ) != QgsTriangle( QgsPoint( 0, 10 ), QgsPoint( 5, 5 ), QgsPoint( 0, 0 ) ) );
7349 : :
7350 : : // clone
7351 : 1 : QgsTriangle *t4 = t3.clone();
7352 : 1 : QCOMPARE( t3, *t4 );
7353 : 1 : delete t4;
7354 : :
7355 : : // constructor from QgsPointXY and QPointF
7356 : 1 : QgsTriangle t_qgspoint = QgsTriangle( QgsPointXY( 0, 0 ), QgsPointXY( 0, 10 ), QgsPointXY( 10, 10 ) );
7357 : 1 : QVERIFY( t3 == t_qgspoint );
7358 : 1 : QgsTriangle t_pointf = QgsTriangle( QPointF( 0, 0 ), QPointF( 0, 10 ), QPointF( 10, 10 ) );
7359 : 1 : QVERIFY( t3 == t_pointf );
7360 : :
7361 : : // Z
7362 : 1 : t3 = QgsTriangle( QgsPoint( QgsWkbTypes::PointZ, 0, 5, 1 ), QgsPoint( QgsWkbTypes::PointZ, 0, 0, 2 ), QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 ) );
7363 : 1 : QVERIFY( !t3.isEmpty() );
7364 : 1 : QVERIFY( t3.is3D() );
7365 : 1 : QVERIFY( !t3.isMeasure() );
7366 : 1 : QCOMPARE( t3.wkbType(), QgsWkbTypes::TriangleZ );
7367 : 1 : QCOMPARE( t3.wktTypeStr(), QString( "TriangleZ" ) );
7368 : 1 : QCOMPARE( t3.geometryType(), QString( "Triangle" ) );
7369 : : // M
7370 : 1 : t3 = QgsTriangle( QgsPoint( QgsWkbTypes::PointM, 0, 5, 0, 1 ), QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 2 ), QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 ) );
7371 : 1 : QVERIFY( !t3.isEmpty() );
7372 : 1 : QVERIFY( !t3.is3D() );
7373 : 1 : QVERIFY( t3.isMeasure() );
7374 : 1 : QCOMPARE( t3.wkbType(), QgsWkbTypes::TriangleM );
7375 : 1 : QCOMPARE( t3.wktTypeStr(), QString( "TriangleM" ) );
7376 : 1 : QCOMPARE( t3.geometryType(), QString( "Triangle" ) );
7377 : : // ZM
7378 : 1 : t3 = QgsTriangle( QgsPoint( QgsWkbTypes::PointZM, 0, 5, 8, 1 ), QgsPoint( QgsWkbTypes::PointZM, 0, 0, 5, 2 ), QgsPoint( QgsWkbTypes::PointZM, 10, 10, 2, 3 ) );
7379 : 1 : QVERIFY( !t3.isEmpty() );
7380 : 1 : QVERIFY( t3.is3D() );
7381 : 1 : QVERIFY( t3.isMeasure() );
7382 : 1 : QCOMPARE( t3.wkbType(), QgsWkbTypes::TriangleZM );
7383 : 1 : QCOMPARE( t3.wktTypeStr(), QString( "TriangleZM" ) );
7384 : 1 : QCOMPARE( t3.geometryType(), QString( "Triangle" ) );
7385 : :
7386 : : // fromWkt
7387 : 1 : QgsTriangle t5;
7388 : 1 : ext.reset( new QgsLineString() );
7389 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
7390 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 ) );
7391 : 1 : t5.setExteriorRing( ext.release() );
7392 : 1 : QString wkt = t5.asWkt();
7393 : 1 : QVERIFY( !wkt.isEmpty() );
7394 : 1 : QgsTriangle t6;
7395 : 1 : QVERIFY( t6.fromWkt( wkt ) );
7396 : 1 : QCOMPARE( t5, t6 );
7397 : :
7398 : : // conversion
7399 : 1 : QgsPolygon p1;
7400 : 1 : ext.reset( new QgsLineString() );
7401 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
7402 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 ) );
7403 : 1 : p1.setExteriorRing( ext.release() );
7404 : : //toPolygon
7405 : 1 : std::unique_ptr< QgsPolygon > poly( t5.toPolygon() );
7406 : 1 : QCOMPARE( *poly, p1 );
7407 : : //surfaceToPolygon
7408 : 1 : std::unique_ptr< QgsPolygon > surface( t5.surfaceToPolygon() );
7409 : 1 : QCOMPARE( *surface, p1 );
7410 : :
7411 : : //bad WKT
7412 : 1 : QVERIFY( !t6.fromWkt( "Point()" ) );
7413 : 1 : QVERIFY( t6.isEmpty() );
7414 : 1 : QVERIFY( !t6.exteriorRing() );
7415 : 1 : QCOMPARE( t6.numInteriorRings(), 0 );
7416 : 1 : QVERIFY( !t6.is3D() );
7417 : 1 : QVERIFY( !t6.isMeasure() );
7418 : 1 : QCOMPARE( t6.wkbType(), QgsWkbTypes::Triangle );
7419 : :
7420 : : // WKB
7421 : 1 : QByteArray wkb = t5.asWkb();
7422 : 1 : QCOMPARE( wkb.size(), t5.wkbSize() );
7423 : 1 : t6.clear();
7424 : 1 : QgsConstWkbPtr wkb16ptr5( wkb );
7425 : 1 : t6.fromWkb( wkb16ptr5 );
7426 : 1 : QCOMPARE( t5.wkbType(), QgsWkbTypes::TriangleZM );
7427 : 1 : QCOMPARE( t5, t6 );
7428 : :
7429 : : //bad WKB - check for no crash
7430 : 1 : t6.clear();
7431 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
7432 : 1 : QVERIFY( !t6.fromWkb( nullPtr ) );
7433 : 1 : QCOMPARE( t6.wkbType(), QgsWkbTypes::Triangle );
7434 : 1 : QgsPoint point( 1, 2 );
7435 : 1 : QByteArray wkbPoint = point.asWkb();
7436 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
7437 : 1 : QVERIFY( !t6.fromWkb( wkbPointPtr ) );
7438 : 1 : QCOMPARE( t6.wkbType(), QgsWkbTypes::Triangle );
7439 : :
7440 : : //asGML2
7441 : 2 : QgsTriangle exportTriangle( QgsPoint( 1, 2 ),
7442 : 1 : QgsPoint( 3, 4 ),
7443 : 1 : QgsPoint( 6, 5 ) );
7444 : 2 : QgsTriangle exportTriangleZ( QgsPoint( 1, 2, 3 ),
7445 : 1 : QgsPoint( 11, 12, 13 ),
7446 : 1 : QgsPoint( 1, 12, 23 ) );
7447 : 2 : QgsTriangle exportTriangleFloat( QgsPoint( 1 + 1 / 3.0, 2 + 2 / 3.0 ),
7448 : 1 : QgsPoint( 3 + 1 / 3.0, 4 + 2 / 3.0 ),
7449 : 1 : QgsPoint( 6 + 1 / 3.0, 5 + 2 / 3.0 ) );
7450 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
7451 : 2 : QString expectedGML2( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1,2 3,4 6,5 1,2</coordinates></LinearRing></outerBoundaryIs></Polygon>" ) );
7452 : 3 : QGSCOMPAREGML( elemToString( exportTriangle.asGml2( doc ) ), expectedGML2 );
7453 : 2 : QString expectedGML2prec3( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1.333,2.667 3.333,4.667 6.333,5.667 1.333,2.667</coordinates></LinearRing></outerBoundaryIs></Polygon>" ) );
7454 : 3 : QGSCOMPAREGML( elemToString( exportTriangleFloat.asGml2( doc, 3 ) ), expectedGML2prec3 );
7455 : 2 : QString expectedGML2empty( QStringLiteral( "<Polygon xmlns=\"gml\"/>" ) );
7456 : 3 : QGSCOMPAREGML( elemToString( QgsTriangle().asGml2( doc ) ), expectedGML2empty );
7457 : :
7458 : : //asGML3
7459 : 2 : QString expectedGML3( QStringLiteral( "<Triangle xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1 2 3 4 6 5 1 2</posList></LinearRing></exterior></Triangle>" ) );
7460 : 1 : QCOMPARE( elemToString( exportTriangle.asGml3( doc ) ), expectedGML3 );
7461 : 2 : QString expectedGML3prec3( QStringLiteral( "<Triangle xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1.333 2.667 3.333 4.667 6.333 5.667 1.333 2.667</posList></LinearRing></exterior></Triangle>" ) );
7462 : 1 : QCOMPARE( elemToString( exportTriangleFloat.asGml3( doc, 3 ) ), expectedGML3prec3 );
7463 : 2 : QString expectedGML3empty( QStringLiteral( "<Triangle xmlns=\"gml\"/>" ) );
7464 : 3 : QGSCOMPAREGML( elemToString( QgsTriangle().asGml3( doc ) ), expectedGML3empty );
7465 : 2 : QString expectedGML3Z( QStringLiteral( "<Triangle xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"3\">1 2 3 11 12 13 1 12 23 1 2 3</posList></LinearRing></exterior></Triangle>" ) );
7466 : 1 : QCOMPARE( elemToString( exportTriangleZ.asGml3( doc ) ), expectedGML3Z );
7467 : :
7468 : :
7469 : : // lengths and angles
7470 : 1 : QgsTriangle t7( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ) );
7471 : :
7472 : 1 : QVector<double> a_tested, a_t7 = t7.angles();
7473 : 1 : a_tested.append( M_PI / 4.0 );
7474 : 1 : a_tested.append( M_PI / 2.0 );
7475 : 1 : a_tested.append( M_PI / 4.0 );
7476 : 1 : QGSCOMPARENEAR( a_tested.at( 0 ), a_t7.at( 0 ), 0.0001 );
7477 : 1 : QGSCOMPARENEAR( a_tested.at( 1 ), a_t7.at( 1 ), 0.0001 );
7478 : 1 : QGSCOMPARENEAR( a_tested.at( 2 ), a_t7.at( 2 ), 0.0001 );
7479 : 1 : QVector<double> a_empty = QgsTriangle().angles();
7480 : 1 : QVERIFY( a_empty.isEmpty() );
7481 : :
7482 : 1 : QVector<double> l_tested, l_t7 = t7.lengths();
7483 : 1 : l_tested.append( 5 );
7484 : 1 : l_tested.append( 5 );
7485 : 1 : l_tested.append( std::sqrt( 5 * 5 + 5 * 5 ) );
7486 : 1 : QGSCOMPARENEAR( l_tested.at( 0 ), l_t7.at( 0 ), 0.0001 );
7487 : 1 : QGSCOMPARENEAR( l_tested.at( 1 ), l_t7.at( 1 ), 0.0001 );
7488 : 1 : QGSCOMPARENEAR( l_tested.at( 2 ), l_t7.at( 2 ), 0.0001 );
7489 : 1 : QVector<double> l_empty = QgsTriangle().lengths();
7490 : 1 : QVERIFY( l_empty.isEmpty() );
7491 : :
7492 : : // type of triangle
7493 : : // Empty triangle returns always false for the types, except isDegenerate
7494 : 1 : QVERIFY( QgsTriangle().isDegenerate() );
7495 : 1 : QVERIFY( !QgsTriangle().isRight() );
7496 : 1 : QVERIFY( !QgsTriangle().isIsocele() );
7497 : 1 : QVERIFY( !QgsTriangle().isScalene() );
7498 : 1 : QVERIFY( !QgsTriangle().isEquilateral() );
7499 : :
7500 : : // type of triangle
7501 : 1 : QVERIFY( !t7.isDegenerate() );
7502 : 1 : QVERIFY( t7.isRight() );
7503 : 1 : QVERIFY( t7.isIsocele() );
7504 : 1 : QVERIFY( !t7.isScalene() );
7505 : 1 : QVERIFY( !t7.isEquilateral() );
7506 : :
7507 : 1 : QgsTriangle t8( QgsPoint( 7.2825, 4.2368 ), QgsPoint( 13.0058, 3.3218 ), QgsPoint( 9.2145, 6.5242 ) );
7508 : : // angles in radians 58.8978;31.1036;89.9985
7509 : : // length 5.79598;4.96279;2.99413
7510 : 1 : QVERIFY( !t8.isDegenerate() );
7511 : 1 : QVERIFY( t8.isRight() );
7512 : 1 : QVERIFY( !t8.isIsocele() );
7513 : 1 : QVERIFY( t8.isScalene() );
7514 : 1 : QVERIFY( !t8.isEquilateral() );
7515 : :
7516 : 1 : QgsTriangle t9( QgsPoint( 10, 10 ), QgsPoint( 16, 10 ), QgsPoint( 13, 15.1962 ) );
7517 : 1 : QVERIFY( !t9.isDegenerate() );
7518 : 1 : QVERIFY( !t9.isRight() );
7519 : 1 : QVERIFY( t9.isIsocele() );
7520 : 1 : QVERIFY( !t9.isScalene() );
7521 : 1 : QVERIFY( t9.isEquilateral() );
7522 : :
7523 : : // vertex
7524 : 1 : QVERIFY( t9.vertexAt( -1 ).isEmpty() );
7525 : 1 : QCOMPARE( t9.vertexAt( 0 ), QgsPoint( 10, 10 ) );
7526 : 1 : QCOMPARE( t9.vertexAt( 1 ), QgsPoint( 16, 10 ) );
7527 : 1 : QCOMPARE( t9.vertexAt( 2 ), QgsPoint( 13, 15.1962 ) );
7528 : 1 : QCOMPARE( t9.vertexAt( 3 ), QgsPoint( 10, 10 ) );
7529 : 1 : QVERIFY( t9.vertexAt( 4 ).isEmpty() );
7530 : :
7531 : : // altitudes
7532 : 1 : QgsTriangle t10( QgsPoint( 20, 2 ), QgsPoint( 16, 6 ), QgsPoint( 26, 2 ) );
7533 : 1 : QVector<QgsLineString> alt = QgsTriangle().altitudes();
7534 : 1 : QVERIFY( alt.isEmpty() );
7535 : 1 : alt = t10.altitudes();
7536 : 1 : QGSCOMPARENEARPOINT( alt.at( 0 ).pointN( 1 ), QgsPoint( 20.8276, 4.0690 ), 0.0001 );
7537 : 1 : QGSCOMPARENEARPOINT( alt.at( 1 ).pointN( 1 ), QgsPoint( 16, 2 ), 0.0001 );
7538 : 1 : QGSCOMPARENEARPOINT( alt.at( 2 ).pointN( 1 ), QgsPoint( 23, -1 ), 0.0001 );
7539 : :
7540 : : // orthocenter
7541 : :
7542 : 1 : QVERIFY( QgsTriangle().orthocenter().isEmpty() );
7543 : 1 : QCOMPARE( QgsPoint( 16, -8 ), t10.orthocenter() );
7544 : 1 : QCOMPARE( QgsPoint( 0, 5 ), t7.orthocenter() );
7545 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 13, 11.7321 ), t9.orthocenter(), 0.0001 );
7546 : :
7547 : : // circumscribed circle
7548 : 1 : QVERIFY( QgsTriangle().circumscribedCenter().isEmpty() );
7549 : 1 : QCOMPARE( 0.0, QgsTriangle().circumscribedRadius() );
7550 : 1 : QCOMPARE( QgsPoint( 2.5, 2.5 ), t7.circumscribedCenter() );
7551 : 1 : QGSCOMPARENEAR( 3.5355, t7.circumscribedRadius(), 0.0001 );
7552 : 1 : QCOMPARE( QgsPoint( 23, 9 ), t10.circumscribedCenter() );
7553 : 1 : QGSCOMPARENEAR( 7.6158, t10.circumscribedRadius(), 0.0001 );
7554 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 13, 11.7321 ), t9.circumscribedCenter(), 0.0001 );
7555 : 1 : QGSCOMPARENEAR( 3.4641, t9.circumscribedRadius(), 0.0001 );
7556 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 13, 11.7321 ), t9.circumscribedCircle().center(), 0.0001 );
7557 : 1 : QGSCOMPARENEAR( 3.4641, t9.circumscribedCircle().radius(), 0.0001 );
7558 : :
7559 : : // inscribed circle
7560 : 1 : QVERIFY( QgsTriangle().inscribedCenter().isEmpty() );
7561 : 1 : QCOMPARE( 0.0, QgsTriangle().inscribedRadius() );
7562 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 1.4645, 3.5355 ), t7.inscribedCenter(), 0.001 );
7563 : 1 : QGSCOMPARENEAR( 1.4645, t7.inscribedRadius(), 0.0001 );
7564 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 20.4433, 3.0701 ), t10.inscribedCenter(), 0.001 );
7565 : 1 : QGSCOMPARENEAR( 1.0701, t10.inscribedRadius(), 0.0001 );
7566 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 13, 11.7321 ), t9.inscribedCenter(), 0.0001 );
7567 : 1 : QGSCOMPARENEAR( 1.7321, t9.inscribedRadius(), 0.0001 );
7568 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 13, 11.7321 ), t9.inscribedCircle().center(), 0.0001 );
7569 : 1 : QGSCOMPARENEAR( 1.7321, t9.inscribedCircle().radius(), 0.0001 );
7570 : :
7571 : : // medians
7572 : 1 : QVector<QgsLineString> med = QgsTriangle().medians();
7573 : 1 : QVERIFY( med.isEmpty() );
7574 : 1 : med = t7.medians();
7575 : 1 : QCOMPARE( med.at( 0 ).pointN( 0 ), t7.vertexAt( 0 ) );
7576 : 1 : QGSCOMPARENEARPOINT( med.at( 0 ).pointN( 1 ), QgsPoint( 2.5, 5 ), 0.0001 );
7577 : 1 : QCOMPARE( med.at( 1 ).pointN( 0 ), t7.vertexAt( 1 ) );
7578 : 1 : QGSCOMPARENEARPOINT( med.at( 1 ).pointN( 1 ), QgsPoint( 2.5, 2.5 ), 0.0001 );
7579 : 1 : QCOMPARE( med.at( 2 ).pointN( 0 ), t7.vertexAt( 2 ) );
7580 : 1 : QGSCOMPARENEARPOINT( med.at( 2 ).pointN( 1 ), QgsPoint( 0, 2.5 ), 0.0001 );
7581 : 1 : med.clear();
7582 : :
7583 : 1 : med = t10.medians();
7584 : 1 : QCOMPARE( med.at( 0 ).pointN( 0 ), t10.vertexAt( 0 ) );
7585 : 1 : QGSCOMPARENEARPOINT( med.at( 0 ).pointN( 1 ), QgsPoint( 21, 4 ), 0.0001 );
7586 : 1 : QCOMPARE( med.at( 1 ).pointN( 0 ), t10.vertexAt( 1 ) );
7587 : 1 : QGSCOMPARENEARPOINT( med.at( 1 ).pointN( 1 ), QgsPoint( 23, 2 ), 0.0001 );
7588 : 1 : QCOMPARE( med.at( 2 ).pointN( 0 ), t10.vertexAt( 2 ) );
7589 : 1 : QGSCOMPARENEARPOINT( med.at( 2 ).pointN( 1 ), QgsPoint( 18, 4 ), 0.0001 );
7590 : 1 : med.clear();
7591 : 1 : alt.clear();
7592 : :
7593 : 1 : med = t9.medians();
7594 : 1 : alt = t9.altitudes();
7595 : 1 : QGSCOMPARENEARPOINT( med.at( 0 ).pointN( 0 ), alt.at( 0 ).pointN( 0 ), 0.0001 );
7596 : 1 : QGSCOMPARENEARPOINT( med.at( 0 ).pointN( 1 ), alt.at( 0 ).pointN( 1 ), 0.0001 );
7597 : 1 : QGSCOMPARENEARPOINT( med.at( 1 ).pointN( 0 ), alt.at( 1 ).pointN( 0 ), 0.0001 );
7598 : 1 : QGSCOMPARENEARPOINT( med.at( 1 ).pointN( 1 ), alt.at( 1 ).pointN( 1 ), 0.0001 );
7599 : 1 : QGSCOMPARENEARPOINT( med.at( 2 ).pointN( 0 ), alt.at( 2 ).pointN( 0 ), 0.0001 );
7600 : 1 : QGSCOMPARENEARPOINT( med.at( 2 ).pointN( 1 ), alt.at( 2 ).pointN( 1 ), 0.0001 );
7601 : :
7602 : : // medial
7603 : 1 : QCOMPARE( QgsTriangle().medial(), QgsTriangle() );
7604 : 1 : QCOMPARE( t7.medial(), QgsTriangle( QgsPoint( 0, 2.5 ), QgsPoint( 2.5, 5 ), QgsPoint( 2.5, 2.5 ) ) );
7605 : 1 : QCOMPARE( t9.medial(), QgsTriangle( QgsGeometryUtils::midpoint( t9.vertexAt( 0 ), t9.vertexAt( 1 ) ),
7606 : : QgsGeometryUtils::midpoint( t9.vertexAt( 1 ), t9.vertexAt( 2 ) ),
7607 : : QgsGeometryUtils::midpoint( t9.vertexAt( 2 ), t9.vertexAt( 0 ) ) ) );
7608 : :
7609 : : // bisectors
7610 : 1 : QVector<QgsLineString> bis = QgsTriangle().bisectors();
7611 : 1 : QVERIFY( bis.isEmpty() );
7612 : 1 : bis = t7.bisectors();
7613 : 1 : QCOMPARE( bis.at( 0 ).pointN( 0 ), t7.vertexAt( 0 ) );
7614 : 1 : QGSCOMPARENEARPOINT( bis.at( 0 ).pointN( 1 ), QgsPoint( 2.0711, 5 ), 0.0001 );
7615 : 1 : QCOMPARE( bis.at( 1 ).pointN( 0 ), t7.vertexAt( 1 ) );
7616 : 1 : QGSCOMPARENEARPOINT( bis.at( 1 ).pointN( 1 ), QgsPoint( 2.5, 2.5 ), 0.0001 );
7617 : 1 : QCOMPARE( bis.at( 2 ).pointN( 0 ), t7.vertexAt( 2 ) );
7618 : 1 : QGSCOMPARENEARPOINT( bis.at( 2 ).pointN( 1 ), QgsPoint( 0, 2.9289 ), 0.0001 );
7619 : :
7620 : : // "deleted" method
7621 : 1 : ext.reset( new QgsLineString() );
7622 : 1 : QgsTriangle t11( QgsPoint( 0, 0 ), QgsPoint( 100, 100 ), QgsPoint( 0, 200 ) );
7623 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 5, 5 )
7624 : 1 : << QgsPoint( 50, 50 ) << QgsPoint( 0, 25 )
7625 : 1 : << QgsPoint( 5, 5 ) );
7626 : 1 : t11.addInteriorRing( ext.release() );
7627 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 100 100, 0 200, 0 0))" ) );
7628 : :
7629 : : /* QList<QgsCurve *> lc;
7630 : : lc.append(ext);
7631 : : t11.setInteriorRings( lc );
7632 : : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 100 100, 0 200, 0 0))" ) );*/
7633 : :
7634 : 1 : QgsVertexId id( 0, 0, 1 );
7635 : 1 : QVERIFY( !t11.deleteVertex( id ) );
7636 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 100 100, 0 200, 0 0))" ) );
7637 : 1 : QVERIFY( !t11.insertVertex( id, QgsPoint( 5, 5 ) ) );
7638 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 100 100, 0 200, 0 0))" ) );
7639 : :
7640 : : //move vertex
7641 : 1 : QgsPoint pt1( 5, 5 );
7642 : : // invalid part
7643 : 1 : id.part = -1;
7644 : 1 : QVERIFY( !t11.moveVertex( id, pt1 ) );
7645 : 1 : id.part = 1;
7646 : 1 : QVERIFY( !t11.moveVertex( id, pt1 ) );
7647 : : // invalid ring
7648 : 1 : id.part = 0;
7649 : 1 : id.ring = -1;
7650 : 1 : QVERIFY( !t11.moveVertex( id, pt1 ) );
7651 : 1 : id.ring = 1;
7652 : 1 : QVERIFY( !t11.moveVertex( id, pt1 ) );
7653 : 1 : id.ring = 0;
7654 : 1 : id.vertex = -1;
7655 : 1 : QVERIFY( !t11.moveVertex( id, pt1 ) );
7656 : 1 : id.vertex = 5;
7657 : 1 : QVERIFY( !t11.moveVertex( id, pt1 ) );
7658 : :
7659 : : // valid vertex
7660 : 1 : id.vertex = 0;
7661 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7662 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((5 5, 100 100, 0 200, 5 5))" ) );
7663 : 1 : pt1 = QgsPoint( 0, 0 );
7664 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7665 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 100 100, 0 200, 0 0))" ) );
7666 : 1 : id.vertex = 4;
7667 : 1 : pt1 = QgsPoint( 5, 5 );
7668 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7669 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((5 5, 100 100, 0 200, 5 5))" ) );
7670 : 1 : pt1 = QgsPoint( 0, 0 );
7671 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7672 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 100 100, 0 200, 0 0))" ) );
7673 : 1 : id.vertex = 1;
7674 : 1 : pt1 = QgsPoint( 5, 5 );
7675 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7676 : 1 : QCOMPARE( t11.asWkt(), QString( "Triangle ((0 0, 5 5, 0 200, 0 0))" ) );
7677 : : // colinear
7678 : 1 : pt1 = QgsPoint( 0, 100 );
7679 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7680 : 1 : pt1 = QgsPoint( 5, 5 );
7681 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7682 : : // duplicate point
7683 : 1 : pt1 = QgsPoint( 0, 0 );
7684 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7685 : 1 : pt1 = QgsPoint( 5, 5 );
7686 : 1 : QVERIFY( t11.moveVertex( id, pt1 ) );
7687 : :
7688 : : //toCurveType
7689 : 1 : QgsTriangle t12( QgsPoint( 7, 4 ), QgsPoint( 13, 3 ), QgsPoint( 9, 6 ) );
7690 : 1 : std::unique_ptr< QgsCurvePolygon > curveType( t12.toCurveType() );
7691 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::CurvePolygon );
7692 : 1 : QCOMPARE( curveType->exteriorRing()->numPoints(), 4 );
7693 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 7, 4 ) );
7694 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 13, 3 ) );
7695 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 9, 6 ) );
7696 : 1 : QCOMPARE( curveType->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( 7, 4 ) );
7697 : 1 : QCOMPARE( curveType->numInteriorRings(), 0 );
7698 : :
7699 : : // boundary
7700 : 1 : QVERIFY( !QgsTriangle().boundary() );
7701 : 1 : std::unique_ptr< QgsCurve > boundary( QgsTriangle( QgsPoint( 7, 4 ), QgsPoint( 13, 3 ), QgsPoint( 9, 6 ) ).boundary() );
7702 : 1 : QCOMPARE( boundary->wkbType(), QgsWkbTypes::LineString );
7703 : 1 : QCOMPARE( boundary->numPoints(), 4 );
7704 : 1 : QCOMPARE( boundary->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 7, 4 ) );
7705 : 1 : QCOMPARE( boundary->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 13, 3 ) );
7706 : 1 : QCOMPARE( boundary->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 9, 6 ) );
7707 : 1 : QCOMPARE( boundary->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( 7, 4 ) );
7708 : :
7709 : : // cast
7710 : 1 : QgsTriangle pCast;
7711 : 1 : QVERIFY( QgsPolygon().cast( &pCast ) );
7712 : 1 : QgsTriangle pCast2( QgsPoint( 7, 4 ), QgsPoint( 13, 3 ), QgsPoint( 9, 6 ) );
7713 : 1 : QVERIFY( QgsPolygon().cast( &pCast2 ) );
7714 : 1 : }
7715 : :
7716 : 1 : void TestQgsGeometry::ellipse()
7717 : : {
7718 : : //test constructors
7719 : 1 : QgsEllipse elp1;
7720 : 1 : QVERIFY( elp1.center().isEmpty() );
7721 : 1 : QCOMPARE( elp1.semiMajorAxis(), 0.0 );
7722 : 1 : QCOMPARE( elp1.semiMinorAxis(), 0.0 );
7723 : 1 : QCOMPARE( elp1.azimuth(), 90.0 );
7724 : 1 : QVERIFY( elp1.isEmpty() );
7725 : :
7726 : 1 : QgsEllipse elp2( QgsPoint( 5, 10 ), 3, 2 );
7727 : 1 : QVERIFY( elp2.center() == QgsPoint( 5, 10 ) );
7728 : 1 : QCOMPARE( elp2.semiMajorAxis(), 3.0 );
7729 : 1 : QCOMPARE( elp2.semiMinorAxis(), 2.0 );
7730 : 1 : QCOMPARE( elp2.azimuth(), 90.0 );
7731 : 1 : QVERIFY( !elp2.isEmpty() );
7732 : :
7733 : 1 : QgsEllipse elp3( QgsPoint( 5, 10 ), 3, 2, 45 );
7734 : 1 : QVERIFY( elp3.center() == QgsPoint( 5, 10 ) );
7735 : 1 : QCOMPARE( elp3.semiMajorAxis(), 3.0 );
7736 : 1 : QCOMPARE( elp3.semiMinorAxis(), 2.0 );
7737 : 1 : QCOMPARE( elp3.azimuth(), 45.0 );
7738 : 1 : QVERIFY( !elp3.isEmpty() );
7739 : :
7740 : 1 : QgsEllipse elp4( QgsPoint( 5, 10 ), 2, 3, 45 );
7741 : 1 : QVERIFY( elp4.center() == QgsPoint( 5, 10 ) );
7742 : 1 : QCOMPARE( elp4.semiMajorAxis(), 3.0 );
7743 : 1 : QCOMPARE( elp4.semiMinorAxis(), 2.0 );
7744 : 1 : QCOMPARE( elp4.azimuth(), 135.0 );
7745 : 1 : QVERIFY( !elp4.isEmpty() );
7746 : :
7747 : : //test toString
7748 : 1 : QCOMPARE( elp1.toString(), QString( "Empty" ) );
7749 : 1 : QCOMPARE( elp2.toString(), QString( "Ellipse (Center: Point (5 10), Semi-Major Axis: 3, Semi-Minor Axis: 2, Azimuth: 90)" ) );
7750 : 1 : QCOMPARE( elp3.toString(), QString( "Ellipse (Center: Point (5 10), Semi-Major Axis: 3, Semi-Minor Axis: 2, Azimuth: 45)" ) );
7751 : 1 : QCOMPARE( elp4.toString(), QString( "Ellipse (Center: Point (5 10), Semi-Major Axis: 3, Semi-Minor Axis: 2, Azimuth: 135)" ) );
7752 : :
7753 : : //test equality operator
7754 : 1 : QCOMPARE( QgsEllipse().isEmpty(), QgsEllipse( QgsPoint(), 0, 0, 90 ).isEmpty() );
7755 : 1 : QVERIFY( !( QgsEllipse() == QgsEllipse( QgsPoint( 0, 0 ), 0, 0, 0.0005 ) ) );
7756 : 1 : QVERIFY( elp2 == QgsEllipse( QgsPoint( 5, 10 ), 2, 3, 0 ) );
7757 : 1 : QVERIFY( elp2 != elp3 );
7758 : 1 : QVERIFY( elp3 != elp4 );
7759 : 1 : QVERIFY( elp4 == QgsEllipse( QgsPoint( 5, 10 ), 3, 2, 90 + 45 ) );
7760 : :
7761 : : //test setter and getter
7762 : 1 : elp1.setAzimuth( 45 );
7763 : 1 : QCOMPARE( elp1.azimuth(), 45.0 );
7764 : :
7765 : 1 : elp1.setSemiMajorAxis( 50 );
7766 : 1 : QCOMPARE( elp1.semiMajorAxis(), 50.0 );
7767 : :
7768 : : // axis_b > axis_a
7769 : 1 : elp1.setSemiMinorAxis( 70 );
7770 : 1 : QCOMPARE( elp1.semiMajorAxis(), 70.0 );
7771 : 1 : QCOMPARE( elp1.semiMinorAxis(), 50.0 );
7772 : : // axis_b < axis_a
7773 : 1 : elp1.setSemiMinorAxis( 3 );
7774 : 1 : QCOMPARE( elp1.semiMinorAxis(), 3.0 );
7775 : 1 : QCOMPARE( elp1.semiMajorAxis(), 70.0 );
7776 : :
7777 : 1 : elp1.setSemiMajorAxis( 2 );
7778 : 1 : QCOMPARE( elp1.semiMinorAxis(), 2.0 );
7779 : 1 : QCOMPARE( elp1.semiMajorAxis(), 3.0 );
7780 : :
7781 : 1 : elp1.setCenter( QgsPoint( 5, 10 ) );
7782 : 1 : QVERIFY( elp1.center() == QgsPoint( 5, 10 ) );
7783 : 1 : QVERIFY( elp1.rcenter() == QgsPoint( 5, 10 ) );
7784 : 1 : elp1.rcenter() = QgsPoint( 25, 310 );
7785 : 1 : QVERIFY( elp1.center() == QgsPoint( 25, 310 ) );
7786 : :
7787 : : //test "alt" constructors
7788 : : // fromExtent
7789 : 1 : QgsEllipse elp_alt = QgsEllipse( QgsPoint( 2.5, 5 ), 2.5, 5 );
7790 : 1 : QVERIFY( QgsEllipse().fromExtent( QgsPoint( 0, 0 ), QgsPoint( 5, 10 ) ) == elp_alt );
7791 : 1 : QVERIFY( QgsEllipse().fromExtent( QgsPoint( 5, 10 ), QgsPoint( 0, 0 ) ) == elp_alt );
7792 : 1 : QVERIFY( QgsEllipse().fromExtent( QgsPoint( 5, 0 ), QgsPoint( 0, 10 ) ) == elp_alt );
7793 : 1 : QVERIFY( QgsEllipse().fromExtent( QgsPoint( -5, 0 ), QgsPoint( 0, 10 ) ) != elp_alt );
7794 : : // fromCenterPoint
7795 : 1 : QVERIFY( QgsEllipse().fromCenterPoint( QgsPoint( 2.5, 5 ), QgsPoint( 5, 10 ) ) == elp_alt );
7796 : 1 : QVERIFY( QgsEllipse().fromCenterPoint( QgsPoint( 2.5, 5 ), QgsPoint( -0, 0 ) ) == elp_alt );
7797 : 1 : QVERIFY( QgsEllipse().fromCenterPoint( QgsPoint( 2.5, 5 ), QgsPoint( 0, -10 ) ) != elp_alt );
7798 : : // fromCenter2Points
7799 : 1 : QVERIFY( QgsEllipse().fromCenter2Points( QgsPoint( 2.5, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ) ) ==
7800 : : QgsEllipse( QgsPoint( 2.5, 5 ), 5, 5, 180 ) );
7801 : 1 : QVERIFY( QgsEllipse().fromCenter2Points( QgsPoint( 2.5, 5 ), QgsPoint( 2.5, 7.5 ), QgsPoint( 7.5, 5 ) ) != elp_alt ); //same ellipse with different azimuth
7802 : 1 : QVERIFY( QgsEllipse().fromCenter2Points( QgsPoint( 2.5, 5 ), QgsPoint( 2.5, 2.5 ), QgsPoint( 7.5, 5 ) ) != elp_alt ); //same ellipse with different azimuth
7803 : 1 : QVERIFY( QgsEllipse().fromCenter2Points( QgsPoint( 2.5, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 5, 5 ) ) == elp_alt );
7804 : 1 : QVERIFY( QgsEllipse().fromCenter2Points( QgsPoint( 5, 10 ), QgsPoint( 5, 10 ).project( 3, 45 ), QgsPoint( 5, 10 ).project( 2, 90 + 45 ) ) ==
7805 : : QgsEllipse( QgsPoint( 5, 10 ), 3, 2, 45 ) );
7806 : :
7807 : : // fromFoci
7808 : : // horizontal
7809 : 1 : QgsEllipse elp_hor = QgsEllipse().fromFoci( QgsPoint( -4, 0 ), QgsPoint( 4, 0 ), QgsPoint( 0, 4 ) );
7810 : 1 : QVERIFY( QgsEllipse( QgsPoint( 0, 0 ), std::sqrt( 32.0 ), std::sqrt( 16.0 ), 90.0 ) == elp_hor );
7811 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 4, 0 ), elp_hor.foci().at( 0 ), 1e-8 );
7812 : 1 : QGSCOMPARENEARPOINT( QgsPoint( -4, 0 ), elp_hor.foci().at( 1 ), 1e-8 );
7813 : 1 : elp_hor = QgsEllipse().fromFoci( QgsPoint( 4, 0 ), QgsPoint( -4, 0 ), QgsPoint( 0, 4 ) );
7814 : 1 : QVERIFY( QgsEllipse( QgsPoint( 0, 0 ), std::sqrt( 32.0 ), std::sqrt( 16.0 ), 270.0 ) == elp_hor );
7815 : 1 : QGSCOMPARENEARPOINT( QgsPoint( -4, 0 ), elp_hor.foci().at( 0 ), 1e-8 );
7816 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 4, 0 ), elp_hor.foci().at( 1 ), 1e-8 );
7817 : :
7818 : : // vertical
7819 : 1 : QgsEllipse elp_ver = QgsEllipse().fromFoci( QgsPoint( 45, -15 ), QgsPoint( 45, 10 ), QgsPoint( 55, 0 ) );
7820 : 1 : QVERIFY( QgsEllipse( QgsPoint( 45, -2.5 ), 16.084946, 10.123017725, 0.0 ) == elp_ver );
7821 : 1 : elp_ver = QgsEllipse().fromFoci( QgsPoint( 45, 10 ), QgsPoint( 45, -15 ), QgsPoint( 55, 0 ) );
7822 : 1 : QVERIFY( QgsEllipse( QgsPoint( 45, -2.5 ), 16.084946, 10.123017725, 180.0 ) == elp_ver );
7823 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 45, -15 ), elp_ver.foci().at( 0 ), 1e-8 );
7824 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 45, 10 ), elp_ver.foci().at( 1 ), 1e-8 );
7825 : : // oriented
7826 : : // first quadrant
7827 : 1 : QgsEllipse elp_ori = QgsEllipse().fromFoci( QgsPoint( 10, 10 ), QgsPoint( 25, 20 ), QgsPoint( 15, 20 ) );
7828 : 1 : QVERIFY( QgsEllipse( QgsPoint( 17.5, 15.0 ), 10.5901699437, 5.55892970251, 90.0 - 33.690067526 ) == elp_ori );
7829 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 25, 20 ), elp_ori.foci().at( 0 ), 1e-8 );
7830 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 10, 10 ), elp_ori.foci().at( 1 ), 1e-8 );
7831 : : // second quadrant
7832 : 1 : elp_ori = QgsEllipse().fromFoci( QgsPoint( 10, 10 ), QgsPoint( 5, 20 ), QgsPoint( 15, 20 ) );
7833 : 1 : QVERIFY( QgsEllipse( QgsPoint( 7.5, 15.0 ), 10.5901699437, 8.99453719974, 360 - 26.56505117 ) == elp_ori );
7834 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 5, 20 ), elp_ori.foci().at( 0 ), 1e-8 );
7835 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 10, 10 ), elp_ori.foci().at( 1 ), 1e-8 );
7836 : : // third quadrant
7837 : 1 : elp_ori = QgsEllipse().fromFoci( QgsPoint( 10, 10 ), QgsPoint( 5, -5 ), QgsPoint( 15, 20 ) );
7838 : 1 : QVERIFY( QgsEllipse( QgsPoint( 7.5, 2.5 ), 19.0530819616, 17.3355107289893, 198.434948822922 ) == elp_ori );
7839 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 10, 10 ), elp_ori.foci().at( 1 ), 1e-8 );
7840 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 5, -5 ), elp_ori.foci().at( 0 ), 1e-8 );
7841 : : // fourth quadrant
7842 : 1 : elp_ori = QgsEllipse().fromFoci( QgsPoint( 10, 10 ), QgsPoint( 25, -5 ), QgsPoint( 15, 20 ) );
7843 : 1 : QVERIFY( QgsEllipse( QgsPoint( 17.5, 2.5 ), 19.0530819616, 15.82782146, 135 ) == elp_ori );
7844 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 25, -5 ), elp_ori.foci().at( 0 ), 1e-8 );
7845 : 1 : QGSCOMPARENEARPOINT( QgsPoint( 10, 10 ), elp_ori.foci().at( 1 ), 1e-8 );
7846 : :
7847 : : // test quadrant
7848 : 1 : QgsEllipse elpq( QgsPoint( 5, 10 ), 3, 2, 45 );
7849 : 1 : QgsPointSequence q = elpq.quadrant();
7850 : 1 : QGSCOMPARENEARPOINT( q.at( 0 ), QgsPoint( 7.1213, 12.1213 ), 0.001 );
7851 : 1 : QGSCOMPARENEARPOINT( q.at( 3 ), QgsPoint( 3.5858, 11.4142 ), 0.001 );
7852 : 1 : QGSCOMPARENEARPOINT( q.at( 2 ), QgsPoint( 2.8787, 7.8787 ), 0.001 );
7853 : 1 : QGSCOMPARENEARPOINT( q.at( 1 ), QgsPoint( 6.4142, 8.5858 ), 0.001 );
7854 : :
7855 : 1 : elpq = QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 90 );
7856 : 1 : q.clear();
7857 : 1 : q = elpq.quadrant();
7858 : 1 : QCOMPARE( q.at( 3 ), QgsPoint( 0, 2 ) );
7859 : 1 : QCOMPARE( q.at( 0 ), QgsPoint( 5, 0 ) );
7860 : 1 : QCOMPARE( q.at( 1 ), QgsPoint( 0, -2 ) );
7861 : 1 : QCOMPARE( q.at( 2 ), QgsPoint( -5, 0 ) );
7862 : :
7863 : 1 : elpq = QgsEllipse( QgsPoint( QgsWkbTypes::PointZM, 0, 0, 123, 321 ), 5, 2, 0 );
7864 : 1 : q.clear();
7865 : 1 : q = elpq.quadrant();
7866 : 1 : QCOMPARE( q.at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 0, 5, 123, 321 ) );
7867 : 1 : QCOMPARE( q.at( 3 ), QgsPoint( QgsWkbTypes::PointZM, -2, 0, 123, 321 ) );
7868 : 1 : QCOMPARE( q.at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 0, -5, 123, 321 ) );
7869 : 1 : QCOMPARE( q.at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 2, 0, 123, 321 ) );
7870 : :
7871 : 1 : elpq = QgsEllipse( QgsPoint( 0, 0 ), 2.5, 2, 315 );
7872 : 1 : q.clear();
7873 : 1 : q = elpq.quadrant();
7874 : 1 : QGSCOMPARENEARPOINT( q.at( 1 ), QgsPoint( 1.4142, 1.4142 ), 0.001 );
7875 : 1 : QGSCOMPARENEARPOINT( q.at( 2 ), QgsPoint( 1.7678, -1.7678 ), 0.001 );
7876 : 1 : QGSCOMPARENEARPOINT( q.at( 3 ), QgsPoint( -1.4142, -1.4142 ), 0.001 );
7877 : 1 : QGSCOMPARENEARPOINT( q.at( 0 ), QgsPoint( -1.7678, 1.7678 ), 0.001 );
7878 : :
7879 : 1 : elpq = QgsEllipse( QgsPoint( 0, 0 ), 5, 2.5, 45 );
7880 : 1 : q.clear();
7881 : 1 : q = elpq.quadrant();
7882 : 1 : QGSCOMPARENEARPOINT( q.at( 3 ), QgsPoint( -1.7678, 1.7678 ), 0.001 );
7883 : 1 : QGSCOMPARENEARPOINT( q.at( 0 ), QgsPoint( 3.5355, 3.5355 ), 0.001 );
7884 : 1 : QGSCOMPARENEARPOINT( q.at( 1 ), QgsPoint( 1.7678, -1.7678 ), 0.001 );
7885 : 1 : QGSCOMPARENEARPOINT( q.at( 2 ), QgsPoint( -3.5355, -3.5355 ), 0.001 );
7886 : :
7887 : : //test conversion
7888 : : // points
7889 : 1 : QgsPointSequence pts;
7890 : 1 : pts = QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).points( 4 );
7891 : 1 : q = QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).quadrant();
7892 : 1 : QCOMPARE( pts.length(), 4 );
7893 : 1 : QGSCOMPARENEARPOINT( q.at( 0 ), pts.at( 0 ), 2 );
7894 : 1 : QGSCOMPARENEARPOINT( q.at( 1 ), pts.at( 1 ), 2 );
7895 : 1 : QGSCOMPARENEARPOINT( q.at( 2 ), pts.at( 2 ), 2 );
7896 : 1 : QGSCOMPARENEARPOINT( q.at( 3 ), pts.at( 3 ), 2 );
7897 : :
7898 : 1 : QVERIFY( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).points( 2 ).isEmpty() ); // segments too low
7899 : :
7900 : : // linestring
7901 : 1 : std::unique_ptr< QgsLineString > l( new QgsLineString() );
7902 : :
7903 : 1 : l.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).toLineString( 2 ) );
7904 : 1 : QVERIFY( l->isEmpty() ); // segments too low
7905 : :
7906 : 1 : l.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).toLineString( 4 ) );
7907 : 1 : QCOMPARE( l->numPoints(), 5 ); // closed linestring
7908 : 1 : QgsPointSequence pts_l;
7909 : 1 : l->points( pts_l );
7910 : 1 : pts_l.pop_back();
7911 : 1 : QCOMPARE( pts, pts_l );
7912 : :
7913 : : // polygon
7914 : 1 : std::unique_ptr< QgsPolygon > p1( new QgsPolygon() );
7915 : :
7916 : 1 : p1.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).toPolygon( 2 ) );
7917 : 1 : QVERIFY( p1->isEmpty() ); // segments too low
7918 : :
7919 : 1 : p1.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).toPolygon( 4 ) );
7920 : 1 : q = QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).quadrant();
7921 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 0 ) ), q.at( 0 ) );
7922 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 1 ) ), q.at( 1 ) );
7923 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 2 ) ), q.at( 2 ) );
7924 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 3 ) ), q.at( 3 ) );
7925 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 4 ) ), q.at( 0 ) );
7926 : 1 : QCOMPARE( 0, p1->numInteriorRings() );
7927 : 1 : QCOMPARE( 5, p1->exteriorRing()->numPoints() );
7928 : :
7929 : 1 : p1.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 90 ).toPolygon( 4 ) );
7930 : 1 : q = QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 90 ).quadrant();
7931 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 0 ) ), q.at( 0 ) );
7932 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 1 ) ), q.at( 1 ) );
7933 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 2 ) ), q.at( 2 ) );
7934 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 3 ) ), q.at( 3 ) );
7935 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 4 ) ), q.at( 0 ) );
7936 : 1 : QCOMPARE( 0, p1->numInteriorRings() );
7937 : 1 : QCOMPARE( 5, p1->exteriorRing()->numPoints() );
7938 : :
7939 : 1 : p1.reset( elpq.toPolygon( 4 ) );
7940 : 1 : q = elpq.quadrant();
7941 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 0 ) ), q.at( 0 ) );
7942 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 1 ) ), q.at( 1 ) );
7943 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 2 ) ), q.at( 2 ) );
7944 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 3 ) ), q.at( 3 ) );
7945 : 1 : QCOMPARE( p1->vertexAt( QgsVertexId( 0, 0, 4 ) ), q.at( 0 ) );
7946 : 1 : QCOMPARE( 0, p1->numInteriorRings() );
7947 : 1 : QCOMPARE( 5, p1->exteriorRing()->numPoints() );
7948 : :
7949 : : // oriented bounding box
7950 : 1 : std::unique_ptr< QgsPolygon > ombb( QgsEllipse().orientedBoundingBox() );
7951 : 1 : QVERIFY( ombb->isEmpty() );
7952 : :
7953 : 1 : elpq = QgsEllipse( QgsPoint( 0, 0 ), 5, 2 );
7954 : 1 : ombb.reset( new QgsPolygon() );
7955 : 1 : QgsLineString *ext = new QgsLineString();
7956 : 1 : ext->setPoints( QgsPointSequence() << QgsPoint( 5, 2 ) << QgsPoint( 5, -2 ) << QgsPoint( -5, -2 ) << QgsPoint( -5, 2 ) );
7957 : 1 : ombb->setExteriorRing( ext );
7958 : 1 : std::unique_ptr< QgsPolygon >ombb2( elpq.orientedBoundingBox() );
7959 : 1 : QCOMPARE( ombb->asWkt( 2 ), ombb2->asWkt( 2 ) );
7960 : :
7961 : 1 : elpq = QgsEllipse( QgsPoint( 0, 0 ), 5, 2.5, 45 );
7962 : 1 : ombb.reset( elpq.orientedBoundingBox() );
7963 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1.7678, 5.3033 ), 0.0001 );
7964 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 5.3033, 1.7678 ), 0.0001 );
7965 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( -1.7678, -5.3033 ), 0.0001 );
7966 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( -5.3033, -1.7678 ), 0.0001 );
7967 : :
7968 : 1 : elpq = QgsEllipse( QgsPoint( 0, 0 ), 5, 2.5, 315 );
7969 : 1 : ombb.reset( elpq.orientedBoundingBox() );
7970 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( -5.3033, 1.7678 ), 0.0001 );
7971 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( -1.7678, 5.3033 ), 0.0001 );
7972 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 5.3033, -1.7678 ), 0.0001 );
7973 : 1 : QGSCOMPARENEARPOINT( ombb->exteriorRing()->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( 1.7678, -5.3033 ), 0.0001 );
7974 : :
7975 : : // bounding box
7976 : 1 : QCOMPARE( QgsEllipse().boundingBox(), QgsRectangle() );
7977 : 1 : ombb.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2 ).orientedBoundingBox() );
7978 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 5, 2 ).boundingBox(), ombb->boundingBox() );
7979 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 5, 5 ).boundingBox(), QgsRectangle( QgsPointXY( -5, -5 ), QgsPointXY( 5, 5 ) ) );
7980 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 5, 5, 60 ).boundingBox(), QgsRectangle( QgsPointXY( -5, -5 ), QgsPointXY( 5, 5 ) ) );
7981 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 13, 9, 45 ).boundingBox().toString( 4 ).toStdString(), QgsRectangle( QgsPointXY( -11.1803, -11.1803 ), QgsPointXY( 11.1803, 11.1803 ) ).toString( 4 ).toStdString() );
7982 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 13, 9, 60 ).boundingBox().toString( 4 ).toStdString(), QgsRectangle( QgsPointXY( -12.12436, -10.14889 ), QgsPointXY( 12.12436, 10.14889 ) ).toString( 4 ).toStdString() );
7983 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 13, 9, 60 + 90 ).boundingBox().toString( 4 ).toStdString(), QgsRectangle( QgsPointXY( -10.14889, -12.12436 ), QgsPointXY( 10.14889, 12.12436 ) ).toString( 4 ).toStdString() );
7984 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 13, 9, 300 ).boundingBox().toString( 4 ).toStdString(), QgsRectangle( QgsPointXY( -12.12436, -10.14889 ), QgsPointXY( 12.12436, 10.14889 ) ).toString( 4 ).toStdString() );
7985 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 13, 9, 300 - 90 ).boundingBox().toString( 4 ).toStdString(), QgsRectangle( QgsPointXY( -10.14889, -12.12436 ), QgsPointXY( 10.14889, 12.12436 ) ).toString( 4 ).toStdString() );
7986 : :
7987 : : // focus
7988 : 1 : QCOMPARE( QgsEllipse().fromFoci( QgsPoint( -4, 0 ), QgsPoint( 4, 0 ), QgsPoint( 0, 4 ) ).focusDistance(), 4.0 );
7989 : 1 : QGSCOMPARENEAR( QgsEllipse().fromFoci( QgsPoint( 10, 10 ), QgsPoint( 25, 20 ), QgsPoint( 15, 20 ) ).focusDistance(), 9.01388, 0.0001 );
7990 : :
7991 : : // eccentricity
7992 : 1 : QCOMPARE( QgsEllipse().fromFoci( QgsPoint( -4, 0 ), QgsPoint( 4, 0 ), QgsPoint( 0, 4 ) ).eccentricity(), 0.7071067811865475 );
7993 : 1 : QCOMPARE( QgsEllipse( QgsPoint( 0, 0 ), 3, 3 ).eccentricity(), 0.0 );
7994 : 1 : QVERIFY( std::isnan( QgsEllipse().eccentricity() ) );
7995 : :
7996 : : // area
7997 : 1 : QGSCOMPARENEAR( 31.4159, QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).area(), 0.0001 );
7998 : : // perimeter
7999 : 1 : p1.reset( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 45 ).toPolygon( 10000 ) );
8000 : 1 : QGSCOMPARENEAR( QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 45 ).perimeter(), p1->perimeter(), 0.001 );
8001 : :
8002 : 1 : }
8003 : :
8004 : 1 : void TestQgsGeometry::circle()
8005 : : {
8006 : : //test constructors
8007 : 1 : QgsCircle circ1;
8008 : 1 : QVERIFY( circ1.center().isEmpty() );
8009 : 1 : QCOMPARE( circ1.radius(), 0.0 );
8010 : 1 : QCOMPARE( circ1.azimuth(), 0.0 );
8011 : 1 : QVERIFY( circ1.isEmpty() );
8012 : :
8013 : 1 : QgsCircle circ2( QgsPoint( 5, 10 ), 3 );
8014 : 1 : QVERIFY( circ2.center() == QgsPoint( 5, 10 ) );
8015 : 1 : QCOMPARE( circ2.radius(), 3.0 );
8016 : 1 : QCOMPARE( circ2.azimuth(), 0.0 );
8017 : 1 : QVERIFY( !circ2.isEmpty() );
8018 : :
8019 : 1 : QgsCircle circ3( QgsPoint( 5, 10 ), 3, 45 );
8020 : 1 : QVERIFY( circ3.center() == QgsPoint( 5, 10 ) );
8021 : 1 : QCOMPARE( circ3.radius(), 3.0 );
8022 : 1 : QCOMPARE( circ3.azimuth(), 45.0 );
8023 : 1 : QVERIFY( !circ3.isEmpty() );
8024 : :
8025 : : //test toString
8026 : 1 : QCOMPARE( circ1.toString(), QString( "Empty" ) );
8027 : 1 : QCOMPARE( circ2.toString(), QString( "Circle (Center: Point (5 10), Radius: 3, Azimuth: 0)" ) );
8028 : 1 : QCOMPARE( circ3.toString(), QString( "Circle (Center: Point (5 10), Radius: 3, Azimuth: 45)" ) );
8029 : :
8030 : : //test equality operator
8031 : 1 : QCOMPARE( QgsCircle().isEmpty(), QgsCircle( QgsPoint(), 0, 0 ).isEmpty() );
8032 : 1 : QVERIFY( !( QgsCircle() == QgsCircle( QgsPoint( 0, 0 ), 0, 0.0005 ) ) );
8033 : 1 : QVERIFY( circ2 == QgsCircle( QgsPoint( 5, 10 ), 3, 0 ) );
8034 : 1 : QVERIFY( circ2 != circ3 );
8035 : :
8036 : : //test setter and getter
8037 : 1 : circ1.setAzimuth( 45 );
8038 : 1 : QCOMPARE( circ1.azimuth(), 45.0 );
8039 : :
8040 : 1 : circ1.setRadius( 50 );
8041 : 1 : QCOMPARE( circ1.radius(), 50.0 );
8042 : 1 : QCOMPARE( circ1.semiMajorAxis(), 50.0 );
8043 : 1 : QCOMPARE( circ1.semiMinorAxis(), 50.0 );
8044 : :
8045 : 1 : circ1.setSemiMajorAxis( 250 );
8046 : 1 : QCOMPARE( circ1.radius(), 250.0 );
8047 : 1 : QCOMPARE( circ1.semiMajorAxis(), 250.0 );
8048 : 1 : QCOMPARE( circ1.semiMinorAxis(), 250.0 );
8049 : :
8050 : 1 : circ1.setSemiMinorAxis( 8250 );
8051 : 1 : QCOMPARE( circ1.radius(), 8250.0 );
8052 : 1 : QCOMPARE( circ1.semiMajorAxis(), 8250.0 );
8053 : 1 : QCOMPARE( circ1.semiMinorAxis(), 8250.0 );
8054 : :
8055 : 1 : circ1.setCenter( QgsPoint( 5, 10 ) );
8056 : 1 : QVERIFY( circ1.center() == QgsPoint( 5, 10 ) );
8057 : 1 : QVERIFY( circ1.rcenter() == QgsPoint( 5, 10 ) );
8058 : 1 : circ1.rcenter() = QgsPoint( 25, 310 );
8059 : 1 : QVERIFY( circ1.center() == QgsPoint( 25, 310 ) );
8060 : :
8061 : : //test "alt" constructors
8062 : : // by2Points
8063 : 1 : QVERIFY( QgsCircle().from2Points( QgsPoint( -5, 0 ), QgsPoint( 5, 0 ) ) == QgsCircle( QgsPoint( 0, 0 ), 5, 90 ) );
8064 : 1 : QVERIFY( QgsCircle().from2Points( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ) ) == QgsCircle( QgsPoint( 0, 0 ), 5, 0 ) );
8065 : : // byExtent
8066 : 1 : QVERIFY( QgsCircle().fromExtent( QgsPoint( -5, -5 ), QgsPoint( 5, 5 ) ) == QgsCircle( QgsPoint( 0, 0 ), 5, 0 ) );
8067 : 1 : QVERIFY( QgsCircle().fromExtent( QgsPoint( -7.5, -2.5 ), QgsPoint( 2.5, 200.5 ) ).isEmpty() );
8068 : : // by3Points
8069 : 1 : QVERIFY( QgsCircle().from3Points( QgsPoint( -5, 0 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) ) == QgsCircle( QgsPoint( 0, 0 ), 5 ) );
8070 : 1 : QVERIFY( QgsCircle().from3Points( QgsPoint( 5, 0 ), QgsPoint( 6, 0 ), QgsPoint( 7, 0 ) ).isEmpty() );
8071 : : // byCenterDiameter
8072 : 1 : QVERIFY( QgsCircle().fromCenterDiameter( QgsPoint( 0, 0 ), 10 ) == QgsCircle( QgsPoint( 0, 0 ), 5, 0 ) );
8073 : 1 : QVERIFY( QgsCircle().fromCenterDiameter( QgsPoint( 2, 100 ), -10 ) == QgsCircle( QgsPoint( 2, 100 ), 5, 0 ) );
8074 : 1 : QVERIFY( QgsCircle().fromCenterDiameter( QgsPoint( 2, 100 ), -10, 45 ) == QgsCircle( QgsPoint( 2, 100 ), 5, 45 ) );
8075 : : // byCenterPoint
8076 : 1 : QVERIFY( QgsCircle().fromCenterPoint( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ) ) == QgsCircle( QgsPoint( 0, 0 ), 5, 90 ) );
8077 : 1 : QVERIFY( QgsCircle().fromCenterPoint( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ) ) == QgsCircle( QgsPoint( 0, 0 ), 5, 0 ) );
8078 : 1 : QVERIFY( QgsCircle().fromCenterPoint( QgsPoint( 0, 0 ), QgsPoint( 5 * std::cos( 45 * M_PI / 180.0 ), 5 * std::sin( 45 * M_PI / 180.0 ) ) ) == QgsCircle( QgsPoint( 0, 0 ), 5, 45 ) );
8079 : : // by3Tangents
8080 : : // Tangents from triangle tri1( 0,0 ; 0,5 ), tri2( 0,0 ; 5,0 ), tri3( 5,0 ; 0,5 )
8081 : 1 : QgsCircle circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 2, 0 ), QgsPoint( 3, 0 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
8082 : 1 : QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 1.4645 ), 0.0001 );
8083 : 1 : QGSCOMPARENEAR( circ_tgt.radius(), 1.4645, 0.0001 );
8084 : : // with parallels
8085 : 1 : circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
8086 : 1 : QVERIFY( circ_tgt.isEmpty() );
8087 : 1 : circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) );
8088 : 1 : QVERIFY( circ_tgt.isEmpty() );
8089 : 1 : circ_tgt = QgsCircle().from3Tangents( QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) );
8090 : 1 : QVERIFY( circ_tgt.isEmpty() );
8091 : : // with 2 parallels
8092 : 1 : const double epsilon = 1e-8;
8093 : 1 : circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ) );
8094 : 1 : QVERIFY( circ_tgt.isEmpty() );
8095 : 1 : circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ), epsilon, QgsPoint( 2, 0 ) );
8096 : 1 : QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 2.5000 ), 0.0001 );
8097 : 1 : QGSCOMPARENEAR( circ_tgt.radius(), 2.5, 0.0001 );
8098 : 1 : circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ), epsilon, QgsPoint( 3, 0 ) );
8099 : 1 : QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 8.5355, 2.5000 ), 0.0001 );
8100 : 1 : QGSCOMPARENEAR( circ_tgt.radius(), 2.5, 0.0001 );
8101 : : // from3tangentsMulti
8102 : 1 : QVector<QgsCircle> circles_tgt;
8103 : 1 : circles_tgt = QgsCircle().from3TangentsMulti( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ) );
8104 : 1 : QCOMPARE( circles_tgt.count(), 2 );
8105 : 1 : circ_tgt = circles_tgt.at( 0 );
8106 : 1 : QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 8.5355, 2.5000 ), 0.0001 );
8107 : 1 : QGSCOMPARENEAR( circ_tgt.radius(), 2.5, 0.0001 );
8108 : 1 : circ_tgt = circles_tgt.at( 1 );
8109 : 1 : QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 2.5000 ), 0.0001 );
8110 : 1 : QGSCOMPARENEAR( circ_tgt.radius(), 2.5, 0.0001 );
8111 : 1 : circles_tgt = QgsCircle().from3TangentsMulti( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ), epsilon, QgsPoint( 2, 0 ) );
8112 : 1 : QCOMPARE( circles_tgt.count(), 1 );
8113 : 1 : circ_tgt = circles_tgt.at( 0 );
8114 : 1 : QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 2.5000 ), 0.0001 );
8115 : 1 : QGSCOMPARENEAR( circ_tgt.radius(), 2.5, 0.0001 );
8116 : 1 : circles_tgt = QgsCircle().from3TangentsMulti( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 2.5, 0 ), QgsPoint( 7.5, 5 ), epsilon, QgsPoint( 3, 0 ) );
8117 : 1 : QCOMPARE( circles_tgt.count(), 1 );
8118 : 1 : circles_tgt = QgsCircle().from3TangentsMulti( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), QgsPoint( 5, 5 ), QgsPoint( 10, 5 ), QgsPoint( 15, 5 ), QgsPoint( 20, 5 ) );
8119 : 1 : QVERIFY( circles_tgt.isEmpty() );
8120 : : // check that Z dimension is ignored in case of using tangents
8121 : 1 : QgsCircle circ_tgt_z = QgsCircle().from3Tangents( QgsPoint( 0, 0, 333 ), QgsPoint( 0, 1, 1 ), QgsPoint( 2, 0, 2 ), QgsPoint( 3, 0, 3 ), QgsPoint( 5, 0, 4 ), QgsPoint( 0, 5, 5 ) );
8122 : 1 : QCOMPARE( circ_tgt_z.center().is3D(), false );
8123 : :
8124 : : // minimalCircleFrom3points
8125 : 1 : QgsCircle minCircle3Points = QgsCircle().minimalCircleFrom3Points( QgsPoint( 0, 5 ), QgsPoint( 0, -5 ), QgsPoint( 1, 2 ) );
8126 : 1 : QGSCOMPARENEARPOINT( minCircle3Points.center(), QgsPoint( 0, 0 ), 0.0001 );
8127 : 1 : QGSCOMPARENEAR( minCircle3Points.radius(), 5.0, 0.0001 );
8128 : 1 : minCircle3Points = QgsCircle().minimalCircleFrom3Points( QgsPoint( 0, 5 ), QgsPoint( 5, 0 ), QgsPoint( -5, 0 ) );
8129 : 1 : QGSCOMPARENEARPOINT( minCircle3Points.center(), QgsPoint( 0, 0 ), 0.0001 );
8130 : 1 : QGSCOMPARENEAR( minCircle3Points.radius(), 5.0, 0.0001 );
8131 : :
8132 : :
8133 : :
8134 : : // test quadrant
8135 : 1 : QgsPointSequence quad = QgsCircle( QgsPoint( 0, 0 ), 5 ).northQuadrant();
8136 : 1 : QVERIFY( quad.at( 0 ) == QgsPoint( 0, 5 ) );
8137 : 1 : QVERIFY( quad.at( 1 ) == QgsPoint( 5, 0 ) );
8138 : 1 : QVERIFY( quad.at( 2 ) == QgsPoint( 0, -5 ) );
8139 : 1 : QVERIFY( quad.at( 3 ) == QgsPoint( -5, 0 ) );
8140 : :
8141 : 1 : quad = QgsCircle( QgsPoint( 0, 0 ), 5, 123 ).northQuadrant();
8142 : 1 : QVERIFY( quad.at( 0 ) == QgsPoint( 0, 5 ) );
8143 : 1 : QVERIFY( quad.at( 1 ) == QgsPoint( 5, 0 ) );
8144 : 1 : QVERIFY( quad.at( 2 ) == QgsPoint( 0, -5 ) );
8145 : 1 : QVERIFY( quad.at( 3 ) == QgsPoint( -5, 0 ) );
8146 : :
8147 : 1 : quad = QgsCircle( QgsPoint( 0, 0 ), 5, 456 ).northQuadrant();
8148 : 1 : QVERIFY( quad.at( 0 ) == QgsPoint( 0, 5 ) );
8149 : 1 : QVERIFY( quad.at( 1 ) == QgsPoint( 5, 0 ) );
8150 : 1 : QVERIFY( quad.at( 2 ) == QgsPoint( 0, -5 ) );
8151 : 1 : QVERIFY( quad.at( 3 ) == QgsPoint( -5, 0 ) );
8152 : :
8153 : 1 : quad = QgsCircle( QgsPoint( 0, 0 ), 5, -789l ).northQuadrant();
8154 : 1 : QVERIFY( quad.at( 0 ) == QgsPoint( 0, 5 ) );
8155 : 1 : QVERIFY( quad.at( 1 ) == QgsPoint( 5, 0 ) );
8156 : 1 : QVERIFY( quad.at( 2 ) == QgsPoint( 0, -5 ) );
8157 : 1 : QVERIFY( quad.at( 3 ) == QgsPoint( -5, 0 ) );
8158 : :
8159 : :
8160 : : //test conversion
8161 : 1 : QgsPointSequence ptsPol;
8162 : 1 : std::unique_ptr< QgsPolygon > pol( new QgsPolygon() );
8163 : : // polygon
8164 : 1 : pol.reset( QgsCircle( QgsPoint( 0, 0 ), 5 ).toPolygon( 4 ) );
8165 : 1 : QCOMPARE( pol->numInteriorRings(), 0 );
8166 : 1 : QCOMPARE( pol->exteriorRing()->numPoints(), 5 );
8167 : :
8168 : 1 : pol->exteriorRing()->points( ptsPol );
8169 : 1 : QCOMPARE( ptsPol.length(), 5 );
8170 : 1 : QVERIFY( ptsPol.at( 0 ) == QgsPoint( 0, 5 ) );
8171 : 1 : QVERIFY( ptsPol.at( 1 ) == QgsPoint( 5, 0 ) );
8172 : 1 : QVERIFY( ptsPol.at( 2 ) == QgsPoint( 0, -5 ) );
8173 : 1 : QVERIFY( ptsPol.at( 3 ) == QgsPoint( -5, 0 ) );
8174 : 1 : QVERIFY( ptsPol.at( 4 ) == QgsPoint( 0, 5 ) );
8175 : :
8176 : : // oriented
8177 : : //45
8178 : 1 : double val = 5 * std::sin( M_PI / 4 );
8179 : 1 : pol.reset( QgsCircle( QgsPoint( 0, 0 ), 5, 45 ).toPolygon( 4 ) );
8180 : 1 : QCOMPARE( pol->numInteriorRings(), 0 );
8181 : 1 : QCOMPARE( pol->exteriorRing()->numPoints(), 5 );
8182 : 1 : pol->exteriorRing()->points( ptsPol );
8183 : 1 : QCOMPARE( ptsPol.length(), 5 );
8184 : 1 : QVERIFY( ptsPol.at( 0 ) == QgsPoint( val, val ) );
8185 : 1 : QVERIFY( ptsPol.at( 1 ) == QgsPoint( val, -val ) );
8186 : 1 : QVERIFY( ptsPol.at( 2 ) == QgsPoint( -val, -val ) );
8187 : 1 : QVERIFY( ptsPol.at( 3 ) == QgsPoint( -val, val ) );
8188 : 1 : QVERIFY( ptsPol.at( 4 ) == QgsPoint( val, val ) );
8189 : : //135
8190 : 1 : pol.reset( QgsCircle( QgsPoint( 0, 0 ), 5, 135 ).toPolygon( 4 ) );
8191 : 1 : QCOMPARE( pol->numInteriorRings(), 0 );
8192 : 1 : QCOMPARE( pol->exteriorRing()->numPoints(), 5 );
8193 : 1 : pol->exteriorRing()->points( ptsPol );
8194 : 1 : QCOMPARE( ptsPol.length(), 5 );
8195 : 1 : QVERIFY( ptsPol.at( 0 ) == QgsPoint( val, -val ) );
8196 : 1 : QVERIFY( ptsPol.at( 1 ) == QgsPoint( -val, -val ) );
8197 : 1 : QVERIFY( ptsPol.at( 2 ) == QgsPoint( -val, val ) );
8198 : 1 : QVERIFY( ptsPol.at( 3 ) == QgsPoint( val, val ) );
8199 : 1 : QVERIFY( ptsPol.at( 4 ) == QgsPoint( val, -val ) );
8200 : : //225
8201 : 1 : pol.reset( QgsCircle( QgsPoint( 0, 0 ), 5, 225 ).toPolygon( 4 ) );
8202 : 1 : QCOMPARE( pol->numInteriorRings(), 0 );
8203 : 1 : QCOMPARE( pol->exteriorRing()->numPoints(), 5 );
8204 : 1 : pol->exteriorRing()->points( ptsPol );
8205 : 1 : QCOMPARE( ptsPol.length(), 5 );
8206 : 1 : QVERIFY( ptsPol.at( 0 ) == QgsPoint( -val, -val ) );
8207 : 1 : QVERIFY( ptsPol.at( 1 ) == QgsPoint( -val, val ) );
8208 : 1 : QVERIFY( ptsPol.at( 2 ) == QgsPoint( val, val ) );
8209 : 1 : QVERIFY( ptsPol.at( 3 ) == QgsPoint( val, -val ) );
8210 : 1 : QVERIFY( ptsPol.at( 4 ) == QgsPoint( -val, -val ) );
8211 : : //315
8212 : 1 : pol.reset( QgsCircle( QgsPoint( 0, 0 ), 5, 315 ).toPolygon( 4 ) );
8213 : 1 : QCOMPARE( pol->numInteriorRings(), 0 );
8214 : 1 : QCOMPARE( pol->exteriorRing()->numPoints(), 5 );
8215 : 1 : pol->exteriorRing()->points( ptsPol );
8216 : 1 : QCOMPARE( ptsPol.length(), 5 );
8217 : 1 : QVERIFY( ptsPol.at( 0 ) == QgsPoint( -val, val ) );
8218 : 1 : QVERIFY( ptsPol.at( 1 ) == QgsPoint( val, val ) );
8219 : 1 : QVERIFY( ptsPol.at( 2 ) == QgsPoint( val, -val ) );
8220 : 1 : QVERIFY( ptsPol.at( 3 ) == QgsPoint( -val, -val ) );
8221 : 1 : QVERIFY( ptsPol.at( 4 ) == QgsPoint( -val, val ) );
8222 : :
8223 : : // circular arc
8224 : 1 : std::unique_ptr< QgsCircularString > cs( QgsCircle( QgsPoint( 0, 0 ), 5 ).toCircularString() );
8225 : 1 : QCOMPARE( cs->asWkt( 2 ), QString( "CircularString (0 5, 5 0, 0 -5, -5 0, 0 5)" ) );
8226 : 1 : cs.reset( QgsCircle( QgsPoint( 0, 0 ), 5 ).toCircularString( true ) );
8227 : 1 : QCOMPARE( cs->asWkt( 2 ), QString( "CircularString (0 5, 5 0, 0 -5, -5 0, 0 5)" ) );
8228 : 1 : cs.reset( QgsCircle( QgsPoint( 0, 0 ), 5, 315 ).toCircularString() );
8229 : 1 : QCOMPARE( cs->asWkt( 2 ), QString( "CircularString (0 5, 5 0, 0 -5, -5 0, 0 5)" ) );
8230 : 1 : cs.reset( QgsCircle( QgsPoint( 0, 0 ), 5, 315 ).toCircularString( true ) );
8231 : 1 : QCOMPARE( cs->asWkt( 2 ), QString( "CircularString (-3.54 3.54, 3.54 3.54, 3.54 -3.54, -3.54 -3.54, -3.54 3.54)" ) );
8232 : :
8233 : : // bounding box
8234 : 1 : QVERIFY( QgsRectangle( QgsPointXY( -2.5, -2.5 ), QgsPointXY( 2.5, 2.5 ) ) == QgsCircle( QgsPoint( 0, 0 ), 2.5, 0 ).boundingBox() );
8235 : 1 : QVERIFY( QgsRectangle( QgsPointXY( -2.5, -2.5 ), QgsPointXY( 2.5, 2.5 ) ) == QgsCircle( QgsPoint( 0, 0 ), 2.5, 45 ).boundingBox() );
8236 : :
8237 : : // area
8238 : 1 : QGSCOMPARENEAR( 314.1593, QgsCircle( QgsPoint( 0, 0 ), 10 ).area(), 0.0001 );
8239 : : // perimeter
8240 : 1 : QGSCOMPARENEAR( 31.4159, QgsCircle( QgsPoint( 0, 0 ), 5 ).perimeter(), 0.0001 );
8241 : :
8242 : : // contains
8243 : 1 : QgsPoint pc;
8244 : 1 : pc = QgsPoint( 1, 1 );
8245 : 1 : QVERIFY( QgsCircle( QgsPoint( 0, 0 ), 5 ).contains( pc ) );
8246 : 1 : pc = QgsPoint( 0, 5 );
8247 : 1 : QVERIFY( QgsCircle( QgsPoint( 0, 0 ), 5 ).contains( pc ) );
8248 : 1 : pc = QgsPoint( 6, 1 );
8249 : 1 : QVERIFY( !QgsCircle( QgsPoint( 0, 0 ), 5 ).contains( pc ) );
8250 : :
8251 : : // intersections
8252 : 1 : QgsCircle ci1( QgsPoint( 0, 0 ), 1 );
8253 : 1 : QgsPoint int1;
8254 : 1 : QgsPoint int2;
8255 : 1 : QCOMPARE( ci1.intersections( QgsCircle( QgsPoint( 2, 0 ), 0.5 ), int1, int2 ), 0 );
8256 : 1 : QCOMPARE( ci1.intersections( QgsCircle( QgsPoint( 0.5, 0.1 ), 0.2 ), int1, int2 ), 0 );
8257 : : // one intersection
8258 : 1 : QCOMPARE( ci1.intersections( QgsCircle( QgsPoint( 3, 0 ), 2 ), int1, int2 ), 1 );
8259 : 1 : QCOMPARE( int1, QgsPoint( 1, 0 ) );
8260 : 1 : QCOMPARE( int2, QgsPoint( 1, 0 ) );
8261 : : // two intersections
8262 : 1 : ci1 = QgsCircle( QgsPoint( 5, 3 ), 2 );
8263 : 1 : QCOMPARE( ci1.intersections( QgsCircle( QgsPoint( 7, -1 ), 4 ), int1, int2 ), 2 );
8264 : 1 : QCOMPARE( int1.wkbType(), QgsWkbTypes::Point );
8265 : 1 : QGSCOMPARENEAR( int1.x(), 3.8, 0.001 );
8266 : 1 : QGSCOMPARENEAR( int1.y(), 1.4, 0.001 );
8267 : 1 : QCOMPARE( int2.wkbType(), QgsWkbTypes::Point );
8268 : 1 : QGSCOMPARENEAR( int2.x(), 7.0, 0.001 );
8269 : 1 : QGSCOMPARENEAR( int2.y(), 3.0, 0.001 );
8270 : : // with z
8271 : 1 : ci1 = QgsCircle( QgsPoint( 5, 3, 11 ), 2 );
8272 : 1 : QCOMPARE( ci1.intersections( QgsCircle( QgsPoint( 7, -1, 5 ), 4 ), int1, int2, true ), 0 );
8273 : 1 : QCOMPARE( ci1.intersections( QgsCircle( QgsPoint( 7, -1, 11 ), 4 ), int1, int2, true ), 2 );
8274 : 1 : QCOMPARE( int1.wkbType(), QgsWkbTypes::PointZ );
8275 : 1 : QGSCOMPARENEAR( int1.x(), 3.8, 0.001 );
8276 : 1 : QGSCOMPARENEAR( int1.y(), 1.4, 0.001 );
8277 : 1 : QGSCOMPARENEAR( int1.z(), 11.0, 0.001 );
8278 : 1 : QCOMPARE( int2.wkbType(), QgsWkbTypes::PointZ );
8279 : 1 : QGSCOMPARENEAR( int2.x(), 7.0, 0.001 );
8280 : 1 : QGSCOMPARENEAR( int2.y(), 3.0, 0.001 );
8281 : 1 : QGSCOMPARENEAR( int2.z(), 11.0, 0.001 );
8282 : :
8283 : : // tangent to point
8284 : 1 : QgsPointXY t1;
8285 : 1 : QgsPointXY t2;
8286 : 1 : QVERIFY( !QgsCircle( QgsPoint( 1, 2 ), 4 ).tangentToPoint( QgsPointXY( 1, 2 ), t1, t2 ) );
8287 : 1 : QVERIFY( QgsCircle( QgsPoint( 1, 2 ), 4 ).tangentToPoint( QgsPointXY( 8, 4 ), t1, t2 ) );
8288 : 1 : QGSCOMPARENEAR( t1.x(), 4.03, 0.01 );
8289 : 1 : QGSCOMPARENEAR( t1.y(), -0.61, 0.01 );
8290 : 1 : QGSCOMPARENEAR( t2.x(), 2.2, 0.01 );
8291 : 1 : QGSCOMPARENEAR( t2.y(), 5.82, 0.01 );
8292 : :
8293 : : // two outer circle tangents
8294 : 1 : QgsPointXY l1p1, l1p2, l2p1, l2p2;
8295 : 1 : QCOMPARE( QgsCircle( QgsPoint( 1, 2 ), 4 ).outerTangents( QgsCircle( QgsPoint( 2, 3 ), 1 ), l1p1, l1p2, l2p1, l2p2 ), 0 );
8296 : 1 : QCOMPARE( QgsCircle( QgsPoint( 1, 2 ), 1 ).outerTangents( QgsCircle( QgsPoint( 10, 3 ), 4 ), l1p1, l1p2, l2p1, l2p2 ), 2 );
8297 : 1 : QGSCOMPARENEAR( l1p1.x(), 0.566, 0.01 );
8298 : 1 : QGSCOMPARENEAR( l1p1.y(), 2.901, 0.01 );
8299 : 1 : QGSCOMPARENEAR( l1p2.x(), 8.266, 0.01 );
8300 : 1 : QGSCOMPARENEAR( l1p2.y(), 6.604, 0.01 );
8301 : 1 : QGSCOMPARENEAR( l2p1.x(), 0.7749, 0.01 );
8302 : 1 : QGSCOMPARENEAR( l2p1.y(), 1.025, 0.01 );
8303 : 1 : QGSCOMPARENEAR( l2p2.x(), 9.099, 0.01 );
8304 : 1 : QGSCOMPARENEAR( l2p2.y(), -0.897, 0.01 );
8305 : :
8306 : : // two inner circle tangents
8307 : 1 : QCOMPARE( QgsCircle( QgsPoint( 1, 2 ), 4 ).innerTangents( QgsCircle( QgsPoint( 2, 3 ), 1 ), l1p1, l1p2, l2p1, l2p2 ), 0 );
8308 : 1 : QCOMPARE( QgsCircle( QgsPoint( 0, 0 ), 4 ).innerTangents( QgsCircle( QgsPoint( 8, 0 ), 5 ), l1p1, l1p2, l2p1, l2p2 ), 0 );
8309 : 1 : QCOMPARE( QgsCircle( QgsPoint( 0, 0 ), 4 ).innerTangents( QgsCircle( QgsPoint( 8, 0 ), 4 ), l1p1, l1p2, l2p1, l2p2 ), 0 );
8310 : 1 : QCOMPARE( QgsCircle( QgsPoint( 1, 2 ), 1 ).innerTangents( QgsCircle( QgsPoint( 10, 3 ), 4 ), l1p1, l1p2, l2p1, l2p2 ), 2 );
8311 : 1 : QGSCOMPARENEAR( l1p1.x(), 7.437, 0.01 );
8312 : 1 : QGSCOMPARENEAR( l1p1.y(), 6.071, 0.01 );
8313 : 1 : QGSCOMPARENEAR( l1p2.x(), 1.641, 0.01 );
8314 : 1 : QGSCOMPARENEAR( l1p2.y(), 1.232, 0.01 );
8315 : 1 : QGSCOMPARENEAR( l2p1.x(), 8.173, 0.01 );
8316 : 1 : QGSCOMPARENEAR( l2p1.y(), -0.558, 0.01 );
8317 : 1 : QGSCOMPARENEAR( l2p2.x(), 1.457, 0.01 );
8318 : 1 : QGSCOMPARENEAR( l2p2.y(), 2.89, 0.01 );
8319 : :
8320 : : // asGML3
8321 : 1 : QgsCircle exportCircle( QgsPoint( 1, 1 ), 3 );
8322 : 1 : QDomDocument doc( "gml" );
8323 : 2 : QString expectedGML3( QStringLiteral( "<Circle xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1 4 4 1 1 -2</posList></Circle>" ) );
8324 : 3 : QGSCOMPAREGML( elemToString( exportCircle.asGml3( doc ) ), expectedGML3 );
8325 : : // asGML2
8326 : 2 : QString expectedGML2( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1,4 1.05,4 1.1,4 1.16,4 1.21,3.99 1.26,3.99 1.31,3.98 1.37,3.98 1.42,3.97 1.47,3.96 1.52,3.95 1.57,3.94 1.62,3.93 1.67,3.92 1.73,3.91 1.78,3.9 1.83,3.88 1.88,3.87 1.93,3.85 1.98,3.84 2.03,3.82 2.08,3.8 2.12,3.78 2.17,3.76 2.22,3.74 2.27,3.72 2.32,3.7 2.36,3.67 2.41,3.65 2.45,3.62 2.5,3.6 2.55,3.57 2.59,3.54 2.63,3.52 2.68,3.49 2.72,3.46 2.76,3.43 2.81,3.4 2.85,3.36 2.89,3.33 2.93,3.3 2.97,3.26 3.01,3.23 3.05,3.19 3.08,3.16 3.12,3.12 3.16,3.08 3.19,3.05 3.23,3.01 3.26,2.97 3.3,2.93 3.33,2.89 3.36,2.85 3.4,2.81 3.43,2.76 3.46,2.72 3.49,2.68 3.52,2.63 3.54,2.59 3.57,2.55 3.6,2.5 3.62,2.45 3.65,2.41 3.67,2.36 3.7,2.32 3.72,2.27 3.74,2.22 3.76,2.17 3.78,2.12 3.8,2.08 3.82,2.03 3.84,1.98 3.85,1.93 3.87,1.88 3.88,1.83 3.9,1.78 3.91,1.73 3.92,1.67 3.93,1.62 3.94,1.57 3.95,1.52 3.96,1.47 3.97,1.42 3.98,1.37 3.98,1.31 3.99,1.26 3.99,1.21 4,1.16 4,1.1 4,1.05 4,1 4,0.95 4,0.9 4,0.84 3.99,0.79 3.99,0.74 3.98,0.69 3.98,0.63 3.97,0.58 3.96,0.53 3.95,0.48 3.94,0.43 3.93,0.38 3.92,0.33 3.91,0.27 3.9,0.22 3.88,0.17 3.87,0.12 3.85,0.07 3.84,0.02 3.82,-0.03 3.8,-0.08 3.78,-0.12 3.76,-0.17 3.74,-0.22 3.72,-0.27 3.7,-0.32 3.67,-0.36 3.65,-0.41 3.62,-0.45 3.6,-0.5 3.57,-0.55 3.54,-0.59 3.52,-0.63 3.49,-0.68 3.46,-0.72 3.43,-0.76 3.4,-0.81 3.36,-0.85 3.33,-0.89 3.3,-0.93 3.26,-0.97 3.23,-1.01 3.19,-1.05 3.16,-1.08 3.12,-1.12 3.08,-1.16 3.05,-1.19 3.01,-1.23 2.97,-1.26 2.93,-1.3 2.89,-1.33 2.85,-1.36 2.81,-1.4 2.76,-1.43 2.72,-1.46 2.68,-1.49 2.63,-1.52 2.59,-1.54 2.55,-1.57 2.5,-1.6 2.45,-1.62 2.41,-1.65 2.36,-1.67 2.32,-1.7 2.27,-1.72 2.22,-1.74 2.17,-1.76 2.12,-1.78 2.08,-1.8 2.03,-1.82 1.98,-1.84 1.93,-1.85 1.88,-1.87 1.83,-1.88 1.78,-1.9 1.73,-1.91 1.67,-1.92 1.62,-1.93 1.57,-1.94 1.52,-1.95 1.47,-1.96 1.42,-1.97 1.37,-1.98 1.31,-1.98 1.26,-1.99 1.21,-1.99 1.16,-2 1.1,-2 1.05,-2 1,-2 0.95,-2 0.9,-2 0.84,-2 0.79,-1.99 0.74,-1.99 0.69,-1.98 0.63,-1.98 0.58,-1.97 0.53,-1.96 0.48,-1.95 0.43,-1.94 0.38,-1.93 0.33,-1.92 0.27,-1.91 0.22,-1.9 0.17,-1.88 0.12,-1.87 0.07,-1.85 0.02,-1.84 -0.03,-1.82 -0.08,-1.8 -0.12,-1.78 -0.17,-1.76 -0.22,-1.74 -0.27,-1.72 -0.32,-1.7 -0.36,-1.67 -0.41,-1.65 -0.45,-1.62 -0.5,-1.6 -0.55,-1.57 -0.59,-1.54 -0.63,-1.52 -0.68,-1.49 -0.72,-1.46 -0.76,-1.43 -0.81,-1.4 -0.85,-1.36 -0.89,-1.33 -0.93,-1.3 -0.97,-1.26 -1.01,-1.23 -1.05,-1.19 -1.08,-1.16 -1.12,-1.12 -1.16,-1.08 -1.19,-1.05 -1.23,-1.01 -1.26,-0.97 -1.3,-0.93 -1.33,-0.89 -1.36,-0.85 -1.4,-0.81 -1.43,-0.76 -1.46,-0.72 -1.49,-0.68 -1.52,-0.63 -1.54,-0.59 -1.57,-0.55 -1.6,-0.5 -1.62,-0.45 -1.65,-0.41 -1.67,-0.36 -1.7,-0.32 -1.72,-0.27 -1.74,-0.22 -1.76,-0.17 -1.78,-0.12 -1.8,-0.08 -1.82,-0.03 -1.84,0.02 -1.85,0.07 -1.87,0.12 -1.88,0.17 -1.9,0.22 -1.91,0.27 -1.92,0.33 -1.93,0.38 -1.94,0.43 -1.95,0.48 -1.96,0.53 -1.97,0.58 -1.98,0.63 -1.98,0.69 -1.99,0.74 -1.99,0.79 -2,0.84 -2,0.9 -2,0.95 -2,1 -2,1.05 -2,1.1 -2,1.16 -1.99,1.21 -1.99,1.26 -1.98,1.31 -1.98,1.37 -1.97,1.42 -1.96,1.47 -1.95,1.52 -1.94,1.57 -1.93,1.62 -1.92,1.67 -1.91,1.73 -1.9,1.78 -1.88,1.83 -1.87,1.88 -1.85,1.93 -1.84,1.98 -1.82,2.03 -1.8,2.08 -1.78,2.12 -1.76,2.17 -1.74,2.22 -1.72,2.27 -1.7,2.32 -1.67,2.36 -1.65,2.41 -1.62,2.45 -1.6,2.5 -1.57,2.55 -1.54,2.59 -1.52,2.63 -1.49,2.68 -1.46,2.72 -1.43,2.76 -1.4,2.81 -1.36,2.85 -1.33,2.89 -1.3,2.93 -1.26,2.97 -1.23,3.01 -1.19,3.05 -1.16,3.08 -1.12,3.12 -1.08,3.16 -1.05,3.19 -1.01,3.23 -0.97,3.26 -0.93,3.3 -0.89,3.33 -0.85,3.36 -0.81,3.4 -0.76,3.43 -0.72,3.46 -0.68,3.49 -0.63,3.52 -0.59,3.54 -0.55,3.57 -0.5,3.6 -0.45,3.62 -0.41,3.65 -0.36,3.67 -0.32,3.7 -0.27,3.72 -0.22,3.74 -0.17,3.76 -0.12,3.78 -0.08,3.8 -0.03,3.82 0.02,3.84 0.07,3.85 0.12,3.87 0.17,3.88 0.22,3.9 0.27,3.91 0.33,3.92 0.38,3.93 0.43,3.94 0.48,3.95 0.53,3.96 0.58,3.97 0.63,3.98 0.69,3.98 0.74,3.99 0.79,3.99 0.84,4 0.9,4 0.95,4 1,4</coordinates></LineString>" ) );
8327 : 3 : QGSCOMPAREGML( elemToString( exportCircle.asGml2( doc, 2 ) ), expectedGML2 );
8328 : 1 : }
8329 : :
8330 : 1 : void TestQgsGeometry::quadrilateral()
8331 : : {
8332 : :
8333 : : // default
8334 : 1 : QgsQuadrilateral quad_init;
8335 : 1 : QgsPointSequence pts = quad_init.points();
8336 : 1 : QVERIFY( pts.at( 0 ).isEmpty() );
8337 : 1 : QVERIFY( pts.at( 1 ).isEmpty() );
8338 : 1 : QVERIFY( pts.at( 2 ).isEmpty() );
8339 : 1 : QVERIFY( pts.at( 3 ).isEmpty() );
8340 : 1 : QVERIFY( !quad_init.isValid() );
8341 : :
8342 : : // colinear
8343 : 1 : QgsQuadrilateral quad4points_col( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 10 ), QgsPoint( 10, 10 ) );
8344 : 1 : QVERIFY( !quad4points_col.isValid() );
8345 : 1 : pts = quad4points_col.points();
8346 : 1 : QVERIFY( pts.at( 0 ).isEmpty() );
8347 : 1 : QVERIFY( pts.at( 1 ).isEmpty() );
8348 : 1 : QVERIFY( pts.at( 2 ).isEmpty() );
8349 : 1 : QVERIFY( pts.at( 3 ).isEmpty() );
8350 : :
8351 : :
8352 : 1 : QgsQuadrilateral quad4pointsXY_col( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 10 ), QgsPoint( 10, 10 ) );
8353 : 1 : QVERIFY( !quad4pointsXY_col.isValid() );
8354 : 1 : pts = quad4pointsXY_col.points();
8355 : 1 : QVERIFY( pts.at( 0 ).isEmpty() );
8356 : 1 : QVERIFY( pts.at( 1 ).isEmpty() );
8357 : 1 : QVERIFY( pts.at( 2 ).isEmpty() );
8358 : 1 : QVERIFY( pts.at( 3 ).isEmpty() );
8359 : :
8360 : :
8361 : : // anti parallelogram
8362 : 1 : QgsQuadrilateral quad4points_anti( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
8363 : 1 : QVERIFY( !quad4points_anti.isValid() );
8364 : 1 : pts = quad4points_anti.points();
8365 : 1 : QVERIFY( pts.at( 0 ).isEmpty() );
8366 : 1 : QVERIFY( pts.at( 1 ).isEmpty() );
8367 : 1 : QVERIFY( pts.at( 2 ).isEmpty() );
8368 : 1 : QVERIFY( pts.at( 3 ).isEmpty() );
8369 : :
8370 : :
8371 : 1 : QgsQuadrilateral quad4pointsXY_anti( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) );
8372 : 1 : QVERIFY( !quad4pointsXY_anti.isValid() );
8373 : 1 : pts = quad4pointsXY_anti.points();
8374 : 1 : QVERIFY( pts.at( 0 ).isEmpty() );
8375 : 1 : QVERIFY( pts.at( 1 ).isEmpty() );
8376 : 1 : QVERIFY( pts.at( 2 ).isEmpty() );
8377 : 1 : QVERIFY( pts.at( 3 ).isEmpty() );
8378 : :
8379 : : // valid
8380 : 1 : QgsQuadrilateral quad4points_valid( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8381 : 1 : QVERIFY( quad4points_valid.isValid() );
8382 : 1 : pts = quad4points_valid.points();
8383 : 1 : QCOMPARE( pts.at( 0 ), QgsPoint( 0, 0 ) );
8384 : 1 : QCOMPARE( pts.at( 1 ), QgsPoint( 0, 5 ) );
8385 : 1 : QCOMPARE( pts.at( 2 ), QgsPoint( 5, 5 ) );
8386 : 1 : QCOMPARE( pts.at( 3 ), QgsPoint( 5, 0 ) );
8387 : :
8388 : : // setPoint
8389 : 1 : QVERIFY( quad4points_valid.setPoint( QgsPoint( -1, -1 ), QgsQuadrilateral::Point1 ) );
8390 : 1 : QVERIFY( quad4points_valid.setPoint( QgsPoint( -1, 6 ), QgsQuadrilateral::Point2 ) );
8391 : 1 : QVERIFY( quad4points_valid.setPoint( QgsPoint( 6, 6 ), QgsQuadrilateral::Point3 ) );
8392 : 1 : QVERIFY( quad4points_valid.setPoint( QgsPoint( 6, -1 ), QgsQuadrilateral::Point4 ) );
8393 : 1 : QVERIFY( quad4points_valid.isValid() );
8394 : 1 : pts = quad4points_valid.points();
8395 : 1 : QCOMPARE( pts.at( 0 ), QgsPoint( -1, -1 ) );
8396 : 1 : QCOMPARE( pts.at( 1 ), QgsPoint( -1, 6 ) );
8397 : 1 : QCOMPARE( pts.at( 2 ), QgsPoint( 6, 6 ) );
8398 : 1 : QCOMPARE( pts.at( 3 ), QgsPoint( 6, -1 ) );
8399 : :
8400 : : // invalid: must have same type
8401 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -1, -1, 10 ), QgsQuadrilateral::Point1 ) );
8402 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -1, 6, 10 ), QgsQuadrilateral::Point2 ) );
8403 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 6, 6, 10 ), QgsQuadrilateral::Point3 ) );
8404 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 6, -1, 10 ), QgsQuadrilateral::Point4 ) );
8405 : :
8406 : : // invalid self-intersection
8407 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 7, 3 ), QgsQuadrilateral::Point1 ) );
8408 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 3, 7 ), QgsQuadrilateral::Point1 ) );
8409 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 3, -7 ), QgsQuadrilateral::Point2 ) );
8410 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 7, 3 ), QgsQuadrilateral::Point2 ) );
8411 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 3, -7 ), QgsQuadrilateral::Point3 ) );
8412 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -7, 3 ), QgsQuadrilateral::Point3 ) );
8413 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 3, 7 ), QgsQuadrilateral::Point4 ) );
8414 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -7, 3 ), QgsQuadrilateral::Point4 ) );
8415 : :
8416 : : // invalid colinear
8417 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 6, -2 ), QgsQuadrilateral::Point1 ) );
8418 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -2, 6 ), QgsQuadrilateral::Point1 ) );
8419 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 6, 7 ), QgsQuadrilateral::Point2 ) );
8420 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -2, -1 ), QgsQuadrilateral::Point2 ) );
8421 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 7, -1 ), QgsQuadrilateral::Point3 ) );
8422 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -1, 7 ), QgsQuadrilateral::Point3 ) );
8423 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( -1, -2 ), QgsQuadrilateral::Point4 ) );
8424 : 1 : QVERIFY( !quad4points_valid.setPoint( QgsPoint( 7, 6 ), QgsQuadrilateral::Point4 ) );
8425 : :
8426 : : //equals
8427 : 1 : QVERIFY( QgsQuadrilateral( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) ) !=
8428 : : QgsQuadrilateral( QgsPoint( 0.01, 0.01 ), QgsPoint( 0.01, 5.01 ), QgsPoint( 5.01, 5.01 ), QgsPoint( 5.01, 0.01 ) ) );
8429 : 1 : QVERIFY( QgsQuadrilateral( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) ).equals(
8430 : : QgsQuadrilateral( QgsPoint( 0.01, 0.01 ), QgsPoint( 0.01, 5.01 ), QgsPoint( 5.01, 5.01 ), QgsPoint( 5.01, 0.01 ) ), 1e-1 ) );
8431 : 1 : QVERIFY( QgsQuadrilateral( QgsPoint( 0, 0, 0 ), QgsPoint( 0, 5, -0.02 ), QgsPoint( 5, 5, 0 ), QgsPoint( 5, 0, -0.02 ) ).equals(
8432 : : QgsQuadrilateral( QgsPoint( 0.01, 0.01, 0.01 ), QgsPoint( 0.01, 5.01, 0 ), QgsPoint( 5.01, 5.01, -0.01 ), QgsPoint( 5.01, 0.01, 0.04 ) ), 1e-1 ) );
8433 : :
8434 : : // rectangleFromExtent
8435 : 1 : QgsQuadrilateral rectangleFromExtent( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8436 : 1 : QgsQuadrilateral rectangleFromExtentZ( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 5, 10 ), QgsPoint( 5, 0, 10 ) );
8437 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 0, 0 ), QgsPoint( 0, 0 ) ), QgsQuadrilateral() );
8438 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 0, 0 ), QgsPoint( 0, 10 ) ), QgsQuadrilateral() );
8439 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ) ), rectangleFromExtent );
8440 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 5, 5 ), QgsPoint( 0, 0 ) ), rectangleFromExtent );
8441 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 0, 0, 10 ), QgsPoint( 5, 5 ) ), rectangleFromExtentZ );
8442 : 1 : QVERIFY( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 0, 0 ), QgsPoint( 5, 5, 10 ) ) != rectangleFromExtentZ );
8443 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromExtent( QgsPoint( 0, 0 ), QgsPoint( 5, 5, 10 ) ), rectangleFromExtent );
8444 : :
8445 : : // squareFromDiagonal
8446 : 1 : QgsQuadrilateral squareFromDiagonal( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8447 : 1 : QgsQuadrilateral squareFromDiagonalZ( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 5, 10 ), QgsPoint( 5, 0, 10 ) );
8448 : 1 : QgsQuadrilateral squareFromDiagonalInv( QgsPoint( 5, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ) );
8449 : 1 : QCOMPARE( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 0, 0 ), QgsPoint( 0, 0 ) ), QgsQuadrilateral() );
8450 : 1 : QCOMPARE( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ) ), squareFromDiagonal );
8451 : 1 : QVERIFY( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 5, 5 ), QgsPoint( 0, 0 ) ) != squareFromDiagonal );
8452 : 1 : QVERIFY( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 5, 5 ), QgsPoint( 0, 0 ) ).equals( squareFromDiagonalInv, 1E-8 ) );
8453 : 1 : QCOMPARE( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 0, 0, 10 ), QgsPoint( 5, 5 ) ), squareFromDiagonalZ );
8454 : 1 : QVERIFY( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 0, 0 ), QgsPoint( 5, 5, 10 ) ) != squareFromDiagonalZ );
8455 : 1 : QCOMPARE( QgsQuadrilateral::squareFromDiagonal( QgsPoint( 0, 0 ), QgsPoint( 5, 5, 10 ) ), squareFromDiagonal );
8456 : :
8457 : : // rectangleFromCenterPoint
8458 : 1 : QgsQuadrilateral rectangleFromCenterPoint( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8459 : 1 : QgsQuadrilateral rectangleFromCenterPointZ( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 5, 10 ), QgsPoint( 5, 0, 10 ) );
8460 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 2.5, 2.5 ) ), QgsQuadrilateral() ) ;
8461 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 5, 5 ) ), rectangleFromCenterPoint ) ;
8462 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 5, 0 ) ), rectangleFromCenterPoint ) ;
8463 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 0, 5 ) ), rectangleFromCenterPoint ) ;
8464 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 0, 0 ) ), rectangleFromCenterPoint ) ;
8465 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5, 10 ), QgsPoint( 5, 5 ) ), rectangleFromCenterPointZ ) ;
8466 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5, 10 ), QgsPoint( 5, 0 ) ), rectangleFromCenterPointZ ) ;
8467 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5, 10 ), QgsPoint( 0, 5 ) ), rectangleFromCenterPointZ ) ;
8468 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5, 10 ), QgsPoint( 0, 0 ) ), rectangleFromCenterPointZ ) ;
8469 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 0, 0, 10 ) ), rectangleFromCenterPoint ) ;
8470 : :
8471 : : // fromRectangle
8472 : 1 : QgsQuadrilateral fromRectangle( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8473 : 1 : QCOMPARE( QgsQuadrilateral::fromRectangle( QgsRectangle( QgsPointXY( 0, 0 ), QgsPointXY( 0, 0 ) ) ), QgsQuadrilateral() );
8474 : 1 : QCOMPARE( QgsQuadrilateral::fromRectangle( QgsRectangle( QgsPointXY( 0, 0 ), QgsPointXY( 5, 5 ) ) ), fromRectangle ) ;
8475 : 1 : QCOMPARE( QgsQuadrilateral::fromRectangle( QgsRectangle( QgsPointXY( 5, 5 ), QgsPointXY( 0, 0 ) ) ), fromRectangle ) ;
8476 : : // rectangleFrom3points
8477 : 1 : QgsQuadrilateral rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8478 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsQuadrilateral::Distance ), QgsQuadrilateral() );
8479 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsQuadrilateral::Projected ), QgsQuadrilateral() );
8480 : :
8481 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsQuadrilateral::Distance ).toLineString()->asWkt( 0 ),
8482 : : QString( "LineString (0 0, 0 5, 5 5, 5 0, 0 0)" ) );
8483 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsQuadrilateral::Distance ).toLineString()->asWkt( 0 ),
8484 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8485 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 5 ), QgsQuadrilateral::Distance ).toLineString()->asWkt( 0 ),
8486 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8487 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5, 10 ), QgsQuadrilateral::Distance ).toLineString()->asWkt( 0 ),
8488 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8489 : :
8490 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 4 ), QgsQuadrilateral::Projected ).toLineString()->asWkt( 0 ),
8491 : : QString( "LineString (0 0, 0 5, 5 5, 5 0, 0 0)" ) );
8492 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5 ), QgsPoint( 5, 4 ), QgsQuadrilateral::Projected ).toLineString()->asWkt( 0 ),
8493 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8494 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 4 ), QgsQuadrilateral::Projected ).toLineString()->asWkt( 0 ),
8495 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8496 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 4, 10 ), QgsQuadrilateral::Projected ).toLineString()->asWkt( 0 ),
8497 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8498 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 4, 10 ), QgsQuadrilateral::Projected ).toLineString()->asWkt( 0 ),
8499 : : QString( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" ) );
8500 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 5 ), QgsPoint( 0, 5, 5 ), QgsPoint( 5, 5, 0 ), QgsQuadrilateral::Projected ).toString( 2 ),
8501 : : QString( "Quadrilateral (Point 1: PointZ (0 0 5), Point 2: PointZ (0 5 5), Point 3: PointZ (5 5 0), Point 4: PointZ (5 0 0))" ) );
8502 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 5 ), QgsPoint( 0, 5, 5 ), QgsPoint( 5, 5, 10 ), QgsQuadrilateral::Projected ).toString( 2 ),
8503 : : QString( "Quadrilateral (Point 1: PointZ (0 0 5), Point 2: PointZ (0 5 5), Point 3: PointZ (5 5 10), Point 4: PointZ (5 0 10))" ) );
8504 : : // toString
8505 : 1 : QCOMPARE( QgsQuadrilateral( ).toString(), QString( "Empty" ) );
8506 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 2.5, 2.5 ) ).toString(), QString( "Empty" ) );
8507 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5 ), QgsPoint( 5, 0 ) ).toString(), QString( "Quadrilateral (Point 1: Point (0 0), Point 2: Point (0 5), Point 3: Point (5 5), Point 4: Point (5 0))" ) );
8508 : 1 : QCOMPARE( QgsQuadrilateral::rectangleFromCenterPoint( QgsPoint( 2.5, 2.5, 10 ), QgsPoint( 5, 0 ) ).toString(), QString( "Quadrilateral (Point 1: PointZ (0 0 10), Point 2: PointZ (0 5 10), Point 3: PointZ (5 5 10), Point 4: PointZ (5 0 10))" ) );
8509 : :
8510 : : // toPolygon / toLineString
8511 : 1 : QCOMPARE( quad_init.toPolygon()->asWkt(), QgsPolygon().asWkt() );
8512 : 1 : QCOMPARE( quad_init.toLineString()->asWkt(), QgsLineString().asWkt() );
8513 : 1 : QgsLineString ext, extZ;
8514 : 1 : QgsPolygon polyg, polygZ;
8515 : 1 : QgsQuadrilateral quad( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 5 ), QgsPoint( 5, 0 ) );
8516 : 1 : QgsQuadrilateral quadZ( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5, 10 ), QgsPoint( 5, 5, 10 ), QgsPoint( 5, 0, 10 ) );
8517 : 1 : ext.fromWkt( "LineString (0 0, 0 5, 5 5, 5 0, 0 0)" );
8518 : 1 : QCOMPARE( quad.toLineString()->asWkt(), ext.asWkt() );
8519 : 1 : polyg.fromWkt( "Polygon ((0 0, 0 5, 5 5, 5 0, 0 0))" );
8520 : 1 : QCOMPARE( quad.toPolygon()->asWkt(), polyg.asWkt() );
8521 : :
8522 : 1 : extZ.fromWkt( "LineStringZ (0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10)" );
8523 : 1 : QCOMPARE( quadZ.toLineString()->asWkt(), extZ.asWkt() );
8524 : 1 : QCOMPARE( quadZ.toLineString( true )->asWkt(), ext.asWkt() );
8525 : 1 : polygZ.fromWkt( "PolygonZ ((0 0 10, 0 5 10, 5 5 10, 5 0 10, 0 0 10))" );
8526 : 1 : QCOMPARE( quadZ.toPolygon()->asWkt(), polygZ.asWkt() );
8527 : 1 : QCOMPARE( quadZ.toPolygon( true )->asWkt(), polyg.asWkt() );
8528 : :
8529 : :
8530 : : // area / perimeter
8531 : :
8532 : 1 : QCOMPARE( QgsQuadrilateral().area(), 0.0 );
8533 : 1 : QCOMPARE( QgsQuadrilateral().perimeter(), 0.0 );
8534 : :
8535 : 1 : QVERIFY( qgsDoubleNear( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5 ), QgsPoint( 5, 4 ), QgsQuadrilateral::Projected ).area(), 25.0 ) );
8536 : 1 : QVERIFY( qgsDoubleNear( QgsQuadrilateral::rectangleFrom3Points( QgsPoint( 0, 0, 10 ), QgsPoint( 0, 5 ), QgsPoint( 5, 4 ), QgsQuadrilateral::Projected ).perimeter(), 20 ) );
8537 : 1 : }
8538 : :
8539 : 1 : void TestQgsGeometry::regularPolygon()
8540 : : {
8541 : : // constructors
8542 : 1 : QgsRegularPolygon rp1 = QgsRegularPolygon();
8543 : 1 : QVERIFY( rp1.center().isEmpty() );
8544 : 1 : QVERIFY( rp1.firstVertex().isEmpty() );
8545 : 1 : QCOMPARE( rp1.numberSides(), static_cast< unsigned int >( 0 ) );
8546 : 1 : QCOMPARE( rp1.radius(), 0.0 );
8547 : 1 : QVERIFY( rp1.isEmpty() );
8548 : :
8549 : 1 : QgsRegularPolygon rp2;
8550 : 1 : QgsRegularPolygon( QgsPoint( 0, 0 ), 5, 0, 2, QgsRegularPolygon::InscribedCircle );
8551 : 1 : QVERIFY( rp2.isEmpty() );
8552 : 1 : QgsRegularPolygon( QgsPoint( 0, 0 ), 5, 0, 5, static_cast< QgsRegularPolygon::ConstructionOption >( 4 ) );
8553 : 1 : QVERIFY( rp2.isEmpty() );
8554 : :
8555 : 1 : rp2 = QgsRegularPolygon( QgsPoint( 0, 0 ), 5, 0, 5, QgsRegularPolygon::InscribedCircle );
8556 : 1 : QVERIFY( !rp2.isEmpty() );
8557 : 1 : QCOMPARE( rp2.center(), QgsPoint( 0, 0 ) );
8558 : 1 : QCOMPARE( rp2.firstVertex(), QgsPoint( 0, 5 ) );
8559 : 1 : QCOMPARE( rp2.numberSides(), static_cast< unsigned int>( 5 ) );
8560 : 1 : QCOMPARE( rp2.radius(), 5.0 );
8561 : 1 : QGSCOMPARENEAR( rp2.apothem(), 4.0451, 10E-4 );
8562 : 1 : QVERIFY( rp2 == QgsRegularPolygon( QgsPoint( 0, 0 ), -5, 0, 5, QgsRegularPolygon::InscribedCircle ) );
8563 : :
8564 : 1 : QgsRegularPolygon rp3 = QgsRegularPolygon( QgsPoint( 0, 0 ), rp2.apothem(), 36.0, 5, QgsRegularPolygon::CircumscribedCircle );
8565 : 1 : QVERIFY( rp2 == rp3 );
8566 : 1 : QVERIFY( rp2 == QgsRegularPolygon( QgsPoint( 0, 0 ), -rp2.apothem(), 36.0, 5, QgsRegularPolygon::CircumscribedCircle ) );
8567 : 1 : QVERIFY( rp1 != rp3 );
8568 : 1 : QVERIFY( rp1 != QgsRegularPolygon( QgsPoint( 5, 5 ), rp2.apothem(), 36.0, 5, QgsRegularPolygon::CircumscribedCircle ) );
8569 : 1 : QVERIFY( rp1 != QgsRegularPolygon( QgsPoint( 0, 0 ), 5, 36.0, 5, QgsRegularPolygon::CircumscribedCircle ) );
8570 : 1 : QVERIFY( rp1 != QgsRegularPolygon( QgsPoint( 0, 0 ), 5, 36.0, 5, QgsRegularPolygon::InscribedCircle ) );
8571 : :
8572 : 1 : QgsRegularPolygon rp4 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), 2, QgsRegularPolygon::InscribedCircle );
8573 : 1 : QVERIFY( rp4.isEmpty() );
8574 : 1 : rp4 = QgsRegularPolygon( QgsPoint(), QgsPoint( 0, 5 ), 5, static_cast< QgsRegularPolygon::ConstructionOption >( 4 ) );
8575 : 1 : QVERIFY( rp4.isEmpty() );
8576 : 1 : rp4 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), 5, QgsRegularPolygon::InscribedCircle );
8577 : 1 : QVERIFY( rp4 == rp2 );
8578 : :
8579 : 1 : QgsRegularPolygon rp5 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 0 ).project( rp2.apothem(), 36.0 ), 2, QgsRegularPolygon::CircumscribedCircle );
8580 : 1 : QVERIFY( rp5.isEmpty() );
8581 : 1 : rp5 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 0 ).project( rp2.apothem(), 36.0 ), 5, static_cast< QgsRegularPolygon::ConstructionOption >( 4 ) );
8582 : 1 : QVERIFY( rp5.isEmpty() );
8583 : 1 : rp5 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 0 ).project( rp2.apothem(), 36.0 ), 5, QgsRegularPolygon::CircumscribedCircle );
8584 : 1 : QVERIFY( rp5 == rp2 );
8585 : :
8586 : 1 : QgsRegularPolygon rp6 = QgsRegularPolygon( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ).project( 5.0, 72 ), 5 );
8587 : 1 : QVERIFY( rp6 == rp2 );
8588 : :
8589 : :
8590 : : // setters and getters
8591 : 1 : QgsRegularPolygon rp7 = QgsRegularPolygon();
8592 : :
8593 : 1 : rp7.setCenter( QgsPoint( 5, 5 ) );
8594 : 1 : QVERIFY( rp7.isEmpty() );
8595 : 1 : QCOMPARE( rp7.center(), QgsPoint( 5, 5 ) );
8596 : :
8597 : 1 : rp7.setNumberSides( 2 );
8598 : 1 : QVERIFY( rp7.isEmpty() );
8599 : 1 : QCOMPARE( rp7.numberSides(), static_cast< unsigned int >( 0 ) );
8600 : 1 : rp7.setNumberSides( 5 );
8601 : 1 : QVERIFY( rp7.isEmpty() );
8602 : 1 : QCOMPARE( rp7.numberSides(), static_cast< unsigned int >( 5 ) );
8603 : 1 : rp7.setNumberSides( 2 );
8604 : 1 : QVERIFY( rp7.isEmpty() );
8605 : 1 : QCOMPARE( rp7.numberSides(), static_cast< unsigned int >( 5 ) );
8606 : 1 : rp7.setNumberSides( 3 );
8607 : 1 : QVERIFY( rp7.isEmpty() );
8608 : 1 : QCOMPARE( rp7.numberSides(), static_cast< unsigned int >( 3 ) );
8609 : :
8610 : 1 : rp7.setRadius( -6 );
8611 : 1 : QVERIFY( !rp7.isEmpty() );
8612 : 1 : QCOMPARE( rp7.radius(), 6.0 );
8613 : 1 : QCOMPARE( rp7.firstVertex(), rp7.center().project( 6, 0 ) );
8614 : :
8615 : 1 : rp7.setFirstVertex( QgsPoint( 4, 4 ) );
8616 : 1 : QCOMPARE( rp7.firstVertex(), QgsPoint( 4, 4 ) );
8617 : 1 : QCOMPARE( rp7.radius(), rp7.center().distance3D( QgsPoint( 4, 4 ) ) );
8618 : :
8619 : 1 : rp7 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), 5, QgsRegularPolygon::InscribedCircle );
8620 : 1 : rp7.setCenter( QgsPoint( 5, 5 ) );
8621 : 1 : QCOMPARE( rp7.radius(), 5.0 );
8622 : 1 : QCOMPARE( rp7.firstVertex(), QgsPoint( 5, 10 ) );
8623 : 1 : rp7.setNumberSides( 3 );
8624 : 1 : QCOMPARE( rp7.radius(), 5.0 );
8625 : 1 : QCOMPARE( rp7.firstVertex(), QgsPoint( 5, 10 ) );
8626 : 1 : rp7.setNumberSides( 2 );
8627 : 1 : QCOMPARE( rp7.radius(), 5.0 );
8628 : 1 : QCOMPARE( rp7.firstVertex(), QgsPoint( 5, 10 ) );
8629 : :
8630 : : // measures
8631 : 1 : QGSCOMPARENEAR( rp1.length(), 0.0, 10e-4 );
8632 : 1 : QGSCOMPARENEAR( rp1.area(), 0.0, 10e-4 );
8633 : 1 : QGSCOMPARENEAR( rp1.perimeter(), 0.0, 10e-4 );
8634 : 1 : QGSCOMPARENEAR( rp2.length(), 5.8779, 10e-4 );
8635 : 1 : QGSCOMPARENEAR( rp2.area(), 59.4410, 10e-4 );
8636 : 1 : QGSCOMPARENEAR( rp2.perimeter(), 29.3893, 10e-4 );
8637 : 1 : QCOMPARE( rp2.interiorAngle(), 108.0 );
8638 : 1 : QCOMPARE( rp2.centralAngle(), 72.0 );
8639 : 1 : QgsRegularPolygon rp8 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 5, 0 ), 5 );
8640 : 1 : QGSCOMPARENEAR( rp8.area(), 43.0119, 10e-4 );
8641 : 1 : QCOMPARE( rp8.perimeter(), 25.0 );
8642 : 1 : QCOMPARE( rp8.length(), 5.0 );
8643 : 1 : QCOMPARE( rp8.interiorAngle(), 108.0 );
8644 : 1 : QCOMPARE( rp8.centralAngle(), 72.0 );
8645 : 1 : rp8.setNumberSides( 4 );
8646 : 1 : QCOMPARE( rp8.interiorAngle(), 90.0 );
8647 : 1 : QCOMPARE( rp8.centralAngle(), 90.0 );
8648 : 1 : rp8.setNumberSides( 3 );
8649 : 1 : QCOMPARE( rp8.interiorAngle(), 60.0 );
8650 : 1 : QCOMPARE( rp8.centralAngle(), 120.0 );
8651 : :
8652 : : //points
8653 : 1 : rp8 = QgsRegularPolygon(); // empty
8654 : 1 : QgsPointSequence points = rp8.points();
8655 : 1 : QVERIFY( points.isEmpty() );
8656 : 1 : rp8 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), 3, QgsRegularPolygon::InscribedCircle );
8657 : 1 : points = rp8.points();
8658 : 1 : QCOMPARE( points.count(), 3 );
8659 : 1 : QCOMPARE( points.at( 0 ), QgsPoint( 0, 5 ) );
8660 : 1 : QGSCOMPARENEAR( points.at( 1 ).x(), 4.33, 0.01 );
8661 : 1 : QGSCOMPARENEAR( points.at( 1 ).y(), -2.4999, 0.01 );
8662 : 1 : QGSCOMPARENEAR( points.at( 2 ).x(), -4.33, 0.01 );
8663 : 1 : QGSCOMPARENEAR( points.at( 2 ).y(), -2.4999, 0.01 );
8664 : :
8665 : : //test conversions
8666 : : // circle
8667 : 1 : QVERIFY( QgsCircle( QgsPoint( 0, 0 ), 5 ) == rp2.circumscribedCircle() );
8668 : 1 : QVERIFY( rp2.inscribedCircle() == QgsRegularPolygon( QgsPoint( 0, 0 ), rp2.apothem(), 36.0, 5, QgsRegularPolygon::InscribedCircle ).circumscribedCircle() );
8669 : :
8670 : : // triangle
8671 : 1 : QCOMPARE( QgsTriangle(), rp2.toTriangle() );
8672 : 1 : QCOMPARE( QgsTriangle(), QgsRegularPolygon().toTriangle() );
8673 : 1 : QgsRegularPolygon rp9 = QgsRegularPolygon( QgsPoint( 0, 0 ), 5, 0, 3, QgsRegularPolygon::InscribedCircle );
8674 : :
8675 : 1 : QVERIFY( QgsCircle( QgsPoint( 0, 0 ), 5 ) == rp9.toTriangle().circumscribedCircle() );
8676 : :
8677 : 1 : QgsRegularPolygon rp10 = QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 4 ), 4 );
8678 : 1 : QVector<QgsTriangle> rp10_tri = rp10.triangulate();
8679 : 1 : QCOMPARE( rp10_tri.length(), static_cast< int >( rp10.numberSides() ) );
8680 : 1 : QVERIFY( rp10_tri.at( 0 ) == QgsTriangle( QgsPoint( 0, 0 ), QgsPoint( 0, 4 ), rp10.center() ) );
8681 : 1 : QVERIFY( rp10_tri.at( 1 ) == QgsTriangle( QgsPoint( 0, 4 ), QgsPoint( 4, 4 ), rp10.center() ) );
8682 : 1 : QVERIFY( rp10_tri.at( 2 ) == QgsTriangle( QgsPoint( 4, 4 ), QgsPoint( 4, 0 ), rp10.center() ) );
8683 : 1 : QVERIFY( rp10_tri.at( 3 ) == QgsTriangle( QgsPoint( 4, 0 ), QgsPoint( 0, 0 ), rp10.center() ) );
8684 : :
8685 : 1 : QVERIFY( QgsRegularPolygon().triangulate().isEmpty() );
8686 : :
8687 : : // polygon
8688 : 1 : std::unique_ptr< QgsPolygon > toP( QgsRegularPolygon().toPolygon() );
8689 : 1 : QVERIFY( toP->isEmpty() );
8690 : :
8691 : 1 : QgsPointSequence ptsPol;
8692 : 1 : std::unique_ptr< QgsPolygon > pol( new QgsPolygon() );
8693 : 1 : pol.reset( rp10.toPolygon() );
8694 : 1 : QCOMPARE( pol->numInteriorRings(), 0 );
8695 : 1 : QCOMPARE( pol->exteriorRing()->numPoints(), 5 );
8696 : :
8697 : 1 : pol->exteriorRing()->points( ptsPol );
8698 : 1 : QCOMPARE( ptsPol.length(), 5 );
8699 : 1 : QVERIFY( ptsPol.at( 0 ) == QgsPoint( 0, 0 ) );
8700 : 1 : QVERIFY( ptsPol.at( 1 ) == QgsPoint( 0, 4 ) );
8701 : 1 : QVERIFY( ptsPol.at( 2 ) == QgsPoint( 4, 4 ) );
8702 : 1 : QVERIFY( ptsPol.at( 3 ) == QgsPoint( 4, 0 ) );
8703 : 1 : QVERIFY( ptsPol.at( 4 ) == QgsPoint( 0, 0 ) );
8704 : 1 : ptsPol.pop_back();
8705 : :
8706 : 1 : std::unique_ptr< QgsLineString > l( QgsRegularPolygon( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), 1, QgsRegularPolygon::InscribedCircle ).toLineString() );
8707 : 1 : QVERIFY( l->isEmpty() );
8708 : 1 : l.reset( rp10.toLineString( ) );
8709 : 1 : QCOMPARE( l->numPoints(), 5 );
8710 : 1 : QCOMPARE( l->pointN( 0 ), l->pointN( 4 ) );
8711 : 1 : QgsPointSequence pts_l;
8712 : 1 : l->points( pts_l );
8713 : 1 : pts_l.pop_back();
8714 : 1 : QCOMPARE( ptsPol, pts_l );
8715 : :
8716 : : //test toString
8717 : 1 : QCOMPARE( rp1.toString(), QString( "Empty" ) );
8718 : 1 : QCOMPARE( rp2.toString(), QString( "RegularPolygon (Center: Point (0 0), First Vertex: Point (0 5), Radius: 5, Azimuth: 0)" ) );
8719 : :
8720 : 1 : }
8721 : :
8722 : :
8723 : 1 : void TestQgsGeometry::curvePolygon()
8724 : : {
8725 : : //test constructor
8726 : 1 : QgsCurvePolygon p1;
8727 : 1 : QVERIFY( p1.isEmpty() );
8728 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
8729 : 1 : QCOMPARE( p1.nCoordinates(), 0 );
8730 : 1 : QCOMPARE( p1.ringCount(), 0 );
8731 : 1 : QCOMPARE( p1.partCount(), 0 );
8732 : 1 : QVERIFY( !p1.is3D() );
8733 : 1 : QVERIFY( !p1.isMeasure() );
8734 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::CurvePolygon );
8735 : 1 : QCOMPARE( p1.wktTypeStr(), QString( "CurvePolygon" ) );
8736 : 1 : QCOMPARE( p1.geometryType(), QString( "CurvePolygon" ) );
8737 : 1 : QCOMPARE( p1.dimension(), 2 );
8738 : 1 : QVERIFY( !p1.hasCurvedSegments() );
8739 : 1 : QCOMPARE( p1.area(), 0.0 );
8740 : 1 : QCOMPARE( p1.perimeter(), 0.0 );
8741 : 1 : QVERIFY( !p1.exteriorRing() );
8742 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
8743 : :
8744 : : //set exterior ring
8745 : :
8746 : : //try with no ring
8747 : 1 : QgsCircularString *ext = nullptr;
8748 : 1 : p1.setExteriorRing( ext );
8749 : 1 : QVERIFY( p1.isEmpty() );
8750 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
8751 : 1 : QCOMPARE( p1.nCoordinates(), 0 );
8752 : 1 : QCOMPARE( p1.ringCount(), 0 );
8753 : 1 : QCOMPARE( p1.partCount(), 0 );
8754 : 1 : QVERIFY( !p1.exteriorRing() );
8755 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
8756 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::CurvePolygon );
8757 : :
8758 : : // empty exterior ring
8759 : 1 : ext = new QgsCircularString();
8760 : 1 : p1.setExteriorRing( ext );
8761 : 1 : QVERIFY( p1.isEmpty() );
8762 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
8763 : 1 : QCOMPARE( p1.nCoordinates(), 0 );
8764 : 1 : QCOMPARE( p1.ringCount(), 1 );
8765 : 1 : QCOMPARE( p1.partCount(), 1 );
8766 : 1 : QVERIFY( p1.exteriorRing() );
8767 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
8768 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::CurvePolygon );
8769 : :
8770 : : //valid exterior ring
8771 : 1 : ext = new QgsCircularString();
8772 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
8773 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
8774 : 1 : p1.setExteriorRing( ext );
8775 : 1 : QVERIFY( !p1.isEmpty() );
8776 : 1 : QCOMPARE( p1.numInteriorRings(), 0 );
8777 : 1 : QCOMPARE( p1.nCoordinates(), 5 );
8778 : 1 : QCOMPARE( p1.ringCount(), 1 );
8779 : 1 : QCOMPARE( p1.partCount(), 1 );
8780 : 1 : QVERIFY( !p1.is3D() );
8781 : 1 : QVERIFY( !p1.isMeasure() );
8782 : 1 : QCOMPARE( p1.wkbType(), QgsWkbTypes::CurvePolygon );
8783 : 1 : QCOMPARE( p1.wktTypeStr(), QString( "CurvePolygon" ) );
8784 : 1 : QCOMPARE( p1.geometryType(), QString( "CurvePolygon" ) );
8785 : 1 : QCOMPARE( p1.dimension(), 2 );
8786 : 1 : QVERIFY( p1.hasCurvedSegments() );
8787 : 1 : QGSCOMPARENEAR( p1.area(), 157.08, 0.01 );
8788 : 1 : QGSCOMPARENEAR( p1.perimeter(), 44.4288, 0.01 );
8789 : 1 : QVERIFY( p1.exteriorRing() );
8790 : 1 : QVERIFY( !p1.interiorRing( 0 ) );
8791 : :
8792 : : //retrieve exterior ring and check
8793 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( p1.exteriorRing() ) ), *ext );
8794 : :
8795 : : //initial setting of exterior ring should set z/m type
8796 : 1 : QgsCurvePolygon p2;
8797 : 1 : ext = new QgsCircularString();
8798 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
8799 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
8800 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
8801 : 1 : p2.setExteriorRing( ext );
8802 : 1 : QVERIFY( p2.is3D() );
8803 : 1 : QVERIFY( !p2.isMeasure() );
8804 : 1 : QCOMPARE( p2.wkbType(), QgsWkbTypes::CurvePolygonZ );
8805 : 1 : QCOMPARE( p2.wktTypeStr(), QString( "CurvePolygonZ" ) );
8806 : 1 : QCOMPARE( p2.geometryType(), QString( "CurvePolygon" ) );
8807 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( p2.exteriorRing() ) ), *ext );
8808 : 1 : QgsCurvePolygon p3;
8809 : 1 : ext = new QgsCircularString();
8810 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 )
8811 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0, 10, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 )
8812 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
8813 : 1 : p3.setExteriorRing( ext );
8814 : 1 : QVERIFY( !p3.is3D() );
8815 : 1 : QVERIFY( p3.isMeasure() );
8816 : 1 : QCOMPARE( p3.wkbType(), QgsWkbTypes::CurvePolygonM );
8817 : 1 : QCOMPARE( p3.wktTypeStr(), QString( "CurvePolygonM" ) );
8818 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( p3.exteriorRing() ) ), *ext );
8819 : 1 : QgsCurvePolygon p4;
8820 : 1 : ext = new QgsCircularString();
8821 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 2, 1 )
8822 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 3, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 5, 3 )
8823 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 2, 1 ) );
8824 : 1 : p4.setExteriorRing( ext );
8825 : 1 : QVERIFY( p4.is3D() );
8826 : 1 : QVERIFY( p4.isMeasure() );
8827 : 1 : QCOMPARE( p4.wkbType(), QgsWkbTypes::CurvePolygonZM );
8828 : 1 : QCOMPARE( p4.wktTypeStr(), QString( "CurvePolygonZM" ) );
8829 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( p4.exteriorRing() ) ), *ext );
8830 : :
8831 : : //addInteriorRing
8832 : 1 : QgsCurvePolygon p6;
8833 : 1 : ext = new QgsCircularString();
8834 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
8835 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
8836 : 1 : p6.setExteriorRing( ext );
8837 : : //empty ring
8838 : 1 : QCOMPARE( p6.numInteriorRings(), 0 );
8839 : 1 : QVERIFY( !p6.interiorRing( -1 ) );
8840 : 1 : QVERIFY( !p6.interiorRing( 0 ) );
8841 : 1 : p6.addInteriorRing( nullptr );
8842 : 1 : QCOMPARE( p6.numInteriorRings(), 0 );
8843 : 1 : QgsCircularString *ring = new QgsCircularString();
8844 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
8845 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) );
8846 : 1 : p6.addInteriorRing( ring );
8847 : 1 : QCOMPARE( p6.numInteriorRings(), 1 );
8848 : 1 : QCOMPARE( p6.interiorRing( 0 ), ring );
8849 : 1 : QVERIFY( !p6.interiorRing( 1 ) );
8850 : :
8851 : 1 : QgsCoordinateSequence seq = p6.coordinateSequence();
8852 : 1 : QCOMPARE( seq, QgsCoordinateSequence() << ( QgsRingSequence() << ( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
8853 : : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) )
8854 : : << ( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
8855 : : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) ) ) );
8856 : 1 : QCOMPARE( p6.nCoordinates(), 10 );
8857 : :
8858 : : //try adding an interior ring with z to a 2d polygon, z should be dropped
8859 : 1 : ring = new QgsCircularString();
8860 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
8861 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
8862 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
8863 : 1 : p6.addInteriorRing( ring );
8864 : 1 : QCOMPARE( p6.numInteriorRings(), 2 );
8865 : 1 : QVERIFY( !p6.is3D() );
8866 : 1 : QVERIFY( !p6.isMeasure() );
8867 : 1 : QCOMPARE( p6.wkbType(), QgsWkbTypes::CurvePolygon );
8868 : 1 : QVERIFY( p6.interiorRing( 1 ) );
8869 : 1 : QVERIFY( !p6.interiorRing( 1 )->is3D() );
8870 : 1 : QVERIFY( !p6.interiorRing( 1 )->isMeasure() );
8871 : 1 : QCOMPARE( p6.interiorRing( 1 )->wkbType(), QgsWkbTypes::CircularString );
8872 : :
8873 : : //try adding an interior ring with m to a 2d polygon, m should be dropped
8874 : 1 : ring = new QgsCircularString();
8875 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.1, 0, 1 )
8876 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.2, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 0.2, 0.2, 0, 3 )
8877 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.2, 0.1, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.1, 0, 1 ) );
8878 : 1 : p6.addInteriorRing( ring );
8879 : 1 : QCOMPARE( p6.numInteriorRings(), 3 );
8880 : 1 : QVERIFY( !p6.is3D() );
8881 : 1 : QVERIFY( !p6.isMeasure() );
8882 : 1 : QCOMPARE( p6.wkbType(), QgsWkbTypes::CurvePolygon );
8883 : 1 : QVERIFY( p6.interiorRing( 2 ) );
8884 : 1 : QVERIFY( !p6.interiorRing( 2 )->is3D() );
8885 : 1 : QVERIFY( !p6.interiorRing( 2 )->isMeasure() );
8886 : 1 : QCOMPARE( p6.interiorRing( 2 )->wkbType(), QgsWkbTypes::CircularString );
8887 : :
8888 : :
8889 : : //addInteriorRing without z/m to PolygonZM
8890 : 1 : QgsCurvePolygon p6b;
8891 : 1 : ext = new QgsCircularString();
8892 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1 )
8893 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3 )
8894 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1 ) );
8895 : 1 : p6b.setExteriorRing( ext );
8896 : 1 : QVERIFY( p6b.is3D() );
8897 : 1 : QVERIFY( p6b.isMeasure() );
8898 : 1 : QCOMPARE( p6b.wkbType(), QgsWkbTypes::CurvePolygonZM );
8899 : : //ring has no z
8900 : 1 : ring = new QgsCircularString();
8901 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 1, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 1, 9 ) << QgsPoint( QgsWkbTypes::PointM, 9, 9 )
8902 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 1 ) << QgsPoint( QgsWkbTypes::PointM, 1, 1 ) );
8903 : 1 : p6b.addInteriorRing( ring );
8904 : 1 : QVERIFY( p6b.interiorRing( 0 ) );
8905 : 1 : QVERIFY( p6b.interiorRing( 0 )->is3D() );
8906 : 1 : QVERIFY( p6b.interiorRing( 0 )->isMeasure() );
8907 : 1 : QCOMPARE( p6b.interiorRing( 0 )->wkbType(), QgsWkbTypes::CircularStringZM );
8908 : 1 : QCOMPARE( p6b.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 0, 2 ) );
8909 : : //ring has no m
8910 : 1 : ring = new QgsCircularString();
8911 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
8912 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
8913 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
8914 : 1 : p6b.addInteriorRing( ring );
8915 : 1 : QVERIFY( p6b.interiorRing( 1 ) );
8916 : 1 : QVERIFY( p6b.interiorRing( 1 )->is3D() );
8917 : 1 : QVERIFY( p6b.interiorRing( 1 )->isMeasure() );
8918 : 1 : QCOMPARE( p6b.interiorRing( 1 )->wkbType(), QgsWkbTypes::CircularStringZM );
8919 : 1 : QCOMPARE( p6b.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 0.1, 0.1, 1, 0 ) );
8920 : :
8921 : : //set interior rings
8922 : 1 : QgsCurvePolygon p7;
8923 : 1 : ext = new QgsCircularString();
8924 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
8925 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
8926 : 1 : p7.setExteriorRing( ext );
8927 : : //add a list of rings with mixed types
8928 : 1 : QVector< QgsCurve * > rings;
8929 : 1 : rings << new QgsCircularString();
8930 : 2 : static_cast< QgsCircularString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
8931 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
8932 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
8933 : 1 : rings << new QgsCircularString();
8934 : 2 : static_cast< QgsCircularString *>( rings[1] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0.3, 0.3, 0, 1 )
8935 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.3, 0.4, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 0.4, 0.4, 0, 3 )
8936 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.4, 0.3, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0.3, 0.3, 0, 1 ) );
8937 : : //throw an empty ring in too
8938 : 1 : rings << 0;
8939 : 1 : rings << new QgsCircularString();
8940 : 2 : static_cast< QgsCircularString *>( rings[3] )->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
8941 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
8942 : 1 : p7.setInteriorRings( rings );
8943 : 1 : QCOMPARE( p7.numInteriorRings(), 3 );
8944 : 1 : QVERIFY( p7.interiorRing( 0 ) );
8945 : 1 : QVERIFY( !p7.interiorRing( 0 )->is3D() );
8946 : 1 : QVERIFY( !p7.interiorRing( 0 )->isMeasure() );
8947 : 1 : QCOMPARE( p7.interiorRing( 0 )->wkbType(), QgsWkbTypes::CircularString );
8948 : 1 : QCOMPARE( p7.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point, 0.1, 0.1 ) );
8949 : 1 : QVERIFY( p7.interiorRing( 1 ) );
8950 : 1 : QVERIFY( !p7.interiorRing( 1 )->is3D() );
8951 : 1 : QVERIFY( !p7.interiorRing( 1 )->isMeasure() );
8952 : 1 : QCOMPARE( p7.interiorRing( 1 )->wkbType(), QgsWkbTypes::CircularString );
8953 : 1 : QCOMPARE( p7.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point, 0.3, 0.3 ) );
8954 : 1 : QVERIFY( p7.interiorRing( 2 ) );
8955 : 1 : QVERIFY( !p7.interiorRing( 2 )->is3D() );
8956 : 1 : QVERIFY( !p7.interiorRing( 2 )->isMeasure() );
8957 : 1 : QCOMPARE( p7.interiorRing( 2 )->wkbType(), QgsWkbTypes::CircularString );
8958 : :
8959 : : //set rings with existing
8960 : 1 : rings.clear();
8961 : 1 : rings << new QgsCircularString();
8962 : 2 : static_cast< QgsCircularString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( 0.8, 0.8 )
8963 : 1 : << QgsPoint( 0.8, 0.9 ) << QgsPoint( 0.9, 0.9 )
8964 : 1 : << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.8, 0.8 ) );
8965 : 1 : p7.setInteriorRings( rings );
8966 : 1 : QCOMPARE( p7.numInteriorRings(), 1 );
8967 : 1 : QVERIFY( p7.interiorRing( 0 ) );
8968 : 1 : QVERIFY( !p7.interiorRing( 0 )->is3D() );
8969 : 1 : QVERIFY( !p7.interiorRing( 0 )->isMeasure() );
8970 : 1 : QCOMPARE( p7.interiorRing( 0 )->wkbType(), QgsWkbTypes::CircularString );
8971 : 1 : QCOMPARE( p7.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::Point, 0.8, 0.8 ) );
8972 : 1 : rings.clear();
8973 : 1 : p7.setInteriorRings( rings );
8974 : 1 : QCOMPARE( p7.numInteriorRings(), 0 );
8975 : :
8976 : : //change dimensionality of interior rings using setExteriorRing
8977 : 1 : QgsCurvePolygon p7a;
8978 : 1 : ext = new QgsCircularString();
8979 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 )
8980 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
8981 : 1 : p7a.setExteriorRing( ext );
8982 : 1 : rings.clear();
8983 : 1 : rings << new QgsCircularString();
8984 : 2 : static_cast< QgsCircularString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 )
8985 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.2, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.2, 3 )
8986 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.2, 0.1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.1, 0.1, 1 ) );
8987 : 1 : rings << new QgsCircularString();
8988 : 2 : static_cast< QgsCircularString *>( rings[1] )->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0.3, 0.3, 1 )
8989 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.3, 0.4, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 0.4, 0.4, 3 )
8990 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0.4, 0.3, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0.3, 0.3, 1 ) );
8991 : 1 : p7a.setInteriorRings( rings );
8992 : 1 : QVERIFY( p7a.is3D() );
8993 : 1 : QVERIFY( !p7a.isMeasure() );
8994 : 1 : QVERIFY( p7a.interiorRing( 0 )->is3D() );
8995 : 1 : QVERIFY( !p7a.interiorRing( 0 )->isMeasure() );
8996 : 1 : QVERIFY( p7a.interiorRing( 1 )->is3D() );
8997 : 1 : QVERIFY( !p7a.interiorRing( 1 )->isMeasure() );
8998 : : //reset exterior ring to 2d
8999 : 1 : ext = new QgsCircularString();
9000 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 )
9001 : 1 : << QgsPoint( 10, 10 ) << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
9002 : 1 : p7a.setExteriorRing( ext );
9003 : 1 : QVERIFY( !p7a.is3D() );
9004 : 1 : QVERIFY( !p7a.interiorRing( 0 )->is3D() ); //rings should also be made 2D
9005 : 1 : QVERIFY( !p7a.interiorRing( 1 )->is3D() );
9006 : : //reset exterior ring to LineStringM
9007 : 1 : ext = new QgsCircularString();
9008 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0 ) << QgsPoint( QgsWkbTypes::PointM, 0, 10 )
9009 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 10 ) << QgsPoint( QgsWkbTypes::PointM, 10, 0 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0 ) );
9010 : 1 : p7a.setExteriorRing( ext );
9011 : 1 : QVERIFY( p7a.isMeasure() );
9012 : 1 : QVERIFY( p7a.interiorRing( 0 )->isMeasure() ); //rings should also gain measure
9013 : 1 : QVERIFY( p7a.interiorRing( 1 )->isMeasure() );
9014 : :
9015 : : //removeInteriorRing
9016 : 1 : QgsCurvePolygon p8;
9017 : 1 : ext = new QgsCircularString();
9018 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
9019 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
9020 : 1 : p8.setExteriorRing( ext );
9021 : 1 : QVERIFY( !p8.removeInteriorRing( -1 ) );
9022 : 1 : QVERIFY( !p8.removeInteriorRing( 0 ) );
9023 : 1 : rings.clear();
9024 : 1 : rings << new QgsCircularString();
9025 : 2 : static_cast< QgsCircularString *>( rings[0] )->setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 )
9026 : 1 : << QgsPoint( 0.1, 0.2 ) << QgsPoint( 0.2, 0.2 )
9027 : 1 : << QgsPoint( 0.2, 0.1 ) << QgsPoint( 0.1, 0.1 ) );
9028 : 1 : rings << new QgsCircularString();
9029 : 2 : static_cast< QgsCircularString *>( rings[1] )->setPoints( QgsPointSequence() << QgsPoint( 0.3, 0.3 )
9030 : 1 : << QgsPoint( 0.3, 0.4 ) << QgsPoint( 0.4, 0.4 )
9031 : 1 : << QgsPoint( 0.4, 0.3 ) << QgsPoint( 0.3, 0.3 ) );
9032 : 1 : rings << new QgsCircularString();
9033 : 2 : static_cast< QgsCircularString *>( rings[2] )->setPoints( QgsPointSequence() << QgsPoint( 0.8, 0.8 )
9034 : 1 : << QgsPoint( 0.8, 0.9 ) << QgsPoint( 0.9, 0.9 )
9035 : 1 : << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.8, 0.8 ) );
9036 : 1 : p8.setInteriorRings( rings );
9037 : 1 : QCOMPARE( p8.numInteriorRings(), 3 );
9038 : 1 : QVERIFY( p8.removeInteriorRing( 0 ) );
9039 : 1 : QCOMPARE( p8.numInteriorRings(), 2 );
9040 : 1 : QCOMPARE( p8.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0.3, 0.3 ) );
9041 : 1 : QCOMPARE( p8.interiorRing( 1 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0.8, 0.8 ) );
9042 : 1 : QVERIFY( p8.removeInteriorRing( 1 ) );
9043 : 1 : QCOMPARE( p8.numInteriorRings(), 1 );
9044 : 1 : QCOMPARE( p8.interiorRing( 0 )->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 0.3, 0.3 ) );
9045 : 1 : QVERIFY( p8.removeInteriorRing( 0 ) );
9046 : 1 : QCOMPARE( p8.numInteriorRings(), 0 );
9047 : 1 : QVERIFY( !p8.removeInteriorRing( 0 ) );
9048 : :
9049 : : //clear
9050 : 1 : QgsCurvePolygon p9;
9051 : 1 : ext = new QgsCircularString();
9052 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
9053 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
9054 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
9055 : 1 : p9.setExteriorRing( ext );
9056 : 1 : ring = new QgsCircularString();
9057 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 )
9058 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 9, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 9, 9, 3 )
9059 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 ) );
9060 : 1 : p9.addInteriorRing( ring );
9061 : 1 : QCOMPARE( p9.numInteriorRings(), 1 );
9062 : 1 : p9.clear();
9063 : 1 : QVERIFY( p9.isEmpty() );
9064 : 1 : QCOMPARE( p9.numInteriorRings(), 0 );
9065 : 1 : QCOMPARE( p9.nCoordinates(), 0 );
9066 : 1 : QCOMPARE( p9.ringCount(), 0 );
9067 : 1 : QCOMPARE( p9.partCount(), 0 );
9068 : 1 : QVERIFY( !p9.is3D() );
9069 : 1 : QVERIFY( !p9.isMeasure() );
9070 : 1 : QCOMPARE( p9.wkbType(), QgsWkbTypes::CurvePolygon );
9071 : :
9072 : : //equality operator
9073 : 1 : QgsCurvePolygon p10;
9074 : 1 : QgsCurvePolygon p10b;
9075 : 1 : QVERIFY( p10 == p10b );
9076 : 1 : QVERIFY( !( p10 != p10b ) );
9077 : 1 : ext = new QgsCircularString();
9078 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
9079 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
9080 : 1 : p10.setExteriorRing( ext );
9081 : 1 : QVERIFY( !( p10 == p10b ) );
9082 : 1 : QVERIFY( p10 != p10b );
9083 : 1 : ext = new QgsCircularString();
9084 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
9085 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
9086 : 1 : p10b.setExteriorRing( ext );
9087 : 1 : QVERIFY( p10 == p10b );
9088 : 1 : QVERIFY( !( p10 != p10b ) );
9089 : 1 : ext = new QgsCircularString();
9090 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 9 ) << QgsPoint( 9, 9 )
9091 : 1 : << QgsPoint( 9, 0 ) << QgsPoint( 0, 0 ) );
9092 : 1 : p10b.setExteriorRing( ext );
9093 : 1 : QVERIFY( !( p10 == p10b ) );
9094 : 1 : QVERIFY( p10 != p10b );
9095 : 1 : ext = new QgsCircularString();
9096 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 )
9097 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
9098 : 1 : p10b.setExteriorRing( ext );
9099 : 1 : QVERIFY( !( p10 == p10b ) );
9100 : 1 : QVERIFY( p10 != p10b );
9101 : 1 : p10b.setExteriorRing( p10.exteriorRing()->clone() );
9102 : 1 : QVERIFY( p10 == p10b );
9103 : 1 : QVERIFY( !( p10 != p10b ) );
9104 : 1 : ring = new QgsCircularString();
9105 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 1, 1 )
9106 : 1 : << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
9107 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) );
9108 : 1 : p10.addInteriorRing( ring );
9109 : 1 : QVERIFY( !( p10 == p10b ) );
9110 : 1 : QVERIFY( p10 != p10b );
9111 : :
9112 : 1 : ring = new QgsCircularString();
9113 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 2, 1 )
9114 : 1 : << QgsPoint( 2, 9 ) << QgsPoint( 9, 9 )
9115 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 2, 1 ) );
9116 : 1 : p10b.addInteriorRing( ring );
9117 : 1 : QVERIFY( !( p10 == p10b ) );
9118 : 1 : QVERIFY( p10 != p10b );
9119 : 1 : p10b.removeInteriorRing( 0 );
9120 : 1 : p10b.addInteriorRing( p10.interiorRing( 0 )->clone() );
9121 : 1 : QVERIFY( p10 == p10b );
9122 : 1 : QVERIFY( !( p10 != p10b ) );
9123 : :
9124 : : //clone
9125 : :
9126 : 1 : QgsCurvePolygon p11;
9127 : 1 : std::unique_ptr< QgsCurvePolygon >cloned( p11.clone() );
9128 : 1 : QCOMPARE( p11, *cloned );
9129 : 1 : ext = new QgsCircularString();
9130 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
9131 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
9132 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
9133 : 1 : p11.setExteriorRing( ext );
9134 : 1 : ring = new QgsCircularString();
9135 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
9136 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
9137 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
9138 : 1 : p11.addInteriorRing( ring );
9139 : 1 : cloned.reset( p11.clone() );
9140 : 1 : QCOMPARE( p11, *cloned );
9141 : :
9142 : : //copy constructor
9143 : 1 : QgsCurvePolygon p12;
9144 : 1 : QgsCurvePolygon p13( p12 );
9145 : 1 : QCOMPARE( p12, p13 );
9146 : 1 : ext = new QgsCircularString();
9147 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
9148 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
9149 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
9150 : 1 : p12.setExteriorRing( ext );
9151 : 1 : ring = new QgsCircularString();
9152 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
9153 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
9154 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
9155 : 1 : p12.addInteriorRing( ring );
9156 : 1 : QgsCurvePolygon p14( p12 );
9157 : 1 : QCOMPARE( p12, p14 );
9158 : :
9159 : : //assignment operator
9160 : 1 : QgsCurvePolygon p15;
9161 : 1 : p15 = p13;
9162 : 1 : QCOMPARE( p13, p15 );
9163 : 1 : p15 = p12;
9164 : 1 : QCOMPARE( p12, p15 );
9165 : :
9166 : : // bounding box
9167 : 1 : QgsCurvePolygon boundingBoxPoly;
9168 : 1 : QgsRectangle bBox = boundingBoxPoly.boundingBox(); //no crash!
9169 : :
9170 : 1 : ext = new QgsCircularString();
9171 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 1, 10, 2 ) << QgsPoint( 0, 18, 3 )
9172 : 1 : << QgsPoint( -1, 4, 4 ) << QgsPoint( 0, 0, 1 ) );
9173 : 1 : boundingBoxPoly.setExteriorRing( ext );
9174 : 1 : bBox = boundingBoxPoly.boundingBox();
9175 : 1 : QGSCOMPARENEAR( bBox.xMinimum(), -1.435273, 0.001 );
9176 : 1 : QGSCOMPARENEAR( bBox.xMaximum(), 1.012344, 0.001 );
9177 : 1 : QGSCOMPARENEAR( bBox.yMinimum(), 0.000000, 0.001 );
9178 : 1 : QGSCOMPARENEAR( bBox.yMaximum(), 18, 0.001 );
9179 : :
9180 : : //surfaceToPolygon
9181 : 1 : QgsCurvePolygon p12a;
9182 : 1 : std::unique_ptr< QgsPolygon > surface( p12a.surfaceToPolygon() );
9183 : 1 : QVERIFY( surface->isEmpty() );
9184 : :
9185 : 1 : ext = new QgsCircularString();
9186 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 3 ) << QgsPoint( 2, 4 )
9187 : 1 : << QgsPoint( -1, 5 ) << QgsPoint( 0, 6 ) );
9188 : 1 : p12a.setExteriorRing( ext );
9189 : 1 : surface.reset( p12a.surfaceToPolygon() );
9190 : 1 : QCOMPARE( surface->wkbType(), QgsWkbTypes::Polygon );
9191 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 290 );
9192 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 290 ); // nCoordinates is cached, so check twice
9193 : 1 : QVERIFY( surface->exteriorRing()->isClosed() );
9194 : : // too many vertices to actually check the result, let's just make sure the bounding boxes are similar
9195 : 1 : QgsRectangle r1 = ext->boundingBox();
9196 : 1 : QgsRectangle r2 = surface->exteriorRing()->boundingBox();
9197 : 1 : QGSCOMPARENEAR( r1.xMinimum(), r2.xMinimum(), 0.0001 );
9198 : 1 : QGSCOMPARENEAR( r1.xMaximum(), r2.xMaximum(), 0.0001 );
9199 : 1 : QGSCOMPARENEAR( r1.yMinimum(), r2.yMinimum(), 0.0001 );
9200 : 1 : QGSCOMPARENEAR( r1.yMaximum(), r2.yMaximum(), 0.0001 );
9201 : 1 : ring = new QgsCircularString();
9202 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
9203 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
9204 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
9205 : 1 : p12a.addInteriorRing( ring );
9206 : 1 : surface.reset( p12a.surfaceToPolygon() );
9207 : 1 : QCOMPARE( surface->wkbType(), QgsWkbTypes::Polygon );
9208 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 290 );
9209 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 290 ); // nCoordinates is cached, so check twice
9210 : 1 : QVERIFY( surface->exteriorRing()->isClosed() );
9211 : 1 : QCOMPARE( surface->numInteriorRings(), 1 );
9212 : : // too many vertices to actually check the result, let's just make sure the bounding boxes are similar
9213 : 1 : r1 = ring->boundingBox();
9214 : 1 : r2 = surface->interiorRing( 0 )->boundingBox();
9215 : 1 : QGSCOMPARENEAR( r1.xMinimum(), r2.xMinimum(), 0.0001 );
9216 : 1 : QGSCOMPARENEAR( r1.xMaximum(), r2.xMaximum(), 0.0001 );
9217 : 1 : QGSCOMPARENEAR( r1.yMinimum(), r2.yMinimum(), 0.0001 );
9218 : 1 : QGSCOMPARENEAR( r1.yMaximum(), r2.yMaximum(), 0.0001 );
9219 : :
9220 : : //toPolygon
9221 : 1 : p12a = QgsCurvePolygon();
9222 : 1 : surface.reset( p12a.toPolygon() );
9223 : 1 : QVERIFY( surface->isEmpty() );
9224 : :
9225 : 1 : ext = new QgsCircularString();
9226 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 10 ) << QgsPoint( 0, 18 )
9227 : 1 : << QgsPoint( -1, 4 ) << QgsPoint( 0, 0 ) );
9228 : 1 : p12a.setExteriorRing( ext );
9229 : 1 : surface.reset( p12a.toPolygon() );
9230 : 1 : QCOMPARE( surface->wkbType(), QgsWkbTypes::Polygon );
9231 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 64 );
9232 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 64 ); // ncoordinates is cached, so check twice
9233 : 1 : QVERIFY( surface->exteriorRing()->isClosed() );
9234 : : // too many vertices to actually check the result, let's just make sure the bounding boxes are similar
9235 : 1 : r1 = ext->boundingBox();
9236 : 1 : r2 = surface->exteriorRing()->boundingBox();
9237 : 1 : QGSCOMPARENEAR( r1.xMinimum(), r2.xMinimum(), 0.01 );
9238 : 1 : QGSCOMPARENEAR( r1.xMaximum(), r2.xMaximum(), 0.01 );
9239 : 1 : QGSCOMPARENEAR( r1.yMinimum(), r2.yMinimum(), 0.01 );
9240 : 1 : QGSCOMPARENEAR( r1.yMaximum(), r2.yMaximum(), 0.01 );
9241 : 1 : ring = new QgsCircularString();
9242 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
9243 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
9244 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
9245 : 1 : p12a.addInteriorRing( ring );
9246 : 1 : surface.reset( p12a.toPolygon() );
9247 : 1 : QCOMPARE( surface->wkbType(), QgsWkbTypes::Polygon );
9248 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 64 );
9249 : 1 : QCOMPARE( surface->exteriorRing()->nCoordinates(), 64 ); //ncoordinates is cached, so check twice
9250 : 1 : QVERIFY( surface->exteriorRing()->isClosed() );
9251 : 1 : QCOMPARE( surface->numInteriorRings(), 1 );
9252 : : // too many vertices to actually check the result, let's just make sure the bounding boxes are similar
9253 : 1 : r1 = ring->boundingBox();
9254 : 1 : r2 = surface->interiorRing( 0 )->boundingBox();
9255 : 1 : QGSCOMPARENEAR( r1.xMinimum(), r2.xMinimum(), 0.0001 );
9256 : 1 : QGSCOMPARENEAR( r1.xMaximum(), r2.xMaximum(), 0.0001 );
9257 : 1 : QGSCOMPARENEAR( r1.yMinimum(), r2.yMinimum(), 0.0001 );
9258 : 1 : QGSCOMPARENEAR( r1.yMaximum(), r2.yMaximum(), 0.0001 );
9259 : :
9260 : : //toCurveType - should be identical since it's already a curve
9261 : 1 : std::unique_ptr< QgsCurvePolygon > curveType( p12a.toCurveType() );
9262 : 1 : QCOMPARE( *curveType, p12a );
9263 : :
9264 : : //to/fromWKB
9265 : 1 : QgsCurvePolygon p16;
9266 : 1 : ext = new QgsCircularString();
9267 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 2, 0 )
9268 : 1 : << QgsPoint( 1, 0.5 ) << QgsPoint( 0, 0 ) );
9269 : 1 : p16.setExteriorRing( ext );
9270 : 1 : ring = new QgsCircularString();
9271 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.1, 0 ) << QgsPoint( 0.2, 0 )
9272 : 1 : << QgsPoint( 0.1, 0.05 ) << QgsPoint( 0, 0 ) );
9273 : 1 : p16.addInteriorRing( ring );
9274 : 1 : QByteArray wkb16 = p16.asWkb();
9275 : 1 : QCOMPARE( wkb16.size(), p16.wkbSize() );
9276 : 1 : QgsCurvePolygon p17;
9277 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
9278 : 1 : p17.fromWkb( wkb16ptr );
9279 : 1 : QCOMPARE( p16, p17 );
9280 : : //CurvePolygonZ
9281 : 1 : p16.clear();
9282 : 1 : p17.clear();
9283 : :
9284 : 1 : ext = new QgsCircularString();
9285 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 1, 0, 2 ) << QgsPoint( 2, 0, 3 )
9286 : 1 : << QgsPoint( 1, 0.5, 4 ) << QgsPoint( 0, 0, 1 ) );
9287 : 1 : p16.setExteriorRing( ext );
9288 : 1 : ring = new QgsCircularString();
9289 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 0.1, 0, 2 ) << QgsPoint( 0.2, 0, 3 )
9290 : 1 : << QgsPoint( 0.1, 0.05, 4 ) << QgsPoint( 0, 0, 1 ) );
9291 : 1 : p16.addInteriorRing( ring );
9292 : 1 : wkb16 = p16.asWkb();
9293 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
9294 : 1 : p17.fromWkb( wkb16ptr2 );
9295 : 1 : QCOMPARE( p16, p17 );
9296 : :
9297 : : // compound curve
9298 : 1 : QgsCompoundCurve *cCurve = new QgsCompoundCurve();
9299 : 1 : ext = new QgsCircularString();
9300 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 1, 0, 2 ) << QgsPoint( 2, 0, 3 )
9301 : 1 : << QgsPoint( 1, 0.5, 4 ) << QgsPoint( 0, 0, 1 ) );
9302 : 1 : cCurve->addCurve( ext );
9303 : 1 : p16.addInteriorRing( cCurve );
9304 : 1 : wkb16 = p16.asWkb();
9305 : 1 : QCOMPARE( wkb16.size(), p16.wkbSize() );
9306 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
9307 : 1 : p17.fromWkb( wkb16ptr3 );
9308 : 1 : QCOMPARE( p16, p17 );
9309 : :
9310 : : //CurvePolygonM
9311 : 1 : p16.clear();
9312 : 1 : p17.clear();
9313 : 1 : ext = new QgsCircularString();
9314 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 1, 0, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 2, 0, 0, 3 )
9315 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1, 0.5, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
9316 : 1 : p16.setExteriorRing( ext );
9317 : 1 : ring = new QgsCircularString();
9318 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 0.1, 0, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 0.2, 0, 0, 3 )
9319 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0.1, 0.05, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
9320 : 1 : p16.addInteriorRing( ring );
9321 : 1 : wkb16 = p16.asWkb();
9322 : 1 : QgsConstWkbPtr wkb16ptr8( wkb16 );
9323 : 1 : p17.fromWkb( wkb16ptr8 );
9324 : 1 : QCOMPARE( p16, p17 );
9325 : :
9326 : : //CurvePolygonZM
9327 : 1 : p16.clear();
9328 : 1 : p17.clear();
9329 : 1 : ext = new QgsCircularString();
9330 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 0, 12, 3 )
9331 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 0.5, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9332 : 1 : p16.setExteriorRing( ext );
9333 : 1 : ring = new QgsCircularString();
9334 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 0.1, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 0.2, 0, 12, 3 )
9335 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0.1, 0.05, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9336 : 1 : p16.addInteriorRing( ring );
9337 : 1 : wkb16 = p16.asWkb();
9338 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
9339 : 1 : p17.fromWkb( wkb16ptr4 );
9340 : 1 : QCOMPARE( p16, p17 );
9341 : :
9342 : : //bad WKB - check for no crash
9343 : 1 : p17.clear();
9344 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
9345 : 1 : QVERIFY( !p17.fromWkb( nullPtr ) );
9346 : 1 : QCOMPARE( p17.wkbType(), QgsWkbTypes::CurvePolygon );
9347 : 1 : QgsPoint point( 1, 2 );
9348 : 1 : QByteArray wkbPoint = point.asWkb();
9349 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
9350 : 1 : QVERIFY( !p17.fromWkb( wkbPointPtr ) );
9351 : 1 : QCOMPARE( p17.wkbType(), QgsWkbTypes::CurvePolygon );
9352 : :
9353 : : //to/from WKT
9354 : 1 : QgsCurvePolygon p18;
9355 : 1 : ext = new QgsCircularString();
9356 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 0, 12, 3 )
9357 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 0.5, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9358 : 1 : p18.setExteriorRing( ext );
9359 : 1 : ring = new QgsCircularString();
9360 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 0.1, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 0.2, 0, 12, 3 )
9361 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0.1, 0.05, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9362 : 1 : p18.addInteriorRing( ring );
9363 : :
9364 : 1 : QString wkt = p18.asWkt();
9365 : 1 : QVERIFY( !wkt.isEmpty() );
9366 : 1 : QgsCurvePolygon p19;
9367 : 1 : QVERIFY( p19.fromWkt( wkt ) );
9368 : 1 : QCOMPARE( p18, p19 );
9369 : :
9370 : : //bad WKT
9371 : 1 : QVERIFY( !p19.fromWkt( "Point()" ) );
9372 : 1 : QVERIFY( p19.isEmpty() );
9373 : 1 : QVERIFY( !p19.exteriorRing() );
9374 : 1 : QCOMPARE( p19.numInteriorRings(), 0 );
9375 : 1 : QVERIFY( !p19.is3D() );
9376 : 1 : QVERIFY( !p19.isMeasure() );
9377 : 1 : QCOMPARE( p19.wkbType(), QgsWkbTypes::CurvePolygon );
9378 : :
9379 : :
9380 : : //as JSON
9381 : 1 : QgsCurvePolygon exportPolygon;
9382 : 1 : ext = new QgsCircularString();
9383 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 0, 12, 3 )
9384 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 0.5, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9385 : 1 : exportPolygon.setExteriorRing( ext );
9386 : :
9387 : :
9388 : : // GML document for compare
9389 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
9390 : :
9391 : : // as GML2
9392 : 2 : QString expectedSimpleGML2( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 1,0 2,0 2,0 2,0 2,0.1 1.9,0.1 1.9,0.1 1.9,0.1 1.9,0.1 1.9,0.1 1.9,0.1 1.9,0.2 1.8,0.2 1.8,0.2 1.8,0.2 1.8,0.2 1.8,0.2 1.8,0.2 1.7,0.3 1.7,0.3 1.7,0.3 1.7,0.3 1.7,0.3 1.6,0.3 1.6,0.3 1.6,0.3 1.6,0.4 1.6,0.4 1.6,0.4 1.5,0.4 1.5,0.4 1.5,0.4 1.5,0.4 1.5,0.4 1.4,0.4 1.4,0.4 1.4,0.4 1.4,0.4 1.4,0.4 1.3,0.5 1.3,0.5 1.3,0.5 1.3,0.5 1.2,0.5 1.2,0.5 1.2,0.5 1.2,0.5 1.2,0.5 1.1,0.5 1.1,0.5 1.1,0.5 1.1,0.5 1.1,0.5 1,0.5 1,0.5 1,0.5 1,0.5 0.9,0.5 0.9,0.5 0.9,0.5 0.9,0.5 0.9,0.5 0.8,0.5 0.8,0.5 0.8,0.5 0.8,0.5 0.8,0.5 0.7,0.5 0.7,0.5 0.7,0.5 0.7,0.5 0.6,0.4 0.6,0.4 0.6,0.4 0.6,0.4 0.6,0.4 0.5,0.4 0.5,0.4 0.5,0.4 0.5,0.4 0.5,0.4 0.4,0.4 0.4,0.4 0.4,0.4 0.4,0.3 0.4,0.3 0.4,0.3 0.3,0.3 0.3,0.3 0.3,0.3 0.3,0.3 0.3,0.3 0.2,0.2 0.2,0.2 0.2,0.2 0.2,0.2 0.2,0.2 0.2,0.2 0.1,0.2 0.1,0.1 0.1,0.1 0.1,0.1 0.1,0.1 0.1,0.1 0.1,0.1 0,0.1 0,0 0,0 0,0</coordinates></LinearRing></outerBoundaryIs></Polygon>" ) );
9393 : 1 : QString res = elemToString( exportPolygon.asGml2( doc, 1 ) );
9394 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
9395 : 2 : QString expectedGML2empty( QStringLiteral( "<Polygon xmlns=\"gml\"/>" ) );
9396 : 3 : QGSCOMPAREGML( elemToString( QgsCurvePolygon().asGml2( doc ) ), expectedGML2empty );
9397 : :
9398 : : //as GML3
9399 : 2 : QString expectedSimpleGML3( QStringLiteral( "<Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"3\">0 0 10 1 0 11 2 0 12 1 0.5 13 0 0 10</posList></ArcString></segments></Curve></exterior></Polygon>" ) );
9400 : 1 : res = elemToString( exportPolygon.asGml3( doc, 2 ) );
9401 : 1 : QCOMPARE( elemToString( exportPolygon.asGml3( doc ) ), expectedSimpleGML3 );
9402 : 2 : QString expectedGML3empty( QStringLiteral( "<Polygon xmlns=\"gml\"/>" ) );
9403 : 3 : QGSCOMPAREGML( elemToString( QgsCurvePolygon().asGml3( doc ) ), expectedGML3empty );
9404 : :
9405 : : // as JSON
9406 : 1 : QString expectedSimpleJson( "{\"coordinates\":[[[0.0,0.0,10.0],[1.0,0.0,11.0],[2.0,0.0,12.0],[2.0,0.0,12.0],[2.0,0.0,12.0],[2.0,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.2],[1.9,0.2,12.2],[1.8,0.2,12.2],[1.8,0.2,12.2],[1.8,0.2,12.2],[1.8,0.2,12.3],[1.8,0.2,12.3],[1.8,0.2,12.3],[1.7,0.3,12.3],[1.7,0.3,12.3],[1.7,0.3,12.4],[1.7,0.3,12.4],[1.7,0.3,12.4],[1.6,0.3,12.4],[1.6,0.3,12.4],[1.6,0.3,12.4],[1.6,0.4,12.5],[1.6,0.4,12.5],[1.6,0.4,12.5],[1.5,0.4,12.5],[1.5,0.4,12.5],[1.5,0.4,12.6],[1.5,0.4,12.6],[1.5,0.4,12.6],[1.4,0.4,12.6],[1.4,0.4,12.6],[1.4,0.4,12.7],[1.4,0.4,12.7],[1.4,0.4,12.7],[1.3,0.5,12.7],[1.3,0.5,12.7],[1.3,0.5,12.7],[1.3,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,13.0],[1.0,0.5,13.0],[1.0,0.5,13.0],[1.0,0.5,13.0],[1.0,0.5,12.9],[0.9,0.5,12.9],[0.9,0.5,12.8],[0.9,0.5,12.7],[0.9,0.5,12.7],[0.9,0.5,12.6],[0.8,0.5,12.6],[0.8,0.5,12.5],[0.8,0.5,12.5],[0.8,0.5,12.4],[0.8,0.5,12.4],[0.7,0.5,12.3],[0.7,0.5,12.2],[0.7,0.5,12.2],[0.7,0.5,12.1],[0.6,0.4,12.1],[0.6,0.4,12.0],[0.6,0.4,12.0],[0.6,0.4,11.9],[0.6,0.4,11.9],[0.5,0.4,11.8],[0.5,0.4,11.7],[0.5,0.4,11.7],[0.5,0.4,11.6],[0.5,0.4,11.6],[0.4,0.4,11.5],[0.4,0.4,11.5],[0.4,0.4,11.4],[0.4,0.3,11.3],[0.4,0.3,11.3],[0.4,0.3,11.2],[0.3,0.3,11.2],[0.3,0.3,11.1],[0.3,0.3,11.1],[0.3,0.3,11.0],[0.3,0.3,11.0],[0.2,0.2,10.9],[0.2,0.2,10.8],[0.2,0.2,10.8],[0.2,0.2,10.7],[0.2,0.2,10.7],[0.2,0.2,10.6],[0.1,0.2,10.6],[0.1,0.1,10.5],[0.1,0.1,10.4],[0.1,0.1,10.4],[0.1,0.1,10.3],[0.1,0.1,10.3],[0.1,0.1,10.2],[0.0,0.1,10.2],[0.0,0.0,10.1],[0.0,0.0,10.1],[0.0,0.0,10.0]]],\"type\":\"Polygon\"}" );
9407 : 1 : res = exportPolygon.asJson( 1 );
9408 : 1 : QCOMPARE( res, expectedSimpleJson );
9409 : :
9410 : 1 : ring = new QgsCircularString();
9411 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 0.1, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 0.2, 0, 12, 3 )
9412 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0.1, 0.05, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9413 : 1 : exportPolygon.addInteriorRing( ring );
9414 : :
9415 : 1 : QString expectedJson( "{\"coordinates\":[[[0.0,0.0,10.0],[1.0,0.0,11.0],[2.0,0.0,12.0],[2.0,0.0,12.0],[2.0,0.0,12.0],[2.0,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.1],[1.9,0.1,12.2],[1.9,0.2,12.2],[1.8,0.2,12.2],[1.8,0.2,12.2],[1.8,0.2,12.2],[1.8,0.2,12.3],[1.8,0.2,12.3],[1.8,0.2,12.3],[1.7,0.3,12.3],[1.7,0.3,12.3],[1.7,0.3,12.4],[1.7,0.3,12.4],[1.7,0.3,12.4],[1.6,0.3,12.4],[1.6,0.3,12.4],[1.6,0.3,12.4],[1.6,0.4,12.5],[1.6,0.4,12.5],[1.6,0.4,12.5],[1.5,0.4,12.5],[1.5,0.4,12.5],[1.5,0.4,12.6],[1.5,0.4,12.6],[1.5,0.4,12.6],[1.4,0.4,12.6],[1.4,0.4,12.6],[1.4,0.4,12.7],[1.4,0.4,12.7],[1.4,0.4,12.7],[1.3,0.5,12.7],[1.3,0.5,12.7],[1.3,0.5,12.7],[1.3,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.8],[1.2,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,12.9],[1.1,0.5,13.0],[1.0,0.5,13.0],[1.0,0.5,13.0],[1.0,0.5,13.0],[1.0,0.5,12.9],[0.9,0.5,12.9],[0.9,0.5,12.8],[0.9,0.5,12.7],[0.9,0.5,12.7],[0.9,0.5,12.6],[0.8,0.5,12.6],[0.8,0.5,12.5],[0.8,0.5,12.5],[0.8,0.5,12.4],[0.8,0.5,12.4],[0.7,0.5,12.3],[0.7,0.5,12.2],[0.7,0.5,12.2],[0.7,0.5,12.1],[0.6,0.4,12.1],[0.6,0.4,12.0],[0.6,0.4,12.0],[0.6,0.4,11.9],[0.6,0.4,11.9],[0.5,0.4,11.8],[0.5,0.4,11.7],[0.5,0.4,11.7],[0.5,0.4,11.6],[0.5,0.4,11.6],[0.4,0.4,11.5],[0.4,0.4,11.5],[0.4,0.4,11.4],[0.4,0.3,11.3],[0.4,0.3,11.3],[0.4,0.3,11.2],[0.3,0.3,11.2],[0.3,0.3,11.1],[0.3,0.3,11.1],[0.3,0.3,11.0],[0.3,0.3,11.0],[0.2,0.2,10.9],[0.2,0.2,10.8],[0.2,0.2,10.8],[0.2,0.2,10.7],[0.2,0.2,10.7],[0.2,0.2,10.6],[0.1,0.2,10.6],[0.1,0.1,10.5],[0.1,0.1,10.4],[0.1,0.1,10.4],[0.1,0.1,10.3],[0.1,0.1,10.3],[0.1,0.1,10.2],[0.0,0.1,10.2],[0.0,0.0,10.1],[0.0,0.0,10.1],[0.0,0.0,10.0]],[[0.0,0.0,10.0],[0.1,0.0,11.0],[0.2,0.0,12.0],[0.2,0.0,12.0],[0.2,0.0,12.0],[0.2,0.0,12.1],[0.2,0.0,12.1],[0.2,0.0,12.1],[0.2,0.0,12.1],[0.2,0.0,12.1],[0.2,0.0,12.1],[0.2,0.0,12.2],[0.2,0.0,12.2],[0.2,0.0,12.2],[0.2,0.0,12.2],[0.2,0.0,12.2],[0.2,0.0,12.3],[0.2,0.0,12.3],[0.2,0.0,12.3],[0.2,0.0,12.3],[0.2,0.0,12.3],[0.2,0.0,12.4],[0.2,0.0,12.4],[0.2,0.0,12.4],[0.2,0.0,12.4],[0.2,0.0,12.4],[0.2,0.0,12.4],[0.2,0.0,12.5],[0.2,0.0,12.5],[0.2,0.0,12.5],[0.2,0.0,12.5],[0.2,0.0,12.5],[0.1,0.0,12.6],[0.1,0.0,12.6],[0.1,0.0,12.6],[0.1,0.0,12.6],[0.1,0.0,12.6],[0.1,0.0,12.7],[0.1,0.0,12.7],[0.1,0.0,12.7],[0.1,0.0,12.7],[0.1,0.0,12.7],[0.1,0.0,12.7],[0.1,0.0,12.8],[0.1,0.0,12.8],[0.1,0.0,12.8],[0.1,0.0,12.8],[0.1,0.0,12.8],[0.1,0.0,12.9],[0.1,0.0,12.9],[0.1,0.0,12.9],[0.1,0.0,12.9],[0.1,0.0,12.9],[0.1,0.0,13.0],[0.1,0.0,13.0],[0.1,0.0,13.0],[0.1,0.0,13.0],[0.1,0.0,12.9],[0.1,0.0,12.9],[0.1,0.0,12.8],[0.1,0.0,12.7],[0.1,0.0,12.7],[0.1,0.0,12.6],[0.1,0.0,12.6],[0.1,0.0,12.5],[0.1,0.0,12.5],[0.1,0.0,12.4],[0.1,0.0,12.4],[0.1,0.0,12.3],[0.1,0.0,12.2],[0.1,0.0,12.2],[0.1,0.0,12.1],[0.1,0.0,12.1],[0.1,0.0,12.0],[0.1,0.0,12.0],[0.1,0.0,11.9],[0.1,0.0,11.9],[0.1,0.0,11.8],[0.1,0.0,11.7],[0.1,0.0,11.7],[0.0,0.0,11.6],[0.0,0.0,11.6],[0.0,0.0,11.5],[0.0,0.0,11.5],[0.0,0.0,11.4],[0.0,0.0,11.3],[0.0,0.0,11.3],[0.0,0.0,11.2],[0.0,0.0,11.2],[0.0,0.0,11.1],[0.0,0.0,11.1],[0.0,0.0,11.0],[0.0,0.0,11.0],[0.0,0.0,10.9],[0.0,0.0,10.8],[0.0,0.0,10.8],[0.0,0.0,10.7],[0.0,0.0,10.7],[0.0,0.0,10.6],[0.0,0.0,10.6],[0.0,0.0,10.5],[0.0,0.0,10.4],[0.0,0.0,10.4],[0.0,0.0,10.3],[0.0,0.0,10.3],[0.0,0.0,10.2],[0.0,0.0,10.2],[0.0,0.0,10.1],[0.0,0.0,10.1],[0.0,0.0,10.0]]],\"type\":\"Polygon\"}" );
9416 : 1 : res = exportPolygon.asJson( 1 );
9417 : 1 : QCOMPARE( res, expectedJson );
9418 : :
9419 : : //asKML
9420 : 2 : QString expectedKml( QStringLiteral( "<Polygon><outerBoundaryIs><LinearRing><altitudeMode>absolute</altitudeMode><coordinates>0,0,10 1,0,11 2,0,12 2,0,12 2,0,12 2,0.1,12.1 1.9,0.1,12.1 1.9,0.1,12.1 1.9,0.1,12.1 1.9,0.1,12.1 1.9,0.1,12.1 1.9,0.1,12.2 1.9,0.2,12.2 1.8,0.2,12.2 1.8,0.2,12.2 1.8,0.2,12.2 1.8,0.2,12.3 1.8,0.2,12.3 1.8,0.2,12.3 1.7,0.3,12.3 1.7,0.3,12.3 1.7,0.3,12.4 1.7,0.3,12.4 1.7,0.3,12.4 1.6,0.3,12.4 1.6,0.3,12.4 1.6,0.3,12.4 1.6,0.4,12.5 1.6,0.4,12.5 1.6,0.4,12.5 1.5,0.4,12.5 1.5,0.4,12.5 1.5,0.4,12.6 1.5,0.4,12.6 1.5,0.4,12.6 1.4,0.4,12.6 1.4,0.4,12.6 1.4,0.4,12.7 1.4,0.4,12.7 1.4,0.4,12.7 1.3,0.5,12.7 1.3,0.5,12.7 1.3,0.5,12.7 1.3,0.5,12.8 1.2,0.5,12.8 1.2,0.5,12.8 1.2,0.5,12.8 1.2,0.5,12.8 1.2,0.5,12.9 1.1,0.5,12.9 1.1,0.5,12.9 1.1,0.5,12.9 1.1,0.5,12.9 1.1,0.5,13 1,0.5,13 1,0.5,13 1,0.5,13 1,0.5,12.9 0.9,0.5,12.9 0.9,0.5,12.8 0.9,0.5,12.7 0.9,0.5,12.7 0.9,0.5,12.6 0.8,0.5,12.6 0.8,0.5,12.5 0.8,0.5,12.5 0.8,0.5,12.4 0.8,0.5,12.4 0.7,0.5,12.3 0.7,0.5,12.2 0.7,0.5,12.2 0.7,0.5,12.1 0.6,0.4,12.1 0.6,0.4,12 0.6,0.4,12 0.6,0.4,11.9 0.6,0.4,11.9 0.5,0.4,11.8 0.5,0.4,11.7 0.5,0.4,11.7 0.5,0.4,11.6 0.5,0.4,11.6 0.4,0.4,11.5 0.4,0.4,11.5 0.4,0.4,11.4 0.4,0.3,11.3 0.4,0.3,11.3 0.4,0.3,11.2 0.3,0.3,11.2 0.3,0.3,11.1 0.3,0.3,11.1 0.3,0.3,11 0.3,0.3,11 0.2,0.2,10.9 0.2,0.2,10.8 0.2,0.2,10.8 0.2,0.2,10.7 0.2,0.2,10.7 0.2,0.2,10.6 0.1,0.2,10.6 0.1,0.1,10.5 0.1,0.1,10.4 0.1,0.1,10.4 0.1,0.1,10.3 0.1,0.1,10.3 0.1,0.1,10.2 0,0.1,10.2 0,0,10.1 0,0,10.1 0,0,10</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><altitudeMode>absolute</altitudeMode><coordinates>0,0,10 0.1,0,11 0.2,0,12 0.2,0,12 0.2,0,12 0.2,0,12.1 0.2,0,12.1 0.2,0,12.1 0.2,0,12.1 0.2,0,12.1 0.2,0,12.1 0.2,0,12.2 0.2,0,12.2 0.2,0,12.2 0.2,0,12.2 0.2,0,12.2 0.2,0,12.3 0.2,0,12.3 0.2,0,12.3 0.2,0,12.3 0.2,0,12.3 0.2,0,12.4 0.2,0,12.4 0.2,0,12.4 0.2,0,12.4 0.2,0,12.4 0.2,0,12.4 0.2,0,12.5 0.2,0,12.5 0.2,0,12.5 0.2,0,12.5 0.2,0,12.5 0.1,0,12.6 0.1,0,12.6 0.1,0,12.6 0.1,0,12.6 0.1,0,12.6 0.1,0,12.7 0.1,0,12.7 0.1,0,12.7 0.1,0,12.7 0.1,0,12.7 0.1,0,12.7 0.1,0,12.8 0.1,0,12.8 0.1,0,12.8 0.1,0,12.8 0.1,0,12.8 0.1,0,12.9 0.1,0,12.9 0.1,0,12.9 0.1,0,12.9 0.1,0,12.9 0.1,0,13 0.1,0,13 0.1,0,13 0.1,0,13 0.1,0,12.9 0.1,0,12.9 0.1,0,12.8 0.1,0,12.7 0.1,0,12.7 0.1,0,12.6 0.1,0,12.6 0.1,0,12.5 0.1,0,12.5 0.1,0,12.4 0.1,0,12.4 0.1,0,12.3 0.1,0,12.2 0.1,0,12.2 0.1,0,12.1 0.1,0,12.1 0.1,0,12 0.1,0,12 0.1,0,11.9 0.1,0,11.9 0.1,0,11.8 0.1,0,11.7 0.1,0,11.7 0,0,11.6 0,0,11.6 0,0,11.5 0,0,11.5 0,0,11.4 0,0,11.3 0,0,11.3 0,0,11.2 0,0,11.2 0,0,11.1 0,0,11.1 0,0,11 0,0,11 0,0,10.9 0,0,10.8 0,0,10.8 0,0,10.7 0,0,10.7 0,0,10.6 0,0,10.6 0,0,10.5 0,0,10.4 0,0,10.4 0,0,10.3 0,0,10.3 0,0,10.2 0,0,10.2 0,0,10.1 0,0,10.1 0,0,10</coordinates></LinearRing></innerBoundaryIs></Polygon>" ) );
9421 : 1 : QCOMPARE( exportPolygon.asKml( 1 ), expectedKml );
9422 : :
9423 : :
9424 : 1 : QgsCurvePolygon exportPolygonFloat;
9425 : 1 : ext = new QgsCircularString();
9426 : 2 : ext->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 1 / 3.0, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 2 / 3.0, 0, 12, 3 )
9427 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1 / 3.0, 0.5, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9428 : 1 : exportPolygonFloat.setExteriorRing( ext );
9429 : 1 : ring = new QgsCircularString();
9430 : 2 : ring->setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 0.1 / 3.0, 0, 11, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 0.2 / 3.0, 0, 12, 3 )
9431 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0.1 / 3.0, 0.05 / 3.0, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 10, 1 ) );
9432 : 1 : exportPolygonFloat.addInteriorRing( ring );
9433 : :
9434 : 1 : QString expectedJsonPrec3( "{\"coordinates\":[[[0.0,0.0,10.0],[0.333,0.0,11.0],[0.667,0.0,12.0],[0.669,0.006,12.009],[0.671,0.012,12.018],[0.673,0.018,12.027],[0.676,0.024,12.035],[0.677,0.029,12.044],[0.679,0.035,12.053],[0.681,0.042,12.062],[0.683,0.048,12.071],[0.684,0.054,12.08],[0.686,0.06,12.088],[0.687,0.066,12.097],[0.688,0.072,12.106],[0.689,0.078,12.115],[0.69,0.084,12.124],[0.691,0.091,12.133],[0.692,0.097,12.142],[0.693,0.103,12.15],[0.693,0.109,12.159],[0.694,0.116,12.168],[0.694,0.122,12.177],[0.694,0.128,12.186],[0.694,0.135,12.195],[0.694,0.141,12.204],[0.694,0.147,12.212],[0.694,0.153,12.221],[0.694,0.16,12.23],[0.693,0.166,12.239],[0.693,0.172,12.248],[0.692,0.178,12.257],[0.692,0.185,12.265],[0.691,0.191,12.274],[0.69,0.197,12.283],[0.689,0.203,12.292],[0.687,0.209,12.301],[0.686,0.216,12.31],[0.685,0.222,12.319],[0.683,0.228,12.327],[0.682,0.234,12.336],[0.68,0.24,12.345],[0.678,0.246,12.354],[0.676,0.252,12.363],[0.674,0.258,12.372],[0.672,0.264,12.381],[0.67,0.27,12.389],[0.668,0.275,12.398],[0.665,0.281,12.407],[0.663,0.287,12.416],[0.66,0.293,12.425],[0.657,0.298,12.434],[0.654,0.304,12.442],[0.652,0.31,12.451],[0.649,0.315,12.46],[0.645,0.321,12.469],[0.642,0.326,12.478],[0.639,0.331,12.487],[0.636,0.337,12.496],[0.632,0.342,12.504],[0.628,0.347,12.513],[0.625,0.352,12.522],[0.621,0.357,12.531],[0.617,0.362,12.54],[0.613,0.367,12.549],[0.609,0.372,12.558],[0.605,0.377,12.566],[0.601,0.381,12.575],[0.597,0.386,12.584],[0.592,0.39,12.593],[0.588,0.395,12.602],[0.584,0.399,12.611],[0.579,0.404,12.619],[0.574,0.408,12.628],[0.57,0.412,12.637],[0.565,0.416,12.646],[0.56,0.42,12.655],[0.555,0.424,12.664],[0.55,0.428,12.673],[0.545,0.431,12.681],[0.54,0.435,12.69],[0.535,0.439,12.699],[0.529,0.442,12.708],[0.524,0.445,12.717],[0.519,0.449,12.726],[0.513,0.452,12.735],[0.508,0.455,12.743],[0.502,0.458,12.752],[0.497,0.461,12.761],[0.491,0.464,12.77],[0.485,0.466,12.779],[0.48,0.469,12.788],[0.474,0.471,12.796],[0.468,0.474,12.805],[0.462,0.476,12.814],[0.456,0.478,12.823],[0.451,0.48,12.832],[0.445,0.482,12.841],[0.439,0.484,12.85],[0.433,0.486,12.858],[0.426,0.488,12.867],[0.42,0.489,12.876],[0.414,0.491,12.885],[0.408,0.492,12.894],[0.402,0.493,12.903],[0.396,0.495,12.912],[0.39,0.496,12.92],[0.383,0.497,12.929],[0.377,0.497,12.938],[0.371,0.498,12.947],[0.365,0.499,12.956],[0.358,0.499,12.965],[0.352,0.5,12.973],[0.346,0.5,12.982],[0.34,0.5,12.991],[0.333,0.5,13.0],[0.327,0.5,12.973],[0.321,0.5,12.947],[0.314,0.5,12.92],[0.308,0.499,12.894],[0.302,0.499,12.867],[0.296,0.498,12.841],[0.289,0.497,12.814],[0.283,0.497,12.788],[0.277,0.496,12.761],[0.271,0.495,12.735],[0.265,0.493,12.708],[0.259,0.492,12.681],[0.252,0.491,12.655],[0.246,0.489,12.628],[0.24,0.488,12.602],[0.234,0.486,12.575],[0.228,0.484,12.549],[0.222,0.482,12.522],[0.216,0.48,12.496],[0.21,0.478,12.469],[0.204,0.476,12.442],[0.198,0.474,12.416],[0.193,0.471,12.389],[0.187,0.469,12.363],[0.181,0.466,12.336],[0.176,0.464,12.31],[0.17,0.461,12.283],[0.164,0.458,12.257],[0.159,0.455,12.23],[0.153,0.452,12.204],[0.148,0.449,12.177],[0.143,0.445,12.15],[0.137,0.442,12.124],[0.132,0.439,12.097],[0.127,0.435,12.071],[0.122,0.431,12.044],[0.117,0.428,12.018],[0.112,0.424,11.991],[0.107,0.42,11.965],[0.102,0.416,11.938],[0.097,0.412,11.912],[0.092,0.408,11.885],[0.088,0.404,11.858],[0.083,0.399,11.832],[0.079,0.395,11.805],[0.074,0.39,11.779],[0.07,0.386,11.752],[0.066,0.381,11.726],[0.061,0.377,11.699],[0.057,0.372,11.673],[0.053,0.367,11.646],[0.049,0.362,11.619],[0.046,0.357,11.593],[0.042,0.352,11.566],[0.038,0.347,11.54],[0.035,0.342,11.513],[0.031,0.337,11.487],[0.028,0.331,11.46],[0.024,0.326,11.434],[0.021,0.321,11.407],[0.018,0.315,11.381],[0.015,0.31,11.354],[0.012,0.304,11.327],[0.009,0.298,11.301],[0.007,0.293,11.274],[0.004,0.287,11.248],[0.001,0.281,11.221],[-0.001,0.275,11.195],[-0.003,0.27,11.168],[-0.005,0.264,11.142],[-0.008,0.258,11.115],[-0.01,0.252,11.088],[-0.012,0.246,11.062],[-0.013,0.24,11.035],[-0.015,0.234,11.009],[-0.017,0.228,10.982],[-0.018,0.222,10.956],[-0.02,0.216,10.929],[-0.021,0.209,10.903],[-0.022,0.203,10.876],[-0.023,0.197,10.85],[-0.024,0.191,10.823],[-0.025,0.185,10.796],[-0.026,0.178,10.77],[-0.026,0.172,10.743],[-0.027,0.166,10.717],[-0.027,0.16,10.69],[-0.027,0.153,10.664],[-0.028,0.147,10.637],[-0.028,0.141,10.611],[-0.028,0.135,10.584],[-0.028,0.128,10.558],[-0.027,0.122,10.531],[-0.027,0.116,10.504],[-0.027,0.109,10.478],[-0.026,0.103,10.451],[-0.025,0.097,10.425],[-0.025,0.091,10.398],[-0.024,0.084,10.372],[-0.023,0.078,10.345],[-0.022,0.072,10.319],[-0.02,0.066,10.292],[-0.019,0.06,10.265],[-0.018,0.054,10.239],[-0.016,0.048,10.212],[-0.014,0.042,10.186],[-0.013,0.035,10.159],[-0.011,0.029,10.133],[-0.009,0.024,10.106],[-0.007,0.018,10.08],[-0.005,0.012,10.053],[-0.002,0.006,10.027],[0.0,0.0,10.0]],[[0.0,0.0,10.0],[0.033,0.0,11.0],[0.067,0.0,12.0],[0.066,0.001,12.019],[0.066,0.001,12.037],[0.065,0.002,12.056],[0.065,0.002,12.075],[0.064,0.003,12.093],[0.064,0.003,12.112],[0.063,0.004,12.131],[0.063,0.004,12.15],[0.062,0.005,12.168],[0.062,0.005,12.187],[0.061,0.006,12.206],[0.061,0.006,12.224],[0.06,0.007,12.243],[0.06,0.007,12.262],[0.059,0.008,12.28],[0.059,0.008,12.299],[0.058,0.009,12.318],[0.057,0.009,12.336],[0.057,0.009,12.355],[0.056,0.01,12.374],[0.056,0.01,12.393],[0.055,0.011,12.411],[0.054,0.011,12.43],[0.054,0.011,12.449],[0.053,0.012,12.467],[0.052,0.012,12.486],[0.052,0.012,12.505],[0.051,0.013,12.523],[0.051,0.013,12.542],[0.05,0.013,12.561],[0.049,0.014,12.579],[0.049,0.014,12.598],[0.048,0.014,12.617],[0.047,0.014,12.636],[0.046,0.015,12.654],[0.046,0.015,12.673],[0.045,0.015,12.692],[0.044,0.015,12.71],[0.044,0.015,12.729],[0.043,0.016,12.748],[0.042,0.016,12.766],[0.042,0.016,12.785],[0.041,0.016,12.804],[0.04,0.016,12.822],[0.039,0.016,12.841],[0.039,0.016,12.86],[0.038,0.016,12.879],[0.037,0.016,12.897],[0.037,0.017,12.916],[0.036,0.017,12.935],[0.035,0.017,12.953],[0.034,0.017,12.972],[0.034,0.017,12.991],[0.033,0.017,12.972],[0.032,0.017,12.916],[0.032,0.017,12.86],[0.031,0.017,12.804],[0.03,0.017,12.748],[0.029,0.016,12.692],[0.029,0.016,12.636],[0.028,0.016,12.579],[0.027,0.016,12.523],[0.027,0.016,12.467],[0.026,0.016,12.411],[0.025,0.016,12.355],[0.024,0.016,12.299],[0.024,0.016,12.243],[0.023,0.015,12.187],[0.022,0.015,12.131],[0.022,0.015,12.075],[0.021,0.015,12.019],[0.02,0.015,11.963],[0.02,0.014,11.907],[0.019,0.014,11.85],[0.018,0.014,11.794],[0.017,0.014,11.738],[0.017,0.013,11.682],[0.016,0.013,11.626],[0.016,0.013,11.57],[0.015,0.012,11.514],[0.014,0.012,11.458],[0.014,0.012,11.402],[0.013,0.011,11.346],[0.012,0.011,11.29],[0.012,0.011,11.234],[0.011,0.01,11.178],[0.01,0.01,11.121],[0.01,0.009,11.065],[0.009,0.009,11.009],[0.009,0.009,10.953],[0.008,0.008,10.897],[0.008,0.008,10.841],[0.007,0.007,10.785],[0.006,0.007,10.729],[0.006,0.006,10.673],[0.005,0.006,10.617],[0.005,0.005,10.561],[0.004,0.005,10.505],[0.004,0.004,10.449],[0.003,0.004,10.393],[0.003,0.003,10.336],[0.002,0.003,10.28],[0.002,0.002,10.224],[0.001,0.002,10.168],[0.001,0.001,10.112],[0.0,0.001,10.056],[0.0,0.0,10.0]]],\"type\":\"Polygon\"}" );
9435 : 1 : res = exportPolygonFloat.asJson( 3 );
9436 : 1 : QCOMPARE( exportPolygonFloat.asJson( 3 ), expectedJsonPrec3 );
9437 : :
9438 : : // as GML2
9439 : 2 : QString expectedGML2( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 1,0 2,0 1.98685,0.01722 1.97341,0.03421 1.95967,0.05096 1.94564,0.06747 1.93133,0.08374 1.91674,0.09976 1.90188,0.11552 1.88674,0.13102 1.87134,0.14625 1.85567,0.16122 1.83975,0.17592 1.82358,0.19033 1.80716,0.20446 1.79049,0.21831 1.77359,0.23186 1.75646,0.24512 1.7391,0.25809 1.72151,0.27074 1.70371,0.2831 1.6857,0.29514 1.66748,0.30687 1.64907,0.31828 1.63045,0.32936 1.61165,0.34013 1.59267,0.35057 1.5735,0.36067 1.55417,0.37045 1.53466,0.37988 1.515,0.38898 1.49518,0.39773 1.47522,0.40614 1.45511,0.41421 1.43486,0.42192 1.41448,0.42928 1.39398,0.43629 1.37336,0.44294 1.35263,0.44923 1.33179,0.45516 1.31086,0.46073 1.28983,0.46594 1.26871,0.47078 1.24751,0.47525 1.22624,0.47936 1.2049,0.48309 1.18349,0.48646 1.16204,0.48945 1.14053,0.49208 1.11898,0.49432 1.0974,0.4962 1.07578,0.4977 1.05415,0.49883 1.0325,0.49958 1.01083,0.49995 0.98917,0.49995 0.9675,0.49958 0.94585,0.49883 0.92422,0.4977 0.9026,0.4962 0.88102,0.49432 0.85947,0.49208 0.83796,0.48945 0.81651,0.48646 0.7951,0.48309 0.77376,0.47936 0.75249,0.47525 0.73129,0.47078 0.71017,0.46594 0.68914,0.46073 0.66821,0.45516 0.64737,0.44923 0.62664,0.44294 0.60602,0.43629 0.58552,0.42928 0.56514,0.42192 0.54489,0.41421 0.52478,0.40614 0.50482,0.39773 0.485,0.38898 0.46534,0.37988 0.44583,0.37045 0.4265,0.36067 0.40733,0.35057 0.38835,0.34013 0.36955,0.32936 0.35093,0.31828 0.33252,0.30687 0.3143,0.29514 0.29629,0.2831 0.27849,0.27074 0.2609,0.25809 0.24354,0.24512 0.22641,0.23186 0.20951,0.21831 0.19284,0.20446 0.17642,0.19033 0.16025,0.17592 0.14433,0.16122 0.12866,0.14625 0.11326,0.13102 0.09812,0.11552 0.08326,0.09976 0.06867,0.08374 0.05436,0.06747 0.04033,0.05096 0.02659,0.03421 0.01315,0.01722 0,0</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 0.1,0 0.2,0 0.19869,0.00172 0.19734,0.00342 0.19597,0.0051 0.19456,0.00675 0.19313,0.00837 0.19167,0.00998 0.19019,0.01155 0.18867,0.0131 0.18713,0.01463 0.18557,0.01612 0.18398,0.01759 0.18236,0.01903 0.18072,0.02045 0.17905,0.02183 0.17736,0.02319 0.17565,0.02451 0.17391,0.02581 0.17215,0.02707 0.17037,0.02831 0.16857,0.02951 0.16675,0.03069 0.16491,0.03183 0.16305,0.03294 0.16117,0.03401 0.15927,0.03506 0.15735,0.03607 0.15542,0.03704 0.15347,0.03799 0.1515,0.0389 0.14952,0.03977 0.14752,0.04061 0.14551,0.04142 0.14349,0.04219 0.14145,0.04293 0.1394,0.04363 0.13734,0.04429 0.13526,0.04492 0.13318,0.04552 0.13109,0.04607 0.12898,0.04659 0.12687,0.04708 0.12475,0.04753 0.12262,0.04794 0.12049,0.04831 0.11835,0.04865 0.1162,0.04895 0.11405,0.04921 0.1119,0.04943 0.10974,0.04962 0.10758,0.04977 0.10541,0.04988 0.10325,0.04996 0.10108,0.05 0.09892,0.05 0.09675,0.04996 0.09459,0.04988 0.09242,0.04977 0.09026,0.04962 0.0881,0.04943 0.08595,0.04921 0.0838,0.04895 0.08165,0.04865 0.07951,0.04831 0.07738,0.04794 0.07525,0.04753 0.07313,0.04708 0.07102,0.04659 0.06891,0.04607 0.06682,0.04552 0.06474,0.04492 0.06266,0.04429 0.0606,0.04363 0.05855,0.04293 0.05651,0.04219 0.05449,0.04142 0.05248,0.04061 0.05048,0.03977 0.0485,0.0389 0.04653,0.03799 0.04458,0.03704 0.04265,0.03607 0.04073,0.03506 0.03883,0.03401 0.03695,0.03294 0.03509,0.03183 0.03325,0.03069 0.03143,0.02951 0.02963,0.02831 0.02785,0.02707 0.02609,0.02581 0.02435,0.02451 0.02264,0.02319 0.02095,0.02183 0.01928,0.02045 0.01764,0.01903 0.01602,0.01759 0.01443,0.01612 0.01287,0.01463 0.01133,0.0131 0.00981,0.01155 0.00833,0.00998 0.00687,0.00837 0.00544,0.00675 0.00403,0.0051 0.00266,0.00342 0.00131,0.00172 0,0</coordinates></LinearRing></innerBoundaryIs></Polygon>" ) );
9440 : 1 : res = elemToString( exportPolygon.asGml2( doc, 5 ) );
9441 : 3 : QGSCOMPAREGML( res, expectedGML2 );
9442 : :
9443 : 2 : QString expectedGML2prec2( QStringLiteral( "<Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 1,0 2,0 1.99,0.02 1.97,0.03 1.96,0.05 1.95,0.07 1.93,0.08 1.92,0.1 1.9,0.12 1.89,0.13 1.87,0.15 1.86,0.16 1.84,0.18 1.82,0.19 1.81,0.2 1.79,0.22 1.77,0.23 1.76,0.25 1.74,0.26 1.72,0.27 1.7,0.28 1.69,0.3 1.67,0.31 1.65,0.32 1.63,0.33 1.61,0.34 1.59,0.35 1.57,0.36 1.55,0.37 1.53,0.38 1.52,0.39 1.5,0.4 1.48,0.41 1.46,0.41 1.43,0.42 1.41,0.43 1.39,0.44 1.37,0.44 1.35,0.45 1.33,0.46 1.31,0.46 1.29,0.47 1.27,0.47 1.25,0.48 1.23,0.48 1.2,0.48 1.18,0.49 1.16,0.49 1.14,0.49 1.12,0.49 1.1,0.5 1.08,0.5 1.05,0.5 1.03,0.5 1.01,0.5 0.99,0.5 0.97,0.5 0.95,0.5 0.92,0.5 0.9,0.5 0.88,0.49 0.86,0.49 0.84,0.49 0.82,0.49 0.8,0.48 0.77,0.48 0.75,0.48 0.73,0.47 0.71,0.47 0.69,0.46 0.67,0.46 0.65,0.45 0.63,0.44 0.61,0.44 0.59,0.43 0.57,0.42 0.54,0.41 0.52,0.41 0.5,0.4 0.48,0.39 0.47,0.38 0.45,0.37 0.43,0.36 0.41,0.35 0.39,0.34 0.37,0.33 0.35,0.32 0.33,0.31 0.31,0.3 0.3,0.28 0.28,0.27 0.26,0.26 0.24,0.25 0.23,0.23 0.21,0.22 0.19,0.2 0.18,0.19 0.16,0.18 0.14,0.16 0.13,0.15 0.11,0.13 0.1,0.12 0.08,0.1 0.07,0.08 0.05,0.07 0.04,0.05 0.03,0.03 0.01,0.02 0,0</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 0.1,0 0.2,0 0.2,0 0.2,0 0.2,0.01 0.19,0.01 0.19,0.01 0.19,0.01 0.19,0.01 0.19,0.01 0.19,0.01 0.19,0.02 0.18,0.02 0.18,0.02 0.18,0.02 0.18,0.02 0.18,0.02 0.18,0.02 0.17,0.03 0.17,0.03 0.17,0.03 0.17,0.03 0.17,0.03 0.16,0.03 0.16,0.03 0.16,0.03 0.16,0.04 0.16,0.04 0.16,0.04 0.15,0.04 0.15,0.04 0.15,0.04 0.15,0.04 0.15,0.04 0.14,0.04 0.14,0.04 0.14,0.04 0.14,0.04 0.14,0.04 0.13,0.05 0.13,0.05 0.13,0.05 0.13,0.05 0.12,0.05 0.12,0.05 0.12,0.05 0.12,0.05 0.12,0.05 0.11,0.05 0.11,0.05 0.11,0.05 0.11,0.05 0.11,0.05 0.1,0.05 0.1,0.05 0.1,0.05 0.1,0.05 0.09,0.05 0.09,0.05 0.09,0.05 0.09,0.05 0.09,0.05 0.08,0.05 0.08,0.05 0.08,0.05 0.08,0.05 0.08,0.05 0.07,0.05 0.07,0.05 0.07,0.05 0.07,0.05 0.06,0.04 0.06,0.04 0.06,0.04 0.06,0.04 0.06,0.04 0.05,0.04 0.05,0.04 0.05,0.04 0.05,0.04 0.05,0.04 0.04,0.04 0.04,0.04 0.04,0.04 0.04,0.03 0.04,0.03 0.04,0.03 0.03,0.03 0.03,0.03 0.03,0.03 0.03,0.03 0.03,0.03 0.02,0.02 0.02,0.02 0.02,0.02 0.02,0.02 0.02,0.02 0.02,0.02 0.01,0.02 0.01,0.01 0.01,0.01 0.01,0.01 0.01,0.01 0.01,0.01 0.01,0.01 0,0.01 0,0 0,0 0,0</coordinates></LinearRing></innerBoundaryIs></Polygon>" ) );
9444 : 1 : res = elemToString( exportPolygon.asGml2( doc, 2 ) );
9445 : 3 : QGSCOMPAREGML( res, expectedGML2prec2 );
9446 : :
9447 : : //as GML3
9448 : 2 : QString expectedGML3( QStringLiteral( "<Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"3\">0 0 10 1 0 11 2 0 12 1 0.5 13 0 0 10</posList></ArcString></segments></Curve></exterior><interior xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"3\">0 0 10 0.10000000000000001 0 11 0.20000000000000001 0 12 0.10000000000000001 0.05 13 0 0 10</posList></ArcString></segments></Curve></interior></Polygon>" ) );
9449 : 1 : res = elemToString( exportPolygon.asGml3( doc ) );
9450 : 1 : QCOMPARE( res, expectedGML3 );
9451 : :
9452 : 2 : QString expectedGML3prec3( QStringLiteral( "<Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"3\">0 0 10 1 0 11 2 0 12 1 0.5 13 0 0 10</posList></ArcString></segments></Curve></exterior><interior xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"3\">0 0 10 0.1 0 11 0.2 0 12 0.1 0.05 13 0 0 10</posList></ArcString></segments></Curve></interior></Polygon>" ) );
9453 : 1 : res = elemToString( exportPolygon.asGml3( doc, 3 ) );
9454 : 1 : QCOMPARE( res, expectedGML3prec3 );
9455 : :
9456 : : //removing the fourth to last vertex removes the whole ring
9457 : 1 : QgsCurvePolygon p20;
9458 : 1 : QgsCircularString *p20ExteriorRing = new QgsCircularString();
9459 : 1 : p20ExteriorRing->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
9460 : 1 : p20.setExteriorRing( p20ExteriorRing );
9461 : 1 : QVERIFY( p20.exteriorRing() );
9462 : 1 : p20.deleteVertex( QgsVertexId( 0, 0, 2 ) );
9463 : 1 : QVERIFY( !p20.exteriorRing() );
9464 : :
9465 : : //boundary
9466 : 1 : QgsCircularString boundary1;
9467 : 2 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 1, 0, 2 ) << QgsPoint( 2, 0, 3 )
9468 : 1 : << QgsPoint( 1, 0.5, 4 ) << QgsPoint( 0, 0, 1 ) );
9469 : 1 : QgsCurvePolygon boundaryPolygon;
9470 : 1 : QVERIFY( !boundaryPolygon.boundary() );
9471 : :
9472 : 1 : boundaryPolygon.setExteriorRing( boundary1.clone() );
9473 : 1 : QgsAbstractGeometry *boundary = boundaryPolygon.boundary();
9474 : 1 : QgsCircularString *lineBoundary = dynamic_cast< QgsCircularString * >( boundary );
9475 : 1 : QVERIFY( lineBoundary );
9476 : 1 : QCOMPARE( lineBoundary->numPoints(), 5 );
9477 : 1 : QCOMPARE( lineBoundary->xAt( 0 ), 0.0 );
9478 : 1 : QCOMPARE( lineBoundary->xAt( 1 ), 1.0 );
9479 : 1 : QCOMPARE( lineBoundary->xAt( 2 ), 2.0 );
9480 : 1 : QCOMPARE( lineBoundary->xAt( 3 ), 1.0 );
9481 : 1 : QCOMPARE( lineBoundary->xAt( 4 ), 0.0 );
9482 : 1 : QCOMPARE( lineBoundary->yAt( 0 ), 0.0 );
9483 : 1 : QCOMPARE( lineBoundary->yAt( 1 ), 0.0 );
9484 : 1 : QCOMPARE( lineBoundary->yAt( 2 ), 0.0 );
9485 : 1 : QCOMPARE( lineBoundary->yAt( 3 ), 0.5 );
9486 : 1 : QCOMPARE( lineBoundary->yAt( 4 ), 0.0 );
9487 : 1 : delete boundary;
9488 : :
9489 : : // add interior rings
9490 : 1 : QgsCircularString boundaryRing1;
9491 : 1 : boundaryRing1.setPoints( QgsPointSequence() << QgsPoint( 0.1, 0.1 ) << QgsPoint( 0.2, 0.1 ) << QgsPoint( 0.2, 0.2 ) );
9492 : 1 : QgsCircularString boundaryRing2;
9493 : 1 : boundaryRing2.setPoints( QgsPointSequence() << QgsPoint( 0.8, 0.8 ) << QgsPoint( 0.9, 0.8 ) << QgsPoint( 0.9, 0.9 ) );
9494 : 1 : boundaryPolygon.setInteriorRings( QVector< QgsCurve * >() << boundaryRing1.clone() << boundaryRing2.clone() );
9495 : 1 : boundary = boundaryPolygon.boundary();
9496 : 1 : QgsMultiCurve *multiLineBoundary = dynamic_cast< QgsMultiCurve * >( boundary );
9497 : 1 : QVERIFY( multiLineBoundary );
9498 : 1 : QCOMPARE( multiLineBoundary->numGeometries(), 3 );
9499 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->numPoints(), 5 );
9500 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
9501 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
9502 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 2 ), 2.0 );
9503 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 3 ), 1.0 );
9504 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 4 ), 0.0 );
9505 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
9506 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
9507 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 2 ), 0.0 );
9508 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.5 );
9509 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 4 ), 0.0 );
9510 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->numPoints(), 3 );
9511 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 0 ), 0.1 );
9512 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 1 ), 0.2 );
9513 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 2 ), 0.2 );
9514 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 0 ), 0.1 );
9515 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 1 ), 0.1 );
9516 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 2 ), 0.2 );
9517 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->numPoints(), 3 );
9518 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 0 ), 0.8 );
9519 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 1 ), 0.9 );
9520 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 2 ), 0.9 );
9521 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 0 ), 0.8 );
9522 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 1 ), 0.8 );
9523 : 1 : QCOMPARE( dynamic_cast< QgsCircularString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 2 ), 0.9 );
9524 : 1 : boundaryPolygon.setInteriorRings( QVector< QgsCurve * >() );
9525 : 1 : delete boundary;
9526 : :
9527 : : //test boundary with z
9528 : 2 : boundary1.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 )
9529 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) );
9530 : 1 : boundaryPolygon.setExteriorRing( boundary1.clone() );
9531 : 1 : boundary = boundaryPolygon.boundary();
9532 : 1 : lineBoundary = dynamic_cast< QgsCircularString * >( boundary );
9533 : 1 : QVERIFY( lineBoundary );
9534 : 1 : QCOMPARE( lineBoundary->numPoints(), 3 );
9535 : 1 : QCOMPARE( lineBoundary->wkbType(), QgsWkbTypes::CircularStringZ );
9536 : 1 : QCOMPARE( lineBoundary->pointN( 0 ).z(), 10.0 );
9537 : 1 : QCOMPARE( lineBoundary->pointN( 1 ).z(), 15.0 );
9538 : 1 : QCOMPARE( lineBoundary->pointN( 2 ).z(), 20.0 );
9539 : 1 : delete boundary;
9540 : :
9541 : : // remove interior rings
9542 : 1 : QgsCircularString removeRingsExt;
9543 : 1 : removeRingsExt.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
9544 : 1 : QgsCurvePolygon removeRings1;
9545 : 1 : removeRings1.removeInteriorRings();
9546 : :
9547 : 1 : removeRings1.setExteriorRing( boundary1.clone() );
9548 : 1 : removeRings1.removeInteriorRings();
9549 : 1 : QCOMPARE( removeRings1.numInteriorRings(), 0 );
9550 : :
9551 : : // add interior rings
9552 : 1 : QgsCircularString removeRingsRing1;
9553 : 2 : removeRingsRing1.setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 0.1, 1, 2 ) << QgsPoint( 0, 2, 3 )
9554 : 1 : << QgsPoint( -0.1, 1.2, 4 ) << QgsPoint( 0, 0, 1 ) );
9555 : 1 : QgsCircularString removeRingsRing2;
9556 : 2 : removeRingsRing2.setPoints( QgsPointSequence() << QgsPoint( 0, 0, 1 ) << QgsPoint( 0.01, 0.1, 2 ) << QgsPoint( 0, 0.2, 3 )
9557 : 1 : << QgsPoint( -0.01, 0.12, 4 ) << QgsPoint( 0, 0, 1 ) );
9558 : 1 : removeRings1.setInteriorRings( QVector< QgsCurve * >() << removeRingsRing1.clone() << removeRingsRing2.clone() );
9559 : :
9560 : : // remove ring with size filter
9561 : 1 : removeRings1.removeInteriorRings( 0.05 );
9562 : 1 : QCOMPARE( removeRings1.numInteriorRings(), 1 );
9563 : :
9564 : : // remove ring with no size filter
9565 : 1 : removeRings1.removeInteriorRings();
9566 : 1 : QCOMPARE( removeRings1.numInteriorRings(), 0 );
9567 : :
9568 : : // cast
9569 : 1 : QVERIFY( !QgsCurvePolygon().cast( nullptr ) );
9570 : 1 : QgsCurvePolygon pCast;
9571 : 1 : QVERIFY( QgsCurvePolygon().cast( &pCast ) );
9572 : 1 : QgsCurvePolygon pCast2;
9573 : 2 : pCast2.fromWkt( QStringLiteral( "CurvePolygonZ((0 0 0, 0 1 1, 1 0 2, 0 0 0))" ) );
9574 : 1 : QVERIFY( QgsCurvePolygon().cast( &pCast2 ) );
9575 : 2 : pCast2.fromWkt( QStringLiteral( "CurvePolygonM((0 0 1, 0 1 2, 1 0 3, 0 0 1))" ) );
9576 : 1 : QVERIFY( QgsCurvePolygon().cast( &pCast2 ) );
9577 : 2 : pCast2.fromWkt( QStringLiteral( "CurvePolygonZM((0 0 0 1, 0 1 1 2, 1 0 2 3, 0 0 0 1))" ) );
9578 : 1 : QVERIFY( QgsCurvePolygon().cast( &pCast2 ) );
9579 : :
9580 : : // draw - most tests are in test_qgsgeometry.py
9581 : 1 : QgsCurvePolygon empty;
9582 : 1 : QPainter p;
9583 : 1 : empty.draw( p ); //no crash!
9584 : :
9585 : :
9586 : : // closestSegment
9587 : 1 : QgsPoint pt;
9588 : 1 : QgsVertexId v;
9589 : 1 : int leftOf = 0;
9590 : 1 : ( void )empty.closestSegment( QgsPoint( 1, 2 ), pt, v ); // empty curve, just want no crash
9591 : :
9592 : 1 : QgsCurvePolygon cp12;
9593 : 1 : QgsLineString cp12ls;
9594 : 1 : cp12ls.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 7, 12 ) << QgsPoint( 5, 15 ) << QgsPoint( 5, 10 ) );
9595 : 1 : cp12.setExteriorRing( cp12ls.clone() );
9596 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 4, 11 ), pt, v, &leftOf ), 1.0, 0.0001 );
9597 : 1 : QGSCOMPARENEAR( pt.x(), 5, 0.01 );
9598 : 1 : QGSCOMPARENEAR( pt.y(), 11, 0.01 );
9599 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
9600 : 1 : QCOMPARE( leftOf, 1 );
9601 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 8, 11 ), pt, v, &leftOf ), 2.0, 0.0001 );
9602 : 1 : QGSCOMPARENEAR( pt.x(), 7, 0.01 );
9603 : 1 : QGSCOMPARENEAR( pt.y(), 12, 0.01 );
9604 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
9605 : 1 : QCOMPARE( leftOf, 1 );
9606 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 6, 11.5 ), pt, v, &leftOf ), 0.125000, 0.0001 );
9607 : 1 : QGSCOMPARENEAR( pt.x(), 6.25, 0.01 );
9608 : 1 : QGSCOMPARENEAR( pt.y(), 11.25, 0.01 );
9609 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
9610 : 1 : QCOMPARE( leftOf, -1 );
9611 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 7, 16 ), pt, v, &leftOf ), 4.923077, 0.0001 );
9612 : 1 : QGSCOMPARENEAR( pt.x(), 5.153846, 0.01 );
9613 : 1 : QGSCOMPARENEAR( pt.y(), 14.769231, 0.01 );
9614 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
9615 : 1 : QCOMPARE( leftOf, 1 );
9616 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 5.5, 13.5 ), pt, v, &leftOf ), 0.173077, 0.0001 );
9617 : 1 : QGSCOMPARENEAR( pt.x(), 5.846154, 0.01 );
9618 : 1 : QGSCOMPARENEAR( pt.y(), 13.730769, 0.01 );
9619 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
9620 : 1 : QCOMPARE( leftOf, -1 );
9621 : : // point directly on segment
9622 : 1 : QCOMPARE( cp12.closestSegment( QgsPoint( 5, 15 ), pt, v, &leftOf ), 0.0 );
9623 : 1 : QCOMPARE( pt, QgsPoint( 5, 15 ) );
9624 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
9625 : 1 : QCOMPARE( leftOf, 0 );
9626 : :
9627 : : // with interior ring
9628 : 1 : cp12ls.setPoints( QgsPointSequence() << QgsPoint( 6, 11.5 ) << QgsPoint( 6.5, 12 ) << QgsPoint( 6, 13 ) << QgsPoint( 6, 11.5 ) );
9629 : 1 : cp12.addInteriorRing( cp12ls.clone() );
9630 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 4, 11 ), pt, v, &leftOf ), 1.0, 0.0001 );
9631 : 1 : QGSCOMPARENEAR( pt.x(), 5, 0.01 );
9632 : 1 : QGSCOMPARENEAR( pt.y(), 11, 0.01 );
9633 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
9634 : 1 : QCOMPARE( leftOf, 1 );
9635 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 8, 11 ), pt, v, &leftOf ), 2.0, 0.0001 );
9636 : 1 : QGSCOMPARENEAR( pt.x(), 7, 0.01 );
9637 : 1 : QGSCOMPARENEAR( pt.y(), 12, 0.01 );
9638 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
9639 : 1 : QCOMPARE( leftOf, 1 );
9640 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 6, 11.4 ), pt, v, &leftOf ), 0.01, 0.0001 );
9641 : 1 : QGSCOMPARENEAR( pt.x(), 6.0, 0.01 );
9642 : 1 : QGSCOMPARENEAR( pt.y(), 11.5, 0.01 );
9643 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 1 ) );
9644 : 1 : QCOMPARE( leftOf, 1 );
9645 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 7, 16 ), pt, v, &leftOf ), 4.923077, 0.0001 );
9646 : 1 : QGSCOMPARENEAR( pt.x(), 5.153846, 0.01 );
9647 : 1 : QGSCOMPARENEAR( pt.y(), 14.769231, 0.01 );
9648 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
9649 : 1 : QCOMPARE( leftOf, 1 );
9650 : 1 : QGSCOMPARENEAR( cp12.closestSegment( QgsPoint( 5.5, 13.5 ), pt, v, &leftOf ), 0.173077, 0.0001 );
9651 : 1 : QGSCOMPARENEAR( pt.x(), 5.846154, 0.01 );
9652 : 1 : QGSCOMPARENEAR( pt.y(), 13.730769, 0.01 );
9653 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
9654 : 1 : QCOMPARE( leftOf, -1 );
9655 : : // point directly on segment
9656 : 1 : QCOMPARE( cp12.closestSegment( QgsPoint( 6, 13 ), pt, v, &leftOf ), 0.0 );
9657 : 1 : QCOMPARE( pt, QgsPoint( 6, 13 ) );
9658 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 2 ) );
9659 : 1 : QCOMPARE( leftOf, 0 );
9660 : :
9661 : : //nextVertex
9662 : 1 : QgsCurvePolygon cp13;
9663 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9664 : 1 : v = QgsVertexId( 0, 0, -2 );
9665 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9666 : 1 : v = QgsVertexId( 0, 0, 10 );
9667 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9668 : 1 : QgsLineString lp22;
9669 : 1 : lp22.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
9670 : 1 : cp13.setExteriorRing( lp22.clone() );
9671 : 1 : v = QgsVertexId( 0, 0, 4 ); //out of range
9672 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9673 : 1 : v = QgsVertexId( 0, 0, -5 );
9674 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9675 : 1 : v = QgsVertexId( 0, 0, -1 );
9676 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9677 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
9678 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
9679 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9680 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
9681 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
9682 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9683 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
9684 : 1 : QCOMPARE( pt, QgsPoint( 1, 12 ) );
9685 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9686 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
9687 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
9688 : 1 : v = QgsVertexId( 0, 1, 0 );
9689 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9690 : 1 : v = QgsVertexId( 1, 0, 0 );
9691 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9692 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 1 ) ); //test that part number is maintained
9693 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
9694 : : // add interior ring
9695 : 1 : lp22.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 11, 22 ) << QgsPoint( 11, 12 ) );
9696 : 1 : cp13.addInteriorRing( lp22.clone() );
9697 : 1 : v = QgsVertexId( 0, 1, 4 ); //out of range
9698 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9699 : 1 : v = QgsVertexId( 0, 1, -5 );
9700 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9701 : 1 : v = QgsVertexId( 0, 1, -1 );
9702 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9703 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 0 ) );
9704 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
9705 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9706 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 1 ) );
9707 : 1 : QCOMPARE( pt, QgsPoint( 21, 22 ) );
9708 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9709 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 2 ) );
9710 : 1 : QCOMPARE( pt, QgsPoint( 11, 22 ) );
9711 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9712 : 1 : QCOMPARE( v, QgsVertexId( 0, 1, 3 ) );
9713 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
9714 : 1 : v = QgsVertexId( 0, 2, 0 );
9715 : 1 : QVERIFY( !cp13.nextVertex( v, pt ) );
9716 : 1 : v = QgsVertexId( 1, 1, 0 );
9717 : 1 : QVERIFY( cp13.nextVertex( v, pt ) );
9718 : 1 : QCOMPARE( v, QgsVertexId( 1, 1, 1 ) ); //test that part number is maintained
9719 : 1 : QCOMPARE( pt, QgsPoint( 21, 22 ) );
9720 : :
9721 : : // dropZValue
9722 : 1 : QgsCurvePolygon p23;
9723 : 1 : p23.dropZValue();
9724 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9725 : 1 : QgsLineString lp23;
9726 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
9727 : 1 : p23.setExteriorRing( lp23.clone() );
9728 : 1 : p23.addInteriorRing( lp23.clone() );
9729 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9730 : 1 : p23.dropZValue(); // not z
9731 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9732 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
9733 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
9734 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
9735 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
9736 : : // with z
9737 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3 ) << QgsPoint( 11, 12, 13 ) << QgsPoint( 1, 12, 23 ) << QgsPoint( 1, 2, 3 ) );
9738 : 1 : p23.clear();
9739 : 1 : p23.setExteriorRing( lp23.clone() );
9740 : 1 : p23.addInteriorRing( lp23.clone() );
9741 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygonZ );
9742 : 1 : p23.dropZValue();
9743 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9744 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
9745 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
9746 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
9747 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
9748 : : // with zm
9749 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
9750 : 1 : p23.clear();
9751 : 1 : p23.setExteriorRing( lp23.clone() );
9752 : 1 : p23.addInteriorRing( lp23.clone() );
9753 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygonZM );
9754 : 1 : p23.dropZValue();
9755 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygonM );
9756 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineStringM );
9757 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
9758 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineStringM );
9759 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
9760 : :
9761 : : // dropMValue
9762 : 1 : p23.clear();
9763 : 1 : p23.dropMValue();
9764 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9765 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
9766 : 1 : p23.setExteriorRing( lp23.clone() );
9767 : 1 : p23.addInteriorRing( lp23.clone() );
9768 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9769 : 1 : p23.dropMValue(); // not zm
9770 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9771 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
9772 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
9773 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
9774 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
9775 : : // with m
9776 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 13 ) << QgsPoint( QgsWkbTypes::PointM, 1, 12, 0, 23 ) << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) );
9777 : 1 : p23.clear();
9778 : 1 : p23.setExteriorRing( lp23.clone() );
9779 : 1 : p23.addInteriorRing( lp23.clone() );
9780 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygonM );
9781 : 1 : p23.dropMValue();
9782 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygon );
9783 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineString );
9784 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( 1, 2 ) );
9785 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineString );
9786 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
9787 : : // with zm
9788 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
9789 : 1 : p23.clear();
9790 : 1 : p23.setExteriorRing( lp23.clone() );
9791 : 1 : p23.addInteriorRing( lp23.clone() );
9792 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygonZM );
9793 : 1 : p23.dropMValue();
9794 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::CurvePolygonZ );
9795 : 1 : QCOMPARE( p23.exteriorRing()->wkbType(), QgsWkbTypes::LineStringZ );
9796 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
9797 : 1 : QCOMPARE( p23.interiorRing( 0 )->wkbType(), QgsWkbTypes::LineStringZ );
9798 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
9799 : :
9800 : :
9801 : : // hasCurvedSegments
9802 : 1 : QgsCurvePolygon p24;
9803 : 1 : QVERIFY( !p24.hasCurvedSegments() );
9804 : 1 : QgsLineString lp24;
9805 : 1 : lp24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
9806 : 1 : p24.setExteriorRing( lp23.clone() );
9807 : 1 : QVERIFY( !p24.hasCurvedSegments() );
9808 : 1 : QgsCircularString cs24;
9809 : 1 : cs24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
9810 : 1 : p24.addInteriorRing( cs24.clone() );
9811 : 1 : QVERIFY( p24.hasCurvedSegments() );
9812 : :
9813 : : //vertexAngle
9814 : 1 : QgsCurvePolygon p25;
9815 : 1 : ( void )p25.vertexAngle( QgsVertexId() ); //just want no crash
9816 : 1 : ( void )p25.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash
9817 : 1 : ( void )p25.vertexAngle( QgsVertexId( 0, 1, 0 ) ); //just want no crash
9818 : 1 : QgsLineString l38;
9819 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
9820 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ) );
9821 : 1 : p25.setExteriorRing( l38.clone() );
9822 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 2.35619, 0.00001 );
9823 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 1.5708, 0.0001 );
9824 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 1.17809, 0.00001 );
9825 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 0.0, 0.00001 );
9826 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 5.10509, 0.00001 );
9827 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 5 ) ), 3.92699, 0.00001 );
9828 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 0, 6 ) ), 2.35619, 0.00001 );
9829 : 1 : p25.addInteriorRing( l38.clone() );
9830 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 0 ) ), 2.35619, 0.00001 );
9831 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 1 ) ), 1.5708, 0.0001 );
9832 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 2 ) ), 1.17809, 0.00001 );
9833 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 3 ) ), 0.0, 0.00001 );
9834 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 4 ) ), 5.10509, 0.00001 );
9835 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 5 ) ), 3.92699, 0.00001 );
9836 : 1 : QGSCOMPARENEAR( p25.vertexAngle( QgsVertexId( 0, 1, 6 ) ), 2.35619, 0.00001 );
9837 : :
9838 : :
9839 : : //insert vertex
9840 : :
9841 : : //insert vertex in empty polygon
9842 : 1 : p25.clear();
9843 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9844 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 6.0, 7.0 ) ) );
9845 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9846 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9847 : 1 : QVERIFY( p25.isEmpty() );
9848 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
9849 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ) );
9850 : 1 : p25.setExteriorRing( l38.clone() );
9851 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 0.3, 0 ) ) );
9852 : 1 : QCOMPARE( p25.nCoordinates(), 8 );
9853 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 0 ), QgsPoint( 0, 0 ) );
9854 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 1 ), QgsPoint( 0.3, 0 ) );
9855 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 2 ), QgsPoint( 0.5, 0 ) );
9856 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 6.0, 7.0 ) ) );
9857 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 100 ), QgsPoint( 6.0, 7.0 ) ) );
9858 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9859 : : // first vertex
9860 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 0, 0.1 ) ) );
9861 : 1 : QCOMPARE( p25.nCoordinates(), 9 );
9862 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
9863 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 1 ), QgsPoint( 0, 0 ) );
9864 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
9865 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
9866 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 7 ), QgsPoint( 0, 2 ) );
9867 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
9868 : : // last vertex
9869 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 9 ), QgsPoint( 0.1, 0.1 ) ) );
9870 : 1 : QCOMPARE( p25.nCoordinates(), 10 );
9871 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 0 ), QgsPoint( 0.1, 0.1 ) );
9872 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 1 ), QgsPoint( 0, 0 ) );
9873 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
9874 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
9875 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
9876 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.exteriorRing() )->pointN( 9 ), QgsPoint( 0.1, 0.1 ) );
9877 : : // with interior ring
9878 : 1 : p25.addInteriorRing( l38.clone() );
9879 : 1 : QCOMPARE( p25.nCoordinates(), 17 );
9880 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 1, 1 ), QgsPoint( 0.3, 0 ) ) );
9881 : 1 : QCOMPARE( p25.nCoordinates(), 18 );
9882 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 0, 0 ) );
9883 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 0.3, 0 ) );
9884 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 0.5, 0 ) );
9885 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, -1 ), QgsPoint( 6.0, 7.0 ) ) );
9886 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 100 ), QgsPoint( 6.0, 7.0 ) ) );
9887 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 2, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9888 : : // first vertex in interior ring
9889 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 0, 0.1 ) ) );
9890 : 1 : QCOMPARE( p25.nCoordinates(), 19 );
9891 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
9892 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
9893 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
9894 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
9895 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 7 ), QgsPoint( 0, 2 ) );
9896 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
9897 : : // last vertex in interior ring
9898 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 1, 9 ), QgsPoint( 0.1, 0.1 ) ) );
9899 : 1 : QCOMPARE( p25.nCoordinates(), 20 );
9900 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 0.1, 0.1 ) );
9901 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
9902 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
9903 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
9904 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 8 ), QgsPoint( 0, 0.1 ) );
9905 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.interiorRing( 0 ) )->pointN( 9 ), QgsPoint( 0.1, 0.1 ) );
9906 : :
9907 : : //move vertex
9908 : :
9909 : : //empty polygon
9910 : 1 : QgsCurvePolygon p26;
9911 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9912 : 1 : QVERIFY( p26.isEmpty() );
9913 : :
9914 : : //valid polygon
9915 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
9916 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
9917 : 1 : p26.setExteriorRing( l38.clone() );
9918 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9919 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
9920 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
9921 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
9922 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
9923 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
9924 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 3 ), QgsPoint( 6.0, 7.0 ) );
9925 : :
9926 : : //out of range
9927 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
9928 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
9929 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 3.0, 4.0 ) ) );
9930 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
9931 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
9932 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
9933 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.exteriorRing() )->pointN( 3 ), QgsPoint( 6.0, 7.0 ) );
9934 : :
9935 : : // with interior ring
9936 : 1 : p26.addInteriorRing( l38.clone() );
9937 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
9938 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 1, 1 ), QgsPoint( 16.0, 17.0 ) ) );
9939 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 1, 2 ), QgsPoint( 26.0, 27.0 ) ) );
9940 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
9941 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
9942 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
9943 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 6.0, 7.0 ) );
9944 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 1, -1 ), QgsPoint( 3.0, 4.0 ) ) );
9945 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 1, 10 ), QgsPoint( 3.0, 4.0 ) ) );
9946 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 2, 0 ), QgsPoint( 3.0, 4.0 ) ) );
9947 : :
9948 : : //delete vertex
9949 : :
9950 : : //empty polygon
9951 : 1 : QgsCurvePolygon p27;
9952 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
9953 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 0 ) ) );
9954 : 1 : QVERIFY( p27.isEmpty() );
9955 : :
9956 : : //valid polygon
9957 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 5, 2 ) << QgsPoint( 6, 2 ) << QgsPoint( 7, 2 )
9958 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
9959 : :
9960 : 1 : p27.setExteriorRing( l38.clone() );
9961 : : //out of range vertices
9962 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, -1 ) ) );
9963 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, 100 ) ) );
9964 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 1 ) ) );
9965 : :
9966 : : //valid vertices
9967 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
9968 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
9969 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 1 ), QgsPoint( 6.0, 2.0 ) );
9970 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 2 ), QgsPoint( 7.0, 2.0 ) );
9971 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
9972 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 5 ), QgsPoint( 1.0, 2.0 ) );
9973 : :
9974 : : // delete first vertex
9975 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
9976 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
9977 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
9978 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
9979 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
9980 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 4 ), QgsPoint( 6.0, 2.0 ) );
9981 : :
9982 : : // delete last vertex
9983 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 4 ) ) );
9984 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 0 ), QgsPoint( 21.0, 22.0 ) );
9985 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
9986 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
9987 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.exteriorRing() )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
9988 : :
9989 : : // delete another vertex - should remove ring
9990 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
9991 : 1 : QVERIFY( !p27.exteriorRing() );
9992 : :
9993 : : // with interior ring
9994 : 1 : p27.setExteriorRing( l38.clone() );
9995 : 1 : p27.addInteriorRing( l38.clone() );
9996 : :
9997 : : //out of range vertices
9998 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, -1 ) ) );
9999 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 100 ) ) );
10000 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 2, 1 ) ) );
10001 : :
10002 : : //valid vertices
10003 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 1 ) ) );
10004 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
10005 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 6.0, 2.0 ) );
10006 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 7.0, 2.0 ) );
10007 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
10008 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 5 ), QgsPoint( 1.0, 2.0 ) );
10009 : :
10010 : : // delete first vertex
10011 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 0 ) ) );
10012 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
10013 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
10014 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
10015 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
10016 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 4 ), QgsPoint( 6.0, 2.0 ) );
10017 : :
10018 : : // delete last vertex
10019 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 4 ) ) );
10020 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 0 ), QgsPoint( 21.0, 22.0 ) );
10021 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
10022 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
10023 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.interiorRing( 0 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
10024 : :
10025 : : // delete another vertex - should remove ring
10026 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 1, 1 ) ) );
10027 : 1 : QCOMPARE( p27.numInteriorRings(), 0 );
10028 : 1 : QVERIFY( p27.exteriorRing() );
10029 : :
10030 : : // test that interior ring is "promoted" when exterior is removed
10031 : 1 : p27.addInteriorRing( l38.clone() );
10032 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
10033 : 1 : QCOMPARE( p27.numInteriorRings(), 1 );
10034 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
10035 : 1 : QCOMPARE( p27.numInteriorRings(), 1 );
10036 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
10037 : 1 : QCOMPARE( p27.numInteriorRings(), 1 );
10038 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
10039 : 1 : QCOMPARE( p27.numInteriorRings(), 0 );
10040 : 1 : QVERIFY( p27.exteriorRing() );
10041 : 1 : }
10042 : :
10043 : 1 : void TestQgsGeometry::compoundCurve()
10044 : : {
10045 : : //test constructors
10046 : 1 : QgsCompoundCurve l1;
10047 : 1 : QVERIFY( l1.isEmpty() );
10048 : 1 : QCOMPARE( l1.numPoints(), 0 );
10049 : 1 : QCOMPARE( l1.vertexCount(), 0 );
10050 : 1 : QCOMPARE( l1.nCoordinates(), 0 );
10051 : 1 : QCOMPARE( l1.ringCount(), 0 );
10052 : 1 : QCOMPARE( l1.partCount(), 0 );
10053 : 1 : QVERIFY( !l1.is3D() );
10054 : 1 : QVERIFY( !l1.isMeasure() );
10055 : 1 : QCOMPARE( l1.wkbType(), QgsWkbTypes::CompoundCurve );
10056 : 1 : QCOMPARE( l1.wktTypeStr(), QString( "CompoundCurve" ) );
10057 : 1 : QCOMPARE( l1.geometryType(), QString( "CompoundCurve" ) );
10058 : 1 : QCOMPARE( l1.dimension(), 1 );
10059 : 1 : QVERIFY( !l1.hasCurvedSegments() );
10060 : 1 : QCOMPARE( l1.area(), 0.0 );
10061 : 1 : QCOMPARE( l1.perimeter(), 0.0 );
10062 : 1 : QgsPointSequence pts;
10063 : 1 : l1.points( pts );
10064 : 1 : QVERIFY( pts.empty() );
10065 : :
10066 : : // empty, test some methods to make sure they don't crash
10067 : 1 : QCOMPARE( l1.nCurves(), 0 );
10068 : 1 : QVERIFY( !l1.curveAt( -1 ) );
10069 : 1 : QVERIFY( !l1.curveAt( 0 ) );
10070 : 1 : QVERIFY( !l1.curveAt( 100 ) );
10071 : 1 : l1.removeCurve( -1 );
10072 : 1 : l1.removeCurve( 0 );
10073 : 1 : l1.removeCurve( 100 );
10074 : :
10075 : : //addCurve
10076 : 1 : QgsCompoundCurve c1;
10077 : : //try to add null curve
10078 : 1 : c1.addCurve( nullptr );
10079 : 1 : QCOMPARE( c1.nCurves(), 0 );
10080 : 1 : QVERIFY( !c1.curveAt( 0 ) );
10081 : :
10082 : 1 : QgsCircularString l2;
10083 : 1 : l2.setPoints( QgsPointSequence() << QgsPoint( 1.0, 2.0 ) );
10084 : 1 : c1.addCurve( l2.clone() );
10085 : 1 : QVERIFY( !c1.isEmpty() );
10086 : 1 : QCOMPARE( c1.numPoints(), 1 );
10087 : 1 : QCOMPARE( c1.vertexCount(), 1 );
10088 : 1 : QCOMPARE( c1.nCoordinates(), 1 );
10089 : 1 : QCOMPARE( c1.ringCount(), 1 );
10090 : 1 : QCOMPARE( c1.partCount(), 1 );
10091 : 1 : QVERIFY( !c1.is3D() );
10092 : 1 : QVERIFY( !c1.isMeasure() );
10093 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::CompoundCurve );
10094 : 1 : QVERIFY( c1.hasCurvedSegments() );
10095 : 1 : QCOMPARE( c1.area(), 0.0 );
10096 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
10097 : 1 : c1.points( pts );
10098 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1.0, 2.0 ) );
10099 : :
10100 : : //adding first curve should set linestring z/m type
10101 : 1 : QgsCircularString l3;
10102 : 1 : l3.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) );
10103 : 1 : QgsCompoundCurve c2;
10104 : 1 : c2.addCurve( l3.clone() );
10105 : 1 : QVERIFY( !c2.isEmpty() );
10106 : 1 : QVERIFY( c2.is3D() );
10107 : 1 : QVERIFY( !c2.isMeasure() );
10108 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::CompoundCurveZ );
10109 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "CompoundCurveZ" ) );
10110 : 1 : c2.points( pts );
10111 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) );
10112 : :
10113 : 1 : QgsCircularString l4;
10114 : 1 : l4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 ) );
10115 : 1 : QgsCompoundCurve c4;
10116 : 1 : c4.addCurve( l4.clone() );
10117 : 1 : QVERIFY( !c4.isEmpty() );
10118 : 1 : QVERIFY( !c4.is3D() );
10119 : 1 : QVERIFY( c4.isMeasure() );
10120 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::CompoundCurveM );
10121 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "CompoundCurveM" ) );
10122 : 1 : c4.points( pts );
10123 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 ) );
10124 : :
10125 : 1 : QgsCircularString l5;
10126 : 1 : l5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
10127 : 1 : QgsCompoundCurve c5;
10128 : 1 : c5.addCurve( l5.clone() );
10129 : 1 : QVERIFY( !c5.isEmpty() );
10130 : 1 : QVERIFY( c5.is3D() );
10131 : 1 : QVERIFY( c5.isMeasure() );
10132 : 1 : QCOMPARE( c5.wkbType(), QgsWkbTypes::CompoundCurveZM );
10133 : 1 : QCOMPARE( c5.wktTypeStr(), QString( "CompoundCurveZM" ) );
10134 : 1 : c5.points( pts );
10135 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
10136 : :
10137 : : //clear
10138 : 1 : c5.clear();
10139 : 1 : QVERIFY( c5.isEmpty() );
10140 : 1 : QCOMPARE( c5.nCurves(), 0 );
10141 : 1 : QCOMPARE( c5.numPoints(), 0 );
10142 : 1 : QCOMPARE( c5.vertexCount(), 0 );
10143 : 1 : QCOMPARE( c5.nCoordinates(), 0 );
10144 : 1 : QCOMPARE( c5.ringCount(), 0 );
10145 : 1 : QCOMPARE( c5.partCount(), 0 );
10146 : 1 : QVERIFY( !c5.is3D() );
10147 : 1 : QVERIFY( !c5.isMeasure() );
10148 : 1 : QCOMPARE( c5.wkbType(), QgsWkbTypes::CompoundCurve );
10149 : :
10150 : : //addCurve
10151 : 1 : QgsCircularString l8;
10152 : 1 : QgsCompoundCurve c8;
10153 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
10154 : 1 : c8.addCurve( l8.clone() );
10155 : 1 : QVERIFY( !c8.isEmpty() );
10156 : 1 : QCOMPARE( c8.numPoints(), 3 );
10157 : 1 : QCOMPARE( c8.vertexCount(), 3 );
10158 : 1 : QCOMPARE( c8.nCoordinates(), 3 );
10159 : 1 : QCOMPARE( c8.ringCount(), 1 );
10160 : 1 : QCOMPARE( c8.partCount(), 1 );
10161 : 1 : QCOMPARE( c8.nCurves(), 1 );
10162 : 1 : QVERIFY( !c8.is3D() );
10163 : 1 : QVERIFY( !c8.isMeasure() );
10164 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurve );
10165 : 1 : QVERIFY( c8.hasCurvedSegments() );
10166 : 1 : c8.points( pts );
10167 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
10168 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 0 ) ), l8 );
10169 : 1 : QVERIFY( ! c8.curveAt( -1 ) );
10170 : 1 : QVERIFY( ! c8.curveAt( 1 ) );
10171 : :
10172 : 1 : QgsCircularString l8a;
10173 : 1 : l8a.setPoints( QgsPointSequence() << QgsPoint( 3, 4 ) << QgsPoint( 4, 5 ) << QgsPoint( 3, 6 ) );
10174 : 1 : c8.addCurve( l8a.clone() );
10175 : 1 : QCOMPARE( c8.numPoints(), 5 );
10176 : 1 : QCOMPARE( c8.vertexCount(), 5 );
10177 : 1 : QCOMPARE( c8.nCoordinates(), 5 );
10178 : 1 : QCOMPARE( c8.ringCount(), 1 );
10179 : 1 : QCOMPARE( c8.partCount(), 1 );
10180 : 1 : QCOMPARE( c8.nCurves(), 2 );
10181 : 1 : pts.clear();
10182 : 1 : c8.points( pts );
10183 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 )
10184 : : << QgsPoint( 4, 5 ) << QgsPoint( 3, 6 ) );
10185 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 0 ) ), l8 );
10186 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 1 ) ), l8a );
10187 : 1 : QVERIFY( ! c8.curveAt( -1 ) );
10188 : 1 : QVERIFY( ! c8.curveAt( 2 ) );
10189 : :
10190 : 1 : QgsLineString l8b;
10191 : 1 : l8b.setPoints( QgsPointSequence() << QgsPoint( 3, 6 ) << QgsPoint( 4, 6 ) );
10192 : 1 : c8.addCurve( l8b.clone() );
10193 : 1 : QCOMPARE( c8.numPoints(), 6 );
10194 : 1 : QCOMPARE( c8.vertexCount(), 6 );
10195 : 1 : QCOMPARE( c8.nCoordinates(), 6 );
10196 : 1 : QCOMPARE( c8.ringCount(), 1 );
10197 : 1 : QCOMPARE( c8.partCount(), 1 );
10198 : 1 : QCOMPARE( c8.nCurves(), 3 );
10199 : 1 : pts.clear();
10200 : 1 : c8.points( pts );
10201 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 )
10202 : : << QgsPoint( 4, 5 ) << QgsPoint( 3, 6 )
10203 : : << QgsPoint( 4, 6 ) );
10204 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 0 ) ), l8 );
10205 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 1 ) ), l8a );
10206 : 1 : QCOMPARE( *dynamic_cast< const QgsLineString *>( c8.curveAt( 2 ) ), l8b );
10207 : 1 : QVERIFY( ! c8.curveAt( -1 ) );
10208 : 1 : QVERIFY( ! c8.curveAt( 3 ) );
10209 : :
10210 : : //removeCurve
10211 : 1 : c8.removeCurve( -1 );
10212 : 1 : c8.removeCurve( 3 );
10213 : 1 : QCOMPARE( c8.nCurves(), 3 );
10214 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 0 ) ), l8 );
10215 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 1 ) ), l8a );
10216 : 1 : QCOMPARE( *dynamic_cast< const QgsLineString *>( c8.curveAt( 2 ) ), l8b );
10217 : 1 : c8.removeCurve( 1 );
10218 : 1 : QCOMPARE( c8.nCurves(), 2 );
10219 : 1 : QCOMPARE( *dynamic_cast< const QgsCircularString *>( c8.curveAt( 0 ) ), l8 );
10220 : 1 : QCOMPARE( *dynamic_cast< const QgsLineString *>( c8.curveAt( 1 ) ), l8b );
10221 : 1 : c8.removeCurve( 0 );
10222 : 1 : QCOMPARE( c8.nCurves(), 1 );
10223 : 1 : QCOMPARE( *dynamic_cast< const QgsLineString *>( c8.curveAt( 0 ) ), l8b );
10224 : 1 : c8.removeCurve( 0 );
10225 : 1 : QCOMPARE( c8.nCurves(), 0 );
10226 : 1 : QVERIFY( c8.isEmpty() );
10227 : :
10228 : : //addCurve with z
10229 : 1 : c8.clear();
10230 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) );
10231 : 1 : c8.addCurve( l8.clone() );
10232 : 1 : QCOMPARE( c8.numPoints(), 2 );
10233 : 1 : QVERIFY( c8.is3D() );
10234 : 1 : QVERIFY( !c8.isMeasure() );
10235 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveZ );
10236 : 1 : pts.clear();
10237 : 1 : c8.points( pts );
10238 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) );
10239 : :
10240 : : //addCurve with m
10241 : 1 : c8.clear();
10242 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) );
10243 : 1 : c8.addCurve( l8.clone() );
10244 : 1 : QCOMPARE( c8.numPoints(), 2 );
10245 : 1 : QVERIFY( !c8.is3D() );
10246 : 1 : QVERIFY( c8.isMeasure() );
10247 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveM );
10248 : 1 : c8.points( pts );
10249 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) );
10250 : :
10251 : : //addCurve with zm
10252 : 1 : c8.clear();
10253 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 4, 5 ) );
10254 : 1 : c8.addCurve( l8.clone() );
10255 : 1 : QCOMPARE( c8.numPoints(), 2 );
10256 : 1 : QVERIFY( c8.is3D() );
10257 : 1 : QVERIFY( c8.isMeasure() );
10258 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveZM );
10259 : 1 : c8.points( pts );
10260 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 4, 5 ) );
10261 : :
10262 : : //addCurve with z to non z compound curve
10263 : 1 : c8.clear();
10264 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 2 ) << QgsPoint( QgsWkbTypes::Point, 2, 3 ) );
10265 : 1 : c8.addCurve( l8.clone() );
10266 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurve );
10267 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 3, 3, 5 ) );
10268 : 1 : c8.addCurve( l8.clone() );
10269 : 1 : QVERIFY( !c8.is3D() );
10270 : 1 : QVERIFY( !c8.isMeasure() );
10271 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurve );
10272 : 1 : c8.points( pts );
10273 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 2 ) << QgsPoint( QgsWkbTypes::Point, 2, 3 )
10274 : : << QgsPoint( QgsWkbTypes::Point, 3, 3 ) );
10275 : 1 : c8.removeCurve( 1 );
10276 : :
10277 : : //addCurve with m to non m compound curve
10278 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 3, 3, 0, 5 ) );
10279 : 1 : c8.addCurve( l8.clone() );
10280 : 1 : QVERIFY( !c8.is3D() );
10281 : 1 : QVERIFY( !c8.isMeasure() );
10282 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurve );
10283 : 1 : c8.points( pts );
10284 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 2 ) << QgsPoint( QgsWkbTypes::Point, 2, 3 )
10285 : : << QgsPoint( QgsWkbTypes::Point, 3, 3 ) );
10286 : 1 : c8.removeCurve( 1 );
10287 : :
10288 : : //addCurve with zm to non m compound curve
10289 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 6, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 3, 1, 5 ) );
10290 : 1 : c8.addCurve( l8.clone() );
10291 : 1 : QVERIFY( !c8.is3D() );
10292 : 1 : QVERIFY( !c8.isMeasure() );
10293 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurve );
10294 : 1 : c8.points( pts );
10295 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 2 ) << QgsPoint( QgsWkbTypes::Point, 2, 3 )
10296 : : << QgsPoint( QgsWkbTypes::Point, 3, 3 ) );
10297 : 1 : c8.removeCurve( 1 );
10298 : :
10299 : : //addCurve with no z to z compound curve
10300 : 1 : c8.clear();
10301 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 5 ) );
10302 : 1 : c8.addCurve( l8.clone() );
10303 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveZ );
10304 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 2, 3 ) << QgsPoint( QgsWkbTypes::Point, 3, 4 ) );
10305 : 1 : c8.addCurve( l8.clone() );
10306 : 1 : QVERIFY( c8.is3D() );
10307 : 1 : QVERIFY( !c8.isMeasure() );
10308 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveZ );
10309 : 1 : c8.points( pts );
10310 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 5 )
10311 : : << QgsPoint( QgsWkbTypes::PointZ, 3, 4, 0 ) );
10312 : 1 : c8.removeCurve( 1 );
10313 : :
10314 : : //add curve with m, no z to z compound curve
10315 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 8 ) << QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 9 ) );
10316 : 1 : c8.addCurve( l8.clone() );
10317 : 1 : QVERIFY( c8.is3D() );
10318 : 1 : QVERIFY( !c8.isMeasure() );
10319 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveZ );
10320 : 1 : c8.points( pts );
10321 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 5 )
10322 : : << QgsPoint( QgsWkbTypes::PointZ, 3, 4, 0 ) );
10323 : 1 : c8.removeCurve( 1 );
10324 : :
10325 : : //add curve with zm to z compound curve
10326 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 6, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 4, 7, 9 ) );
10327 : 1 : c8.addCurve( l8.clone() );
10328 : 1 : QVERIFY( c8.is3D() );
10329 : 1 : QVERIFY( !c8.isMeasure() );
10330 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveZ );
10331 : 1 : c8.points( pts );
10332 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 5 )
10333 : : << QgsPoint( QgsWkbTypes::PointZ, 3, 4, 7 ) );
10334 : 1 : c8.removeCurve( 1 );
10335 : :
10336 : : //addCurve with no m to m compound curve
10337 : 1 : c8.clear();
10338 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 5 ) );
10339 : 1 : c8.addCurve( l8.clone() );
10340 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveM );
10341 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 2, 3 ) << QgsPoint( QgsWkbTypes::Point, 3, 4 ) );
10342 : 1 : c8.addCurve( l8.clone() );
10343 : 1 : QVERIFY( !c8.is3D() );
10344 : 1 : QVERIFY( c8.isMeasure() );
10345 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveM );
10346 : 1 : c8.points( pts );
10347 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 5 )
10348 : : << QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 0 ) );
10349 : 1 : c8.removeCurve( 1 );
10350 : :
10351 : : //add curve with z, no m to m compound curve
10352 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 2, 3, 8 ) << QgsPoint( QgsWkbTypes::PointZ, 3, 4, 9 ) );
10353 : 1 : c8.addCurve( l8.clone() );
10354 : 1 : QVERIFY( !c8.is3D() );
10355 : 1 : QVERIFY( c8.isMeasure() );
10356 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveM );
10357 : 1 : c8.points( pts );
10358 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 5 )
10359 : : << QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 0 ) );
10360 : 1 : c8.removeCurve( 1 );
10361 : :
10362 : : //add curve with zm to m compound curve
10363 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 2, 3, 6, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 4, 7, 9 ) );
10364 : 1 : c8.addCurve( l8.clone() );
10365 : 1 : QVERIFY( !c8.is3D() );
10366 : 1 : QVERIFY( c8.isMeasure() );
10367 : 1 : QCOMPARE( c8.wkbType(), QgsWkbTypes::CompoundCurveM );
10368 : 1 : c8.points( pts );
10369 : 1 : QCOMPARE( pts, QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 2, 3, 0, 5 )
10370 : : << QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 9 ) );
10371 : 1 : c8.removeCurve( 1 );
10372 : :
10373 : : // add curve and extend existing
10374 : 1 : QgsCompoundCurve c8j;
10375 : : // try to extend empty compound curve
10376 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2, 3 ) << QgsPoint( 3, 4 ) );
10377 : 1 : c8j.addCurve( l8.clone(), true );
10378 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve (CircularString (1 2, 2 3, 3 4))" ) );
10379 : : // try to add another curve with extend existing as true - should be ignored.
10380 : 1 : l8.setPoints( QgsPointSequence() << QgsPoint( 6, 6 ) << QgsPoint( 7, 8 ) );
10381 : 1 : c8j.addCurve( l8.clone(), true );
10382 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve (CircularString (1 2, 2 3, 3 4),CircularString (6 6, 7 8))" ) );
10383 : : // try to add a linestring with extend existing as true - should be ignored because the last curve isn't a linestring
10384 : 1 : QgsLineString l8j;
10385 : 1 : l8j.setPoints( QgsPointSequence() << QgsPoint( 10, 8 ) << QgsPoint( 10, 12 ) );
10386 : 1 : c8j.addCurve( l8j.clone(), true );
10387 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve (CircularString (1 2, 2 3, 3 4),CircularString (6 6, 7 8),(10 8, 10 12))" ) );
10388 : : // try to extend with another linestring -- should add to final part
10389 : 1 : l8j.setPoints( QgsPointSequence() << QgsPoint( 11, 13 ) << QgsPoint( 12, 12 ) );
10390 : 1 : c8j.addCurve( l8j.clone(), true );
10391 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve (CircularString (1 2, 2 3, 3 4),CircularString (6 6, 7 8),(10 8, 10 12, 11 13, 12 12))" ) );
10392 : : // try to extend with another linestring -- should add to final part, with no duplicate points
10393 : 1 : l8j.setPoints( QgsPointSequence() << QgsPoint( 12, 12 ) << QgsPoint( 13, 12 ) << QgsPoint( 14, 15 ) );
10394 : 1 : c8j.addCurve( l8j.clone(), true );
10395 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve (CircularString (1 2, 2 3, 3 4),CircularString (6 6, 7 8),(10 8, 10 12, 11 13, 12 12, 13 12, 14 15))" ) );
10396 : : // not extending, should be added as new curve
10397 : 1 : l8j.setPoints( QgsPointSequence() << QgsPoint( 15, 16 ) << QgsPoint( 17, 12 ) );
10398 : 1 : c8j.addCurve( l8j.clone(), false );
10399 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve (CircularString (1 2, 2 3, 3 4),CircularString (6 6, 7 8),(10 8, 10 12, 11 13, 12 12, 13 12, 14 15),(15 16, 17 12))" ) );
10400 : 1 : c8j.clear();
10401 : : // adding a linestring as first part, with extend as true
10402 : 1 : c8j.addCurve( l8j.clone(), true );
10403 : 2 : QCOMPARE( c8j.asWkt(), QStringLiteral( "CompoundCurve ((15 16, 17 12))" ) );
10404 : :
10405 : : //test getters/setters
10406 : 1 : QgsCompoundCurve c9;
10407 : :
10408 : : // no crash!
10409 : 1 : ( void )c9.xAt( -1 );
10410 : 1 : ( void )c9.xAt( 1 );
10411 : 1 : ( void )c9.yAt( -1 );
10412 : 1 : ( void )c9.yAt( 1 );
10413 : :
10414 : 1 : QgsCircularString l9;
10415 : 2 : l9.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10416 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 )
10417 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 ) );
10418 : 1 : c9.addCurve( l9.clone() );
10419 : 1 : QCOMPARE( c9.xAt( 0 ), 1.0 );
10420 : 1 : QCOMPARE( c9.xAt( 1 ), 11.0 );
10421 : 1 : QCOMPARE( c9.xAt( 2 ), 21.0 );
10422 : 1 : ( void ) c9.xAt( -1 ); //out of range
10423 : 1 : ( void ) c9.xAt( 11 ); //out of range
10424 : 1 : QCOMPARE( c9.yAt( 0 ), 2.0 );
10425 : 1 : QCOMPARE( c9.yAt( 1 ), 12.0 );
10426 : 1 : QCOMPARE( c9.yAt( 2 ), 22.0 );
10427 : 1 : ( void ) c9.yAt( -1 ); //out of range
10428 : 1 : ( void ) c9.yAt( 11 ); //out of range
10429 : :
10430 : 1 : QgsLineString l9a;
10431 : 2 : l9a.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 23, 24 )
10432 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 31, 22, 13, 14 ) );
10433 : 1 : c9.addCurve( l9a.clone() );
10434 : 1 : QCOMPARE( c9.xAt( 0 ), 1.0 );
10435 : 1 : QCOMPARE( c9.xAt( 1 ), 11.0 );
10436 : 1 : QCOMPARE( c9.xAt( 2 ), 21.0 );
10437 : 1 : QCOMPARE( c9.xAt( 3 ), 31.0 );
10438 : 1 : QCOMPARE( c9.xAt( 4 ), 0.0 );
10439 : 1 : ( void ) c9.xAt( -1 ); //out of range
10440 : 1 : ( void ) c9.xAt( 11 ); //out of range
10441 : 1 : QCOMPARE( c9.yAt( 0 ), 2.0 );
10442 : 1 : QCOMPARE( c9.yAt( 1 ), 12.0 );
10443 : 1 : QCOMPARE( c9.yAt( 2 ), 22.0 );
10444 : 1 : QCOMPARE( c9.yAt( 3 ), 22.0 );
10445 : 1 : QCOMPARE( c9.yAt( 4 ), 0.0 );
10446 : 1 : ( void ) c9.yAt( -1 ); //out of range
10447 : 1 : ( void ) c9.yAt( 11 ); //out of range
10448 : :
10449 : 1 : c9.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 51.0, 52.0 ) );
10450 : 1 : QCOMPARE( c9.xAt( 0 ), 51.0 );
10451 : 1 : QCOMPARE( c9.yAt( 0 ), 52.0 );
10452 : 1 : c9.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 61.0, 62 ) );
10453 : 1 : QCOMPARE( c9.xAt( 1 ), 61.0 );
10454 : 1 : QCOMPARE( c9.yAt( 1 ), 62.0 );
10455 : 1 : c9.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 71.0, 2 ) ); //out of range
10456 : 1 : c9.moveVertex( QgsVertexId( 0, 0, 11 ), QgsPoint( 71.0, 2 ) ); //out of range
10457 : :
10458 : 1 : QgsPoint p;
10459 : : QgsVertexId::VertexType type;
10460 : 1 : QVERIFY( !c9.pointAt( -1, p, type ) );
10461 : 1 : QVERIFY( !c9.pointAt( 11, p, type ) );
10462 : 1 : QVERIFY( c9.pointAt( 0, p, type ) );
10463 : 1 : QCOMPARE( p.z(), 3.0 );
10464 : 1 : QCOMPARE( p.m(), 4.0 );
10465 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
10466 : 1 : QVERIFY( c9.pointAt( 1, p, type ) );
10467 : 1 : QCOMPARE( p.z(), 13.0 );
10468 : 1 : QCOMPARE( p.m(), 14.0 );
10469 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
10470 : 1 : QVERIFY( c9.pointAt( 2, p, type ) );
10471 : 1 : QCOMPARE( p.z(), 23.0 );
10472 : 1 : QCOMPARE( p.m(), 24.0 );
10473 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
10474 : 1 : QVERIFY( c9.pointAt( 3, p, type ) );
10475 : 1 : QCOMPARE( p.z(), 13.0 );
10476 : 1 : QCOMPARE( p.m(), 14.0 );
10477 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
10478 : :
10479 : : //equality
10480 : 1 : QgsCompoundCurve e1;
10481 : 1 : QgsCompoundCurve e2;
10482 : 1 : QVERIFY( e1 == e2 );
10483 : 1 : QVERIFY( !( e1 != e2 ) );
10484 : 1 : QgsLineString le1;
10485 : 1 : QgsLineString le2;
10486 : 1 : le1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) );
10487 : 1 : e1.addCurve( le1.clone() );
10488 : 1 : QVERIFY( !( e1 == e2 ) ); //different number of curves
10489 : 1 : QVERIFY( e1 != e2 );
10490 : 1 : e2.addCurve( le1.clone() );
10491 : 1 : QVERIFY( e1 == e2 );
10492 : 1 : QVERIFY( !( e1 != e2 ) );
10493 : 1 : le1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 1 / 3.0, 4 / 3.0 ) );
10494 : 1 : e1.addCurve( le1.clone() );
10495 : 1 : QVERIFY( !( e1 == e2 ) ); //different number of curves
10496 : 1 : QVERIFY( e1 != e2 );
10497 : 1 : le2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2 / 6.0, 8 / 6.0 ) );
10498 : 1 : e2.addCurve( le2.clone() );
10499 : 1 : QVERIFY( e1 == e2 ); //check non-integer equality
10500 : 1 : QVERIFY( !( e1 != e2 ) );
10501 : 1 : le1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 1 / 3.0, 4 / 3.0 ) << QgsPoint( 7, 8 ) );
10502 : 1 : e1.addCurve( le1.clone() );
10503 : 1 : le2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 2 / 6.0, 8 / 6.0 ) << QgsPoint( 6, 9 ) );
10504 : 1 : e2.addCurve( le2.clone() );
10505 : 1 : QVERIFY( !( e1 == e2 ) ); //different coordinates
10506 : 1 : QVERIFY( e1 != e2 );
10507 : :
10508 : : // different dimensions
10509 : 1 : QgsCompoundCurve e3;
10510 : 1 : e1.clear();
10511 : 1 : e1.addCurve( le1.clone() );
10512 : 1 : QgsLineString le3;
10513 : 2 : le3.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 0 )
10514 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1 / 3.0, 4 / 3.0, 0 )
10515 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 7, 8, 0 ) );
10516 : 1 : e3.addCurve( le3.clone() );
10517 : 1 : QVERIFY( !( e1 == e3 ) ); //different dimension
10518 : 1 : QVERIFY( e1 != e3 );
10519 : 1 : QgsCompoundCurve e4;
10520 : 1 : QgsLineString le4;
10521 : 2 : le4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 )
10522 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1 / 3.0, 4 / 3.0, 3 )
10523 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 7, 8, 4 ) );
10524 : 1 : e4.addCurve( le4.clone() );
10525 : 1 : QVERIFY( !( e3 == e4 ) ); //different z coordinates
10526 : 1 : QVERIFY( e3 != e4 );
10527 : 1 : QgsCompoundCurve e5;
10528 : 1 : QgsLineString le5;
10529 : 2 : le5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 1 )
10530 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1 / 3.0, 4 / 3.0, 0, 2 )
10531 : 1 : << QgsPoint( QgsWkbTypes::PointM, 7, 8, 0, 3 ) );
10532 : 1 : e5.addCurve( le5.clone() );
10533 : 1 : QgsCompoundCurve e6;
10534 : 1 : QgsLineString le6;
10535 : 2 : le6.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 11 )
10536 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1 / 3.0, 4 / 3.0, 0, 12 )
10537 : 1 : << QgsPoint( QgsWkbTypes::PointM, 7, 8, 0, 13 ) );
10538 : 1 : e6.addCurve( le6.clone() );
10539 : 1 : QVERIFY( !( e5 == e6 ) ); //different m values
10540 : 1 : QVERIFY( e5 != e6 );
10541 : :
10542 : 1 : QVERIFY( e6 != QgsLineString() );
10543 : :
10544 : : // assignment operator
10545 : 1 : e5.addCurve( le5.clone() );
10546 : 1 : QVERIFY( e5 != e6 );
10547 : 1 : e6 = e5;
10548 : 1 : QCOMPARE( e5, e6 );
10549 : :
10550 : : //isClosed
10551 : 1 : QgsCompoundCurve c11;
10552 : 1 : QgsCircularString l11;
10553 : 1 : QVERIFY( !c11.isClosed() );
10554 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
10555 : 1 : << QgsPoint( 11, 2 )
10556 : 1 : << QgsPoint( 11, 22 )
10557 : 1 : << QgsPoint( 1, 22 ) );
10558 : 1 : c11.addCurve( l11.clone() );
10559 : 1 : QVERIFY( !c11.isClosed() );
10560 : 1 : QgsLineString ls11;
10561 : 2 : ls11.setPoints( QgsPointSequence() << QgsPoint( 1, 22 )
10562 : 1 : << QgsPoint( 1, 2 ) );
10563 : 1 : c11.addCurve( ls11.clone() );
10564 : 1 : QVERIFY( c11.isClosed() );
10565 : :
10566 : : //test that m values aren't considered when testing for closedness
10567 : 1 : c11.clear();
10568 : 2 : l11.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 )
10569 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 2, 0, 4 )
10570 : 1 : << QgsPoint( QgsWkbTypes::PointM, 11, 22, 0, 5 )
10571 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 6 ) );
10572 : 1 : c11.addCurve( l11.clone() );
10573 : 1 : QVERIFY( c11.isClosed() );
10574 : :
10575 : : //polygonf
10576 : 1 : QgsCircularString lc13;
10577 : 1 : QgsCompoundCurve c13;
10578 : 2 : lc13.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10579 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
10580 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
10581 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
10582 : 1 : c13.addCurve( lc13.clone() );
10583 : 1 : QgsLineString ls13;
10584 : 1 : ls13.setPoints( QgsPointSequence() << QgsPoint( 1, 22 ) << QgsPoint( 23, 22 ) );
10585 : 1 : c13.addCurve( ls13.clone() );
10586 : 1 : QPolygonF poly = c13.asQPolygonF();
10587 : 1 : QCOMPARE( poly.count(), 183 );
10588 : 1 : QCOMPARE( poly.at( 0 ).x(), 1.0 );
10589 : 1 : QCOMPARE( poly.at( 0 ).y(), 2.0 );
10590 : 1 : QCOMPARE( poly.at( 182 ).x(), 23.0 );
10591 : 1 : QCOMPARE( poly.at( 182 ).y(), 22.0 );
10592 : :
10593 : : // clone tests
10594 : 1 : QgsCircularString lc14;
10595 : 2 : lc14.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
10596 : 1 : << QgsPoint( 11, 2 )
10597 : 1 : << QgsPoint( 11, 22 )
10598 : 1 : << QgsPoint( 1, 22 ) );
10599 : 1 : QgsCompoundCurve c14;
10600 : 1 : c14.addCurve( lc14.clone() );
10601 : 1 : QgsLineString ls14;
10602 : 1 : ls14.setPoints( QgsPointSequence() << QgsPoint( 1, 22 ) << QgsPoint( 23, 22 ) );
10603 : 1 : c14.addCurve( ls14.clone() );
10604 : 1 : std::unique_ptr<QgsCompoundCurve> cloned( c14.clone() );
10605 : 1 : QCOMPARE( *cloned, c14 );
10606 : :
10607 : : //clone with Z/M
10608 : 2 : lc14.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10609 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
10610 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
10611 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
10612 : 1 : ls14.setPoints( QgsPointSequence() << QgsPoint( 1, 22, 31, 34 ) << QgsPoint( 23, 22, 42, 43 ) );
10613 : 1 : c14.clear();
10614 : 1 : c14.addCurve( lc14.clone() );
10615 : 1 : c14.addCurve( ls14.clone() );
10616 : 1 : cloned.reset( c14.clone() );
10617 : 1 : QCOMPARE( *cloned, c14 );
10618 : :
10619 : : //clone an empty line
10620 : 1 : c14.clear();
10621 : 1 : cloned.reset( c14.clone() );
10622 : 1 : QVERIFY( cloned->isEmpty() );
10623 : 1 : QCOMPARE( cloned->numPoints(), 0 );
10624 : 1 : QVERIFY( !cloned->is3D() );
10625 : 1 : QVERIFY( !cloned->isMeasure() );
10626 : 1 : QCOMPARE( cloned->wkbType(), QgsWkbTypes::CompoundCurve );
10627 : :
10628 : : //segmentize tests
10629 : 1 : QgsCompoundCurve toSegment;
10630 : 1 : QgsCircularString lcSegment;
10631 : 2 : lcSegment.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
10632 : 1 : << QgsPoint( 11, 10 ) << QgsPoint( 21, 2 ) );
10633 : 1 : toSegment.addCurve( lcSegment.clone() );
10634 : 1 : std::unique_ptr<QgsLineString> segmentized( static_cast< QgsLineString * >( toSegment.segmentize() ) );
10635 : 1 : QCOMPARE( segmentized->numPoints(), 156 );
10636 : 1 : QCOMPARE( segmentized->vertexCount(), 156 );
10637 : 1 : QCOMPARE( segmentized->ringCount(), 1 );
10638 : 1 : QCOMPARE( segmentized->partCount(), 1 );
10639 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineString );
10640 : 1 : QVERIFY( !segmentized->is3D() );
10641 : 1 : QVERIFY( !segmentized->isMeasure() );
10642 : :
10643 : 1 : QCOMPARE( segmentized->pointN( 0 ), lcSegment.pointN( 0 ) );
10644 : 1 : QCOMPARE( segmentized->pointN( segmentized->numPoints() - 1 ), lcSegment.pointN( toSegment.numPoints() - 1 ) );
10645 : :
10646 : : //segmentize with Z/M
10647 : 2 : lcSegment.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10648 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 10, 11, 14 )
10649 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 2, 21, 24 ) );
10650 : 1 : toSegment.clear();
10651 : 1 : toSegment.addCurve( lcSegment.clone() );
10652 : 1 : segmentized.reset( static_cast< QgsLineString * >( toSegment.segmentize() ) );
10653 : 1 : QCOMPARE( segmentized->numPoints(), 156 );
10654 : 1 : QCOMPARE( segmentized->vertexCount(), 156 );
10655 : 1 : QCOMPARE( segmentized->ringCount(), 1 );
10656 : 1 : QCOMPARE( segmentized->partCount(), 1 );
10657 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineStringZM );
10658 : 1 : QVERIFY( segmentized->is3D() );
10659 : 1 : QVERIFY( segmentized->isMeasure() );
10660 : 1 : QCOMPARE( segmentized->pointN( 0 ), lcSegment.pointN( 0 ) );
10661 : 1 : QCOMPARE( segmentized->pointN( segmentized->numPoints() - 1 ), lcSegment.pointN( toSegment.numPoints() - 1 ) );
10662 : :
10663 : : //segmentize an empty line
10664 : 1 : toSegment.clear();
10665 : 1 : segmentized.reset( static_cast< QgsLineString * >( toSegment.segmentize() ) );
10666 : 1 : QVERIFY( segmentized->isEmpty() );
10667 : 1 : QCOMPARE( segmentized->numPoints(), 0 );
10668 : 1 : QVERIFY( !segmentized->is3D() );
10669 : 1 : QVERIFY( !segmentized->isMeasure() );
10670 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineString );
10671 : :
10672 : : //to/from WKB
10673 : 1 : QgsCompoundCurve c15;
10674 : 1 : QgsCircularString l15;
10675 : 2 : l15.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10676 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
10677 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
10678 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
10679 : 1 : c15.addCurve( l15.clone() );
10680 : 1 : QByteArray wkb15 = c15.asWkb();
10681 : 1 : QCOMPARE( wkb15.size(), c15.wkbSize() );
10682 : 1 : QgsCompoundCurve c16;
10683 : 1 : QgsConstWkbPtr wkb15ptr( wkb15 );
10684 : 1 : c16.fromWkb( wkb15ptr );
10685 : 1 : QCOMPARE( c16.numPoints(), 4 );
10686 : 1 : QCOMPARE( c16.vertexCount(), 4 );
10687 : 1 : QCOMPARE( c16.nCoordinates(), 4 );
10688 : 1 : QCOMPARE( c16.ringCount(), 1 );
10689 : 1 : QCOMPARE( c16.partCount(), 1 );
10690 : 1 : QCOMPARE( c16.wkbType(), QgsWkbTypes::CompoundCurveZM );
10691 : 1 : QVERIFY( c16.is3D() );
10692 : 1 : QVERIFY( c16.isMeasure() );
10693 : 1 : QCOMPARE( c16.nCurves(), 1 );
10694 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c16.curveAt( 0 ) )->pointN( 0 ), l15.pointN( 0 ) );
10695 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c16.curveAt( 0 ) )->pointN( 1 ), l15.pointN( 1 ) );
10696 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c16.curveAt( 0 ) )->pointN( 2 ), l15.pointN( 2 ) );
10697 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c16.curveAt( 0 ) )->pointN( 3 ), l15.pointN( 3 ) );
10698 : :
10699 : : //bad WKB - check for no crash
10700 : 1 : c16.clear();
10701 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
10702 : 1 : QVERIFY( !c16.fromWkb( nullPtr ) );
10703 : 1 : QCOMPARE( c16.wkbType(), QgsWkbTypes::CompoundCurve );
10704 : 1 : QgsPoint point( 1, 2 );
10705 : 1 : QByteArray wkb16 = point.asWkb();
10706 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
10707 : 1 : QVERIFY( !c16.fromWkb( wkb16ptr ) );
10708 : 1 : QCOMPARE( c16.wkbType(), QgsWkbTypes::CompoundCurve );
10709 : :
10710 : : //to/from WKT
10711 : 1 : QgsCompoundCurve c17;
10712 : 1 : QgsCircularString l17;
10713 : 2 : l17.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10714 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 2, 11, 14 )
10715 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 22, 21, 24 )
10716 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 31, 34 ) );
10717 : 1 : c17.addCurve( l17.clone() );
10718 : :
10719 : 1 : QString wkt = c17.asWkt();
10720 : 1 : QVERIFY( !wkt.isEmpty() );
10721 : 1 : QgsCompoundCurve c18;
10722 : 1 : QVERIFY( c18.fromWkt( wkt ) );
10723 : 1 : QCOMPARE( c18.numPoints(), 4 );
10724 : 1 : QCOMPARE( c18.wkbType(), QgsWkbTypes::CompoundCurveZM );
10725 : 1 : QVERIFY( c18.is3D() );
10726 : 1 : QVERIFY( c18.isMeasure() );
10727 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c18.curveAt( 0 ) )->pointN( 0 ), l17.pointN( 0 ) );
10728 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c18.curveAt( 0 ) )->pointN( 1 ), l17.pointN( 1 ) );
10729 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c18.curveAt( 0 ) )->pointN( 2 ), l17.pointN( 2 ) );
10730 : 1 : QCOMPARE( dynamic_cast< const QgsCircularString *>( c18.curveAt( 0 ) )->pointN( 3 ), l17.pointN( 3 ) );
10731 : :
10732 : : //bad WKT
10733 : 1 : QVERIFY( !c18.fromWkt( "Polygon()" ) );
10734 : 1 : QVERIFY( c18.isEmpty() );
10735 : 1 : QCOMPARE( c18.numPoints(), 0 );
10736 : 1 : QVERIFY( !c18.is3D() );
10737 : 1 : QVERIFY( !c18.isMeasure() );
10738 : 1 : QCOMPARE( c18.wkbType(), QgsWkbTypes::CompoundCurve );
10739 : 1 : QVERIFY( !c18.fromWkt( "CompoundCurve(LineString(0 0, 1 1),Point( 2 2 ))" ) );
10740 : :
10741 : : //asGML2
10742 : 1 : QgsCompoundCurve exportCurve;
10743 : 1 : QgsCircularString exportLine;
10744 : 2 : exportLine.setPoints( QgsPointSequence() << QgsPoint( 31, 32 )
10745 : 1 : << QgsPoint( 41, 42 )
10746 : 1 : << QgsPoint( 51, 52 ) );
10747 : 1 : exportCurve.addCurve( exportLine.clone() );
10748 : 1 : QgsLineString exportLineString;
10749 : 2 : exportLineString.setPoints( QgsPointSequence() << QgsPoint( 51, 52 )
10750 : 1 : << QgsPoint( 61, 62 ) );
10751 : 1 : exportCurve.addCurve( exportLineString.clone() );
10752 : :
10753 : 1 : QgsCircularString exportLineFloat;
10754 : 2 : exportLineFloat.setPoints( QgsPointSequence() << QgsPoint( 1 / 3.0, 2 / 3.0 )
10755 : 1 : << QgsPoint( 1 + 1 / 3.0, 1 + 2 / 3.0 )
10756 : 1 : << QgsPoint( 2 + 1 / 3.0, 2 + 2 / 3.0 ) );
10757 : 1 : QgsCompoundCurve exportCurveFloat;
10758 : 1 : exportCurveFloat.addCurve( exportLineFloat.clone() );
10759 : 1 : QgsLineString exportLineStringFloat;
10760 : 2 : exportLineStringFloat.setPoints( QgsPointSequence() << QgsPoint( 2 + 1 / 3.0, 2 + 2 / 3.0 )
10761 : 1 : << QgsPoint( 3 + 1 / 3.0, 3 + 2 / 3.0 ) );
10762 : 1 : exportCurveFloat.addCurve( exportLineStringFloat.clone() );
10763 : :
10764 : 2 : QDomDocument doc( QStringLiteral( "gml" ) );
10765 : 2 : QString expectedGML2( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">31,32 41,42 51,52 61,62</coordinates></LineString>" ) );
10766 : 1 : QString result = elemToString( exportCurve.asGml2( doc ) );
10767 : 3 : QGSCOMPAREGML( result, expectedGML2 );
10768 : 2 : QString expectedGML2prec3( QStringLiteral( "<LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.333,0.667 1.333,1.667 2.333,2.667 3.333,3.667</coordinates></LineString>" ) );
10769 : 1 : result = elemToString( exportCurveFloat.asGml2( doc, 3 ) );
10770 : 3 : QGSCOMPAREGML( result, expectedGML2prec3 );
10771 : 2 : QString expectedGML2empty( QStringLiteral( "<LineString xmlns=\"gml\"/>" ) );
10772 : 3 : QGSCOMPAREGML( elemToString( QgsCompoundCurve().asGml2( doc ) ), expectedGML2empty );
10773 : :
10774 : :
10775 : : //asGML3
10776 : 2 : QString expectedGML3( QStringLiteral( "<CompositeCurve xmlns=\"gml\"><curveMember xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">31 32 41 42 51 52</posList></ArcString></segments></Curve></curveMember><curveMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">51 52 61 62</posList></LineString></curveMember></CompositeCurve>" ) );
10777 : 1 : result = elemToString( exportCurve.asGml3( doc ) );
10778 : 1 : QCOMPARE( result, expectedGML3 );
10779 : 2 : QString expectedGML3prec3( QStringLiteral( "<CompositeCurve xmlns=\"gml\"><curveMember xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0.333 0.667 1.333 1.667 2.333 2.667</posList></ArcString></segments></Curve></curveMember><curveMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">2.333 2.667 3.333 3.667</posList></LineString></curveMember></CompositeCurve>" ) );
10780 : 1 : result = elemToString( exportCurveFloat.asGml3( doc, 3 ) );
10781 : 1 : QCOMPARE( result, expectedGML3prec3 );
10782 : 2 : QString expectedGML3empty( QStringLiteral( "<CompositeCurve xmlns=\"gml\"/>" ) );
10783 : 3 : QGSCOMPAREGML( elemToString( QgsCompoundCurve().asGml3( doc ) ), expectedGML3empty );
10784 : :
10785 : : //asJSON
10786 : 1 : QString expectedJson( "{\"coordinates\":[[31.0,32.0],[41.0,42.0],[51.0,52.0],[61.0,62.0]],\"type\":\"LineString\"}" );
10787 : 1 : result = exportCurve.asJson();
10788 : 1 : QCOMPARE( result, expectedJson );
10789 : 1 : QString expectedJsonPrec3( "{\"coordinates\":[[0.333,0.667],[1.333,1.667],[2.333,2.667],[3.333,3.667]],\"type\":\"LineString\"}" );
10790 : 1 : result = exportCurveFloat.asJson( 3 );
10791 : 1 : QCOMPARE( result, expectedJsonPrec3 );
10792 : :
10793 : : //asKML
10794 : 2 : QString expectedKml( QStringLiteral( "<LineString><altitudeMode>clampToGround</altitudeMode><coordinates>31,32,0 41,42,0 51,52,0 61,62,0</coordinates></LineString>" ) );
10795 : 1 : QCOMPARE( exportCurve.asKml(), expectedKml );
10796 : 2 : QString expectedKmlPrec3( QStringLiteral( "<LineString><altitudeMode>clampToGround</altitudeMode><coordinates>0.333,0.667,0 1.333,1.667,0 2.333,2.667,0 3.333,3.667,0</coordinates></LineString>" ) );
10797 : 1 : QCOMPARE( exportCurveFloat.asKml( 3 ), expectedKmlPrec3 );
10798 : :
10799 : : //length
10800 : 1 : QgsCompoundCurve c19;
10801 : 1 : QCOMPARE( c19.length(), 0.0 );
10802 : 1 : QgsCircularString l19;
10803 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
10804 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
10805 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
10806 : 1 : c19.addCurve( l19.clone() );
10807 : 1 : QgsLineString l19a;
10808 : 2 : l19a.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 )
10809 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 25, 10, 6, 7 ) );
10810 : 1 : c19.addCurve( l19a.clone() );
10811 : 1 : QGSCOMPARENEAR( c19.length(), 36.1433, 0.001 );
10812 : :
10813 : : //startPoint
10814 : 1 : QCOMPARE( c19.startPoint(), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 ) );
10815 : :
10816 : : //endPoint
10817 : 1 : QCOMPARE( c19.endPoint(), QgsPoint( QgsWkbTypes::PointZM, 25, 10, 6, 7 ) );
10818 : :
10819 : : //bad start/end points. Test that this doesn't crash.
10820 : 1 : c19.clear();
10821 : 1 : QVERIFY( c19.startPoint().isEmpty() );
10822 : 1 : QVERIFY( c19.endPoint().isEmpty() );
10823 : :
10824 : : //curveToLine
10825 : 1 : c19.clear();
10826 : 2 : l19.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
10827 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
10828 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
10829 : 1 : c19.addCurve( l19.clone() );
10830 : 2 : l19a.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 )
10831 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 25, 10, 6, 7 ) );
10832 : 1 : c19.addCurve( l19a.clone() );
10833 : 1 : segmentized.reset( c19.curveToLine() );
10834 : 1 : QCOMPARE( segmentized->numPoints(), 182 );
10835 : 1 : QCOMPARE( segmentized->wkbType(), QgsWkbTypes::LineStringZM );
10836 : 1 : QVERIFY( segmentized->is3D() );
10837 : 1 : QVERIFY( segmentized->isMeasure() );
10838 : 1 : QCOMPARE( segmentized->pointN( 0 ), l19.pointN( 0 ) );
10839 : 1 : QCOMPARE( segmentized->pointN( segmentized->numPoints() - 1 ), l19a.pointN( l19a.numPoints() - 1 ) );
10840 : :
10841 : : // points
10842 : 1 : QgsCompoundCurve c20;
10843 : 1 : QgsCircularString l20;
10844 : 1 : QgsPointSequence points;
10845 : 1 : c20.points( points );
10846 : 1 : QVERIFY( points.isEmpty() );
10847 : 2 : l20.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
10848 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
10849 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
10850 : 1 : c20.addCurve( l20.clone() );
10851 : 1 : QgsLineString ls20;
10852 : 2 : ls20.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 )
10853 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 25, 10, 6, 7 ) );
10854 : 1 : c20.addCurve( ls20.clone() );
10855 : 1 : c20.points( points );
10856 : 1 : QCOMPARE( points.count(), 4 );
10857 : 1 : QCOMPARE( points.at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 ) );
10858 : 1 : QCOMPARE( points.at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 ) );
10859 : 1 : QCOMPARE( points.at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
10860 : 1 : QCOMPARE( points.at( 3 ), QgsPoint( QgsWkbTypes::PointZM, 25, 10, 6, 7 ) );
10861 : :
10862 : : //CRS transform
10863 : 2 : QgsCoordinateReferenceSystem sourceSrs( QStringLiteral( "EPSG:3994" ) );
10864 : 2 : QgsCoordinateReferenceSystem destSrs( QStringLiteral( "EPSG:4202" ) ); // want a transform with ellipsoid change
10865 : 1 : QgsCoordinateTransform tr( sourceSrs, destSrs, QgsProject::instance() );
10866 : :
10867 : : // 2d CRS transform
10868 : 1 : QgsCompoundCurve c21;
10869 : 1 : QgsCircularString l21;
10870 : 2 : l21.setPoints( QgsPointSequence() << QgsPoint( 6374985, -3626584 )
10871 : 1 : << QgsPoint( 6474985, -3526584 ) );
10872 : 1 : c21.addCurve( l21.clone() );
10873 : 1 : QgsLineString ls21;
10874 : 2 : ls21.setPoints( QgsPointSequence() << QgsPoint( 6474985, -3526584 )
10875 : 1 : << QgsPoint( 6504985, -3526584 ) );
10876 : 1 : c21.addCurve( ls21.clone() );
10877 : 1 : c21.transform( tr, QgsCoordinateTransform::ForwardTransform );
10878 : 1 : QGSCOMPARENEAR( c21.xAt( 0 ), 175.771, 0.001 );
10879 : 1 : QGSCOMPARENEAR( c21.yAt( 0 ), -39.724, 0.001 );
10880 : 1 : QGSCOMPARENEAR( c21.xAt( 1 ), 176.959, 0.001 );
10881 : 1 : QGSCOMPARENEAR( c21.yAt( 1 ), -38.7999, 0.001 );
10882 : 1 : QGSCOMPARENEAR( c21.xAt( 2 ), 177.315211, 0.001 );
10883 : 1 : QGSCOMPARENEAR( c21.yAt( 2 ), -38.799974, 0.001 );
10884 : 1 : QGSCOMPARENEAR( c21.boundingBox().xMinimum(), 175.770033, 0.001 );
10885 : 1 : QGSCOMPARENEAR( c21.boundingBox().yMinimum(), -39.724, 0.001 );
10886 : 1 : QGSCOMPARENEAR( c21.boundingBox().xMaximum(), 177.315211, 0.001 );
10887 : 1 : QGSCOMPARENEAR( c21.boundingBox().yMaximum(), -38.7999, 0.001 );
10888 : :
10889 : : //3d CRS transform
10890 : 1 : QgsCompoundCurve c22;
10891 : 2 : l21.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 )
10892 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6474985, -3526584, 3, 4 ) );
10893 : 1 : c22.addCurve( l21.clone() );
10894 : 2 : ls21.setPoints( QgsPointSequence() << QgsPoint( 6474985, -3526584, 3, 4 )
10895 : 1 : << QgsPoint( 6504985, -3526584, 5, 6 ) );
10896 : 1 : c22.addCurve( ls21.clone() );
10897 : 1 : c22.transform( tr, QgsCoordinateTransform::ForwardTransform );
10898 : 1 : QgsPoint pt;
10899 : : QgsVertexId::VertexType v;
10900 : 1 : c22.pointAt( 0, pt, v );
10901 : 1 : QGSCOMPARENEAR( pt.x(), 175.771, 0.001 );
10902 : 1 : QGSCOMPARENEAR( pt.y(), -39.724, 0.001 );
10903 : 1 : QGSCOMPARENEAR( pt.z(), 1.0, 0.001 );
10904 : 1 : QCOMPARE( pt.m(), 2.0 );
10905 : 1 : c22.pointAt( 1, pt, v );
10906 : 1 : QGSCOMPARENEAR( pt.x(), 176.959, 0.001 );
10907 : 1 : QGSCOMPARENEAR( pt.y(), -38.7999, 0.001 );
10908 : 1 : QGSCOMPARENEAR( pt.z(), 3.0, 0.001 );
10909 : 1 : QCOMPARE( pt.m(), 4.0 );
10910 : 1 : c22.pointAt( 2, pt, v );
10911 : 1 : QGSCOMPARENEAR( pt.x(), 177.315211, 0.001 );
10912 : 1 : QGSCOMPARENEAR( pt.y(), -38.7999, 0.001 );
10913 : 1 : QGSCOMPARENEAR( pt.z(), 5.0, 0.001 );
10914 : 1 : QCOMPARE( pt.m(), 6.0 );
10915 : :
10916 : : //reverse transform
10917 : 1 : c22.transform( tr, QgsCoordinateTransform::ReverseTransform );
10918 : 1 : c22.pointAt( 0, pt, v );
10919 : 1 : QGSCOMPARENEAR( pt.x(), 6374985, 100 );
10920 : 1 : QGSCOMPARENEAR( pt.y(), -3626584, 100 );
10921 : 1 : QGSCOMPARENEAR( pt.z(), 1.0, 0.001 );
10922 : 1 : QCOMPARE( pt.m(), 2.0 );
10923 : 1 : c22.pointAt( 1, pt, v );
10924 : 1 : QGSCOMPARENEAR( pt.x(), 6474985, 100 );
10925 : 1 : QGSCOMPARENEAR( pt.y(), -3526584, 100 );
10926 : 1 : QGSCOMPARENEAR( pt.z(), 3.0, 0.001 );
10927 : 1 : QCOMPARE( pt.m(), 4.0 );
10928 : 1 : c22.pointAt( 2, pt, v );
10929 : 1 : QGSCOMPARENEAR( pt.x(), 6504985, 100 );
10930 : 1 : QGSCOMPARENEAR( pt.y(), -3526584, 100 );
10931 : 1 : QGSCOMPARENEAR( pt.z(), 5.0, 0.001 );
10932 : 1 : QCOMPARE( pt.m(), 6.0 );
10933 : :
10934 : : #if PROJ_VERSION_MAJOR<6 // note - z value transform doesn't currently work with proj 6+, because we don't yet support compound CRS definitions
10935 : : //z value transform
10936 : : c22.transform( tr, QgsCoordinateTransform::ForwardTransform, true );
10937 : : c22.pointAt( 0, pt, v );
10938 : : QGSCOMPARENEAR( pt.z(), -19.249066, 0.001 );
10939 : : c22.pointAt( 1, pt, v );
10940 : : QGSCOMPARENEAR( pt.z(), -21.092128, 0.001 );
10941 : : c22.pointAt( 2, pt, v );
10942 : : QGSCOMPARENEAR( pt.z(), -19.370485, 0.001 );
10943 : :
10944 : : c22.transform( tr, QgsCoordinateTransform::ReverseTransform, true );
10945 : : c22.pointAt( 0, pt, v );
10946 : : QGSCOMPARENEAR( pt.z(), 1, 0.001 );
10947 : : c22.pointAt( 1, pt, v );
10948 : : QGSCOMPARENEAR( pt.z(), 3, 0.001 );
10949 : : c22.pointAt( 2, pt, v );
10950 : : QGSCOMPARENEAR( pt.z(), 5, 0.001 );
10951 : : #endif
10952 : :
10953 : : //QTransform transform
10954 : 1 : QTransform qtr = QTransform::fromScale( 2, 3 );
10955 : 1 : QgsCompoundCurve c23;
10956 : 1 : QgsCircularString l23;
10957 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
10958 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
10959 : 1 : c23.addCurve( l23.clone() );
10960 : 1 : QgsLineString ls23;
10961 : 1 : ls23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) << QgsPoint( QgsWkbTypes::PointZM, 21, 13, 13, 14 ) );
10962 : 1 : c23.addCurve( ls23.clone() );
10963 : 1 : c23.transform( qtr, 5, 2, 4, 3 );
10964 : 1 : c23.pointAt( 0, pt, v );
10965 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 2, 6, 11, 16 ) );
10966 : 1 : c23.pointAt( 1, pt, v );
10967 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 22, 36, 31, 46 ) );
10968 : 1 : c23.pointAt( 2, pt, v );
10969 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 42, 39, 31, 46 ) );
10970 : 1 : QCOMPARE( c23.boundingBox(), QgsRectangle( 2, 6, 42, 39 ) );
10971 : :
10972 : : //insert vertex
10973 : : //cannot insert vertex in empty line
10974 : 1 : QgsCompoundCurve c24;
10975 : 1 : QVERIFY( !c24.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
10976 : 1 : QCOMPARE( c24.numPoints(), 0 );
10977 : :
10978 : : //2d line
10979 : 1 : QgsCircularString l24;
10980 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
10981 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
10982 : 1 : c24.addCurve( l24.clone() );
10983 : 1 : QVERIFY( c24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 4.0, 7.0 ) ) );
10984 : 1 : QCOMPARE( c24.numPoints(), 5 );
10985 : 1 : QVERIFY( !c24.is3D() );
10986 : 1 : QVERIFY( !c24.isMeasure() );
10987 : 1 : QCOMPARE( c24.wkbType(), QgsWkbTypes::CompoundCurve );
10988 : 1 : c24.pointAt( 0, pt, v );
10989 : 1 : QCOMPARE( pt, QgsPoint( 1.0, 2.0 ) );
10990 : 1 : c24.pointAt( 1, pt, v );
10991 : 1 : QCOMPARE( pt, QgsPoint( 4.0, 7.0 ) );
10992 : 1 : c24.pointAt( 2, pt, v );
10993 : 1 : QGSCOMPARENEAR( pt.x(), 7.192236, 0.01 );
10994 : 1 : QGSCOMPARENEAR( pt.y(), 9.930870, 0.01 );
10995 : 1 : c24.pointAt( 3, pt, v );
10996 : 1 : QCOMPARE( pt, QgsPoint( 11.0, 12.0 ) );
10997 : 1 : c24.pointAt( 4, pt, v );
10998 : 1 : QCOMPARE( pt, QgsPoint( 1.0, 22.0 ) );
10999 : :
11000 : 1 : QVERIFY( c24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 8.0, 9.0 ) ) );
11001 : 1 : QVERIFY( c24.insertVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 18.0, 16.0 ) ) );
11002 : 1 : QCOMPARE( c24.numPoints(), 9 );
11003 : 1 : c24.pointAt( 0, pt, v );
11004 : 1 : QCOMPARE( pt, QgsPoint( 1.0, 2.0 ) );
11005 : 1 : c24.pointAt( 1, pt, v );
11006 : 1 : QGSCOMPARENEAR( pt.x(), 4.363083, 0.01 );
11007 : 1 : QGSCOMPARENEAR( pt.y(), 5.636917, 0.01 );
11008 : 1 : c24.pointAt( 2, pt, v );
11009 : 1 : QCOMPARE( pt, QgsPoint( 8.0, 9.0 ) );
11010 : 1 : c24.pointAt( 3, pt, v );
11011 : 1 : QCOMPARE( pt, QgsPoint( 18.0, 16.0 ) );
11012 : 1 : c24.pointAt( 4, pt, v );
11013 : 1 : QGSCOMPARENEAR( pt.x(), 5.876894, 0.01 );
11014 : 1 : QGSCOMPARENEAR( pt.y(), 8.246211, 0.01 );
11015 : 1 : c24.pointAt( 5, pt, v );
11016 : 1 : QCOMPARE( pt, QgsPoint( 4.0, 7.0 ) );
11017 : 1 : c24.pointAt( 6, pt, v );
11018 : 1 : QGSCOMPARENEAR( pt.x(), 7.192236, 0.01 );
11019 : 1 : QGSCOMPARENEAR( pt.y(), 9.930870, 0.01 );
11020 : 1 : c24.pointAt( 7, pt, v );
11021 : 1 : QCOMPARE( pt, QgsPoint( 11.0, 12.0 ) );
11022 : 1 : c24.pointAt( 8, pt, v );
11023 : 1 : QCOMPARE( pt, QgsPoint( 1.0, 22.0 ) );
11024 : :
11025 : : //insert vertex at end
11026 : 1 : QVERIFY( !c24.insertVertex( QgsVertexId( 0, 0, 9 ), QgsPoint( 31.0, 32.0 ) ) );
11027 : :
11028 : : //insert vertex past end
11029 : 1 : QVERIFY( !c24.insertVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 41.0, 42.0 ) ) );
11030 : 1 : QCOMPARE( c24.numPoints(), 9 );
11031 : :
11032 : : //insert vertex before start
11033 : 1 : QVERIFY( !c24.insertVertex( QgsVertexId( 0, 0, -18 ), QgsPoint( 41.0, 42.0 ) ) );
11034 : 1 : QCOMPARE( c24.numPoints(), 9 );
11035 : :
11036 : : //insert 4d vertex in 4d line
11037 : 1 : c24.clear();
11038 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
11039 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
11040 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
11041 : 1 : c24.addCurve( l24.clone( ) );
11042 : 1 : QVERIFY( c24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) ) );
11043 : 1 : QCOMPARE( c24.numPoints(), 5 );
11044 : 1 : c24.pointAt( 1, pt, v );
11045 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
11046 : :
11047 : : //insert 2d vertex in 4d line
11048 : 1 : QVERIFY( c24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 101, 102 ) ) );
11049 : 1 : QCOMPARE( c24.numPoints(), 7 );
11050 : 1 : QCOMPARE( c24.wkbType(), QgsWkbTypes::CompoundCurveZM );
11051 : 1 : c24.pointAt( 1, pt, v );
11052 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 101, 102 ) );
11053 : :
11054 : : //insert 4d vertex in 2d line
11055 : 1 : c24.clear();
11056 : 2 : l24.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
11057 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
11058 : 1 : c24.addCurve( l24.clone() );
11059 : 1 : QVERIFY( c24.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 2, 4, 103, 104 ) ) );
11060 : 1 : QCOMPARE( c24.numPoints(), 5 );
11061 : 1 : QCOMPARE( c24.wkbType(), QgsWkbTypes::CompoundCurve );
11062 : 1 : c24.pointAt( 1, pt, v );
11063 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 2, 4 ) );
11064 : :
11065 : : // invalid
11066 : 1 : QVERIFY( !c24.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 1, 2 ) ) );
11067 : :
11068 : : //move vertex
11069 : :
11070 : : //empty line
11071 : 1 : QgsCompoundCurve c25;
11072 : 1 : QgsCircularString l25;
11073 : 1 : QVERIFY( !c25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
11074 : 1 : QVERIFY( c25.isEmpty() );
11075 : :
11076 : : //valid line
11077 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
11078 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
11079 : 1 : c25.addCurve( l25.clone() );
11080 : 1 : QVERIFY( c25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
11081 : 1 : QVERIFY( c25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
11082 : 1 : QVERIFY( c25.moveVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
11083 : 1 : c25.pointAt( 0, pt, v );
11084 : 1 : QCOMPARE( pt, QgsPoint( 6.0, 7.0 ) );
11085 : 1 : c25.pointAt( 1, pt, v );
11086 : 1 : QCOMPARE( pt, QgsPoint( 16.0, 17.0 ) );
11087 : 1 : c25.pointAt( 2, pt, v );
11088 : 1 : QCOMPARE( pt, QgsPoint( 26.0, 27.0 ) );
11089 : :
11090 : : //out of range
11091 : 1 : QVERIFY( !c25.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
11092 : 1 : QVERIFY( !c25.moveVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
11093 : 1 : QVERIFY( !c25.moveVertex( QgsVertexId( 0, 1, 10 ), QgsPoint( 3.0, 4.0 ) ) );
11094 : 1 : c25.pointAt( 0, pt, v );
11095 : 1 : QCOMPARE( pt, QgsPoint( 6.0, 7.0 ) );
11096 : 1 : c25.pointAt( 1, pt, v );
11097 : 1 : QCOMPARE( pt, QgsPoint( 16.0, 17.0 ) );
11098 : 1 : c25.pointAt( 2, pt, v );
11099 : 1 : QCOMPARE( pt, QgsPoint( 26.0, 27.0 ) );
11100 : :
11101 : : //move 4d point in 4d line
11102 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 2, 3 )
11103 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 10, 4, 5 )
11104 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 15, 10, 6, 7 ) );
11105 : 1 : c25.clear();
11106 : 1 : c25.addCurve( l25.clone() );
11107 : 1 : QVERIFY( c25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 7, 12, 13 ) ) );
11108 : 1 : c25.pointAt( 1, pt, v );
11109 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 6, 7, 12, 13 ) );
11110 : :
11111 : : //move 2d point in 4d line, existing z/m should be maintained
11112 : 1 : QVERIFY( c25.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 34, 35 ) ) );
11113 : 1 : c25.pointAt( 1, pt, v );
11114 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 34, 35, 12, 13 ) );
11115 : :
11116 : : //move 4d point in 2d line
11117 : 2 : l25.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
11118 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
11119 : 1 : c25.clear();
11120 : 1 : c25.addCurve( l25.clone() );
11121 : 1 : QVERIFY( c25.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 3, 4, 2, 3 ) ) );
11122 : 1 : c25.pointAt( 0, pt, v );
11123 : 1 : QCOMPARE( pt, QgsPoint( 3, 4 ) );
11124 : :
11125 : : //delete vertex
11126 : :
11127 : : //empty line
11128 : 1 : QgsCompoundCurve c26;
11129 : 1 : QgsCircularString l26;
11130 : 1 : QVERIFY( !c26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
11131 : 1 : QVERIFY( c26.isEmpty() );
11132 : :
11133 : : //valid line
11134 : 2 : l26.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
11135 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
11136 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 )
11137 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 31, 32, 6, 7 ) );
11138 : 1 : c26.addCurve( l26.clone() );
11139 : : //out of range vertices
11140 : 1 : QVERIFY( !c26.deleteVertex( QgsVertexId( 0, 0, -1 ) ) );
11141 : 1 : QVERIFY( !c26.deleteVertex( QgsVertexId( 0, 0, 100 ) ) );
11142 : :
11143 : : //valid vertices
11144 : 1 : QVERIFY( c26.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
11145 : 1 : QCOMPARE( c26.numPoints(), 2 );
11146 : 1 : c26.pointAt( 0, pt, v );
11147 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
11148 : 1 : c26.pointAt( 1, pt, v );
11149 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 31, 32, 6, 7 ) );
11150 : :
11151 : : //removing the next vertex removes all remaining vertices
11152 : 1 : QVERIFY( c26.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
11153 : 1 : QCOMPARE( c26.numPoints(), 0 );
11154 : 1 : QVERIFY( c26.isEmpty() );
11155 : :
11156 : : // two lines
11157 : 1 : QgsLineString ls26;
11158 : 1 : c26.clear();
11159 : 2 : ls26.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
11160 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
11161 : 1 : c26.addCurve( ls26.clone() );
11162 : 2 : ls26.setPoints( QgsPointSequence()
11163 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
11164 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 32, 4, 5 )
11165 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 31, 42, 4, 5 ) );
11166 : 1 : c26.addCurve( ls26.clone() );
11167 : 1 : QVERIFY( c26.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
11168 : 1 : QCOMPARE( c26.nCurves(), 1 );
11169 : 1 : const QgsLineString *ls26r = dynamic_cast< const QgsLineString * >( c26.curveAt( 0 ) );
11170 : 1 : QCOMPARE( ls26r->numPoints(), 2 );
11171 : 1 : QCOMPARE( ls26r->startPoint(), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
11172 : 1 : QCOMPARE( ls26r->endPoint(), QgsPoint( QgsWkbTypes::PointZM, 31, 42, 4, 5 ) );
11173 : :
11174 : : //add vertex at the end of linestring
11175 : 1 : QVERIFY( c26.insertVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( QgsWkbTypes::PointZM, 35, 43, 4, 5 ) ) );
11176 : 1 : ls26r = dynamic_cast< const QgsLineString * >( c26.curveAt( 0 ) );
11177 : 1 : QCOMPARE( ls26r->numPoints(), 3 );
11178 : 1 : QCOMPARE( ls26r->startPoint(), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
11179 : 1 : QCOMPARE( ls26r->endPoint(), QgsPoint( QgsWkbTypes::PointZM, 35, 43, 4, 5 ) );
11180 : :
11181 : 1 : c26.clear();
11182 : 2 : ls26.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
11183 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
11184 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 32, 4, 5 ) );
11185 : 1 : c26.addCurve( ls26.clone() );
11186 : 2 : ls26.setPoints( QgsPointSequence()
11187 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 32, 4, 5 )
11188 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 31, 42, 4, 5 ) );
11189 : 1 : c26.addCurve( ls26.clone() );
11190 : 1 : QVERIFY( c26.deleteVertex( QgsVertexId( 0, 0, 2 ) ) );
11191 : 1 : QCOMPARE( c26.nCurves(), 1 );
11192 : 1 : ls26r = dynamic_cast< const QgsLineString * >( c26.curveAt( 0 ) );
11193 : 1 : QCOMPARE( ls26r->numPoints(), 2 );
11194 : 1 : QCOMPARE( ls26r->startPoint(), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
11195 : 1 : QCOMPARE( ls26r->endPoint(), QgsPoint( QgsWkbTypes::PointZM, 31, 42, 4, 5 ) );
11196 : :
11197 : : //reversed
11198 : 1 : QgsCompoundCurve c27;
11199 : 1 : QgsCircularString l27;
11200 : 1 : std::unique_ptr< QgsCompoundCurve > reversed( c27.reversed() );
11201 : 1 : QVERIFY( reversed->isEmpty() );
11202 : 2 : l27.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
11203 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
11204 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
11205 : 1 : c27.addCurve( l27.clone() );
11206 : 1 : QgsLineString ls27;
11207 : 2 : ls27.setPoints( QgsPointSequence()
11208 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 )
11209 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 23, 32, 7, 8 ) );
11210 : 1 : c27.addCurve( ls27.clone() );
11211 : :
11212 : 1 : reversed.reset( c27.reversed() );
11213 : 1 : QCOMPARE( reversed->numPoints(), 4 );
11214 : 1 : QVERIFY( dynamic_cast< const QgsLineString * >( reversed->curveAt( 0 ) ) );
11215 : 1 : QVERIFY( dynamic_cast< const QgsCircularString * >( reversed->curveAt( 1 ) ) );
11216 : 1 : QCOMPARE( reversed->wkbType(), QgsWkbTypes::CompoundCurveZM );
11217 : 1 : QVERIFY( reversed->is3D() );
11218 : 1 : QVERIFY( reversed->isMeasure() );
11219 : 1 : reversed->pointAt( 0, pt, v );
11220 : 1 : reversed->pointAt( 1, pt, v );
11221 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
11222 : 1 : reversed->pointAt( 2, pt, v );
11223 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
11224 : 1 : reversed->pointAt( 3, pt, v );
11225 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
11226 : :
11227 : : //addZValue
11228 : 1 : QgsCompoundCurve c28;
11229 : 1 : QgsCircularString l28;
11230 : 1 : QCOMPARE( c28.wkbType(), QgsWkbTypes::CompoundCurve );
11231 : 1 : QVERIFY( c28.addZValue() );
11232 : 1 : QCOMPARE( c28.wkbType(), QgsWkbTypes::CompoundCurveZ );
11233 : 1 : c28.clear();
11234 : : //2d line
11235 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11236 : 1 : c28.addCurve( l28.clone() );
11237 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 3, 4 ) );
11238 : 1 : c28.addCurve( l28.clone() );
11239 : 1 : QVERIFY( c28.addZValue( 2 ) );
11240 : 1 : QVERIFY( c28.is3D() );
11241 : 1 : QCOMPARE( c28.wkbType(), QgsWkbTypes::CompoundCurveZ );
11242 : 1 : c28.pointAt( 0, pt, v );
11243 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ) );
11244 : 1 : c28.pointAt( 1, pt, v );
11245 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 2 ) );
11246 : 1 : c28.pointAt( 2, pt, v );
11247 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 3, 4, 2 ) );
11248 : :
11249 : 1 : QVERIFY( !c28.addZValue( 4 ) ); //already has z value, test that existing z is unchanged
11250 : 1 : c28.pointAt( 0, pt, v );
11251 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 2 ) );
11252 : 1 : c28.pointAt( 1, pt, v );
11253 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 2 ) );
11254 : 1 : c28.pointAt( 2, pt, v );
11255 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 3, 4, 2 ) );
11256 : :
11257 : : //linestring with m
11258 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) );
11259 : 1 : c28.clear();
11260 : 1 : c28.addCurve( l28.clone() );
11261 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 21, 32, 0, 4 ) );
11262 : 1 : c28.addCurve( l28.clone() );
11263 : 1 : QVERIFY( c28.addZValue( 5 ) );
11264 : 1 : QVERIFY( c28.is3D() );
11265 : 1 : QVERIFY( c28.isMeasure() );
11266 : 1 : QCOMPARE( c28.wkbType(), QgsWkbTypes::CompoundCurveZM );
11267 : 1 : c28.pointAt( 0, pt, v );
11268 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 5, 3 ) );
11269 : 1 : c28.pointAt( 1, pt, v );
11270 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 5, 4 ) );
11271 : 1 : c28.pointAt( 2, pt, v );
11272 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 21, 32, 5, 4 ) );
11273 : :
11274 : : //addMValue
11275 : 1 : c28.clear();
11276 : : //2d line
11277 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11278 : 1 : c28.addCurve( l28.clone() );
11279 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 3, 4 ) );
11280 : 1 : c28.addCurve( l28.clone() );
11281 : 1 : QVERIFY( c28.addMValue( 2 ) );
11282 : 1 : QVERIFY( c28.isMeasure() );
11283 : 1 : QCOMPARE( c28.wkbType(), QgsWkbTypes::CompoundCurveM );
11284 : 1 : c28.pointAt( 0, pt, v );
11285 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 2 ) );
11286 : 1 : c28.pointAt( 1, pt, v );
11287 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 2 ) );
11288 : 1 : c28.pointAt( 2, pt, v );
11289 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 2 ) );
11290 : :
11291 : 1 : QVERIFY( !c28.addMValue( 4 ) ); //already has z value, test that existing z is unchanged
11292 : 1 : c28.pointAt( 0, pt, v );
11293 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 2 ) );
11294 : 1 : c28.pointAt( 1, pt, v );
11295 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 2 ) );
11296 : 1 : c28.pointAt( 2, pt, v );
11297 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 2 ) );
11298 : :
11299 : : //linestring with z
11300 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 4 ) );
11301 : 1 : c28.clear();
11302 : 1 : c28.addCurve( l28.clone() );
11303 : 1 : l28.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 21, 32, 4 ) );
11304 : 1 : c28.addCurve( l28.clone() );
11305 : 1 : QVERIFY( c28.addMValue( 5 ) );
11306 : 1 : QVERIFY( c28.is3D() );
11307 : 1 : QVERIFY( c28.isMeasure() );
11308 : 1 : QCOMPARE( c28.wkbType(), QgsWkbTypes::CompoundCurveZM );
11309 : 1 : c28.pointAt( 0, pt, v );
11310 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 5 ) );
11311 : 1 : c28.pointAt( 1, pt, v );
11312 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
11313 : 1 : c28.pointAt( 2, pt, v );
11314 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 21, 32, 4, 5 ) );
11315 : :
11316 : : //dropZValue
11317 : 1 : QgsCompoundCurve c28d;
11318 : 1 : QgsCircularString l28d;
11319 : 1 : QVERIFY( !c28d.dropZValue() );
11320 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11321 : 1 : c28d.addCurve( l28d.clone() );
11322 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
11323 : 1 : c28d.addCurve( l28d.clone() );
11324 : 1 : QVERIFY( !c28d.dropZValue() );
11325 : 1 : c28d.addZValue( 1.0 );
11326 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveZ );
11327 : 1 : QVERIFY( c28d.is3D() );
11328 : 1 : QVERIFY( c28d.dropZValue() );
11329 : 1 : QVERIFY( !c28d.is3D() );
11330 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurve );
11331 : 1 : c28d.pointAt( 0, pt, v );
11332 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
11333 : 1 : c28d.pointAt( 1, pt, v );
11334 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
11335 : 1 : c28d.pointAt( 2, pt, v );
11336 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 21, 22 ) );
11337 : :
11338 : 1 : QVERIFY( !c28d.dropZValue() ); //already dropped
11339 : : //linestring with m
11340 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) );
11341 : 1 : c28d.clear();
11342 : 1 : c28d.addCurve( l28d.clone() );
11343 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 3, 4 ) );
11344 : 1 : c28d.addCurve( l28d.clone() );
11345 : 1 : QVERIFY( c28d.dropZValue() );
11346 : 1 : QVERIFY( !c28d.is3D() );
11347 : 1 : QVERIFY( c28d.isMeasure() );
11348 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveM );
11349 : 1 : c28d.pointAt( 0, pt, v );
11350 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
11351 : 1 : c28d.pointAt( 1, pt, v );
11352 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 4 ) );
11353 : 1 : c28d.pointAt( 2, pt, v );
11354 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 4 ) );
11355 : :
11356 : : //dropMValue
11357 : 1 : c28d.clear();
11358 : 1 : QVERIFY( !c28d.dropMValue() );
11359 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11360 : 1 : c28d.addCurve( l28d.clone() );
11361 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
11362 : 1 : c28d.addCurve( l28d.clone() );
11363 : 1 : QVERIFY( !c28d.dropMValue() );
11364 : 1 : c28d.addMValue( 1.0 );
11365 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveM );
11366 : 1 : QVERIFY( c28d.isMeasure() );
11367 : 1 : QVERIFY( c28d.dropMValue() );
11368 : 1 : QVERIFY( !c28d.isMeasure() );
11369 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurve );
11370 : 1 : c28d.pointAt( 0, pt, v );
11371 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
11372 : 1 : c28d.pointAt( 1, pt, v );
11373 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 11, 12 ) );
11374 : 1 : c28d.pointAt( 2, pt, v );
11375 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 21, 22 ) );
11376 : :
11377 : 1 : QVERIFY( !c28d.dropMValue() ); //already dropped
11378 : : //linestring with z
11379 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) );
11380 : 1 : c28d.clear();
11381 : 1 : c28d.addCurve( l28d.clone() );
11382 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 3, 4 ) );
11383 : 1 : c28d.addCurve( l28d.clone() );
11384 : 1 : QVERIFY( c28d.dropMValue() );
11385 : 1 : QVERIFY( !c28d.isMeasure() );
11386 : 1 : QVERIFY( c28d.is3D() );
11387 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveZ );
11388 : 1 : c28d.pointAt( 0, pt, v );
11389 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
11390 : 1 : c28d.pointAt( 1, pt, v );
11391 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 3 ) );
11392 : 1 : c28d.pointAt( 2, pt, v );
11393 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 21, 22, 3 ) );
11394 : :
11395 : : //convertTo
11396 : 1 : l28d.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11397 : 1 : c28d.clear();
11398 : 1 : c28d.addCurve( l28d.clone() );
11399 : 1 : QVERIFY( c28d.convertTo( QgsWkbTypes::CompoundCurve ) );
11400 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurve );
11401 : 1 : QVERIFY( c28d.convertTo( QgsWkbTypes::CompoundCurveZ ) );
11402 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveZ );
11403 : 1 : c28d.pointAt( 0, pt, v );
11404 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 1, 2 ) );
11405 : :
11406 : 1 : QVERIFY( c28d.convertTo( QgsWkbTypes::CompoundCurveZM ) );
11407 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveZM );
11408 : 1 : c28d.pointAt( 0, pt, v );
11409 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 1, 2 ) );
11410 : 1 : c28d.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 1, 2, 5 ) );
11411 : 1 : c28d.pointAt( 0, pt, v );
11412 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 5.0 ) );
11413 : 1 : QVERIFY( c28d.convertTo( QgsWkbTypes::CompoundCurveM ) );
11414 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurveM );
11415 : 1 : c28d.pointAt( 0, pt, v );
11416 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 1, 2 ) );
11417 : 1 : c28d.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 1, 2, 0, 6 ) );
11418 : 1 : c28d.pointAt( 0, pt, v );
11419 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0.0, 6.0 ) );
11420 : 1 : QVERIFY( c28d.convertTo( QgsWkbTypes::CompoundCurve ) );
11421 : 1 : QCOMPARE( c28d.wkbType(), QgsWkbTypes::CompoundCurve );
11422 : 1 : c28d.pointAt( 0, pt, v );
11423 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
11424 : 1 : QVERIFY( !c28d.convertTo( QgsWkbTypes::Polygon ) );
11425 : :
11426 : : //isRing
11427 : 1 : QgsCircularString l30;
11428 : 1 : QgsCompoundCurve c30;
11429 : 1 : QVERIFY( !c30.isRing() );
11430 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 2 ) );
11431 : 1 : c30.addCurve( l30.clone() );
11432 : 1 : QVERIFY( !c30.isRing() ); //<4 points
11433 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 31, 32 ) );
11434 : 1 : c30.clear();
11435 : 1 : c30.addCurve( l30.clone() );
11436 : 1 : QVERIFY( !c30.isRing() ); //not closed
11437 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
11438 : 1 : c30.clear();
11439 : 1 : c30.addCurve( l30.clone() );
11440 : 1 : QVERIFY( c30.isRing() );
11441 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11442 : 1 : c30.clear();
11443 : 1 : c30.addCurve( l30.clone() );
11444 : 1 : QVERIFY( !c30.isRing() );
11445 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) );
11446 : 1 : c30.addCurve( l30.clone() );
11447 : 1 : QVERIFY( !c30.isRing() );
11448 : 1 : l30.setPoints( QgsPointSequence() << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
11449 : 1 : c30.addCurve( l30.clone() );
11450 : 1 : QVERIFY( c30.isRing() );
11451 : :
11452 : : //coordinateSequence
11453 : 1 : QgsCompoundCurve c31;
11454 : 1 : QgsCircularString l31;
11455 : 1 : QgsCoordinateSequence coords = c31.coordinateSequence();
11456 : 1 : QCOMPARE( coords.count(), 1 );
11457 : 1 : QCOMPARE( coords.at( 0 ).count(), 1 );
11458 : 1 : QVERIFY( coords.at( 0 ).at( 0 ).isEmpty() );
11459 : 2 : l31.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 )
11460 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 )
11461 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
11462 : 1 : c31.addCurve( l31.clone() );
11463 : 1 : QgsLineString ls31;
11464 : 2 : ls31.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) <<
11465 : 1 : QgsPoint( QgsWkbTypes::PointZM, 31, 32, 16, 17 ) );
11466 : 1 : c31.addCurve( ls31.clone() );
11467 : 1 : coords = c31.coordinateSequence();
11468 : 1 : QCOMPARE( coords.count(), 1 );
11469 : 1 : QCOMPARE( coords.at( 0 ).count(), 1 );
11470 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).count(), 4 );
11471 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 2, 3 ) );
11472 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 4, 5 ) );
11473 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 2 ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 6, 7 ) );
11474 : 1 : QCOMPARE( coords.at( 0 ).at( 0 ).at( 3 ), QgsPoint( QgsWkbTypes::PointZM, 31, 32, 16, 17 ) );
11475 : :
11476 : : //nextVertex
11477 : 1 : QgsCompoundCurve c32;
11478 : 1 : QgsCircularString l32;
11479 : 1 : QgsVertexId vId;
11480 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11481 : 1 : vId = QgsVertexId( 0, 0, -2 );
11482 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11483 : 1 : vId = QgsVertexId( 0, 0, 10 );
11484 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11485 : : //CircularString
11486 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) );
11487 : 1 : c32.addCurve( l32.clone() );
11488 : 1 : vId = QgsVertexId( 0, 0, 2 ); //out of range
11489 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11490 : 1 : vId = QgsVertexId( 0, 0, -5 );
11491 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11492 : 1 : vId = QgsVertexId( 0, 0, -1 );
11493 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11494 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 0 ) );
11495 : 1 : QCOMPARE( p, QgsPoint( 1, 2 ) );
11496 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11497 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11498 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
11499 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11500 : 1 : vId = QgsVertexId( 0, 1, 0 );
11501 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11502 : 1 : QCOMPARE( vId, QgsVertexId( 0, 1, 1 ) ); //test that ring number is maintained
11503 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
11504 : 1 : vId = QgsVertexId( 1, 0, 0 );
11505 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11506 : 1 : QCOMPARE( vId, QgsVertexId( 1, 0, 1 ) ); //test that part number is maintained
11507 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
11508 : 1 : QgsLineString ls32;
11509 : 1 : ls32.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 13, 14 ) );
11510 : 1 : c32.addCurve( ls32.clone() );
11511 : 1 : vId = QgsVertexId( 0, 0, 1 );
11512 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11513 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 2 ) );
11514 : 1 : QCOMPARE( p, QgsPoint( 13, 14 ) );
11515 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11516 : :
11517 : : //CircularStringZ
11518 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
11519 : 1 : c32.clear();
11520 : 1 : c32.addCurve( l32.clone() );
11521 : 1 : vId = QgsVertexId( 0, 0, -1 );
11522 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11523 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 0 ) );
11524 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
11525 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11526 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11527 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
11528 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11529 : : //CircularStringM
11530 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
11531 : 1 : c32.clear();
11532 : 1 : c32.addCurve( l32.clone() );
11533 : 1 : vId = QgsVertexId( 0, 0, -1 );
11534 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11535 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 0 ) );
11536 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
11537 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11538 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11539 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
11540 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11541 : : //CircularStringZM
11542 : 1 : l32.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
11543 : 1 : c32.clear();
11544 : 1 : c32.addCurve( l32.clone() );
11545 : 1 : vId = QgsVertexId( 0, 0, -1 );
11546 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11547 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 0 ) );
11548 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
11549 : 1 : QVERIFY( c32.nextVertex( vId, p ) );
11550 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11551 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
11552 : 1 : QVERIFY( !c32.nextVertex( vId, p ) );
11553 : :
11554 : : //vertexAt and pointAt
11555 : 1 : QgsCompoundCurve c33;
11556 : 1 : QgsCircularString l33;
11557 : 1 : c33.vertexAt( QgsVertexId( 0, 0, -10 ) ); //out of bounds, check for no crash
11558 : 1 : c33.vertexAt( QgsVertexId( 0, 0, 10 ) ); //out of bounds, check for no crash
11559 : 1 : QVERIFY( !c33.pointAt( -10, p, type ) );
11560 : 1 : QVERIFY( !c33.pointAt( 10, p, type ) );
11561 : : //CircularString
11562 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
11563 : 1 : c33.addCurve( l33.clone() );
11564 : 1 : c33.vertexAt( QgsVertexId( 0, 0, -10 ) );
11565 : 1 : c33.vertexAt( QgsVertexId( 0, 0, 10 ) ); //out of bounds, check for no crash
11566 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
11567 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
11568 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 1, 22 ) );
11569 : 1 : QVERIFY( !c33.pointAt( -10, p, type ) );
11570 : 1 : QVERIFY( !c33.pointAt( 10, p, type ) );
11571 : 1 : QVERIFY( c33.pointAt( 0, p, type ) );
11572 : 1 : QCOMPARE( p, QgsPoint( 1, 2 ) );
11573 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11574 : 1 : QVERIFY( c33.pointAt( 1, p, type ) );
11575 : 1 : QCOMPARE( p, QgsPoint( 11, 12 ) );
11576 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
11577 : 1 : QVERIFY( c33.pointAt( 2, p, type ) );
11578 : 1 : QCOMPARE( p, QgsPoint( 1, 22 ) );
11579 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11580 : 1 : QgsLineString ls33;
11581 : 1 : ls33.setPoints( QgsPointSequence() << QgsPoint( 1, 22 ) << QgsPoint( 3, 34 ) );
11582 : 1 : c33.addCurve( ls33.clone() );
11583 : 1 : QVERIFY( c33.pointAt( 3, p, type ) );
11584 : 1 : QCOMPARE( p, QgsPoint( 3, 34 ) );
11585 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11586 : :
11587 : 1 : c33.clear();
11588 : : //CircularStringZ
11589 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 22, 23 ) );
11590 : 1 : c33.addCurve( l33.clone() );
11591 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
11592 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
11593 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZ, 1, 22, 23 ) );
11594 : 1 : QVERIFY( c33.pointAt( 0, p, type ) );
11595 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
11596 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11597 : 1 : QVERIFY( c33.pointAt( 1, p, type ) );
11598 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
11599 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
11600 : 1 : QVERIFY( c33.pointAt( 2, p, type ) );
11601 : 1 : QCOMPARE( p, QgsPoint( 1, 22, 23 ) );
11602 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11603 : :
11604 : : //CircularStringM
11605 : 1 : c33.clear();
11606 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) << QgsPoint( QgsWkbTypes::PointM, 1, 22, 0, 24 ) );
11607 : 1 : c33.addCurve( l33.clone() );
11608 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
11609 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
11610 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointM, 1, 22, 0, 24 ) );
11611 : 1 : QVERIFY( c33.pointAt( 0, p, type ) );
11612 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
11613 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11614 : 1 : QVERIFY( c33.pointAt( 1, p, type ) );
11615 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 14 ) );
11616 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
11617 : 1 : QVERIFY( c33.pointAt( 2, p, type ) );
11618 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointM, 1, 22, 0, 24 ) );
11619 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11620 : : //CircularStringZM
11621 : 1 : l33.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 22, 23, 24 ) );
11622 : 1 : c33.clear();
11623 : 1 : c33.addCurve( l33.clone() );
11624 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
11625 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
11626 : 1 : QCOMPARE( c33.vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 22, 23, 24 ) );
11627 : 1 : QVERIFY( c33.pointAt( 0, p, type ) );
11628 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
11629 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11630 : 1 : QVERIFY( c33.pointAt( 1, p, type ) );
11631 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
11632 : 1 : QCOMPARE( type, QgsVertexId::CurveVertex );
11633 : 1 : QVERIFY( c33.pointAt( 2, p, type ) );
11634 : 1 : QCOMPARE( p, QgsPoint( QgsWkbTypes::PointZM, 1, 22, 23, 24 ) );
11635 : 1 : QCOMPARE( type, QgsVertexId::SegmentVertex );
11636 : :
11637 : : //centroid
11638 : 1 : QgsCircularString l34;
11639 : 1 : QgsCompoundCurve c34;
11640 : 1 : QCOMPARE( c34.centroid(), QgsPoint( 0, 0 ) );
11641 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
11642 : 1 : c34.addCurve( l34.clone() );
11643 : 1 : QCOMPARE( c34.centroid(), QgsPoint( 5, 10 ) );
11644 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 20, 10 ) << QgsPoint( 2, 9 ) );
11645 : 1 : c34.clear();
11646 : 1 : c34.addCurve( l34.clone() );
11647 : 1 : QgsPoint centroid = c34.centroid();
11648 : 1 : QGSCOMPARENEAR( centroid.x(), 7.333, 0.001 );
11649 : 1 : QGSCOMPARENEAR( centroid.y(), 6.333, 0.001 );
11650 : 1 : l34.setPoints( QgsPointSequence() << QgsPoint( 2, 9 ) << QgsPoint( 12, 9 ) << QgsPoint( 15, 19 ) );
11651 : 1 : c34.addCurve( l34.clone() );
11652 : 1 : centroid = c34.centroid();
11653 : 1 : QGSCOMPARENEAR( centroid.x(), 9.756646, 0.001 );
11654 : 1 : QGSCOMPARENEAR( centroid.y(), 8.229039, 0.001 );
11655 : :
11656 : : //closest segment
11657 : 1 : QgsCompoundCurve c35;
11658 : 1 : QgsCircularString l35;
11659 : 1 : int leftOf = 0;
11660 : 1 : p = QgsPoint( 0, 0 ); // reset all coords to zero
11661 : 1 : ( void )c35.closestSegment( QgsPoint( 1, 2 ), p, vId ); //empty line, just want no crash
11662 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
11663 : 1 : c35.addCurve( l35.clone() );
11664 : 1 : QVERIFY( c35.closestSegment( QgsPoint( 5, 10 ), p, vId ) < 0 );
11665 : 1 : l35.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 7, 12 ) << QgsPoint( 5, 15 ) );
11666 : 1 : c35.clear();
11667 : 1 : c35.addCurve( l35.clone() );
11668 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 4, 11 ), p, vId, &leftOf ), 2.0, 0.0001 );
11669 : 1 : QCOMPARE( p, QgsPoint( 5, 10 ) );
11670 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11671 : 1 : QCOMPARE( leftOf, -1 );
11672 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 8, 11 ), p, vId, &leftOf ), 1.583512, 0.0001 );
11673 : 1 : QGSCOMPARENEAR( p.x(), 6.84, 0.01 );
11674 : 1 : QGSCOMPARENEAR( p.y(), 11.49, 0.01 );
11675 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11676 : 1 : QCOMPARE( leftOf, 1 );
11677 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 5.5, 11.5 ), p, vId, &leftOf ), 1.288897, 0.0001 );
11678 : 1 : QGSCOMPARENEAR( p.x(), 6.302776, 0.01 );
11679 : 1 : QGSCOMPARENEAR( p.y(), 10.7, 0.01 );
11680 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 1 ) );
11681 : 1 : QCOMPARE( leftOf, -1 );
11682 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 7, 16 ), p, vId, &leftOf ), 3.068288, 0.0001 );
11683 : 1 : QGSCOMPARENEAR( p.x(), 5.981872, 0.01 );
11684 : 1 : QGSCOMPARENEAR( p.y(), 14.574621, 0.01 );
11685 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 2 ) );
11686 : 1 : QCOMPARE( leftOf, 1 );
11687 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 5.5, 13.5 ), p, vId, &leftOf ), 1.288897, 0.0001 );
11688 : 1 : QGSCOMPARENEAR( p.x(), 6.302776, 0.01 );
11689 : 1 : QGSCOMPARENEAR( p.y(), 14.3, 0.01 );
11690 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 2 ) );
11691 : 1 : QCOMPARE( leftOf, -1 );
11692 : : // point directly on segment
11693 : 1 : QCOMPARE( c35.closestSegment( QgsPoint( 5, 15 ), p, vId, &leftOf ), 0.0 );
11694 : 1 : QCOMPARE( p, QgsPoint( 5, 15 ) );
11695 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 2 ) );
11696 : 1 : QCOMPARE( leftOf, 0 );
11697 : :
11698 : 1 : QgsLineString ls35;
11699 : 1 : ls35.setPoints( QgsPointSequence() << QgsPoint( 5, 15 ) << QgsPoint( 5, 20 ) );
11700 : 1 : c35.addCurve( ls35.clone() );
11701 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 5.5, 16.5 ), p, vId, &leftOf ), 0.25, 0.0001 );
11702 : 1 : QGSCOMPARENEAR( p.x(), 5.0, 0.01 );
11703 : 1 : QGSCOMPARENEAR( p.y(), 16.5, 0.01 );
11704 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 3 ) );
11705 : 1 : QCOMPARE( leftOf, 1 );
11706 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 4.5, 16.5 ), p, vId, &leftOf ), 0.25, 0.0001 );
11707 : 1 : QGSCOMPARENEAR( p.x(), 5.0, 0.01 );
11708 : 1 : QGSCOMPARENEAR( p.y(), 16.5, 0.01 );
11709 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 3 ) );
11710 : 1 : QCOMPARE( leftOf, -1 );
11711 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 4.5, 21.5 ), p, vId, &leftOf ), 2.500000, 0.0001 );
11712 : 1 : QGSCOMPARENEAR( p.x(), 5.0, 0.01 );
11713 : 1 : QGSCOMPARENEAR( p.y(), 20.0, 0.01 );
11714 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 3 ) );
11715 : 1 : QCOMPARE( leftOf, -1 );
11716 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 5.5, 21.5 ), p, vId, &leftOf ), 2.500000, 0.0001 );
11717 : 1 : QGSCOMPARENEAR( p.x(), 5.0, 0.01 );
11718 : 1 : QGSCOMPARENEAR( p.y(), 20.0, 0.01 );
11719 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 3 ) );
11720 : 1 : QCOMPARE( leftOf, 1 );
11721 : 1 : QGSCOMPARENEAR( c35.closestSegment( QgsPoint( 5, 20 ), p, vId, &leftOf ), 0.0000, 0.0001 );
11722 : 1 : QGSCOMPARENEAR( p.x(), 5.0, 0.01 );
11723 : 1 : QGSCOMPARENEAR( p.y(), 20.0, 0.01 );
11724 : 1 : QCOMPARE( vId, QgsVertexId( 0, 0, 3 ) );
11725 : 1 : QCOMPARE( leftOf, 0 );
11726 : :
11727 : : //sumUpArea
11728 : 1 : QgsCompoundCurve c36;
11729 : 1 : QgsCircularString l36;
11730 : 1 : double area = 1.0; //sumUpArea adds to area, so start with non-zero value
11731 : 1 : c36.sumUpArea( area );
11732 : 1 : QCOMPARE( area, 1.0 );
11733 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) );
11734 : 1 : c36.addCurve( l36.clone() );
11735 : 1 : c36.sumUpArea( area );
11736 : 1 : QCOMPARE( area, 1.0 );
11737 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 10 ) );
11738 : 1 : c36.clear();
11739 : 1 : c36.addCurve( l36.clone() );
11740 : 1 : c36.sumUpArea( area );
11741 : 1 : QCOMPARE( area, 1.0 );
11742 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2, 0 ) << QgsPoint( 2, 2 ) );
11743 : 1 : c36.clear();
11744 : 1 : c36.addCurve( l36.clone() );
11745 : 1 : c36.sumUpArea( area );
11746 : 1 : QGSCOMPARENEAR( area, 4.141593, 0.0001 );
11747 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 2, 0 ) << QgsPoint( 2, 2 ) << QgsPoint( 0, 2 ) );
11748 : 1 : c36.clear();
11749 : 1 : c36.addCurve( l36.clone() );
11750 : 1 : c36.sumUpArea( area );
11751 : 1 : QGSCOMPARENEAR( area, 7.283185, 0.0001 );
11752 : : // full circle
11753 : 1 : l36.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 4, 0 ) << QgsPoint( 0, 0 ) );
11754 : 1 : c36.clear();
11755 : 1 : c36.addCurve( l36.clone() );
11756 : 1 : area = 0.0;
11757 : 1 : c36.sumUpArea( area );
11758 : 1 : QGSCOMPARENEAR( area, 12.566370614359172, 0.0001 );
11759 : :
11760 : : //boundingBox - test that bounding box is updated after every modification to the circular string
11761 : 1 : QgsCompoundCurve c37;
11762 : 1 : QgsCircularString l37;
11763 : 1 : QVERIFY( c37.boundingBox().isNull() );
11764 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 15 ) );
11765 : 1 : c37.addCurve( l37.clone() );
11766 : 1 : QCOMPARE( c37.boundingBox(), QgsRectangle( 5, 10, 10, 15 ) );
11767 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( -5, -10 ) << QgsPoint( -6, -10 ) << QgsPoint( -5.5, -9 ) );
11768 : 1 : c37.clear();
11769 : 1 : c37.addCurve( l37.clone() );
11770 : 1 : QCOMPARE( c37.boundingBox(), QgsRectangle( -6.125, -10.25, -5, -9 ) );
11771 : 1 : QByteArray wkbToAppend = c37.asWkb();
11772 : 1 : c37.clear();
11773 : 1 : QVERIFY( c37.boundingBox().isNull() );
11774 : 1 : QgsConstWkbPtr wkbToAppendPtr( wkbToAppend );
11775 : 1 : l37.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 10, 15 ) );
11776 : 1 : c37.clear();
11777 : 1 : c37.addCurve( l37.clone() );
11778 : 1 : QCOMPARE( c37.boundingBox(), QgsRectangle( 5, 10, 10, 15 ) );
11779 : 1 : c37.fromWkb( wkbToAppendPtr );
11780 : 1 : QCOMPARE( c37.boundingBox(), QgsRectangle( -6.125, -10.25, -5, -9 ) );
11781 : 2 : c37.fromWkt( QStringLiteral( "CompoundCurve(CircularString( 5 10, 6 10, 5.5 9 ))" ) );
11782 : 1 : QCOMPARE( c37.boundingBox(), QgsRectangle( 5, 9, 6.125, 10.25 ) );
11783 : 1 : c37.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( -1, 7 ) );
11784 : 1 : QgsRectangle r = c37.boundingBox();
11785 : 1 : QGSCOMPARENEAR( r.xMinimum(), -3.014, 0.01 );
11786 : 1 : QGSCOMPARENEAR( r.xMaximum(), 14.014, 0.01 );
11787 : 1 : QGSCOMPARENEAR( r.yMinimum(), -7.0146, 0.01 );
11788 : 1 : QGSCOMPARENEAR( r.yMaximum(), 12.4988, 0.01 );
11789 : 1 : c37.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( -3, 10 ) );
11790 : 1 : r = c37.boundingBox();
11791 : 1 : QGSCOMPARENEAR( r.xMinimum(), -10.294, 0.01 );
11792 : 1 : QGSCOMPARENEAR( r.xMaximum(), 12.294, 0.01 );
11793 : 1 : QGSCOMPARENEAR( r.yMinimum(), 9, 0.01 );
11794 : 1 : QGSCOMPARENEAR( r.yMaximum(), 31.856, 0.01 );
11795 : 1 : c37.deleteVertex( QgsVertexId( 0, 0, 1 ) );
11796 : 1 : r = c37.boundingBox();
11797 : 1 : QGSCOMPARENEAR( r.xMinimum(), 5, 0.01 );
11798 : 1 : QGSCOMPARENEAR( r.xMaximum(), 6.125, 0.01 );
11799 : 1 : QGSCOMPARENEAR( r.yMinimum(), 9, 0.01 );
11800 : 1 : QGSCOMPARENEAR( r.yMaximum(), 10.25, 0.01 );
11801 : :
11802 : : //angle
11803 : 1 : QgsCompoundCurve c38;
11804 : 1 : QgsCircularString l38;
11805 : 1 : ( void )c38.vertexAngle( QgsVertexId() ); //just want no crash
11806 : 1 : ( void )c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash
11807 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) );
11808 : 1 : c38.addCurve( l38.clone() );
11809 : 1 : ( void )c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash, any answer is meaningless
11810 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) );
11811 : 1 : c38.clear();
11812 : 1 : c38.addCurve( l38.clone() );
11813 : 1 : ( void )c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash, any answer is meaningless
11814 : 1 : ( void )c38.vertexAngle( QgsVertexId( 0, 0, 1 ) ); //just want no crash, any answer is meaningless
11815 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 ) );
11816 : 1 : c38.clear();
11817 : 1 : c38.addCurve( l38.clone() );
11818 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
11819 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 0, 0.0001 );
11820 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 4.712389, 0.0001 );
11821 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 2 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
11822 : 1 : c38.clear();
11823 : 1 : c38.addCurve( l38.clone() );
11824 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
11825 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.141593, 0.0001 );
11826 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 4.712389, 0.0001 );
11827 : 1 : ( void )c38.vertexAngle( QgsVertexId( 0, 0, 20 ) ); // no crash
11828 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 )
11829 : 1 : << QgsPoint( -1, 3 ) << QgsPoint( 0, 4 ) );
11830 : 1 : c38.clear();
11831 : 1 : c38.addCurve( l38.clone() );
11832 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 1.5708, 0.0001 );
11833 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 0, 0.0001 );
11834 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 4.712389, 0.0001 );
11835 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 0, 0.0001 );
11836 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 1.5708, 0.0001 );
11837 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 4 ) << QgsPoint( -1, 3 ) << QgsPoint( 0, 2 )
11838 : 1 : << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
11839 : 1 : c38.clear();
11840 : 1 : c38.addCurve( l38.clone() );
11841 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 4.712389, 0.0001 );
11842 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.141592, 0.0001 );
11843 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 1.5708, 0.0001 );
11844 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 3.141592, 0.0001 );
11845 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 4.712389, 0.0001 );
11846 : :
11847 : : // with second curve
11848 : 1 : QgsLineString ls38;
11849 : 1 : ls38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, -1 ) );
11850 : 1 : c38.addCurve( ls38.clone() );
11851 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 3.926991, 0.0001 );
11852 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 5 ) ), 3.141593, 0.0001 );
11853 : :
11854 : : //closed circular string
11855 : 1 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 0, 0 ) );
11856 : 1 : c38.clear();
11857 : 1 : c38.addCurve( l38.clone() );
11858 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 0, 0.00001 );
11859 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 3.141592, 0.00001 );
11860 : 1 : QGSCOMPARENEAR( c38.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 0, 0.00001 );
11861 : :
11862 : : //removing a vertex from a 3 point comound curveshould remove the whole line
11863 : 1 : QgsCircularString l39;
11864 : 1 : QgsCompoundCurve c39;
11865 : 1 : l39.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 ) );
11866 : 1 : c39.addCurve( l39.clone() );
11867 : 1 : QCOMPARE( c39.numPoints(), 3 );
11868 : 1 : c39.deleteVertex( QgsVertexId( 0, 0, 2 ) );
11869 : 1 : QCOMPARE( c39.numPoints(), 0 );
11870 : :
11871 : : //boundary
11872 : 1 : QgsCompoundCurve cBoundary1;
11873 : 1 : QgsCircularString boundary1;
11874 : 1 : QVERIFY( !cBoundary1.boundary() );
11875 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
11876 : 1 : cBoundary1.addCurve( boundary1.clone() );
11877 : 1 : QgsAbstractGeometry *boundary = cBoundary1.boundary();
11878 : 1 : QgsMultiPoint *mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
11879 : 1 : QVERIFY( mpBoundary );
11880 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
11881 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
11882 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
11883 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
11884 : 1 : delete boundary;
11885 : :
11886 : : // closed string = no boundary
11887 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
11888 : 1 : cBoundary1.clear();
11889 : 1 : cBoundary1.addCurve( boundary1.clone() );
11890 : 1 : QVERIFY( !cBoundary1.boundary() );
11891 : :
11892 : : //boundary with z
11893 : 1 : boundary1.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) );
11894 : 1 : cBoundary1.clear();
11895 : 1 : cBoundary1.addCurve( boundary1.clone() );
11896 : 1 : boundary = cBoundary1.boundary();
11897 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
11898 : 1 : QVERIFY( mpBoundary );
11899 : 1 : QCOMPARE( mpBoundary->geometryN( 0 )->wkbType(), QgsWkbTypes::PointZ );
11900 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
11901 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
11902 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->z(), 10.0 );
11903 : 1 : QCOMPARE( mpBoundary->geometryN( 1 )->wkbType(), QgsWkbTypes::PointZ );
11904 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
11905 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
11906 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
11907 : 1 : delete boundary;
11908 : :
11909 : : // addToPainterPath (note most tests are in test_qgsgeometry.py)
11910 : 1 : QgsCompoundCurve ccPath;
11911 : 1 : QgsCircularString path;
11912 : 1 : QPainterPath pPath;
11913 : 1 : ccPath.addToPainterPath( pPath );
11914 : 1 : QVERIFY( pPath.isEmpty() );
11915 : 2 : path.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 )
11916 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 21, 2, 3 ) );
11917 : 1 : ccPath.addCurve( path.clone() );
11918 : 1 : ccPath.addToPainterPath( pPath );
11919 : 1 : QGSCOMPARENEAR( pPath.currentPosition().x(), 21.0, 0.01 );
11920 : 1 : QGSCOMPARENEAR( pPath.currentPosition().y(), 2.0, 0.01 );
11921 : 1 : QVERIFY( !pPath.isEmpty() );
11922 : 1 : QgsLineString lsPath;
11923 : 2 : lsPath.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 21, 2, 3 )
11924 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 31, 12, 3 ) );
11925 : 1 : ccPath.addCurve( lsPath.clone() );
11926 : 1 : pPath = QPainterPath();
11927 : 1 : ccPath.addToPainterPath( pPath );
11928 : 1 : QGSCOMPARENEAR( pPath.currentPosition().x(), 31.0, 0.01 );
11929 : 1 : QGSCOMPARENEAR( pPath.currentPosition().y(), 12.0, 0.01 );
11930 : :
11931 : : // even number of points - should still work
11932 : 1 : pPath = QPainterPath();
11933 : 1 : path.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZ, 11, 12, 13 ) );
11934 : 1 : ccPath.clear();
11935 : 1 : ccPath.addCurve( path.clone() );
11936 : 1 : ccPath.addToPainterPath( pPath );
11937 : 1 : QGSCOMPARENEAR( pPath.currentPosition().x(), 11.0, 0.01 );
11938 : 1 : QGSCOMPARENEAR( pPath.currentPosition().y(), 12.0, 0.01 );
11939 : 1 : QVERIFY( !pPath.isEmpty() );
11940 : :
11941 : : // toCurveType
11942 : 1 : QgsCircularString curveLine1;
11943 : 1 : QgsCompoundCurve cc1;
11944 : 1 : curveLine1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
11945 : 1 : cc1.addCurve( curveLine1.clone() );
11946 : 1 : std::unique_ptr< QgsCurve > curveType( cc1.toCurveType() );
11947 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::CompoundCurve );
11948 : 1 : QCOMPARE( curveType->numPoints(), 3 );
11949 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
11950 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
11951 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 1, 22 ) );
11952 : 1 : QgsLineString ccls1;
11953 : 1 : ccls1.setPoints( QgsPointSequence() << QgsPoint( 1, 22 ) << QgsPoint( 1, 25 ) );
11954 : 1 : cc1.addCurve( ccls1.clone() );
11955 : 1 : curveType.reset( cc1.toCurveType() );
11956 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::CompoundCurve );
11957 : 1 : QCOMPARE( curveType->numPoints(), 4 );
11958 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( 1, 2 ) );
11959 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( 11, 12 ) );
11960 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( 1, 22 ) );
11961 : 1 : QCOMPARE( curveType->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( 1, 25 ) );
11962 : :
11963 : : //test that area of a compound curve ring is equal to a closed linestring with the same vertices
11964 : 1 : QgsCompoundCurve cc;
11965 : 1 : QgsLineString *ll1 = new QgsLineString();
11966 : 1 : ll1->setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 ) );
11967 : 1 : cc.addCurve( ll1 );
11968 : 1 : QgsLineString *ll2 = new QgsLineString();
11969 : 1 : ll2->setPoints( QgsPointSequence() << QgsPoint( 0, 2 ) << QgsPoint( -1, 0 ) << QgsPoint( 0, -1 ) );
11970 : 1 : cc.addCurve( ll2 );
11971 : 1 : QgsLineString *ll3 = new QgsLineString();
11972 : 1 : ll3->setPoints( QgsPointSequence() << QgsPoint( 0, -1 ) << QgsPoint( 1, 1 ) );
11973 : 1 : cc.addCurve( ll3 );
11974 : :
11975 : 1 : double ccArea = 0.0;
11976 : 1 : cc.sumUpArea( ccArea );
11977 : :
11978 : 1 : QgsLineString ls;
11979 : 2 : ls.setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 0, 2 ) << QgsPoint( -1, 0 ) << QgsPoint( 0, -1 )
11980 : 1 : << QgsPoint( 1, 1 ) );
11981 : 1 : double lsArea = 0.0;
11982 : 1 : ls.sumUpArea( lsArea );
11983 : 1 : QGSCOMPARENEAR( ccArea, lsArea, 4 * std::numeric_limits<double>::epsilon() );
11984 : :
11985 : :
11986 : : //addVertex
11987 : 1 : QgsCompoundCurve ac1;
11988 : 1 : ac1.addVertex( QgsPoint( 1.0, 2.0 ) );
11989 : 1 : QVERIFY( !ac1.isEmpty() );
11990 : 1 : QCOMPARE( ac1.numPoints(), 1 );
11991 : 1 : QCOMPARE( ac1.vertexCount(), 1 );
11992 : 1 : QCOMPARE( ac1.nCoordinates(), 1 );
11993 : 1 : QCOMPARE( ac1.ringCount(), 1 );
11994 : 1 : QCOMPARE( ac1.partCount(), 1 );
11995 : 1 : QVERIFY( !ac1.is3D() );
11996 : 1 : QVERIFY( !ac1.isMeasure() );
11997 : 1 : QCOMPARE( ac1.wkbType(), QgsWkbTypes::CompoundCurve );
11998 : 1 : QVERIFY( !ac1.hasCurvedSegments() );
11999 : 1 : QCOMPARE( ac1.area(), 0.0 );
12000 : 1 : QCOMPARE( ac1.perimeter(), 0.0 );
12001 : :
12002 : : //adding first vertex should set linestring z/m type
12003 : 1 : QgsCompoundCurve ac2;
12004 : 1 : ac2.addVertex( QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) );
12005 : 1 : QVERIFY( !ac2.isEmpty() );
12006 : 1 : QVERIFY( ac2.is3D() );
12007 : 1 : QVERIFY( !ac2.isMeasure() );
12008 : 1 : QCOMPARE( ac2.wkbType(), QgsWkbTypes::CompoundCurveZ );
12009 : 1 : QCOMPARE( ac2.wktTypeStr(), QString( "CompoundCurveZ" ) );
12010 : :
12011 : 1 : QgsCompoundCurve ac3;
12012 : 1 : ac3.addVertex( QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0.0, 3.0 ) );
12013 : 1 : QVERIFY( !ac3.isEmpty() );
12014 : 1 : QVERIFY( !ac3.is3D() );
12015 : 1 : QVERIFY( ac3.isMeasure() );
12016 : 1 : QCOMPARE( ac3.wkbType(), QgsWkbTypes::CompoundCurveM );
12017 : 1 : QCOMPARE( ac3.wktTypeStr(), QString( "CompoundCurveM" ) );
12018 : :
12019 : 1 : QgsCompoundCurve ac4;
12020 : 1 : ac4.addVertex( QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 ) );
12021 : 1 : QVERIFY( !ac4.isEmpty() );
12022 : 1 : QVERIFY( ac4.is3D() );
12023 : 1 : QVERIFY( ac4.isMeasure() );
12024 : 1 : QCOMPARE( ac4.wkbType(), QgsWkbTypes::CompoundCurveZM );
12025 : 1 : QCOMPARE( ac4.wktTypeStr(), QString( "CompoundCurveZM" ) );
12026 : :
12027 : : //adding subsequent vertices should not alter z/m type, regardless of points type
12028 : 1 : QgsCompoundCurve ac5;
12029 : 1 : ac5.addVertex( QgsPoint( QgsWkbTypes::Point, 1.0, 2.0 ) ); //2d type
12030 : 1 : QCOMPARE( ac5.wkbType(), QgsWkbTypes::CompoundCurve );
12031 : 1 : ac5.addVertex( QgsPoint( QgsWkbTypes::PointZ, 11.0, 12.0, 13.0 ) ); // add 3d point
12032 : 1 : QCOMPARE( ac5.numPoints(), 2 );
12033 : 1 : QCOMPARE( ac5.vertexCount(), 2 );
12034 : 1 : QCOMPARE( ac5.nCoordinates(), 2 );
12035 : 1 : QCOMPARE( ac5.ringCount(), 1 );
12036 : 1 : QCOMPARE( ac5.partCount(), 1 );
12037 : 1 : QCOMPARE( ac5.wkbType(), QgsWkbTypes::CompoundCurve ); //should still be 2d
12038 : 1 : QVERIFY( !ac5.is3D() );
12039 : 1 : QCOMPARE( ac5.area(), 0.0 );
12040 : 1 : QCOMPARE( ac5.perimeter(), 0.0 );
12041 : :
12042 : 1 : QgsCompoundCurve ac6;
12043 : 1 : ac6.addVertex( QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3.0 ) ); //3d type
12044 : 1 : QCOMPARE( ac6.wkbType(), QgsWkbTypes::CompoundCurveZ );
12045 : 1 : ac6.addVertex( QgsPoint( QgsWkbTypes::Point, 11.0, 12.0 ) ); //add 2d point
12046 : 1 : QCOMPARE( ac6.wkbType(), QgsWkbTypes::CompoundCurveZ ); //should still be 3d
12047 : 1 : ac6.pointAt( 1, pt, v );
12048 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZ, 11.0, 12.0 ) );
12049 : 1 : QVERIFY( ac6.is3D() );
12050 : 1 : QCOMPARE( ac6.numPoints(), 2 );
12051 : 1 : QCOMPARE( ac6.vertexCount(), 2 );
12052 : 1 : QCOMPARE( ac6.nCoordinates(), 2 );
12053 : 1 : QCOMPARE( ac6.ringCount(), 1 );
12054 : 1 : QCOMPARE( ac6.partCount(), 1 );
12055 : :
12056 : : //close
12057 : 1 : QgsLineString closeC1;
12058 : 1 : QgsCompoundCurve closeCc1;
12059 : 1 : closeCc1.close();
12060 : 1 : QVERIFY( closeCc1.isEmpty() );
12061 : 1 : closeC1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
12062 : 1 : closeCc1.addCurve( closeC1.clone() );
12063 : 1 : QCOMPARE( closeCc1.numPoints(), 3 );
12064 : 1 : QVERIFY( !closeCc1.isClosed() );
12065 : 1 : closeCc1.close();
12066 : 1 : QCOMPARE( closeCc1.numPoints(), 4 );
12067 : 1 : QVERIFY( closeCc1.isClosed() );
12068 : 1 : closeCc1.pointAt( 3, pt, v );
12069 : 1 : QCOMPARE( pt, QgsPoint( QgsWkbTypes::Point, 1, 2 ) );
12070 : 1 : closeCc1.close();
12071 : 1 : QCOMPARE( closeCc1.numPoints(), 4 );
12072 : 1 : QVERIFY( closeCc1.isClosed() );
12073 : :
12074 : : //segmentLength
12075 : 1 : QgsCircularString curveLine2;
12076 : 1 : QgsCompoundCurve slc1;
12077 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
12078 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 0 ) ), 0.0 );
12079 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 1, 0, 0 ) ), 0.0 );
12080 : 1 : curveLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 22 ) );
12081 : 1 : slc1.addCurve( curveLine2.clone() );
12082 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId() ), 0.0 );
12083 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
12084 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( 0, 0, 0 ) ), 31.4159, 0.001 );
12085 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 1 ) ), 0.0 );
12086 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 2 ) ), 0.0 );
12087 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
12088 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( -1, 0, 0 ) ), 31.4159, 0.001 );
12089 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 1, 0, 1 ) ), 0.0 );
12090 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( 1, 1, 0 ) ), 31.4159, 0.001 );
12091 : 1 : curveLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 22 ) << QgsPoint( -9, 32 ) << QgsPoint( 1, 42 ) );
12092 : 1 : slc1.addCurve( curveLine2.clone() );
12093 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId() ), 0.0 );
12094 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
12095 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( 0, 0, 0 ) ), 31.4159, 0.001 );
12096 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 1 ) ), 0.0 );
12097 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( 0, 0, 2 ) ), 31.4159, 0.001 );
12098 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 3 ) ), 0.0 );
12099 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 4 ) ), 0.0 );
12100 : 1 : QgsLineString curveLine3;
12101 : 1 : curveLine3.setPoints( QgsPointSequence() << QgsPoint( 1, 42 ) << QgsPoint( 10, 42 ) );
12102 : 1 : slc1.addCurve( curveLine3.clone() );
12103 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId() ), 0.0 );
12104 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
12105 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( 0, 0, 0 ) ), 31.4159, 0.001 );
12106 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 1 ) ), 0.0 );
12107 : 1 : QGSCOMPARENEAR( slc1.segmentLength( QgsVertexId( 0, 0, 2 ) ), 31.4159, 0.001 );
12108 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 3 ) ), 0.0 );
12109 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 4 ) ), 9.0 );
12110 : 1 : QCOMPARE( slc1.segmentLength( QgsVertexId( 0, 0, 5 ) ), 0.0 );
12111 : :
12112 : : //removeDuplicateNodes
12113 : 1 : QgsCompoundCurve nodeCurve;
12114 : 1 : QgsCircularString nodeLine;
12115 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes() );
12116 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
12117 : 1 : nodeCurve.addCurve( nodeLine.clone() );
12118 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes() );
12119 : 2 : QCOMPARE( nodeCurve.asWkt(), QStringLiteral( "CompoundCurve (CircularString (11 2, 11 12, 111 12))" ) );
12120 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 11, 2 ) );
12121 : 1 : nodeCurve.clear();
12122 : 1 : nodeCurve.addCurve( nodeLine.clone() );
12123 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes() );
12124 : 2 : QCOMPARE( nodeCurve.asWkt(), QStringLiteral( "CompoundCurve (CircularString (11 2, 11 12, 11 2))" ) );
12125 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 10, 3 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 9, 3 )
12126 : 1 : << QgsPoint( 11, 2 ) );
12127 : 1 : nodeCurve.clear();
12128 : 1 : nodeCurve.addCurve( nodeLine.clone() );
12129 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes( 0.02 ) );
12130 : 2 : QCOMPARE( nodeCurve.asWkt( 2 ), QStringLiteral( "CompoundCurve (CircularString (11 2, 10 3, 11.01 1.99, 9 3, 11 2))" ) );
12131 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
12132 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) << QgsPoint( 111.01, 11.99 ) );
12133 : 1 : nodeCurve.clear();
12134 : 1 : nodeCurve.addCurve( nodeLine.clone() );
12135 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes() );
12136 : 2 : QCOMPARE( nodeCurve.asWkt( 2 ), QStringLiteral( "CompoundCurve (CircularString (11 2, 11.01 1.99, 11.02 2.01, 11 12, 111 12, 111.01 11.99))" ) );
12137 : 1 : QVERIFY( nodeCurve.removeDuplicateNodes( 0.02 ) );
12138 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes( 0.02 ) );
12139 : 2 : QCOMPARE( nodeCurve.asWkt( 2 ), QStringLiteral( "CompoundCurve (CircularString (11 2, 11 12, 111 12, 111.01 11.99))" ) );
12140 : :
12141 : : // with tiny segment
12142 : 1 : QgsLineString linePart;
12143 : 1 : linePart.setPoints( QgsPointSequence() << QgsPoint( 111.01, 11.99 ) << QgsPoint( 111, 12 ) );
12144 : 1 : nodeCurve.addCurve( linePart.clone() );
12145 : 1 : QVERIFY( !nodeCurve.removeDuplicateNodes() );
12146 : 2 : QCOMPARE( nodeCurve.asWkt( 2 ), QStringLiteral( "CompoundCurve (CircularString (11 2, 11 12, 111 12, 111.01 11.99),(111.01 11.99, 111 12))" ) );
12147 : 1 : QVERIFY( nodeCurve.removeDuplicateNodes( 0.02 ) );
12148 : 2 : QCOMPARE( nodeCurve.asWkt( 2 ), QStringLiteral( "CompoundCurve (CircularString (11 2, 11 12, 111 12, 111.01 11.99))" ) );
12149 : :
12150 : : // with multiple duplicate nodes
12151 : 2 : nodeCurve.fromWkt( QStringLiteral( "CompoundCurve ((11 1, 11 2, 11 2),CircularString(11 2, 10 3, 10 2),(10 2, 10 2, 11 1))" ) );
12152 : 1 : QVERIFY( nodeCurve.removeDuplicateNodes( 0.02 ) );
12153 : 2 : QCOMPARE( nodeCurve.asWkt( 0 ), QStringLiteral( "CompoundCurve ((11 1, 11 2),CircularString (11 2, 10 3, 10 2),(10 2, 11 1))" ) );
12154 : :
12155 : : // ensure continuity
12156 : 1 : nodeCurve.clear();
12157 : 1 : linePart.setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 111.01, 11.99 ) << QgsPoint( 111, 12 ) );
12158 : 1 : nodeCurve.addCurve( linePart.clone() );
12159 : 1 : linePart.setPoints( QgsPointSequence() << QgsPoint( 111, 12 ) << QgsPoint( 31, 33 ) );
12160 : 1 : nodeCurve.addCurve( linePart.clone() );
12161 : 1 : QVERIFY( nodeCurve.removeDuplicateNodes( 0.02 ) );
12162 : 2 : QCOMPARE( nodeCurve.asWkt( 2 ), QStringLiteral( "CompoundCurve ((1 1, 111.01 11.99),(111.01 11.99, 31 33))" ) );
12163 : :
12164 : : // swap xy
12165 : 1 : QgsCompoundCurve swapCurve;
12166 : 1 : swapCurve.swapXy(); //no crash
12167 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
12168 : 1 : swapCurve.addCurve( nodeLine.clone() );
12169 : 1 : swapCurve.swapXy();
12170 : 2 : QCOMPARE( swapCurve.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (2 11 3 4, 12 11 13 14, 12 111 23 24))" ) );
12171 : 1 : QgsLineString lsSwap;
12172 : 1 : lsSwap.setPoints( QgsPointSequence() << QgsPoint( 12, 111, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 22, 122, 33, 34, QgsWkbTypes::PointZM ) );
12173 : 1 : swapCurve.addCurve( lsSwap.clone() );
12174 : 1 : swapCurve.swapXy();
12175 : 2 : QCOMPARE( swapCurve.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (11 2 3 4, 11 12 13 14, 111 12 23 24),(111 12 23 24, 122 22 33 34))" ) );
12176 : :
12177 : : // filter vertices
12178 : 11 : auto filter = []( const QgsPoint & point )-> bool
12179 : : {
12180 : 11 : return point.x() > 5;
12181 : : };
12182 : 1 : QgsCompoundCurve filterCurve;
12183 : 1 : filterCurve.filterVertices( filter ); //no crash
12184 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) );
12185 : 1 : filterCurve.addCurve( nodeLine.clone() );
12186 : 1 : filterCurve.filterVertices( filter );
12187 : 2 : QCOMPARE( filterCurve.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (11 2 3 4, 11 12 13 14, 111 12 23 24))" ) );
12188 : 1 : QgsLineString lsFilter;
12189 : 1 : lsFilter.setPoints( QgsPointSequence() << QgsPoint( 12, 111, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 22, 122, 33, 34, QgsWkbTypes::PointZM ) << QgsPoint( 1, 111, 23, 24, QgsWkbTypes::PointZM ) );
12190 : 1 : filterCurve.addCurve( lsFilter.clone() );
12191 : 1 : filterCurve.filterVertices( filter );
12192 : 2 : QCOMPARE( filterCurve.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (11 2 3 4, 11 12 13 14, 111 12 23 24),(12 111 23 24, 22 122 33 34))" ) );
12193 : :
12194 : : // transform vertices
12195 : 13 : auto transform = []( const QgsPoint & point )-> QgsPoint
12196 : : {
12197 : 13 : return QgsPoint( point.x() + 2, point.y() + 3, point.z() + 4, point.m() + 5 );
12198 : : };
12199 : 1 : QgsCompoundCurve transformCurve;
12200 : 1 : transformCurve.transformVertices( transform ); //no crash
12201 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) );
12202 : 1 : transformCurve.addCurve( nodeLine.clone() );
12203 : 1 : transformCurve.transformVertices( transform );
12204 : 2 : QCOMPARE( transformCurve.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (3 5 7 9, 13 5 7 9, 13 15 17 19, 113 15 27 29, 3 5 7 9))" ) );
12205 : 1 : QgsLineString lsTransform;
12206 : 1 : lsTransform.setPoints( QgsPointSequence() << QgsPoint( 12, 111, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 22, 122, 33, 34, QgsWkbTypes::PointZM ) << QgsPoint( 1, 111, 23, 24, QgsWkbTypes::PointZM ) );
12207 : 1 : transformCurve.addCurve( lsTransform.clone() );
12208 : 1 : transformCurve.transformVertices( transform );
12209 : 2 : QCOMPARE( transformCurve.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (5 8 11 14, 15 8 11 14, 15 18 21 24, 115 18 31 34, 5 8 11 14),(14 114 27 29, 24 125 37 39, 3 114 27 29))" ) );
12210 : :
12211 : : // transform using class
12212 : 1 : QgsCompoundCurve transformCurve2;
12213 : 1 : TestTransformer transformer;
12214 : : // no crash
12215 : 1 : QVERIFY( transformCurve2.transform( &transformer ) );
12216 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) );
12217 : 1 : transformCurve2.addCurve( nodeLine.clone() );
12218 : 1 : QVERIFY( transformCurve2.transform( &transformer ) );
12219 : 2 : QCOMPARE( transformCurve2.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (3 16 8 3, 33 16 8 3, 33 26 18 13, 333 26 28 23, 3 16 8 3))" ) );
12220 : 1 : transformCurve2.addCurve( lsTransform.clone() );
12221 : 1 : QVERIFY( transformCurve2.transform( &transformer ) );
12222 : 2 : QCOMPARE( transformCurve2.asWkt(), QStringLiteral( "CompoundCurveZM (CircularStringZM (9 30 13 2, 99 30 13 2, 99 40 23 12, 999 40 33 22, 9 30 13 2),(36 125 28 23, 66 136 38 33, 3 125 28 23))" ) );
12223 : :
12224 : 1 : TestFailTransformer failTransformer;
12225 : 1 : QVERIFY( !transformCurve2.transform( &failTransformer ) );
12226 : :
12227 : : // substring
12228 : 1 : QgsCompoundCurve substring;
12229 : 1 : std::unique_ptr< QgsCompoundCurve > substringResult( substring.curveSubstring( 1, 2 ) ); // no crash
12230 : 1 : QVERIFY( substringResult.get() );
12231 : 1 : QVERIFY( substringResult->isEmpty() );
12232 : 2 : substring.fromWkt( QStringLiteral( "CompoundCurveZM( ( 5 0 -1 -2, 10 0 1 2 ), CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14))" ) );
12233 : 1 : substringResult.reset( substring.curveSubstring( 0, 0 ) );
12234 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((5 0 -1 -2, 5 0 -1 -2))" ) );
12235 : 1 : substringResult.reset( substring.curveSubstring( -1, -0.1 ) );
12236 : 1 : QVERIFY( substringResult->isEmpty() );
12237 : 1 : substringResult.reset( substring.curveSubstring( 100000, 10000 ) );
12238 : 1 : QVERIFY( substringResult->isEmpty() );
12239 : 1 : substringResult.reset( substring.curveSubstring( -1, 1 ) );
12240 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((5 0 -1 -2, 6 0 -0.6 -1.2))" ) );
12241 : 1 : substringResult.reset( substring.curveSubstring( 1, -1 ) );
12242 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((6 0 -0.6 -1.2, 6 0 -0.6 -1.2))" ) );
12243 : 1 : substringResult.reset( substring.curveSubstring( -1, 10000 ) );
12244 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((5 0 -1 -2, 10 0 1 2),CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14))" ) );
12245 : 1 : substringResult.reset( substring.curveSubstring( 1, 10000 ) );
12246 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((6 0 -0.6 -1.2, 10 0 1 2),CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14))" ) );
12247 : 1 : substringResult.reset( substring.curveSubstring( 1, 7 ) );
12248 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((6 0 -0.6 -1.2, 10 0 1 2),CircularStringZM (10 0 1 2, 10.46 0.84 2.27 3.27, 11.42 0.91 5.73 6.73))" ) );
12249 : 1 : substringResult.reset( substring.curveSubstring( 1, 1.5 ) );
12250 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZM ((6 0 -0.6 -1.2, 6.5 0 -0.4 -0.8))" ) );
12251 : :
12252 : 2 : substring.fromWkt( QStringLiteral( "CompoundCurveZ( ( 5 0 -1, 10 0 1 ), CircularStringZ (10 0 1, 11 1 3, 12 0 13))" ) );
12253 : 1 : substringResult.reset( substring.curveSubstring( 1, 7 ) );
12254 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveZ ((6 0 -0.6, 10 0 1),CircularStringZ (10 0 1, 10.46 0.84 2.27, 11.42 0.91 5.73))" ) );
12255 : 2 : substring.fromWkt( QStringLiteral( "CompoundCurveM( ( 5 0 -1, 10 0 1 ), CircularStringM (10 0 1, 11 1 3, 12 0 13))" ) );
12256 : 1 : substringResult.reset( substring.curveSubstring( 1, 7 ) );
12257 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurveM ((6 0 -0.6, 10 0 1),CircularStringM (10 0 1, 10.46 0.84 2.27, 11.42 0.91 5.73))" ) );
12258 : 2 : substring.fromWkt( QStringLiteral( "CompoundCurve( ( 5 0, 10 0 ), CircularString (10 0, 11 1, 12 0))" ) );
12259 : 1 : substringResult.reset( substring.curveSubstring( 1, 7 ) );
12260 : 2 : QCOMPARE( substringResult->asWkt( 2 ), QStringLiteral( "CompoundCurve ((6 0, 10 0),CircularString (10 0, 10.46 0.84, 11.42 0.91))" ) );
12261 : :
12262 : : // substring
12263 : 1 : QgsCompoundCurve interpolate;
12264 : 1 : std::unique_ptr< QgsPoint > interpolateResult( interpolate.interpolatePoint( 1 ) ); // no crash
12265 : 1 : QVERIFY( !interpolateResult.get() );
12266 : 2 : interpolate.fromWkt( QStringLiteral( "CompoundCurveZM( ( 5 0 -1 -2, 10 0 1 2 ), CircularStringZM (10 0 1 2, 11 1 3 4, 12 0 13 14))" ) );
12267 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 0 ) );
12268 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (5 0 -1 -2)" ) );
12269 : 1 : interpolateResult.reset( interpolate.interpolatePoint( -1 ) );
12270 : 1 : QVERIFY( !interpolateResult.get() );
12271 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 100000 ) );
12272 : 1 : QVERIFY( !interpolateResult.get() );
12273 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
12274 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (6 0 -0.6 -1.2)" ) );
12275 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 7 ) );
12276 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (11.42 0.91 5.73 6.73)" ) );
12277 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1.5 ) );
12278 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (6.5 0 -0.4 -0.8)" ) );
12279 : 1 : interpolateResult.reset( interpolate.interpolatePoint( interpolate.length() ) );
12280 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZM (12 0 13 14)" ) );
12281 : :
12282 : 2 : interpolate.fromWkt( QStringLiteral( "CompoundCurveZ( ( 5 0 -1, 10 0 1 ), CircularStringZ (10 0 1, 11 1 3, 12 0 13))" ) );
12283 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
12284 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointZ (6 0 -0.6)" ) );
12285 : 2 : interpolate.fromWkt( QStringLiteral( "CompoundCurveM( ( 5 0 -1, 10 0 1 ), CircularStringM (10 0 1, 11 1 3, 12 0 13))" ) );
12286 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
12287 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "PointM (6 0 -0.6)" ) );
12288 : 2 : interpolate.fromWkt( QStringLiteral( "CompoundCurve( ( 5 0, 10 0 ), CircularString (10 0, 11 1, 12 0))" ) );
12289 : 1 : interpolateResult.reset( interpolate.interpolatePoint( 1 ) );
12290 : 2 : QCOMPARE( interpolateResult->asWkt( 2 ), QStringLiteral( "Point (6 0)" ) );
12291 : :
12292 : : // orientation
12293 : 1 : QgsCompoundCurve orientation;
12294 : 1 : ( void )orientation.orientation(); // no crash
12295 : 2 : orientation.fromWkt( QStringLiteral( "CompoundCurve( ( 0 0, 0 1), CircularString (0 1, 1 1, 1 0), (1 0, 0 0))" ) );
12296 : 1 : QCOMPARE( orientation.orientation(), QgsCurve::Clockwise );
12297 : 2 : orientation.fromWkt( QStringLiteral( "CompoundCurve( ( 0 0, 1 0), CircularString (1 0, 1 1, 0 1), (0 1, 0 0))" ) );
12298 : 1 : QCOMPARE( orientation.orientation(), QgsCurve::CounterClockwise );
12299 : 1 : }
12300 : :
12301 : 1 : void TestQgsGeometry::multiPoint()
12302 : : {
12303 : : //test constructor
12304 : 1 : QgsMultiPoint c1;
12305 : 1 : QVERIFY( c1.isEmpty() );
12306 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
12307 : 1 : QCOMPARE( c1.ringCount(), 0 );
12308 : 1 : QCOMPARE( c1.partCount(), 0 );
12309 : 1 : QVERIFY( !c1.is3D() );
12310 : 1 : QVERIFY( !c1.isMeasure() );
12311 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPoint );
12312 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiPoint" ) );
12313 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiPoint" ) );
12314 : 1 : QCOMPARE( c1.dimension(), 0 );
12315 : 1 : QVERIFY( !c1.hasCurvedSegments() );
12316 : 1 : QCOMPARE( c1.area(), 0.0 );
12317 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
12318 : 1 : QCOMPARE( c1.numGeometries(), 0 );
12319 : 1 : QVERIFY( !c1.geometryN( 0 ) );
12320 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12321 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 0 );
12322 : 1 : QCOMPARE( c1.vertexCount( 0, 1 ), 0 );
12323 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
12324 : :
12325 : : //addGeometry
12326 : :
12327 : : //try with nullptr
12328 : 1 : c1.addGeometry( nullptr );
12329 : 1 : QVERIFY( c1.isEmpty() );
12330 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
12331 : 1 : QCOMPARE( c1.ringCount(), 0 );
12332 : 1 : QCOMPARE( c1.partCount(), 0 );
12333 : 1 : QCOMPARE( c1.numGeometries(), 0 );
12334 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPoint );
12335 : 1 : QVERIFY( !c1.geometryN( 0 ) );
12336 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12337 : :
12338 : : // not a point
12339 : 1 : QVERIFY( !c1.addGeometry( new QgsLineString() ) );
12340 : 1 : QVERIFY( c1.isEmpty() );
12341 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
12342 : 1 : QCOMPARE( c1.ringCount(), 0 );
12343 : 1 : QCOMPARE( c1.partCount(), 0 );
12344 : 1 : QCOMPARE( c1.numGeometries(), 0 );
12345 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPoint );
12346 : 1 : QVERIFY( !c1.geometryN( 0 ) );
12347 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12348 : :
12349 : : //valid geometry
12350 : 1 : QgsPoint part( 1, 10 );
12351 : 1 : c1.addGeometry( part.clone() );
12352 : 1 : QVERIFY( !c1.isEmpty() );
12353 : 1 : QCOMPARE( c1.numGeometries(), 1 );
12354 : 1 : QCOMPARE( c1.nCoordinates(), 1 );
12355 : 1 : QCOMPARE( c1.ringCount(), 1 );
12356 : 1 : QCOMPARE( c1.partCount(), 1 );
12357 : 1 : QVERIFY( !c1.is3D() );
12358 : 1 : QVERIFY( !c1.isMeasure() );
12359 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPoint );
12360 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiPoint" ) );
12361 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiPoint" ) );
12362 : 1 : QCOMPARE( c1.dimension(), 0 );
12363 : 1 : QVERIFY( !c1.hasCurvedSegments() );
12364 : 1 : QCOMPARE( c1.area(), 0.0 );
12365 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
12366 : 1 : QVERIFY( c1.geometryN( 0 ) );
12367 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c1.geometryN( 0 ) ), part );
12368 : 1 : QVERIFY( !c1.geometryN( 100 ) );
12369 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12370 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 1 );
12371 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
12372 : :
12373 : : //initial adding of geometry should set z/m type
12374 : 1 : part = QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 );
12375 : 1 : QgsMultiPoint c2;
12376 : 1 : c2.addGeometry( part.clone() );
12377 : 1 : QVERIFY( c2.is3D() );
12378 : 1 : QVERIFY( !c2.isMeasure() );
12379 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::MultiPointZ );
12380 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "MultiPointZ" ) );
12381 : 1 : QCOMPARE( c2.geometryType(), QString( "MultiPoint" ) );
12382 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c2.geometryN( 0 ) ) ), part );
12383 : 1 : QgsMultiPoint c3;
12384 : 1 : part = QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 );
12385 : 1 : c3.addGeometry( part.clone() );
12386 : 1 : QVERIFY( !c3.is3D() );
12387 : 1 : QVERIFY( c3.isMeasure() );
12388 : 1 : QCOMPARE( c3.wkbType(), QgsWkbTypes::MultiPointM );
12389 : 1 : QCOMPARE( c3.wktTypeStr(), QString( "MultiPointM" ) );
12390 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c3.geometryN( 0 ) ) ), part );
12391 : 1 : QgsMultiPoint c4;
12392 : 1 : part = QgsPoint( QgsWkbTypes::PointZM, 10, 10, 5, 3 );
12393 : 1 : c4.addGeometry( part.clone() );
12394 : 1 : QVERIFY( c4.is3D() );
12395 : 1 : QVERIFY( c4.isMeasure() );
12396 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::MultiPointZM );
12397 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "MultiPointZM" ) );
12398 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c4.geometryN( 0 ) ) ), part );
12399 : :
12400 : : //add another part
12401 : 1 : QgsMultiPoint c6;
12402 : 1 : part = QgsPoint( 10, 11 );
12403 : 1 : c6.addGeometry( part.clone() );
12404 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 1 );
12405 : 1 : part = QgsPoint( 9, 1 );
12406 : 1 : c6.addGeometry( part.clone() );
12407 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 1 );
12408 : 1 : QCOMPARE( c6.numGeometries(), 2 );
12409 : 1 : QVERIFY( c6.geometryN( 0 ) );
12410 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c6.geometryN( 1 ) ), part );
12411 : :
12412 : 1 : QgsCoordinateSequence seq = c6.coordinateSequence();
12413 : 1 : QCOMPARE( seq, QgsCoordinateSequence() << ( QgsRingSequence() << ( QgsPointSequence() << QgsPoint( 10, 11 ) ) )
12414 : : << ( QgsRingSequence() << ( QgsPointSequence() << QgsPoint( 9, 1 ) ) ) );
12415 : 1 : QCOMPARE( c6.nCoordinates(), 2 );
12416 : :
12417 : : //adding subsequent points should not alter z/m type, regardless of points type
12418 : 1 : c6.clear();
12419 : 1 : c6.addGeometry( part.clone() );
12420 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPoint );
12421 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3 ) );
12422 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPoint );
12423 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 1 );
12424 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 1 );
12425 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 0 );
12426 : 1 : QCOMPARE( c6.vertexCount( -1, 0 ), 0 );
12427 : 1 : QCOMPARE( c6.nCoordinates(), 2 );
12428 : 1 : QCOMPARE( c6.ringCount(), 1 );
12429 : 1 : QCOMPARE( c6.partCount(), 2 );
12430 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPoint ); //should still be 2d
12431 : 1 : QVERIFY( !c6.is3D() );
12432 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 1 ) ) ), QgsPoint( 1, 2 ) );
12433 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointM, 11.0, 12.0, 0, 3 ) );
12434 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPoint );
12435 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 1 );
12436 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 1 );
12437 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 1 );
12438 : 1 : QCOMPARE( c6.nCoordinates(), 3 );
12439 : 1 : QCOMPARE( c6.ringCount(), 1 );
12440 : 1 : QCOMPARE( c6.partCount(), 3 );
12441 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPoint ); //should still be 2d
12442 : 1 : QVERIFY( !c6.is3D() );
12443 : 1 : QVERIFY( !c6.isMeasure() );
12444 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 2 ) ) ), QgsPoint( 11, 12 ) );
12445 : :
12446 : 1 : c6.clear();
12447 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 1.0, 2.0, 3 ) );
12448 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZ );
12449 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::Point, 11.0, 12.0 ) );
12450 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZ );
12451 : 1 : QVERIFY( c6.is3D() );
12452 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 0 ) ) ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
12453 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 1 ) ) ), QgsPoint( QgsWkbTypes::PointZ, 11, 12, 0 ) );
12454 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointM, 21.0, 22.0, 0, 3 ) );
12455 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZ );
12456 : 1 : QVERIFY( c6.is3D() );
12457 : 1 : QVERIFY( !c6.isMeasure() );
12458 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 2 ) ) ), QgsPoint( QgsWkbTypes::PointZ, 21, 22, 0 ) );
12459 : :
12460 : 1 : c6.clear();
12461 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointM, 1.0, 2.0, 0, 3 ) );
12462 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointM );
12463 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::Point, 11.0, 12.0 ) );
12464 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointM );
12465 : 1 : QVERIFY( c6.isMeasure() );
12466 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 0 ) ) ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) );
12467 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 1 ) ) ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
12468 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 21.0, 22.0, 3 ) );
12469 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointM );
12470 : 1 : QVERIFY( !c6.is3D() );
12471 : 1 : QVERIFY( c6.isMeasure() );
12472 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 2 ) ) ), QgsPoint( QgsWkbTypes::PointM, 21, 22, 0, 0 ) );
12473 : :
12474 : 1 : c6.clear();
12475 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 1.0, 2.0, 4, 3 ) );
12476 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZM );
12477 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::Point, 11.0, 12.0 ) );
12478 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZM );
12479 : 1 : QVERIFY( c6.isMeasure() );
12480 : 1 : QVERIFY( c6.is3D() );
12481 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 0 ) ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 4, 3 ) );
12482 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 1 ) ) ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 0, 0 ) );
12483 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 21.0, 22.0, 3 ) );
12484 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZM );
12485 : 1 : QVERIFY( c6.is3D() );
12486 : 1 : QVERIFY( c6.isMeasure() );
12487 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 2 ) ) ), QgsPoint( QgsWkbTypes::PointZM, 21, 22, 3, 0 ) );
12488 : 1 : c6.addGeometry( new QgsPoint( QgsWkbTypes::PointM, 31.0, 32.0, 0, 4 ) );
12489 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPointZM );
12490 : 1 : QVERIFY( c6.is3D() );
12491 : 1 : QVERIFY( c6.isMeasure() );
12492 : 1 : QCOMPARE( *( static_cast< const QgsPoint * >( c6.geometryN( 3 ) ) ), QgsPoint( QgsWkbTypes::PointZM, 31, 32, 0, 4 ) );
12493 : :
12494 : : //clear
12495 : 1 : QgsMultiPoint c7;
12496 : 1 : c7.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) );
12497 : 1 : c7.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 11, 12, 3 ) );
12498 : 1 : QCOMPARE( c7.numGeometries(), 2 );
12499 : 1 : c7.clear();
12500 : 1 : QVERIFY( c7.isEmpty() );
12501 : 1 : QCOMPARE( c7.numGeometries(), 0 );
12502 : 1 : QCOMPARE( c7.nCoordinates(), 0 );
12503 : 1 : QCOMPARE( c7.ringCount(), 0 );
12504 : 1 : QCOMPARE( c7.partCount(), 0 );
12505 : 1 : QVERIFY( !c7.is3D() );
12506 : 1 : QVERIFY( !c7.isMeasure() );
12507 : 1 : QCOMPARE( c7.wkbType(), QgsWkbTypes::MultiPoint );
12508 : :
12509 : : //clone
12510 : 1 : QgsMultiPoint c11;
12511 : 1 : std::unique_ptr< QgsMultiPoint >cloned( c11.clone() );
12512 : 1 : QVERIFY( cloned->isEmpty() );
12513 : 1 : c11.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 ) );
12514 : 1 : c11.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
12515 : 1 : cloned.reset( c11.clone() );
12516 : 1 : QCOMPARE( cloned->numGeometries(), 2 );
12517 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( cloned->geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 ) );
12518 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( cloned->geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
12519 : :
12520 : : //copy constructor
12521 : 1 : QgsMultiPoint c12;
12522 : 1 : QgsMultiPoint c13( c12 );
12523 : 1 : QVERIFY( c13.isEmpty() );
12524 : 1 : c12.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12525 : 1 : c12.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 20, 10, 14, 18 ) );
12526 : 1 : QgsMultiPoint c14( c12 );
12527 : 1 : QCOMPARE( c14.numGeometries(), 2 );
12528 : 1 : QCOMPARE( c14.wkbType(), QgsWkbTypes::MultiPointZM );
12529 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c14.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12530 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c14.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 20, 10, 14, 18 ) );
12531 : :
12532 : : //assignment operator
12533 : 1 : QgsMultiPoint c15;
12534 : 1 : c15 = c13;
12535 : 1 : QCOMPARE( c15.numGeometries(), 0 );
12536 : 1 : c15 = c14;
12537 : 1 : QCOMPARE( c15.numGeometries(), 2 );
12538 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c15.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12539 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c15.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 20, 10, 14, 18 ) );
12540 : :
12541 : : //toCurveType
12542 : 1 : std::unique_ptr< QgsMultiPoint > curveType( c12.toCurveType() );
12543 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::MultiPointZM );
12544 : 1 : QCOMPARE( curveType->numGeometries(), 2 );
12545 : 1 : const QgsPoint *curve = static_cast< const QgsPoint * >( curveType->geometryN( 0 ) );
12546 : 1 : QCOMPARE( *curve, QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12547 : 1 : curve = static_cast< const QgsPoint * >( curveType->geometryN( 1 ) );
12548 : 1 : QCOMPARE( *curve, QgsPoint( QgsWkbTypes::PointZM, 20, 10, 14, 18 ) );
12549 : :
12550 : : //to/fromWKB
12551 : 1 : QgsMultiPoint c16;
12552 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::Point, 10, 11 ) );
12553 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::Point, 20, 21 ) );
12554 : 1 : QByteArray wkb16 = c16.asWkb();
12555 : 1 : QgsMultiPoint c17;
12556 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
12557 : 1 : c17.fromWkb( wkb16ptr );
12558 : 1 : QCOMPARE( c17.numGeometries(), 2 );
12559 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::Point, 10, 11 ) );
12560 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::Point, 20, 21 ) );
12561 : :
12562 : : //parts with Z
12563 : 1 : c16.clear();
12564 : 1 : c17.clear();
12565 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) );
12566 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) );
12567 : 1 : wkb16 = c16.asWkb();
12568 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
12569 : 1 : c17.fromWkb( wkb16ptr2 );
12570 : 1 : QCOMPARE( c17.numGeometries(), 2 );
12571 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPointZ );
12572 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) );
12573 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) );
12574 : :
12575 : : //parts with m
12576 : 1 : c16.clear();
12577 : 1 : c17.clear();
12578 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) );
12579 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::PointM, 9, 1, 0, 4 ) );
12580 : 1 : wkb16 = c16.asWkb();
12581 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
12582 : 1 : c17.fromWkb( wkb16ptr3 );
12583 : 1 : QCOMPARE( c17.numGeometries(), 2 );
12584 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPointM );
12585 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) );
12586 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointM, 9, 1, 0, 4 ) );
12587 : :
12588 : : // parts with ZM
12589 : 1 : c16.clear();
12590 : 1 : c17.clear();
12591 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 0, 70, 4 ) );
12592 : 1 : c16.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 9, 1, 3, 4 ) );
12593 : 1 : wkb16 = c16.asWkb();
12594 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
12595 : 1 : c17.fromWkb( wkb16ptr4 );
12596 : 1 : QCOMPARE( c17.numGeometries(), 2 );
12597 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPointZM );
12598 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 0, 70, 4 ) );
12599 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c17.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 9, 1, 3, 4 ) );
12600 : :
12601 : : //bad WKB - check for no crash
12602 : 1 : c17.clear();
12603 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
12604 : 1 : QVERIFY( !c17.fromWkb( nullPtr ) );
12605 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPoint );
12606 : 1 : QgsPoint point( 1, 2 );
12607 : 1 : QByteArray wkbPoint = point.asWkb();
12608 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
12609 : 1 : QVERIFY( !c17.fromWkb( wkbPointPtr ) );
12610 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPoint );
12611 : :
12612 : : //to/from WKT
12613 : 1 : QgsMultiPoint c18;
12614 : 1 : c18.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12615 : 1 : c18.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) );
12616 : :
12617 : 1 : QString wkt = c18.asWkt();
12618 : 1 : QVERIFY( !wkt.isEmpty() );
12619 : 1 : QgsMultiPoint c19;
12620 : 1 : QVERIFY( c19.fromWkt( wkt ) );
12621 : 1 : QCOMPARE( c19.numGeometries(), 2 );
12622 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c19.geometryN( 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12623 : 1 : QCOMPARE( *static_cast< const QgsPoint * >( c19.geometryN( 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) );
12624 : :
12625 : : //bad WKT
12626 : 1 : QgsMultiPoint c20;
12627 : 1 : QVERIFY( !c20.fromWkt( "Point()" ) );
12628 : 1 : QVERIFY( c20.isEmpty() );
12629 : 1 : QCOMPARE( c20.numGeometries(), 0 );
12630 : 1 : QCOMPARE( c20.wkbType(), QgsWkbTypes::MultiPoint );
12631 : :
12632 : : //as JSON
12633 : 1 : QgsMultiPoint exportC;
12634 : 1 : exportC.addGeometry( new QgsPoint( QgsWkbTypes::Point, 0, 10 ) );
12635 : 1 : exportC.addGeometry( new QgsPoint( QgsWkbTypes::Point, 10, 0 ) );
12636 : :
12637 : : // GML document for compare
12638 : 1 : QDomDocument doc( "gml" );
12639 : :
12640 : : // as GML2
12641 : 2 : QString expectedSimpleGML2( QStringLiteral( "<MultiPoint xmlns=\"gml\"><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,10</coordinates></Point></pointMember><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">10,0</coordinates></Point></pointMember></MultiPoint>" ) );
12642 : 1 : QString res = elemToString( exportC.asGml2( doc ) );
12643 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
12644 : 2 : QString expectedGML2empty( QStringLiteral( "<MultiPoint xmlns=\"gml\"/>" ) );
12645 : 3 : QGSCOMPAREGML( elemToString( QgsMultiPoint().asGml2( doc ) ), expectedGML2empty );
12646 : :
12647 : : //as GML3
12648 : 2 : QString expectedSimpleGML3( QStringLiteral( "<MultiPoint xmlns=\"gml\"><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">0 10</pos></Point></pointMember><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">10 0</pos></Point></pointMember></MultiPoint>" ) );
12649 : 1 : res = elemToString( exportC.asGml3( doc ) );
12650 : 1 : QCOMPARE( res, expectedSimpleGML3 );
12651 : 2 : QString expectedGML3empty( QStringLiteral( "<MultiPoint xmlns=\"gml\"/>" ) );
12652 : 3 : QGSCOMPAREGML( elemToString( QgsMultiPoint().asGml3( doc ) ), expectedGML3empty );
12653 : :
12654 : : // as JSON
12655 : 1 : QString expectedSimpleJson( "{\"coordinates\":[[0.0,10.0],[10.0,0.0]],\"type\":\"MultiPoint\"}" );
12656 : 1 : res = exportC.asJson();
12657 : 1 : QCOMPARE( res, expectedSimpleJson );
12658 : :
12659 : 1 : QgsMultiPoint exportFloat;
12660 : 1 : exportFloat.addGeometry( new QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 100 / 9.0 ) );
12661 : 1 : exportFloat.addGeometry( new QgsPoint( QgsWkbTypes::Point, 4 / 3.0, 2 / 3.0 ) );
12662 : :
12663 : :
12664 : 1 : QString expectedJsonPrec3( "{\"coordinates\":[[1.111,11.111],[1.333,0.667]],\"type\":\"MultiPoint\"}" );
12665 : 1 : res = exportFloat.asJson( 3 );
12666 : 1 : QCOMPARE( res, expectedJsonPrec3 );
12667 : :
12668 : : // as GML2
12669 : 2 : QString expectedGML2prec3( QStringLiteral( "<MultiPoint xmlns=\"gml\"><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1.111,11.111</coordinates></Point></pointMember><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1.333,0.667</coordinates></Point></pointMember></MultiPoint>" ) );
12670 : 1 : res = elemToString( exportFloat.asGml2( doc, 3 ) );
12671 : 3 : QGSCOMPAREGML( res, expectedGML2prec3 );
12672 : :
12673 : : //as GML3
12674 : 2 : QString expectedGML3prec3( QStringLiteral( "<MultiPoint xmlns=\"gml\"><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">1.111 11.111</pos></Point></pointMember><pointMember xmlns=\"gml\"><Point xmlns=\"gml\"><pos xmlns=\"gml\" srsDimension=\"2\">1.333 0.667</pos></Point></pointMember></MultiPoint>" ) );
12675 : 1 : res = elemToString( exportFloat.asGml3( doc, 3 ) );
12676 : 1 : QCOMPARE( res, expectedGML3prec3 );
12677 : :
12678 : : //asKML
12679 : 2 : QString expectedKml( QStringLiteral( "<MultiGeometry><Point><coordinates>0,10</coordinates></Point><Point><coordinates>10,0</coordinates></Point></MultiGeometry>" ) );
12680 : 1 : QCOMPARE( exportC.asKml(), expectedKml );
12681 : 2 : QString expectedKmlPrec3( QStringLiteral( "<MultiGeometry><Point><coordinates>1.111,11.111</coordinates></Point><Point><coordinates>1.333,0.667</coordinates></Point></MultiGeometry>" ) );
12682 : 1 : QCOMPARE( exportFloat.asKml( 3 ), expectedKmlPrec3 );
12683 : :
12684 : :
12685 : : // insert geometry
12686 : 1 : QgsMultiPoint rc;
12687 : 1 : rc.clear();
12688 : 1 : rc.insertGeometry( nullptr, 0 );
12689 : 1 : QVERIFY( rc.isEmpty() );
12690 : 1 : QCOMPARE( rc.numGeometries(), 0 );
12691 : 1 : rc.insertGeometry( nullptr, -1 );
12692 : 1 : QVERIFY( rc.isEmpty() );
12693 : 1 : QCOMPARE( rc.numGeometries(), 0 );
12694 : 1 : rc.insertGeometry( nullptr, 100 );
12695 : 1 : QVERIFY( rc.isEmpty() );
12696 : 1 : QCOMPARE( rc.numGeometries(), 0 );
12697 : :
12698 : 1 : rc.insertGeometry( new QgsLineString(), 0 );
12699 : 1 : QVERIFY( rc.isEmpty() );
12700 : 1 : QCOMPARE( rc.numGeometries(), 0 );
12701 : :
12702 : : // cast
12703 : 1 : QVERIFY( !QgsMultiPoint().cast( nullptr ) );
12704 : 1 : QgsMultiPoint pCast;
12705 : 1 : QVERIFY( QgsMultiPoint().cast( &pCast ) );
12706 : 1 : QgsMultiPoint pCast2;
12707 : 2 : pCast2.fromWkt( QStringLiteral( "MultiPointZ(PointZ(0 1 1))" ) );
12708 : 1 : QVERIFY( QgsMultiPoint().cast( &pCast2 ) );
12709 : 2 : pCast2.fromWkt( QStringLiteral( "MultiPointM(PointM(0 1 1))" ) );
12710 : 1 : QVERIFY( QgsMultiPoint().cast( &pCast2 ) );
12711 : 2 : pCast2.fromWkt( QStringLiteral( "MultiPointZM(PointZM(0 1 1 2))" ) );
12712 : 1 : QVERIFY( QgsMultiPoint().cast( &pCast2 ) );
12713 : :
12714 : : // bounding box
12715 : 1 : QgsMultiPoint boundingBox;
12716 : 1 : boundingBox.addGeometry( new QgsPoint( 0, 0 ) );
12717 : 1 : QCOMPARE( boundingBox.boundingBox(), QgsRectangle( 0, 0, 0, 0 ) );
12718 : 1 : boundingBox.addGeometry( new QgsPoint( 1, 2 ) );
12719 : 1 : QCOMPARE( boundingBox.boundingBox(), QgsRectangle( 0, 0, 1, 2 ) );
12720 : 1 : QgsMultiPoint boundingBox2;
12721 : 1 : QCOMPARE( boundingBox2.boundingBox(), QgsRectangle( 0, 0, 0, 0 ) );
12722 : 1 : boundingBox2.addGeometry( new QgsPoint( 1, 2 ) );
12723 : 1 : QCOMPARE( boundingBox2.boundingBox(), QgsRectangle( 1, 2, 1, 2 ) );
12724 : 1 : boundingBox2.addGeometry( new QgsPoint( 10, 3 ) );
12725 : 1 : QCOMPARE( boundingBox2.boundingBox(), QgsRectangle( 1, 2, 10, 3 ) );
12726 : 1 : boundingBox2.addGeometry( new QgsPoint( 0, 0 ) );
12727 : 1 : QCOMPARE( boundingBox2.boundingBox(), QgsRectangle( 0, 0, 10, 3 ) );
12728 : :
12729 : : //boundary
12730 : :
12731 : : //multipoints have no boundary defined
12732 : 1 : QgsMultiPoint boundaryMP;
12733 : 1 : QVERIFY( !boundaryMP.boundary() );
12734 : : // add some points and retest, should still be undefined
12735 : 1 : boundaryMP.addGeometry( new QgsPoint( 0, 0 ) );
12736 : 1 : boundaryMP.addGeometry( new QgsPoint( 1, 1 ) );
12737 : 1 : QVERIFY( !boundaryMP.boundary() );
12738 : :
12739 : : // closestSegment
12740 : 1 : QgsPoint closest;
12741 : 1 : QgsVertexId after;
12742 : : // return error - points have no segments
12743 : 1 : QVERIFY( boundaryMP.closestSegment( QgsPoint( 0.5, 0.5 ), closest, after ) < 0 );
12744 : :
12745 : : // vertex iterator
12746 : 1 : QgsAbstractGeometry::vertex_iterator it = boundaryMP.vertices_begin();
12747 : 1 : QgsAbstractGeometry::vertex_iterator itEnd = boundaryMP.vertices_end();
12748 : 1 : QCOMPARE( *it, QgsPoint( 0, 0 ) );
12749 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 0 ) );
12750 : 1 : ++it;
12751 : 1 : QCOMPARE( *it, QgsPoint( 1, 1 ) );
12752 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 0 ) );
12753 : 1 : ++it;
12754 : 1 : QCOMPARE( it, itEnd );
12755 : :
12756 : : // Java-style iterator
12757 : 1 : QgsVertexIterator it2( &boundaryMP );
12758 : 1 : QVERIFY( it2.hasNext() );
12759 : 1 : QCOMPARE( it2.next(), QgsPoint( 0, 0 ) );
12760 : 1 : QVERIFY( it2.hasNext() );
12761 : 1 : QCOMPARE( it2.next(), QgsPoint( 1, 1 ) );
12762 : 1 : QVERIFY( !it2.hasNext() );
12763 : :
12764 : : //adjacent vertices - both should be invalid
12765 : 1 : QgsMultiPoint c21;
12766 : 1 : c21.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12767 : 1 : c21.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) );
12768 : 1 : QgsVertexId prev( 1, 2, 3 ); // start with something
12769 : 1 : QgsVertexId next( 4, 5, 6 );
12770 : 1 : c21.adjacentVertices( QgsVertexId( 0, 0, 0 ), prev, next );
12771 : 1 : QCOMPARE( prev, QgsVertexId() );
12772 : 1 : QCOMPARE( next, QgsVertexId() );
12773 : 1 : c21.adjacentVertices( QgsVertexId( 1, 0, 0 ), prev, next );
12774 : 1 : QCOMPARE( prev, QgsVertexId() );
12775 : 1 : QCOMPARE( next, QgsVertexId() );
12776 : :
12777 : : // vertex number
12778 : 1 : QgsMultiPoint c22;
12779 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
12780 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), -1 );
12781 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
12782 : 1 : c22.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12783 : 1 : c22.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) );
12784 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
12785 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 2, 0, 0 ) ), -1 );
12786 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
12787 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), -1 );
12788 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), -1 );
12789 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), 1 );
12790 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( 1, 0, 1 ) ), -1 );
12791 : 1 : QCOMPARE( c22.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
12792 : :
12793 : 1 : QgsMultiPoint mp;
12794 : : // multipoints should not be affected by removeDuplicatePoints
12795 : 1 : QVERIFY( !mp.removeDuplicateNodes() );
12796 : 1 : mp.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 1, 4, 8 ) );
12797 : 1 : mp.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 1, 4, 8 ) );
12798 : 1 : QVERIFY( !mp.removeDuplicateNodes() );
12799 : 1 : QCOMPARE( mp.numGeometries(), 2 );
12800 : :
12801 : : // filter vertex
12802 : 1 : QgsMultiPoint filterPoint;
12803 : 4 : auto filter = []( const QgsPoint & point )-> bool
12804 : : {
12805 : 4 : return point.x() < 5;
12806 : : };
12807 : 1 : filterPoint.filterVertices( filter ); // no crash
12808 : 1 : filterPoint.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
12809 : 1 : filterPoint.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 3, 0, 4, 8 ) );
12810 : 1 : filterPoint.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 1, 0, 4, 8 ) );
12811 : 1 : filterPoint.addGeometry( new QgsPoint( QgsWkbTypes::PointZM, 11, 0, 4, 8 ) );
12812 : 1 : filterPoint.filterVertices( filter );
12813 : 2 : QCOMPARE( filterPoint.asWkt( 2 ), QStringLiteral( "MultiPointZM ((3 0 4 8),(1 0 4 8))" ) );
12814 : 1 : }
12815 : :
12816 : 1 : void TestQgsGeometry::multiLineString()
12817 : : {
12818 : : //test constructor
12819 : 1 : QgsMultiLineString c1;
12820 : 1 : QVERIFY( c1.isEmpty() );
12821 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
12822 : 1 : QCOMPARE( c1.ringCount(), 0 );
12823 : 1 : QCOMPARE( c1.partCount(), 0 );
12824 : 1 : QVERIFY( !c1.is3D() );
12825 : 1 : QVERIFY( !c1.isMeasure() );
12826 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiLineString );
12827 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiLineString" ) );
12828 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiLineString" ) );
12829 : 1 : QCOMPARE( c1.dimension(), 0 );
12830 : 1 : QVERIFY( !c1.hasCurvedSegments() );
12831 : 1 : QCOMPARE( c1.area(), 0.0 );
12832 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
12833 : 1 : QCOMPARE( c1.numGeometries(), 0 );
12834 : 1 : QVERIFY( !c1.geometryN( 0 ) );
12835 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12836 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 0 );
12837 : 1 : QCOMPARE( c1.vertexCount( 0, 1 ), 0 );
12838 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
12839 : :
12840 : : //addGeometry
12841 : :
12842 : : //try with nullptr
12843 : 1 : c1.addGeometry( nullptr );
12844 : 1 : QVERIFY( c1.isEmpty() );
12845 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
12846 : 1 : QCOMPARE( c1.ringCount(), 0 );
12847 : 1 : QCOMPARE( c1.partCount(), 0 );
12848 : 1 : QCOMPARE( c1.numGeometries(), 0 );
12849 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiLineString );
12850 : 1 : QVERIFY( !c1.geometryN( 0 ) );
12851 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12852 : :
12853 : : // not a linestring
12854 : 1 : QVERIFY( !c1.addGeometry( new QgsPoint() ) );
12855 : 1 : QVERIFY( c1.isEmpty() );
12856 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
12857 : 1 : QCOMPARE( c1.ringCount(), 0 );
12858 : 1 : QCOMPARE( c1.partCount(), 0 );
12859 : 1 : QCOMPARE( c1.numGeometries(), 0 );
12860 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiLineString );
12861 : 1 : QVERIFY( !c1.geometryN( 0 ) );
12862 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12863 : :
12864 : : //valid geometry
12865 : 1 : QgsLineString part;
12866 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) );
12867 : 1 : c1.addGeometry( part.clone() );
12868 : 1 : QVERIFY( !c1.isEmpty() );
12869 : 1 : QCOMPARE( c1.numGeometries(), 1 );
12870 : 1 : QCOMPARE( c1.nCoordinates(), 2 );
12871 : 1 : QCOMPARE( c1.ringCount(), 1 );
12872 : 1 : QCOMPARE( c1.partCount(), 1 );
12873 : 1 : QVERIFY( !c1.is3D() );
12874 : 1 : QVERIFY( !c1.isMeasure() );
12875 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiLineString );
12876 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiLineString" ) );
12877 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiLineString" ) );
12878 : 1 : QCOMPARE( c1.dimension(), 1 );
12879 : 1 : QVERIFY( !c1.hasCurvedSegments() );
12880 : 1 : QCOMPARE( c1.area(), 0.0 );
12881 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
12882 : 1 : QVERIFY( c1.geometryN( 0 ) );
12883 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c1.geometryN( 0 ) ), part );
12884 : 1 : QVERIFY( !c1.geometryN( 100 ) );
12885 : 1 : QVERIFY( !c1.geometryN( -1 ) );
12886 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 2 );
12887 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
12888 : :
12889 : : //initial adding of geometry should set z/m type
12890 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 20, 21, 2 ) );
12891 : 1 : QgsMultiLineString c2;
12892 : 1 : c2.addGeometry( part.clone() );
12893 : 1 : QVERIFY( c2.is3D() );
12894 : 1 : QVERIFY( !c2.isMeasure() );
12895 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::MultiLineStringZ );
12896 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "MultiLineStringZ" ) );
12897 : 1 : QCOMPARE( c2.geometryType(), QString( "MultiLineString" ) );
12898 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c2.geometryN( 0 ) ) ), part );
12899 : 1 : QgsMultiLineString c3;
12900 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 10, 11, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 20, 21, 0, 2 ) );
12901 : 1 : c3.addGeometry( part.clone() );
12902 : 1 : QVERIFY( !c3.is3D() );
12903 : 1 : QVERIFY( c3.isMeasure() );
12904 : 1 : QCOMPARE( c3.wkbType(), QgsWkbTypes::MultiLineStringM );
12905 : 1 : QCOMPARE( c3.wktTypeStr(), QString( "MultiLineStringM" ) );
12906 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c3.geometryN( 0 ) ) ), part );
12907 : 1 : QgsMultiLineString c4;
12908 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 10, 11, 2, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 20, 21, 3, 2 ) );
12909 : 1 : c4.addGeometry( part.clone() );
12910 : 1 : QVERIFY( c4.is3D() );
12911 : 1 : QVERIFY( c4.isMeasure() );
12912 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::MultiLineStringZM );
12913 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "MultiLineStringZM" ) );
12914 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c4.geometryN( 0 ) ) ), part );
12915 : :
12916 : : //add another part
12917 : 1 : QgsMultiLineString c6;
12918 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) );
12919 : 1 : c6.addGeometry( part.clone() );
12920 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 2 );
12921 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 9, 12 ) << QgsPoint( 3, 13 ) );
12922 : 1 : c6.addGeometry( part.clone() );
12923 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 2 );
12924 : 1 : QCOMPARE( c6.numGeometries(), 2 );
12925 : 1 : QVERIFY( c6.geometryN( 0 ) );
12926 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c6.geometryN( 1 ) ), part );
12927 : :
12928 : : //adding subsequent points should not alter z/m type, regardless of points type
12929 : 1 : c6.clear();
12930 : 1 : c6.addGeometry( part.clone() );
12931 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineString );
12932 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) ) ;
12933 : 1 : c6.addGeometry( part.clone() );
12934 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineString );
12935 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 2 );
12936 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 2 );
12937 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 0 );
12938 : 1 : QCOMPARE( c6.vertexCount( -1, 0 ), 0 );
12939 : 1 : QCOMPARE( c6.nCoordinates(), 4 );
12940 : 1 : QCOMPARE( c6.ringCount(), 1 );
12941 : 1 : QCOMPARE( c6.partCount(), 2 );
12942 : 1 : QVERIFY( !c6.is3D() );
12943 : 1 : const QgsLineString *ls = static_cast< const QgsLineString * >( c6.geometryN( 0 ) );
12944 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 9, 12 ) );
12945 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 3, 13 ) );
12946 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 1 ) );
12947 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 1, 10 ) );
12948 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 2, 11 ) );
12949 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 21, 30, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 32, 41, 0, 3 ) ) ;
12950 : 1 : c6.addGeometry( part.clone() );
12951 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineString );
12952 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 2 );
12953 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 2 );
12954 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 2 );
12955 : 1 : QCOMPARE( c6.nCoordinates(), 6 );
12956 : 1 : QCOMPARE( c6.ringCount(), 1 );
12957 : 1 : QCOMPARE( c6.partCount(), 3 );
12958 : 1 : QVERIFY( !c6.is3D() );
12959 : 1 : QVERIFY( !c6.isMeasure() );
12960 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 2 ) );
12961 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 21, 30 ) );
12962 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 32, 41 ) );
12963 : :
12964 : 1 : c6.clear();
12965 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) ) ;
12966 : 1 : c6.addGeometry( part.clone() );
12967 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZ );
12968 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) ) ;
12969 : 1 : c6.addGeometry( part.clone() );
12970 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZ );
12971 : 1 : QVERIFY( c6.is3D() );
12972 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 0 ) );
12973 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 1, 10, 2 ) );
12974 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 2, 11, 3 ) );
12975 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 1 ) );
12976 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 2, 20, 0 ) );
12977 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 3, 31, 0 ) );
12978 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 ) ) ;
12979 : 1 : c6.addGeometry( part.clone() );
12980 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZ );
12981 : 1 : QVERIFY( c6.is3D() );
12982 : 1 : QVERIFY( !c6.isMeasure() );
12983 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 2 ) );
12984 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 5, 50, 0 ) );
12985 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 6, 61, 0 ) );
12986 : :
12987 : 1 : c6.clear();
12988 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineString );
12989 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 ) ) ;
12990 : 1 : c6.addGeometry( part.clone() );
12991 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringM );
12992 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) ) ;
12993 : 1 : c6.addGeometry( part.clone() );
12994 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringM );
12995 : 1 : QVERIFY( c6.isMeasure() );
12996 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 0 ) );
12997 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) );
12998 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 ) );
12999 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 1 ) );
13000 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 2, 20, 0, 0 ) );
13001 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 3, 31, 0, 0 ) );
13002 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 11, 12, 13 ) << QgsPoint( 14, 15, 16 ) ) ;
13003 : 1 : c6.addGeometry( part.clone() );
13004 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringM );
13005 : 1 : QVERIFY( !c6.is3D() );
13006 : 1 : QVERIFY( c6.isMeasure() );
13007 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 2 ) );
13008 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
13009 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 14, 15, 0, 0 ) );
13010 : :
13011 : 1 : c6.clear();
13012 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 ) ) ;
13013 : 1 : c6.addGeometry( part.clone() );
13014 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZM );
13015 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) ) ;
13016 : 1 : c6.addGeometry( part.clone() );
13017 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZM );
13018 : 1 : QVERIFY( c6.isMeasure() );
13019 : 1 : QVERIFY( c6.is3D() );
13020 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 0 ) );
13021 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) );
13022 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 ) );
13023 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 1 ) );
13024 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 0, 0 ) );
13025 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 3, 13, 0, 0 ) );
13026 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 77, 87, 7 ) << QgsPoint( QgsWkbTypes::PointZ, 83, 83, 8 ) ) ;
13027 : 1 : c6.addGeometry( part.clone() );
13028 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZM );
13029 : 1 : QVERIFY( c6.is3D() );
13030 : 1 : QVERIFY( c6.isMeasure() );
13031 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 2 ) );
13032 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 77, 87, 7, 0 ) );
13033 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 83, 83, 8, 0 ) );
13034 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 177, 187, 0, 9 ) << QgsPoint( QgsWkbTypes::PointM, 183, 183, 0, 11 ) ) ;
13035 : 1 : c6.addGeometry( part.clone() );
13036 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiLineStringZM );
13037 : 1 : QVERIFY( c6.is3D() );
13038 : 1 : QVERIFY( c6.isMeasure() );
13039 : 1 : ls = static_cast< const QgsLineString * >( c6.geometryN( 3 ) );
13040 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 177, 187, 0, 9 ) );
13041 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 183, 183, 0, 11 ) );
13042 : :
13043 : : //clear
13044 : 1 : QgsMultiLineString c7;
13045 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 ) ) ;
13046 : 1 : c7.addGeometry( part.clone() );
13047 : 1 : c7.addGeometry( part.clone() );
13048 : 1 : QCOMPARE( c7.numGeometries(), 2 );
13049 : 1 : c7.clear();
13050 : 1 : QVERIFY( c7.isEmpty() );
13051 : 1 : QCOMPARE( c7.numGeometries(), 0 );
13052 : 1 : QCOMPARE( c7.nCoordinates(), 0 );
13053 : 1 : QCOMPARE( c7.ringCount(), 0 );
13054 : 1 : QCOMPARE( c7.partCount(), 0 );
13055 : 1 : QVERIFY( !c7.is3D() );
13056 : 1 : QVERIFY( !c7.isMeasure() );
13057 : 1 : QCOMPARE( c7.wkbType(), QgsWkbTypes::MultiLineString );
13058 : :
13059 : : //clone
13060 : 1 : QgsMultiLineString c11;
13061 : 1 : std::unique_ptr< QgsMultiLineString >cloned( c11.clone() );
13062 : 1 : QVERIFY( cloned->isEmpty() );
13063 : 1 : c11.addGeometry( part.clone() );
13064 : 1 : c11.addGeometry( part.clone() );
13065 : 1 : cloned.reset( c11.clone() );
13066 : 1 : QCOMPARE( cloned->numGeometries(), 2 );
13067 : 1 : ls = static_cast< const QgsLineString * >( cloned->geometryN( 0 ) );
13068 : 1 : QCOMPARE( *ls, part );
13069 : 1 : ls = static_cast< const QgsLineString * >( cloned->geometryN( 1 ) );
13070 : 1 : QCOMPARE( *ls, part );
13071 : :
13072 : : //copy constructor
13073 : 1 : QgsMultiLineString c12;
13074 : 1 : QgsMultiLineString c13( c12 );
13075 : 1 : QVERIFY( c13.isEmpty() );
13076 : 1 : c12.addGeometry( part.clone() );
13077 : 1 : c12.addGeometry( part.clone() );
13078 : 1 : QgsMultiLineString c14( c12 );
13079 : 1 : QCOMPARE( c14.numGeometries(), 2 );
13080 : 1 : QCOMPARE( c14.wkbType(), QgsWkbTypes::MultiLineStringZM );
13081 : 1 : ls = static_cast< const QgsLineString * >( c14.geometryN( 0 ) );
13082 : 1 : QCOMPARE( *ls, part );
13083 : 1 : ls = static_cast< const QgsLineString * >( c14.geometryN( 1 ) );
13084 : 1 : QCOMPARE( *ls, part );
13085 : :
13086 : : //assignment operator
13087 : 1 : QgsMultiLineString c15;
13088 : 1 : c15 = c13;
13089 : 1 : QCOMPARE( c15.numGeometries(), 0 );
13090 : 1 : c15 = c14;
13091 : 1 : QCOMPARE( c15.numGeometries(), 2 );
13092 : 1 : ls = static_cast< const QgsLineString * >( c15.geometryN( 0 ) );
13093 : 1 : QCOMPARE( *ls, part );
13094 : 1 : ls = static_cast< const QgsLineString * >( c15.geometryN( 1 ) );
13095 : 1 : QCOMPARE( *ls, part );
13096 : :
13097 : : //toCurveType
13098 : 1 : std::unique_ptr< QgsMultiCurve > curveType( c12.toCurveType() );
13099 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::MultiCurveZM );
13100 : 1 : QCOMPARE( curveType->numGeometries(), 2 );
13101 : 1 : const QgsCompoundCurve *curve = static_cast< const QgsCompoundCurve * >( curveType->geometryN( 0 ) );
13102 : 2 : QCOMPARE( curve->asWkt(), QStringLiteral( "CompoundCurveZM ((5 50 1 4, 6 61 3 5))" ) );
13103 : 1 : curve = static_cast< const QgsCompoundCurve * >( curveType->geometryN( 1 ) );
13104 : 2 : QCOMPARE( curve->asWkt(), QStringLiteral( "CompoundCurveZM ((5 50 1 4, 6 61 3 5))" ) );
13105 : :
13106 : : //to/fromWKB
13107 : 1 : QgsMultiLineString c16;
13108 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) ) ;
13109 : 1 : c16.addGeometry( part.clone() );
13110 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) ) ;
13111 : 1 : c16.addGeometry( part.clone() );
13112 : 1 : QByteArray wkb16 = c16.asWkb();
13113 : 1 : QgsMultiLineString c17;
13114 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
13115 : 1 : c17.fromWkb( wkb16ptr );
13116 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13117 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 0 ) ) );
13118 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 1 ) ) );
13119 : :
13120 : : //parts with Z
13121 : 1 : c16.clear();
13122 : 1 : c17.clear();
13123 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 7, 17, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 3, 13, 4 ) ) ;
13124 : 1 : c16.addGeometry( part.clone() );
13125 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 27, 37, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 43, 43, 5 ) ) ;
13126 : 1 : c16.addGeometry( part.clone() );
13127 : 1 : wkb16 = c16.asWkb();
13128 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
13129 : 1 : c17.fromWkb( wkb16ptr2 );
13130 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13131 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiLineStringZ );
13132 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 0 ) ) );
13133 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 1 ) ) );
13134 : :
13135 : : //parts with m
13136 : 1 : c16.clear();
13137 : 1 : c17.clear();
13138 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 7, 17, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 3, 13, 0, 4 ) ) ;
13139 : 1 : c16.addGeometry( part.clone() );
13140 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 27, 37, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 43, 43, 0, 5 ) ) ;
13141 : 1 : c16.addGeometry( part.clone() );
13142 : 1 : wkb16 = c16.asWkb();
13143 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
13144 : 1 : c17.fromWkb( wkb16ptr3 );
13145 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13146 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiLineStringM );
13147 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 0 ) ) );
13148 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 1 ) ) );
13149 : :
13150 : : // parts with ZM
13151 : 1 : c16.clear();
13152 : 1 : c17.clear();
13153 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) ) ;
13154 : 1 : c16.addGeometry( part.clone() );
13155 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) ) ;
13156 : 1 : c16.addGeometry( part.clone() );
13157 : 1 : wkb16 = c16.asWkb();
13158 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
13159 : 1 : c17.fromWkb( wkb16ptr4 );
13160 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13161 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiLineStringZM );
13162 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 0 ) ) );
13163 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), *static_cast< const QgsLineString * >( c16.geometryN( 1 ) ) );
13164 : :
13165 : : //bad WKB - check for no crash
13166 : 1 : c17.clear();
13167 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
13168 : 1 : QVERIFY( !c17.fromWkb( nullPtr ) );
13169 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiLineString );
13170 : 1 : QgsPoint point( 1, 2 );
13171 : 1 : QByteArray wkbPoint = point.asWkb();
13172 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
13173 : 1 : QVERIFY( !c17.fromWkb( wkbPointPtr ) );
13174 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiLineString );
13175 : :
13176 : : //to/from WKT
13177 : 1 : QgsMultiLineString c18;
13178 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) ) ;
13179 : 1 : c18.addGeometry( part.clone() );
13180 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) ) ;
13181 : 1 : c18.addGeometry( part.clone() );
13182 : :
13183 : 1 : QString wkt = c18.asWkt();
13184 : 1 : QVERIFY( !wkt.isEmpty() );
13185 : 1 : QgsMultiLineString c19;
13186 : 1 : QVERIFY( c19.fromWkt( wkt ) );
13187 : 1 : QCOMPARE( c19.numGeometries(), 2 );
13188 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c19.geometryN( 0 ) ), *static_cast< const QgsLineString * >( c18.geometryN( 0 ) ) );
13189 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c19.geometryN( 1 ) ), *static_cast< const QgsLineString * >( c18.geometryN( 1 ) ) );
13190 : :
13191 : : //bad WKT
13192 : 1 : QgsMultiLineString c20;
13193 : 1 : QVERIFY( !c20.fromWkt( "Point()" ) );
13194 : 1 : QVERIFY( c20.isEmpty() );
13195 : 1 : QCOMPARE( c20.numGeometries(), 0 );
13196 : 1 : QCOMPARE( c20.wkbType(), QgsWkbTypes::MultiLineString );
13197 : :
13198 : : //as JSON
13199 : 1 : QgsMultiLineString exportC;
13200 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) ) ;
13201 : 1 : exportC.addGeometry( part.clone() );
13202 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) ) ;
13203 : 1 : exportC.addGeometry( part.clone() );
13204 : :
13205 : : // GML document for compare
13206 : 1 : QDomDocument doc( "gml" );
13207 : :
13208 : : // as GML2
13209 : 2 : QString expectedSimpleGML2( QStringLiteral( "<MultiLineString xmlns=\"gml\"><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">7,17 3,13</coordinates></LineString></lineStringMember><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">27,37 43,43</coordinates></LineString></lineStringMember></MultiLineString>" ) );
13210 : 1 : QString res = elemToString( exportC.asGml2( doc ) );
13211 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
13212 : 2 : QString expectedGML2empty( QStringLiteral( "<MultiLineString xmlns=\"gml\"/>" ) );
13213 : 3 : QGSCOMPAREGML( elemToString( QgsMultiLineString().asGml2( doc ) ), expectedGML2empty );
13214 : :
13215 : : //as GML3
13216 : 2 : QString expectedSimpleGML3( QStringLiteral( "<MultiCurve xmlns=\"gml\"><curveMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">7 17 3 13</posList></LineString></curveMember><curveMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">27 37 43 43</posList></LineString></curveMember></MultiCurve>" ) );
13217 : 1 : res = elemToString( exportC.asGml3( doc ) );
13218 : 1 : QCOMPARE( res, expectedSimpleGML3 );
13219 : 2 : QString expectedGML3empty( QStringLiteral( "<MultiCurve xmlns=\"gml\"/>" ) );
13220 : 3 : QGSCOMPAREGML( elemToString( QgsMultiLineString().asGml3( doc ) ), expectedGML3empty );
13221 : :
13222 : : // as JSON
13223 : 1 : QString expectedSimpleJson( "{\"coordinates\":[[[7.0,17.0],[3.0,13.0]],[[27.0,37.0],[43.0,43.0]]],\"type\":\"MultiLineString\"}" );
13224 : 1 : res = exportC.asJson();
13225 : 1 : QCOMPARE( res, expectedSimpleJson );
13226 : :
13227 : 1 : QgsMultiLineString exportFloat;
13228 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7 / 3.0, 17 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 3 / 5.0, 13 / 3.0 ) ) ;
13229 : 1 : exportFloat.addGeometry( part.clone() );
13230 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27 / 3.0, 37 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 43 / 41.0, 43 / 42.0 ) ) ;
13231 : 1 : exportFloat.addGeometry( part.clone() );
13232 : :
13233 : 1 : QString expectedJsonPrec3( "{\"coordinates\":[[[2.333,5.667],[0.6,4.333]],[[9.0,4.111],[1.049,1.024]]],\"type\":\"MultiLineString\"}" );
13234 : 1 : res = exportFloat.asJson( 3 );
13235 : 1 : QCOMPARE( res, expectedJsonPrec3 );
13236 : :
13237 : : // as GML2
13238 : 2 : QString expectedGML2prec3( QStringLiteral( "<MultiLineString xmlns=\"gml\"><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">2.333,5.667 0.6,4.333</coordinates></LineString></lineStringMember><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">9,4.111 1.049,1.024</coordinates></LineString></lineStringMember></MultiLineString>" ) );
13239 : 1 : res = elemToString( exportFloat.asGml2( doc, 3 ) );
13240 : 3 : QGSCOMPAREGML( res, expectedGML2prec3 );
13241 : :
13242 : : //as GML3
13243 : 2 : QString expectedGML3prec3( QStringLiteral( "<MultiCurve xmlns=\"gml\"><curveMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">2.333 5.667 0.6 4.333</posList></LineString></curveMember><curveMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">9 4.111 1.049 1.024</posList></LineString></curveMember></MultiCurve>" ) );
13244 : 1 : res = elemToString( exportFloat.asGml3( doc, 3 ) );
13245 : 1 : QCOMPARE( res, expectedGML3prec3 );
13246 : :
13247 : : //asKML
13248 : 2 : QString expectedKml( QStringLiteral( "<MultiGeometry><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>7,17,0 3,13,0</coordinates></LineString><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>27,37,0 43,43,0</coordinates></LineString></MultiGeometry>" ) );
13249 : 1 : QCOMPARE( exportC.asKml(), expectedKml );
13250 : 2 : QString expectedKmlPrec3( QStringLiteral( "<MultiGeometry><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>2.333,5.667,0 0.6,4.333,0</coordinates></LineString><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>9,4.111,0 1.049,1.024,0</coordinates></LineString></MultiGeometry>" ) );
13251 : 1 : QCOMPARE( exportFloat.asKml( 3 ), expectedKmlPrec3 );
13252 : :
13253 : : // insert geometry
13254 : 1 : QgsMultiLineString rc;
13255 : 1 : rc.clear();
13256 : 1 : rc.insertGeometry( nullptr, 0 );
13257 : 1 : QVERIFY( rc.isEmpty() );
13258 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13259 : 1 : rc.insertGeometry( nullptr, -1 );
13260 : 1 : QVERIFY( rc.isEmpty() );
13261 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13262 : 1 : rc.insertGeometry( nullptr, 100 );
13263 : 1 : QVERIFY( rc.isEmpty() );
13264 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13265 : :
13266 : 1 : rc.insertGeometry( new QgsPoint(), 0 );
13267 : 1 : QVERIFY( rc.isEmpty() );
13268 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13269 : :
13270 : 1 : rc.insertGeometry( part.clone(), 0 );
13271 : 1 : QVERIFY( !rc.isEmpty() );
13272 : 1 : QCOMPARE( rc.numGeometries(), 1 );
13273 : :
13274 : : // cast
13275 : 1 : QVERIFY( !QgsMultiLineString().cast( nullptr ) );
13276 : 1 : QgsMultiLineString pCast;
13277 : 1 : QVERIFY( QgsMultiLineString().cast( &pCast ) );
13278 : 1 : QgsMultiLineString pCast2;
13279 : 2 : pCast2.fromWkt( QStringLiteral( "MultiLineStringZ()" ) );
13280 : 1 : QVERIFY( QgsMultiLineString().cast( &pCast2 ) );
13281 : 2 : pCast2.fromWkt( QStringLiteral( "MultiLineStringM()" ) );
13282 : 1 : QVERIFY( QgsMultiLineString().cast( &pCast2 ) );
13283 : 2 : pCast2.fromWkt( QStringLiteral( "MultiLineStringZM()" ) );
13284 : 1 : QVERIFY( QgsMultiLineString().cast( &pCast2 ) );
13285 : :
13286 : : //boundary
13287 : 1 : QgsMultiLineString multiLine1;
13288 : 1 : QVERIFY( !multiLine1.boundary() );
13289 : 1 : QgsLineString boundaryLine1;
13290 : 1 : boundaryLine1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
13291 : 1 : multiLine1.addGeometry( boundaryLine1.clone() );
13292 : 1 : QgsAbstractGeometry *boundary = multiLine1.boundary();
13293 : 1 : QgsMultiPoint *mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13294 : 1 : QVERIFY( mpBoundary );
13295 : 1 : QCOMPARE( mpBoundary->numGeometries(), 2 );
13296 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13297 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13298 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13299 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13300 : 1 : delete boundary;
13301 : : // add another linestring
13302 : 1 : QgsLineString boundaryLine2;
13303 : 1 : boundaryLine2.setPoints( QgsPointSequence() << QgsPoint( 10, 10 ) << QgsPoint( 11, 10 ) << QgsPoint( 11, 11 ) );
13304 : 1 : multiLine1.addGeometry( boundaryLine2.clone() );
13305 : 1 : boundary = multiLine1.boundary();
13306 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13307 : 1 : QVERIFY( mpBoundary );
13308 : 1 : QCOMPARE( mpBoundary->numGeometries(), 4 );
13309 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13310 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13311 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13312 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13313 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
13314 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
13315 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->x(), 11.0 );
13316 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->y(), 11.0 );
13317 : 1 : delete boundary;
13318 : :
13319 : : // vertex iterator: 2 linestrings with 3 points each
13320 : 1 : QgsAbstractGeometry::vertex_iterator it = multiLine1.vertices_begin();
13321 : 1 : QgsAbstractGeometry::vertex_iterator itEnd = multiLine1.vertices_end();
13322 : 1 : QCOMPARE( *it, QgsPoint( 0, 0 ) );
13323 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 0 ) );
13324 : 1 : ++it;
13325 : 1 : QCOMPARE( *it, QgsPoint( 1, 0 ) );
13326 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 1 ) );
13327 : 1 : ++it;
13328 : 1 : QCOMPARE( *it, QgsPoint( 1, 1 ) );
13329 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 2 ) );
13330 : 1 : ++it;
13331 : 1 : QCOMPARE( *it, QgsPoint( 10, 10 ) );
13332 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 0 ) );
13333 : 1 : ++it;
13334 : 1 : QCOMPARE( *it, QgsPoint( 11, 10 ) );
13335 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 1 ) );
13336 : 1 : ++it;
13337 : 1 : QCOMPARE( *it, QgsPoint( 11, 11 ) );
13338 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 2 ) );
13339 : 1 : ++it;
13340 : 1 : QCOMPARE( it, itEnd );
13341 : :
13342 : : // Java-style iterator
13343 : 1 : QgsVertexIterator it2( &multiLine1 );
13344 : 1 : QVERIFY( it2.hasNext() );
13345 : 1 : QCOMPARE( it2.next(), QgsPoint( 0, 0 ) );
13346 : 1 : QVERIFY( it2.hasNext() );
13347 : 1 : QCOMPARE( it2.next(), QgsPoint( 1, 0 ) );
13348 : 1 : QVERIFY( it2.hasNext() );
13349 : 1 : QCOMPARE( it2.next(), QgsPoint( 1, 1 ) );
13350 : 1 : QVERIFY( it2.hasNext() );
13351 : 1 : QCOMPARE( it2.next(), QgsPoint( 10, 10 ) );
13352 : 1 : QVERIFY( it2.hasNext() );
13353 : 1 : QCOMPARE( it2.next(), QgsPoint( 11, 10 ) );
13354 : 1 : QVERIFY( it2.hasNext() );
13355 : 1 : QCOMPARE( it2.next(), QgsPoint( 11, 11 ) );
13356 : 1 : QVERIFY( !it2.hasNext() );
13357 : :
13358 : : // add a closed string = no boundary
13359 : 1 : QgsLineString boundaryLine3;
13360 : 1 : boundaryLine3.setPoints( QgsPointSequence() << QgsPoint( 20, 20 ) << QgsPoint( 21, 20 ) << QgsPoint( 21, 21 ) << QgsPoint( 20, 20 ) );
13361 : 1 : multiLine1.addGeometry( boundaryLine3.clone() );
13362 : 1 : boundary = multiLine1.boundary();
13363 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13364 : 1 : QVERIFY( mpBoundary );
13365 : 1 : QCOMPARE( mpBoundary->numGeometries(), 4 );
13366 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13367 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13368 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13369 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13370 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
13371 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
13372 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->x(), 11.0 );
13373 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->y(), 11.0 );
13374 : 1 : delete boundary;
13375 : :
13376 : : //boundary with z
13377 : 1 : QgsLineString boundaryLine4;
13378 : 1 : boundaryLine4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) );
13379 : 1 : QgsLineString boundaryLine5;
13380 : 1 : boundaryLine5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 150 ) << QgsPoint( QgsWkbTypes::PointZ, 20, 20, 200 ) );
13381 : 1 : QgsMultiLineString multiLine2;
13382 : 1 : multiLine2.addGeometry( boundaryLine4.clone() );
13383 : 1 : multiLine2.addGeometry( boundaryLine5.clone() );
13384 : :
13385 : 1 : boundary = multiLine2.boundary();
13386 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13387 : 1 : QVERIFY( mpBoundary );
13388 : 1 : QCOMPARE( mpBoundary->numGeometries(), 4 );
13389 : 1 : QCOMPARE( mpBoundary->geometryN( 0 )->wkbType(), QgsWkbTypes::PointZ );
13390 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13391 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13392 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->z(), 10.0 );
13393 : 1 : QCOMPARE( mpBoundary->geometryN( 1 )->wkbType(), QgsWkbTypes::PointZ );
13394 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13395 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13396 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
13397 : 1 : QCOMPARE( mpBoundary->geometryN( 2 )->wkbType(), QgsWkbTypes::PointZ );
13398 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
13399 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
13400 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->z(), 100.0 );
13401 : 1 : QCOMPARE( mpBoundary->geometryN( 3 )->wkbType(), QgsWkbTypes::PointZ );
13402 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->x(), 20.0 );
13403 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->y(), 20.0 );
13404 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->z(), 200.0 );
13405 : 1 : delete boundary;
13406 : :
13407 : : //segmentLength
13408 : 1 : QgsMultiLineString multiLine3;
13409 : 1 : QgsLineString vertexLine3;
13410 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
13411 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 0 ) ), 0.0 );
13412 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 0 ) ), 0.0 );
13413 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, -1, 0 ) ), 0.0 );
13414 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 1, 0 ) ), 0.0 );
13415 : 2 : vertexLine3.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 )
13416 : 1 : << QgsPoint( 111, 2 ) << QgsPoint( 11, 2 ) );
13417 : 1 : multiLine3.addGeometry( vertexLine3.clone() );
13418 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId() ), 0.0 );
13419 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
13420 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 0 ) ), 10.0 );
13421 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 1 ) ), 100.0 );
13422 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 2 ) ), 10.0 );
13423 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 3 ) ), 100.0 );
13424 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 4 ) ), 0.0 );
13425 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
13426 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
13427 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, -1, 0 ) ), 10.0 );
13428 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 1, 0 ) ), 0.0 );
13429 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 1, 1 ) ), 0.0 );
13430 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 1 ) ), 0.0 );
13431 : :
13432 : : // add another line
13433 : 2 : vertexLine3.setPoints( QgsPointSequence() << QgsPoint( 30, 6 ) << QgsPoint( 34, 6 ) << QgsPoint( 34, 8 )
13434 : 1 : << QgsPoint( 30, 8 ) << QgsPoint( 30, 6 ) );
13435 : 1 : multiLine3.addGeometry( vertexLine3.clone() );
13436 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId() ), 0.0 );
13437 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, -1 ) ), 0.0 );
13438 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 0 ) ), 10.0 );
13439 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 1 ) ), 100.0 );
13440 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 2 ) ), 10.0 );
13441 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 3 ) ), 100.0 );
13442 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, 0, 4 ) ), 0.0 );
13443 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( -1, 0, -1 ) ), 0.0 );
13444 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( -1, 0, 0 ) ), 0.0 );
13445 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 0, -1, 0 ) ), 10.0 );
13446 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, -1 ) ), 0.0 );
13447 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 0 ) ), 4.0 );
13448 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 1 ) ), 2.0 );
13449 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 2 ) ), 4.0 );
13450 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 3 ) ), 2.0 );
13451 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 0, 4 ) ), 0.0 );
13452 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 1, 1 ) ), 2.0 );
13453 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 1, 1, 2 ) ), 4.0 );
13454 : 1 : QCOMPARE( multiLine3.segmentLength( QgsVertexId( 2, 0, 0 ) ), 0.0 );
13455 : 1 : }
13456 : :
13457 : 1 : void TestQgsGeometry::multiCurve()
13458 : : {
13459 : : //test constructor
13460 : 1 : QgsMultiCurve c1;
13461 : 1 : QVERIFY( c1.isEmpty() );
13462 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
13463 : 1 : QCOMPARE( c1.ringCount(), 0 );
13464 : 1 : QCOMPARE( c1.partCount(), 0 );
13465 : 1 : QVERIFY( !c1.is3D() );
13466 : 1 : QVERIFY( !c1.isMeasure() );
13467 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiCurve );
13468 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiCurve" ) );
13469 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiCurve" ) );
13470 : 1 : QCOMPARE( c1.dimension(), 0 );
13471 : 1 : QVERIFY( !c1.hasCurvedSegments() );
13472 : 1 : QCOMPARE( c1.area(), 0.0 );
13473 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
13474 : 1 : QCOMPARE( c1.numGeometries(), 0 );
13475 : 1 : QVERIFY( !c1.geometryN( 0 ) );
13476 : 1 : QVERIFY( !c1.geometryN( -1 ) );
13477 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 0 );
13478 : 1 : QCOMPARE( c1.vertexCount( 0, 1 ), 0 );
13479 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
13480 : :
13481 : : //addGeometry
13482 : : //try with nullptr
13483 : 1 : c1.addGeometry( nullptr );
13484 : 1 : QVERIFY( c1.isEmpty() );
13485 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
13486 : 1 : QCOMPARE( c1.ringCount(), 0 );
13487 : 1 : QCOMPARE( c1.partCount(), 0 );
13488 : 1 : QCOMPARE( c1.numGeometries(), 0 );
13489 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiCurve );
13490 : 1 : QVERIFY( !c1.geometryN( 0 ) );
13491 : 1 : QVERIFY( !c1.geometryN( -1 ) );
13492 : :
13493 : : // not a curve
13494 : 1 : QVERIFY( !c1.addGeometry( new QgsPoint() ) );
13495 : 1 : QVERIFY( c1.isEmpty() );
13496 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
13497 : 1 : QCOMPARE( c1.ringCount(), 0 );
13498 : 1 : QCOMPARE( c1.partCount(), 0 );
13499 : 1 : QCOMPARE( c1.numGeometries(), 0 );
13500 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiCurve );
13501 : 1 : QVERIFY( !c1.geometryN( 0 ) );
13502 : 1 : QVERIFY( !c1.geometryN( -1 ) );
13503 : :
13504 : : //valid geometry
13505 : 1 : QgsCircularString part;
13506 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) << QgsPoint( 1, 12 ) );
13507 : 1 : c1.addGeometry( part.clone() );
13508 : 1 : QVERIFY( !c1.isEmpty() );
13509 : 1 : QCOMPARE( c1.numGeometries(), 1 );
13510 : 1 : QCOMPARE( c1.nCoordinates(), 3 );
13511 : 1 : QCOMPARE( c1.ringCount(), 1 );
13512 : 1 : QCOMPARE( c1.partCount(), 1 );
13513 : 1 : QVERIFY( !c1.is3D() );
13514 : 1 : QVERIFY( !c1.isMeasure() );
13515 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiCurve );
13516 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiCurve" ) );
13517 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiCurve" ) );
13518 : 1 : QCOMPARE( c1.dimension(), 1 );
13519 : 1 : QVERIFY( c1.hasCurvedSegments() );
13520 : 1 : QCOMPARE( c1.area(), 0.0 );
13521 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
13522 : 1 : QVERIFY( c1.geometryN( 0 ) );
13523 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c1.geometryN( 0 ) ), part );
13524 : 1 : QVERIFY( !c1.geometryN( 100 ) );
13525 : 1 : QVERIFY( !c1.geometryN( -1 ) );
13526 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 3 );
13527 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
13528 : :
13529 : : //initial adding of geometry should set z/m type
13530 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 20, 21, 2 )
13531 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 31, 3 ) );
13532 : 1 : QgsMultiCurve c2;
13533 : 1 : c2.addGeometry( part.clone() );
13534 : 1 : QVERIFY( c2.is3D() );
13535 : 1 : QVERIFY( !c2.isMeasure() );
13536 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::MultiCurveZ );
13537 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "MultiCurveZ" ) );
13538 : 1 : QCOMPARE( c2.geometryType(), QString( "MultiCurve" ) );
13539 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( c2.geometryN( 0 ) ) ), part );
13540 : 1 : QgsMultiCurve c3;
13541 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 10, 11, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 20, 21, 0, 2 )
13542 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 31, 0, 3 ) );
13543 : 1 : c3.addGeometry( part.clone() );
13544 : 1 : QVERIFY( !c3.is3D() );
13545 : 1 : QVERIFY( c3.isMeasure() );
13546 : 1 : QCOMPARE( c3.wkbType(), QgsWkbTypes::MultiCurveM );
13547 : 1 : QCOMPARE( c3.wktTypeStr(), QString( "MultiCurveM" ) );
13548 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( c3.geometryN( 0 ) ) ), part );
13549 : 1 : QgsMultiCurve c4;
13550 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 10, 11, 2, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 20, 21, 3, 2 )
13551 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 31, 4, 5 ) );
13552 : 1 : c4.addGeometry( part.clone() );
13553 : 1 : QVERIFY( c4.is3D() );
13554 : 1 : QVERIFY( c4.isMeasure() );
13555 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::MultiCurveZM );
13556 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "MultiCurveZM" ) );
13557 : 1 : QCOMPARE( *( static_cast< const QgsCircularString * >( c4.geometryN( 0 ) ) ), part );
13558 : :
13559 : : //add another part
13560 : 1 : QgsMultiCurve c6;
13561 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) << QgsPoint( 1, 20 ) );
13562 : 1 : c6.addGeometry( part.clone() );
13563 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 3 );
13564 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 9, 12 ) << QgsPoint( 3, 13 ) << QgsPoint( 9, 20 ) );
13565 : 1 : c6.addGeometry( part.clone() );
13566 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 3 );
13567 : 1 : QCOMPARE( c6.numGeometries(), 2 );
13568 : 1 : QVERIFY( c6.geometryN( 0 ) );
13569 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c6.geometryN( 1 ) ), part );
13570 : :
13571 : : //adding subsequent points should not alter z/m type, regardless of parts type
13572 : 1 : c6.clear();
13573 : 1 : c6.addGeometry( part.clone() );
13574 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurve );
13575 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) << QgsPoint( 1, 20, 4 ) ) ;
13576 : 1 : c6.addGeometry( part.clone() );
13577 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurve );
13578 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 3 );
13579 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 3 );
13580 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 0 );
13581 : 1 : QCOMPARE( c6.vertexCount( -1, 0 ), 0 );
13582 : 1 : QCOMPARE( c6.nCoordinates(), 6 );
13583 : 1 : QCOMPARE( c6.ringCount(), 1 );
13584 : 1 : QCOMPARE( c6.partCount(), 2 );
13585 : 1 : QVERIFY( !c6.is3D() );
13586 : 1 : const QgsCircularString *ls = static_cast< const QgsCircularString * >( c6.geometryN( 0 ) );
13587 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 9, 12 ) );
13588 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 3, 13 ) );
13589 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( 9, 20 ) );
13590 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 1 ) );
13591 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 1, 10 ) );
13592 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 2, 11 ) );
13593 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( 1, 20 ) );
13594 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 21, 30, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 32, 41, 0, 3 )
13595 : 1 : << QgsPoint( QgsWkbTypes::PointM, 21, 51, 0, 4 ) ) ;
13596 : 1 : c6.addGeometry( part.clone() );
13597 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurve );
13598 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 3 );
13599 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 3 );
13600 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 3 );
13601 : 1 : QCOMPARE( c6.nCoordinates(), 9 );
13602 : 1 : QCOMPARE( c6.ringCount(), 1 );
13603 : 1 : QCOMPARE( c6.partCount(), 3 );
13604 : 1 : QVERIFY( !c6.is3D() );
13605 : 1 : QVERIFY( !c6.isMeasure() );
13606 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 2 ) );
13607 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 21, 30 ) );
13608 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 32, 41 ) );
13609 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( 21, 51 ) );
13610 : :
13611 : 1 : c6.clear();
13612 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) << QgsPoint( 1, 21, 4 ) ) ;
13613 : 1 : c6.addGeometry( part.clone() );
13614 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZ );
13615 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) << QgsPoint( 2, 41 ) ) ;
13616 : 1 : c6.addGeometry( part.clone() );
13617 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZ );
13618 : 1 : QVERIFY( c6.is3D() );
13619 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 0 ) );
13620 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 1, 10, 2 ) );
13621 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 2, 11, 3 ) );
13622 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( 1, 21, 4 ) );
13623 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 1 ) );
13624 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 2, 20, 0 ) );
13625 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 3, 31, 0 ) );
13626 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( 2, 41, 0 ) );
13627 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 )
13628 : 1 : << QgsPoint( QgsWkbTypes::PointM, 5, 71, 0, 6 ) ) ;
13629 : 1 : c6.addGeometry( part.clone() );
13630 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZ );
13631 : 1 : QVERIFY( c6.is3D() );
13632 : 1 : QVERIFY( !c6.isMeasure() );
13633 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 2 ) );
13634 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( 5, 50, 0 ) );
13635 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( 6, 61, 0 ) );
13636 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( 5, 71, 0 ) );
13637 : :
13638 : 1 : c6.clear();
13639 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurve );
13640 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 )
13641 : 1 : << QgsPoint( QgsWkbTypes::PointM, 5, 71, 0, 5 ) ) ;
13642 : 1 : c6.addGeometry( part.clone() );
13643 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveM );
13644 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) << QgsPoint( 2, 41 ) ) ;
13645 : 1 : c6.addGeometry( part.clone() );
13646 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveM );
13647 : 1 : QVERIFY( c6.isMeasure() );
13648 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 0 ) );
13649 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) );
13650 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 ) );
13651 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 5, 71, 0, 5 ) );
13652 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 1 ) );
13653 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 2, 20, 0, 0 ) );
13654 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 3, 31, 0, 0 ) );
13655 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 2, 41, 0, 0 ) );
13656 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( 11, 12, 13 ) << QgsPoint( 14, 15, 16 ) << QgsPoint( 11, 25, 17 ) ) ;
13657 : 1 : c6.addGeometry( part.clone() );
13658 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveM );
13659 : 1 : QVERIFY( !c6.is3D() );
13660 : 1 : QVERIFY( c6.isMeasure() );
13661 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 2 ) );
13662 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
13663 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 14, 15, 0, 0 ) );
13664 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 11, 25, 0, 0 ) );
13665 : :
13666 : 1 : c6.clear();
13667 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 )
13668 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 5, 71, 4, 6 ) ) ;
13669 : 1 : c6.addGeometry( part.clone() );
13670 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZM );
13671 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 )
13672 : 1 : << QgsPoint( QgsWkbTypes::Point, 7, 11 ) ) ;
13673 : 1 : c6.addGeometry( part.clone() );
13674 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZM );
13675 : 1 : QVERIFY( c6.isMeasure() );
13676 : 1 : QVERIFY( c6.is3D() );
13677 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 0 ) );
13678 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) );
13679 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 ) );
13680 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 5, 71, 4, 6 ) );
13681 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 1 ) );
13682 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 0, 0 ) );
13683 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 3, 13, 0, 0 ) );
13684 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 7, 11, 0, 0 ) );
13685 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 77, 87, 7 ) << QgsPoint( QgsWkbTypes::PointZ, 83, 83, 8 )
13686 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 77, 81, 9 ) ) ;
13687 : 1 : c6.addGeometry( part.clone() );
13688 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZM );
13689 : 1 : QVERIFY( c6.is3D() );
13690 : 1 : QVERIFY( c6.isMeasure() );
13691 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 2 ) );
13692 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 77, 87, 7, 0 ) );
13693 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 83, 83, 8, 0 ) );
13694 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 77, 81, 9, 0 ) );
13695 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 177, 187, 0, 9 ) << QgsPoint( QgsWkbTypes::PointM, 183, 183, 0, 11 )
13696 : 1 : << QgsPoint( QgsWkbTypes::PointM, 177, 181, 0, 13 ) ) ;
13697 : 1 : c6.addGeometry( part.clone() );
13698 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiCurveZM );
13699 : 1 : QVERIFY( c6.is3D() );
13700 : 1 : QVERIFY( c6.isMeasure() );
13701 : 1 : ls = static_cast< const QgsCircularString * >( c6.geometryN( 3 ) );
13702 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 177, 187, 0, 9 ) );
13703 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 183, 183, 0, 11 ) );
13704 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 177, 181, 0, 13 ) );
13705 : :
13706 : : //clear
13707 : 1 : QgsMultiCurve c7;
13708 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 )
13709 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 5, 71, 4, 6 ) ) ;
13710 : 1 : c7.addGeometry( part.clone() );
13711 : 1 : c7.addGeometry( part.clone() );
13712 : 1 : QCOMPARE( c7.numGeometries(), 2 );
13713 : 1 : c7.clear();
13714 : 1 : QVERIFY( c7.isEmpty() );
13715 : 1 : QCOMPARE( c7.numGeometries(), 0 );
13716 : 1 : QCOMPARE( c7.nCoordinates(), 0 );
13717 : 1 : QCOMPARE( c7.ringCount(), 0 );
13718 : 1 : QCOMPARE( c7.partCount(), 0 );
13719 : 1 : QVERIFY( !c7.is3D() );
13720 : 1 : QVERIFY( !c7.isMeasure() );
13721 : 1 : QCOMPARE( c7.wkbType(), QgsWkbTypes::MultiCurve );
13722 : :
13723 : : //clone
13724 : 1 : QgsMultiCurve c11;
13725 : 1 : std::unique_ptr< QgsMultiCurve >cloned( c11.clone() );
13726 : 1 : QVERIFY( cloned->isEmpty() );
13727 : 1 : c11.addGeometry( part.clone() );
13728 : 1 : c11.addGeometry( part.clone() );
13729 : 1 : cloned.reset( c11.clone() );
13730 : 1 : QCOMPARE( cloned->numGeometries(), 2 );
13731 : 1 : ls = static_cast< const QgsCircularString * >( cloned->geometryN( 0 ) );
13732 : 1 : QCOMPARE( *ls, part );
13733 : 1 : ls = static_cast< const QgsCircularString * >( cloned->geometryN( 1 ) );
13734 : 1 : QCOMPARE( *ls, part );
13735 : :
13736 : : //copy constructor
13737 : 1 : QgsMultiCurve c12;
13738 : 1 : QgsMultiCurve c13( c12 );
13739 : 1 : QVERIFY( c13.isEmpty() );
13740 : 1 : c12.addGeometry( part.clone() );
13741 : 1 : c12.addGeometry( part.clone() );
13742 : 1 : QgsMultiCurve c14( c12 );
13743 : 1 : QCOMPARE( c14.numGeometries(), 2 );
13744 : 1 : QCOMPARE( c14.wkbType(), QgsWkbTypes::MultiCurveZM );
13745 : 1 : ls = static_cast< const QgsCircularString * >( c14.geometryN( 0 ) );
13746 : 1 : QCOMPARE( *ls, part );
13747 : 1 : ls = static_cast< const QgsCircularString * >( c14.geometryN( 1 ) );
13748 : 1 : QCOMPARE( *ls, part );
13749 : :
13750 : : //assignment operator
13751 : 1 : QgsMultiCurve c15;
13752 : 1 : c15 = c13;
13753 : 1 : QCOMPARE( c15.numGeometries(), 0 );
13754 : 1 : c15 = c14;
13755 : 1 : QCOMPARE( c15.numGeometries(), 2 );
13756 : 1 : ls = static_cast< const QgsCircularString * >( c15.geometryN( 0 ) );
13757 : 1 : QCOMPARE( *ls, part );
13758 : 1 : ls = static_cast< const QgsCircularString * >( c15.geometryN( 1 ) );
13759 : 1 : QCOMPARE( *ls, part );
13760 : :
13761 : : //toCurveType
13762 : 1 : std::unique_ptr< QgsMultiCurve > curveType( c12.toCurveType() );
13763 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::MultiCurveZM );
13764 : 1 : QCOMPARE( curveType->numGeometries(), 2 );
13765 : 1 : const QgsCircularString *curve = static_cast< const QgsCircularString * >( curveType->geometryN( 0 ) );
13766 : 1 : QCOMPARE( *curve, *static_cast< const QgsCircularString * >( c12.geometryN( 0 ) ) );
13767 : 1 : curve = static_cast< const QgsCircularString * >( curveType->geometryN( 1 ) );
13768 : 1 : QCOMPARE( *curve, *static_cast< const QgsCircularString * >( c12.geometryN( 1 ) ) );
13769 : :
13770 : : //to/fromWKB
13771 : 1 : QgsMultiCurve c16;
13772 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) << QgsPoint( QgsWkbTypes::Point, 7, 11 ) ) ;
13773 : 1 : c16.addGeometry( part.clone() );
13774 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) << QgsPoint( QgsWkbTypes::Point, 27, 54 ) ) ;
13775 : 1 : c16.addGeometry( part.clone() );
13776 : 1 : QByteArray wkb16 = c16.asWkb();
13777 : 1 : QgsMultiCurve c17;
13778 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
13779 : 1 : c17.fromWkb( wkb16ptr );
13780 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13781 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 0 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 0 ) ) );
13782 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 1 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 1 ) ) );
13783 : :
13784 : : //parts with Z
13785 : 1 : c16.clear();
13786 : 1 : c17.clear();
13787 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 7, 17, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 3, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 7, 11, 3 ) ) ;
13788 : 1 : c16.addGeometry( part.clone() );
13789 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 27, 37, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 43, 43, 5 ) << QgsPoint( QgsWkbTypes::PointZ, 27, 53, 6 ) ) ;
13790 : 1 : c16.addGeometry( part.clone() );
13791 : 1 : wkb16 = c16.asWkb();
13792 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
13793 : 1 : c17.fromWkb( wkb16ptr2 );
13794 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13795 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiCurveZ );
13796 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 0 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 0 ) ) );
13797 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 1 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 1 ) ) );
13798 : :
13799 : : //parts with m
13800 : 1 : c16.clear();
13801 : 1 : c17.clear();
13802 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 7, 17, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 3, 13, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 7, 11, 0, 5 ) ) ;
13803 : 1 : c16.addGeometry( part.clone() );
13804 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 27, 37, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 43, 43, 0, 5 ) << QgsPoint( QgsWkbTypes::PointM, 27, 53, 0, 7 ) ) ;
13805 : 1 : c16.addGeometry( part.clone() );
13806 : 1 : wkb16 = c16.asWkb();
13807 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
13808 : 1 : c17.fromWkb( wkb16ptr3 );
13809 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13810 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiCurveM );
13811 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 0 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 0 ) ) );
13812 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 1 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 1 ) ) );
13813 : :
13814 : : // parts with ZM
13815 : 1 : c16.clear();
13816 : 1 : c17.clear();
13817 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 11, 2, 5 ) ) ;
13818 : 1 : c16.addGeometry( part.clone() );
13819 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 47, 12, 15 ) ) ;
13820 : 1 : c16.addGeometry( part.clone() );
13821 : 1 : wkb16 = c16.asWkb();
13822 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
13823 : 1 : c17.fromWkb( wkb16ptr4 );
13824 : 1 : QCOMPARE( c17.numGeometries(), 2 );
13825 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiCurveZM );
13826 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 0 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 0 ) ) );
13827 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c17.geometryN( 1 ) ), *static_cast< const QgsCircularString * >( c16.geometryN( 1 ) ) );
13828 : :
13829 : : //bad WKB - check for no crash
13830 : 1 : c17.clear();
13831 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
13832 : 1 : QVERIFY( !c17.fromWkb( nullPtr ) );
13833 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiCurve );
13834 : 1 : QgsPoint point( 1, 2 );
13835 : 1 : QByteArray wkbPoint = point.asWkb();
13836 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
13837 : 1 : QVERIFY( !c17.fromWkb( wkbPointPtr ) );
13838 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiCurve );
13839 : :
13840 : : //to/from WKT
13841 : 1 : QgsMultiCurve c18;
13842 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 11, 2, 8 ) ) ;
13843 : 1 : c18.addGeometry( part.clone() );
13844 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 53, 21, 52 ) ) ;
13845 : 1 : c18.addGeometry( part.clone() );
13846 : :
13847 : 1 : QString wkt = c18.asWkt();
13848 : 1 : QVERIFY( !wkt.isEmpty() );
13849 : 1 : QgsMultiCurve c19;
13850 : 1 : QVERIFY( c19.fromWkt( wkt ) );
13851 : 1 : QCOMPARE( c19.numGeometries(), 2 );
13852 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c19.geometryN( 0 ) ), *static_cast< const QgsCircularString * >( c18.geometryN( 0 ) ) );
13853 : 1 : QCOMPARE( *static_cast< const QgsCircularString * >( c19.geometryN( 1 ) ), *static_cast< const QgsCircularString * >( c18.geometryN( 1 ) ) );
13854 : :
13855 : : //bad WKT
13856 : 1 : QgsMultiCurve c20;
13857 : 1 : QVERIFY( !c20.fromWkt( "Point()" ) );
13858 : 1 : QVERIFY( c20.isEmpty() );
13859 : 1 : QCOMPARE( c20.numGeometries(), 0 );
13860 : 1 : QCOMPARE( c20.wkbType(), QgsWkbTypes::MultiCurve );
13861 : :
13862 : : //as JSON
13863 : 1 : QgsMultiCurve exportC;
13864 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) << QgsPoint( QgsWkbTypes::Point, 7, 11 ) ) ;
13865 : 1 : exportC.addGeometry( part.clone() );
13866 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) << QgsPoint( QgsWkbTypes::Point, 27, 47 ) ) ;
13867 : 1 : exportC.addGeometry( part.clone() );
13868 : :
13869 : : // GML document for compare
13870 : 1 : QDomDocument doc( "gml" );
13871 : :
13872 : : // as GML2
13873 : 2 : QString expectedSimpleGML2( QStringLiteral( "<MultiLineString xmlns=\"gml\"><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">7,17 6.9,17 6.9,17 6.8,17 6.8,17.1 6.7,17.1 6.7,17.1 6.6,17.1 6.6,17.1 6.5,17.1 6.5,17.1 6.4,17.1 6.4,17.1 6.3,17.1 6.2,17.2 6.2,17.2 6.1,17.2 6.1,17.2 6,17.2 6,17.2 5.9,17.2 5.9,17.2 5.8,17.2 5.7,17.2 5.7,17.1 5.6,17.1 5.6,17.1 5.5,17.1 5.5,17.1 5.4,17.1 5.4,17.1 5.3,17.1 5.3,17.1 5.2,17.1 5.2,17 5.1,17 5,17 5,17 4.9,17 4.9,17 4.8,16.9 4.8,16.9 4.7,16.9 4.7,16.9 4.6,16.9 4.6,16.8 4.5,16.8 4.5,16.8 4.4,16.8 4.4,16.7 4.3,16.7 4.3,16.7 4.3,16.6 4.2,16.6 4.2,16.6 4.1,16.5 4.1,16.5 4,16.5 4,16.4 3.9,16.4 3.9,16.4 3.9,16.3 3.8,16.3 3.8,16.3 3.7,16.2 3.7,16.2 3.7,16.1 3.6,16.1 3.6,16.1 3.6,16 3.5,16 3.5,15.9 3.5,15.9 3.4,15.8 3.4,15.8 3.4,15.7 3.3,15.7 3.3,15.7 3.3,15.6 3.2,15.6 3.2,15.5 3.2,15.5 3.2,15.4 3.1,15.4 3.1,15.3 3.1,15.3 3.1,15.2 3.1,15.2 3,15.1 3,15.1 3,15 3,15 3,14.9 3,14.8 2.9,14.8 2.9,14.7 2.9,14.7 2.9,14.6 2.9,14.6 2.9,14.5 2.9,14.5 2.9,14.4 2.9,14.4 2.9,14.3 2.8,14.2 2.8,14.2 2.8,14.1 2.8,14.1 2.8,14 2.8,14 2.8,13.9 2.8,13.9 2.8,13.8 2.8,13.8 2.9,13.7 2.9,13.6 2.9,13.6 2.9,13.5 2.9,13.5 2.9,13.4 2.9,13.4 2.9,13.3 2.9,13.3 2.9,13.2 3,13.2 3,13.1 3,13 3,13 3,12.9 3,12.9 3.1,12.8 3.1,12.8 3.1,12.7 3.1,12.7 3.1,12.6 3.2,12.6 3.2,12.5 3.2,12.5 3.2,12.4 3.3,12.4 3.3,12.3 3.3,12.3 3.4,12.3 3.4,12.2 3.4,12.2 3.5,12.1 3.5,12.1 3.5,12 3.6,12 3.6,11.9 3.6,11.9 3.7,11.9 3.7,11.8 3.7,11.8 3.8,11.7 3.8,11.7 3.9,11.7 3.9,11.6 3.9,11.6 4,11.6 4,11.5 4.1,11.5 4.1,11.5 4.2,11.4 4.2,11.4 4.3,11.4 4.3,11.3 4.3,11.3 4.4,11.3 4.4,11.2 4.5,11.2 4.5,11.2 4.6,11.2 4.6,11.1 4.7,11.1 4.7,11.1 4.8,11.1 4.8,11.1 4.9,11 4.9,11 5,11 5,11 5.1,11 5.2,11 5.2,10.9 5.3,10.9 5.3,10.9 5.4,10.9 5.4,10.9 5.5,10.9 5.5,10.9 5.6,10.9 5.6,10.9 5.7,10.9 5.7,10.8 5.8,10.8 5.9,10.8 5.9,10.8 6,10.8 6,10.8 6.1,10.8 6.1,10.8 6.2,10.8 6.2,10.8 6.3,10.9 6.4,10.9 6.4,10.9 6.5,10.9 6.5,10.9 6.6,10.9 6.6,10.9 6.7,10.9 6.7,10.9 6.8,10.9 6.8,11 6.9,11 6.9,11 7,11</coordinates></LineString></lineStringMember><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">27,37 27.1,36.9 27.2,36.8 27.3,36.6 27.4,36.5 27.5,36.4 27.6,36.3 27.7,36.2 27.8,36 27.9,35.9 28,35.8 28.1,35.7 28.2,35.6 28.3,35.5 28.4,35.4 28.5,35.3 28.7,35.2 28.8,35.1 28.9,35 29,34.9 29.1,34.8 29.3,34.7 29.4,34.6 29.5,34.6 29.7,34.5 29.8,34.4 29.9,34.3 30.1,34.3 30.2,34.2 30.3,34.1 30.5,34 30.6,34 30.7,33.9 30.9,33.9 31,33.8 31.2,33.7 31.3,33.7 31.5,33.6 31.6,33.6 31.8,33.6 31.9,33.5 32.1,33.5 32.2,33.4 32.4,33.4 32.5,33.4 32.7,33.3 32.8,33.3 33,33.3 33.1,33.3 33.3,33.2 33.4,33.2 33.6,33.2 33.7,33.2 33.9,33.2 34,33.2 34.2,33.2 34.3,33.2 34.5,33.2 34.6,33.2 34.8,33.2 34.9,33.2 35.1,33.2 35.3,33.3 35.4,33.3 35.6,33.3 35.7,33.3 35.9,33.3 36,33.4 36.2,33.4 36.3,33.4 36.5,33.5 36.6,33.5 36.8,33.6 36.9,33.6 37.1,33.7 37.2,33.7 37.3,33.8 37.5,33.8 37.6,33.9 37.8,33.9 37.9,34 38,34.1 38.2,34.1 38.3,34.2 38.5,34.3 38.6,34.3 38.7,34.4 38.9,34.5 39,34.6 39.1,34.7 39.2,34.7 39.4,34.8 39.5,34.9 39.6,35 39.7,35.1 39.9,35.2 40,35.3 40.1,35.4 40.2,35.5 40.3,35.6 40.4,35.7 40.5,35.8 40.6,35.9 40.7,36.1 40.8,36.2 40.9,36.3 41,36.4 41.1,36.5 41.2,36.6 41.3,36.8 41.4,36.9 41.5,37 41.6,37.1 41.7,37.3 41.8,37.4 41.8,37.5 41.9,37.7 42,37.8 42.1,37.9 42.1,38.1 42.2,38.2 42.3,38.3 42.3,38.5 42.4,38.6 42.4,38.8 42.5,38.9 42.6,39.1 42.6,39.2 42.6,39.4 42.7,39.5 42.7,39.6 42.8,39.8 42.8,39.9 42.8,40.1 42.9,40.2 42.9,40.4 42.9,40.5 43,40.7 43,40.9 43,41 43,41.2 43,41.3 43,41.5 43,41.6 43.1,41.8 43.1,41.9 43.1,42.1 43.1,42.2 43,42.4 43,42.5 43,42.7 43,42.8 43,43 43,43.1 43,43.3 42.9,43.5 42.9,43.6 42.9,43.8 42.8,43.9 42.8,44.1 42.8,44.2 42.7,44.4 42.7,44.5 42.6,44.6 42.6,44.8 42.6,44.9 42.5,45.1 42.4,45.2 42.4,45.4 42.3,45.5 42.3,45.7 42.2,45.8 42.1,45.9 42.1,46.1 42,46.2 41.9,46.3 41.8,46.5 41.8,46.6 41.7,46.7 41.6,46.9 41.5,47 41.4,47.1 41.3,47.2 41.2,47.4 41.1,47.5 41,47.6 40.9,47.7 40.8,47.8 40.7,47.9 40.6,48.1 40.5,48.2 40.4,48.3 40.3,48.4 40.2,48.5 40.1,48.6 40,48.7 39.9,48.8 39.7,48.9 39.6,49 39.5,49.1 39.4,49.2 39.2,49.3 39.1,49.3 39,49.4 38.9,49.5 38.7,49.6 38.6,49.7 38.5,49.7 38.3,49.8 38.2,49.9 38,49.9 37.9,50 37.8,50.1 37.6,50.1 37.5,50.2 37.3,50.2 37.2,50.3 37.1,50.3 36.9,50.4 36.8,50.4 36.6,50.5 36.5,50.5 36.3,50.6 36.2,50.6 36,50.6 35.9,50.7 35.7,50.7 35.6,50.7 35.4,50.7 35.3,50.7 35.1,50.8 34.9,50.8 34.8,50.8 34.6,50.8 34.5,50.8 34.3,50.8 34.2,50.8 34,50.8 33.9,50.8 33.7,50.8 33.6,50.8 33.4,50.8 33.3,50.8 33.1,50.7 33,50.7 32.8,50.7 32.7,50.7 32.5,50.6 32.4,50.6 32.2,50.6 32.1,50.5 31.9,50.5 31.8,50.4 31.6,50.4 31.5,50.4 31.3,50.3 31.2,50.3 31,50.2 30.9,50.1 30.7,50.1 30.6,50 30.5,50 30.3,49.9 30.2,49.8 30.1,49.7 29.9,49.7 29.8,49.6 29.7,49.5 29.5,49.4 29.4,49.4 29.3,49.3 29.1,49.2 29,49.1 28.9,49 28.8,48.9 28.7,48.8 28.5,48.7 28.4,48.6 28.3,48.5 28.2,48.4 28.1,48.3 28,48.2 27.9,48.1 27.8,48 27.7,47.8 27.6,47.7 27.5,47.6 27.4,47.5 27.3,47.4 27.2,47.2 27.1,47.1 27,47</coordinates></LineString></lineStringMember></MultiLineString>" ) );
13874 : 1 : QString res = elemToString( exportC.asGml2( doc, 1 ) );
13875 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
13876 : 2 : QString expectedGML2empty( QStringLiteral( "<MultiLineString xmlns=\"gml\"/>" ) );
13877 : 3 : QGSCOMPAREGML( elemToString( QgsMultiCurve().asGml2( doc ) ), expectedGML2empty );
13878 : :
13879 : : //as GML3
13880 : 2 : QString expectedSimpleGML3( QStringLiteral( "<MultiCurve xmlns=\"gml\"><curveMember xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">7 17 3 13 7 11</posList></ArcString></segments></Curve></curveMember><curveMember xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">27 37 43 43 27 47</posList></ArcString></segments></Curve></curveMember></MultiCurve>" ) );
13881 : 1 : res = elemToString( exportC.asGml3( doc ) );
13882 : 1 : QCOMPARE( res, expectedSimpleGML3 );
13883 : 2 : QString expectedGML3empty( QStringLiteral( "<MultiCurve xmlns=\"gml\"/>" ) );
13884 : 3 : QGSCOMPAREGML( elemToString( QgsMultiCurve().asGml3( doc ) ), expectedGML3empty );
13885 : :
13886 : : // as JSON
13887 : 1 : QString expectedSimpleJson( "{\"coordinates\":[[[7.0,17.0],[6.9,17.0],[6.9,17.0],[6.8,17.0],[6.8,17.1],[6.7,17.1],[6.7,17.1],[6.6,17.1],[6.6,17.1],[6.5,17.1],[6.5,17.1],[6.4,17.1],[6.4,17.1],[6.3,17.1],[6.2,17.2],[6.2,17.2],[6.1,17.2],[6.1,17.2],[6.0,17.2],[6.0,17.2],[5.9,17.2],[5.9,17.2],[5.8,17.2],[5.7,17.2],[5.7,17.1],[5.6,17.1],[5.6,17.1],[5.5,17.1],[5.5,17.1],[5.4,17.1],[5.4,17.1],[5.3,17.1],[5.3,17.1],[5.2,17.1],[5.2,17.0],[5.1,17.0],[5.0,17.0],[5.0,17.0],[4.9,17.0],[4.9,17.0],[4.8,16.9],[4.8,16.9],[4.7,16.9],[4.7,16.9],[4.6,16.9],[4.6,16.8],[4.5,16.8],[4.5,16.8],[4.4,16.8],[4.4,16.7],[4.3,16.7],[4.3,16.7],[4.3,16.6],[4.2,16.6],[4.2,16.6],[4.1,16.5],[4.1,16.5],[4.0,16.5],[4.0,16.4],[3.9,16.4],[3.9,16.4],[3.9,16.3],[3.8,16.3],[3.8,16.3],[3.7,16.2],[3.7,16.2],[3.7,16.1],[3.6,16.1],[3.6,16.1],[3.6,16.0],[3.5,16.0],[3.5,15.9],[3.5,15.9],[3.4,15.8],[3.4,15.8],[3.4,15.7],[3.3,15.7],[3.3,15.7],[3.3,15.6],[3.2,15.6],[3.2,15.5],[3.2,15.5],[3.2,15.4],[3.1,15.4],[3.1,15.3],[3.1,15.3],[3.1,15.2],[3.1,15.2],[3.0,15.1],[3.0,15.1],[3.0,15.0],[3.0,15.0],[3.0,14.9],[3.0,14.8],[2.9,14.8],[2.9,14.7],[2.9,14.7],[2.9,14.6],[2.9,14.6],[2.9,14.5],[2.9,14.5],[2.9,14.4],[2.9,14.4],[2.9,14.3],[2.8,14.2],[2.8,14.2],[2.8,14.1],[2.8,14.1],[2.8,14.0],[2.8,14.0],[2.8,13.9],[2.8,13.9],[2.8,13.8],[2.8,13.8],[2.9,13.7],[2.9,13.6],[2.9,13.6],[2.9,13.5],[2.9,13.5],[2.9,13.4],[2.9,13.4],[2.9,13.3],[2.9,13.3],[2.9,13.2],[3.0,13.2],[3.0,13.1],[3.0,13.0],[3.0,13.0],[3.0,12.9],[3.0,12.9],[3.1,12.8],[3.1,12.8],[3.1,12.7],[3.1,12.7],[3.1,12.6],[3.2,12.6],[3.2,12.5],[3.2,12.5],[3.2,12.4],[3.3,12.4],[3.3,12.3],[3.3,12.3],[3.4,12.3],[3.4,12.2],[3.4,12.2],[3.5,12.1],[3.5,12.1],[3.5,12.0],[3.6,12.0],[3.6,11.9],[3.6,11.9],[3.7,11.9],[3.7,11.8],[3.7,11.8],[3.8,11.7],[3.8,11.7],[3.9,11.7],[3.9,11.6],[3.9,11.6],[4.0,11.6],[4.0,11.5],[4.1,11.5],[4.1,11.5],[4.2,11.4],[4.2,11.4],[4.3,11.4],[4.3,11.3],[4.3,11.3],[4.4,11.3],[4.4,11.2],[4.5,11.2],[4.5,11.2],[4.6,11.2],[4.6,11.1],[4.7,11.1],[4.7,11.1],[4.8,11.1],[4.8,11.1],[4.9,11.0],[4.9,11.0],[5.0,11.0],[5.0,11.0],[5.1,11.0],[5.2,11.0],[5.2,10.9],[5.3,10.9],[5.3,10.9],[5.4,10.9],[5.4,10.9],[5.5,10.9],[5.5,10.9],[5.6,10.9],[5.6,10.9],[5.7,10.9],[5.7,10.8],[5.8,10.8],[5.9,10.8],[5.9,10.8],[6.0,10.8],[6.0,10.8],[6.1,10.8],[6.1,10.8],[6.2,10.8],[6.2,10.8],[6.3,10.9],[6.4,10.9],[6.4,10.9],[6.5,10.9],[6.5,10.9],[6.6,10.9],[6.6,10.9],[6.7,10.9],[6.7,10.9],[6.8,10.9],[6.8,11.0],[6.9,11.0],[6.9,11.0],[7.0,11.0]],[[27.0,37.0],[27.1,36.9],[27.2,36.8],[27.3,36.6],[27.4,36.5],[27.5,36.4],[27.6,36.3],[27.7,36.2],[27.8,36.0],[27.9,35.9],[28.0,35.8],[28.1,35.7],[28.2,35.6],[28.3,35.5],[28.4,35.4],[28.5,35.3],[28.7,35.2],[28.8,35.1],[28.9,35.0],[29.0,34.9],[29.1,34.8],[29.3,34.7],[29.4,34.6],[29.5,34.6],[29.7,34.5],[29.8,34.4],[29.9,34.3],[30.1,34.3],[30.2,34.2],[30.3,34.1],[30.5,34.0],[30.6,34.0],[30.7,33.9],[30.9,33.9],[31.0,33.8],[31.2,33.7],[31.3,33.7],[31.5,33.6],[31.6,33.6],[31.8,33.6],[31.9,33.5],[32.1,33.5],[32.2,33.4],[32.4,33.4],[32.5,33.4],[32.7,33.3],[32.8,33.3],[33.0,33.3],[33.1,33.3],[33.3,33.2],[33.4,33.2],[33.6,33.2],[33.7,33.2],[33.9,33.2],[34.0,33.2],[34.2,33.2],[34.3,33.2],[34.5,33.2],[34.6,33.2],[34.8,33.2],[34.9,33.2],[35.1,33.2],[35.3,33.3],[35.4,33.3],[35.6,33.3],[35.7,33.3],[35.9,33.3],[36.0,33.4],[36.2,33.4],[36.3,33.4],[36.5,33.5],[36.6,33.5],[36.8,33.6],[36.9,33.6],[37.1,33.7],[37.2,33.7],[37.3,33.8],[37.5,33.8],[37.6,33.9],[37.8,33.9],[37.9,34.0],[38.0,34.1],[38.2,34.1],[38.3,34.2],[38.5,34.3],[38.6,34.3],[38.7,34.4],[38.9,34.5],[39.0,34.6],[39.1,34.7],[39.2,34.7],[39.4,34.8],[39.5,34.9],[39.6,35.0],[39.7,35.1],[39.9,35.2],[40.0,35.3],[40.1,35.4],[40.2,35.5],[40.3,35.6],[40.4,35.7],[40.5,35.8],[40.6,35.9],[40.7,36.1],[40.8,36.2],[40.9,36.3],[41.0,36.4],[41.1,36.5],[41.2,36.6],[41.3,36.8],[41.4,36.9],[41.5,37.0],[41.6,37.1],[41.7,37.3],[41.8,37.4],[41.8,37.5],[41.9,37.7],[42.0,37.8],[42.1,37.9],[42.1,38.1],[42.2,38.2],[42.3,38.3],[42.3,38.5],[42.4,38.6],[42.4,38.8],[42.5,38.9],[42.6,39.1],[42.6,39.2],[42.6,39.4],[42.7,39.5],[42.7,39.6],[42.8,39.8],[42.8,39.9],[42.8,40.1],[42.9,40.2],[42.9,40.4],[42.9,40.5],[43.0,40.7],[43.0,40.9],[43.0,41.0],[43.0,41.2],[43.0,41.3],[43.0,41.5],[43.0,41.6],[43.1,41.8],[43.1,41.9],[43.1,42.1],[43.1,42.2],[43.0,42.4],[43.0,42.5],[43.0,42.7],[43.0,42.8],[43.0,43.0],[43.0,43.1],[43.0,43.3],[42.9,43.5],[42.9,43.6],[42.9,43.8],[42.8,43.9],[42.8,44.1],[42.8,44.2],[42.7,44.4],[42.7,44.5],[42.6,44.6],[42.6,44.8],[42.6,44.9],[42.5,45.1],[42.4,45.2],[42.4,45.4],[42.3,45.5],[42.3,45.7],[42.2,45.8],[42.1,45.9],[42.1,46.1],[42.0,46.2],[41.9,46.3],[41.8,46.5],[41.8,46.6],[41.7,46.7],[41.6,46.9],[41.5,47.0],[41.4,47.1],[41.3,47.2],[41.2,47.4],[41.1,47.5],[41.0,47.6],[40.9,47.7],[40.8,47.8],[40.7,47.9],[40.6,48.1],[40.5,48.2],[40.4,48.3],[40.3,48.4],[40.2,48.5],[40.1,48.6],[40.0,48.7],[39.9,48.8],[39.7,48.9],[39.6,49.0],[39.5,49.1],[39.4,49.2],[39.2,49.3],[39.1,49.3],[39.0,49.4],[38.9,49.5],[38.7,49.6],[38.6,49.7],[38.5,49.7],[38.3,49.8],[38.2,49.9],[38.0,49.9],[37.9,50.0],[37.8,50.1],[37.6,50.1],[37.5,50.2],[37.3,50.2],[37.2,50.3],[37.1,50.3],[36.9,50.4],[36.8,50.4],[36.6,50.5],[36.5,50.5],[36.3,50.6],[36.2,50.6],[36.0,50.6],[35.9,50.7],[35.7,50.7],[35.6,50.7],[35.4,50.7],[35.3,50.7],[35.1,50.8],[34.9,50.8],[34.8,50.8],[34.6,50.8],[34.5,50.8],[34.3,50.8],[34.2,50.8],[34.0,50.8],[33.9,50.8],[33.7,50.8],[33.6,50.8],[33.4,50.8],[33.3,50.8],[33.1,50.7],[33.0,50.7],[32.8,50.7],[32.7,50.7],[32.5,50.6],[32.4,50.6],[32.2,50.6],[32.1,50.5],[31.9,50.5],[31.8,50.4],[31.6,50.4],[31.5,50.4],[31.3,50.3],[31.2,50.3],[31.0,50.2],[30.9,50.1],[30.7,50.1],[30.6,50.0],[30.5,50.0],[30.3,49.9],[30.2,49.8],[30.1,49.7],[29.9,49.7],[29.8,49.6],[29.7,49.5],[29.5,49.4],[29.4,49.4],[29.3,49.3],[29.1,49.2],[29.0,49.1],[28.9,49.0],[28.8,48.9],[28.7,48.8],[28.5,48.7],[28.4,48.6],[28.3,48.5],[28.2,48.4],[28.1,48.3],[28.0,48.2],[27.9,48.1],[27.8,48.0],[27.7,47.8],[27.6,47.7],[27.5,47.6],[27.4,47.5],[27.3,47.4],[27.2,47.2],[27.1,47.1],[27.0,47.0]]],\"type\":\"MultiLineString\"}" );
13888 : 1 : res = exportC.asJson( 1 );
13889 : 1 : QCOMPARE( res, expectedSimpleJson );
13890 : :
13891 : 1 : QgsMultiCurve exportFloat;
13892 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7 / 3.0, 17 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 3 / 5.0, 13 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 7 / 3.0, 11 / 3.0 ) ) ;
13893 : 1 : exportFloat.addGeometry( part.clone() );
13894 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27 / 3.0, 37 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 43 / 41.0, 43 / 42.0 ) << QgsPoint( QgsWkbTypes::Point, 27 / 3.0, 1 / 3.0 ) ) ;
13895 : 1 : exportFloat.addGeometry( part.clone() );
13896 : :
13897 : 2 : QString expectedJsonPrec3( QStringLiteral( "{\"coordinates\":[[[2.333,5.667],[2.316,5.677],[2.298,5.687],[2.28,5.697],[2.262,5.707],[2.244,5.716],[2.226,5.725],[2.207,5.734],[2.188,5.742],[2.17,5.75],[2.151,5.757],[2.131,5.765],[2.112,5.772],[2.093,5.778],[2.074,5.785],[2.054,5.79],[2.034,5.796],[2.015,5.801],[1.995,5.806],[1.975,5.811],[1.955,5.815],[1.935,5.819],[1.915,5.822],[1.894,5.826],[1.874,5.828],[1.854,5.831],[1.834,5.833],[1.813,5.835],[1.793,5.836],[1.773,5.837],[1.752,5.838],[1.732,5.838],[1.711,5.838],[1.691,5.838],[1.67,5.837],[1.65,5.836],[1.63,5.834],[1.609,5.833],[1.589,5.83],[1.569,5.828],[1.548,5.825],[1.528,5.822],[1.508,5.818],[1.488,5.814],[1.468,5.81],[1.448,5.805],[1.428,5.801],[1.409,5.795],[1.389,5.79],[1.37,5.784],[1.35,5.777],[1.331,5.771],[1.312,5.764],[1.293,5.756],[1.274,5.749],[1.255,5.741],[1.236,5.732],[1.218,5.724],[1.199,5.715],[1.181,5.705],[1.163,5.696],[1.145,5.686],[1.128,5.676],[1.11,5.665],[1.093,5.654],[1.076,5.643],[1.059,5.632],[1.042,5.62],[1.025,5.608],[1.009,5.596],[0.993,5.583],[0.977,5.57],[0.962,5.557],[0.946,5.543],[0.931,5.53],[0.916,5.516],[0.901,5.502],[0.887,5.487],[0.873,5.473],[0.859,5.458],[0.845,5.442],[0.832,5.427],[0.819,5.411],[0.806,5.395],[0.793,5.379],[0.781,5.363],[0.769,5.346],[0.757,5.33],[0.746,5.313],[0.735,5.296],[0.724,5.278],[0.713,5.261],[0.703,5.243],[0.693,5.225],[0.684,5.207],[0.674,5.189],[0.666,5.171],[0.657,5.152],[0.649,5.133],[0.641,5.115],[0.633,5.096],[0.626,5.077],[0.619,5.057],[0.612,5.038],[0.606,5.019],[0.6,4.999],[0.594,4.979],[0.589,4.96],[0.584,4.94],[0.579,4.92],[0.575,4.9],[0.571,4.88],[0.568,4.86],[0.564,4.84],[0.562,4.819],[0.559,4.799],[0.557,4.779],[0.555,4.759],[0.554,4.738],[0.553,4.718],[0.552,4.697],[0.552,4.677],[0.552,4.656],[0.552,4.636],[0.553,4.616],[0.554,4.595],[0.555,4.575],[0.557,4.554],[0.559,4.534],[0.562,4.514],[0.564,4.494],[0.568,4.473],[0.571,4.453],[0.575,4.433],[0.579,4.413],[0.584,4.393],[0.589,4.374],[0.594,4.354],[0.6,4.334],[0.606,4.315],[0.612,4.295],[0.619,4.276],[0.626,4.257],[0.633,4.238],[0.641,4.219],[0.649,4.2],[0.657,4.181],[0.666,4.163],[0.674,4.144],[0.684,4.126],[0.693,4.108],[0.703,4.09],[0.713,4.073],[0.724,4.055],[0.735,4.038],[0.746,4.021],[0.757,4.004],[0.769,3.987],[0.781,3.97],[0.793,3.954],[0.806,3.938],[0.819,3.922],[0.832,3.906],[0.845,3.891],[0.859,3.876],[0.873,3.861],[0.887,3.846],[0.901,3.832],[0.916,3.817],[0.931,3.804],[0.946,3.79],[0.962,3.776],[0.977,3.763],[0.993,3.75],[1.009,3.738],[1.025,3.726],[1.042,3.713],[1.059,3.702],[1.076,3.69],[1.093,3.679],[1.11,3.668],[1.128,3.658],[1.145,3.648],[1.163,3.638],[1.181,3.628],[1.199,3.619],[1.218,3.61],[1.236,3.601],[1.255,3.593],[1.274,3.585],[1.293,3.577],[1.312,3.57],[1.331,3.563],[1.35,3.556],[1.37,3.55],[1.389,3.544],[1.409,3.538],[1.428,3.533],[1.448,3.528],[1.468,3.523],[1.488,3.519],[1.508,3.515],[1.528,3.511],[1.548,3.508],[1.569,3.505],[1.589,3.503],[1.609,3.501],[1.63,3.499],[1.65,3.497],[1.67,3.496],[1.691,3.496],[1.711,3.495],[1.732,3.495],[1.752,3.496],[1.773,3.496],[1.793,3.497],[1.813,3.499],[1.834,3.5],[1.854,3.503],[1.874,3.505],[1.894,3.508],[1.915,3.511],[1.935,3.514],[1.955,3.518],[1.975,3.523],[1.995,3.527],[2.015,3.532],[2.034,3.537],[2.054,3.543],[2.074,3.549],[2.093,3.555],[2.112,3.562],[2.131,3.569],[2.151,3.576],[2.17,3.584],[2.188,3.592],[2.207,3.6],[2.226,3.608],[2.244,3.617],[2.262,3.627],[2.28,3.636],[2.298,3.646],[2.316,3.656],[2.333,3.667]],[[9.0,4.111],[8.966,4.178],[8.932,4.244],[8.896,4.309],[8.859,4.374],[8.821,4.438],[8.782,4.502],[8.742,4.565],[8.7,4.627],[8.658,4.688],[8.614,4.749],[8.57,4.809],[8.524,4.868],[8.477,4.926],[8.43,4.983],[8.381,5.04],[8.331,5.096],[8.281,5.151],[8.229,5.205],[8.177,5.258],[8.124,5.31],[8.069,5.361],[8.014,5.411],[7.958,5.461],[7.901,5.509],[7.844,5.556],[7.785,5.603],[7.726,5.648],[7.666,5.692],[7.605,5.735],[7.543,5.777],[7.481,5.818],[7.418,5.858],[7.354,5.897],[7.29,5.935],[7.225,5.971],[7.159,6.007],[7.093,6.041],[7.026,6.074],[6.958,6.106],[6.89,6.137],[6.822,6.167],[6.753,6.195],[6.683,6.222],[6.613,6.248],[6.543,6.273],[6.472,6.296],[6.401,6.319],[6.329,6.34],[6.257,6.36],[6.185,6.378],[6.112,6.395],[6.04,6.411],[5.966,6.426],[5.893,6.44],[5.819,6.452],[5.746,6.463],[5.672,6.472],[5.597,6.48],[5.523,6.487],[5.449,6.493],[5.374,6.498],[5.3,6.501],[5.225,6.503],[5.15,6.503],[5.076,6.502],[5.001,6.5],[4.927,6.497],[4.852,6.492],[4.778,6.486],[4.704,6.479],[4.629,6.47],[4.555,6.46],[4.482,6.449],[4.408,6.437],[4.335,6.423],[4.262,6.408],[4.189,6.392],[4.116,6.374],[4.044,6.355],[3.972,6.335],[3.901,6.314],[3.83,6.292],[3.759,6.268],[3.688,6.243],[3.619,6.217],[3.549,6.189],[3.48,6.16],[3.412,6.131],[3.344,6.1],[3.277,6.067],[3.21,6.034],[3.144,5.999],[3.078,5.964],[3.013,5.927],[2.949,5.889],[2.886,5.85],[2.823,5.81],[2.761,5.768],[2.699,5.726],[2.638,5.683],[2.578,5.638],[2.519,5.593],[2.461,5.546],[2.403,5.499],[2.347,5.45],[2.291,5.401],[2.236,5.35],[2.182,5.299],[2.129,5.246],[2.076,5.193],[2.025,5.139],[1.975,5.084],[1.925,5.028],[1.877,4.971],[1.829,4.914],[1.783,4.855],[1.738,4.796],[1.693,4.736],[1.65,4.675],[1.608,4.614],[1.567,4.551],[1.527,4.488],[1.488,4.425],[1.45,4.36],[1.413,4.295],[1.378,4.23],[1.343,4.164],[1.31,4.097],[1.278,4.029],[1.247,3.961],[1.217,3.893],[1.189,3.824],[1.161,3.755],[1.135,3.685],[1.11,3.614],[1.087,3.544],[1.064,3.472],[1.043,3.401],[1.023,3.329],[1.004,3.257],[0.987,3.184],[0.971,3.111],[0.956,3.038],[0.942,2.965],[0.93,2.891],[0.919,2.817],[0.909,2.743],[0.901,2.669],[0.894,2.595],[0.888,2.52],[0.883,2.446],[0.88,2.371],[0.878,2.297],[0.878,2.222],[0.878,2.148],[0.88,2.073],[0.883,1.998],[0.888,1.924],[0.894,1.85],[0.901,1.775],[0.909,1.701],[0.919,1.627],[0.93,1.553],[0.942,1.48],[0.956,1.406],[0.971,1.333],[0.987,1.26],[1.004,1.188],[1.023,1.116],[1.043,1.044],[1.064,0.972],[1.087,0.901],[1.11,0.83],[1.135,0.76],[1.161,0.69],[1.189,0.62],[1.217,0.551],[1.247,0.483],[1.278,0.415],[1.31,0.348],[1.343,0.281],[1.378,0.215],[1.413,0.149],[1.45,0.084],[1.488,0.02],[1.527,-0.044],[1.567,-0.107],[1.608,-0.169],[1.65,-0.231],[1.693,-0.291],[1.738,-0.351],[1.783,-0.411],[1.829,-0.469],[1.877,-0.527],[1.925,-0.584],[1.975,-0.639],[2.025,-0.694],[2.076,-0.749],[2.129,-0.802],[2.182,-0.854],[2.236,-0.906],[2.291,-0.956],[2.347,-1.006],[2.403,-1.054],[2.461,-1.102],[2.519,-1.148],[2.578,-1.194],[2.638,-1.238],[2.699,-1.282],[2.761,-1.324],[2.823,-1.365],[2.886,-1.405],[2.949,-1.444],[3.013,-1.482],[3.078,-1.519],[3.144,-1.555],[3.21,-1.589],[3.277,-1.623],[3.344,-1.655],[3.412,-1.686],[3.48,-1.716],[3.549,-1.745],[3.619,-1.772],[3.688,-1.798],[3.759,-1.823],[3.83,-1.847],[3.901,-1.87],[3.972,-1.891],[4.044,-1.911],[4.116,-1.93],[4.189,-1.947],[4.262,-1.964],[4.335,-1.979],[4.408,-1.992],[4.482,-2.005],[4.555,-2.016],[4.629,-2.026],[4.704,-2.034],[4.778,-2.042],[4.852,-2.048],[4.927,-2.052],[5.001,-2.056],[5.076,-2.058],[5.15,-2.059],[5.225,-2.058],[5.3,-2.056],[5.374,-2.053],[5.449,-2.049],[5.523,-2.043],[5.597,-2.036],[5.672,-2.028],[5.746,-2.018],[5.819,-2.007],[5.893,-1.995],[5.966,-1.982],[6.04,-1.967],[6.112,-1.951],[6.185,-1.934],[6.257,-1.915],[6.329,-1.895],[6.401,-1.874],[6.472,-1.852],[6.543,-1.829],[6.613,-1.804],[6.683,-1.778],[6.753,-1.751],[6.822,-1.722],[6.89,-1.693],[6.958,-1.662],[7.026,-1.63],[7.093,-1.597],[7.159,-1.562],[7.225,-1.527],[7.29,-1.49],[7.354,-1.453],[7.418,-1.414],[7.481,-1.374],[7.543,-1.333],[7.605,-1.291],[7.666,-1.248],[7.726,-1.203],[7.785,-1.158],[7.844,-1.112],[7.901,-1.065],[7.958,-1.016],[8.014,-0.967],[8.069,-0.917],[8.124,-0.865],[8.177,-0.813],[8.229,-0.76],[8.281,-0.706],[8.331,-0.651],[8.381,-0.596],[8.43,-0.539],[8.477,-0.482],[8.524,-0.423],[8.57,-0.364],[8.614,-0.304],[8.658,-0.244],[8.7,-0.182],[8.742,-0.12],[8.782,-0.057],[8.821,0.006],[8.859,0.07],[8.896,0.135],[8.932,0.201],[8.966,0.267],[9.0,0.333]]],\"type\":\"MultiLineString\"}" ) );
13898 : 1 : res = exportFloat.asJson( 3 );
13899 : 1 : QCOMPARE( res, expectedJsonPrec3 );
13900 : :
13901 : : // as GML2
13902 : 2 : QString expectedGML2prec3( QStringLiteral( "<MultiLineString xmlns=\"gml\"><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">2.333,5.667 2.316,5.677 2.298,5.687 2.28,5.697 2.262,5.707 2.244,5.716 2.226,5.725 2.207,5.734 2.188,5.742 2.17,5.75 2.151,5.757 2.131,5.765 2.112,5.772 2.093,5.778 2.074,5.785 2.054,5.79 2.034,5.796 2.015,5.801 1.995,5.806 1.975,5.811 1.955,5.815 1.935,5.819 1.915,5.822 1.894,5.826 1.874,5.828 1.854,5.831 1.834,5.833 1.813,5.835 1.793,5.836 1.773,5.837 1.752,5.838 1.732,5.838 1.711,5.838 1.691,5.838 1.67,5.837 1.65,5.836 1.63,5.834 1.609,5.833 1.589,5.83 1.569,5.828 1.548,5.825 1.528,5.822 1.508,5.818 1.488,5.814 1.468,5.81 1.448,5.805 1.428,5.801 1.409,5.795 1.389,5.79 1.37,5.784 1.35,5.777 1.331,5.771 1.312,5.764 1.293,5.756 1.274,5.749 1.255,5.741 1.236,5.732 1.218,5.724 1.199,5.715 1.181,5.705 1.163,5.696 1.145,5.686 1.128,5.676 1.11,5.665 1.093,5.654 1.076,5.643 1.059,5.632 1.042,5.62 1.025,5.608 1.009,5.596 0.993,5.583 0.977,5.57 0.962,5.557 0.946,5.543 0.931,5.53 0.916,5.516 0.901,5.502 0.887,5.487 0.873,5.473 0.859,5.458 0.845,5.442 0.832,5.427 0.819,5.411 0.806,5.395 0.793,5.379 0.781,5.363 0.769,5.346 0.757,5.33 0.746,5.313 0.735,5.296 0.724,5.278 0.713,5.261 0.703,5.243 0.693,5.225 0.684,5.207 0.674,5.189 0.666,5.171 0.657,5.152 0.649,5.133 0.641,5.115 0.633,5.096 0.626,5.077 0.619,5.057 0.612,5.038 0.606,5.019 0.6,4.999 0.594,4.979 0.589,4.96 0.584,4.94 0.579,4.92 0.575,4.9 0.571,4.88 0.568,4.86 0.564,4.84 0.562,4.819 0.559,4.799 0.557,4.779 0.555,4.759 0.554,4.738 0.553,4.718 0.552,4.697 0.552,4.677 0.552,4.656 0.552,4.636 0.553,4.616 0.554,4.595 0.555,4.575 0.557,4.554 0.559,4.534 0.562,4.514 0.564,4.494 0.568,4.473 0.571,4.453 0.575,4.433 0.579,4.413 0.584,4.393 0.589,4.374 0.594,4.354 0.6,4.334 0.606,4.315 0.612,4.295 0.619,4.276 0.626,4.257 0.633,4.238 0.641,4.219 0.649,4.2 0.657,4.181 0.666,4.163 0.674,4.144 0.684,4.126 0.693,4.108 0.703,4.09 0.713,4.073 0.724,4.055 0.735,4.038 0.746,4.021 0.757,4.004 0.769,3.987 0.781,3.97 0.793,3.954 0.806,3.938 0.819,3.922 0.832,3.906 0.845,3.891 0.859,3.876 0.873,3.861 0.887,3.846 0.901,3.832 0.916,3.817 0.931,3.804 0.946,3.79 0.962,3.776 0.977,3.763 0.993,3.75 1.009,3.738 1.025,3.726 1.042,3.713 1.059,3.702 1.076,3.69 1.093,3.679 1.11,3.668 1.128,3.658 1.145,3.648 1.163,3.638 1.181,3.628 1.199,3.619 1.218,3.61 1.236,3.601 1.255,3.593 1.274,3.585 1.293,3.577 1.312,3.57 1.331,3.563 1.35,3.556 1.37,3.55 1.389,3.544 1.409,3.538 1.428,3.533 1.448,3.528 1.468,3.523 1.488,3.519 1.508,3.515 1.528,3.511 1.548,3.508 1.569,3.505 1.589,3.503 1.609,3.501 1.63,3.499 1.65,3.497 1.67,3.496 1.691,3.496 1.711,3.495 1.732,3.495 1.752,3.496 1.773,3.496 1.793,3.497 1.813,3.499 1.834,3.5 1.854,3.503 1.874,3.505 1.894,3.508 1.915,3.511 1.935,3.514 1.955,3.518 1.975,3.523 1.995,3.527 2.015,3.532 2.034,3.537 2.054,3.543 2.074,3.549 2.093,3.555 2.112,3.562 2.131,3.569 2.151,3.576 2.17,3.584 2.188,3.592 2.207,3.6 2.226,3.608 2.244,3.617 2.262,3.627 2.28,3.636 2.298,3.646 2.316,3.656 2.333,3.667</coordinates></LineString></lineStringMember><lineStringMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">9,4.111 8.966,4.178 8.932,4.244 8.896,4.309 8.859,4.374 8.821,4.438 8.782,4.502 8.742,4.565 8.7,4.627 8.658,4.688 8.614,4.749 8.57,4.809 8.524,4.868 8.477,4.926 8.43,4.983 8.381,5.04 8.331,5.096 8.281,5.151 8.229,5.205 8.177,5.258 8.124,5.31 8.069,5.361 8.014,5.411 7.958,5.461 7.901,5.509 7.844,5.556 7.785,5.603 7.726,5.648 7.666,5.692 7.605,5.735 7.543,5.777 7.481,5.818 7.418,5.858 7.354,5.897 7.29,5.935 7.225,5.971 7.159,6.007 7.093,6.041 7.026,6.074 6.958,6.106 6.89,6.137 6.822,6.167 6.753,6.195 6.683,6.222 6.613,6.248 6.543,6.273 6.472,6.296 6.401,6.319 6.329,6.34 6.257,6.36 6.185,6.378 6.112,6.395 6.04,6.411 5.966,6.426 5.893,6.44 5.819,6.452 5.746,6.463 5.672,6.472 5.597,6.48 5.523,6.487 5.449,6.493 5.374,6.498 5.3,6.501 5.225,6.503 5.15,6.503 5.076,6.502 5.001,6.5 4.927,6.497 4.852,6.492 4.778,6.486 4.704,6.479 4.629,6.47 4.555,6.46 4.482,6.449 4.408,6.437 4.335,6.423 4.262,6.408 4.189,6.392 4.116,6.374 4.044,6.355 3.972,6.335 3.901,6.314 3.83,6.292 3.759,6.268 3.688,6.243 3.619,6.217 3.549,6.189 3.48,6.16 3.412,6.131 3.344,6.1 3.277,6.067 3.21,6.034 3.144,5.999 3.078,5.964 3.013,5.927 2.949,5.889 2.886,5.85 2.823,5.81 2.761,5.768 2.699,5.726 2.638,5.683 2.578,5.638 2.519,5.593 2.461,5.546 2.403,5.499 2.347,5.45 2.291,5.401 2.236,5.35 2.182,5.299 2.129,5.246 2.076,5.193 2.025,5.139 1.975,5.084 1.925,5.028 1.877,4.971 1.829,4.914 1.783,4.855 1.738,4.796 1.693,4.736 1.65,4.675 1.608,4.614 1.567,4.551 1.527,4.488 1.488,4.425 1.45,4.36 1.413,4.295 1.378,4.23 1.343,4.164 1.31,4.097 1.278,4.029 1.247,3.961 1.217,3.893 1.189,3.824 1.161,3.755 1.135,3.685 1.11,3.614 1.087,3.544 1.064,3.472 1.043,3.401 1.023,3.329 1.004,3.257 0.987,3.184 0.971,3.111 0.956,3.038 0.942,2.965 0.93,2.891 0.919,2.817 0.909,2.743 0.901,2.669 0.894,2.595 0.888,2.52 0.883,2.446 0.88,2.371 0.878,2.297 0.878,2.222 0.878,2.148 0.88,2.073 0.883,1.998 0.888,1.924 0.894,1.85 0.901,1.775 0.909,1.701 0.919,1.627 0.93,1.553 0.942,1.48 0.956,1.406 0.971,1.333 0.987,1.26 1.004,1.188 1.023,1.116 1.043,1.044 1.064,0.972 1.087,0.901 1.11,0.83 1.135,0.76 1.161,0.69 1.189,0.62 1.217,0.551 1.247,0.483 1.278,0.415 1.31,0.348 1.343,0.281 1.378,0.215 1.413,0.149 1.45,0.084 1.488,0.02 1.527,-0.044 1.567,-0.107 1.608,-0.169 1.65,-0.231 1.693,-0.291 1.738,-0.351 1.783,-0.411 1.829,-0.469 1.877,-0.527 1.925,-0.584 1.975,-0.639 2.025,-0.694 2.076,-0.749 2.129,-0.802 2.182,-0.854 2.236,-0.906 2.291,-0.956 2.347,-1.006 2.403,-1.054 2.461,-1.102 2.519,-1.148 2.578,-1.194 2.638,-1.238 2.699,-1.282 2.761,-1.324 2.823,-1.365 2.886,-1.405 2.949,-1.444 3.013,-1.482 3.078,-1.519 3.144,-1.555 3.21,-1.589 3.277,-1.623 3.344,-1.655 3.412,-1.686 3.48,-1.716 3.549,-1.745 3.619,-1.772 3.688,-1.798 3.759,-1.823 3.83,-1.847 3.901,-1.87 3.972,-1.891 4.044,-1.911 4.116,-1.93 4.189,-1.947 4.262,-1.964 4.335,-1.979 4.408,-1.992 4.482,-2.005 4.555,-2.016 4.629,-2.026 4.704,-2.034 4.778,-2.042 4.852,-2.048 4.927,-2.052 5.001,-2.056 5.076,-2.058 5.15,-2.059 5.225,-2.058 5.3,-2.056 5.374,-2.053 5.449,-2.049 5.523,-2.043 5.597,-2.036 5.672,-2.028 5.746,-2.018 5.819,-2.007 5.893,-1.995 5.966,-1.982 6.04,-1.967 6.112,-1.951 6.185,-1.934 6.257,-1.915 6.329,-1.895 6.401,-1.874 6.472,-1.852 6.543,-1.829 6.613,-1.804 6.683,-1.778 6.753,-1.751 6.822,-1.722 6.89,-1.693 6.958,-1.662 7.026,-1.63 7.093,-1.597 7.159,-1.562 7.225,-1.527 7.29,-1.49 7.354,-1.453 7.418,-1.414 7.481,-1.374 7.543,-1.333 7.605,-1.291 7.666,-1.248 7.726,-1.203 7.785,-1.158 7.844,-1.112 7.901,-1.065 7.958,-1.016 8.014,-0.967 8.069,-0.917 8.124,-0.865 8.177,-0.813 8.229,-0.76 8.281,-0.706 8.331,-0.651 8.381,-0.596 8.43,-0.539 8.477,-0.482 8.524,-0.423 8.57,-0.364 8.614,-0.304 8.658,-0.244 8.7,-0.182 8.742,-0.12 8.782,-0.057 8.821,0.006 8.859,0.07 8.896,0.135 8.932,0.201 8.966,0.267 9,0.333</coordinates></LineString></lineStringMember></MultiLineString>" ) );
13903 : 1 : res = elemToString( exportFloat.asGml2( doc, 3 ) );
13904 : 3 : QGSCOMPAREGML( res, expectedGML2prec3 );
13905 : :
13906 : : //as GML3
13907 : 2 : QString expectedGML3prec3( QStringLiteral( "<MultiCurve xmlns=\"gml\"><curveMember xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">2.333 5.667 0.6 4.333 2.333 3.667</posList></ArcString></segments></Curve></curveMember><curveMember xmlns=\"gml\"><Curve xmlns=\"gml\"><segments xmlns=\"gml\"><ArcString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">9 4.111 1.049 1.024 9 0.333</posList></ArcString></segments></Curve></curveMember></MultiCurve>" ) );
13908 : 1 : res = elemToString( exportFloat.asGml3( doc, 3 ) );
13909 : 1 : QCOMPARE( res, expectedGML3prec3 );
13910 : :
13911 : : //asKML
13912 : 2 : QString expectedKml( QStringLiteral( "<MultiGeometry><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>7,17,0 6.9,17,0 6.9,17,0 6.8,17,0 6.8,17.1,0 6.7,17.1,0 6.7,17.1,0 6.6,17.1,0 6.6,17.1,0 6.5,17.1,0 6.5,17.1,0 6.4,17.1,0 6.4,17.1,0 6.3,17.1,0 6.2,17.2,0 6.2,17.2,0 6.1,17.2,0 6.1,17.2,0 6,17.2,0 6,17.2,0 5.9,17.2,0 5.9,17.2,0 5.8,17.2,0 5.7,17.2,0 5.7,17.1,0 5.6,17.1,0 5.6,17.1,0 5.5,17.1,0 5.5,17.1,0 5.4,17.1,0 5.4,17.1,0 5.3,17.1,0 5.3,17.1,0 5.2,17.1,0 5.2,17,0 5.1,17,0 5,17,0 5,17,0 4.9,17,0 4.9,17,0 4.8,16.9,0 4.8,16.9,0 4.7,16.9,0 4.7,16.9,0 4.6,16.9,0 4.6,16.8,0 4.5,16.8,0 4.5,16.8,0 4.4,16.8,0 4.4,16.7,0 4.3,16.7,0 4.3,16.7,0 4.3,16.6,0 4.2,16.6,0 4.2,16.6,0 4.1,16.5,0 4.1,16.5,0 4,16.5,0 4,16.4,0 3.9,16.4,0 3.9,16.4,0 3.9,16.3,0 3.8,16.3,0 3.8,16.3,0 3.7,16.2,0 3.7,16.2,0 3.7,16.1,0 3.6,16.1,0 3.6,16.1,0 3.6,16,0 3.5,16,0 3.5,15.9,0 3.5,15.9,0 3.4,15.8,0 3.4,15.8,0 3.4,15.7,0 3.3,15.7,0 3.3,15.7,0 3.3,15.6,0 3.2,15.6,0 3.2,15.5,0 3.2,15.5,0 3.2,15.4,0 3.1,15.4,0 3.1,15.3,0 3.1,15.3,0 3.1,15.2,0 3.1,15.2,0 3,15.1,0 3,15.1,0 3,15,0 3,15,0 3,14.9,0 3,14.8,0 2.9,14.8,0 2.9,14.7,0 2.9,14.7,0 2.9,14.6,0 2.9,14.6,0 2.9,14.5,0 2.9,14.5,0 2.9,14.4,0 2.9,14.4,0 2.9,14.3,0 2.8,14.2,0 2.8,14.2,0 2.8,14.1,0 2.8,14.1,0 2.8,14,0 2.8,14,0 2.8,13.9,0 2.8,13.9,0 2.8,13.8,0 2.8,13.8,0 2.9,13.7,0 2.9,13.6,0 2.9,13.6,0 2.9,13.5,0 2.9,13.5,0 2.9,13.4,0 2.9,13.4,0 2.9,13.3,0 2.9,13.3,0 2.9,13.2,0 3,13.2,0 3,13.1,0 3,13,0 3,13,0 3,12.9,0 3,12.9,0 3.1,12.8,0 3.1,12.8,0 3.1,12.7,0 3.1,12.7,0 3.1,12.6,0 3.2,12.6,0 3.2,12.5,0 3.2,12.5,0 3.2,12.4,0 3.3,12.4,0 3.3,12.3,0 3.3,12.3,0 3.4,12.3,0 3.4,12.2,0 3.4,12.2,0 3.5,12.1,0 3.5,12.1,0 3.5,12,0 3.6,12,0 3.6,11.9,0 3.6,11.9,0 3.7,11.9,0 3.7,11.8,0 3.7,11.8,0 3.8,11.7,0 3.8,11.7,0 3.9,11.7,0 3.9,11.6,0 3.9,11.6,0 4,11.6,0 4,11.5,0 4.1,11.5,0 4.1,11.5,0 4.2,11.4,0 4.2,11.4,0 4.3,11.4,0 4.3,11.3,0 4.3,11.3,0 4.4,11.3,0 4.4,11.2,0 4.5,11.2,0 4.5,11.2,0 4.6,11.2,0 4.6,11.1,0 4.7,11.1,0 4.7,11.1,0 4.8,11.1,0 4.8,11.1,0 4.9,11,0 4.9,11,0 5,11,0 5,11,0 5.1,11,0 5.2,11,0 5.2,10.9,0 5.3,10.9,0 5.3,10.9,0 5.4,10.9,0 5.4,10.9,0 5.5,10.9,0 5.5,10.9,0 5.6,10.9,0 5.6,10.9,0 5.7,10.9,0 5.7,10.8,0 5.8,10.8,0 5.9,10.8,0 5.9,10.8,0 6,10.8,0 6,10.8,0 6.1,10.8,0 6.1,10.8,0 6.2,10.8,0 6.2,10.8,0 6.3,10.9,0 6.4,10.9,0 6.4,10.9,0 6.5,10.9,0 6.5,10.9,0 6.6,10.9,0 6.6,10.9,0 6.7,10.9,0 6.7,10.9,0 6.8,10.9,0 6.8,11,0 6.9,11,0 6.9,11,0 7,11,0</coordinates></LineString><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>27,37,0 27.1,36.9,0 27.2,36.8,0 27.3,36.6,0 27.4,36.5,0 27.5,36.4,0 27.6,36.3,0 27.7,36.2,0 27.8,36,0 27.9,35.9,0 28,35.8,0 28.1,35.7,0 28.2,35.6,0 28.3,35.5,0 28.4,35.4,0 28.5,35.3,0 28.7,35.2,0 28.8,35.1,0 28.9,35,0 29,34.9,0 29.1,34.8,0 29.3,34.7,0 29.4,34.6,0 29.5,34.6,0 29.7,34.5,0 29.8,34.4,0 29.9,34.3,0 30.1,34.3,0 30.2,34.2,0 30.3,34.1,0 30.5,34,0 30.6,34,0 30.7,33.9,0 30.9,33.9,0 31,33.8,0 31.2,33.7,0 31.3,33.7,0 31.5,33.6,0 31.6,33.6,0 31.8,33.6,0 31.9,33.5,0 32.1,33.5,0 32.2,33.4,0 32.4,33.4,0 32.5,33.4,0 32.7,33.3,0 32.8,33.3,0 33,33.3,0 33.1,33.3,0 33.3,33.2,0 33.4,33.2,0 33.6,33.2,0 33.7,33.2,0 33.9,33.2,0 34,33.2,0 34.2,33.2,0 34.3,33.2,0 34.5,33.2,0 34.6,33.2,0 34.8,33.2,0 34.9,33.2,0 35.1,33.2,0 35.3,33.3,0 35.4,33.3,0 35.6,33.3,0 35.7,33.3,0 35.9,33.3,0 36,33.4,0 36.2,33.4,0 36.3,33.4,0 36.5,33.5,0 36.6,33.5,0 36.8,33.6,0 36.9,33.6,0 37.1,33.7,0 37.2,33.7,0 37.3,33.8,0 37.5,33.8,0 37.6,33.9,0 37.8,33.9,0 37.9,34,0 38,34.1,0 38.2,34.1,0 38.3,34.2,0 38.5,34.3,0 38.6,34.3,0 38.7,34.4,0 38.9,34.5,0 39,34.6,0 39.1,34.7,0 39.2,34.7,0 39.4,34.8,0 39.5,34.9,0 39.6,35,0 39.7,35.1,0 39.9,35.2,0 40,35.3,0 40.1,35.4,0 40.2,35.5,0 40.3,35.6,0 40.4,35.7,0 40.5,35.8,0 40.6,35.9,0 40.7,36.1,0 40.8,36.2,0 40.9,36.3,0 41,36.4,0 41.1,36.5,0 41.2,36.6,0 41.3,36.8,0 41.4,36.9,0 41.5,37,0 41.6,37.1,0 41.7,37.3,0 41.8,37.4,0 41.8,37.5,0 41.9,37.7,0 42,37.8,0 42.1,37.9,0 42.1,38.1,0 42.2,38.2,0 42.3,38.3,0 42.3,38.5,0 42.4,38.6,0 42.4,38.8,0 42.5,38.9,0 42.6,39.1,0 42.6,39.2,0 42.6,39.4,0 42.7,39.5,0 42.7,39.6,0 42.8,39.8,0 42.8,39.9,0 42.8,40.1,0 42.9,40.2,0 42.9,40.4,0 42.9,40.5,0 43,40.7,0 43,40.9,0 43,41,0 43,41.2,0 43,41.3,0 43,41.5,0 43,41.6,0 43.1,41.8,0 43.1,41.9,0 43.1,42.1,0 43.1,42.2,0 43,42.4,0 43,42.5,0 43,42.7,0 43,42.8,0 43,43,0 43,43.1,0 43,43.3,0 42.9,43.5,0 42.9,43.6,0 42.9,43.8,0 42.8,43.9,0 42.8,44.1,0 42.8,44.2,0 42.7,44.4,0 42.7,44.5,0 42.6,44.6,0 42.6,44.8,0 42.6,44.9,0 42.5,45.1,0 42.4,45.2,0 42.4,45.4,0 42.3,45.5,0 42.3,45.7,0 42.2,45.8,0 42.1,45.9,0 42.1,46.1,0 42,46.2,0 41.9,46.3,0 41.8,46.5,0 41.8,46.6,0 41.7,46.7,0 41.6,46.9,0 41.5,47,0 41.4,47.1,0 41.3,47.2,0 41.2,47.4,0 41.1,47.5,0 41,47.6,0 40.9,47.7,0 40.8,47.8,0 40.7,47.9,0 40.6,48.1,0 40.5,48.2,0 40.4,48.3,0 40.3,48.4,0 40.2,48.5,0 40.1,48.6,0 40,48.7,0 39.9,48.8,0 39.7,48.9,0 39.6,49,0 39.5,49.1,0 39.4,49.2,0 39.2,49.3,0 39.1,49.3,0 39,49.4,0 38.9,49.5,0 38.7,49.6,0 38.6,49.7,0 38.5,49.7,0 38.3,49.8,0 38.2,49.9,0 38,49.9,0 37.9,50,0 37.8,50.1,0 37.6,50.1,0 37.5,50.2,0 37.3,50.2,0 37.2,50.3,0 37.1,50.3,0 36.9,50.4,0 36.8,50.4,0 36.6,50.5,0 36.5,50.5,0 36.3,50.6,0 36.2,50.6,0 36,50.6,0 35.9,50.7,0 35.7,50.7,0 35.6,50.7,0 35.4,50.7,0 35.3,50.7,0 35.1,50.8,0 34.9,50.8,0 34.8,50.8,0 34.6,50.8,0 34.5,50.8,0 34.3,50.8,0 34.2,50.8,0 34,50.8,0 33.9,50.8,0 33.7,50.8,0 33.6,50.8,0 33.4,50.8,0 33.3,50.8,0 33.1,50.7,0 33,50.7,0 32.8,50.7,0 32.7,50.7,0 32.5,50.6,0 32.4,50.6,0 32.2,50.6,0 32.1,50.5,0 31.9,50.5,0 31.8,50.4,0 31.6,50.4,0 31.5,50.4,0 31.3,50.3,0 31.2,50.3,0 31,50.2,0 30.9,50.1,0 30.7,50.1,0 30.6,50,0 30.5,50,0 30.3,49.9,0 30.2,49.8,0 30.1,49.7,0 29.9,49.7,0 29.8,49.6,0 29.7,49.5,0 29.5,49.4,0 29.4,49.4,0 29.3,49.3,0 29.1,49.2,0 29,49.1,0 28.9,49,0 28.8,48.9,0 28.7,48.8,0 28.5,48.7,0 28.4,48.6,0 28.3,48.5,0 28.2,48.4,0 28.1,48.3,0 28,48.2,0 27.9,48.1,0 27.8,48,0 27.7,47.8,0 27.6,47.7,0 27.5,47.6,0 27.4,47.5,0 27.3,47.4,0 27.2,47.2,0 27.1,47.1,0 27,47,0</coordinates></LineString></MultiGeometry>" ) );
13913 : 1 : QCOMPARE( exportC.asKml( 1 ), expectedKml );
13914 : 2 : QString expectedKmlPrec3( QStringLiteral( "<MultiGeometry><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>2.333,5.667,0 2.316,5.677,0 2.298,5.687,0 2.28,5.697,0 2.262,5.707,0 2.244,5.716,0 2.226,5.725,0 2.207,5.734,0 2.188,5.742,0 2.17,5.75,0 2.151,5.757,0 2.131,5.765,0 2.112,5.772,0 2.093,5.778,0 2.074,5.785,0 2.054,5.79,0 2.034,5.796,0 2.015,5.801,0 1.995,5.806,0 1.975,5.811,0 1.955,5.815,0 1.935,5.819,0 1.915,5.822,0 1.894,5.826,0 1.874,5.828,0 1.854,5.831,0 1.834,5.833,0 1.813,5.835,0 1.793,5.836,0 1.773,5.837,0 1.752,5.838,0 1.732,5.838,0 1.711,5.838,0 1.691,5.838,0 1.67,5.837,0 1.65,5.836,0 1.63,5.834,0 1.609,5.833,0 1.589,5.83,0 1.569,5.828,0 1.548,5.825,0 1.528,5.822,0 1.508,5.818,0 1.488,5.814,0 1.468,5.81,0 1.448,5.805,0 1.428,5.801,0 1.409,5.795,0 1.389,5.79,0 1.37,5.784,0 1.35,5.777,0 1.331,5.771,0 1.312,5.764,0 1.293,5.756,0 1.274,5.749,0 1.255,5.741,0 1.236,5.732,0 1.218,5.724,0 1.199,5.715,0 1.181,5.705,0 1.163,5.696,0 1.145,5.686,0 1.128,5.676,0 1.11,5.665,0 1.093,5.654,0 1.076,5.643,0 1.059,5.632,0 1.042,5.62,0 1.025,5.608,0 1.009,5.596,0 0.993,5.583,0 0.977,5.57,0 0.962,5.557,0 0.946,5.543,0 0.931,5.53,0 0.916,5.516,0 0.901,5.502,0 0.887,5.487,0 0.873,5.473,0 0.859,5.458,0 0.845,5.442,0 0.832,5.427,0 0.819,5.411,0 0.806,5.395,0 0.793,5.379,0 0.781,5.363,0 0.769,5.346,0 0.757,5.33,0 0.746,5.313,0 0.735,5.296,0 0.724,5.278,0 0.713,5.261,0 0.703,5.243,0 0.693,5.225,0 0.684,5.207,0 0.674,5.189,0 0.666,5.171,0 0.657,5.152,0 0.649,5.133,0 0.641,5.115,0 0.633,5.096,0 0.626,5.077,0 0.619,5.057,0 0.612,5.038,0 0.606,5.019,0 0.6,4.999,0 0.594,4.979,0 0.589,4.96,0 0.584,4.94,0 0.579,4.92,0 0.575,4.9,0 0.571,4.88,0 0.568,4.86,0 0.564,4.84,0 0.562,4.819,0 0.559,4.799,0 0.557,4.779,0 0.555,4.759,0 0.554,4.738,0 0.553,4.718,0 0.552,4.697,0 0.552,4.677,0 0.552,4.656,0 0.552,4.636,0 0.553,4.616,0 0.554,4.595,0 0.555,4.575,0 0.557,4.554,0 0.559,4.534,0 0.562,4.514,0 0.564,4.494,0 0.568,4.473,0 0.571,4.453,0 0.575,4.433,0 0.579,4.413,0 0.584,4.393,0 0.589,4.374,0 0.594,4.354,0 0.6,4.334,0 0.606,4.315,0 0.612,4.295,0 0.619,4.276,0 0.626,4.257,0 0.633,4.238,0 0.641,4.219,0 0.649,4.2,0 0.657,4.181,0 0.666,4.163,0 0.674,4.144,0 0.684,4.126,0 0.693,4.108,0 0.703,4.09,0 0.713,4.073,0 0.724,4.055,0 0.735,4.038,0 0.746,4.021,0 0.757,4.004,0 0.769,3.987,0 0.781,3.97,0 0.793,3.954,0 0.806,3.938,0 0.819,3.922,0 0.832,3.906,0 0.845,3.891,0 0.859,3.876,0 0.873,3.861,0 0.887,3.846,0 0.901,3.832,0 0.916,3.817,0 0.931,3.804,0 0.946,3.79,0 0.962,3.776,0 0.977,3.763,0 0.993,3.75,0 1.009,3.738,0 1.025,3.726,0 1.042,3.713,0 1.059,3.702,0 1.076,3.69,0 1.093,3.679,0 1.11,3.668,0 1.128,3.658,0 1.145,3.648,0 1.163,3.638,0 1.181,3.628,0 1.199,3.619,0 1.218,3.61,0 1.236,3.601,0 1.255,3.593,0 1.274,3.585,0 1.293,3.577,0 1.312,3.57,0 1.331,3.563,0 1.35,3.556,0 1.37,3.55,0 1.389,3.544,0 1.409,3.538,0 1.428,3.533,0 1.448,3.528,0 1.468,3.523,0 1.488,3.519,0 1.508,3.515,0 1.528,3.511,0 1.548,3.508,0 1.569,3.505,0 1.589,3.503,0 1.609,3.501,0 1.63,3.499,0 1.65,3.497,0 1.67,3.496,0 1.691,3.496,0 1.711,3.495,0 1.732,3.495,0 1.752,3.496,0 1.773,3.496,0 1.793,3.497,0 1.813,3.499,0 1.834,3.5,0 1.854,3.503,0 1.874,3.505,0 1.894,3.508,0 1.915,3.511,0 1.935,3.514,0 1.955,3.518,0 1.975,3.523,0 1.995,3.527,0 2.015,3.532,0 2.034,3.537,0 2.054,3.543,0 2.074,3.549,0 2.093,3.555,0 2.112,3.562,0 2.131,3.569,0 2.151,3.576,0 2.17,3.584,0 2.188,3.592,0 2.207,3.6,0 2.226,3.608,0 2.244,3.617,0 2.262,3.627,0 2.28,3.636,0 2.298,3.646,0 2.316,3.656,0 2.333,3.667,0</coordinates></LineString><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>9,4.111,0 8.966,4.178,0 8.932,4.244,0 8.896,4.309,0 8.859,4.374,0 8.821,4.438,0 8.782,4.502,0 8.742,4.565,0 8.7,4.627,0 8.658,4.688,0 8.614,4.749,0 8.57,4.809,0 8.524,4.868,0 8.477,4.926,0 8.43,4.983,0 8.381,5.04,0 8.331,5.096,0 8.281,5.151,0 8.229,5.205,0 8.177,5.258,0 8.124,5.31,0 8.069,5.361,0 8.014,5.411,0 7.958,5.461,0 7.901,5.509,0 7.844,5.556,0 7.785,5.603,0 7.726,5.648,0 7.666,5.692,0 7.605,5.735,0 7.543,5.777,0 7.481,5.818,0 7.418,5.858,0 7.354,5.897,0 7.29,5.935,0 7.225,5.971,0 7.159,6.007,0 7.093,6.041,0 7.026,6.074,0 6.958,6.106,0 6.89,6.137,0 6.822,6.167,0 6.753,6.195,0 6.683,6.222,0 6.613,6.248,0 6.543,6.273,0 6.472,6.296,0 6.401,6.319,0 6.329,6.34,0 6.257,6.36,0 6.185,6.378,0 6.112,6.395,0 6.04,6.411,0 5.966,6.426,0 5.893,6.44,0 5.819,6.452,0 5.746,6.463,0 5.672,6.472,0 5.597,6.48,0 5.523,6.487,0 5.449,6.493,0 5.374,6.498,0 5.3,6.501,0 5.225,6.503,0 5.15,6.503,0 5.076,6.502,0 5.001,6.5,0 4.927,6.497,0 4.852,6.492,0 4.778,6.486,0 4.704,6.479,0 4.629,6.47,0 4.555,6.46,0 4.482,6.449,0 4.408,6.437,0 4.335,6.423,0 4.262,6.408,0 4.189,6.392,0 4.116,6.374,0 4.044,6.355,0 3.972,6.335,0 3.901,6.314,0 3.83,6.292,0 3.759,6.268,0 3.688,6.243,0 3.619,6.217,0 3.549,6.189,0 3.48,6.16,0 3.412,6.131,0 3.344,6.1,0 3.277,6.067,0 3.21,6.034,0 3.144,5.999,0 3.078,5.964,0 3.013,5.927,0 2.949,5.889,0 2.886,5.85,0 2.823,5.81,0 2.761,5.768,0 2.699,5.726,0 2.638,5.683,0 2.578,5.638,0 2.519,5.593,0 2.461,5.546,0 2.403,5.499,0 2.347,5.45,0 2.291,5.401,0 2.236,5.35,0 2.182,5.299,0 2.129,5.246,0 2.076,5.193,0 2.025,5.139,0 1.975,5.084,0 1.925,5.028,0 1.877,4.971,0 1.829,4.914,0 1.783,4.855,0 1.738,4.796,0 1.693,4.736,0 1.65,4.675,0 1.608,4.614,0 1.567,4.551,0 1.527,4.488,0 1.488,4.425,0 1.45,4.36,0 1.413,4.295,0 1.378,4.23,0 1.343,4.164,0 1.31,4.097,0 1.278,4.029,0 1.247,3.961,0 1.217,3.893,0 1.189,3.824,0 1.161,3.755,0 1.135,3.685,0 1.11,3.614,0 1.087,3.544,0 1.064,3.472,0 1.043,3.401,0 1.023,3.329,0 1.004,3.257,0 0.987,3.184,0 0.971,3.111,0 0.956,3.038,0 0.942,2.965,0 0.93,2.891,0 0.919,2.817,0 0.909,2.743,0 0.901,2.669,0 0.894,2.595,0 0.888,2.52,0 0.883,2.446,0 0.88,2.371,0 0.878,2.297,0 0.878,2.222,0 0.878,2.148,0 0.88,2.073,0 0.883,1.998,0 0.888,1.924,0 0.894,1.85,0 0.901,1.775,0 0.909,1.701,0 0.919,1.627,0 0.93,1.553,0 0.942,1.48,0 0.956,1.406,0 0.971,1.333,0 0.987,1.26,0 1.004,1.188,0 1.023,1.116,0 1.043,1.044,0 1.064,0.972,0 1.087,0.901,0 1.11,0.83,0 1.135,0.76,0 1.161,0.69,0 1.189,0.62,0 1.217,0.551,0 1.247,0.483,0 1.278,0.415,0 1.31,0.348,0 1.343,0.281,0 1.378,0.215,0 1.413,0.149,0 1.45,0.084,0 1.488,0.02,0 1.527,-0.044,0 1.567,-0.107,0 1.608,-0.169,0 1.65,-0.231,0 1.693,-0.291,0 1.738,-0.351,0 1.783,-0.411,0 1.829,-0.469,0 1.877,-0.527,0 1.925,-0.584,0 1.975,-0.639,0 2.025,-0.694,0 2.076,-0.749,0 2.129,-0.802,0 2.182,-0.854,0 2.236,-0.906,0 2.291,-0.956,0 2.347,-1.006,0 2.403,-1.054,0 2.461,-1.102,0 2.519,-1.148,0 2.578,-1.194,0 2.638,-1.238,0 2.699,-1.282,0 2.761,-1.324,0 2.823,-1.365,0 2.886,-1.405,0 2.949,-1.444,0 3.013,-1.482,0 3.078,-1.519,0 3.144,-1.555,0 3.21,-1.589,0 3.277,-1.623,0 3.344,-1.655,0 3.412,-1.686,0 3.48,-1.716,0 3.549,-1.745,0 3.619,-1.772,0 3.688,-1.798,0 3.759,-1.823,0 3.83,-1.847,0 3.901,-1.87,0 3.972,-1.891,0 4.044,-1.911,0 4.116,-1.93,0 4.189,-1.947,0 4.262,-1.964,0 4.335,-1.979,0 4.408,-1.992,0 4.482,-2.005,0 4.555,-2.016,0 4.629,-2.026,0 4.704,-2.034,0 4.778,-2.042,0 4.852,-2.048,0 4.927,-2.052,0 5.001,-2.056,0 5.076,-2.058,0 5.15,-2.059,0 5.225,-2.058,0 5.3,-2.056,0 5.374,-2.053,0 5.449,-2.049,0 5.523,-2.043,0 5.597,-2.036,0 5.672,-2.028,0 5.746,-2.018,0 5.819,-2.007,0 5.893,-1.995,0 5.966,-1.982,0 6.04,-1.967,0 6.112,-1.951,0 6.185,-1.934,0 6.257,-1.915,0 6.329,-1.895,0 6.401,-1.874,0 6.472,-1.852,0 6.543,-1.829,0 6.613,-1.804,0 6.683,-1.778,0 6.753,-1.751,0 6.822,-1.722,0 6.89,-1.693,0 6.958,-1.662,0 7.026,-1.63,0 7.093,-1.597,0 7.159,-1.562,0 7.225,-1.527,0 7.29,-1.49,0 7.354,-1.453,0 7.418,-1.414,0 7.481,-1.374,0 7.543,-1.333,0 7.605,-1.291,0 7.666,-1.248,0 7.726,-1.203,0 7.785,-1.158,0 7.844,-1.112,0 7.901,-1.065,0 7.958,-1.016,0 8.014,-0.967,0 8.069,-0.917,0 8.124,-0.865,0 8.177,-0.813,0 8.229,-0.76,0 8.281,-0.706,0 8.331,-0.651,0 8.381,-0.596,0 8.43,-0.539,0 8.477,-0.482,0 8.524,-0.423,0 8.57,-0.364,0 8.614,-0.304,0 8.658,-0.244,0 8.7,-0.182,0 8.742,-0.12,0 8.782,-0.057,0 8.821,0.006,0 8.859,0.07,0 8.896,0.135,0 8.932,0.201,0 8.966,0.267,0 9,0.333,0</coordinates></LineString></MultiGeometry>" ) );
13915 : 1 : QCOMPARE( exportFloat.asKml( 3 ), expectedKmlPrec3 );
13916 : :
13917 : : // insert geometry
13918 : 1 : QgsMultiCurve rc;
13919 : 1 : rc.clear();
13920 : 1 : rc.insertGeometry( nullptr, 0 );
13921 : 1 : QVERIFY( rc.isEmpty() );
13922 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13923 : 1 : rc.insertGeometry( nullptr, -1 );
13924 : 1 : QVERIFY( rc.isEmpty() );
13925 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13926 : 1 : rc.insertGeometry( nullptr, 100 );
13927 : 1 : QVERIFY( rc.isEmpty() );
13928 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13929 : :
13930 : 1 : rc.insertGeometry( new QgsPoint(), 0 );
13931 : 1 : QVERIFY( rc.isEmpty() );
13932 : 1 : QCOMPARE( rc.numGeometries(), 0 );
13933 : :
13934 : 1 : rc.insertGeometry( part.clone(), 0 );
13935 : 1 : QVERIFY( !rc.isEmpty() );
13936 : 1 : QCOMPARE( rc.numGeometries(), 1 );
13937 : :
13938 : : // cast
13939 : 1 : QVERIFY( !QgsMultiCurve().cast( nullptr ) );
13940 : 1 : QgsMultiCurve pCast;
13941 : 1 : QVERIFY( QgsMultiCurve().cast( &pCast ) );
13942 : 1 : QgsMultiCurve pCast2;
13943 : 2 : pCast2.fromWkt( QStringLiteral( "MultiCurveZ()" ) );
13944 : 1 : QVERIFY( QgsMultiCurve().cast( &pCast2 ) );
13945 : 2 : pCast2.fromWkt( QStringLiteral( "MultiCurveM()" ) );
13946 : 1 : QVERIFY( QgsMultiCurve().cast( &pCast2 ) );
13947 : 2 : pCast2.fromWkt( QStringLiteral( "MultiCurveZM()" ) );
13948 : 1 : QVERIFY( QgsMultiCurve().cast( &pCast2 ) );
13949 : :
13950 : : //boundary
13951 : 1 : QgsMultiCurve multiLine1;
13952 : 1 : QVERIFY( !multiLine1.boundary() );
13953 : 1 : QgsCircularString boundaryLine1;
13954 : 1 : boundaryLine1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) );
13955 : 1 : multiLine1.addGeometry( boundaryLine1.clone() );
13956 : 1 : QgsAbstractGeometry *boundary = multiLine1.boundary();
13957 : 1 : QgsMultiPoint *mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13958 : 1 : QVERIFY( mpBoundary );
13959 : 1 : QCOMPARE( mpBoundary->numGeometries(), 2 );
13960 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13961 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13962 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13963 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13964 : 1 : delete boundary;
13965 : : // add another QgsCircularString
13966 : 1 : QgsCircularString boundaryLine2;
13967 : 1 : boundaryLine2.setPoints( QgsPointSequence() << QgsPoint( 10, 10 ) << QgsPoint( 11, 10 ) << QgsPoint( 11, 11 ) );
13968 : 1 : multiLine1.addGeometry( boundaryLine2.clone() );
13969 : 1 : boundary = multiLine1.boundary();
13970 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13971 : 1 : QVERIFY( mpBoundary );
13972 : 1 : QCOMPARE( mpBoundary->numGeometries(), 4 );
13973 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13974 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13975 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13976 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13977 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
13978 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
13979 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->x(), 11.0 );
13980 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->y(), 11.0 );
13981 : 1 : delete boundary;
13982 : :
13983 : : // add a closed string = no boundary
13984 : 1 : QgsCircularString boundaryLine3;
13985 : 1 : boundaryLine3.setPoints( QgsPointSequence() << QgsPoint( 20, 20 ) << QgsPoint( 21, 20 ) << QgsPoint( 20, 20 ) );
13986 : 1 : multiLine1.addGeometry( boundaryLine3.clone() );
13987 : 1 : boundary = multiLine1.boundary();
13988 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
13989 : 1 : QVERIFY( mpBoundary );
13990 : 1 : QCOMPARE( mpBoundary->numGeometries(), 4 );
13991 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
13992 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
13993 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
13994 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
13995 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
13996 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
13997 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->x(), 11.0 );
13998 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->y(), 11.0 );
13999 : 1 : delete boundary;
14000 : :
14001 : : //boundary with z
14002 : 1 : QgsCircularString boundaryLine4;
14003 : 1 : boundaryLine4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 20 ) );
14004 : 1 : QgsCircularString boundaryLine5;
14005 : 1 : boundaryLine5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 150 ) << QgsPoint( QgsWkbTypes::PointZ, 20, 20, 200 ) );
14006 : 1 : QgsMultiCurve multiLine2;
14007 : 1 : multiLine2.addGeometry( boundaryLine4.clone() );
14008 : 1 : multiLine2.addGeometry( boundaryLine5.clone() );
14009 : :
14010 : 1 : boundary = multiLine2.boundary();
14011 : 1 : mpBoundary = dynamic_cast< QgsMultiPoint * >( boundary );
14012 : 1 : QVERIFY( mpBoundary );
14013 : 1 : QCOMPARE( mpBoundary->numGeometries(), 4 );
14014 : 1 : QCOMPARE( mpBoundary->geometryN( 0 )->wkbType(), QgsWkbTypes::PointZ );
14015 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->x(), 0.0 );
14016 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->y(), 0.0 );
14017 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 0 ) )->z(), 10.0 );
14018 : 1 : QCOMPARE( mpBoundary->geometryN( 1 )->wkbType(), QgsWkbTypes::PointZ );
14019 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->x(), 1.0 );
14020 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->y(), 1.0 );
14021 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 1 ) )->z(), 20.0 );
14022 : 1 : QCOMPARE( mpBoundary->geometryN( 2 )->wkbType(), QgsWkbTypes::PointZ );
14023 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->x(), 10.0 );
14024 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->y(), 10.0 );
14025 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 2 ) )->z(), 100.0 );
14026 : 1 : QCOMPARE( mpBoundary->geometryN( 3 )->wkbType(), QgsWkbTypes::PointZ );
14027 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->x(), 20.0 );
14028 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->y(), 20.0 );
14029 : 1 : QCOMPARE( static_cast< QgsPoint *>( mpBoundary->geometryN( 3 ) )->z(), 200.0 );
14030 : 1 : delete boundary;
14031 : :
14032 : : //reversed
14033 : 1 : QgsMultiCurve cR;
14034 : 1 : std::unique_ptr< QgsMultiCurve > reversed( cR.reversed() );
14035 : 1 : QVERIFY( reversed->isEmpty() );
14036 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 11, 2, 8 ) ) ;
14037 : 1 : cR.addGeometry( part.clone() );
14038 : 1 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 53, 21, 52 ) ) ;
14039 : 1 : cR.addGeometry( part.clone() );
14040 : 1 : reversed.reset( cR.reversed() );
14041 : 1 : QVERIFY( !reversed->isEmpty() );
14042 : 1 : ls = static_cast< const QgsCircularString * >( reversed->geometryN( 0 ) );
14043 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 7, 11, 2, 8 ) );
14044 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) );
14045 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) );
14046 : 1 : ls = static_cast< const QgsCircularString * >( reversed->geometryN( 1 ) );
14047 : 1 : QCOMPARE( ls->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 27, 53, 21, 52 ) );
14048 : 1 : QCOMPARE( ls->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) );
14049 : 1 : QCOMPARE( ls->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) );
14050 : :
14051 : : // segmentize
14052 : 1 : QgsMultiCurve multiCurve2;
14053 : 1 : QgsCompoundCurve compoundCurve2;
14054 : 1 : QgsCircularString circularString2;
14055 : 1 : circularString2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 10 ) << QgsPoint( 21, 2 ) );
14056 : 1 : compoundCurve2.addCurve( circularString2.clone() );
14057 : 1 : multiCurve2.addGeometry( compoundCurve2.clone() );
14058 : 1 : QgsMultiLineString *segmentized2 = static_cast<QgsMultiLineString *>( multiCurve2.segmentize() );
14059 : 1 : QCOMPARE( segmentized2->vertexCount(), 156 );
14060 : 1 : QCOMPARE( segmentized2->partCount(), 1 );
14061 : 1 : QVERIFY( !segmentized2->is3D() );
14062 : 1 : QVERIFY( !segmentized2->isMeasure() );
14063 : 1 : QCOMPARE( segmentized2->wkbType(), QgsWkbTypes::Type::MultiLineString );
14064 : 1 : }
14065 : :
14066 : 1 : void TestQgsGeometry::multiSurface()
14067 : : {
14068 : : //test constructor
14069 : 1 : QgsMultiSurface c1;
14070 : 1 : QVERIFY( c1.isEmpty() );
14071 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
14072 : 1 : QCOMPARE( c1.ringCount(), 0 );
14073 : 1 : QCOMPARE( c1.partCount(), 0 );
14074 : 1 : QVERIFY( !c1.is3D() );
14075 : 1 : QVERIFY( !c1.isMeasure() );
14076 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiSurface );
14077 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiSurface" ) );
14078 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiSurface" ) );
14079 : 1 : QCOMPARE( c1.dimension(), 0 );
14080 : 1 : QVERIFY( !c1.hasCurvedSegments() );
14081 : 1 : QCOMPARE( c1.area(), 0.0 );
14082 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
14083 : 1 : QCOMPARE( c1.numGeometries(), 0 );
14084 : 1 : QVERIFY( !c1.geometryN( 0 ) );
14085 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14086 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 0 );
14087 : 1 : QCOMPARE( c1.vertexCount( 0, 1 ), 0 );
14088 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
14089 : :
14090 : : //addGeometry
14091 : : //try with nullptr
14092 : 1 : c1.addGeometry( nullptr );
14093 : 1 : QVERIFY( c1.isEmpty() );
14094 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
14095 : 1 : QCOMPARE( c1.ringCount(), 0 );
14096 : 1 : QCOMPARE( c1.partCount(), 0 );
14097 : 1 : QCOMPARE( c1.numGeometries(), 0 );
14098 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiSurface );
14099 : 1 : QVERIFY( !c1.geometryN( 0 ) );
14100 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14101 : :
14102 : : // not a surface
14103 : 1 : QVERIFY( !c1.addGeometry( new QgsPoint() ) );
14104 : 1 : QVERIFY( c1.isEmpty() );
14105 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
14106 : 1 : QCOMPARE( c1.ringCount(), 0 );
14107 : 1 : QCOMPARE( c1.partCount(), 0 );
14108 : 1 : QCOMPARE( c1.numGeometries(), 0 );
14109 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiSurface );
14110 : 1 : QVERIFY( !c1.geometryN( 0 ) );
14111 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14112 : :
14113 : : //valid geometry
14114 : 1 : QgsCurvePolygon part;
14115 : 1 : QgsCircularString ring;
14116 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) << QgsPoint( 1, 10 ) );
14117 : 1 : part.setExteriorRing( ring.clone() );
14118 : 1 : c1.addGeometry( part.clone() );
14119 : 1 : QVERIFY( !c1.isEmpty() );
14120 : 1 : QCOMPARE( c1.numGeometries(), 1 );
14121 : 1 : QCOMPARE( c1.nCoordinates(), 3 );
14122 : 1 : QCOMPARE( c1.ringCount(), 1 );
14123 : 1 : QCOMPARE( c1.partCount(), 1 );
14124 : 1 : QVERIFY( !c1.is3D() );
14125 : 1 : QVERIFY( !c1.isMeasure() );
14126 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiSurface );
14127 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiSurface" ) );
14128 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiSurface" ) );
14129 : 1 : QCOMPARE( c1.dimension(), 2 );
14130 : 1 : QVERIFY( c1.hasCurvedSegments() );
14131 : 1 : QVERIFY( c1.geometryN( 0 ) );
14132 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c1.geometryN( 0 ) ), part );
14133 : 1 : QVERIFY( !c1.geometryN( 100 ) );
14134 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14135 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 3 );
14136 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
14137 : :
14138 : : //initial adding of geometry should set z/m type
14139 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 20, 21, 2 )
14140 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 ) );
14141 : 1 : part.clear();
14142 : 1 : part.setExteriorRing( ring.clone() );
14143 : 1 : QgsMultiSurface c2;
14144 : 1 : c2.addGeometry( part.clone() );
14145 : 1 : QVERIFY( c2.is3D() );
14146 : 1 : QVERIFY( !c2.isMeasure() );
14147 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::MultiSurfaceZ );
14148 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "MultiSurfaceZ" ) );
14149 : 1 : QCOMPARE( c2.geometryType(), QString( "MultiSurface" ) );
14150 : 1 : QCOMPARE( *( static_cast< const QgsCurvePolygon * >( c2.geometryN( 0 ) ) ), part );
14151 : 1 : QgsMultiSurface c3;
14152 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 10, 11, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 20, 21, 0, 2 )
14153 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 11, 0, 1 ) );
14154 : 1 : part.clear();
14155 : 1 : part.setExteriorRing( ring.clone() );
14156 : 1 : c3.addGeometry( part.clone() );
14157 : 1 : QVERIFY( !c3.is3D() );
14158 : 1 : QVERIFY( c3.isMeasure() );
14159 : 1 : QCOMPARE( c3.wkbType(), QgsWkbTypes::MultiSurfaceM );
14160 : 1 : QCOMPARE( c3.wktTypeStr(), QString( "MultiSurfaceM" ) );
14161 : 1 : QCOMPARE( *( static_cast< const QgsCurvePolygon * >( c3.geometryN( 0 ) ) ), part );
14162 : 1 : QgsMultiSurface c4;
14163 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 10, 11, 2, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 20, 21, 3, 2 )
14164 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 11, 2, 1 ) );
14165 : 1 : part.clear();
14166 : 1 : part.setExteriorRing( ring.clone() );
14167 : 1 : c4.addGeometry( part.clone() );
14168 : 1 : QVERIFY( c4.is3D() );
14169 : 1 : QVERIFY( c4.isMeasure() );
14170 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14171 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "MultiSurfaceZM" ) );
14172 : 1 : QCOMPARE( *( static_cast< const QgsCurvePolygon * >( c4.geometryN( 0 ) ) ), part );
14173 : :
14174 : : //add another part
14175 : 1 : QgsMultiSurface c6;
14176 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) << QgsPoint( 1, 10 ) );
14177 : 1 : part.clear();
14178 : 1 : part.setExteriorRing( ring.clone() );
14179 : 1 : c6.addGeometry( part.clone() );
14180 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 3 );
14181 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 9, 12 ) << QgsPoint( 3, 13 ) << QgsPoint( 9, 12 ) );
14182 : 1 : part.clear();
14183 : 1 : part.setExteriorRing( ring.clone() );
14184 : 1 : c6.addGeometry( part.clone() );
14185 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 3 );
14186 : 1 : QCOMPARE( c6.numGeometries(), 2 );
14187 : 1 : QVERIFY( c6.geometryN( 0 ) );
14188 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c6.geometryN( 1 ) ), part );
14189 : :
14190 : : //adding subsequent points should not alter z/m type, regardless of parts type
14191 : 1 : c6.clear();
14192 : 1 : c6.addGeometry( part.clone() );
14193 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurface );
14194 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) << QgsPoint( 1, 10, 2 ) ) ;
14195 : 1 : part.clear();
14196 : 1 : part.setExteriorRing( ring.clone() );
14197 : 1 : c6.addGeometry( part.clone() );
14198 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurface );
14199 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 3 );
14200 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 3 );
14201 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 0 );
14202 : 1 : QCOMPARE( c6.vertexCount( -1, 0 ), 0 );
14203 : 1 : QCOMPARE( c6.nCoordinates(), 6 );
14204 : 1 : QCOMPARE( c6.ringCount(), 1 );
14205 : 1 : QCOMPARE( c6.partCount(), 2 );
14206 : 1 : QVERIFY( !c6.is3D() );
14207 : 1 : const QgsCurvePolygon *ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 0 ) );
14208 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 9, 12 ) );
14209 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 3, 13 ) );
14210 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 9, 12 ) );
14211 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 1 ) );
14212 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 1, 10 ) );
14213 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 2, 11 ) );
14214 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 1, 10 ) );
14215 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 21, 30, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 32, 41, 0, 3 )
14216 : 1 : << QgsPoint( QgsWkbTypes::PointM, 21, 30, 0, 2 ) ) ;
14217 : 1 : part.clear();
14218 : 1 : part.setExteriorRing( ring.clone() );
14219 : 1 : c6.addGeometry( part.clone() );
14220 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurface );
14221 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 3 );
14222 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 3 );
14223 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 3 );
14224 : 1 : QCOMPARE( c6.nCoordinates(), 9 );
14225 : 1 : QCOMPARE( c6.ringCount(), 1 );
14226 : 1 : QCOMPARE( c6.partCount(), 3 );
14227 : 1 : QVERIFY( !c6.is3D() );
14228 : 1 : QVERIFY( !c6.isMeasure() );
14229 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 2 ) );
14230 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 21, 30 ) );
14231 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 32, 41 ) );
14232 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 21, 30 ) );
14233 : :
14234 : 1 : c6.clear();
14235 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) << QgsPoint( 1, 10, 2 ) ) ;
14236 : 1 : part.clear();
14237 : 1 : part.setExteriorRing( ring.clone() );
14238 : 1 : c6.addGeometry( part.clone() );
14239 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZ );
14240 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) << QgsPoint( 2, 20 ) ) ;
14241 : 1 : part.clear();
14242 : 1 : part.setExteriorRing( ring.clone() );
14243 : 1 : c6.addGeometry( part.clone() );
14244 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZ );
14245 : 1 : QVERIFY( c6.is3D() );
14246 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 0 ) );
14247 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 1, 10, 2 ) );
14248 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 2, 11, 3 ) );
14249 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 1, 10, 2 ) );
14250 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 1 ) );
14251 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 2, 20, 0 ) );
14252 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 3, 31, 0 ) );
14253 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 2, 20, 0 ) );
14254 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 )
14255 : 1 : << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) ) ;
14256 : 1 : part.clear();
14257 : 1 : part.setExteriorRing( ring.clone() );
14258 : 1 : c6.addGeometry( part.clone() );
14259 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZ );
14260 : 1 : QVERIFY( c6.is3D() );
14261 : 1 : QVERIFY( !c6.isMeasure() );
14262 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 2 ) );
14263 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 5, 50, 0 ) );
14264 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 6, 61, 0 ) );
14265 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 5, 50, 0 ) );
14266 : :
14267 : 1 : c6.clear();
14268 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurface );
14269 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 )
14270 : 1 : << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) ) ;
14271 : 1 : part.clear();
14272 : 1 : part.setExteriorRing( ring.clone() );
14273 : 1 : c6.addGeometry( part.clone() );
14274 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceM );
14275 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) << QgsPoint( 2, 20 ) ) ;
14276 : 1 : part.clear();
14277 : 1 : part.setExteriorRing( ring.clone() );
14278 : 1 : c6.addGeometry( part.clone() );
14279 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceM );
14280 : 1 : QVERIFY( c6.isMeasure() );
14281 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 0 ) );
14282 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) );
14283 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 ) );
14284 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) );
14285 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 1 ) );
14286 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 2, 20, 0, 0 ) );
14287 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 3, 31, 0, 0 ) );
14288 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 2, 20, 0, 0 ) );
14289 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 11, 12, 13 ) << QgsPoint( 14, 15, 16 ) << QgsPoint( 11, 12, 13 ) ) ;
14290 : 1 : part.clear();
14291 : 1 : part.setExteriorRing( ring.clone() );
14292 : 1 : c6.addGeometry( part.clone() );
14293 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceM );
14294 : 1 : QVERIFY( !c6.is3D() );
14295 : 1 : QVERIFY( c6.isMeasure() );
14296 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 2 ) );
14297 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
14298 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 14, 15, 0, 0 ) );
14299 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
14300 : :
14301 : 1 : c6.clear();
14302 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 )
14303 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) ) ;
14304 : 1 : part.clear();
14305 : 1 : part.setExteriorRing( ring.clone() );
14306 : 1 : c6.addGeometry( part.clone() );
14307 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14308 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 )
14309 : 1 : << QgsPoint( QgsWkbTypes::Point, 7, 17 ) ) ;
14310 : 1 : part.clear();
14311 : 1 : part.setExteriorRing( ring.clone() );
14312 : 1 : c6.addGeometry( part.clone() );
14313 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14314 : 1 : QVERIFY( c6.isMeasure() );
14315 : 1 : QVERIFY( c6.is3D() );
14316 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 0 ) );
14317 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) );
14318 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 ) );
14319 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) );
14320 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 1 ) );
14321 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 0, 0 ) );
14322 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 3, 13, 0, 0 ) );
14323 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 0, 0 ) );
14324 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 77, 87, 7 ) << QgsPoint( QgsWkbTypes::PointZ, 83, 83, 8 )
14325 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 77, 87, 7 ) ) ;
14326 : 1 : part.clear();
14327 : 1 : part.setExteriorRing( ring.clone() );
14328 : 1 : c6.addGeometry( part.clone() );
14329 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14330 : 1 : QVERIFY( c6.is3D() );
14331 : 1 : QVERIFY( c6.isMeasure() );
14332 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 2 ) );
14333 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 77, 87, 7, 0 ) );
14334 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 83, 83, 8, 0 ) );
14335 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 77, 87, 7, 0 ) );
14336 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 177, 187, 0, 9 ) << QgsPoint( QgsWkbTypes::PointM, 183, 183, 0, 11 )
14337 : 1 : << QgsPoint( QgsWkbTypes::PointM, 177, 187, 0, 9 ) ) ;
14338 : 1 : part.clear();
14339 : 1 : part.setExteriorRing( ring.clone() );
14340 : 1 : c6.addGeometry( part.clone() );
14341 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14342 : 1 : QVERIFY( c6.is3D() );
14343 : 1 : QVERIFY( c6.isMeasure() );
14344 : 1 : ls = static_cast< const QgsCurvePolygon * >( c6.geometryN( 3 ) );
14345 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 177, 187, 0, 9 ) );
14346 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 183, 183, 0, 11 ) );
14347 : 1 : QCOMPARE( static_cast< const QgsCircularString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 177, 187, 0, 9 ) );
14348 : :
14349 : : //clear
14350 : 1 : QgsMultiSurface c7;
14351 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 )
14352 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 5, 71, 4, 6 ) ) ;
14353 : 1 : part.clear();
14354 : 1 : part.setExteriorRing( ring.clone() );
14355 : 1 : c7.addGeometry( part.clone() );
14356 : 1 : c7.addGeometry( part.clone() );
14357 : 1 : QCOMPARE( c7.numGeometries(), 2 );
14358 : 1 : c7.clear();
14359 : 1 : QVERIFY( c7.isEmpty() );
14360 : 1 : QCOMPARE( c7.numGeometries(), 0 );
14361 : 1 : QCOMPARE( c7.nCoordinates(), 0 );
14362 : 1 : QCOMPARE( c7.ringCount(), 0 );
14363 : 1 : QCOMPARE( c7.partCount(), 0 );
14364 : 1 : QVERIFY( !c7.is3D() );
14365 : 1 : QVERIFY( !c7.isMeasure() );
14366 : 1 : QCOMPARE( c7.wkbType(), QgsWkbTypes::MultiSurface );
14367 : :
14368 : : //clone
14369 : 1 : QgsMultiSurface c11;
14370 : 1 : std::unique_ptr< QgsMultiSurface >cloned( c11.clone() );
14371 : 1 : QVERIFY( cloned->isEmpty() );
14372 : 1 : c11.addGeometry( part.clone() );
14373 : 1 : c11.addGeometry( part.clone() );
14374 : 1 : cloned.reset( c11.clone() );
14375 : 1 : QCOMPARE( cloned->numGeometries(), 2 );
14376 : 1 : ls = static_cast< const QgsCurvePolygon * >( cloned->geometryN( 0 ) );
14377 : 1 : QCOMPARE( *ls, part );
14378 : 1 : ls = static_cast< const QgsCurvePolygon * >( cloned->geometryN( 1 ) );
14379 : 1 : QCOMPARE( *ls, part );
14380 : :
14381 : : //copy constructor
14382 : 1 : QgsMultiSurface c12;
14383 : 1 : QgsMultiSurface c13( c12 );
14384 : 1 : QVERIFY( c13.isEmpty() );
14385 : 1 : c12.addGeometry( part.clone() );
14386 : 1 : c12.addGeometry( part.clone() );
14387 : 1 : QgsMultiSurface c14( c12 );
14388 : 1 : QCOMPARE( c14.numGeometries(), 2 );
14389 : 1 : QCOMPARE( c14.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14390 : 1 : ls = static_cast< const QgsCurvePolygon * >( c14.geometryN( 0 ) );
14391 : 1 : QCOMPARE( *ls, part );
14392 : 1 : ls = static_cast< const QgsCurvePolygon * >( c14.geometryN( 1 ) );
14393 : 1 : QCOMPARE( *ls, part );
14394 : :
14395 : : //assignment operator
14396 : 1 : QgsMultiSurface c15;
14397 : 1 : c15 = c13;
14398 : 1 : QCOMPARE( c15.numGeometries(), 0 );
14399 : 1 : c15 = c14;
14400 : 1 : QCOMPARE( c15.numGeometries(), 2 );
14401 : 1 : ls = static_cast< const QgsCurvePolygon * >( c15.geometryN( 0 ) );
14402 : 1 : QCOMPARE( *ls, part );
14403 : 1 : ls = static_cast< const QgsCurvePolygon * >( c15.geometryN( 1 ) );
14404 : 1 : QCOMPARE( *ls, part );
14405 : :
14406 : : //toCurveType
14407 : 1 : std::unique_ptr< QgsMultiSurface > curveType( c12.toCurveType() );
14408 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::MultiSurfaceZM );
14409 : 1 : QCOMPARE( curveType->numGeometries(), 2 );
14410 : 1 : const QgsCurvePolygon *curve = static_cast< const QgsCurvePolygon * >( curveType->geometryN( 0 ) );
14411 : 1 : QCOMPARE( *curve, *static_cast< const QgsCurvePolygon * >( c12.geometryN( 0 ) ) );
14412 : 1 : curve = static_cast< const QgsCurvePolygon * >( curveType->geometryN( 1 ) );
14413 : 1 : QCOMPARE( *curve, *static_cast< const QgsCurvePolygon * >( c12.geometryN( 1 ) ) );
14414 : :
14415 : : //to/fromWKB
14416 : 1 : QgsMultiSurface c16;
14417 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) << QgsPoint( QgsWkbTypes::Point, 7, 17 ) ) ;
14418 : 1 : part.clear();
14419 : 1 : part.setExteriorRing( ring.clone() );
14420 : 1 : c16.addGeometry( part.clone() );
14421 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) << QgsPoint( QgsWkbTypes::Point, 27, 37 ) ) ;
14422 : 1 : part.clear();
14423 : 1 : part.setExteriorRing( ring.clone() );
14424 : 1 : c16.addGeometry( part.clone() );
14425 : 1 : QByteArray wkb16 = c16.asWkb();
14426 : 1 : QgsMultiSurface c17;
14427 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
14428 : 1 : c17.fromWkb( wkb16ptr );
14429 : 1 : QCOMPARE( c17.numGeometries(), 2 );
14430 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 0 ) ) );
14431 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 1 ) ) );
14432 : :
14433 : : //parts with Z
14434 : 1 : c16.clear();
14435 : 1 : c17.clear();
14436 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 7, 17, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 3, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 7, 17, 1 ) ) ;
14437 : 1 : part.clear();
14438 : 1 : part.setExteriorRing( ring.clone() );
14439 : 1 : c16.addGeometry( part.clone() );
14440 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 27, 37, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 43, 43, 5 ) << QgsPoint( QgsWkbTypes::PointZ, 27, 37, 2 ) ) ;
14441 : 1 : part.clear();
14442 : 1 : part.setExteriorRing( ring.clone() );
14443 : 1 : c16.addGeometry( part.clone() );
14444 : 1 : wkb16 = c16.asWkb();
14445 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
14446 : 1 : c17.fromWkb( wkb16ptr2 );
14447 : 1 : QCOMPARE( c17.numGeometries(), 2 );
14448 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiSurfaceZ );
14449 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 0 ) ) );
14450 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 1 ) ) );
14451 : :
14452 : : //parts with m
14453 : 1 : c16.clear();
14454 : 1 : c17.clear();
14455 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 7, 17, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 3, 13, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 7, 17, 0, 1 ) ) ;
14456 : 1 : part.clear();
14457 : 1 : part.setExteriorRing( ring.clone() );
14458 : 1 : c16.addGeometry( part.clone() );
14459 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 27, 37, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 43, 43, 0, 5 ) << QgsPoint( QgsWkbTypes::PointM, 27, 37, 0, 2 ) ) ;
14460 : 1 : part.clear();
14461 : 1 : part.setExteriorRing( ring.clone() );
14462 : 1 : c16.addGeometry( part.clone() );
14463 : 1 : wkb16 = c16.asWkb();
14464 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
14465 : 1 : c17.fromWkb( wkb16ptr3 );
14466 : 1 : QCOMPARE( c17.numGeometries(), 2 );
14467 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiSurfaceM );
14468 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 0 ) ) );
14469 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 1 ) ) );
14470 : :
14471 : : // parts with ZM
14472 : 1 : c16.clear();
14473 : 1 : c17.clear();
14474 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) ) ;
14475 : 1 : part.clear();
14476 : 1 : part.setExteriorRing( ring.clone() );
14477 : 1 : c16.addGeometry( part.clone() );
14478 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) ) ;
14479 : 1 : part.clear();
14480 : 1 : part.setExteriorRing( ring.clone() );
14481 : 1 : c16.addGeometry( part.clone() );
14482 : 1 : wkb16 = c16.asWkb();
14483 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
14484 : 1 : c17.fromWkb( wkb16ptr4 );
14485 : 1 : QCOMPARE( c17.numGeometries(), 2 );
14486 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiSurfaceZM );
14487 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 0 ) ) );
14488 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsCurvePolygon * >( c16.geometryN( 1 ) ) );
14489 : :
14490 : : //bad WKB - check for no crash
14491 : 1 : c17.clear();
14492 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
14493 : 1 : QVERIFY( !c17.fromWkb( nullPtr ) );
14494 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiSurface );
14495 : 1 : QgsPoint point( 1, 2 );
14496 : 1 : QByteArray wkbPoint = point.asWkb();
14497 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
14498 : 1 : QVERIFY( !c17.fromWkb( wkbPointPtr ) );
14499 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiSurface );
14500 : :
14501 : : //to/from WKT
14502 : 1 : QgsMultiSurface c18;
14503 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 11, 2, 8 ) ) ;
14504 : 1 : part.clear();
14505 : 1 : part.setExteriorRing( ring.clone() );
14506 : 1 : c18.addGeometry( part.clone() );
14507 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 53, 21, 52 ) ) ;
14508 : 1 : part.clear();
14509 : 1 : part.setExteriorRing( ring.clone() );
14510 : 1 : c18.addGeometry( part.clone() );
14511 : :
14512 : 1 : QString wkt = c18.asWkt();
14513 : 1 : QVERIFY( !wkt.isEmpty() );
14514 : 1 : QgsMultiSurface c19;
14515 : 1 : QVERIFY( c19.fromWkt( wkt ) );
14516 : 1 : QCOMPARE( c19.numGeometries(), 2 );
14517 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c19.geometryN( 0 ) ), *static_cast< const QgsCurvePolygon * >( c18.geometryN( 0 ) ) );
14518 : 1 : QCOMPARE( *static_cast< const QgsCurvePolygon * >( c19.geometryN( 1 ) ), *static_cast< const QgsCurvePolygon * >( c18.geometryN( 1 ) ) );
14519 : :
14520 : : //bad WKT
14521 : 1 : QgsMultiSurface c20;
14522 : 1 : QVERIFY( !c20.fromWkt( "Point()" ) );
14523 : 1 : QVERIFY( c20.isEmpty() );
14524 : 1 : QCOMPARE( c20.numGeometries(), 0 );
14525 : 1 : QCOMPARE( c20.wkbType(), QgsWkbTypes::MultiSurface );
14526 : :
14527 : : //as JSON
14528 : 1 : QgsMultiSurface exportC;
14529 : 1 : QgsLineString lineRing;
14530 : 1 : lineRing.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 7, 13 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) << QgsPoint( QgsWkbTypes::Point, 7, 17 ) ) ;
14531 : 1 : part.clear();
14532 : 1 : part.setExteriorRing( lineRing.clone() );
14533 : 1 : exportC.addGeometry( part.clone() );
14534 : 1 : lineRing.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 27, 43 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) << QgsPoint( QgsWkbTypes::Point, 27, 37 ) ) ;
14535 : 1 : part.clear();
14536 : 1 : part.setExteriorRing( lineRing.clone() );
14537 : 1 : exportC.addGeometry( part.clone() );
14538 : :
14539 : : // GML document for compare
14540 : 1 : QDomDocument doc( "gml" );
14541 : :
14542 : : // as GML2
14543 : 2 : QString expectedSimpleGML2( QStringLiteral( "<MultiPolygon xmlns=\"gml\"><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">7,17 7,13 3,13 7,17</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">27,37 27,43 43,43 27,37</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember></MultiPolygon>" ) );
14544 : 1 : QString res = elemToString( exportC.asGml2( doc, 1 ) );
14545 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
14546 : 2 : QString expectedGML2empty( QStringLiteral( "<MultiPolygon xmlns=\"gml\"/>" ) );
14547 : 3 : QGSCOMPAREGML( elemToString( QgsMultiSurface().asGml2( doc ) ), expectedGML2empty );
14548 : :
14549 : : //as GML3
14550 : :
14551 : 2 : QString expectedSimpleGML3( QStringLiteral( "<MultiSurface xmlns=\"gml\"><surfaceMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">7 17 7 13 3 13 7 17</posList></LinearRing></exterior></Polygon></surfaceMember><surfaceMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">27 37 27 43 43 43 27 37</posList></LinearRing></exterior></Polygon></surfaceMember></MultiSurface>" ) );
14552 : 1 : res = elemToString( exportC.asGml3( doc ) );
14553 : 1 : QCOMPARE( res, expectedSimpleGML3 );
14554 : 2 : QString expectedGML3empty( QStringLiteral( "<MultiSurface xmlns=\"gml\"/>" ) );
14555 : 3 : QGSCOMPAREGML( elemToString( QgsMultiSurface().asGml3( doc ) ), expectedGML3empty );
14556 : :
14557 : : // as JSON
14558 : 1 : QString expectedSimpleJson( "{\"coordinates\":[[[[7.0,17.0],[7.0,13.0],[3.0,13.0],[7.0,17.0]]],[[[27.0,37.0],[27.0,43.0],[43.0,43.0],[27.0,37.0]]]],\"type\":\"MultiPolygon\"}" );
14559 : 1 : res = exportC.asJson( 1 );
14560 : 1 : QCOMPARE( res, expectedSimpleJson );
14561 : :
14562 : 1 : lineRing.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 17, 27 ) << QgsPoint( QgsWkbTypes::Point, 17, 28 ) << QgsPoint( QgsWkbTypes::Point, 18, 28 ) << QgsPoint( QgsWkbTypes::Point, 17, 27 ) ) ;
14563 : 1 : part.addInteriorRing( lineRing.clone() );
14564 : 1 : exportC.addGeometry( part.clone() );
14565 : :
14566 : 1 : QString expectedJsonWithRings( "{\"coordinates\":[[[[7.0,17.0],[7.0,13.0],[3.0,13.0],[7.0,17.0]]],[[[27.0,37.0],[27.0,43.0],[43.0,43.0],[27.0,37.0]]],[[[27.0,37.0],[27.0,43.0],[43.0,43.0],[27.0,37.0]],[[17.0,27.0],[17.0,28.0],[18.0,28.0],[17.0,27.0]]]],\"type\":\"MultiPolygon\"}" );
14567 : 1 : res = exportC.asJson( 1 );
14568 : 1 : QCOMPARE( res, expectedJsonWithRings );
14569 : :
14570 : 1 : QgsMultiSurface exportFloat;
14571 : 1 : lineRing.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 0.1234, 0.1234 ) << QgsPoint( QgsWkbTypes::Point, 0.1234, 1.2344 ) << QgsPoint( QgsWkbTypes::Point, 1.2344, 1.2344 ) << QgsPoint( QgsWkbTypes::Point, 0.1234, 0.1234 ) ) ;
14572 : 1 : part.clear();
14573 : 1 : part.setExteriorRing( lineRing.clone() );
14574 : 1 : exportFloat.addGeometry( part.clone() );
14575 : :
14576 : 2 : QString expectedJsonPrec3( QStringLiteral( "{\"coordinates\":[[[[0.123,0.123],[0.123,1.234],[1.234,1.234],[0.123,0.123]]]],\"type\":\"MultiPolygon\"}" ) );
14577 : 1 : res = exportFloat.asJson( 3 );
14578 : 1 : QCOMPARE( res, expectedJsonPrec3 );
14579 : :
14580 : : // as GML2
14581 : 2 : QString expectedGML2prec3( QStringLiteral( "<MultiPolygon xmlns=\"gml\"><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.123,0.123 0.123,1.234 1.234,1.234 0.123,0.123</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember></MultiPolygon>" ) );
14582 : 1 : res = elemToString( exportFloat.asGml2( doc, 3 ) );
14583 : 3 : QGSCOMPAREGML( res, expectedGML2prec3 );
14584 : :
14585 : : //as GML3
14586 : 2 : QString expectedGML3prec3( QStringLiteral( "<MultiSurface xmlns=\"gml\"><surfaceMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0.123 0.123 0.123 1.234 1.234 1.234 0.123 0.123</posList></LinearRing></exterior></Polygon></surfaceMember></MultiSurface>" ) );
14587 : 1 : res = elemToString( exportFloat.asGml3( doc, 3 ) );
14588 : 1 : QCOMPARE( res, expectedGML3prec3 );
14589 : :
14590 : : //asKML
14591 : 2 : QString expectedKmlPrec3( QStringLiteral( "<MultiGeometry><Polygon><outerBoundaryIs><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>0.123,0.123,0 0.123,1.234,0 1.234,1.234,0 0.123,0.123,0</coordinates></LinearRing></outerBoundaryIs></Polygon></MultiGeometry>" ) );
14592 : 1 : QCOMPARE( exportFloat.asKml( 3 ), expectedKmlPrec3 );
14593 : :
14594 : : // insert geometry
14595 : 1 : QgsMultiSurface rc;
14596 : 1 : rc.clear();
14597 : 1 : rc.insertGeometry( nullptr, 0 );
14598 : 1 : QVERIFY( rc.isEmpty() );
14599 : 1 : QCOMPARE( rc.numGeometries(), 0 );
14600 : 1 : rc.insertGeometry( nullptr, -1 );
14601 : 1 : QVERIFY( rc.isEmpty() );
14602 : 1 : QCOMPARE( rc.numGeometries(), 0 );
14603 : 1 : rc.insertGeometry( nullptr, 100 );
14604 : 1 : QVERIFY( rc.isEmpty() );
14605 : 1 : QCOMPARE( rc.numGeometries(), 0 );
14606 : :
14607 : 1 : rc.insertGeometry( new QgsPoint(), 0 );
14608 : 1 : QVERIFY( rc.isEmpty() );
14609 : 1 : QCOMPARE( rc.numGeometries(), 0 );
14610 : :
14611 : 1 : rc.insertGeometry( part.clone(), 0 );
14612 : 1 : QVERIFY( !rc.isEmpty() );
14613 : 1 : QCOMPARE( rc.numGeometries(), 1 );
14614 : :
14615 : : // cast
14616 : 1 : QVERIFY( !QgsMultiSurface().cast( nullptr ) );
14617 : 1 : QgsMultiSurface pCast;
14618 : 1 : QVERIFY( QgsMultiSurface().cast( &pCast ) );
14619 : 1 : QgsMultiSurface pCast2;
14620 : 2 : pCast2.fromWkt( QStringLiteral( "MultiSurfaceZ()" ) );
14621 : 1 : QVERIFY( QgsMultiSurface().cast( &pCast2 ) );
14622 : 2 : pCast2.fromWkt( QStringLiteral( "MultiSurfaceM()" ) );
14623 : 1 : QVERIFY( QgsMultiSurface().cast( &pCast2 ) );
14624 : 2 : pCast2.fromWkt( QStringLiteral( "MultiSurfaceZM()" ) );
14625 : 1 : QVERIFY( QgsMultiSurface().cast( &pCast2 ) );
14626 : :
14627 : : //boundary
14628 : 1 : QgsMultiSurface multiSurface;
14629 : 1 : QVERIFY( !multiSurface.boundary() );
14630 : 1 : QgsCircularString boundaryLine1;
14631 : 1 : boundaryLine1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 0, 0 ) );
14632 : 1 : part.clear();
14633 : 1 : part.setExteriorRing( boundaryLine1.clone() );
14634 : 1 : multiSurface.addGeometry( part.clone() );
14635 : 1 : QgsAbstractGeometry *boundary = multiSurface.boundary();
14636 : 1 : QgsMultiCurve *mpBoundary = dynamic_cast< QgsMultiCurve * >( boundary );
14637 : 1 : QVERIFY( mpBoundary );
14638 : 1 : QCOMPARE( mpBoundary->numGeometries(), 1 );
14639 : 1 : QCOMPARE( *static_cast< const QgsCurve *>( mpBoundary->geometryN( 0 ) ), *part.exteriorRing() );
14640 : 1 : delete boundary;
14641 : : // add another QgsCircularString
14642 : 1 : QgsCircularString boundaryLine2;
14643 : 1 : boundaryLine2.setPoints( QgsPointSequence() << QgsPoint( 10, 10 ) << QgsPoint( 11, 10 ) << QgsPoint( 10, 10 ) );
14644 : 1 : QgsCurvePolygon part2;
14645 : 1 : part2.setExteriorRing( boundaryLine2.clone() );
14646 : 1 : multiSurface.addGeometry( part2.clone() );
14647 : 1 : boundary = multiSurface.boundary();
14648 : 1 : mpBoundary = dynamic_cast< QgsMultiCurve * >( boundary );
14649 : 1 : QVERIFY( mpBoundary );
14650 : 1 : QCOMPARE( mpBoundary->numGeometries(), 2 );
14651 : 1 : QCOMPARE( *static_cast< const QgsCurve *>( mpBoundary->geometryN( 0 ) ), *part.exteriorRing() );
14652 : 1 : QCOMPARE( *static_cast< const QgsCurve *>( mpBoundary->geometryN( 1 ) ), *part2.exteriorRing() );
14653 : 1 : delete boundary;
14654 : :
14655 : : //boundary with z
14656 : 1 : QgsCircularString boundaryLine4;
14657 : 1 : boundaryLine4.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 0, 15 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 10 ) );
14658 : 1 : part.clear();
14659 : 1 : part.setExteriorRing( boundaryLine4.clone() );
14660 : 1 : QgsCircularString boundaryLine5;
14661 : 1 : boundaryLine5.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 150 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 100 ) );
14662 : 1 : part2.clear();
14663 : 1 : part2.setExteriorRing( boundaryLine5.clone() );
14664 : 1 : QgsMultiSurface multiSurface2;
14665 : 1 : multiSurface2.addGeometry( part.clone() );
14666 : 1 : multiSurface2.addGeometry( part2.clone() );
14667 : :
14668 : 1 : boundary = multiSurface2.boundary();
14669 : 1 : mpBoundary = dynamic_cast< QgsMultiCurve * >( boundary );
14670 : 1 : QVERIFY( mpBoundary );
14671 : 1 : QCOMPARE( mpBoundary->numGeometries(), 2 );
14672 : 1 : QCOMPARE( *static_cast< const QgsCurve *>( mpBoundary->geometryN( 0 ) ), *part.exteriorRing() );
14673 : 1 : QCOMPARE( *static_cast< const QgsCurve *>( mpBoundary->geometryN( 1 ) ), *part2.exteriorRing() );
14674 : 1 : delete boundary;
14675 : 1 : }
14676 : :
14677 : 1 : void TestQgsGeometry::multiPolygon()
14678 : : {
14679 : : //test constructor
14680 : 1 : QgsMultiPolygon c1;
14681 : 1 : QVERIFY( c1.isEmpty() );
14682 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
14683 : 1 : QCOMPARE( c1.ringCount(), 0 );
14684 : 1 : QCOMPARE( c1.partCount(), 0 );
14685 : 1 : QVERIFY( !c1.is3D() );
14686 : 1 : QVERIFY( !c1.isMeasure() );
14687 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPolygon );
14688 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiPolygon" ) );
14689 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiPolygon" ) );
14690 : 1 : QCOMPARE( c1.dimension(), 0 );
14691 : 1 : QVERIFY( !c1.hasCurvedSegments() );
14692 : 1 : QCOMPARE( c1.area(), 0.0 );
14693 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
14694 : 1 : QCOMPARE( c1.numGeometries(), 0 );
14695 : 1 : QVERIFY( !c1.geometryN( 0 ) );
14696 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14697 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 0 );
14698 : 1 : QCOMPARE( c1.vertexCount( 0, 1 ), 0 );
14699 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
14700 : :
14701 : : //addGeometry
14702 : : //try with nullptr
14703 : 1 : c1.addGeometry( nullptr );
14704 : 1 : QVERIFY( c1.isEmpty() );
14705 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
14706 : 1 : QCOMPARE( c1.ringCount(), 0 );
14707 : 1 : QCOMPARE( c1.partCount(), 0 );
14708 : 1 : QCOMPARE( c1.numGeometries(), 0 );
14709 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPolygon );
14710 : 1 : QVERIFY( !c1.geometryN( 0 ) );
14711 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14712 : :
14713 : : // not a surface
14714 : 1 : QVERIFY( !c1.addGeometry( new QgsPoint() ) );
14715 : 1 : QVERIFY( c1.isEmpty() );
14716 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
14717 : 1 : QCOMPARE( c1.ringCount(), 0 );
14718 : 1 : QCOMPARE( c1.partCount(), 0 );
14719 : 1 : QCOMPARE( c1.numGeometries(), 0 );
14720 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPolygon );
14721 : 1 : QVERIFY( !c1.geometryN( 0 ) );
14722 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14723 : :
14724 : : //valid geometry
14725 : 1 : QgsPolygon part;
14726 : 1 : QgsLineString ring;
14727 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) << QgsPoint( 2, 21 ) << QgsPoint( 1, 10 ) );
14728 : 1 : part.setExteriorRing( ring.clone() );
14729 : 1 : c1.addGeometry( part.clone() );
14730 : 1 : QVERIFY( !c1.isEmpty() );
14731 : 1 : QCOMPARE( c1.numGeometries(), 1 );
14732 : 1 : QCOMPARE( c1.nCoordinates(), 4 );
14733 : 1 : QCOMPARE( c1.ringCount(), 1 );
14734 : 1 : QCOMPARE( c1.partCount(), 1 );
14735 : 1 : QVERIFY( !c1.is3D() );
14736 : 1 : QVERIFY( !c1.isMeasure() );
14737 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::MultiPolygon );
14738 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "MultiPolygon" ) );
14739 : 1 : QCOMPARE( c1.geometryType(), QString( "MultiPolygon" ) );
14740 : 1 : QCOMPARE( c1.dimension(), 2 );
14741 : 1 : QVERIFY( !c1.hasCurvedSegments() );
14742 : 1 : QVERIFY( c1.geometryN( 0 ) );
14743 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c1.geometryN( 0 ) ), part );
14744 : 1 : QVERIFY( !c1.geometryN( 100 ) );
14745 : 1 : QVERIFY( !c1.geometryN( -1 ) );
14746 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 4 );
14747 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
14748 : :
14749 : : //initial adding of geometry should set z/m type
14750 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 20, 21, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 31, 2 )
14751 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 11, 1 ) );
14752 : 1 : part.clear();
14753 : 1 : part.setExteriorRing( ring.clone() );
14754 : 1 : QgsMultiPolygon c2;
14755 : 1 : c2.addGeometry( part.clone() );
14756 : 1 : QVERIFY( c2.is3D() );
14757 : 1 : QVERIFY( !c2.isMeasure() );
14758 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::MultiPolygonZ );
14759 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "MultiPolygonZ" ) );
14760 : 1 : QCOMPARE( c2.geometryType(), QString( "MultiPolygon" ) );
14761 : 1 : QCOMPARE( *( static_cast< const QgsPolygon * >( c2.geometryN( 0 ) ) ), part );
14762 : 1 : QgsMultiPolygon c3;
14763 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 10, 11, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 20, 21, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 30, 31, 0, 2 )
14764 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 11, 0, 1 ) );
14765 : 1 : part.clear();
14766 : 1 : part.setExteriorRing( ring.clone() );
14767 : 1 : c3.addGeometry( part.clone() );
14768 : 1 : QVERIFY( !c3.is3D() );
14769 : 1 : QVERIFY( c3.isMeasure() );
14770 : 1 : QCOMPARE( c3.wkbType(), QgsWkbTypes::MultiPolygonM );
14771 : 1 : QCOMPARE( c3.wktTypeStr(), QString( "MultiPolygonM" ) );
14772 : 1 : QCOMPARE( *( static_cast< const QgsPolygon * >( c3.geometryN( 0 ) ) ), part );
14773 : 1 : QgsMultiPolygon c4;
14774 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 10, 11, 2, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 20, 21, 3, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 30, 31, 3, 2 )
14775 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 11, 2, 1 ) );
14776 : 1 : part.clear();
14777 : 1 : part.setExteriorRing( ring.clone() );
14778 : 1 : c4.addGeometry( part.clone() );
14779 : 1 : QVERIFY( c4.is3D() );
14780 : 1 : QVERIFY( c4.isMeasure() );
14781 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::MultiPolygonZM );
14782 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "MultiPolygonZM" ) );
14783 : 1 : QCOMPARE( *( static_cast< const QgsPolygon * >( c4.geometryN( 0 ) ) ), part );
14784 : :
14785 : : //add another part
14786 : 1 : QgsMultiPolygon c6;
14787 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10 ) << QgsPoint( 2, 11 ) << QgsPoint( 10, 21 ) << QgsPoint( 1, 10 ) );
14788 : 1 : part.clear();
14789 : 1 : part.setExteriorRing( ring.clone() );
14790 : 1 : c6.addGeometry( part.clone() );
14791 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 4 );
14792 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 9, 12 ) << QgsPoint( 3, 13 ) << QgsPoint( 4, 17 ) << QgsPoint( 9, 12 ) );
14793 : 1 : part.clear();
14794 : 1 : part.setExteriorRing( ring.clone() );
14795 : 1 : c6.addGeometry( part.clone() );
14796 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 4 );
14797 : 1 : QCOMPARE( c6.numGeometries(), 2 );
14798 : 1 : QVERIFY( c6.geometryN( 0 ) );
14799 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c6.geometryN( 1 ) ), part );
14800 : :
14801 : : //adding subsequent points should not alter z/m type, regardless of parts type
14802 : 1 : c6.clear();
14803 : 1 : c6.addGeometry( part.clone() );
14804 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygon );
14805 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) << QgsPoint( 10, 13, 3 ) << QgsPoint( 1, 10, 2 ) ) ;
14806 : 1 : part.clear();
14807 : 1 : part.setExteriorRing( ring.clone() );
14808 : 1 : c6.addGeometry( part.clone() );
14809 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygon );
14810 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 4 );
14811 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 4 );
14812 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 0 );
14813 : 1 : QCOMPARE( c6.vertexCount( -1, 0 ), 0 );
14814 : 1 : QCOMPARE( c6.nCoordinates(), 8 );
14815 : 1 : QCOMPARE( c6.ringCount(), 1 );
14816 : 1 : QCOMPARE( c6.partCount(), 2 );
14817 : 1 : QVERIFY( !c6.is3D() );
14818 : 1 : const QgsPolygon *ls = static_cast< const QgsPolygon * >( c6.geometryN( 0 ) );
14819 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 9, 12 ) );
14820 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 3, 13 ) );
14821 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 4, 17 ) );
14822 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( 9, 12 ) );
14823 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 1 ) );
14824 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 1, 10 ) );
14825 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 2, 11 ) );
14826 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 10, 13 ) );
14827 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( 1, 10 ) );
14828 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 21, 30, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 32, 41, 0, 3 )
14829 : 1 : << QgsPoint( QgsWkbTypes::PointM, 42, 61, 0, 4 )
14830 : 1 : << QgsPoint( QgsWkbTypes::PointM, 21, 30, 0, 2 ) ) ;
14831 : 1 : part.clear();
14832 : 1 : part.setExteriorRing( ring.clone() );
14833 : 1 : c6.addGeometry( part.clone() );
14834 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygon );
14835 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 4 );
14836 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 4 );
14837 : 1 : QCOMPARE( c6.vertexCount( 2, 0 ), 4 );
14838 : 1 : QCOMPARE( c6.nCoordinates(), 12 );
14839 : 1 : QCOMPARE( c6.ringCount(), 1 );
14840 : 1 : QCOMPARE( c6.partCount(), 3 );
14841 : 1 : QVERIFY( !c6.is3D() );
14842 : 1 : QVERIFY( !c6.isMeasure() );
14843 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 2 ) );
14844 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 21, 30 ) );
14845 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 32, 41 ) );
14846 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 42, 61 ) );
14847 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( 21, 30 ) );
14848 : :
14849 : 1 : c6.clear();
14850 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 1, 10, 2 ) << QgsPoint( 2, 11, 3 ) << QgsPoint( 9, 15, 3 ) << QgsPoint( 1, 10, 2 ) ) ;
14851 : 1 : part.clear();
14852 : 1 : part.setExteriorRing( ring.clone() );
14853 : 1 : c6.addGeometry( part.clone() );
14854 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZ );
14855 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) << QgsPoint( 7, 34 ) << QgsPoint( 2, 20 ) ) ;
14856 : 1 : part.clear();
14857 : 1 : part.setExteriorRing( ring.clone() );
14858 : 1 : c6.addGeometry( part.clone() );
14859 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZ );
14860 : 1 : QVERIFY( c6.is3D() );
14861 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 0 ) );
14862 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 1, 10, 2 ) );
14863 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 2, 11, 3 ) );
14864 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 9, 15, 3 ) );
14865 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( 1, 10, 2 ) );
14866 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 1 ) );
14867 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 2, 20, 0 ) );
14868 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 3, 31, 0 ) );
14869 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 7, 34, 0 ) );
14870 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( 2, 20, 0 ) );
14871 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 )
14872 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 65, 0, 7 ) << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) ) ;
14873 : 1 : part.clear();
14874 : 1 : part.setExteriorRing( ring.clone() );
14875 : 1 : c6.addGeometry( part.clone() );
14876 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZ );
14877 : 1 : QVERIFY( c6.is3D() );
14878 : 1 : QVERIFY( !c6.isMeasure() );
14879 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 2 ) );
14880 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( 5, 50, 0 ) );
14881 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( 6, 61, 0 ) );
14882 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( 9, 65, 0 ) );
14883 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( 5, 50, 0 ) );
14884 : :
14885 : 1 : c6.clear();
14886 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygon );
14887 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 )
14888 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 76, 0, 8 ) << QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) ) ;
14889 : 1 : part.clear();
14890 : 1 : part.setExteriorRing( ring.clone() );
14891 : 1 : c6.addGeometry( part.clone() );
14892 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonM );
14893 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 2, 20 ) << QgsPoint( 3, 31 ) << QgsPoint( 7, 39 ) << QgsPoint( 2, 20 ) ) ;
14894 : 1 : part.clear();
14895 : 1 : part.setExteriorRing( ring.clone() );
14896 : 1 : c6.addGeometry( part.clone() );
14897 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonM );
14898 : 1 : QVERIFY( c6.isMeasure() );
14899 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 0 ) );
14900 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) );
14901 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 6, 61, 0, 5 ) );
14902 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 9, 76, 0, 8 ) );
14903 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointM, 5, 50, 0, 4 ) );
14904 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 1 ) );
14905 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 2, 20, 0, 0 ) );
14906 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 3, 31, 0, 0 ) );
14907 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 7, 39, 0, 0 ) );
14908 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointM, 2, 20, 0, 0 ) );
14909 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( 11, 12, 13 ) << QgsPoint( 14, 15, 16 ) << QgsPoint( 24, 21, 5 ) << QgsPoint( 11, 12, 13 ) ) ;
14910 : 1 : part.clear();
14911 : 1 : part.setExteriorRing( ring.clone() );
14912 : 1 : c6.addGeometry( part.clone() );
14913 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonM );
14914 : 1 : QVERIFY( !c6.is3D() );
14915 : 1 : QVERIFY( c6.isMeasure() );
14916 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 2 ) );
14917 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
14918 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointM, 14, 15, 0, 0 ) );
14919 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointM, 24, 21, 0, 0 ) );
14920 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 0 ) );
14921 : :
14922 : 1 : c6.clear();
14923 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 )
14924 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 71, 4, 9 ) << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) ) ;
14925 : 1 : part.clear();
14926 : 1 : part.setExteriorRing( ring.clone() );
14927 : 1 : c6.addGeometry( part.clone() );
14928 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZM );
14929 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 )
14930 : 1 : << QgsPoint( QgsWkbTypes::Point, 13, 27 ) << QgsPoint( QgsWkbTypes::Point, 7, 17 ) ) ;
14931 : 1 : part.clear();
14932 : 1 : part.setExteriorRing( ring.clone() );
14933 : 1 : c6.addGeometry( part.clone() );
14934 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZM );
14935 : 1 : QVERIFY( c6.isMeasure() );
14936 : 1 : QVERIFY( c6.is3D() );
14937 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 0 ) );
14938 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) );
14939 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 ) );
14940 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 9, 71, 4, 9 ) );
14941 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) );
14942 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 1 ) );
14943 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 0, 0 ) );
14944 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 3, 13, 0, 0 ) );
14945 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 13, 27, 0, 0 ) );
14946 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointZM, 7, 17, 0, 0 ) );
14947 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 77, 87, 7 ) << QgsPoint( QgsWkbTypes::PointZ, 83, 83, 8 )
14948 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 93, 85, 10 ) << QgsPoint( QgsWkbTypes::PointZ, 77, 87, 7 ) ) ;
14949 : 1 : part.clear();
14950 : 1 : part.setExteriorRing( ring.clone() );
14951 : 1 : c6.addGeometry( part.clone() );
14952 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZM );
14953 : 1 : QVERIFY( c6.is3D() );
14954 : 1 : QVERIFY( c6.isMeasure() );
14955 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 2 ) );
14956 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 77, 87, 7, 0 ) );
14957 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 83, 83, 8, 0 ) );
14958 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 93, 85, 10, 0 ) );
14959 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointZM, 77, 87, 7, 0 ) );
14960 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 177, 187, 0, 9 ) << QgsPoint( QgsWkbTypes::PointM, 183, 183, 0, 11 )
14961 : 1 : << QgsPoint( QgsWkbTypes::PointM, 185, 193, 0, 13 ) << QgsPoint( QgsWkbTypes::PointM, 177, 187, 0, 9 ) ) ;
14962 : 1 : part.clear();
14963 : 1 : part.setExteriorRing( ring.clone() );
14964 : 1 : c6.addGeometry( part.clone() );
14965 : 1 : QCOMPARE( c6.wkbType(), QgsWkbTypes::MultiPolygonZM );
14966 : 1 : QVERIFY( c6.is3D() );
14967 : 1 : QVERIFY( c6.isMeasure() );
14968 : 1 : ls = static_cast< const QgsPolygon * >( c6.geometryN( 3 ) );
14969 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 177, 187, 0, 9 ) );
14970 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 183, 183, 0, 11 ) );
14971 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 2 ), QgsPoint( QgsWkbTypes::PointZM, 185, 193, 0, 13 ) );
14972 : 1 : QCOMPARE( static_cast< const QgsLineString *>( ls->exteriorRing() )->pointN( 3 ), QgsPoint( QgsWkbTypes::PointZM, 177, 187, 0, 9 ) );
14973 : :
14974 : : //clear
14975 : 1 : QgsMultiPolygon c7;
14976 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 5, 50, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 6, 61, 3, 5 )
14977 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 71, 4, 15 ) << QgsPoint( QgsWkbTypes::PointZM, 5, 71, 4, 6 ) ) ;
14978 : 1 : part.clear();
14979 : 1 : part.setExteriorRing( ring.clone() );
14980 : 1 : c7.addGeometry( part.clone() );
14981 : 1 : c7.addGeometry( part.clone() );
14982 : 1 : QCOMPARE( c7.numGeometries(), 2 );
14983 : 1 : c7.clear();
14984 : 1 : QVERIFY( c7.isEmpty() );
14985 : 1 : QCOMPARE( c7.numGeometries(), 0 );
14986 : 1 : QCOMPARE( c7.nCoordinates(), 0 );
14987 : 1 : QCOMPARE( c7.ringCount(), 0 );
14988 : 1 : QCOMPARE( c7.partCount(), 0 );
14989 : 1 : QVERIFY( !c7.is3D() );
14990 : 1 : QVERIFY( !c7.isMeasure() );
14991 : 1 : QCOMPARE( c7.wkbType(), QgsWkbTypes::MultiPolygon );
14992 : :
14993 : : //clone
14994 : 1 : QgsMultiPolygon c11;
14995 : 1 : std::unique_ptr< QgsMultiPolygon >cloned( c11.clone() );
14996 : 1 : QVERIFY( cloned->isEmpty() );
14997 : 1 : c11.addGeometry( part.clone() );
14998 : 1 : c11.addGeometry( part.clone() );
14999 : 1 : cloned.reset( c11.clone() );
15000 : 1 : QCOMPARE( cloned->numGeometries(), 2 );
15001 : 1 : ls = static_cast< const QgsPolygon * >( cloned->geometryN( 0 ) );
15002 : 1 : QCOMPARE( *ls, part );
15003 : 1 : ls = static_cast< const QgsPolygon * >( cloned->geometryN( 1 ) );
15004 : 1 : QCOMPARE( *ls, part );
15005 : :
15006 : : //copy constructor
15007 : 1 : QgsMultiPolygon c12;
15008 : 1 : QgsMultiPolygon c13( c12 );
15009 : 1 : QVERIFY( c13.isEmpty() );
15010 : 1 : c12.addGeometry( part.clone() );
15011 : 1 : c12.addGeometry( part.clone() );
15012 : 1 : QgsMultiPolygon c14( c12 );
15013 : 1 : QCOMPARE( c14.numGeometries(), 2 );
15014 : 1 : QCOMPARE( c14.wkbType(), QgsWkbTypes::MultiPolygonZM );
15015 : 1 : ls = static_cast< const QgsPolygon * >( c14.geometryN( 0 ) );
15016 : 1 : QCOMPARE( *ls, part );
15017 : 1 : ls = static_cast< const QgsPolygon * >( c14.geometryN( 1 ) );
15018 : 1 : QCOMPARE( *ls, part );
15019 : :
15020 : : //assignment operator
15021 : 1 : QgsMultiPolygon c15;
15022 : 1 : c15 = c13;
15023 : 1 : QCOMPARE( c15.numGeometries(), 0 );
15024 : 1 : c15 = c14;
15025 : 1 : QCOMPARE( c15.numGeometries(), 2 );
15026 : 1 : ls = static_cast< const QgsPolygon * >( c15.geometryN( 0 ) );
15027 : 1 : QCOMPARE( *ls, part );
15028 : 1 : ls = static_cast< const QgsPolygon * >( c15.geometryN( 1 ) );
15029 : 1 : QCOMPARE( *ls, part );
15030 : :
15031 : : //toCurveType
15032 : 1 : std::unique_ptr< QgsMultiSurface > curveType( c12.toCurveType() );
15033 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::MultiSurfaceZM );
15034 : 1 : QCOMPARE( curveType->numGeometries(), 2 );
15035 : 1 : const QgsPolygon *curve = static_cast< const QgsPolygon * >( curveType->geometryN( 0 ) );
15036 : 1 : QCOMPARE( *curve, *static_cast< const QgsPolygon * >( c12.geometryN( 0 ) ) );
15037 : 1 : curve = static_cast< const QgsPolygon * >( curveType->geometryN( 1 ) );
15038 : 1 : QCOMPARE( *curve, *static_cast< const QgsPolygon * >( c12.geometryN( 1 ) ) );
15039 : :
15040 : : //to/fromWKB
15041 : 1 : QgsMultiPolygon c16;
15042 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 ) << QgsPoint( QgsWkbTypes::Point, 9, 27 ) << QgsPoint( QgsWkbTypes::Point, 7, 17 ) ) ;
15043 : 1 : part.clear();
15044 : 1 : part.setExteriorRing( ring.clone() );
15045 : 1 : c16.addGeometry( part.clone() );
15046 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 ) << QgsPoint( QgsWkbTypes::Point, 29, 39 ) << QgsPoint( QgsWkbTypes::Point, 27, 37 ) ) ;
15047 : 1 : part.clear();
15048 : 1 : part.setExteriorRing( ring.clone() );
15049 : 1 : c16.addGeometry( part.clone() );
15050 : 1 : QByteArray wkb16 = c16.asWkb();
15051 : 1 : QCOMPARE( wkb16.size(), c16.wkbSize() );
15052 : 1 : QgsMultiPolygon c17;
15053 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
15054 : 1 : c17.fromWkb( wkb16ptr );
15055 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15056 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 0 ) ) );
15057 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 1 ) ) );
15058 : :
15059 : : //parts with Z
15060 : 1 : c16.clear();
15061 : 1 : c17.clear();
15062 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 7, 17, 1 ) << QgsPoint( QgsWkbTypes::PointZ, 3, 13, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 9, 27, 5 ) << QgsPoint( QgsWkbTypes::PointZ, 7, 17, 1 ) ) ;
15063 : 1 : part.clear();
15064 : 1 : part.setExteriorRing( ring.clone() );
15065 : 1 : c16.addGeometry( part.clone() );
15066 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 27, 37, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 43, 43, 5 ) << QgsPoint( QgsWkbTypes::PointZ, 87, 54, 7 ) << QgsPoint( QgsWkbTypes::PointZ, 27, 37, 2 ) ) ;
15067 : 1 : part.clear();
15068 : 1 : part.setExteriorRing( ring.clone() );
15069 : 1 : c16.addGeometry( part.clone() );
15070 : 1 : wkb16 = c16.asWkb();
15071 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
15072 : 1 : c17.fromWkb( wkb16ptr2 );
15073 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15074 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPolygonZ );
15075 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 0 ) ) );
15076 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 1 ) ) );
15077 : :
15078 : : //parts with m
15079 : 1 : c16.clear();
15080 : 1 : c17.clear();
15081 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 7, 17, 0, 1 ) << QgsPoint( QgsWkbTypes::PointM, 3, 13, 0, 4 )
15082 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 21, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 7, 17, 0, 1 ) ) ;
15083 : 1 : part.clear();
15084 : 1 : part.setExteriorRing( ring.clone() );
15085 : 1 : c16.addGeometry( part.clone() );
15086 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 27, 37, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 43, 43, 0, 5 )
15087 : 1 : << QgsPoint( QgsWkbTypes::PointM, 37, 31, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 27, 37, 0, 2 ) ) ;
15088 : 1 : part.clear();
15089 : 1 : part.setExteriorRing( ring.clone() );
15090 : 1 : c16.addGeometry( part.clone() );
15091 : 1 : wkb16 = c16.asWkb();
15092 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
15093 : 1 : c17.fromWkb( wkb16ptr3 );
15094 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15095 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPolygonM );
15096 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 0 ) ) );
15097 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 1 ) ) );
15098 : :
15099 : : // parts with ZM
15100 : 1 : c16.clear();
15101 : 1 : c17.clear();
15102 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 )
15103 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 19, 13, 5, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) ) ;
15104 : 1 : part.clear();
15105 : 1 : part.setExteriorRing( ring.clone() );
15106 : 1 : c16.addGeometry( part.clone() );
15107 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 )
15108 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) ) ;
15109 : 1 : part.clear();
15110 : 1 : part.setExteriorRing( ring.clone() );
15111 : 1 : c16.addGeometry( part.clone() );
15112 : 1 : wkb16 = c16.asWkb();
15113 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
15114 : 1 : c17.fromWkb( wkb16ptr4 );
15115 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15116 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPolygonZM );
15117 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 0 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 0 ) ) );
15118 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c17.geometryN( 1 ) ), *static_cast< const QgsPolygon * >( c16.geometryN( 1 ) ) );
15119 : :
15120 : : //bad WKB - check for no crash
15121 : 1 : c17.clear();
15122 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
15123 : 1 : QVERIFY( !c17.fromWkb( nullPtr ) );
15124 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPolygon );
15125 : 1 : QgsPoint point( 1, 2 );
15126 : 1 : QByteArray wkbPoint = point.asWkb();
15127 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
15128 : 1 : QVERIFY( !c17.fromWkb( wkbPointPtr ) );
15129 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::MultiPolygon );
15130 : :
15131 : : //to/from WKT
15132 : 1 : QgsMultiPolygon c18;
15133 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 7, 17, 4, 1 ) << QgsPoint( QgsWkbTypes::PointZM, 3, 13, 1, 4 )
15134 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 13, 19, 3, 10 ) << QgsPoint( QgsWkbTypes::PointZM, 7, 11, 2, 8 ) ) ;
15135 : 1 : part.clear();
15136 : 1 : part.setExteriorRing( ring.clone() );
15137 : 1 : c18.addGeometry( part.clone() );
15138 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 27, 37, 6, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 43, 43, 11, 5 )
15139 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 17, 49, 31, 53 ) << QgsPoint( QgsWkbTypes::PointZM, 27, 53, 21, 52 ) ) ;
15140 : 1 : part.clear();
15141 : 1 : part.setExteriorRing( ring.clone() );
15142 : 1 : c18.addGeometry( part.clone() );
15143 : :
15144 : 1 : QString wkt = c18.asWkt();
15145 : 1 : QVERIFY( !wkt.isEmpty() );
15146 : 1 : QgsMultiPolygon c19;
15147 : 1 : QVERIFY( c19.fromWkt( wkt ) );
15148 : 1 : QCOMPARE( c19.numGeometries(), 2 );
15149 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c19.geometryN( 0 ) ), *static_cast< const QgsPolygon * >( c18.geometryN( 0 ) ) );
15150 : 1 : QCOMPARE( *static_cast< const QgsPolygon * >( c19.geometryN( 1 ) ), *static_cast< const QgsPolygon * >( c18.geometryN( 1 ) ) );
15151 : :
15152 : : //bad WKT
15153 : 1 : QgsMultiPolygon c20;
15154 : 1 : QVERIFY( !c20.fromWkt( "Point()" ) );
15155 : 1 : QVERIFY( c20.isEmpty() );
15156 : 1 : QCOMPARE( c20.numGeometries(), 0 );
15157 : 1 : QCOMPARE( c20.wkbType(), QgsWkbTypes::MultiPolygon );
15158 : :
15159 : : //as JSON
15160 : 1 : QgsMultiPolygon exportC;
15161 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7, 17 ) << QgsPoint( QgsWkbTypes::Point, 3, 13 )
15162 : 1 : << QgsPoint( QgsWkbTypes::Point, 7, 21 ) << QgsPoint( QgsWkbTypes::Point, 7, 17 ) ) ;
15163 : 1 : part.clear();
15164 : 1 : part.setExteriorRing( ring.clone() );
15165 : 1 : exportC.addGeometry( part.clone() );
15166 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27, 37 ) << QgsPoint( QgsWkbTypes::Point, 43, 43 )
15167 : 1 : << QgsPoint( QgsWkbTypes::Point, 41, 39 ) << QgsPoint( QgsWkbTypes::Point, 27, 37 ) ) ;
15168 : 1 : part.clear();
15169 : 1 : part.setExteriorRing( ring.clone() );
15170 : 1 : exportC.addGeometry( part.clone() );
15171 : :
15172 : : // GML document for compare
15173 : 1 : QDomDocument doc( "gml" );
15174 : :
15175 : : // as GML2
15176 : 2 : QString expectedSimpleGML2( QStringLiteral( "<MultiPolygon xmlns=\"gml\"><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">7,17 3,13 7,21 7,17</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">27,37 43,43 41,39 27,37</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember></MultiPolygon>" ) );
15177 : 1 : QString res = elemToString( exportC.asGml2( doc, 1 ) );
15178 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
15179 : 2 : QString expectedGML2empty( QStringLiteral( "<MultiPolygon xmlns=\"gml\"/>" ) );
15180 : 3 : QGSCOMPAREGML( elemToString( QgsMultiPolygon().asGml2( doc ) ), expectedGML2empty );
15181 : :
15182 : : //as GML3
15183 : 2 : QString expectedSimpleGML3( QStringLiteral( "<MultiPolygon xmlns=\"gml\"><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">7 17 3 13 7 21 7 17</posList></LinearRing></exterior></Polygon></polygonMember><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">27 37 43 43 41 39 27 37</posList></LinearRing></exterior></Polygon></polygonMember></MultiPolygon>" ) );
15184 : 1 : res = elemToString( exportC.asGml3( doc ) );
15185 : 1 : QCOMPARE( res, expectedSimpleGML3 );
15186 : 2 : QString expectedGML3empty( QStringLiteral( "<MultiPolygon xmlns=\"gml\"/>" ) );
15187 : 3 : QGSCOMPAREGML( elemToString( QgsMultiPolygon().asGml3( doc ) ), expectedGML3empty );
15188 : :
15189 : : // as JSON
15190 : 1 : QString expectedSimpleJson( "{\"coordinates\":[[[[7.0,17.0],[3.0,13.0],[7.0,21.0],[7.0,17.0]]],[[[27.0,37.0],[43.0,43.0],[41.0,39.0],[27.0,37.0]]]],\"type\":\"MultiPolygon\"}" );
15191 : 1 : res = exportC.asJson( 1 );
15192 : 1 : QCOMPARE( res, expectedSimpleJson );
15193 : :
15194 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 17, 27 ) << QgsPoint( QgsWkbTypes::Point, 18, 28 ) << QgsPoint( QgsWkbTypes::Point, 19, 37 ) << QgsPoint( QgsWkbTypes::Point, 17, 27 ) ) ;
15195 : 1 : part.addInteriorRing( ring.clone() );
15196 : 1 : exportC.addGeometry( part.clone() );
15197 : :
15198 : 1 : QString expectedJsonWithRings( "{\"coordinates\":[[[[7.0,17.0],[3.0,13.0],[7.0,21.0],[7.0,17.0]]],[[[27.0,37.0],[43.0,43.0],[41.0,39.0],[27.0,37.0]]],[[[27.0,37.0],[43.0,43.0],[41.0,39.0],[27.0,37.0]],[[17.0,27.0],[18.0,28.0],[19.0,37.0],[17.0,27.0]]]],\"type\":\"MultiPolygon\"}" );
15199 : 1 : res = exportC.asJson( 1 );
15200 : 1 : QCOMPARE( res, expectedJsonWithRings );
15201 : :
15202 : 1 : QgsMultiPolygon exportFloat;
15203 : 2 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 7 / 3.0, 17 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 3 / 5.0, 13 / 3.0 )
15204 : 1 : << QgsPoint( QgsWkbTypes::Point, 8 / 3.0, 27 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 7 / 3.0, 17 / 3.0 ) ) ;
15205 : 1 : part.clear();
15206 : 1 : part.setExteriorRing( ring.clone() );
15207 : 1 : exportFloat.addGeometry( part.clone() );
15208 : 1 : ring.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 27 / 3.0, 37 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 43 / 41.0, 43 / 42.0 ) << QgsPoint( QgsWkbTypes::Point, 27 / 3.0, 37 / 9.0 ) ) ;
15209 : 1 : part.clear();
15210 : 1 : part.setExteriorRing( ring.clone() );
15211 : 1 : exportFloat.addGeometry( part.clone() );
15212 : :
15213 : 1 : QString expectedJsonPrec3( "{\"coordinates\":[[[[2.333,5.667],[0.6,4.333],[2.667,9.0],[2.333,5.667]]],[[[9.0,4.111],[1.049,1.024],[9.0,4.111]]]],\"type\":\"MultiPolygon\"}" );
15214 : 1 : res = exportFloat.asJson( 3 );
15215 : 1 : QCOMPARE( res, expectedJsonPrec3 );
15216 : :
15217 : : // as GML2
15218 : 1 : QString expectedGML2prec3( "<MultiPolygon xmlns=\"gml\"><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">2.333,5.667 0.6,4.333 2.667,9 2.333,5.667</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><outerBoundaryIs xmlns=\"gml\"><LinearRing xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">9,4.111 1.049,1.024 9,4.111</coordinates></LinearRing></outerBoundaryIs></Polygon></polygonMember></MultiPolygon>" );
15219 : 1 : res = elemToString( exportFloat.asGml2( doc, 3 ) );
15220 : 3 : QGSCOMPAREGML( res, expectedGML2prec3 );
15221 : :
15222 : : //as GML3
15223 : 1 : QString expectedGML3prec3( "<MultiPolygon xmlns=\"gml\"><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">2.333 5.667 0.6 4.333 2.667 9 2.333 5.667</posList></LinearRing></exterior></Polygon></polygonMember><polygonMember xmlns=\"gml\"><Polygon xmlns=\"gml\"><exterior xmlns=\"gml\"><LinearRing xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">9 4.111 1.049 1.024 9 4.111</posList></LinearRing></exterior></Polygon></polygonMember></MultiPolygon>" );
15224 : 1 : res = elemToString( exportFloat.asGml3( doc, 3 ) );
15225 : 1 : QCOMPARE( res, expectedGML3prec3 );
15226 : :
15227 : : //asKML
15228 : 1 : QString expectedKmlPrec3( "<MultiGeometry><Polygon><outerBoundaryIs><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>2.333,5.667,0 0.6,4.333,0 2.667,9,0 2.333,5.667,0</coordinates></LinearRing></outerBoundaryIs></Polygon><Polygon><outerBoundaryIs><LineString><altitudeMode>clampToGround</altitudeMode><coordinates>9,4.111,0 1.049,1.024,0 9,4.111,0</coordinates></LineString></outerBoundaryIs></Polygon></MultiGeometry>" );
15229 : 1 : QCOMPARE( exportFloat.asKml( 3 ), expectedKmlPrec3 );
15230 : :
15231 : :
15232 : : // insert geometry
15233 : 1 : QgsMultiPolygon rc;
15234 : 1 : rc.clear();
15235 : 1 : rc.insertGeometry( nullptr, 0 );
15236 : 1 : QVERIFY( rc.isEmpty() );
15237 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15238 : 1 : rc.insertGeometry( nullptr, -1 );
15239 : 1 : QVERIFY( rc.isEmpty() );
15240 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15241 : 1 : rc.insertGeometry( nullptr, 100 );
15242 : 1 : QVERIFY( rc.isEmpty() );
15243 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15244 : :
15245 : 1 : rc.insertGeometry( new QgsPoint(), 0 );
15246 : 1 : QVERIFY( rc.isEmpty() );
15247 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15248 : :
15249 : 1 : rc.insertGeometry( part.clone(), 0 );
15250 : 1 : QVERIFY( !rc.isEmpty() );
15251 : 1 : QCOMPARE( rc.numGeometries(), 1 );
15252 : :
15253 : : // cast
15254 : 1 : QVERIFY( !QgsMultiPolygon().cast( nullptr ) );
15255 : 1 : QgsMultiPolygon pCast;
15256 : 1 : QVERIFY( QgsMultiPolygon().cast( &pCast ) );
15257 : 1 : QgsMultiPolygon pCast2;
15258 : 2 : pCast2.fromWkt( QStringLiteral( "MultiPolygonZ()" ) );
15259 : 1 : QVERIFY( QgsMultiPolygon().cast( &pCast2 ) );
15260 : 2 : pCast2.fromWkt( QStringLiteral( "MultiPolygonM()" ) );
15261 : 1 : QVERIFY( QgsMultiPolygon().cast( &pCast2 ) );
15262 : 2 : pCast2.fromWkt( QStringLiteral( "MultiPolygonZM()" ) );
15263 : 1 : QVERIFY( QgsMultiPolygon().cast( &pCast2 ) );
15264 : :
15265 : :
15266 : : //boundary
15267 : 1 : QgsMultiPolygon multiPolygon1;
15268 : 1 : QVERIFY( !multiPolygon1.boundary() );
15269 : :
15270 : 1 : QgsLineString ring1;
15271 : 1 : ring1.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 0, 0 ) );
15272 : 1 : QgsPolygon polygon1;
15273 : 1 : polygon1.setExteriorRing( ring1.clone() );
15274 : 1 : multiPolygon1.addGeometry( polygon1.clone() );
15275 : :
15276 : 1 : std::unique_ptr< QgsAbstractGeometry > boundary( multiPolygon1.boundary() );
15277 : 1 : QgsMultiLineString *lineBoundary = dynamic_cast< QgsMultiLineString * >( boundary.get() );
15278 : 1 : QVERIFY( lineBoundary );
15279 : 1 : QCOMPARE( lineBoundary->numGeometries(), 1 );
15280 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->numPoints(), 4 );
15281 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
15282 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
15283 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->xAt( 2 ), 1.0 );
15284 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->xAt( 3 ), 0.0 );
15285 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
15286 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
15287 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->yAt( 2 ), 1.0 );
15288 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( lineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.0 );
15289 : :
15290 : : // add polygon with interior rings
15291 : 1 : QgsLineString ring2;
15292 : 1 : ring2.setPoints( QgsPointSequence() << QgsPoint( 10, 10 ) << QgsPoint( 11, 10 ) << QgsPoint( 11, 11 ) << QgsPoint( 10, 10 ) );
15293 : 1 : QgsPolygon polygon2;
15294 : 1 : polygon2.setExteriorRing( ring2.clone() );
15295 : 1 : QgsLineString boundaryRing1;
15296 : 1 : boundaryRing1.setPoints( QgsPointSequence() << QgsPoint( 10.1, 10.1 ) << QgsPoint( 10.2, 10.1 ) << QgsPoint( 10.2, 10.2 ) << QgsPoint( 10.1, 10.1 ) );
15297 : 1 : QgsLineString boundaryRing2;
15298 : 1 : boundaryRing2.setPoints( QgsPointSequence() << QgsPoint( 10.8, 10.8 ) << QgsPoint( 10.9, 10.8 ) << QgsPoint( 10.9, 10.9 ) << QgsPoint( 10.8, 10.8 ) );
15299 : 1 : polygon2.setInteriorRings( QVector< QgsCurve * >() << boundaryRing1.clone() << boundaryRing2.clone() );
15300 : 1 : multiPolygon1.addGeometry( polygon2.clone() );
15301 : :
15302 : 1 : boundary.reset( multiPolygon1.boundary() );
15303 : 1 : QgsMultiLineString *multiLineBoundary( static_cast< QgsMultiLineString * >( boundary.get() ) );
15304 : 1 : QVERIFY( multiLineBoundary );
15305 : 1 : QCOMPARE( multiLineBoundary->numGeometries(), 4 );
15306 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->numPoints(), 4 );
15307 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 0 ), 0.0 );
15308 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 1 ), 1.0 );
15309 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 2 ), 1.0 );
15310 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->xAt( 3 ), 0.0 );
15311 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 0 ), 0.0 );
15312 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 1 ), 0.0 );
15313 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 2 ), 1.0 );
15314 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 0 ) )->yAt( 3 ), 0.0 );
15315 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->numPoints(), 4 );
15316 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 0 ), 10.0 );
15317 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 1 ), 11.0 );
15318 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 2 ), 11.0 );
15319 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->xAt( 3 ), 10.0 );
15320 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 0 ), 10.0 );
15321 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 1 ), 10.0 );
15322 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 2 ), 11.0 );
15323 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 1 ) )->yAt( 3 ), 10.0 );
15324 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->numPoints(), 4 );
15325 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 0 ), 10.1 );
15326 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 1 ), 10.2 );
15327 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 2 ), 10.2 );
15328 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->xAt( 3 ), 10.1 );
15329 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 0 ), 10.1 );
15330 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 1 ), 10.1 );
15331 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 2 ), 10.2 );
15332 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 2 ) )->yAt( 3 ), 10.1 );
15333 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->numPoints(), 4 );
15334 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->xAt( 0 ), 10.8 );
15335 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->xAt( 1 ), 10.9 );
15336 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->xAt( 2 ), 10.9 );
15337 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->xAt( 3 ), 10.8 );
15338 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->yAt( 0 ), 10.8 );
15339 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->yAt( 1 ), 10.8 );
15340 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->yAt( 2 ), 10.9 );
15341 : 1 : QCOMPARE( dynamic_cast< QgsLineString * >( multiLineBoundary->geometryN( 3 ) )->yAt( 3 ), 10.8 );
15342 : :
15343 : : // vertex iterator: 2 polygons (one with just exterior ring, other with two interior rings)
15344 : 1 : QgsAbstractGeometry::vertex_iterator it = multiPolygon1.vertices_begin();
15345 : 1 : QgsAbstractGeometry::vertex_iterator itEnd = multiPolygon1.vertices_end();
15346 : 1 : QCOMPARE( *it, QgsPoint( 0, 0 ) );
15347 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 0 ) );
15348 : 1 : ++it;
15349 : 1 : QCOMPARE( *it, QgsPoint( 1, 0 ) );
15350 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 1 ) );
15351 : 1 : ++it;
15352 : 1 : QCOMPARE( *it, QgsPoint( 1, 1 ) );
15353 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 2 ) );
15354 : 1 : ++it;
15355 : 1 : QCOMPARE( *it, QgsPoint( 0, 0 ) );
15356 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 0, 0, 3 ) );
15357 : 1 : ++it;
15358 : : // 2nd polygon - exterior ring
15359 : 1 : QCOMPARE( *it, QgsPoint( 10, 10 ) );
15360 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 0 ) );
15361 : 1 : ++it;
15362 : 1 : QCOMPARE( *it, QgsPoint( 11, 10 ) );
15363 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 1 ) );
15364 : 1 : ++it;
15365 : 1 : QCOMPARE( *it, QgsPoint( 11, 11 ) );
15366 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 2 ) );
15367 : 1 : ++it;
15368 : 1 : QCOMPARE( *it, QgsPoint( 10, 10 ) );
15369 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 0, 3 ) );
15370 : 1 : ++it;
15371 : : // 2nd polygon - 1st interior ring
15372 : 1 : QCOMPARE( *it, QgsPoint( 10.1, 10.1 ) );
15373 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 1, 0 ) );
15374 : 1 : ++it;
15375 : 1 : QCOMPARE( *it, QgsPoint( 10.2, 10.1 ) );
15376 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 1, 1 ) );
15377 : 1 : ++it;
15378 : 1 : QCOMPARE( *it, QgsPoint( 10.2, 10.2 ) );
15379 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 1, 2 ) );
15380 : 1 : ++it;
15381 : 1 : QCOMPARE( *it, QgsPoint( 10.1, 10.1 ) );
15382 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 1, 3 ) );
15383 : 1 : ++it;
15384 : : // 2nd polygon - 2nd interior ring
15385 : 1 : QCOMPARE( *it, QgsPoint( 10.8, 10.8 ) );
15386 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 2, 0 ) );
15387 : 1 : ++it;
15388 : 1 : QCOMPARE( *it, QgsPoint( 10.9, 10.8 ) );
15389 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 2, 1 ) );
15390 : 1 : ++it;
15391 : 1 : QCOMPARE( *it, QgsPoint( 10.9, 10.9 ) );
15392 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 2, 2 ) );
15393 : 1 : ++it;
15394 : 1 : QCOMPARE( *it, QgsPoint( 10.8, 10.8 ) );
15395 : 1 : QCOMPARE( it.vertexId(), QgsVertexId( 1, 2, 3 ) );
15396 : 1 : ++it;
15397 : : // done!
15398 : 1 : QCOMPARE( it, itEnd );
15399 : :
15400 : : // Java-style iterator
15401 : 1 : QgsVertexIterator it2( &multiPolygon1 );
15402 : 1 : QVERIFY( it2.hasNext() );
15403 : 1 : QCOMPARE( it2.next(), QgsPoint( 0, 0 ) );
15404 : 1 : QVERIFY( it2.hasNext() );
15405 : 1 : QCOMPARE( it2.next(), QgsPoint( 1, 0 ) );
15406 : 1 : QVERIFY( it2.hasNext() );
15407 : 1 : QCOMPARE( it2.next(), QgsPoint( 1, 1 ) );
15408 : 1 : QVERIFY( it2.hasNext() );
15409 : 1 : QCOMPARE( it2.next(), QgsPoint( 0, 0 ) );
15410 : 1 : QVERIFY( it2.hasNext() );
15411 : : // 2nd polygon - exterior ring
15412 : 1 : QCOMPARE( it2.next(), QgsPoint( 10, 10 ) );
15413 : 1 : QVERIFY( it2.hasNext() );
15414 : 1 : QCOMPARE( it2.next(), QgsPoint( 11, 10 ) );
15415 : 1 : QVERIFY( it2.hasNext() );
15416 : 1 : QCOMPARE( it2.next(), QgsPoint( 11, 11 ) );
15417 : 1 : QVERIFY( it2.hasNext() );
15418 : 1 : QCOMPARE( it2.next(), QgsPoint( 10, 10 ) );
15419 : 1 : QVERIFY( it2.hasNext() );
15420 : : // 2nd polygon - 1st interior ring
15421 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.1, 10.1 ) );
15422 : 1 : QVERIFY( it2.hasNext() );
15423 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.2, 10.1 ) );
15424 : 1 : QVERIFY( it2.hasNext() );
15425 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.2, 10.2 ) );
15426 : 1 : QVERIFY( it2.hasNext() );
15427 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.1, 10.1 ) );
15428 : 1 : QVERIFY( it2.hasNext() );
15429 : : // 2nd polygon - 2nd interior ring
15430 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.8, 10.8 ) );
15431 : 1 : QVERIFY( it2.hasNext() );
15432 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.9, 10.8 ) );
15433 : 1 : QVERIFY( it2.hasNext() );
15434 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.9, 10.9 ) );
15435 : 1 : QVERIFY( it2.hasNext() );
15436 : 1 : QCOMPARE( it2.next(), QgsPoint( 10.8, 10.8 ) );
15437 : 1 : QVERIFY( !it2.hasNext() );
15438 : :
15439 : : //removeDuplicateNodes
15440 : 1 : QgsMultiPolygon dn1;
15441 : 2 : QVERIFY( dn1.fromWkt( QStringLiteral( "MultiPolygonZ (((0 0 0, 10 10 0, 11 9 0, 9 8 0, 9 8 0, 1 -1 0, 0 0 0)),((7 -1 0, 12 7 0, 13 6 0, 13 6 0, 8 -3 0, 7 -1 0)))" ) ) );
15442 : 1 : QCOMPARE( dn1.numGeometries(), 2 );
15443 : : // First call should remove all duplicate nodes (one per part)
15444 : 1 : QVERIFY( dn1.removeDuplicateNodes( 0.001, false ) );
15445 : 1 : QVERIFY( !dn1.removeDuplicateNodes( 0.001, false ) );
15446 : 2 : QCOMPARE( dn1.asWkt(), QStringLiteral( "MultiPolygonZ (((0 0 0, 10 10 0, 11 9 0, 9 8 0, 1 -1 0, 0 0 0)),((7 -1 0, 12 7 0, 13 6 0, 8 -3 0, 7 -1 0)))" ) );
15447 : 1 : }
15448 : :
15449 : 1 : void TestQgsGeometry::geometryCollection()
15450 : : {
15451 : : //test constructor
15452 : 1 : QgsGeometryCollection c1;
15453 : 1 : QVERIFY( c1.isEmpty() );
15454 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
15455 : 1 : QCOMPARE( c1.ringCount(), 0 );
15456 : 1 : QCOMPARE( c1.partCount(), 0 );
15457 : 1 : QVERIFY( !c1.is3D() );
15458 : 1 : QVERIFY( !c1.isMeasure() );
15459 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::GeometryCollection );
15460 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "GeometryCollection" ) );
15461 : 1 : QCOMPARE( c1.geometryType(), QString( "GeometryCollection" ) );
15462 : 1 : QCOMPARE( c1.dimension(), 0 );
15463 : 1 : QVERIFY( !c1.hasCurvedSegments() );
15464 : 1 : QCOMPARE( c1.area(), 0.0 );
15465 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
15466 : 1 : QCOMPARE( c1.numGeometries(), 0 );
15467 : 1 : QVERIFY( !c1.geometryN( 0 ) );
15468 : 1 : QVERIFY( !c1.geometryN( -1 ) );
15469 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 0 );
15470 : 1 : QCOMPARE( c1.vertexCount( 0, 1 ), 0 );
15471 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
15472 : :
15473 : : //addGeometry
15474 : :
15475 : : //try with nullptr
15476 : 1 : c1.addGeometry( nullptr );
15477 : 1 : QVERIFY( c1.isEmpty() );
15478 : 1 : QCOMPARE( c1.nCoordinates(), 0 );
15479 : 1 : QCOMPARE( c1.ringCount(), 0 );
15480 : 1 : QCOMPARE( c1.partCount(), 0 );
15481 : 1 : QCOMPARE( c1.numGeometries(), 0 );
15482 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::GeometryCollection );
15483 : 1 : QVERIFY( !c1.geometryN( 0 ) );
15484 : 1 : QVERIFY( !c1.geometryN( -1 ) );
15485 : :
15486 : : //valid geometry
15487 : 1 : QgsLineString part;
15488 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
15489 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
15490 : 1 : c1.addGeometry( part.clone() );
15491 : 1 : QVERIFY( !c1.isEmpty() );
15492 : 1 : QCOMPARE( c1.numGeometries(), 1 );
15493 : 1 : QCOMPARE( c1.nCoordinates(), 5 );
15494 : 1 : QCOMPARE( c1.ringCount(), 1 );
15495 : 1 : QCOMPARE( c1.partCount(), 1 );
15496 : 1 : QVERIFY( !c1.is3D() );
15497 : 1 : QVERIFY( !c1.isMeasure() );
15498 : 1 : QCOMPARE( c1.wkbType(), QgsWkbTypes::GeometryCollection );
15499 : 1 : QCOMPARE( c1.wktTypeStr(), QString( "GeometryCollection" ) );
15500 : 1 : QCOMPARE( c1.geometryType(), QString( "GeometryCollection" ) );
15501 : 1 : QCOMPARE( c1.dimension(), 1 );
15502 : 1 : QVERIFY( !c1.hasCurvedSegments() );
15503 : 1 : QCOMPARE( c1.area(), 0.0 );
15504 : 1 : QCOMPARE( c1.perimeter(), 0.0 );
15505 : 1 : QVERIFY( c1.geometryN( 0 ) );
15506 : 1 : QVERIFY( !c1.geometryN( 100 ) );
15507 : 1 : QVERIFY( !c1.geometryN( -1 ) );
15508 : 1 : QCOMPARE( c1.vertexCount( 0, 0 ), 5 );
15509 : 1 : QCOMPARE( c1.vertexCount( 1, 0 ), 0 );
15510 : :
15511 : : //retrieve geometry and check
15512 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c1.geometryN( 0 ) ) ), part );
15513 : :
15514 : : //initial adding of geometry should set z/m type
15515 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
15516 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
15517 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
15518 : 1 : QgsGeometryCollection c2;
15519 : 1 : c2.addGeometry( part.clone() );
15520 : : //QVERIFY( c2.is3D() ); //no meaning for collections?
15521 : : //QVERIFY( !c2.isMeasure() ); //no meaning for collections?
15522 : 1 : QCOMPARE( c2.wkbType(), QgsWkbTypes::GeometryCollection );
15523 : 1 : QCOMPARE( c2.wktTypeStr(), QString( "GeometryCollection" ) );
15524 : 1 : QCOMPARE( c2.geometryType(), QString( "GeometryCollection" ) );
15525 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c2.geometryN( 0 ) ) ), part );
15526 : 1 : QgsGeometryCollection c3;
15527 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 )
15528 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0, 10, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 )
15529 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
15530 : 1 : c3.addGeometry( part.clone() );
15531 : : //QVERIFY( !c3.is3D() ); //no meaning for collections?
15532 : : //QVERIFY( c3.isMeasure() ); //no meaning for collections?
15533 : 1 : QCOMPARE( c3.wkbType(), QgsWkbTypes::GeometryCollection );
15534 : 1 : QCOMPARE( c3.wktTypeStr(), QString( "GeometryCollection" ) );
15535 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c3.geometryN( 0 ) ) ), part );
15536 : 1 : QgsGeometryCollection c4;
15537 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 2, 1 )
15538 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 3, 2 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 5, 3 )
15539 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 2, 1 ) );
15540 : 1 : c4.addGeometry( part.clone() );
15541 : : //QVERIFY( c4.is3D() ); //no meaning for collections?
15542 : : //QVERIFY( c4.isMeasure() ); //no meaning for collections?
15543 : 1 : QCOMPARE( c4.wkbType(), QgsWkbTypes::GeometryCollection );
15544 : 1 : QCOMPARE( c4.wktTypeStr(), QString( "GeometryCollection" ) );
15545 : 1 : QCOMPARE( *( static_cast< const QgsLineString * >( c4.geometryN( 0 ) ) ), part );
15546 : :
15547 : : //add another part
15548 : 1 : QgsGeometryCollection c6;
15549 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
15550 : 1 : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) );
15551 : 1 : c6.addGeometry( part.clone() );
15552 : 1 : QCOMPARE( c6.vertexCount( 0, 0 ), 5 );
15553 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
15554 : 1 : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) );
15555 : 1 : c6.addGeometry( part.clone() );
15556 : 1 : QCOMPARE( c6.vertexCount( 1, 0 ), 5 );
15557 : 1 : QCOMPARE( c6.numGeometries(), 2 );
15558 : 1 : QVERIFY( c6.geometryN( 0 ) );
15559 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c6.geometryN( 1 ) ), part );
15560 : :
15561 : 1 : QgsCoordinateSequence seq = c6.coordinateSequence();
15562 : 1 : QCOMPARE( seq, QgsCoordinateSequence() << ( QgsRingSequence() << ( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0, 10 ) << QgsPoint( 10, 10 )
15563 : : << QgsPoint( 10, 0 ) << QgsPoint( 0, 0 ) ) )
15564 : : << ( QgsRingSequence() << ( QgsPointSequence() << QgsPoint( 1, 1 ) << QgsPoint( 1, 9 ) << QgsPoint( 9, 9 )
15565 : : << QgsPoint( 9, 1 ) << QgsPoint( 1, 1 ) ) ) );
15566 : 1 : QCOMPARE( c6.nCoordinates(), 10 );
15567 : :
15568 : :
15569 : : //clear
15570 : 1 : QgsGeometryCollection c7;
15571 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
15572 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
15573 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
15574 : 1 : c7.addGeometry( part.clone() );
15575 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 )
15576 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 9, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 9, 9, 3 )
15577 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 ) );
15578 : 1 : c7.addGeometry( part.clone() );
15579 : 1 : QCOMPARE( c7.numGeometries(), 2 );
15580 : 1 : c7.clear();
15581 : 1 : QVERIFY( c7.isEmpty() );
15582 : 1 : QCOMPARE( c7.numGeometries(), 0 );
15583 : 1 : QCOMPARE( c7.nCoordinates(), 0 );
15584 : 1 : QCOMPARE( c7.ringCount(), 0 );
15585 : 1 : QCOMPARE( c7.partCount(), 0 );
15586 : 1 : QVERIFY( !c7.is3D() );
15587 : 1 : QVERIFY( !c7.isMeasure() );
15588 : 1 : QCOMPARE( c7.wkbType(), QgsWkbTypes::GeometryCollection );
15589 : :
15590 : : //clone
15591 : 1 : QgsGeometryCollection c11;
15592 : 1 : std::unique_ptr< QgsGeometryCollection >cloned( c11.clone() );
15593 : 1 : QVERIFY( cloned->isEmpty() );
15594 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
15595 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
15596 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
15597 : 1 : c11.addGeometry( part.clone() );
15598 : 1 : QgsLineString part2;
15599 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
15600 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
15601 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
15602 : 1 : c11.addGeometry( part2.clone() );
15603 : 1 : cloned.reset( c11.clone() );
15604 : 1 : QCOMPARE( cloned->numGeometries(), 2 );
15605 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( cloned->geometryN( 0 ) ), part );
15606 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( cloned->geometryN( 1 ) ), part2 );
15607 : :
15608 : : //copy constructor
15609 : 1 : QgsGeometryCollection c12;
15610 : 1 : QgsGeometryCollection c13( c12 );
15611 : 1 : QVERIFY( c13.isEmpty() );
15612 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
15613 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
15614 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
15615 : 1 : c12.addGeometry( part.clone() );
15616 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
15617 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
15618 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
15619 : 1 : c12.addGeometry( part2.clone() );
15620 : 1 : QgsGeometryCollection c14( c12 );
15621 : 1 : QCOMPARE( c14.numGeometries(), 2 );
15622 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c14.geometryN( 0 ) ), part );
15623 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c14.geometryN( 1 ) ), part2 );
15624 : :
15625 : : //assignment operator
15626 : 1 : QgsGeometryCollection c15;
15627 : 1 : c15 = c13;
15628 : 1 : QCOMPARE( c15.numGeometries(), 0 );
15629 : 1 : c15 = c14;
15630 : 1 : QCOMPARE( c15.numGeometries(), 2 );
15631 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c15.geometryN( 0 ) ), part );
15632 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c15.geometryN( 1 ) ), part2 );
15633 : :
15634 : : //equality
15635 : 1 : QgsGeometryCollection emptyCollection;
15636 : 1 : QVERIFY( !( emptyCollection == c15 ) );
15637 : 1 : QVERIFY( emptyCollection != c15 );
15638 : 1 : QgsPoint notCollection;
15639 : 1 : QVERIFY( !( emptyCollection == notCollection ) );
15640 : 1 : QVERIFY( emptyCollection != notCollection );
15641 : 1 : QgsMultiPoint mp;
15642 : 1 : QgsMultiLineString ml;
15643 : 1 : QVERIFY( mp != ml );
15644 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
15645 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
15646 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
15647 : 1 : ml.addGeometry( part.clone() );
15648 : 1 : QgsMultiLineString ml2;
15649 : 1 : QVERIFY( ml != ml2 );
15650 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 )
15651 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
15652 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
15653 : 1 : ml2.addGeometry( part.clone() );
15654 : 1 : QVERIFY( ml != ml2 );
15655 : :
15656 : 1 : QgsMultiLineString ml3;
15657 : 1 : ml3.addGeometry( part.clone() );
15658 : 1 : QVERIFY( ml2 == ml3 );
15659 : :
15660 : : //toCurveType
15661 : 1 : std::unique_ptr< QgsGeometryCollection > curveType( c12.toCurveType() );
15662 : 1 : QCOMPARE( curveType->wkbType(), QgsWkbTypes::GeometryCollection );
15663 : 1 : QCOMPARE( curveType->numGeometries(), 2 );
15664 : 1 : const QgsCompoundCurve *curve = static_cast< const QgsCompoundCurve * >( curveType->geometryN( 0 ) );
15665 : 1 : QCOMPARE( curve->numPoints(), 5 );
15666 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 ) );
15667 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) );
15668 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 ) );
15669 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) );
15670 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 4 ) ), QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
15671 : 1 : curve = static_cast< const QgsCompoundCurve * >( curveType->geometryN( 1 ) );
15672 : 1 : QCOMPARE( curve->numPoints(), 5 );
15673 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 0 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 ) );
15674 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 1 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) );
15675 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 ) );
15676 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 3 ) ), QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) );
15677 : 1 : QCOMPARE( curve->vertexAt( QgsVertexId( 0, 0, 4 ) ), QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
15678 : :
15679 : : //to/fromWKB
15680 : 1 : QgsGeometryCollection c16;
15681 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 0, 0 )
15682 : 1 : << QgsPoint( QgsWkbTypes::Point, 0, 10 ) << QgsPoint( QgsWkbTypes::Point, 10, 10 )
15683 : 1 : << QgsPoint( QgsWkbTypes::Point, 10, 0 ) << QgsPoint( QgsWkbTypes::Point, 0, 0 ) );
15684 : 1 : c16.addGeometry( part.clone() );
15685 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 1 )
15686 : 1 : << QgsPoint( QgsWkbTypes::Point, 1, 9 ) << QgsPoint( QgsWkbTypes::Point, 9, 9 )
15687 : 1 : << QgsPoint( QgsWkbTypes::Point, 9, 1 ) << QgsPoint( QgsWkbTypes::Point, 1, 1 ) );
15688 : 1 : c16.addGeometry( part2.clone() );
15689 : 1 : QByteArray wkb16 = c16.asWkb();
15690 : 1 : QCOMPARE( wkb16.size(), c16.wkbSize() );
15691 : 1 : QgsGeometryCollection c17;
15692 : 1 : QgsConstWkbPtr wkb16ptr( wkb16 );
15693 : 1 : c17.fromWkb( wkb16ptr );
15694 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15695 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), part );
15696 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), part2 );
15697 : :
15698 : : //parts with Z
15699 : 1 : c16.clear();
15700 : 1 : c17.clear();
15701 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 )
15702 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 0, 10, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 3 )
15703 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 10, 0, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 0, 0, 1 ) );
15704 : 1 : c16.addGeometry( part.clone() );
15705 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 )
15706 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 1, 9, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 9, 9, 3 )
15707 : 1 : << QgsPoint( QgsWkbTypes::PointZ, 9, 1, 4 ) << QgsPoint( QgsWkbTypes::PointZ, 1, 1, 1 ) );
15708 : 1 : c16.addGeometry( part2.clone() );
15709 : 1 : wkb16 = c16.asWkb();
15710 : 1 : QgsConstWkbPtr wkb16ptr2( wkb16 );
15711 : 1 : c17.fromWkb( wkb16ptr2 );
15712 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15713 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), part );
15714 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), part2 );
15715 : :
15716 : :
15717 : : //parts with m
15718 : 1 : c16.clear();
15719 : 1 : c17.clear();
15720 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 )
15721 : 1 : << QgsPoint( QgsWkbTypes::PointM, 0, 10, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 10, 10, 0, 3 )
15722 : 1 : << QgsPoint( QgsWkbTypes::PointM, 10, 0, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 0, 0, 0, 1 ) );
15723 : 1 : c16.addGeometry( part.clone() );
15724 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 1, 0, 1 )
15725 : 1 : << QgsPoint( QgsWkbTypes::PointM, 1, 9, 0, 2 ) << QgsPoint( QgsWkbTypes::PointM, 9, 9, 0, 3 )
15726 : 1 : << QgsPoint( QgsWkbTypes::PointM, 9, 1, 0, 4 ) << QgsPoint( QgsWkbTypes::PointM, 1, 1, 0, 1 ) );
15727 : 1 : c16.addGeometry( part2.clone() );
15728 : 1 : wkb16 = c16.asWkb();
15729 : 1 : QgsConstWkbPtr wkb16ptr3( wkb16 );
15730 : 1 : c17.fromWkb( wkb16ptr3 );
15731 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15732 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), part );
15733 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), part2 );
15734 : :
15735 : : // parts with ZM
15736 : 1 : c16.clear();
15737 : 1 : c17.clear();
15738 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
15739 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
15740 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
15741 : 1 : c16.addGeometry( part.clone() );
15742 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
15743 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
15744 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
15745 : 1 : c16.addGeometry( part2.clone() );
15746 : 1 : wkb16 = c16.asWkb();
15747 : 1 : QgsConstWkbPtr wkb16ptr4( wkb16 );
15748 : 1 : c17.fromWkb( wkb16ptr4 );
15749 : 1 : QCOMPARE( c17.numGeometries(), 2 );
15750 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 0 ) ), part );
15751 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c17.geometryN( 1 ) ), part2 );
15752 : :
15753 : :
15754 : : //bad WKB - check for no crash
15755 : 1 : c17.clear();
15756 : 1 : QgsConstWkbPtr nullPtr( nullptr, 0 );
15757 : 1 : QVERIFY( !c17.fromWkb( nullPtr ) );
15758 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::GeometryCollection );
15759 : 1 : QgsPoint point( 1, 2 );
15760 : 1 : QByteArray wkbPoint = point.asWkb();
15761 : 1 : QgsConstWkbPtr wkbPointPtr( wkbPoint );
15762 : 1 : QVERIFY( !c17.fromWkb( wkbPointPtr ) );
15763 : 1 : QCOMPARE( c17.wkbType(), QgsWkbTypes::GeometryCollection );
15764 : :
15765 : : //to/from WKT
15766 : 1 : QgsGeometryCollection c18;
15767 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
15768 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
15769 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
15770 : 1 : c18.addGeometry( part.clone() );
15771 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
15772 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
15773 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
15774 : 1 : c18.addGeometry( part2.clone() );
15775 : :
15776 : 1 : QString wkt = c18.asWkt();
15777 : 1 : QVERIFY( !wkt.isEmpty() );
15778 : 1 : QgsGeometryCollection c19;
15779 : 1 : QVERIFY( c19.fromWkt( wkt ) );
15780 : 1 : QCOMPARE( c19.numGeometries(), 2 );
15781 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c19.geometryN( 0 ) ), part );
15782 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( c19.geometryN( 1 ) ), part2 );
15783 : :
15784 : : //bad WKT
15785 : 1 : QgsGeometryCollection c20;
15786 : 1 : QVERIFY( !c20.fromWkt( "Point()" ) );
15787 : 1 : QVERIFY( c20.isEmpty() );
15788 : 1 : QCOMPARE( c20.numGeometries(), 0 );
15789 : 1 : QCOMPARE( c20.wkbType(), QgsWkbTypes::GeometryCollection );
15790 : :
15791 : : //as JSON
15792 : 1 : QgsGeometryCollection exportC;
15793 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 0, 0 )
15794 : 1 : << QgsPoint( QgsWkbTypes::Point, 0, 10 ) << QgsPoint( QgsWkbTypes::Point, 10, 10 )
15795 : 1 : << QgsPoint( QgsWkbTypes::Point, 10, 0 ) << QgsPoint( QgsWkbTypes::Point, 0, 0 ) );
15796 : 1 : exportC.addGeometry( part.clone() );
15797 : :
15798 : : // GML document for compare
15799 : 1 : QDomDocument doc( "gml" );
15800 : :
15801 : :
15802 : : // as GML2
15803 : 2 : QString expectedSimpleGML2( QStringLiteral( "<MultiGeometry xmlns=\"gml\"><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 0,10 10,10 10,0 0,0</coordinates></LineString></geometryMember></MultiGeometry>" ) );
15804 : 1 : QString res = elemToString( exportC.asGml2( doc ) );
15805 : 3 : QGSCOMPAREGML( res, expectedSimpleGML2 );
15806 : 2 : QString expectedGML2empty( QStringLiteral( "<MultiGeometry xmlns=\"gml\"/>" ) );
15807 : 3 : QGSCOMPAREGML( elemToString( QgsGeometryCollection().asGml2( doc ) ), expectedGML2empty );
15808 : :
15809 : : //as GML3
15810 : 2 : QString expectedSimpleGML3( QStringLiteral( "<MultiGeometry xmlns=\"gml\"><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0 0 0 10 10 10 10 0 0 0</posList></LineString></geometryMember></MultiGeometry>" ) );
15811 : 1 : res = elemToString( exportC.asGml3( doc ) );
15812 : 1 : QCOMPARE( res, expectedSimpleGML3 );
15813 : 2 : QString expectedGML3empty( QStringLiteral( "<MultiGeometry xmlns=\"gml\"/>" ) );
15814 : 3 : QGSCOMPAREGML( elemToString( QgsGeometryCollection().asGml3( doc ) ), expectedGML3empty );
15815 : :
15816 : : // as JSON
15817 : 1 : QString expectedSimpleJson( "{\"geometries\":[{\"coordinates\":[[0.0,0.0],[0.0,10.0],[10.0,10.0],[10.0,0.0],[0.0,0.0]],\"type\":\"LineString\"}],\"type\":\"GeometryCollection\"}" );
15818 : 1 : res = exportC.asJson();
15819 : 1 : QCOMPARE( res, expectedSimpleJson );
15820 : :
15821 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 1, 1 )
15822 : 1 : << QgsPoint( QgsWkbTypes::Point, 1, 9 ) << QgsPoint( QgsWkbTypes::Point, 9, 9 )
15823 : 1 : << QgsPoint( QgsWkbTypes::Point, 9, 1 ) << QgsPoint( QgsWkbTypes::Point, 1, 1 ) );
15824 : 1 : exportC.addGeometry( part.clone() );
15825 : :
15826 : 1 : QString expectedJson( "{\"geometries\":[{\"coordinates\":[[0.0,0.0],[0.0,10.0],[10.0,10.0],[10.0,0.0],[0.0,0.0]],\"type\":\"LineString\"},{\"coordinates\":[[1.0,1.0],[1.0,9.0],[9.0,9.0],[9.0,1.0],[1.0,1.0]],\"type\":\"LineString\"}],\"type\":\"GeometryCollection\"}" );
15827 : 1 : res = exportC.asJson();
15828 : 1 : QCOMPARE( res, expectedJson );
15829 : :
15830 : 1 : QgsGeometryCollection exportFloat;
15831 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 10 / 9.0 )
15832 : 1 : << QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 100 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 100 / 9.0, 100 / 9.0 )
15833 : 1 : << QgsPoint( QgsWkbTypes::Point, 100 / 9.0, 10 / 9.0 ) << QgsPoint( QgsWkbTypes::Point, 10 / 9.0, 10 / 9.0 ) );
15834 : 1 : exportFloat.addGeometry( part.clone() );
15835 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 2 / 3.0 )
15836 : 1 : << QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 4 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 4 / 3.0, 4 / 3.0 )
15837 : 1 : << QgsPoint( QgsWkbTypes::Point, 4 / 3.0, 2 / 3.0 ) << QgsPoint( QgsWkbTypes::Point, 2 / 3.0, 2 / 3.0 ) );
15838 : 1 : exportFloat.addGeometry( part.clone() );
15839 : :
15840 : 1 : QString expectedJsonPrec3( "{\"geometries\":[{\"coordinates\":[[1.111,1.111],[1.111,11.111],[11.111,11.111],[11.111,1.111],[1.111,1.111]],\"type\":\"LineString\"},{\"coordinates\":[[0.667,0.667],[0.667,1.333],[1.333,1.333],[1.333,0.667],[0.667,0.667]],\"type\":\"LineString\"}],\"type\":\"GeometryCollection\"}" );
15841 : 1 : res = exportFloat.asJson( 3 );
15842 : 1 : QCOMPARE( res, expectedJsonPrec3 );
15843 : :
15844 : : // as GML2
15845 : 2 : QString expectedGML2( QStringLiteral( "<MultiGeometry xmlns=\"gml\"><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0,0 0,10 10,10 10,0 0,0</coordinates></LineString></geometryMember><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1,1 1,9 9,9 9,1 1,1</coordinates></LineString></geometryMember></MultiGeometry>" ) );
15846 : 1 : res = elemToString( exportC.asGml2( doc ) );
15847 : 3 : QGSCOMPAREGML( res, expectedGML2 );
15848 : 2 : QString expectedGML2prec3( QStringLiteral( "<MultiGeometry xmlns=\"gml\"><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1.111,1.111 1.111,11.111 11.111,11.111 11.111,1.111 1.111,1.111</coordinates></LineString></geometryMember><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><coordinates xmlns=\"gml\" cs=\",\" ts=\" \">0.667,0.667 0.667,1.333 1.333,1.333 1.333,0.667 0.667,0.667</coordinates></LineString></geometryMember></MultiGeometry>" ) );
15849 : 1 : res = elemToString( exportFloat.asGml2( doc, 3 ) );
15850 : 3 : QGSCOMPAREGML( res, expectedGML2prec3 );
15851 : :
15852 : : //as GML3
15853 : 2 : QString expectedGML3( QStringLiteral( "<MultiGeometry xmlns=\"gml\"><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0 0 0 10 10 10 10 0 0 0</posList></LineString></geometryMember><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1 1 1 9 9 9 9 1 1 1</posList></LineString></geometryMember></MultiGeometry>" ) );
15854 : 1 : res = elemToString( exportC.asGml3( doc ) );
15855 : 1 : QCOMPARE( res, expectedGML3 );
15856 : 2 : QString expectedGML3prec3( QStringLiteral( "<MultiGeometry xmlns=\"gml\"><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">1.111 1.111 1.111 11.111 11.111 11.111 11.111 1.111 1.111 1.111</posList></LineString></geometryMember><geometryMember xmlns=\"gml\"><LineString xmlns=\"gml\"><posList xmlns=\"gml\" srsDimension=\"2\">0.667 0.667 0.667 1.333 1.333 1.333 1.333 0.667 0.667 0.667</posList></LineString></geometryMember></MultiGeometry>" ) );
15857 : 1 : res = elemToString( exportFloat.asGml3( doc, 3 ) );
15858 : 1 : QCOMPARE( res, expectedGML3prec3 );
15859 : :
15860 : : //asKML
15861 : 2 : QString expectedKml( QStringLiteral( "<MultiGeometry><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>0,0,0 0,10,0 10,10,0 10,0,0 0,0,0</coordinates></LinearRing><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>1,1,0 1,9,0 9,9,0 9,1,0 1,1,0</coordinates></LinearRing></MultiGeometry>" ) );
15862 : 1 : QCOMPARE( exportC.asKml(), expectedKml );
15863 : 2 : QString expectedKmlPrec3( QStringLiteral( "<MultiGeometry><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>1.111,1.111,0 1.111,11.111,0 11.111,11.111,0 11.111,1.111,0 1.111,1.111,0</coordinates></LinearRing><LinearRing><altitudeMode>clampToGround</altitudeMode><coordinates>0.667,0.667,0 0.667,1.333,0 1.333,1.333,0 1.333,0.667,0 0.667,0.667,0</coordinates></LinearRing></MultiGeometry>" ) );
15864 : 1 : QCOMPARE( exportFloat.asKml( 3 ), expectedKmlPrec3 );
15865 : :
15866 : :
15867 : : // remove geometry
15868 : 1 : QgsGeometryCollection rc;
15869 : : // no crash!
15870 : 1 : rc.removeGeometry( -1 );
15871 : 1 : rc.removeGeometry( 0 );
15872 : 1 : rc.removeGeometry( 100 );
15873 : 2 : part.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 5 )
15874 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 0, 10, 2, 6 ) << QgsPoint( QgsWkbTypes::PointZM, 10, 10, 3, 7 )
15875 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 10, 0, 4, 8 ) << QgsPoint( QgsWkbTypes::PointZM, 0, 0, 1, 9 ) );
15876 : 1 : rc.addGeometry( part.clone() );
15877 : 2 : part2.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 2 )
15878 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 9, 2, 3 ) << QgsPoint( QgsWkbTypes::PointZM, 9, 9, 3, 6 )
15879 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 9, 1, 4, 4 ) << QgsPoint( QgsWkbTypes::PointZM, 1, 1, 1, 7 ) );
15880 : 1 : rc.addGeometry( part2.clone() );
15881 : : // no crash
15882 : 1 : rc.removeGeometry( -1 );
15883 : 1 : rc.removeGeometry( 100 );
15884 : :
15885 : 1 : rc.removeGeometry( 0 );
15886 : 1 : QCOMPARE( rc.numGeometries(), 1 );
15887 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 0 ) ), part2 );
15888 : :
15889 : 1 : rc.addGeometry( part.clone() );
15890 : 1 : rc.removeGeometry( 1 );
15891 : 1 : QCOMPARE( rc.numGeometries(), 1 );
15892 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 0 ) ), part2 );
15893 : 1 : rc.removeGeometry( 0 );
15894 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15895 : :
15896 : :
15897 : : // insert geometry
15898 : 1 : rc.clear();
15899 : 1 : rc.insertGeometry( nullptr, 0 );
15900 : 1 : QVERIFY( rc.isEmpty() );
15901 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15902 : 1 : rc.insertGeometry( nullptr, -1 );
15903 : 1 : QVERIFY( rc.isEmpty() );
15904 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15905 : 1 : rc.insertGeometry( nullptr, 100 );
15906 : 1 : QVERIFY( rc.isEmpty() );
15907 : 1 : QCOMPARE( rc.numGeometries(), 0 );
15908 : :
15909 : 1 : rc.insertGeometry( part.clone(), 0 );
15910 : 1 : QCOMPARE( rc.numGeometries(), 1 );
15911 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 0 ) ), part );
15912 : 1 : rc.insertGeometry( part2.clone(), 0 );
15913 : 1 : QCOMPARE( rc.numGeometries(), 2 );
15914 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 0 ) ), part2 );
15915 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 1 ) ), part );
15916 : 1 : rc.removeGeometry( 0 );
15917 : 1 : rc.insertGeometry( part2.clone(), 1 );
15918 : 1 : QCOMPARE( rc.numGeometries(), 2 );
15919 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 0 ) ), part );
15920 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 1 ) ), part2 );
15921 : 1 : rc.removeGeometry( 1 );
15922 : 1 : rc.insertGeometry( part2.clone(), 2 );
15923 : 1 : QCOMPARE( rc.numGeometries(), 2 );
15924 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 0 ) ), part );
15925 : 1 : QCOMPARE( *static_cast< const QgsLineString * >( rc.geometryN( 1 ) ), part2 );
15926 : :
15927 : : // cast
15928 : 1 : QVERIFY( !QgsGeometryCollection().cast( nullptr ) );
15929 : 1 : QgsGeometryCollection pCast;
15930 : 1 : QVERIFY( QgsGeometryCollection().cast( &pCast ) );
15931 : 1 : QgsGeometryCollection pCast2;
15932 : 2 : pCast2.fromWkt( QStringLiteral( "GeometryCollectionZ(PolygonZ((0 0 0, 0 1 1, 1 0 2, 0 0 0)))" ) );
15933 : 1 : QVERIFY( QgsGeometryCollection().cast( &pCast2 ) );
15934 : 2 : pCast2.fromWkt( QStringLiteral( "GeometryCollectionM(PolygonM((0 0 1, 0 1 2, 1 0 3, 0 0 1)))" ) );
15935 : 1 : QVERIFY( QgsGeometryCollection().cast( &pCast2 ) );
15936 : 2 : pCast2.fromWkt( QStringLiteral( "GeometryCollectionZM(PolygonZM((0 0 0 1, 0 1 1 2, 1 0 2 3, 0 0 0 1)))" ) );
15937 : 1 : QVERIFY( QgsGeometryCollection().cast( &pCast2 ) );
15938 : :
15939 : : //transform
15940 : : //CRS transform
15941 : 2 : QgsCoordinateReferenceSystem sourceSrs( QStringLiteral( "EPSG:3994" ) );
15942 : 2 : QgsCoordinateReferenceSystem destSrs( QStringLiteral( "EPSG:4202" ) ); // want a transform with ellipsoid change
15943 : 1 : QgsCoordinateTransform tr( sourceSrs, destSrs, QgsProject::instance() );
15944 : :
15945 : : // 2d CRS transform
15946 : 1 : QgsGeometryCollection pTransform;
15947 : 1 : QgsLineString l21;
15948 : 2 : l21.setPoints( QgsPointSequence() << QgsPoint( 6374985, -3626584 )
15949 : 1 : << QgsPoint( 6274985, -3526584 )
15950 : 1 : << QgsPoint( 6474985, -3526584 )
15951 : 1 : << QgsPoint( 6374985, -3626584 ) );
15952 : 1 : pTransform.addGeometry( l21.clone() );
15953 : 1 : pTransform.addGeometry( l21.clone() );
15954 : 1 : pTransform.transform( tr, QgsCoordinateTransform::ForwardTransform );
15955 : 1 : const QgsLineString *extR = static_cast< const QgsLineString * >( pTransform.geometryN( 0 ) );
15956 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 175.771, 0.001 );
15957 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), -39.724, 0.001 );
15958 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 174.581448, 0.001 );
15959 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), -38.7999, 0.001 );
15960 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 176.958633, 0.001 );
15961 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), -38.7999, 0.001 );
15962 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 175.771, 0.001 );
15963 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), -39.724, 0.001 );
15964 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMinimum(), 174.581448, 0.001 );
15965 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMinimum(), -39.724, 0.001 );
15966 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMaximum(), 176.959, 0.001 );
15967 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMaximum(), -38.7999, 0.001 );
15968 : 1 : const QgsLineString *intR = static_cast< const QgsLineString * >( pTransform.geometryN( 1 ) );
15969 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 175.771, 0.001 );
15970 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), -39.724, 0.001 );
15971 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 174.581448, 0.001 );
15972 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), -38.7999, 0.001 );
15973 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 176.958633, 0.001 );
15974 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), -38.7999, 0.001 );
15975 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 175.771, 0.001 );
15976 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), -39.724, 0.001 );
15977 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 174.581448, 0.001 );
15978 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMinimum(), -39.724, 0.001 );
15979 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 176.959, 0.001 );
15980 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMaximum(), -38.7999, 0.001 );
15981 : :
15982 : : //3d CRS transform
15983 : 1 : QgsLineString l22;
15984 : 2 : l22.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 )
15985 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6274985, -3526584, 3, 4 )
15986 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6474985, -3526584, 5, 6 )
15987 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 6374985, -3626584, 1, 2 ) );
15988 : 1 : pTransform.clear();
15989 : 1 : pTransform.addGeometry( l22.clone() );
15990 : 1 : pTransform.addGeometry( l22.clone() );
15991 : 1 : pTransform.transform( tr, QgsCoordinateTransform::ForwardTransform );
15992 : 1 : extR = static_cast< const QgsLineString * >( pTransform.geometryN( 0 ) );
15993 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 175.771, 0.001 );
15994 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), -39.724, 0.001 );
15995 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 1.0, 0.001 );
15996 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).m(), 2.0, 0.001 );
15997 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 174.581448, 0.001 );
15998 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), -38.7999, 0.001 );
15999 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 3.0, 0.001 );
16000 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).m(), 4.0, 0.001 );
16001 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 176.958633, 0.001 );
16002 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), -38.7999, 0.001 );
16003 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 5.0, 0.001 );
16004 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).m(), 6.0, 0.001 );
16005 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 175.771, 0.001 );
16006 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), -39.724, 0.001 );
16007 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 1.0, 0.001 );
16008 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).m(), 2.0, 0.001 );
16009 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMinimum(), 174.581448, 0.001 );
16010 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMinimum(), -39.724, 0.001 );
16011 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMaximum(), 176.959, 0.001 );
16012 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMaximum(), -38.7999, 0.001 );
16013 : 1 : intR = static_cast< const QgsLineString * >( pTransform.geometryN( 1 ) );
16014 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 175.771, 0.001 );
16015 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), -39.724, 0.001 );
16016 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 1.0, 0.001 );
16017 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).m(), 2.0, 0.001 );
16018 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 174.581448, 0.001 );
16019 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), -38.7999, 0.001 );
16020 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 3.0, 0.001 );
16021 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).m(), 4.0, 0.001 );
16022 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 176.958633, 0.001 );
16023 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), -38.7999, 0.001 );
16024 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 5.0, 0.001 );
16025 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).m(), 6.0, 0.001 );
16026 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 175.771, 0.001 );
16027 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), -39.724, 0.001 );
16028 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 1.0, 0.001 );
16029 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).m(), 2.0, 0.001 );
16030 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 174.581448, 0.001 );
16031 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMinimum(), -39.724, 0.001 );
16032 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 176.959, 0.001 );
16033 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMaximum(), -38.7999, 0.001 );
16034 : :
16035 : : //reverse transform
16036 : 1 : pTransform.transform( tr, QgsCoordinateTransform::ReverseTransform );
16037 : 1 : extR = static_cast< const QgsLineString * >( pTransform.geometryN( 0 ) );
16038 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 6374984, 100 );
16039 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), -3626584, 100 );
16040 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 1.0, 0.001 );
16041 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).m(), 2.0, 0.001 );
16042 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 6274984, 100 );
16043 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), -3526584, 100 );
16044 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 3.0, 0.001 );
16045 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).m(), 4.0, 0.001 );
16046 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 6474984, 100 );
16047 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), -3526584, 100 );
16048 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 5.0, 0.001 );
16049 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).m(), 6.0, 0.001 );
16050 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 6374984, 100 );
16051 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), -3626584, 100 );
16052 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 1.0, 0.001 );
16053 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).m(), 2.0, 0.001 );
16054 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMinimum(), 6274984, 100 );
16055 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMinimum(), -3626584, 100 );
16056 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMaximum(), 6474984, 100 );
16057 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMaximum(), -3526584, 100 );
16058 : 1 : intR = static_cast< const QgsLineString * >( pTransform.geometryN( 1 ) );
16059 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 6374984, 100 );
16060 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), -3626584, 100 );
16061 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 1.0, 0.001 );
16062 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).m(), 2.0, 0.001 );
16063 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 6274984, 100 );
16064 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), -3526584, 100 );
16065 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 3.0, 0.001 );
16066 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).m(), 4.0, 0.001 );
16067 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 6474984, 100 );
16068 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), -3526584, 100 );
16069 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 5.0, 0.001 );
16070 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).m(), 6.0, 0.001 );
16071 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 6374984, 100 );
16072 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), -3626584, 100 );
16073 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 1.0, 0.001 );
16074 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).m(), 2.0, 0.001 );
16075 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 6274984, 100 );
16076 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMinimum(), -3626584, 100 );
16077 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 6474984, 100 );
16078 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMaximum(), -3526584, 100 );
16079 : :
16080 : : #if PROJ_VERSION_MAJOR<6 // note - z value transform doesn't currently work with proj 6+, because we don't yet support compound CRS definitions
16081 : : //z value transform
16082 : : pTransform.transform( tr, QgsCoordinateTransform::ForwardTransform, true );
16083 : : extR = static_cast< const QgsLineString * >( pTransform.geometryN( 0 ) );
16084 : : QGSCOMPARENEAR( extR->pointN( 0 ).z(), -19.249066, 0.001 );
16085 : : QGSCOMPARENEAR( extR->pointN( 1 ).z(), -19.148357, 0.001 );
16086 : : QGSCOMPARENEAR( extR->pointN( 2 ).z(), -19.092128, 0.001 );
16087 : : QGSCOMPARENEAR( extR->pointN( 3 ).z(), -19.249066, 0.001 );
16088 : : intR = static_cast< const QgsLineString * >( pTransform.geometryN( 1 ) );
16089 : : QGSCOMPARENEAR( intR->pointN( 0 ).z(), -19.249066, 0.001 );
16090 : : QGSCOMPARENEAR( intR->pointN( 1 ).z(), -19.148357, 0.001 );
16091 : : QGSCOMPARENEAR( intR->pointN( 2 ).z(), -19.092128, 0.001 );
16092 : : QGSCOMPARENEAR( intR->pointN( 3 ).z(), -19.249066, 0.001 );
16093 : : pTransform.transform( tr, QgsCoordinateTransform::ReverseTransform, true );
16094 : : extR = static_cast< const QgsLineString * >( pTransform.geometryN( 0 ) );
16095 : : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 1, 0.001 );
16096 : : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 3, 0.001 );
16097 : : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 5, 0.001 );
16098 : : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 1, 0.001 );
16099 : : intR = static_cast< const QgsLineString * >( pTransform.geometryN( 1 ) );
16100 : : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 1, 0.001 );
16101 : : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 3, 0.001 );
16102 : : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 5, 0.001 );
16103 : : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 1, 0.001 );
16104 : : #endif
16105 : :
16106 : : //QTransform transform
16107 : 1 : QTransform qtr = QTransform::fromScale( 2, 3 );
16108 : 1 : QgsLineString l23;
16109 : 2 : l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
16110 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 )
16111 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 12, 23, 24 )
16112 : 1 : << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 ) );
16113 : 1 : QgsGeometryCollection pTransform2;
16114 : 1 : pTransform2.addGeometry( l23.clone() );
16115 : 1 : pTransform2.addGeometry( l23.clone() );
16116 : 1 : pTransform2.transform( qtr, 3, 2, 6, 3 );
16117 : :
16118 : 1 : extR = static_cast< const QgsLineString * >( pTransform2.geometryN( 0 ) );
16119 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).x(), 2, 100 );
16120 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).y(), 6, 100 );
16121 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).z(), 9.0, 0.001 );
16122 : 1 : QGSCOMPARENEAR( extR->pointN( 0 ).m(), 18.0, 0.001 );
16123 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).x(), 22, 100 );
16124 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).y(), 36, 100 );
16125 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).z(), 29.0, 0.001 );
16126 : 1 : QGSCOMPARENEAR( extR->pointN( 1 ).m(), 48.0, 0.001 );
16127 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).x(), 2, 100 );
16128 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).y(), 36, 100 );
16129 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).z(), 49.0, 0.001 );
16130 : 1 : QGSCOMPARENEAR( extR->pointN( 2 ).m(), 78.0, 0.001 );
16131 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).x(), 2, 100 );
16132 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).y(), 6, 100 );
16133 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).z(), 9.0, 0.001 );
16134 : 1 : QGSCOMPARENEAR( extR->pointN( 3 ).m(), 18.0, 0.001 );
16135 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMinimum(), 2, 0.001 );
16136 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMinimum(), 6, 0.001 );
16137 : 1 : QGSCOMPARENEAR( extR->boundingBox().xMaximum(), 22, 0.001 );
16138 : 1 : QGSCOMPARENEAR( extR->boundingBox().yMaximum(), 36, 0.001 );
16139 : 1 : intR = static_cast< const QgsLineString * >( pTransform2.geometryN( 1 ) );
16140 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).x(), 2, 100 );
16141 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).y(), 6, 100 );
16142 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).z(), 9.0, 0.001 );
16143 : 1 : QGSCOMPARENEAR( intR->pointN( 0 ).m(), 18.0, 0.001 );
16144 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).x(), 22, 100 );
16145 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).y(), 36, 100 );
16146 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).z(), 29.0, 0.001 );
16147 : 1 : QGSCOMPARENEAR( intR->pointN( 1 ).m(), 48.0, 0.001 );
16148 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).x(), 2, 100 );
16149 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).y(), 36, 100 );
16150 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).z(), 49.0, 0.001 );
16151 : 1 : QGSCOMPARENEAR( intR->pointN( 2 ).m(), 78.0, 0.001 );
16152 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).x(), 2, 100 );
16153 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).y(), 6, 100 );
16154 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).z(), 9.0, 0.001 );
16155 : 1 : QGSCOMPARENEAR( intR->pointN( 3 ).m(), 18.0, 0.001 );
16156 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 2, 0.001 );
16157 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMinimum(), 6, 0.001 );
16158 : 1 : QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 22, 0.001 );
16159 : 1 : QGSCOMPARENEAR( intR->boundingBox().yMaximum(), 36, 0.001 );
16160 : :
16161 : :
16162 : : // closestSegment
16163 : 1 : QgsPoint pt;
16164 : 1 : QgsVertexId v;
16165 : 1 : int leftOf = 0;
16166 : 1 : QgsGeometryCollection empty;
16167 : 1 : ( void )empty.closestSegment( QgsPoint( 1, 2 ), pt, v ); // empty collection, just want no crash
16168 : :
16169 : 1 : QgsGeometryCollection p21;
16170 : 1 : QgsLineString p21ls;
16171 : 1 : p21ls.setPoints( QgsPointSequence() << QgsPoint( 5, 10 ) << QgsPoint( 7, 12 ) << QgsPoint( 5, 15 ) << QgsPoint( 5, 10 ) );
16172 : 1 : p21.addGeometry( p21ls.clone() );
16173 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 4, 11 ), pt, v, &leftOf ), 1.0, 0.0001 );
16174 : 1 : QGSCOMPARENEAR( pt.x(), 5, 0.01 );
16175 : 1 : QGSCOMPARENEAR( pt.y(), 11, 0.01 );
16176 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
16177 : 1 : QCOMPARE( leftOf, 1 );
16178 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 8, 11 ), pt, v, &leftOf ), 2.0, 0.0001 );
16179 : 1 : QGSCOMPARENEAR( pt.x(), 7, 0.01 );
16180 : 1 : QGSCOMPARENEAR( pt.y(), 12, 0.01 );
16181 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
16182 : 1 : QCOMPARE( leftOf, 1 );
16183 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 6, 11.5 ), pt, v, &leftOf ), 0.125000, 0.0001 );
16184 : 1 : QGSCOMPARENEAR( pt.x(), 6.25, 0.01 );
16185 : 1 : QGSCOMPARENEAR( pt.y(), 11.25, 0.01 );
16186 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
16187 : 1 : QCOMPARE( leftOf, -1 );
16188 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 7, 16 ), pt, v, &leftOf ), 4.923077, 0.0001 );
16189 : 1 : QGSCOMPARENEAR( pt.x(), 5.153846, 0.01 );
16190 : 1 : QGSCOMPARENEAR( pt.y(), 14.769231, 0.01 );
16191 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
16192 : 1 : QCOMPARE( leftOf, 1 );
16193 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 5.5, 13.5 ), pt, v, &leftOf ), 0.173077, 0.0001 );
16194 : 1 : QGSCOMPARENEAR( pt.x(), 5.846154, 0.01 );
16195 : 1 : QGSCOMPARENEAR( pt.y(), 13.730769, 0.01 );
16196 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
16197 : 1 : QCOMPARE( leftOf, -1 );
16198 : : // point directly on segment
16199 : 1 : QCOMPARE( p21.closestSegment( QgsPoint( 5, 15 ), pt, v, &leftOf ), 0.0 );
16200 : 1 : QCOMPARE( pt, QgsPoint( 5, 15 ) );
16201 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
16202 : : // with interior ring
16203 : 1 : p21ls.setPoints( QgsPointSequence() << QgsPoint( 6, 11.5 ) << QgsPoint( 6.5, 12 ) << QgsPoint( 6, 13 ) << QgsPoint( 6, 11.5 ) );
16204 : 1 : p21.addGeometry( p21ls.clone() );
16205 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 4, 11 ), pt, v, &leftOf ), 1.0, 0.0001 );
16206 : 1 : QGSCOMPARENEAR( pt.x(), 5, 0.01 );
16207 : 1 : QGSCOMPARENEAR( pt.y(), 11, 0.01 );
16208 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
16209 : 1 : QCOMPARE( leftOf, 1 );
16210 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 8, 11 ), pt, v, &leftOf ), 2.0, 0.0001 );
16211 : 1 : QGSCOMPARENEAR( pt.x(), 7, 0.01 );
16212 : 1 : QGSCOMPARENEAR( pt.y(), 12, 0.01 );
16213 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
16214 : 1 : QCOMPARE( leftOf, 1 );
16215 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 6, 11.4 ), pt, v, &leftOf ), 0.01, 0.0001 );
16216 : 1 : QGSCOMPARENEAR( pt.x(), 6.0, 0.01 );
16217 : 1 : QGSCOMPARENEAR( pt.y(), 11.5, 0.01 );
16218 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 1 ) );
16219 : 1 : QCOMPARE( leftOf, 1 );
16220 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 7, 16 ), pt, v, &leftOf ), 4.923077, 0.0001 );
16221 : 1 : QGSCOMPARENEAR( pt.x(), 5.153846, 0.01 );
16222 : 1 : QGSCOMPARENEAR( pt.y(), 14.769231, 0.01 );
16223 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
16224 : 1 : QCOMPARE( leftOf, 1 );
16225 : 1 : QGSCOMPARENEAR( p21.closestSegment( QgsPoint( 5.5, 13.5 ), pt, v, &leftOf ), 0.173077, 0.0001 );
16226 : 1 : QGSCOMPARENEAR( pt.x(), 5.846154, 0.01 );
16227 : 1 : QGSCOMPARENEAR( pt.y(), 13.730769, 0.01 );
16228 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
16229 : 1 : QCOMPARE( leftOf, -1 );
16230 : : // point directly on segment
16231 : 1 : QCOMPARE( p21.closestSegment( QgsPoint( 6, 13 ), pt, v, &leftOf ), 0.0 );
16232 : 1 : QCOMPARE( pt, QgsPoint( 6, 13 ) );
16233 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 2 ) );
16234 : 1 : QCOMPARE( leftOf, 0 );
16235 : :
16236 : : //nextVertex
16237 : 1 : QgsGeometryCollection p22;
16238 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16239 : 1 : v = QgsVertexId( 0, 0, -2 );
16240 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16241 : 1 : v = QgsVertexId( 0, 0, 10 );
16242 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16243 : 1 : QgsLineString lp22;
16244 : 1 : lp22.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
16245 : 1 : p22.addGeometry( lp22.clone() );
16246 : 1 : v = QgsVertexId( 0, 0, 4 ); //out of range
16247 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16248 : 1 : v = QgsVertexId( 0, 0, -5 );
16249 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16250 : 1 : v = QgsVertexId( 0, 0, -1 );
16251 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16252 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 0 ) );
16253 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
16254 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16255 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 1 ) );
16256 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
16257 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16258 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 2 ) );
16259 : 1 : QCOMPARE( pt, QgsPoint( 1, 12 ) );
16260 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16261 : 1 : QCOMPARE( v, QgsVertexId( 0, 0, 3 ) );
16262 : 1 : QCOMPARE( pt, QgsPoint( 1, 2 ) );
16263 : 1 : v = QgsVertexId( 1, 0, 0 );
16264 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16265 : 1 : v = QgsVertexId( 1, 0, 0 );
16266 : : // add another part
16267 : 1 : lp22.setPoints( QgsPointSequence() << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 11, 22 ) << QgsPoint( 11, 12 ) );
16268 : 1 : p22.addGeometry( lp22.clone() );
16269 : 1 : v = QgsVertexId( 1, 0, 4 ); //out of range
16270 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16271 : 1 : v = QgsVertexId( 1, 0, -5 );
16272 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16273 : 1 : v = QgsVertexId( 1, 0, -1 );
16274 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16275 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 0 ) );
16276 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
16277 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16278 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 1 ) );
16279 : 1 : QCOMPARE( pt, QgsPoint( 21, 22 ) );
16280 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16281 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 2 ) );
16282 : 1 : QCOMPARE( pt, QgsPoint( 11, 22 ) );
16283 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16284 : 1 : QCOMPARE( v, QgsVertexId( 1, 0, 3 ) );
16285 : 1 : QCOMPARE( pt, QgsPoint( 11, 12 ) );
16286 : 1 : v = QgsVertexId( 2, 0, 0 );
16287 : 1 : QVERIFY( !p22.nextVertex( v, pt ) );
16288 : 1 : v = QgsVertexId( 1, 1, 0 );
16289 : 1 : QVERIFY( p22.nextVertex( v, pt ) );
16290 : 1 : QCOMPARE( v, QgsVertexId( 1, 1, 1 ) ); //test that part number is maintained
16291 : 1 : QCOMPARE( pt, QgsPoint( 21, 22 ) );
16292 : :
16293 : :
16294 : : // dropZValue
16295 : 1 : QgsGeometryCollection p23;
16296 : 1 : p23.dropZValue();
16297 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16298 : 1 : QgsLineString lp23;
16299 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
16300 : 1 : p23.addGeometry( lp23.clone() );
16301 : 1 : p23.addGeometry( lp23.clone() );
16302 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16303 : 1 : p23.dropZValue(); // not z
16304 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16305 : 1 : QCOMPARE( p23.geometryN( 0 )->wkbType(), QgsWkbTypes::LineString );
16306 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16307 : 1 : QCOMPARE( p23.geometryN( 1 )->wkbType(), QgsWkbTypes::LineString );
16308 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16309 : : // with z
16310 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3 ) << QgsPoint( 11, 12, 13 ) << QgsPoint( 1, 12, 23 ) << QgsPoint( 1, 2, 3 ) );
16311 : 1 : p23.clear();
16312 : 1 : p23.addGeometry( lp23.clone() );
16313 : 1 : p23.addGeometry( lp23.clone() );
16314 : 1 : p23.dropZValue();
16315 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16316 : 1 : QCOMPARE( p23.geometryN( 0 )->wkbType(), QgsWkbTypes::LineString );
16317 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16318 : 1 : QCOMPARE( p23.geometryN( 1 )->wkbType(), QgsWkbTypes::LineString );
16319 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16320 : : // with zm
16321 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
16322 : 1 : p23.clear();
16323 : 1 : p23.addGeometry( lp23.clone() );
16324 : 1 : p23.addGeometry( lp23.clone() );
16325 : 1 : p23.dropZValue();
16326 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16327 : 1 : QCOMPARE( p23.geometryN( 0 )->wkbType(), QgsWkbTypes::LineStringM );
16328 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 0 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
16329 : 1 : QCOMPARE( p23.geometryN( 1 )->wkbType(), QgsWkbTypes::LineStringM );
16330 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 1 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 4 ) );
16331 : :
16332 : :
16333 : : // dropMValue
16334 : 1 : p23.clear();
16335 : 1 : p23.dropMValue();
16336 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16337 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 1, 12 ) << QgsPoint( 1, 2 ) );
16338 : 1 : p23.addGeometry( lp23.clone() );
16339 : 1 : p23.addGeometry( lp23.clone() );
16340 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16341 : 1 : p23.dropMValue(); // not zm
16342 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16343 : 1 : QCOMPARE( p23.geometryN( 0 )->wkbType(), QgsWkbTypes::LineString );
16344 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16345 : 1 : QCOMPARE( p23.geometryN( 1 )->wkbType(), QgsWkbTypes::LineString );
16346 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16347 : : // with m
16348 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) << QgsPoint( QgsWkbTypes::PointM, 11, 12, 0, 13 ) << QgsPoint( QgsWkbTypes::PointM, 1, 12, 0, 23 ) << QgsPoint( QgsWkbTypes::PointM, 1, 2, 0, 3 ) );
16349 : 1 : p23.clear();
16350 : 1 : p23.addGeometry( lp23.clone() );
16351 : 1 : p23.addGeometry( lp23.clone() );
16352 : 1 : p23.dropMValue();
16353 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16354 : 1 : QCOMPARE( p23.geometryN( 0 )->wkbType(), QgsWkbTypes::LineString );
16355 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16356 : 1 : QCOMPARE( p23.geometryN( 1 )->wkbType(), QgsWkbTypes::LineString );
16357 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 1, 2 ) );
16358 : : // with zm
16359 : 1 : lp23.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4 ) << QgsPoint( 11, 12, 13, 14 ) << QgsPoint( 1, 12, 23, 24 ) << QgsPoint( 1, 2, 3, 4 ) );
16360 : 1 : p23.clear();
16361 : 1 : p23.addGeometry( lp23.clone() );
16362 : 1 : p23.addGeometry( lp23.clone() );
16363 : 1 : p23.dropMValue();
16364 : 1 : QCOMPARE( p23.wkbType(), QgsWkbTypes::GeometryCollection );
16365 : 1 : QCOMPARE( p23.geometryN( 0 )->wkbType(), QgsWkbTypes::LineStringZ );
16366 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 0 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
16367 : 1 : QCOMPARE( p23.geometryN( 1 )->wkbType(), QgsWkbTypes::LineStringZ );
16368 : 1 : QCOMPARE( static_cast< const QgsLineString *>( p23.geometryN( 1 ) )->pointN( 0 ), QgsPoint( QgsWkbTypes::PointZ, 1, 2, 3 ) );
16369 : :
16370 : : //vertexAngle
16371 : 1 : QgsGeometryCollection p24;
16372 : 1 : ( void )p24.vertexAngle( QgsVertexId() ); //just want no crash
16373 : 1 : ( void )p24.vertexAngle( QgsVertexId( 0, 0, 0 ) ); //just want no crash
16374 : 1 : ( void )p24.vertexAngle( QgsVertexId( 0, 1, 0 ) ); //just want no crash
16375 : 1 : ( void )p24.vertexAngle( QgsVertexId( 1, 0, 0 ) ); //just want no crash
16376 : 1 : ( void )p24.vertexAngle( QgsVertexId( -1, 0, 0 ) ); //just want no crash
16377 : 1 : QgsLineString l38;
16378 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
16379 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ) );
16380 : 1 : p24.addGeometry( l38.clone() );
16381 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 0 ) ), 2.35619, 0.00001 );
16382 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 1 ) ), 1.5708, 0.0001 );
16383 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 2 ) ), 1.17809, 0.00001 );
16384 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 3 ) ), 0.0, 0.00001 );
16385 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 4 ) ), 5.10509, 0.00001 );
16386 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 5 ) ), 3.92699, 0.00001 );
16387 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 0, 0, 6 ) ), 2.35619, 0.00001 );
16388 : 1 : p24.addGeometry( l38.clone() );
16389 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 0 ) ), 2.35619, 0.00001 );
16390 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 1 ) ), 1.5708, 0.0001 );
16391 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 2 ) ), 1.17809, 0.00001 );
16392 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 3 ) ), 0.0, 0.00001 );
16393 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 4 ) ), 5.10509, 0.00001 );
16394 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 5 ) ), 3.92699, 0.00001 );
16395 : 1 : QGSCOMPARENEAR( p24.vertexAngle( QgsVertexId( 1, 0, 6 ) ), 2.35619, 0.00001 );
16396 : :
16397 : : //insert vertex
16398 : :
16399 : : //insert vertex in empty collection
16400 : 1 : QgsGeometryCollection p25;
16401 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16402 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 6.0, 7.0 ) ) );
16403 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 1, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16404 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16405 : 1 : QVERIFY( p25.isEmpty() );
16406 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 0.5, 0 ) << QgsPoint( 1, 0 )
16407 : 1 : << QgsPoint( 2, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ) );
16408 : 1 : p25.addGeometry( l38.clone() );
16409 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 0.3, 0 ) ) );
16410 : 1 : QCOMPARE( p25.nCoordinates(), 8 );
16411 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 0, 0 ) );
16412 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 0.3, 0 ) );
16413 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 0.5, 0 ) );
16414 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 6.0, 7.0 ) ) );
16415 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 0, 0, 100 ), QgsPoint( 6.0, 7.0 ) ) );
16416 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16417 : : // first vertex
16418 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 0, 0.1 ) ) );
16419 : 1 : QCOMPARE( p25.nCoordinates(), 9 );
16420 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
16421 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
16422 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
16423 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
16424 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 7 ), QgsPoint( 0, 2 ) );
16425 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 8 ), QgsPoint( 0, 0 ) );
16426 : : // last vertex
16427 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 0, 0, 9 ), QgsPoint( 0.1, 0.1 ) ) );
16428 : 1 : QCOMPARE( p25.nCoordinates(), 10 );
16429 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
16430 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
16431 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
16432 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
16433 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 8 ), QgsPoint( 0, 0 ) );
16434 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 0 ) )->pointN( 9 ), QgsPoint( 0.1, 0.1 ) );
16435 : : // with second part
16436 : 1 : p25.addGeometry( l38.clone() );
16437 : 1 : QCOMPARE( p25.nCoordinates(), 17 );
16438 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 1, 0, 1 ), QgsPoint( 0.3, 0 ) ) );
16439 : 1 : QCOMPARE( p25.nCoordinates(), 18 );
16440 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 0, 0 ) );
16441 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 0.3, 0 ) );
16442 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 0.5, 0 ) );
16443 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 1, 0, -1 ), QgsPoint( 6.0, 7.0 ) ) );
16444 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 1, 0, 100 ), QgsPoint( 6.0, 7.0 ) ) );
16445 : 1 : QVERIFY( !p25.insertVertex( QgsVertexId( 2, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16446 : : // first vertex in second part
16447 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 0, 0.1 ) ) );
16448 : 1 : QCOMPARE( p25.nCoordinates(), 19 );
16449 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
16450 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
16451 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
16452 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
16453 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 7 ), QgsPoint( 0, 2 ) );
16454 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 8 ), QgsPoint( 0, 0 ) );
16455 : : // last vertex in second part
16456 : 1 : QVERIFY( p25.insertVertex( QgsVertexId( 1, 0, 9 ), QgsPoint( 0.1, 0.1 ) ) );
16457 : 1 : QCOMPARE( p25.nCoordinates(), 20 );
16458 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 0, 0.1 ) );
16459 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 0, 0 ) );
16460 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 0.3, 0 ) );
16461 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 3 ), QgsPoint( 0.5, 0 ) );
16462 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 8 ), QgsPoint( 0, 0 ) );
16463 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p25.geometryN( 1 ) )->pointN( 9 ), QgsPoint( 0.1, 0.1 ) );
16464 : :
16465 : : //move vertex
16466 : :
16467 : : //empty collection
16468 : 1 : QgsGeometryCollection p26;
16469 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16470 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( -1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16471 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16472 : 1 : QVERIFY( p26.isEmpty() );
16473 : :
16474 : : //valid collection
16475 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
16476 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
16477 : 1 : p26.addGeometry( l38.clone() );
16478 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16479 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
16480 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 0, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
16481 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
16482 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
16483 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
16484 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 1, 2 ) );
16485 : :
16486 : : //out of range
16487 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
16488 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 0, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
16489 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 3.0, 4.0 ) ) );
16490 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
16491 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
16492 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
16493 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 1.0, 2.0 ) );
16494 : :
16495 : : // with second part
16496 : 1 : p26.addGeometry( l38.clone() );
16497 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 1, 0, 0 ), QgsPoint( 6.0, 7.0 ) ) );
16498 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 1, 0, 1 ), QgsPoint( 16.0, 17.0 ) ) );
16499 : 1 : QVERIFY( p26.moveVertex( QgsVertexId( 1, 0, 2 ), QgsPoint( 26.0, 27.0 ) ) );
16500 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 6.0, 7.0 ) );
16501 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 16.0, 17.0 ) );
16502 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 26.0, 27.0 ) );
16503 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p26.geometryN( 1 ) )->pointN( 3 ), QgsPoint( 1.0, 2.0 ) );
16504 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 1, 0, -1 ), QgsPoint( 3.0, 4.0 ) ) );
16505 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 1, 0, 10 ), QgsPoint( 3.0, 4.0 ) ) );
16506 : 1 : QVERIFY( !p26.moveVertex( QgsVertexId( 2, 0, 0 ), QgsPoint( 3.0, 4.0 ) ) );
16507 : :
16508 : : //delete vertex
16509 : :
16510 : : //empty collection
16511 : 1 : QgsGeometryCollection p27;
16512 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16513 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 1, 0 ) ) );
16514 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 1, 1, 0 ) ) );
16515 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( -1, 1, 0 ) ) );
16516 : 1 : QVERIFY( p27.isEmpty() );
16517 : :
16518 : : //valid collection
16519 : 2 : l38.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 5, 2 ) << QgsPoint( 6, 2 ) << QgsPoint( 7, 2 )
16520 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 21, 22 ) << QgsPoint( 1, 2 ) );
16521 : :
16522 : 1 : p27.addGeometry( l38.clone() );
16523 : : //out of range vertices
16524 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, -1 ) ) );
16525 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 0, 0, 100 ) ) );
16526 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 1, 0, 1 ) ) );
16527 : :
16528 : : //valid vertices
16529 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 1 ) ) );
16530 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
16531 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 6.0, 2.0 ) );
16532 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 7.0, 2.0 ) );
16533 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
16534 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 5 ), QgsPoint( 1.0, 2.0 ) );
16535 : :
16536 : : // delete first vertex
16537 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16538 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
16539 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
16540 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
16541 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
16542 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 4 ), QgsPoint( 1.0, 2.0 ) );
16543 : :
16544 : : // delete last vertex
16545 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 4 ) ) );
16546 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
16547 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
16548 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
16549 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 0 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
16550 : :
16551 : : // delete some more vertices - should remove part
16552 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16553 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16554 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16555 : 1 : QVERIFY( !p27.geometryN( 0 ) );
16556 : :
16557 : : // with two parts
16558 : 1 : p27.addGeometry( l38.clone() );
16559 : 1 : p27.addGeometry( l38.clone() );
16560 : :
16561 : : //out of range vertices
16562 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 1, 0, -1 ) ) );
16563 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 1, 0, 100 ) ) );
16564 : 1 : QVERIFY( !p27.deleteVertex( QgsVertexId( 2, 0, 1 ) ) );
16565 : :
16566 : : //valid vertices
16567 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 1, 0, 1 ) ) );
16568 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 1.0, 2.0 ) );
16569 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 6.0, 2.0 ) );
16570 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 7.0, 2.0 ) );
16571 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 3 ), QgsPoint( 11.0, 12.0 ) );
16572 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 5 ), QgsPoint( 1.0, 2.0 ) );
16573 : :
16574 : : // delete first vertex
16575 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 1, 0, 0 ) ) );
16576 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
16577 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
16578 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
16579 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
16580 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 4 ), QgsPoint( 1.0, 2.0 ) );
16581 : :
16582 : : // delete last vertex
16583 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 1, 0, 4 ) ) );
16584 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 0 ), QgsPoint( 6.0, 2.0 ) );
16585 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 1 ), QgsPoint( 7.0, 2.0 ) );
16586 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 2 ), QgsPoint( 11.0, 12.0 ) );
16587 : 1 : QCOMPARE( static_cast< const QgsLineString * >( p27.geometryN( 1 ) )->pointN( 3 ), QgsPoint( 21.0, 22.0 ) );
16588 : :
16589 : : // delete some more vertices - should remove part
16590 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 1, 0, 1 ) ) );
16591 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 1, 0, 1 ) ) );
16592 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 1, 0, 1 ) ) );
16593 : 1 : QCOMPARE( p27.numGeometries(), 1 );
16594 : 1 : QVERIFY( p27.geometryN( 0 ) );
16595 : :
16596 : : // test that second geometry is "promoted" when first is removed
16597 : 1 : p27.addGeometry( l38.clone() );
16598 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16599 : 1 : QCOMPARE( p27.numGeometries(), 2 );
16600 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16601 : 1 : QCOMPARE( p27.numGeometries(), 2 );
16602 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16603 : 1 : QCOMPARE( p27.numGeometries(), 2 );
16604 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16605 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16606 : 1 : QVERIFY( p27.deleteVertex( QgsVertexId( 0, 0, 0 ) ) );
16607 : 1 : QCOMPARE( p27.numGeometries(), 1 );
16608 : 1 : QVERIFY( p27.geometryN( 0 ) );
16609 : :
16610 : : //boundary
16611 : :
16612 : : // collections have no boundary defined
16613 : 1 : QgsGeometryCollection boundaryCollection;
16614 : 1 : QVERIFY( !boundaryCollection.boundary() );
16615 : : // add a geometry and retest, should still be undefined
16616 : 1 : QgsLineString *lineBoundary = new QgsLineString();
16617 : 1 : lineBoundary->setPoints( QgsPointSequence() << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) );
16618 : 1 : boundaryCollection.addGeometry( lineBoundary );
16619 : 1 : QVERIFY( !boundaryCollection.boundary() );
16620 : :
16621 : : // segmentize
16622 : 1 : QgsGeometryCollection segmentC;
16623 : 1 : QgsCircularString toSegment;
16624 : 2 : toSegment.setPoints( QgsPointSequence() << QgsPoint( 1, 2 )
16625 : 1 : << QgsPoint( 11, 10 ) << QgsPoint( 21, 2 ) );
16626 : 1 : segmentC.addGeometry( toSegment.clone() );
16627 : 1 : std::unique_ptr<QgsGeometryCollection> segmentized( static_cast< QgsGeometryCollection * >( segmentC.segmentize() ) );
16628 : 1 : const QgsLineString *segmentizedLine = static_cast< const QgsLineString * >( segmentized->geometryN( 0 ) );
16629 : 1 : QCOMPARE( segmentizedLine->numPoints(), 156 );
16630 : 1 : QCOMPARE( segmentizedLine->vertexCount(), 156 );
16631 : 1 : QCOMPARE( segmentizedLine->ringCount(), 1 );
16632 : 1 : QCOMPARE( segmentizedLine->partCount(), 1 );
16633 : 1 : QCOMPARE( segmentizedLine->wkbType(), QgsWkbTypes::LineString );
16634 : 1 : QVERIFY( !segmentizedLine->is3D() );
16635 : 1 : QVERIFY( !segmentizedLine->isMeasure() );
16636 : 1 : QCOMPARE( segmentizedLine->pointN( 0 ), toSegment.pointN( 0 ) );
16637 : 1 : QCOMPARE( segmentizedLine->pointN( segmentizedLine->numPoints() - 1 ), toSegment.pointN( toSegment.numPoints() - 1 ) );
16638 : :
16639 : : // hasCurvedSegments
16640 : 1 : QgsGeometryCollection c30;
16641 : 1 : QVERIFY( !c30.hasCurvedSegments() );
16642 : 1 : c30.addGeometry( part.clone() );
16643 : 1 : QVERIFY( !c30.hasCurvedSegments() );
16644 : 1 : c30.addGeometry( toSegment.clone() );
16645 : 1 : QVERIFY( c30.hasCurvedSegments() );
16646 : :
16647 : :
16648 : : //adjacent vertices
16649 : 1 : QgsGeometryCollection c31;
16650 : 1 : QgsLineString vertexLine1;
16651 : 1 : QgsVertexId prev( 1, 2, 3 ); // start with something
16652 : 1 : QgsVertexId next( 4, 5, 6 );
16653 : 1 : c31.adjacentVertices( QgsVertexId( 0, 0, -1 ), prev, next );
16654 : 1 : QCOMPARE( prev, QgsVertexId() );
16655 : 1 : QCOMPARE( next, QgsVertexId() );
16656 : 1 : c31.adjacentVertices( QgsVertexId( -1, 0, -1 ), prev, next );
16657 : 1 : QCOMPARE( prev, QgsVertexId() );
16658 : 1 : QCOMPARE( next, QgsVertexId() );
16659 : 1 : c31.adjacentVertices( QgsVertexId( 10, 0, -1 ), prev, next );
16660 : 1 : QCOMPARE( prev, QgsVertexId() );
16661 : 1 : QCOMPARE( next, QgsVertexId() );
16662 : 1 : vertexLine1.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 112 ) );
16663 : 1 : c31.addGeometry( vertexLine1.clone() );
16664 : 1 : c31.addGeometry( vertexLine1.clone() );
16665 : 1 : c31.adjacentVertices( QgsVertexId( -1, 0, -1 ), prev, next );
16666 : 1 : QCOMPARE( prev, QgsVertexId() );
16667 : 1 : QCOMPARE( next, QgsVertexId() );
16668 : 1 : c31.adjacentVertices( QgsVertexId( 10, 0, -1 ), prev, next );
16669 : 1 : QCOMPARE( prev, QgsVertexId() );
16670 : 1 : QCOMPARE( next, QgsVertexId() );
16671 : 1 : c31.adjacentVertices( QgsVertexId( 0, 0, 0 ), prev, next );
16672 : 1 : QCOMPARE( prev, QgsVertexId() );
16673 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
16674 : 1 : c31.adjacentVertices( QgsVertexId( 0, 0, 1 ), prev, next );
16675 : 1 : QCOMPARE( prev, QgsVertexId( 0, 0, 0 ) );
16676 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
16677 : 1 : c31.adjacentVertices( QgsVertexId( 1, 0, 1 ), prev, next );
16678 : 1 : QCOMPARE( prev, QgsVertexId( 1, 0, 0 ) );
16679 : 1 : QCOMPARE( next, QgsVertexId( 1, 0, 2 ) );
16680 : :
16681 : :
16682 : : // vertex number
16683 : 1 : QgsGeometryCollection c32;
16684 : 1 : QgsLineString vertexLine2;
16685 : 1 : vertexLine2.setPoints( QgsPointSequence() << QgsPoint( 1, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 112 ) );
16686 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
16687 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
16688 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, -1, 0 ) ), -1 );
16689 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), -1 );
16690 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, -1 ) ), -1 );
16691 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), -1 );
16692 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), -1 );
16693 : 1 : c32.addGeometry( vertexLine2.clone() );
16694 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( -1, 0, 0 ) ), -1 );
16695 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), -1 );
16696 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, -1, 0 ) ), -1 );
16697 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 1, 0 ) ), -1 );
16698 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, -1 ) ), -1 );
16699 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
16700 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), 1 );
16701 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 2 ) ), 2 );
16702 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 3 ) ), -1 );
16703 : 1 : c32.addGeometry( vertexLine2.clone() );
16704 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
16705 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), 1 );
16706 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 2 ) ), 2 );
16707 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 3 ) ), -1 );
16708 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), 3 );
16709 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 1 ) ), 4 );
16710 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 2 ) ), 5 );
16711 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 3 ) ), -1 );
16712 : 1 : QgsPolygon polyPart;
16713 : 1 : vertexLine2.close();
16714 : 1 : polyPart.setExteriorRing( vertexLine2.clone() );
16715 : 1 : c32.addGeometry( polyPart.clone() );
16716 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 0 ) ), 0 );
16717 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 1 ) ), 1 );
16718 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 2 ) ), 2 );
16719 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 0, 0, 3 ) ), -1 );
16720 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 0 ) ), 3 );
16721 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 1 ) ), 4 );
16722 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 2 ) ), 5 );
16723 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 1, 0, 3 ) ), -1 );
16724 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, -1, 0 ) ), -1 );
16725 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 1, 0 ) ), -1 );
16726 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, -1 ) ), -1 );
16727 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 0 ) ), 6 );
16728 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 1 ) ), 7 );
16729 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 2 ) ), 8 );
16730 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 3 ) ), 9 );
16731 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 4 ) ), -1 );
16732 : 1 : polyPart.addInteriorRing( vertexLine2.clone() );
16733 : 1 : c32.addGeometry( polyPart.clone() );
16734 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 0 ) ), 6 );
16735 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 1 ) ), 7 );
16736 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 2 ) ), 8 );
16737 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 3 ) ), 9 );
16738 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 2, 0, 4 ) ), -1 );
16739 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, -1, 0 ) ), -1 );
16740 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 2, 0 ) ), -1 );
16741 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 0, 0 ) ), 10 );
16742 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 0, 1 ) ), 11 );
16743 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 0, 2 ) ), 12 );
16744 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 0, 3 ) ), 13 );
16745 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 0, 4 ) ), -1 );
16746 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 1, 0 ) ), 14 );
16747 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 1, 1 ) ), 15 );
16748 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 1, 2 ) ), 16 );
16749 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 1, 3 ) ), 17 );
16750 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 1, 4 ) ), -1 );
16751 : 1 : QCOMPARE( c32.vertexNumberFromVertexId( QgsVertexId( 3, 2, 0 ) ), -1 );
16752 : :
16753 : :
16754 : : //removeDuplicateNodes
16755 : 1 : QgsGeometryCollection gcNodes;
16756 : 1 : QgsLineString nodeLine;
16757 : 1 : QVERIFY( !gcNodes.removeDuplicateNodes() );
16758 : 1 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) );
16759 : 1 : gcNodes.addGeometry( nodeLine.clone() );
16760 : 1 : QVERIFY( !gcNodes.removeDuplicateNodes( 0.02 ) );
16761 : 2 : QCOMPARE( gcNodes.asWkt(), QStringLiteral( "GeometryCollection (LineString (11 2, 11 12, 111 12))" ) );
16762 : 2 : nodeLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2 ) << QgsPoint( 11.01, 1.99 ) << QgsPoint( 11.02, 2.01 )
16763 : 1 : << QgsPoint( 11, 12 ) << QgsPoint( 111, 12 ) << QgsPoint( 111.01, 11.99 ) );
16764 : 1 : gcNodes.addGeometry( nodeLine.clone() );
16765 : 1 : QVERIFY( gcNodes.removeDuplicateNodes( 0.02 ) );
16766 : 1 : QVERIFY( !gcNodes.removeDuplicateNodes( 0.02 ) );
16767 : 2 : QCOMPARE( gcNodes.asWkt( 2 ), QStringLiteral( "GeometryCollection (LineString (11 2, 11 12, 111 12),LineString (11 2, 11 12, 111 12))" ) );
16768 : :
16769 : : //swapXy
16770 : 1 : QgsGeometryCollection swapCollect;
16771 : 1 : QgsLineString swapLine;
16772 : 1 : swapCollect.swapXy(); // no crash
16773 : 1 : swapLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
16774 : 1 : swapCollect.addGeometry( swapLine.clone() );
16775 : 1 : swapCollect.swapXy();
16776 : 2 : QCOMPARE( swapCollect.asWkt(), QStringLiteral( "GeometryCollection (LineStringZM (2 11 3 4, 12 11 13 14, 12 111 23 24))" ) );
16777 : 1 : swapLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 11.01, 1.99, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11.02, 2.01, 25, 26, QgsWkbTypes::PointZM ) );
16778 : 1 : swapCollect.addGeometry( swapLine.clone() );
16779 : 1 : swapCollect.swapXy();
16780 : 2 : QCOMPARE( swapCollect.asWkt( 2 ), QStringLiteral( "GeometryCollection (LineStringZM (11 2 3 4, 11 12 13 14, 111 12 23 24),LineStringZM (2 11 5 6, 1.99 11.01 15 16, 2.01 11.02 25 26))" ) );
16781 : :
16782 : : // filter vertices
16783 : 1 : QgsGeometryCollection filterCollect;
16784 : 8 : auto filter = []( const QgsPoint & point )-> bool
16785 : : {
16786 : 8 : return point.x() > 5;
16787 : : };
16788 : 1 : QgsLineString filterLine;
16789 : 1 : filterCollect.filterVertices( filter ); // no crash
16790 : 1 : filterLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
16791 : 1 : filterCollect.addGeometry( filterLine.clone() );
16792 : 1 : filterCollect.filterVertices( filter );
16793 : 2 : QCOMPARE( filterCollect.asWkt(), QStringLiteral( "GeometryCollection (LineStringZM (11 12 13 14, 111 12 23 24))" ) );
16794 : 1 : filterLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 1.01, 1.99, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11.02, 2.01, 25, 26, QgsWkbTypes::PointZM ) );
16795 : 1 : filterCollect.addGeometry( filterLine.clone() );
16796 : 1 : filterCollect.filterVertices( filter );
16797 : 2 : QCOMPARE( filterCollect.asWkt( 2 ), QStringLiteral( "GeometryCollection (LineStringZM (11 12 13 14, 111 12 23 24),LineStringZM (11 2 5 6, 11.02 2.01 25 26))" ) );
16798 : :
16799 : : // transform vertices
16800 : 1 : QgsGeometryCollection transformCollect;
16801 : 9 : auto transform = []( const QgsPoint & point )-> QgsPoint
16802 : : {
16803 : 9 : return QgsPoint( point.x() + 2, point.y() + 3, point.z() + 4, point.m() + 5 );
16804 : : };
16805 : 1 : QgsLineString transformLine;
16806 : 1 : transformCollect.transformVertices( transform ); // no crash
16807 : 1 : transformLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
16808 : 1 : transformCollect.addGeometry( transformLine.clone() );
16809 : 1 : transformCollect.transformVertices( transform );
16810 : 2 : QCOMPARE( transformCollect.asWkt(), QStringLiteral( "GeometryCollection (LineStringZM (3 5 7 9, 13 15 17 19, 113 15 27 29))" ) );
16811 : 1 : transformLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 1.01, 1.99, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11.02, 2.01, 25, 26, QgsWkbTypes::PointZM ) );
16812 : 1 : transformCollect.addGeometry( transformLine.clone() );
16813 : 1 : transformCollect.transformVertices( transform );
16814 : 2 : QCOMPARE( transformCollect.asWkt( 2 ), QStringLiteral( "GeometryCollection (LineStringZM (5 8 11 14, 15 18 21 24, 115 18 31 34),LineStringZM (13 5 9 11, 3.01 4.99 19 21, 13.02 5.01 29 31))" ) );
16815 : :
16816 : : // transform using class
16817 : 1 : TestTransformer transformer;
16818 : 1 : QgsGeometryCollection transformCollect2;
16819 : 1 : transformCollect2.transform( &transformer ); // no crash
16820 : 1 : transformLine.setPoints( QgsPointSequence() << QgsPoint( 1, 2, 3, 4, QgsWkbTypes::PointZM ) << QgsPoint( 11, 12, 13, 14, QgsWkbTypes::PointZM ) << QgsPoint( 111, 12, 23, 24, QgsWkbTypes::PointZM ) );
16821 : 1 : transformCollect2.addGeometry( transformLine.clone() );
16822 : 1 : QVERIFY( transformCollect2.transform( &transformer ) );
16823 : 2 : QCOMPARE( transformCollect2.asWkt(), QStringLiteral( "GeometryCollection (LineStringZM (3 16 8 3, 33 26 18 13, 333 26 28 23))" ) );
16824 : 1 : transformLine.setPoints( QgsPointSequence() << QgsPoint( 11, 2, 5, 6, QgsWkbTypes::PointZM ) << QgsPoint( 1.01, 1.99, 15, 16, QgsWkbTypes::PointZM ) << QgsPoint( 11.02, 2.01, 25, 26, QgsWkbTypes::PointZM ) );
16825 : 1 : transformCollect2.addGeometry( transformLine.clone() );
16826 : 1 : QVERIFY( transformCollect2.transform( &transformer ) );
16827 : 2 : QCOMPARE( transformCollect2.asWkt( 2 ), QStringLiteral( "GeometryCollection (LineStringZM (9 30 13 2, 99 40 23 12, 999 40 33 22),LineStringZM (33 16 10 5, 3.03 15.99 20 15, 33.06 16.01 30 25))" ) );
16828 : :
16829 : 1 : TestFailTransformer failTransformer;
16830 : 1 : QVERIFY( !transformCollect2.transform( &failTransformer ) );
16831 : 1 : }
16832 : :
16833 : 1 : void TestQgsGeometry::fromQgsPointXY()
16834 : : {
16835 : 1 : QgsPointXY point( 1.0, 2.0 );
16836 : 1 : QgsGeometry result( QgsGeometry::fromPointXY( point ) );
16837 : 1 : QCOMPARE( result.wkbType(), QgsWkbTypes::Point );
16838 : 1 : QgsPointXY resultPoint = result.asPoint();
16839 : 1 : QCOMPARE( resultPoint, point );
16840 : 1 : }
16841 : :
16842 : 1 : void TestQgsGeometry::fromQPoint()
16843 : : {
16844 : 1 : QPointF point( 1.0, 2.0 );
16845 : 1 : QgsGeometry result( QgsGeometry::fromQPointF( point ) );
16846 : 1 : QCOMPARE( result.wkbType(), QgsWkbTypes::Point );
16847 : 1 : QgsPointXY resultPoint = result.asPoint();
16848 : 1 : QCOMPARE( resultPoint.x(), 1.0 );
16849 : 1 : QCOMPARE( resultPoint.y(), 2.0 );
16850 : 1 : }
16851 : :
16852 : 1 : void TestQgsGeometry::fromQPolygonF()
16853 : : {
16854 : : //test with a polyline
16855 : 1 : QPolygonF polyline;
16856 : 1 : polyline << QPointF( 1.0, 2.0 ) << QPointF( 4.0, 6.0 ) << QPointF( 4.0, 3.0 ) << QPointF( 2.0, 2.0 );
16857 : 1 : QgsGeometry result( QgsGeometry::fromQPolygonF( polyline ) );
16858 : 1 : QCOMPARE( result.wkbType(), QgsWkbTypes::LineString );
16859 : 1 : QgsPolylineXY resultLine = result.asPolyline();
16860 : 1 : QCOMPARE( resultLine.size(), 4 );
16861 : 1 : QCOMPARE( resultLine.at( 0 ), QgsPointXY( 1.0, 2.0 ) );
16862 : 1 : QCOMPARE( resultLine.at( 1 ), QgsPointXY( 4.0, 6.0 ) );
16863 : 1 : QCOMPARE( resultLine.at( 2 ), QgsPointXY( 4.0, 3.0 ) );
16864 : 1 : QCOMPARE( resultLine.at( 3 ), QgsPointXY( 2.0, 2.0 ) );
16865 : :
16866 : : //test with a closed polygon
16867 : 1 : QPolygonF polygon;
16868 : 1 : polygon << QPointF( 1.0, 2.0 ) << QPointF( 4.0, 6.0 ) << QPointF( 4.0, 3.0 ) << QPointF( 2.0, 2.0 ) << QPointF( 1.0, 2.0 );
16869 : 1 : QgsGeometry result2( QgsGeometry::fromQPolygonF( polygon ) );
16870 : 1 : QCOMPARE( result2.wkbType(), QgsWkbTypes::Polygon );
16871 : 1 : QgsPolygonXY resultPolygon = result2.asPolygon();
16872 : 1 : QCOMPARE( resultPolygon.size(), 1 );
16873 : 1 : QCOMPARE( resultPolygon.at( 0 ).at( 0 ), QgsPointXY( 1.0, 2.0 ) );
16874 : 1 : QCOMPARE( resultPolygon.at( 0 ).at( 1 ), QgsPointXY( 4.0, 6.0 ) );
16875 : 1 : QCOMPARE( resultPolygon.at( 0 ).at( 2 ), QgsPointXY( 4.0, 3.0 ) );
16876 : 1 : QCOMPARE( resultPolygon.at( 0 ).at( 3 ), QgsPointXY( 2.0, 2.0 ) );
16877 : 1 : QCOMPARE( resultPolygon.at( 0 ).at( 4 ), QgsPointXY( 1.0, 2.0 ) );
16878 : 1 : }
16879 : :
16880 : 1 : void TestQgsGeometry::fromPolyline()
16881 : : {
16882 : 1 : QgsPolyline polyline;
16883 : 1 : QgsGeometry fromPolyline = QgsGeometry::fromPolyline( polyline );
16884 : 1 : QVERIFY( fromPolyline.isEmpty() );
16885 : 1 : QCOMPARE( fromPolyline.wkbType(), QgsWkbTypes::LineString );
16886 : 1 : polyline << QgsPoint( 10, 20 ) << QgsPoint( 30, 40 );
16887 : 1 : fromPolyline = QgsGeometry::fromPolyline( polyline );
16888 : 2 : QCOMPARE( fromPolyline.asWkt(), QStringLiteral( "LineString (10 20, 30 40)" ) );
16889 : 1 : QgsPolyline polyline3d;
16890 : 1 : polyline3d << QgsPoint( QgsWkbTypes::PointZ, 10, 20, 100 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 40, 200 );
16891 : 1 : fromPolyline = QgsGeometry::fromPolyline( polyline3d );
16892 : 2 : QCOMPARE( fromPolyline.asWkt(), QStringLiteral( "LineStringZ (10 20 100, 30 40 200)" ) );
16893 : 1 : QgsPolyline polylineM;
16894 : 1 : polylineM << QgsPoint( QgsWkbTypes::PointM, 10, 20, 0, 100 ) << QgsPoint( QgsWkbTypes::PointM, 30, 40, 0, 200 );
16895 : 1 : fromPolyline = QgsGeometry::fromPolyline( polylineM );
16896 : 2 : QCOMPARE( fromPolyline.asWkt(), QStringLiteral( "LineStringM (10 20 100, 30 40 200)" ) );
16897 : 1 : QgsPolyline polylineZM;
16898 : 1 : polylineZM << QgsPoint( QgsWkbTypes::PointZM, 10, 20, 4, 100 ) << QgsPoint( QgsWkbTypes::PointZM, 30, 40, 5, 200 );
16899 : 1 : fromPolyline = QgsGeometry::fromPolyline( polylineZM );
16900 : 2 : QCOMPARE( fromPolyline.asWkt(), QStringLiteral( "LineStringZM (10 20 4 100, 30 40 5 200)" ) );
16901 : 1 : }
16902 : :
16903 : 1 : void TestQgsGeometry::asQPointF()
16904 : : {
16905 : 1 : QPointF point( 1.0, 2.0 );
16906 : 1 : QgsGeometry geom( QgsGeometry::fromQPointF( point ) );
16907 : 1 : QPointF resultPoint = geom.asQPointF();
16908 : 1 : QCOMPARE( resultPoint, point );
16909 : :
16910 : : //non point geom
16911 : 1 : QPointF badPoint = mpPolygonGeometryA.asQPointF();
16912 : 1 : QVERIFY( badPoint.isNull() );
16913 : 1 : }
16914 : :
16915 : 1 : void TestQgsGeometry::asQPolygonF()
16916 : : {
16917 : 1 : QgsPointXY point1 = QgsPointXY( 20.0, 20.0 );
16918 : 1 : QgsPointXY point2 = QgsPointXY( 80.0, 20.0 );
16919 : 1 : QgsPointXY point3 = QgsPointXY( 80.0, 80.0 );
16920 : 1 : QgsPointXY point4 = QgsPointXY( 20.0, 80.0 );
16921 : :
16922 : 1 : QgsGeometry polygonGeometryA = QgsGeometry::fromPolygonXY( QgsPolygonXY() << ( QgsPolylineXY() << point1 << point2 << point3 << point4 << point1 ) );
16923 : :
16924 : : //test polygon
16925 : 1 : QPolygonF fromPoly = polygonGeometryA.asQPolygonF();
16926 : 1 : QVERIFY( fromPoly.isClosed() );
16927 : 1 : QCOMPARE( fromPoly.size(), 5 );
16928 : 1 : QCOMPARE( fromPoly.at( 0 ).x(), point1.x() );
16929 : 1 : QCOMPARE( fromPoly.at( 0 ).y(), point1.y() );
16930 : 1 : QCOMPARE( fromPoly.at( 1 ).x(), point2.x() );
16931 : 1 : QCOMPARE( fromPoly.at( 1 ).y(), point2.y() );
16932 : 1 : QCOMPARE( fromPoly.at( 2 ).x(), point3.x() );
16933 : 1 : QCOMPARE( fromPoly.at( 2 ).y(), point3.y() );
16934 : 1 : QCOMPARE( fromPoly.at( 3 ).x(), point4.x() );
16935 : 1 : QCOMPARE( fromPoly.at( 3 ).y(), point4.y() );
16936 : 1 : QCOMPARE( fromPoly.at( 4 ).x(), point1.x() );
16937 : 1 : QCOMPARE( fromPoly.at( 4 ).y(), point1.y() );
16938 : :
16939 : : //test polyline
16940 : 1 : QgsPolylineXY testline;
16941 : 1 : testline << point1 << point2 << point3;
16942 : 1 : QgsGeometry lineGeom( QgsGeometry::fromPolylineXY( testline ) );
16943 : 1 : QPolygonF fromLine = lineGeom.asQPolygonF();
16944 : 1 : QVERIFY( !fromLine.isClosed() );
16945 : 1 : QCOMPARE( fromLine.size(), 3 );
16946 : 1 : QCOMPARE( fromLine.at( 0 ).x(), point1.x() );
16947 : 1 : QCOMPARE( fromLine.at( 0 ).y(), point1.y() );
16948 : 1 : QCOMPARE( fromLine.at( 1 ).x(), point2.x() );
16949 : 1 : QCOMPARE( fromLine.at( 1 ).y(), point2.y() );
16950 : 1 : QCOMPARE( fromLine.at( 2 ).x(), point3.x() );
16951 : 1 : QCOMPARE( fromLine.at( 2 ).y(), point3.y() );
16952 : :
16953 : : //test a bad geometry
16954 : 1 : QgsGeometry badGeom( QgsGeometry::fromPointXY( point1 ) );
16955 : 1 : QPolygonF fromBad = badGeom.asQPolygonF();
16956 : 1 : QVERIFY( fromBad.isEmpty() );
16957 : :
16958 : : // test a multipolygon
16959 : 2 : QPolygonF res = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0 )),((2 2, 4 2, 4 4, 2 4, 2 2)))" ) ).asQPolygonF();
16960 : 1 : QVERIFY( res.isClosed() );
16961 : 1 : QCOMPARE( res.size(), 5 );
16962 : 1 : QCOMPARE( res.at( 0 ).x(), 0.0 );
16963 : 1 : QCOMPARE( res.at( 0 ).y(), 0.0 );
16964 : 1 : QCOMPARE( res.at( 1 ).x(), 10.0 );
16965 : 1 : QCOMPARE( res.at( 1 ).y(), 0.0 );
16966 : 1 : QCOMPARE( res.at( 2 ).x(), 10.0 );
16967 : 1 : QCOMPARE( res.at( 2 ).y(), 10.0 );
16968 : 1 : QCOMPARE( res.at( 3 ).x(), 0.0 );
16969 : 1 : QCOMPARE( res.at( 3 ).y(), 10.0 );
16970 : 1 : QCOMPARE( res.at( 4 ).x(), 0.0 );
16971 : 1 : QCOMPARE( res.at( 4 ).y(), 0.0 );
16972 : :
16973 : : // test a multilinestring
16974 : 2 : res = QgsGeometry::fromWkt( QStringLiteral( "MultiLineString((0 0, 10 0, 10 10, 0 10 ),(2 2, 4 2, 4 4, 2 4))" ) ).asQPolygonF();
16975 : 1 : QVERIFY( !res.isClosed() );
16976 : 1 : QCOMPARE( res.size(), 4 );
16977 : 1 : QCOMPARE( res.at( 0 ).x(), 0.0 );
16978 : 1 : QCOMPARE( res.at( 0 ).y(), 0.0 );
16979 : 1 : QCOMPARE( res.at( 1 ).x(), 10.0 );
16980 : 1 : QCOMPARE( res.at( 1 ).y(), 0.0 );
16981 : 1 : QCOMPARE( res.at( 2 ).x(), 10.0 );
16982 : 1 : QCOMPARE( res.at( 2 ).y(), 10.0 );
16983 : 1 : QCOMPARE( res.at( 3 ).x(), 0.0 );
16984 : 1 : QCOMPARE( res.at( 3 ).y(), 10.0 );
16985 : 1 : }
16986 : :
16987 : 1 : void TestQgsGeometry::comparePolylines()
16988 : : {
16989 : 1 : QgsPointXY point1 = QgsPointXY( 20.0, 20.0 );
16990 : 1 : QgsPointXY point2 = QgsPointXY( 80.0, 20.0 );
16991 : 1 : QgsPointXY point3 = QgsPointXY( 80.0, 80.0 );
16992 : 1 : QgsPointXY point4 = QgsPointXY( 20.0, 80.0 );
16993 : 1 : QgsPointXY pointA = QgsPointXY( 40.0, 40.0 );
16994 : :
16995 : 1 : QgsPolylineXY line1;
16996 : 1 : line1 << point1 << point2 << point3;
16997 : 1 : QgsPolylineXY line2;
16998 : 1 : line2 << point1 << point2 << point3;
16999 : 1 : QVERIFY( QgsGeometry::compare( line1, line2 ) );
17000 : :
17001 : : //different number of nodes
17002 : 1 : QgsPolylineXY line3;
17003 : 1 : line3 << point1 << point2 << point3 << point4;
17004 : 1 : QVERIFY( !QgsGeometry::compare( line1, line3 ) );
17005 : :
17006 : : //different nodes
17007 : 1 : QgsPolylineXY line4;
17008 : 1 : line3 << point1 << pointA << point3 << point4;
17009 : 1 : QVERIFY( !QgsGeometry::compare( line3, line4 ) );
17010 : 1 : }
17011 : :
17012 : 1 : void TestQgsGeometry::comparePolygons()
17013 : : {
17014 : 1 : QgsPointXY point1 = QgsPointXY( 20.0, 20.0 );
17015 : 1 : QgsPointXY point2 = QgsPointXY( 80.0, 20.0 );
17016 : 1 : QgsPointXY point3 = QgsPointXY( 80.0, 80.0 );
17017 : 1 : QgsPointXY point4 = QgsPointXY( 20.0, 80.0 );
17018 : 1 : QgsPointXY pointA = QgsPointXY( 40.0, 40.0 );
17019 : 1 : QgsPointXY pointB = QgsPointXY( 100.0, 40.0 );
17020 : :
17021 : 1 : QgsPolylineXY ring1;
17022 : 1 : ring1 << point1 << point2 << point3 << point1;
17023 : 1 : QgsPolylineXY ring2;
17024 : 1 : ring2 << point4 << pointA << pointB << point4;
17025 : 1 : QgsPolygonXY poly1;
17026 : 1 : poly1 << ring1 << ring2;
17027 : 1 : QgsPolygonXY poly2;
17028 : 1 : poly2 << ring1 << ring2;
17029 : 1 : QVERIFY( QgsGeometry::compare( poly1, poly2 ) );
17030 : :
17031 : : //different number of rings
17032 : 1 : QgsPolygonXY poly3;
17033 : 1 : poly3 << ring1;
17034 : 1 : QVERIFY( !QgsGeometry::compare( poly1, poly3 ) );
17035 : :
17036 : : //different rings
17037 : 1 : QgsPolygonXY poly4;
17038 : 1 : poly4 << ring2;
17039 : 1 : QVERIFY( !QgsGeometry::compare( poly3, poly4 ) );
17040 : 1 : }
17041 : :
17042 : : #if defined(__clang__) || defined(__GNUG__)
17043 : : #include <cxxabi.h>
17044 : : #include <ctime>
17045 : :
17046 : 1392 : QString generateSpacesString( int numberOfSpace )
17047 : : {
17048 : 1392 : QStringList spaces;
17049 : 1392 : spaces << QString( " " ) << QString( "\t" ) << QString( "\n" ) << QString( "\r" );
17050 : :
17051 : 1392 : QString ret;
17052 : 7872 : for ( int i = 0; i < numberOfSpace; ++i )
17053 : : {
17054 : 6480 : int r = rand() % ( spaces.count() );
17055 : 6480 : ret += spaces.at( r );
17056 : 6480 : }
17057 : 1392 : return ret;
17058 : 1392 : }
17059 : :
17060 : : #endif
17061 : : // Helper function (in anonymous namespace to prevent possible link with the extirior)
17062 : : namespace
17063 : : {
17064 : : template<typename T>
17065 : 12 : inline void testCreateEmptyWithSameType()
17066 : : {
17067 : 12 : std::unique_ptr<QgsAbstractGeometry> geom { new T() };
17068 : 12 : std::unique_ptr<QgsAbstractGeometry> created { TestQgsGeometry::createEmpty( geom.get() ) };
17069 : 12 : QVERIFY( created->isEmpty() );
17070 : : #if defined(__clang__) || defined(__GNUG__)
17071 : 12 : srand( ( unsigned )time( NULL ) );
17072 : :
17073 : 12 : const std::type_info &ti = typeid( T );
17074 : : int status;
17075 : 12 : char *realname = abi::__cxa_demangle( ti.name(), 0, 0, &status );
17076 : :
17077 : 12 : QString type = realname;
17078 : : // remove Qgs prefix
17079 : 12 : type = type.right( type.count() - 3 );
17080 : 12 : QStringList extensionZM;
17081 : 12 : extensionZM << QString() << QString( "Z" ) << QString( "M" ) << QString( "ZM" );
17082 : 60 : for ( QString ext : extensionZM )
17083 : : {
17084 : 48 : QString wkt = type + ext;
17085 : 48 : QString result = wkt + QLatin1String( " EMPTY" );
17086 : :
17087 : 48 : QStringList emptyStringList;
17088 : 48 : emptyStringList << QString( "EMPTY" ) << QString( "Empty" ) << QString( "empty" ) << QString( "EmptY" ) << QString( "EmPtY" );
17089 : 528 : for ( int i = 0 ; i < 10 ; ++i )
17090 : : {
17091 : 480 : QString spacesBefore = generateSpacesString( i );
17092 : 528 : QString spacesMiddle = i == 0 ? QStringLiteral( " " ) : generateSpacesString( i );
17093 : 480 : QString spacesAfter = generateSpacesString( i );
17094 : 2880 : for ( int j = 0; j < emptyStringList.count() ; ++j )
17095 : : {
17096 : 2400 : QString generatedWkt = spacesBefore + wkt + spacesMiddle + emptyStringList.at( j ) + spacesAfter;
17097 : :
17098 : 2400 : QgsGeometry gWkt = QgsGeometry().fromWkt( generatedWkt );
17099 : 2400 : QVERIFY( gWkt.asWkt().compare( result, Qt::CaseInsensitive ) == 0 );
17100 : :
17101 : 2400 : QVERIFY( geom->fromWkt( generatedWkt ) );
17102 : 2400 : QVERIFY( geom->asWkt().compare( result, Qt::CaseInsensitive ) == 0 );
17103 : 2400 : }
17104 : 480 : }
17105 : 48 : }
17106 : 12 : free( realname );
17107 : : #endif
17108 : :
17109 : :
17110 : : // Check that it is the correct type
17111 : 12 : QVERIFY( static_cast<T *>( created.get() ) != nullptr );
17112 : 12 : }
17113 : : }
17114 : :
17115 : 1 : void TestQgsGeometry::createEmptyWithSameType()
17116 : : {
17117 : 1 : testCreateEmptyWithSameType<QgsCircularString>();
17118 : 1 : testCreateEmptyWithSameType<QgsCompoundCurve>();
17119 : 1 : testCreateEmptyWithSameType<QgsLineString>();
17120 : 1 : testCreateEmptyWithSameType<QgsGeometryCollection>();
17121 : 1 : testCreateEmptyWithSameType<QgsMultiCurve>();
17122 : 1 : testCreateEmptyWithSameType<QgsMultiLineString>();
17123 : 1 : testCreateEmptyWithSameType<QgsMultiPoint>();
17124 : 1 : testCreateEmptyWithSameType<QgsMultiSurface>();
17125 : 1 : testCreateEmptyWithSameType<QgsPoint>();
17126 : 1 : testCreateEmptyWithSameType<QgsCurvePolygon>();
17127 : 1 : testCreateEmptyWithSameType<QgsPolygon>();
17128 : 1 : testCreateEmptyWithSameType<QgsTriangle>();
17129 : 1 : }
17130 : :
17131 : :
17132 : : // MK, Disabled 14.11.2014
17133 : : // Too unclear what exactly should be tested and which variations are allowed for the line
17134 : : #if 0
17135 : : void TestQgsGeometry::simplifyCheck1()
17136 : : {
17137 : : initPainterTest();
17138 : : QVERIFY( mpPolylineGeometryD->simplify( 0.5 ) );
17139 : : // should be a single polygon as A intersect B
17140 : : QgsGeometry *mypSimplifyGeometry = mpPolylineGeometryD->simplify( 0.5 );
17141 : : qDebug( "Geometry Type: %s", QgsWkbTypes::displayString( mypSimplifyGeometry->wkbType() ) );
17142 : : QVERIFY( mypSimplifyGeometry->wkbType() == QgsWkbTypes::LineString );
17143 : : QgsPolyline myLine = mypSimplifyGeometry->asPolyline();
17144 : : QVERIFY( myLine.size() > 0 ); //check that the union created a feature
17145 : : dumpPolyline( myLine );
17146 : : delete mypSimplifyGeometry;
17147 : : QVERIFY( renderCheck( "geometry_simplifyCheck1", "Checking simplify of line" ) );
17148 : : }
17149 : : #endif
17150 : :
17151 : 1 : void TestQgsGeometry::intersectionCheck1()
17152 : : {
17153 : 1 : initPainterTest();
17154 : 1 : QVERIFY( mpPolygonGeometryA.intersects( mpPolygonGeometryB ) );
17155 : :
17156 : 1 : std::unique_ptr< QgsGeometryEngine > engine( QgsGeometry::createGeometryEngine( mpPolygonGeometryA.constGet() ) );
17157 : 1 : QVERIFY( engine->intersects( mpPolygonGeometryB.constGet() ) );
17158 : 1 : engine->prepareGeometry();
17159 : 1 : QVERIFY( engine->intersects( mpPolygonGeometryB.constGet() ) );
17160 : :
17161 : : // should be a single polygon as A intersect B
17162 : 1 : QgsGeometry mypIntersectionGeometry = mpPolygonGeometryA.intersection( mpPolygonGeometryB );
17163 : 1 : QVERIFY( mypIntersectionGeometry.wkbType() == QgsWkbTypes::Polygon );
17164 : 1 : QgsPolygonXY myPolygon = mypIntersectionGeometry.asPolygon();
17165 : 1 : QVERIFY( myPolygon.size() > 0 ); //check that the union created a feature
17166 : 1 : paintPolygon( myPolygon );
17167 : 1 : QVERIFY( renderCheck( "geometry_intersectionCheck1", "Checking if A intersects B" ) );
17168 : 1 : }
17169 : 1 : void TestQgsGeometry::intersectionCheck2()
17170 : : {
17171 : 1 : QVERIFY( !mpPolygonGeometryA.intersects( mpPolygonGeometryC ) );
17172 : 1 : }
17173 : :
17174 : 1 : void TestQgsGeometry::translateCheck1()
17175 : : {
17176 : 2 : QString wkt = QStringLiteral( "LineString (0 0, 10 0, 10 10)" );
17177 : 1 : QgsGeometry geom( QgsGeometry::fromWkt( wkt ) );
17178 : 1 : geom.translate( 10, -5 );
17179 : 1 : QString obtained = geom.asWkt();
17180 : 2 : QString expected = QStringLiteral( "LineString (10 -5, 20 -5, 20 5)" );
17181 : 1 : QCOMPARE( obtained, expected );
17182 : 1 : geom.translate( -10, 5 );
17183 : 1 : obtained = geom.asWkt();
17184 : 1 : QCOMPARE( obtained, wkt );
17185 : :
17186 : 2 : wkt = QStringLiteral( "Polygon ((-2 4, -2 -10, 2 3, -2 4),(1 1, -1 1, -1 -1, 1 1))" );
17187 : 1 : geom = QgsGeometry::fromWkt( wkt );
17188 : 1 : geom.translate( -2, 10 );
17189 : 1 : obtained = geom.asWkt();
17190 : 2 : expected = QStringLiteral( "Polygon ((-4 14, -4 0, 0 13, -4 14),(-1 11, -3 11, -3 9, -1 11))" );
17191 : 1 : QCOMPARE( obtained, expected );
17192 : 1 : geom.translate( 2, -10 );
17193 : 1 : obtained = geom.asWkt();
17194 : 1 : QCOMPARE( obtained, wkt );
17195 : :
17196 : 2 : wkt = QStringLiteral( "Point (40 50)" );
17197 : 1 : geom = QgsGeometry::fromWkt( wkt );
17198 : 1 : geom.translate( -2, 10 );
17199 : 1 : obtained = geom.asWkt();
17200 : 2 : expected = QStringLiteral( "Point (38 60)" );
17201 : 1 : QCOMPARE( obtained, expected );
17202 : 1 : geom.translate( 2, -10 );
17203 : 1 : obtained = geom.asWkt();
17204 : 1 : QCOMPARE( obtained, wkt );
17205 : :
17206 : 1 : }
17207 : :
17208 : 1 : void TestQgsGeometry::rotateCheck1()
17209 : : {
17210 : 2 : QString wkt = QStringLiteral( "LineString (0 0, 10 0, 10 10)" );
17211 : 1 : QgsGeometry geom( QgsGeometry::fromWkt( wkt ) );
17212 : 1 : geom.rotate( 90, QgsPointXY( 0, 0 ) );
17213 : 1 : QString obtained = geom.asWkt();
17214 : 2 : QString expected = QStringLiteral( "LineString (0 0, 0 -10, 10 -10)" );
17215 : 1 : QCOMPARE( obtained, expected );
17216 : 1 : geom.rotate( -90, QgsPointXY( 0, 0 ) );
17217 : 1 : obtained = geom.asWkt();
17218 : 1 : QCOMPARE( obtained, wkt );
17219 : :
17220 : 2 : wkt = QStringLiteral( "Polygon ((-2 4, -2 -10, 2 3, -2 4),(1 1, -1 1, -1 -1, 1 1))" );
17221 : 1 : geom = QgsGeometry::fromWkt( wkt );
17222 : 1 : geom.rotate( 90, QgsPointXY( 0, 0 ) );
17223 : 1 : obtained = geom.asWkt();
17224 : 2 : expected = QStringLiteral( "Polygon ((4 2, -10 2, 3 -2, 4 2),(1 -1, 1 1, -1 1, 1 -1))" );
17225 : 1 : QCOMPARE( obtained, expected );
17226 : 1 : geom.rotate( -90, QgsPointXY( 0, 0 ) );
17227 : 1 : obtained = geom.asWkt();
17228 : 1 : QCOMPARE( obtained, wkt );
17229 : :
17230 : 2 : wkt = QStringLiteral( "Point (40 50)" );
17231 : 1 : geom = QgsGeometry::fromWkt( wkt );
17232 : 1 : geom.rotate( 90, QgsPointXY( 0, 0 ) );
17233 : 1 : obtained = geom.asWkt();
17234 : 2 : expected = QStringLiteral( "Point (50 -40)" );
17235 : 1 : QCOMPARE( obtained, expected );
17236 : 1 : geom.rotate( -90, QgsPointXY( 0, 0 ) );
17237 : 1 : obtained = geom.asWkt();
17238 : 1 : QCOMPARE( obtained, wkt );
17239 : 1 : geom.rotate( 180, QgsPointXY( 40, 0 ) );
17240 : 2 : expected = QStringLiteral( "Point (40 -50)" );
17241 : 1 : obtained = geom.asWkt();
17242 : 1 : QCOMPARE( obtained, expected );
17243 : 1 : geom.rotate( 180, QgsPointXY( 40, 0 ) ); // round-trip
17244 : 1 : obtained = geom.asWkt();
17245 : 1 : QCOMPARE( obtained, wkt );
17246 : :
17247 : 1 : }
17248 : :
17249 : 1 : void TestQgsGeometry::unionCheck1()
17250 : : {
17251 : 1 : initPainterTest();
17252 : : // should be a multipolygon with 2 parts as A does not intersect C
17253 : 1 : QgsGeometry mypUnionGeometry = mpPolygonGeometryA.combine( mpPolygonGeometryC );
17254 : 1 : QVERIFY( mypUnionGeometry.wkbType() == QgsWkbTypes::MultiPolygon );
17255 : 1 : QgsMultiPolygonXY myMultiPolygon = mypUnionGeometry.asMultiPolygon();
17256 : 1 : QVERIFY( myMultiPolygon.size() > 0 ); //check that the union did not fail
17257 : 1 : paintMultiPolygon( myMultiPolygon );
17258 : 1 : QVERIFY( renderCheck( "geometry_unionCheck1", "Checking A union C produces 2 polys" ) );
17259 : 1 : }
17260 : :
17261 : 1 : void TestQgsGeometry::unionCheck2()
17262 : : {
17263 : 1 : initPainterTest();
17264 : : // should be a single polygon as A intersect B
17265 : 1 : QgsGeometry mypUnionGeometry = mpPolygonGeometryA.combine( mpPolygonGeometryB );
17266 : 1 : QVERIFY( mypUnionGeometry.wkbType() == QgsWkbTypes::Polygon );
17267 : 1 : QgsPolygonXY myPolygon = mypUnionGeometry.asPolygon();
17268 : 1 : QVERIFY( myPolygon.size() > 0 ); //check that the union created a feature
17269 : 1 : paintPolygon( myPolygon );
17270 : 1 : QVERIFY( renderCheck( "geometry_unionCheck2", "Checking A union B produces single union poly" ) );
17271 : 1 : }
17272 : :
17273 : 1 : void TestQgsGeometry::differenceCheck1()
17274 : : {
17275 : 1 : initPainterTest();
17276 : : // should be same as A since A does not intersect C so diff is 100% of A
17277 : 1 : QgsGeometry mypDifferenceGeometry( mpPolygonGeometryA.difference( mpPolygonGeometryC ) );
17278 : 1 : QVERIFY( mypDifferenceGeometry.wkbType() == QgsWkbTypes::Polygon );
17279 : 1 : QgsPolygonXY myPolygon = mypDifferenceGeometry.asPolygon();
17280 : 1 : QVERIFY( myPolygon.size() > 0 ); //check that the union did not fail
17281 : 1 : paintPolygon( myPolygon );
17282 : 1 : QVERIFY( renderCheck( "geometry_differenceCheck1", "Checking (A - C) = A" ) );
17283 : 1 : }
17284 : :
17285 : 1 : void TestQgsGeometry::differenceCheck2()
17286 : : {
17287 : 1 : initPainterTest();
17288 : : // should be a single polygon as (A - B) = subset of A
17289 : 1 : QgsGeometry mypDifferenceGeometry( mpPolygonGeometryA.difference( mpPolygonGeometryB ) );
17290 : 1 : QVERIFY( mypDifferenceGeometry.wkbType() == QgsWkbTypes::Polygon );
17291 : 1 : QgsPolygonXY myPolygon = mypDifferenceGeometry.asPolygon();
17292 : 1 : QVERIFY( myPolygon.size() > 0 ); //check that the union created a feature
17293 : 1 : paintPolygon( myPolygon );
17294 : 1 : QVERIFY( renderCheck( "geometry_differenceCheck2", "Checking (A - B) = subset of A" ) );
17295 : 1 : }
17296 : 1 : void TestQgsGeometry::bufferCheck()
17297 : : {
17298 : 1 : initPainterTest();
17299 : : // should be a single polygon
17300 : 1 : QgsGeometry mypBufferGeometry( mpPolygonGeometryB.buffer( 10, 10 ) );
17301 : 1 : QVERIFY( mypBufferGeometry.wkbType() == QgsWkbTypes::Polygon );
17302 : 1 : QgsPolygonXY myPolygon = mypBufferGeometry.asPolygon();
17303 : 1 : QVERIFY( myPolygon.size() > 0 ); //check that the buffer created a feature
17304 : 1 : paintPolygon( myPolygon );
17305 : 1 : QVERIFY( renderCheck( "geometry_bufferCheck", "Checking buffer(10,10) of B", 10 ) );
17306 : 1 : }
17307 : :
17308 : 1 : void TestQgsGeometry::smoothCheck()
17309 : : {
17310 : : //can't smooth a point
17311 : 2 : QString wkt = QStringLiteral( "Point (40 50)" );
17312 : 1 : QgsGeometry geom( QgsGeometry::fromWkt( wkt ) );
17313 : 1 : QgsGeometry result = geom.smooth( 1, 0.25 );
17314 : 1 : QString obtained = result.asWkt();
17315 : 1 : QCOMPARE( obtained, wkt );
17316 : :
17317 : : //linestring
17318 : 2 : wkt = QStringLiteral( "LineString(0 0, 10 0, 10 10, 20 10)" );
17319 : 1 : geom = QgsGeometry::fromWkt( wkt );
17320 : 1 : result = geom.smooth( 1, 0.25 );
17321 : 1 : QgsPolylineXY line = result.asPolyline();
17322 : 1 : QgsPolylineXY expectedLine;
17323 : 1 : expectedLine << QgsPointXY( 0, 0 ) << QgsPointXY( 7.5, 0 ) << QgsPointXY( 10.0, 2.5 )
17324 : 1 : << QgsPointXY( 10.0, 7.5 ) << QgsPointXY( 12.5, 10.0 ) << QgsPointXY( 20.0, 10.0 );
17325 : 1 : QVERIFY( QgsGeometry::compare( line, expectedLine ) );
17326 : :
17327 : : //linestringM
17328 : 2 : wkt = QStringLiteral( "LineStringM(0 0 1, 10 0 2, 10 10 6, 20 10 4)" );
17329 : 1 : geom = QgsGeometry::fromWkt( wkt );
17330 : 1 : result = geom.smooth( 1, 0.25 );
17331 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineStringM (0 0 1, 7.5 0 1.75, 10 2.5 3, 10 7.5 5, 12.5 10 5.5, 20 10 4)" ) );
17332 : :
17333 : : //linestringZ
17334 : 2 : wkt = QStringLiteral( "LineStringZ(0 0 1, 10 0 2, 10 10 6, 20 10 4)" );
17335 : 1 : geom = QgsGeometry::fromWkt( wkt );
17336 : 1 : result = geom.smooth( 1, 0.25 );
17337 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineStringZ (0 0 1, 7.5 0 1.75, 10 2.5 3, 10 7.5 5, 12.5 10 5.5, 20 10 4)" ) );
17338 : :
17339 : : //linestringZM
17340 : 2 : wkt = QStringLiteral( "LineStringZM(0 0 1 4, 10 0 2 8, 10 10 6 2, 20 10 4 0)" );
17341 : 1 : geom = QgsGeometry::fromWkt( wkt );
17342 : 1 : result = geom.smooth( 1, 0.25 );
17343 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "LineStringZM (0 0 1 4, 7.5 0 1.75 7, 10 2.5 3 6.5, 10 7.5 5 3.5, 12.5 10 5.5 1.5, 20 10 4 0)" ) );
17344 : :
17345 : : //linestring, with min distance
17346 : 2 : wkt = QStringLiteral( "LineString(0 0, 10 0, 10 10, 15 10, 15 20)" );
17347 : 1 : geom = QgsGeometry::fromWkt( wkt );
17348 : 1 : result = geom.smooth( 1, 0.25, 6 );
17349 : 1 : line = result.asPolyline();
17350 : 1 : expectedLine.clear();
17351 : 1 : expectedLine << QgsPointXY( 0, 0 ) << QgsPointXY( 7.5, 0 ) << QgsPointXY( 10.0, 2.5 )
17352 : 1 : << QgsPointXY( 10.0, 7.5 ) << QgsPointXY( 15, 12.5 ) << QgsPointXY( 15.0, 20.0 );
17353 : 1 : QVERIFY( QgsGeometry::compare( line, expectedLine ) );
17354 : :
17355 : : //linestring, with max angle
17356 : 2 : wkt = QStringLiteral( "LineString(0 0, 10 0, 15 5, 25 -5, 30 -5 )" );
17357 : 1 : geom = QgsGeometry::fromWkt( wkt );
17358 : 1 : result = geom.smooth( 1, 0.25, 0, 50 );
17359 : 1 : line = result.asPolyline();
17360 : 1 : expectedLine.clear();
17361 : 1 : expectedLine << QgsPointXY( 0, 0 ) << QgsPointXY( 7.5, 0 ) << QgsPointXY( 11.25, 1.25 )
17362 : 1 : << QgsPointXY( 15.0, 5.0 ) << QgsPointXY( 22.5, -2.5 ) << QgsPointXY( 26.25, -5 ) << QgsPointXY( 30, -5 );
17363 : 1 : QVERIFY( QgsGeometry::compare( line, expectedLine ) );
17364 : :
17365 : : //linestring, with max angle, other direction
17366 : 2 : wkt = QStringLiteral( "LineString( 30 -5, 25 -5, 15 5, 10 0, 0 0 )" );
17367 : 1 : geom = QgsGeometry::fromWkt( wkt );
17368 : 1 : result = geom.smooth( 1, 0.25, 0, 50 );
17369 : 1 : line = result.asPolyline();
17370 : 1 : expectedLine.clear();
17371 : 1 : expectedLine << QgsPointXY( 30, -5 ) << QgsPointXY( 26.25, -5 ) << QgsPointXY( 22.5, -2.5 )
17372 : 1 : << QgsPointXY( 15.0, 5.0 ) << QgsPointXY( 11.25, 1.25 ) << QgsPointXY( 7.5, 0 ) << QgsPointXY( 0, 0 );
17373 : 1 : QVERIFY( QgsGeometry::compare( line, expectedLine ) );
17374 : :
17375 : : //linestring, max angle, first corner sharp
17376 : 2 : wkt = QStringLiteral( "LineString(0 0, 10 0, 10 10 )" );
17377 : 1 : geom = QgsGeometry::fromWkt( wkt );
17378 : 1 : result = geom.smooth( 1, 0.25, 0, 50 );
17379 : 1 : line = result.asPolyline();
17380 : 1 : expectedLine.clear();
17381 : 1 : expectedLine << QgsPointXY( 0, 0 ) << QgsPointXY( 10, 0 ) << QgsPointXY( 10, 10 );
17382 : 1 : QVERIFY( QgsGeometry::compare( line, expectedLine ) );
17383 : :
17384 : 2 : wkt = QStringLiteral( "MultiLineString ((0 0, 10 0, 10 10, 20 10),(30 30, 40 30, 40 40, 50 40))" );
17385 : 1 : geom = QgsGeometry::fromWkt( wkt );
17386 : 1 : result = geom.smooth( 1, 0.25 );
17387 : 1 : QgsMultiPolylineXY multiLine = result.asMultiPolyline();
17388 : 1 : QgsMultiPolylineXY expectedMultiline;
17389 : 3 : expectedMultiline << ( QgsPolylineXY() << QgsPointXY( 0, 0 ) << QgsPointXY( 7.5, 0 ) << QgsPointXY( 10.0, 2.5 )
17390 : 1 : << QgsPointXY( 10.0, 7.5 ) << QgsPointXY( 12.5, 10.0 ) << QgsPointXY( 20.0, 10.0 ) )
17391 : 2 : << ( QgsPolylineXY() << QgsPointXY( 30.0, 30.0 ) << QgsPointXY( 37.5, 30.0 ) << QgsPointXY( 40.0, 32.5 )
17392 : 1 : << QgsPointXY( 40.0, 37.5 ) << QgsPointXY( 42.5, 40.0 ) << QgsPointXY( 50.0, 40.0 ) );
17393 : 1 : QVERIFY( QgsGeometry::compare( multiLine, expectedMultiline ) );
17394 : :
17395 : : //polygon
17396 : 2 : wkt = QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0 ),(2 2, 4 2, 4 4, 2 4, 2 2))" );
17397 : 1 : geom = QgsGeometry::fromWkt( wkt );
17398 : 1 : result = geom.smooth( 1, 0.25 );
17399 : 1 : QgsPolygonXY poly = result.asPolygon();
17400 : 1 : QgsPolygonXY expectedPolygon;
17401 : 3 : expectedPolygon << ( QgsPolylineXY() << QgsPointXY( 2.5, 0 ) << QgsPointXY( 7.5, 0 ) << QgsPointXY( 10.0, 2.5 )
17402 : 1 : << QgsPointXY( 10.0, 7.5 ) << QgsPointXY( 7.5, 10.0 ) << QgsPointXY( 2.5, 10.0 ) << QgsPointXY( 0, 7.5 )
17403 : 1 : << QgsPointXY( 0, 2.5 ) << QgsPointXY( 2.5, 0 ) )
17404 : 2 : << ( QgsPolylineXY() << QgsPointXY( 2.5, 2.0 ) << QgsPointXY( 3.5, 2.0 ) << QgsPointXY( 4.0, 2.5 )
17405 : 1 : << QgsPointXY( 4.0, 3.5 ) << QgsPointXY( 3.5, 4.0 ) << QgsPointXY( 2.5, 4.0 )
17406 : 1 : << QgsPointXY( 2.0, 3.5 ) << QgsPointXY( 2.0, 2.5 ) << QgsPointXY( 2.5, 2.0 ) );
17407 : 1 : QVERIFY( QgsGeometry::compare( poly, expectedPolygon ) );
17408 : :
17409 : : //polygonM
17410 : 2 : wkt = QStringLiteral( "PolygonM ((0 0 1, 10 0 4, 10 10 6, 0 10 8, 0 0 1 ),(2 2 3, 4 2 5, 4 4 7, 2 4 9, 2 2 3))" );
17411 : 1 : geom = QgsGeometry::fromWkt( wkt );
17412 : 1 : result = geom.smooth( 1, 0.25 );
17413 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "PolygonM ((2.5 0 1.75, 7.5 0 3.25, 10 2.5 4.5, 10 7.5 5.5, 7.5 10 6.5, 2.5 10 7.5, 0 7.5 6.25, 0 2.5 2.75, 2.5 0 1.75),(2.5 2 3.5, 3.5 2 4.5, 4 2.5 5.5, 4 3.5 6.5, 3.5 4 7.5, 2.5 4 8.5, 2 3.5 7.5, 2 2.5 4.5, 2.5 2 3.5))" ) );
17414 : :
17415 : : //polygonZ
17416 : 2 : wkt = QStringLiteral( "PolygonZ ((0 0 1, 10 0 4, 10 10 6, 0 10 8, 0 0 1 ),(2 2 3, 4 2 5, 4 4 7, 2 4 9, 2 2 3))" );
17417 : 1 : geom = QgsGeometry::fromWkt( wkt );
17418 : 1 : result = geom.smooth( 1, 0.25 );
17419 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "PolygonZ ((2.5 0 1.75, 7.5 0 3.25, 10 2.5 4.5, 10 7.5 5.5, 7.5 10 6.5, 2.5 10 7.5, 0 7.5 6.25, 0 2.5 2.75, 2.5 0 1.75),(2.5 2 3.5, 3.5 2 4.5, 4 2.5 5.5, 4 3.5 6.5, 3.5 4 7.5, 2.5 4 8.5, 2 3.5 7.5, 2 2.5 4.5, 2.5 2 3.5))" ) );
17420 : :
17421 : : //polygonZM
17422 : 2 : wkt = QStringLiteral( "PolygonZ ((0 0 1 6, 10 0 4 2, 10 10 6 0, 0 10 8 4, 0 0 1 6 ))" );
17423 : 1 : geom = QgsGeometry::fromWkt( wkt );
17424 : 1 : result = geom.smooth( 1, 0.25 );
17425 : 2 : QCOMPARE( result.asWkt(), QStringLiteral( "PolygonZM ((2.5 0 1.75 5, 7.5 0 3.25 3, 10 2.5 4.5 1.5, 10 7.5 5.5 0.5, 7.5 10 6.5 1, 2.5 10 7.5 3, 0 7.5 6.25 4.5, 0 2.5 2.75 5.5, 2.5 0 1.75 5))" ) );
17426 : :
17427 : : //polygon with max angle - should be unchanged
17428 : 2 : wkt = QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0))" );
17429 : 1 : geom = QgsGeometry::fromWkt( wkt );
17430 : 1 : result = geom.smooth( 1, 0.25, -1, 50 );
17431 : 1 : poly = result.asPolygon();
17432 : 1 : expectedPolygon.clear();
17433 : 2 : expectedPolygon << ( QgsPolylineXY() << QgsPointXY( 0, 0 ) << QgsPointXY( 10, 0 ) << QgsPointXY( 10.0, 10 )
17434 : 1 : << QgsPointXY( 0, 10 ) << QgsPointXY( 0, 0 ) );
17435 : 1 : QVERIFY( QgsGeometry::compare( poly, expectedPolygon ) );
17436 : :
17437 : : //multipolygon)
17438 : 2 : wkt = QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0 )),((2 2, 4 2, 4 4, 2 4, 2 2)))" );
17439 : 1 : geom = QgsGeometry::fromWkt( wkt );
17440 : 1 : result = geom.smooth( 1, 0.1 );
17441 : 1 : QgsMultiPolygonXY multipoly = result.asMultiPolygon();
17442 : 1 : QgsMultiPolygonXY expectedMultiPoly;
17443 : 1 : expectedMultiPoly
17444 : 2 : << ( QgsPolygonXY() << ( QgsPolylineXY() << QgsPointXY( 1.0, 0 ) << QgsPointXY( 9, 0 ) << QgsPointXY( 10.0, 1 )
17445 : 1 : << QgsPointXY( 10.0, 9 ) << QgsPointXY( 9, 10.0 ) << QgsPointXY( 1, 10.0 ) << QgsPointXY( 0, 9 )
17446 : 1 : << QgsPointXY( 0, 1 ) << QgsPointXY( 1, 0 ) ) )
17447 : 2 : << ( QgsPolygonXY() << ( QgsPolylineXY() << QgsPointXY( 2.2, 2.0 ) << QgsPointXY( 3.8, 2.0 ) << QgsPointXY( 4.0, 2.2 )
17448 : 1 : << QgsPointXY( 4.0, 3.8 ) << QgsPointXY( 3.8, 4.0 ) << QgsPointXY( 2.2, 4.0 ) << QgsPointXY( 2.0, 3.8 )
17449 : 1 : << QgsPointXY( 2, 2.2 ) << QgsPointXY( 2.2, 2 ) ) );
17450 : 1 : QVERIFY( QgsGeometry::compare( multipoly, expectedMultiPoly ) );
17451 : :
17452 : : // curved geometry
17453 : 2 : wkt = QStringLiteral( "CurvePolygon (CompoundCurve (CircularString (-70.75639028391421448 42.11076979194393743, -70.75300889449444242 42.10738840252416537, -70.75639028391421448 42.10400701310439331, -70.75977167333398654 42.10738840252416537, -70.75639028391421448 42.11076979194393743))) 1" );
17454 : 1 : geom = QgsGeometry::fromWkt( wkt );
17455 : 1 : result = geom.smooth( 3 );
17456 : 1 : QCOMPARE( result.wkbType(), QgsWkbTypes::Polygon );
17457 : 1 : }
17458 : :
17459 : 1 : void TestQgsGeometry::shortestLineEmptyGeometry()
17460 : : {
17461 : : // test calculating distance to an empty geometry
17462 : : // refs https://github.com/qgis/QGIS/issues/41968
17463 : 2 : QgsGeometry geom1( QgsGeometry::fromWkt( QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0 ))" ) ) );
17464 : 1 : QgsGeometry geom2( new QgsPoint() );
17465 : 1 : QgsGeos geos( geom1.constGet() );
17466 : 1 : QVERIFY( geos.shortestLine( geom2.constGet() ).isNull() );
17467 : 1 : }
17468 : :
17469 : 1 : void TestQgsGeometry::unaryUnion()
17470 : : {
17471 : : //test QgsGeometry::unaryUnion with null geometry
17472 : 2 : QString wkt1 = QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0 ))" );
17473 : 2 : QString wkt2 = QStringLiteral( "Polygon ((2 2, 4 2, 4 4, 2 4, 2 2))" );
17474 : 1 : QgsGeometry geom1( QgsGeometry::fromWkt( wkt1 ) );
17475 : 1 : QgsGeometry geom2( QgsGeometry::fromWkt( wkt2 ) );
17476 : 1 : QgsGeometry empty;
17477 : 1 : QVector< QgsGeometry > list;
17478 : 1 : list << geom1 << empty << geom2;
17479 : :
17480 : 1 : QgsGeometry result( QgsGeometry::unaryUnion( list ) );
17481 : : Q_UNUSED( result );
17482 : 1 : }
17483 : :
17484 : 1 : void TestQgsGeometry::dataStream()
17485 : : {
17486 : 2 : QString wkt = QStringLiteral( "Point (40 50)" );
17487 : 1 : QgsGeometry geom( QgsGeometry::fromWkt( wkt ) );
17488 : :
17489 : 1 : QByteArray ba;
17490 : 1 : QDataStream ds( &ba, QIODevice::ReadWrite );
17491 : 1 : ds << geom;
17492 : :
17493 : 1 : QgsGeometry resultGeometry;
17494 : 1 : ds.device()->seek( 0 );
17495 : 1 : ds >> resultGeometry;
17496 : :
17497 : 1 : QCOMPARE( geom.constGet()->asWkt(), resultGeometry.constGet()->asWkt() );
17498 : :
17499 : : //also test with geometry without data
17500 : 1 : std::unique_ptr<QgsGeometry> emptyGeom( new QgsGeometry() );
17501 : :
17502 : 1 : QByteArray ba2;
17503 : 1 : QDataStream ds2( &ba2, QIODevice::ReadWrite );
17504 : 1 : ds2 << emptyGeom.get();
17505 : :
17506 : 1 : ds2.device()->seek( 0 );
17507 : 1 : ds2 >> resultGeometry;
17508 : :
17509 : 1 : QVERIFY( resultGeometry.isNull() );
17510 : 1 : }
17511 : :
17512 : 1 : void TestQgsGeometry::exportToGeoJSON()
17513 : : {
17514 : : //Point
17515 : 2 : QString wkt = QStringLiteral( "Point (40 50)" );
17516 : 1 : QgsGeometry geom( QgsGeometry::fromWkt( wkt ) );
17517 : 1 : QString obtained = geom.asJson();
17518 : 2 : QString geojson = QStringLiteral( "{\"coordinates\":[40.0,50.0],\"type\":\"Point\"}" );
17519 : 1 : QCOMPARE( obtained, geojson );
17520 : :
17521 : : //MultiPoint
17522 : 2 : wkt = QStringLiteral( "MultiPoint (0 0, 10 0, 10 10, 20 10)" );
17523 : 1 : geom = QgsGeometry::fromWkt( wkt );
17524 : 1 : obtained = geom.asJson();
17525 : 2 : geojson = QStringLiteral( "{\"coordinates\":[[0.0,0.0],[10.0,0.0],[10.0,10.0],[20.0,10.0]],\"type\":\"MultiPoint\"}" );
17526 : 1 : QCOMPARE( obtained, geojson );
17527 : :
17528 : : //Linestring
17529 : 2 : wkt = QStringLiteral( "LineString(0 0, 10 0, 10 10, 20 10)" );
17530 : 1 : geom = QgsGeometry::fromWkt( wkt );
17531 : 1 : obtained = geom.asJson();
17532 : 2 : geojson = QStringLiteral( "{\"coordinates\":[[0.0,0.0],[10.0,0.0],[10.0,10.0],[20.0,10.0]],\"type\":\"LineString\"}" );
17533 : 1 : QCOMPARE( obtained, geojson );
17534 : :
17535 : : //MultiLineString
17536 : 2 : wkt = QStringLiteral( "MultiLineString ((0 0, 10 0, 10 10, 20 10),(30 30, 40 30, 40 40, 50 40))" );
17537 : 1 : geom = QgsGeometry::fromWkt( wkt );
17538 : 1 : obtained = geom.asJson();
17539 : 2 : geojson = QStringLiteral( "{\"coordinates\":[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[20.0,10.0]],[[30.0,30.0],[40.0,30.0],[40.0,40.0],[50.0,40.0]]],\"type\":\"MultiLineString\"}" );
17540 : 1 : QCOMPARE( obtained, geojson );
17541 : :
17542 : : //Polygon
17543 : 2 : wkt = QStringLiteral( "Polygon ((0 0, 10 0, 10 10, 0 10, 0 0 ),(2 2, 4 2, 4 4, 2 4, 2 2))" );
17544 : 1 : geom = QgsGeometry::fromWkt( wkt );
17545 : 1 : obtained = geom.asJson();
17546 : 2 : geojson = QStringLiteral( "{\"coordinates\":[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]],[[2.0,2.0],[4.0,2.0],[4.0,4.0],[2.0,4.0],[2.0,2.0]]],\"type\":\"Polygon\"}" );
17547 : 1 : QCOMPARE( obtained, geojson );
17548 : :
17549 : : //MultiPolygon
17550 : 2 : wkt = QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0 )),((2 2, 4 2, 4 4, 2 4, 2 2)))" );
17551 : 1 : geom = QgsGeometry::fromWkt( wkt );
17552 : 1 : obtained = geom.asJson();
17553 : 2 : geojson = QStringLiteral( "{\"coordinates\":[[[[0.0,0.0],[10.0,0.0],[10.0,10.0],[0.0,10.0],[0.0,0.0]]],[[[2.0,2.0],[4.0,2.0],[4.0,4.0],[2.0,4.0],[2.0,2.0]]]],\"type\":\"MultiPolygon\"}" );
17554 : 1 : QCOMPARE( obtained, geojson );
17555 : :
17556 : : // no geometry
17557 : 1 : QgsGeometry nullGeom( nullptr );
17558 : 1 : obtained = nullGeom.asJson();
17559 : 2 : geojson = QStringLiteral( "null" );
17560 : 1 : QCOMPARE( obtained, geojson );
17561 : 1 : }
17562 : :
17563 : 6 : bool TestQgsGeometry::renderCheck( const QString &testName, const QString &comment, int mismatchCount )
17564 : : {
17565 : 6 : mReport += "<h2>" + testName + "</h2>\n";
17566 : 6 : mReport += "<h3>" + comment + "</h3>\n";
17567 : 6 : QString myTmpDir = QDir::tempPath() + '/';
17568 : 6 : QString myFileName = myTmpDir + testName + ".png";
17569 : 6 : mImage.save( myFileName, "PNG" );
17570 : 6 : QgsRenderChecker myChecker;
17571 : 6 : myChecker.setControlName( "expected_" + testName );
17572 : 6 : myChecker.setRenderedImage( myFileName );
17573 : 6 : bool myResultFlag = myChecker.compareImages( testName, mismatchCount );
17574 : 6 : mReport += myChecker.report();
17575 : 6 : return myResultFlag;
17576 : 6 : }
17577 : :
17578 : 0 : void TestQgsGeometry::dumpMultiPolygon( QgsMultiPolygonXY &multiPolygon )
17579 : : {
17580 : 0 : qDebug( "Multipolygon Geometry Dump" );
17581 : 0 : for ( int i = 0; i < multiPolygon.size(); i++ )
17582 : : {
17583 : 0 : QgsPolygonXY myPolygon = multiPolygon.at( i );
17584 : 0 : qDebug( "\tPolygon in multipolygon: %d", i );
17585 : 0 : dumpPolygon( myPolygon );
17586 : 0 : }
17587 : 0 : }
17588 : :
17589 : 1 : void TestQgsGeometry::paintMultiPolygon( QgsMultiPolygonXY &multiPolygon )
17590 : : {
17591 : 3 : for ( int i = 0; i < multiPolygon.size(); i++ )
17592 : : {
17593 : 2 : QgsPolygonXY myPolygon = multiPolygon.at( i );
17594 : 2 : paintPolygon( myPolygon );
17595 : 2 : }
17596 : 1 : }
17597 : :
17598 : 0 : void TestQgsGeometry::dumpPolygon( QgsPolygonXY &polygon )
17599 : : {
17600 : 0 : for ( int j = 0; j < polygon.size(); j++ )
17601 : : {
17602 : 0 : QgsPolylineXY myPolyline = polygon.at( j ); //rings of polygon
17603 : 0 : qDebug( "\t\tRing in polygon: %d", j );
17604 : :
17605 : 0 : for ( int k = 0; k < myPolyline.size(); k++ )
17606 : : {
17607 : 0 : QgsPointXY myPoint = myPolyline.at( k );
17608 : 0 : qDebug( "\t\t\tPoint in ring %d : %s", k, myPoint.toString().toLocal8Bit().constData() );
17609 : 0 : }
17610 : 0 : }
17611 : 0 : }
17612 : :
17613 : 25 : void TestQgsGeometry::paintPolygon( QgsPolygonXY &polygon )
17614 : : {
17615 : 25 : QVector<QPointF> myPoints;
17616 : 50 : for ( int j = 0; j < polygon.size(); j++ )
17617 : : {
17618 : 25 : QgsPolylineXY myPolyline = polygon.at( j ); //rings of polygon
17619 : 196 : for ( int k = 0; k < myPolyline.size(); k++ )
17620 : : {
17621 : 171 : QgsPointXY myPoint = myPolyline.at( k );
17622 : 171 : myPoints << QPointF( myPoint.x(), myPoint.y() );
17623 : 171 : }
17624 : 25 : }
17625 : 25 : mpPainter->drawPolygon( myPoints );
17626 : 25 : }
17627 : :
17628 : 0 : void TestQgsGeometry::dumpPolyline( QgsPolylineXY &polyline )
17629 : : {
17630 : 0 : QVector<QPointF> myPoints;
17631 : : // QgsPolyline myPolyline = polyline.at( j ); //rings of polygon
17632 : 0 : for ( int j = 0; j < polyline.size(); j++ )
17633 : : {
17634 : 0 : QgsPointXY myPoint = polyline.at( j );
17635 : : // QgsPolyline myPolyline = polygon.at( j ); //rings of polygon
17636 : 0 : myPoints << QPointF( myPoint.x(), myPoint.y() );
17637 : 0 : qDebug( "\t\tPoint in line: %d", j );
17638 : :
17639 : : // for ( int k = 0; k < myPolyline.size(); k++ )
17640 : : // {
17641 : : // QgsPointXY myPoint = myPolyline.at( k );
17642 : : // qDebug( "\t\t\tPoint in ring %d : %s", k, myPoint.toString().toLocal8Bit().constData() );
17643 : : // myPoints << QPointF( myPoint.x(), myPoint.y() );
17644 : : // }
17645 : 0 : }
17646 : 0 : mpPainter->drawPolyline( myPoints );
17647 : 0 : }
17648 : :
17649 : 92 : QString TestQgsGeometry::elemToString( const QDomElement &elem ) const
17650 : : {
17651 : 92 : QString s;
17652 : 92 : QTextStream stream( &s );
17653 : 92 : elem.save( stream, -1 );
17654 : :
17655 : 92 : return s;
17656 : 92 : }
17657 : :
17658 : 1 : void TestQgsGeometry::wkbInOut()
17659 : : {
17660 : : // Premature end of WKB
17661 : : // See https://github.com/qgis/QGIS/issues/22184
17662 : 1 : const char *hexwkb = "0102000000EF0000000000000000000000000000000000000000000000000000000000000000000000";
17663 : : int size;
17664 : 1 : unsigned char *wkb = hex2bytes( hexwkb, &size );
17665 : 1 : QgsGeometry g14182;
17666 : : // NOTE: wkb onwership transferred to QgsGeometry
17667 : 1 : g14182.fromWkb( wkb, size );
17668 : : //QList<QgsGeometry::Error> errors;
17669 : : //g14182.validateGeometry(errors);
17670 : : // Check with valgrind !
17671 : 1 : QString wkt = g14182.asWkt();
17672 : 1 : QCOMPARE( wkt, QString() );
17673 : :
17674 : : //WKB with a truncated header
17675 : 1 : const char *badHeaderHexwkb = "0102";
17676 : 1 : wkb = hex2bytes( badHeaderHexwkb, &size );
17677 : 1 : QgsGeometry badHeader;
17678 : : // NOTE: wkb onwership transferred to QgsGeometry
17679 : 1 : badHeader.fromWkb( wkb, size );
17680 : 1 : QVERIFY( badHeader.isNull() );
17681 : 1 : QCOMPARE( badHeader.wkbType(), QgsWkbTypes::Unknown );
17682 : 1 : }
17683 : :
17684 : 1 : void TestQgsGeometry::directionNeutralSegmentation()
17685 : : {
17686 : : //Tests, if segmentation of a circularstring is the same in both directions
17687 : 2 : QString CWCircularStringWkt( QStringLiteral( "CIRCULARSTRING( 0 0, 0.5 0.5, 0.83 7.33 )" ) );
17688 : 1 : QgsCircularString *CWCircularString = static_cast<QgsCircularString *>( QgsGeometryFactory::geomFromWkt( CWCircularStringWkt ).release() );
17689 : 1 : QgsLineString *CWLineString = CWCircularString->curveToLine();
17690 : :
17691 : 2 : QString CCWCircularStringWkt( QStringLiteral( "CIRCULARSTRING( 0.83 7.33, 0.5 0.5, 0 0 )" ) );
17692 : 1 : QgsCircularString *CCWCircularString = static_cast<QgsCircularString *>( QgsGeometryFactory::geomFromWkt( CCWCircularStringWkt ).release() );
17693 : 1 : QgsLineString *CCWLineString = CCWCircularString->curveToLine();
17694 : 1 : QgsLineString *reversedCCWLineString = CCWLineString->reversed();
17695 : :
17696 : 1 : QCOMPARE( CWLineString->asWkt(), reversedCCWLineString->asWkt() );
17697 : 1 : bool equal = ( *CWLineString == *reversedCCWLineString );
17698 : :
17699 : 1 : delete CWCircularString;
17700 : 1 : delete CCWCircularString;
17701 : 1 : delete CWLineString;
17702 : 1 : delete CCWLineString;
17703 : 1 : delete reversedCCWLineString;
17704 : :
17705 : 1 : QVERIFY( equal );
17706 : 1 : }
17707 : :
17708 : 1 : void TestQgsGeometry::poleOfInaccessibility()
17709 : : {
17710 : 1 : QString poly1Wkt( "Polygon ((3116 3071, 3394 3431, 3563 3362, 3611 3205, 3599 3181, 3477 3281, 3449 3160, 3570 3127, 3354 3116,"
17711 : : " 3436 3008, 3158 2907, 2831 2438, 3269 2916, 3438 2885, 3295 2799, 3407 2772, 3278 2629, 3411 2689, 3329 2611,"
17712 : : " 3360 2531, 3603 2800, 3598 2501, 3317 2429, 3329 2401, 3170 2340, 3142 2291, 3524 2403, 3598 2233, 3460 2117,"
17713 : : " 3590 1931, 3364 1753, 3597 1875, 3639 1835, 3660 1733, 3600 1771, 3538 1694, 3661 1732, 3359 1554, 3334 1554,"
17714 : : " 3341 1588, 3317 1588, 3305 1644, 3286 1656, 3115 1255, 3072 1252, 3078 1335, 3046 1355, 2984 1234, 2983 1409,"
17715 : : " 2876 1222, 2525 1161, 2488 787, 2162 913, 2079 661, 2270 380, 2188 823, 2510 592, 2659 992, 2911 1118, 2943 938,"
17716 : : " 2957 1097, 3092 1002, 3006 1097, 3233 1282, 3325 1291, 3296 1116, 3333 1115, 3391 1333, 3434 1274, 3413 1326,"
17717 : : " 3449 1327, 3473 1408, 3490 1430, 3526 1434, 3198 -112, 3263 -87, 3289 -128, 4224 -128, 4224 -128, 3474 -128,"
17718 : : " 3475 -116, 3486 -120, 3458 -49, 3523 -78, 3513 -128, 3509 -119, 3509 -128, 3717 -128, 3705 -60, 3735 -16,"
17719 : : " 3714 38, 3758 88, 3825 47, 3812 -11, 3859 -51, 3871 49, 3760 149, 3636 -74, 3510 126, 3501 245, 3504 270,"
17720 : : " 3511 284, 3582 16, 3631 19, 3569 125, 3570 193, 3610 212, 3583 119, 3655 29, 3738 170, 3561 466, 3826 549,"
17721 : : " 3527 604, 3609 833, 3681 798, 3956 1127, 3917 964, 4043 850, 4049 1096, 4193 1052, 4191 1078, 4208 1106,"
17722 : : " 4222 1110, 4224 1109, 4224 1144, 4202 1158, 4177 1161, 4182 1181, 4075 1201, 4141 1275, 4215 1215, 4221 1223,"
17723 : : " 4219 1231, 4224 1243, 4224 1257, 4224 1262, 4224 1345, 4224 1339, 4224 1328, 4215 1335, 4203 1355, 4215 1369,"
17724 : : " 4224 1363, 4215 1377, 4208 1387, 4217 1401, 4224 1403, 4224 1520, 4219 1535, 4221 1544, 4199 1593, 4223 1595,"
17725 : : " 4206 1626, 4214 1648, 4224 1645, 4224 1640, 4224 2108, 4220 2125, 4224 2125, 4224 2143, 4205 2141, 4180 2159,"
17726 : : " 4201 2182, 4163 2189, 4176 2229, 4199 2211, 4210 2218, 4212 2210, 4223 2214, 4224 2207, 4224 2216, 4217 2225,"
17727 : : " 4221 2233, 4203 2227, 4209 2248, 4185 2240, 4198 2276, 4144 2218, 4091 2343, 4119 2332, 4121 2347, 4155 2337,"
17728 : : " 4180 2355, 4200 2342, 4201 2354, 4213 2352, 4224 2348, 4224 2356, 4207 2361, 4184 2358, 4176 2367, 4106 2355,"
17729 : : " 3983 2765, 4050 3151, 4139 2720, 4209 2589, 4211 2600, 4219 2599, 4224 2592, 4224 2574, 4223 2566, 4224 2562,"
17730 : : " 4224 2553, 4224 2552, 4224 -128, 4224 4224, 4205 4224, 4015 3513, 3993 3494, 3873 3533, 3887 3539, 3923 3524,"
17731 : : " 3950 3529, 4018 3572, 3987 3633, 3983 3571, 3955 3583, 3936 3547, 3882 3539, 3913 3557, 3920 3598, 3901 3596,"
17732 : : " 3923 3631, 3914 3628, 3919 3647, 3922 3656, 3917 3666, 3523 3438, 3631 3564, 3527 3597, 3718 3655, 3578 3672,"
17733 : : " 3660 3867, 3543 3628, 3416 3725, 3487 3503, 3274 3583, 3271 3644, 3197 3671, 3210 3775, 3184 3788, 3181 3672,"
17734 : : " 3306 3521, 3292 3508, 3229 3565, 3219 3564, 3216 3574, 3192 3578, 3297 3444, 3089 3395, 3029 3028, 2973 3133,"
17735 : : " 2529 2945, 2538 2811, 2461 2901, 2170 2839, 2121 2797, 2156 2733, 2105 2709, 2096 2695, 2114 2621, 2102 2693,"
17736 : : " 2168 2738, 2167 2778, 2447 2765, 2441 2866, 2527 2793, 2670 2938, 2626 2651, 2688 2623, 2740 2922, 3084 2960,"
17737 : : " 3116 3071),(4016 1878, 4029 1859, 4008 1839, 4006 1863, 4016 1878),(3315 1339, 3331 1324, 3290 1293, 3305 1315,"
17738 : : " 3315 1339),(4136 3071, 4136 3080, 4143 3020, 4137 3036, 4136 3071),(4218 3073, 4183 3114, 4117 3157, 4159 3147,"
17739 : : " 4218 3073),(3912 3542, 3934 3536, 3955 3536, 3937 3527, 3900 3540, 3912 3542),(4050 3172, 4043 3210, 4085 3209,"
17740 : : " 4090 3179, 4050 3172),(4151 2998, 4158 2977, 4159 2946, 4147 2988, 4151 2998),(2920 3005, 2935 2994, 2864 2973,"
17741 : : " 2905 3016, 2920 3005),(3571 2424, 3545 2469, 3608 2480, 3596 2434, 3571 2424),(4095 1229, 4073 1234, 4076 1293,"
17742 : : " 4121 1285, 4095 1229),(4173 1536, 4153 1576, 4166 1585, 4198 1571, 4188 1532, 4213 1535, 4224 1512, 4224 1511,"
17743 : : " 4209 1511, 4198 1506, 4190 1517, 4194 1509, 4192 1499, 4200 1496, 4202 1504, 4224 1510, 4224 1488, 4215 1486,"
17744 : : " 4216 1478, 4224 1472, 4224 1464, 4207 1458, 4193 1464, 4173 1536),(3934 1537, 3968 1630, 3960 1666, 3968 1673,"
17745 : : " 3975 1562, 3934 1537),(4182 1653, 4196 1624, 4166 1614, 4157 1674, 4216 1671, 4182 1653),(4200 1619, 4196 1620,"
17746 : : " 4200 1632, 4195 1642, 4207 1648, 4200 1619),(4026 1835, 4025 1830, 4016 1808, 4007 1836, 4026 1835),(4199 1384,"
17747 : : " 4182 1389, 4206 1412, 4216 1401, 4199 1384),(3926 1251, 3969 1206, 3913 1149, 3878 1173, 3876 1229, 3926 1251),"
17748 : : " (3926 1354, 3958 1389, 3997 1384, 3991 1352, 3960 1322, 3955 1299, 3926 1354),(3964 1319, 3974 1329, 3984 1285,"
17749 : : " 3963 1301, 3964 1319),(3687 959, 3696 903, 3678 885, 3665 930, 3687 959),(3452 79, 3437 124, 3456 149, 3476 141,"
17750 : : " 3452 79),(3751 927, 3738 906, 3719 942, 3739 929, 3751 927))" );
17751 : :
17752 : 1 : QString poly2Wkt( "Polygon ((-128 4224, -128 2734, -11 2643, -101 2919, 120 2654, 19 2846, 217 2897, -13 2873, -79 2998, -106 2989,"
17753 : : " -128 3002, -128 4224, -128 4224, 1249 4224, 1247 4199, 1231 4132, 909 3902, 775 3278, 509 2903, 470 2603, 663 2311,"
17754 : : " 889 2134, 989 2146, 534 2585, 575 2880, 833 3112, 833 3037, 1025 2977, 834 3096, 946 3217, 923 3153, 971 3094,"
17755 : : " 997 3103, 1166 3423, 1198 3329, 1233 3367, 1270 3327, 1274 3354, 1290 3360, 1321 3322, 1331 3318, 1343 3325,"
17756 : : " 1310 3073, 1363 3093, 1413 3186, 1325 3398, 1458 3364, 1493 3426, 1526 3394, 1588 3465, 1417 3824, 1458 3825,"
17757 : : " 1522 3849, 1729 3488, 2018 3223, 1908 3291, 1924 3238, 1899 3187, 1913 3150, 2070 3041, 2102 3063, 2112 3053,"
17758 : : " 2168 3085, 2101 2994, 2265 2863, 1890 2593, 2106 2713, 2130 2706, 2108 2678, 2117 2647, 2105 2636, 2099 2604,"
17759 : : " 2094 2591, 2088 2575, 2088 2564, 2249 2751, 2441 2618, 2689 1728, 2681 2323, 2776 1685, 2711 1708, 2673 1680,"
17760 : : " 2675 1639, 2810 1522, 2765 1535, 2734 1510, 2850 1332, 2863 1186, 2847 1025, 2832 985, 2739 1025, 2850 1090,"
17761 : : " 2859 1174, 2853 1235, 2827 1235, 2839 1279, 2811 1286, 2751 1272, 2851 1160, 2788 1159, 2724 1204, 2713 1198,"
17762 : : " 2708 1213, 2699 1221, 2724 1179, 2797 1145, 2785 1123, 2848 1143, 2821 1092, 2284 980, 2288 963, 2264 962,"
17763 : : " 2261 948, 2247 958, 2194 947, 2120 900, 2047 809, 2434 923, 2450 817, 2528 737, 2527 667, 2641 544, 2641 460,"
17764 : : " 2710 452, 2687 447, 2681 435, 2693 330, 2772 327, 2766 291, 2779 245, 2769 219, 2771 198, 2816 219, 2781 342,"
17765 : : " 2612 647, 2903 188, 2803 539, 2950 206, 2927 342, 3123 339, 3092 300, 3073 175, 3082 160, 3412 -103, 4224 -128,"
17766 : : " 4032 167, 3572 63, 3554 109, 3606 211, 3604 232, 3454 124, 3332 345, 3237 212, 3181 415, 2953 364, 2761 692,"
17767 : : " 2819 788, 2997 769, 2997 626, 3199 659, 3155 730, 2929 805, 2908 841, 3218 717, 3276 744, 3246 723, 3270 658,"
17768 : : " 4223 473, 4224 589, 3906 681, 3818 677, 3915 686, 4224 592, 4224 4224, -128 4224, -128 4224),(2049 3181,"
17769 : : " 2224 3084, 2204 3040, 2169 3036, 2174 3084, 2155 3102, 2126 3123, 2109 3127, 2103 3102, 2049 3181),(1578 3811,"
17770 : : " 1567 3883, 1675 3768, 1658 3712, 1659 3751, 1578 3811),(2304 2930, 2335 2918, 2287 2880, 2279 2926, 2304 2930),"
17771 : : " (2316 2895, 2317 2895, 2316 2901, 2331 2901, 2332 2889, 2316 2895),(2304 2850, 2335 2861, 2344 2910, 2357 2828,"
17772 : : " 2304 2850),(1714 3583, 1725 3638, 1682 3717, 1797 3564, 1714 3583),(1537 3873, 1456 3827, 1405 3876, 1461 3898,"
17773 : : " 1537 3873),(2547 2560, 2375 2815, 2384 2825, 2470 2722, 2685 2336, 2648 2310, 2547 2560),(2107 3073, 2107 3098,"
17774 : : " 2144 3086, 2122 3073, 2113 3059, 2107 3073),(2117 3120, 2156 3099, 2164 3083, 2106 3103, 2117 3120),(2303 2981,"
17775 : : " 2226 3010, 2232 3064, 2286 3012, 2344 2928, 2303 2981),(2304 2858, 2291 2864, 2303 2885, 2324 2870, 2304 2858),"
17776 : : " (2175 3002, 2179 2983, 2152 2991, 2175 3002, 2175 3002),(2175 3022, 2150 3017, 2144 3048, 2159 3031, 2184 3030,"
17777 : : " 2175 3022),(2265 2953, 2270 2950, 2262 2950, 2254 2963, 2253 2979, 2265 2953),(2229 2928, 2250 2928, 2241 2922,"
17778 : : " 2239 2914, 2224 2900, 2237 2914, 2229 2928),(2531 2473, 2520 2466, 2521 2474, 2511 2503, 2531 2473),(2547 2526,"
17779 : : " 2529 2519, 2528 2541, 2544 2538, 2547 2526),(2559 646, 2513 810, 2463 835, 2462 930, 2746 731, 2559 646),(3840 653,"
17780 : : " 3809 641, 3718 689, 3547 733, 3553 712, 3440 780, 3840 653),(3327 741, 3242 750, 3195 745, 3180 758, 3326 764,"
17781 : : " 3440 742, 3327 741),(3282 702, 3265 699, 3273 721, 3290 714, 3282 702),(3762 662, 3783 654, 3786 638, 3742 653,"
17782 : : " 3762 662),(3071 703, 3082 741, 3079 655, 3064 657, 3071 703),(3881 637, 3904 647, 3914 626, 3861 638, 3881 637))" );
17783 : :
17784 : 1 : QgsGeometry poly1 = QgsGeometry::fromWkt( poly1Wkt );
17785 : 1 : QgsGeometry poly2 = QgsGeometry::fromWkt( poly2Wkt );
17786 : :
17787 : : double distance;
17788 : 1 : QgsPointXY point = poly1.poleOfInaccessibility( 1, &distance ).asPoint();
17789 : 1 : QGSCOMPARENEAR( point.x(), 3867.37, 0.01 );
17790 : 1 : QGSCOMPARENEAR( point.y(), 2126.45, 0.01 );
17791 : 1 : QGSCOMPARENEAR( distance, 289.51, 0.01 );
17792 : :
17793 : 1 : point = poly1.poleOfInaccessibility( 50 ).asPoint();
17794 : 1 : QGSCOMPARENEAR( point.x(), 3855.33, 0.01 );
17795 : 1 : QGSCOMPARENEAR( point.y(), 2117.55, 0.01 );
17796 : :
17797 : 1 : point = poly2.poleOfInaccessibility( 1 ).asPoint();
17798 : 1 : QGSCOMPARENEAR( point.x(), 3263.50, 0.01 );
17799 : 1 : QGSCOMPARENEAR( point.y(), 3263.50, 0.01 );
17800 : :
17801 : : //test degenerate polygons
17802 : 2 : QgsGeometry degen1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon(( 0 0, 1 0, 2 0, 0 0 ))" ) );
17803 : 1 : point = degen1.poleOfInaccessibility( 1 ).asPoint();
17804 : 1 : QGSCOMPARENEAR( point.x(), 0, 0.01 );
17805 : 1 : QGSCOMPARENEAR( point.y(), 0, 0.01 );
17806 : :
17807 : 2 : QgsGeometry degen2 = QgsGeometry::fromWkt( QStringLiteral( "Polygon(( 0 0, 1 0, 1 1 , 1 0, 0 0 ))" ) );
17808 : 1 : point = degen2.poleOfInaccessibility( 1 ).asPoint();
17809 : 1 : QGSCOMPARENEAR( point.x(), 0, 0.01 );
17810 : 1 : QGSCOMPARENEAR( point.y(), 0, 0.01 );
17811 : :
17812 : : //empty geometry
17813 : 1 : QVERIFY( QgsGeometry().poleOfInaccessibility( 1 ).isNull() );
17814 : :
17815 : : // not a polygon
17816 : 2 : QgsGeometry lineString = QgsGeometry::fromWkt( QStringLiteral( "LineString(1 0, 2 2 )" ) );
17817 : 1 : QVERIFY( lineString.poleOfInaccessibility( 1 ).isNull() );
17818 : :
17819 : : // invalid threshold
17820 : 1 : QVERIFY( poly1.poleOfInaccessibility( -1 ).isNull() );
17821 : 1 : QVERIFY( poly1.poleOfInaccessibility( 0 ).isNull() );
17822 : :
17823 : : // curved geometry
17824 : 1 : QgsGeometry curved = QgsGeometry::fromWkt( "CurvePolygon( CompoundCurve( CircularString(-0.44 0.35, 0.51 0.34, 0.56 0.21, 0.11 -0.33, 0.15 -0.35,"
17825 : : "-0.93 -0.30, -1.02 -0.22, -0.49 0.01, -0.23 -0.04),(-0.23 -0.04, -0.44, 0.35)))" );
17826 : 1 : point = curved.poleOfInaccessibility( 0.01 ).asPoint();
17827 : 1 : QGSCOMPARENEAR( point.x(), -0.4324, 0.0001 );
17828 : 1 : QGSCOMPARENEAR( point.y(), -0.2434, 0.0001 );
17829 : :
17830 : : // multipolygon
17831 : 2 : QgsGeometry multiPoly = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0)),((30 30, 50 30, 50 60, 30 60, 30 30)))" ) );
17832 : 1 : point = multiPoly.poleOfInaccessibility( 0.01, &distance ).asPoint();
17833 : 1 : QGSCOMPARENEAR( point.x(), 40, 0.0001 );
17834 : 1 : QGSCOMPARENEAR( point.y(), 45, 0.0001 );
17835 : 1 : QGSCOMPARENEAR( distance, 10.0, 0.00001 );
17836 : 1 : }
17837 : :
17838 : 1 : void TestQgsGeometry::makeValid()
17839 : : {
17840 : : typedef QPair<QString, QString> InputAndExpectedWktPair;
17841 : 1 : QList<InputAndExpectedWktPair> geoms;
17842 : : // dimension collapse
17843 : 3 : geoms << qMakePair( QStringLiteral( "LINESTRING(0 0)" ),
17844 : 2 : QStringLiteral( "POINT(0 0)" ) );
17845 : : // unclosed ring
17846 : 3 : geoms << qMakePair( QStringLiteral( "POLYGON((10 22,10 32,20 32,20 22))" ),
17847 : 2 : QStringLiteral( "POLYGON((10 22,10 32,20 32,20 22,10 22))" ) );
17848 : : // butterfly polygon (self-intersecting ring)
17849 : 3 : geoms << qMakePair( QStringLiteral( "POLYGON((0 0, 10 10, 10 0, 0 10, 0 0))" ),
17850 : 2 : QStringLiteral( "MULTIPOLYGON(((5 5, 0 0, 0 10, 5 5)),((5 5, 10 10, 10 0, 5 5)))" ) );
17851 : : // polygon with extra tail (a part of the ring does not form any area)
17852 : 3 : geoms << qMakePair( QStringLiteral( "POLYGON((0 0, 1 0, 1 1, 0 1, 0 0, -1 0, 0 0))" ),
17853 : 2 : QStringLiteral( "GEOMETRYCOLLECTION(POLYGON((0 0, 0 1, 1 1, 1 0, 0 0)), LINESTRING(0 0, -1 0))" ) );
17854 : : // collection with invalid geometries
17855 : 3 : geoms << qMakePair( QStringLiteral( "GEOMETRYCOLLECTION(LINESTRING(0 0, 0 0), POLYGON((0 0, 10 10, 10 0, 0 10, 0 0)), LINESTRING(10 0, 10 10))" ),
17856 : 2 : QStringLiteral( "GEOMETRYCOLLECTION(POINT(0 0), MULTIPOLYGON(((5 5, 0 0, 0 10, 5 5)),((5 5, 10 10, 10 0, 5 5))), LINESTRING(10 0, 10 10))" ) );
17857 : : // null line (#18077)
17858 : 3 : geoms << qMakePair( QStringLiteral( "MultiLineString ((356984.0625 6300089, 356984.0625 6300089))" ),
17859 : 2 : QStringLiteral( "MultiPoint ((356984.0625 6300089))" ) );
17860 : :
17861 : 7 : for ( const InputAndExpectedWktPair &pair : geoms )
17862 : : {
17863 : 6 : QgsGeometry gInput = QgsGeometry::fromWkt( pair.first );
17864 : 6 : QgsGeometry gExp = QgsGeometry::fromWkt( pair.second );
17865 : 6 : QVERIFY( !gInput.isNull() );
17866 : 6 : QVERIFY( !gExp.isNull() );
17867 : :
17868 : 6 : QgsGeometry gValid = gInput.makeValid();
17869 : 6 : QVERIFY( gValid.isGeosValid() );
17870 : 6 : QVERIFY( gValid.isGeosEqual( gExp ) );
17871 : 6 : }
17872 : 1 : }
17873 : :
17874 : 1 : void TestQgsGeometry::isSimple_data()
17875 : : {
17876 : 1 : QTest::addColumn<QString>( "wkt" );
17877 : 1 : QTest::addColumn<bool>( "simple" );
17878 : :
17879 : 2 : QTest::newRow( "linestring" ) << QStringLiteral( "LINESTRING(0 0, 1 0, 1 1)" ) << true;
17880 : 2 : QTest::newRow( "may be closed (linear ring)" ) << QStringLiteral( "LINESTRING(0 0, 1 0, 1 1, 0 0)" ) << true;
17881 : 2 : QTest::newRow( "self-intersection" ) << QStringLiteral( "LINESTRING(0 0, 1 0, 1 1, 0 -1)" ) << false;
17882 : 2 : QTest::newRow( "self-tangency" ) << QStringLiteral( "LINESTRING(0 0, 1 0, 1 1, 0.5 0, 0 1)" ) << false;
17883 : 2 : QTest::newRow( "points are simple" ) << QStringLiteral( "POINT(1 1)" ) << true;
17884 : 2 : QTest::newRow( "multipoint" ) << QStringLiteral( "MULTIPOINT((1 1), (2 2))" ) << true;
17885 : 2 : QTest::newRow( "must not contain the same point twice" ) << QStringLiteral( "MULTIPOINT((1 1), (1 1))" ) << false;
17886 : 2 : QTest::newRow( "multiline string simple" ) << QStringLiteral( "MULTILINESTRING((0 0, 1 0), (0 1, 1 1))" ) << true;
17887 : 2 : QTest::newRow( "may be touching at endpoints" ) << QStringLiteral( "MULTILINESTRING((0 0, 1 0), (0 0, 1 0))" ) << true;
17888 : 2 : QTest::newRow( "must not intersect each other" ) << QStringLiteral( "MULTILINESTRING((0 0, 1 1), (0 1, 1 0))" ) << false;
17889 : 1 : }
17890 : :
17891 : 10 : void TestQgsGeometry::isSimple()
17892 : : {
17893 : 10 : QFETCH( QString, wkt );
17894 : 10 : QFETCH( bool, simple );
17895 : :
17896 : 10 : QgsGeometry gInput = QgsGeometry::fromWkt( wkt );
17897 : 10 : QVERIFY( !gInput.isNull() );
17898 : :
17899 : 10 : bool res = gInput.isSimple();
17900 : 10 : QCOMPARE( res, simple );
17901 : 10 : }
17902 : :
17903 : 1 : void TestQgsGeometry::reshapeGeometryLineMerge()
17904 : : {
17905 : : int res;
17906 : 2 : QgsGeometry g2D = QgsGeometry::fromWkt( QStringLiteral( "LINESTRING(10 10, 20 20)" ) );
17907 : 2 : QgsGeometry g3D = QgsGeometry::fromWkt( QStringLiteral( "LINESTRINGZ(10 10 1, 20 20 2)" ) );
17908 : :
17909 : : // prepare 2D reshaping line
17910 : 1 : QgsPointSequence v2D_1, v2D_2;
17911 : 1 : v2D_1 << QgsPoint( 20, 20 ) << QgsPoint( 30, 30 );
17912 : 1 : v2D_2 << QgsPoint( 10, 10 ) << QgsPoint( -10, -10 );
17913 : 1 : QgsLineString line2D_1( v2D_1 ), line2D_2( v2D_2 );
17914 : :
17915 : : // prepare 3D reshaping line
17916 : 1 : QgsPointSequence v3D_1, v3D_2;
17917 : 1 : v3D_1 << QgsPoint( QgsWkbTypes::PointZ, 20, 20, 2 ) << QgsPoint( QgsWkbTypes::PointZ, 30, 30, 3 );
17918 : 1 : v3D_2 << QgsPoint( QgsWkbTypes::PointZ, 10, 10, 1 ) << QgsPoint( QgsWkbTypes::PointZ, -10, -10, -1 );
17919 : 1 : QgsLineString line3D_1( v3D_1 ), line3D_2( v3D_2 );
17920 : :
17921 : : // append with 2D line
17922 : 1 : QgsGeometry g2D_1 = g2D;
17923 : 1 : res = g2D_1.reshapeGeometry( line2D_1 );
17924 : 1 : QCOMPARE( res, 0 );
17925 : 1 : QCOMPARE( g2D_1.asWkt(), QString( "LineString (10 10, 20 20, 30 30)" ) );
17926 : :
17927 : : // prepend with 2D line
17928 : 1 : QgsGeometry g2D_2 = g2D;
17929 : 1 : res = g2D_2.reshapeGeometry( line2D_2 );
17930 : 1 : QCOMPARE( res, 0 );
17931 : 1 : QCOMPARE( g2D_2.asWkt(), QString( "LineString (-10 -10, 10 10, 20 20)" ) );
17932 : :
17933 : : // append with 3D line
17934 : 1 : QgsGeometry g3D_1 = g3D;
17935 : 1 : res = g3D_1.reshapeGeometry( line3D_1 );
17936 : 1 : QCOMPARE( res, 0 );
17937 : 1 : QCOMPARE( g3D_1.asWkt(), QString( "LineStringZ (10 10 1, 20 20 2, 30 30 3)" ) );
17938 : :
17939 : : // prepend with 3D line
17940 : 1 : QgsGeometry g3D_2 = g3D;
17941 : 1 : res = g3D_2.reshapeGeometry( line3D_2 );
17942 : 1 : QCOMPARE( res, 0 );
17943 : 1 : QCOMPARE( g3D_2.asWkt(), QString( "LineStringZ (-10 -10 -1, 10 10 1, 20 20 2)" ) );
17944 : 1 : }
17945 : :
17946 : 1 : void TestQgsGeometry::createCollectionOfType()
17947 : : {
17948 : 1 : std::unique_ptr< QgsGeometryCollection > collect( QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::Unknown ) );
17949 : 1 : QVERIFY( !collect );
17950 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::Point );
17951 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiPoint );
17952 : 1 : QVERIFY( dynamic_cast< QgsMultiPoint *>( collect.get() ) );
17953 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::PointM );
17954 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiPointM );
17955 : 1 : QVERIFY( dynamic_cast< QgsMultiPoint *>( collect.get() ) );
17956 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::PointZM );
17957 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiPointZM );
17958 : 1 : QVERIFY( dynamic_cast< QgsMultiPoint *>( collect.get() ) );
17959 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::PointZ );
17960 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiPointZ );
17961 : 1 : QVERIFY( dynamic_cast< QgsMultiPoint *>( collect.get() ) );
17962 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::MultiPoint );
17963 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiPoint );
17964 : 1 : QVERIFY( dynamic_cast< QgsMultiPoint *>( collect.get() ) );
17965 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::LineStringZ );
17966 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiLineStringZ );
17967 : 1 : QVERIFY( dynamic_cast< QgsMultiLineString *>( collect.get() ) );
17968 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::PolygonM );
17969 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiPolygonM );
17970 : 1 : QVERIFY( dynamic_cast< QgsMultiPolygon *>( collect.get() ) );
17971 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::GeometryCollectionZ );
17972 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::GeometryCollectionZ );
17973 : 1 : QVERIFY( dynamic_cast< QgsGeometryCollection *>( collect.get() ) );
17974 : 1 : collect = QgsGeometryFactory::createCollectionOfType( QgsWkbTypes::CurvePolygonM );
17975 : 1 : QCOMPARE( collect->wkbType(), QgsWkbTypes::MultiSurfaceM );
17976 : 1 : QVERIFY( dynamic_cast< QgsMultiSurface *>( collect.get() ) );
17977 : 1 : }
17978 : :
17979 : 1 : void TestQgsGeometry::orientedMinimumBoundingBox()
17980 : : {
17981 : 1 : QgsGeometry geomTest;
17982 : 1 : QgsGeometry result, resultTest;
17983 : : // empty
17984 : 1 : result = geomTest.orientedMinimumBoundingBox( );
17985 : 1 : QVERIFY( result.isEmpty() );
17986 : :
17987 : : // oriented rectangle
17988 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( " Polygon(0 0, 5 5, -2.07106781186547462 12.07106781186547551, -7.07106781186547462 7.07106781186547551, 0 0) " ) );
17989 : 1 : result = geomTest.orientedMinimumBoundingBox( );
17990 : 1 : QgsPolygonXY geomXY, resultXY;
17991 : 1 : geomXY = geomTest.asPolygon();
17992 : 1 : resultXY = result.asPolygon();
17993 : :
17994 : 1 : QCOMPARE( geomXY.count(), resultXY.count() );
17995 : : // can't strictly compare, use tolerance
17996 : 1 : for ( int i = 0 ; i < geomXY.count() ; ++i )
17997 : : {
17998 : 0 : QVERIFY( geomXY.at( 0 ).at( i ).compare( resultXY.at( 0 ).at( i ), 1E-8 ) );
17999 : 0 : }
18000 : :
18001 : : // Issue https://github.com/qgis/QGIS/issues/33532
18002 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( " Polygon ((264 -525, 248 -521, 244 -519, 233 -508, 231 -504, 210 -445, 196 -396, 180 -332, 178 -322, 176 -310, 174 -296, 174 -261, 176 -257, 178 -255, 183 -251, 193 -245, 197 -243, 413 -176, 439 -168, 447 -166, 465 -164, 548 -164, 552 -166, 561 -175, 567 -187, 602 -304, 618 -379, 618 -400, 616 -406, 612 -414, 606 -420, 587 -430, 575 -436, 547 -446, 451 -474, 437 -478, 321 -511, 283 -521, 275 -523, 266 -525, 264 -525)) " ) );
18003 : 1 : result = geomTest.orientedMinimumBoundingBox( );
18004 : 2 : QString resultTestWKT = QStringLiteral( "Polygon ((635.86 -420.08, 552.66 -134.85, 153.5 -251.27, 236.69 -536.51, 635.86 -420.08))" );
18005 : 1 : QCOMPARE( result.asWkt( 2 ), resultTestWKT );
18006 : :
18007 : 1 : }
18008 : 1 : void TestQgsGeometry::minimalEnclosingCircle()
18009 : : {
18010 : 1 : QgsGeometry geomTest;
18011 : 1 : QgsGeometry result, resultTest;
18012 : 1 : QgsPointXY center;
18013 : : double radius;
18014 : :
18015 : : // empty
18016 : 1 : result = geomTest.minimalEnclosingCircle( center, radius );
18017 : 1 : QCOMPARE( center, QgsPointXY() );
18018 : 1 : QCOMPARE( radius, 0.0 );
18019 : 1 : QVERIFY( result.isNull() );
18020 : :
18021 : : // case 1
18022 : 1 : geomTest = QgsGeometry::fromPointXY( QgsPointXY( 5, 5 ) );
18023 : 1 : result = geomTest.minimalEnclosingCircle( center, radius );
18024 : 1 : QCOMPARE( center, QgsPointXY( 5, 5 ) );
18025 : 1 : QCOMPARE( radius, 0.0 );
18026 : 1 : resultTest.set( QgsCircle( QgsPoint( center ), radius ).toPolygon( 36 ) );
18027 : 1 : QCOMPARE( result.asWkt(), resultTest.asWkt() );
18028 : :
18029 : : // case 2
18030 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( "MULTIPOINT( 3 8, 7 4 )" ) );
18031 : 1 : result = geomTest.minimalEnclosingCircle( center, radius, 6 );
18032 : 1 : QGSCOMPARENEARPOINT( center, QgsPointXY( 5, 6 ), 0.0001 );
18033 : 1 : QGSCOMPARENEAR( radius, sqrt( 2 ) * 2, 0.0001 );
18034 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "Polygon ((7 4, 4.3 3.3, 2.3 5.3, 3 8, 5.7 8.7, 7.7 6.7, 7 4))" ) );
18035 : :
18036 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( "LINESTRING( 0 5, 2 2, 0 -5, -1 -1 )" ) );
18037 : 1 : result = geomTest.minimalEnclosingCircle( center, radius, 6 );
18038 : 1 : QGSCOMPARENEARPOINT( center, QgsPointXY( 0, 0 ), 0.0001 );
18039 : 1 : QGSCOMPARENEAR( radius, 5, 0.0001 );
18040 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "Polygon ((0 5, 4.3 2.5, 4.3 -2.5, 0 -5, -4.3 -2.5, -4.3 2.5, 0 5))" ) );
18041 : :
18042 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( "MULTIPOINT( 0 5, 2 2, 0 -5, -1 -1 )" ) );
18043 : 1 : result = geomTest.minimalEnclosingCircle( center, radius, 6 );
18044 : 1 : QGSCOMPARENEARPOINT( center, QgsPointXY( 0, 0 ), 0.0001 );
18045 : 1 : QGSCOMPARENEAR( radius, 5, 0.0001 );
18046 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "Polygon ((0 5, 4.3 2.5, 4.3 -2.5, 0 -5, -4.3 -2.5, -4.3 2.5, 0 5))" ) );
18047 : :
18048 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( "POLYGON(( 0 5, 2 2, 0 -5, -1 -1 ))" ) );
18049 : 1 : result = geomTest.minimalEnclosingCircle( center, radius, 6 );
18050 : 1 : QGSCOMPARENEARPOINT( center, QgsPointXY( 0, 0 ), 0.0001 );
18051 : 1 : QGSCOMPARENEAR( radius, 5, 0.0001 );
18052 : 1 : resultTest.set( QgsCircle( QgsPoint( center ), radius ).toPolygon( 36 ) );
18053 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "Polygon ((0 5, 4.3 2.5, 4.3 -2.5, 0 -5, -4.3 -2.5, -4.3 2.5, 0 5))" ) );
18054 : :
18055 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( "MULTIPOINT( 0 5, 0 -5, 0 0 )" ) );
18056 : 1 : result = geomTest.minimalEnclosingCircle( center, radius, 6 );
18057 : 1 : QGSCOMPARENEARPOINT( center, QgsPointXY( 0, 0 ), 0.0001 );
18058 : 1 : QGSCOMPARENEAR( radius, 5, 0.0001 );
18059 : 1 : resultTest.set( QgsCircle( QgsPoint( center ), radius ).toPolygon( 36 ) );
18060 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "Polygon ((0 5, 4.3 2.5, 4.3 -2.5, 0 -5, -4.3 -2.5, -4.3 2.5, 0 5))" ) );
18061 : :
18062 : : // case 3
18063 : 2 : geomTest = QgsGeometry::fromWkt( QStringLiteral( "MULTIPOINT((0 0), (5 5), (0 -5), (0 5), (-5 0))" ) );
18064 : 1 : result = geomTest.minimalEnclosingCircle( center, radius, 6 );
18065 : 1 : QGSCOMPARENEARPOINT( center, QgsPointXY( 0.8333, 0.8333 ), 0.0001 );
18066 : 1 : QGSCOMPARENEAR( radius, 5.8926, 0.0001 );
18067 : 1 : resultTest.set( QgsCircle( QgsPoint( center ), radius ).toPolygon( 36 ) );
18068 : 2 : QCOMPARE( result.asWkt( 1 ), QStringLiteral( "Polygon ((0.8 6.7, 5.9 3.8, 5.9 -2.1, 0.8 -5.1, -4.3 -2.1, -4.3 3.8, 0.8 6.7))" ) );
18069 : :
18070 : 1 : }
18071 : :
18072 : 1 : void TestQgsGeometry::splitGeometry()
18073 : : {
18074 : 1 : QVector<QgsGeometry> newGeoms;
18075 : 1 : QgsPointSequence testPoints;
18076 : 1 : qDebug() << GEOSversion() << "\n";
18077 : 2 : QgsGeometry g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((492980.38648063864093274 7082334.45244149677455425, 493082.65415841294452548 7082319.87918917648494244, 492980.38648063858272508 7082334.45244149677455425, 492980.38648063864093274 7082334.45244149677455425))" ) );
18078 : : if ( GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR < 9 )
18079 : : {
18080 : : QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 493825.46541286131832749, 7082214.02779923938214779 ) << QgsPoint( 492955.04876351181883365, 7082338.06309300474822521 ),
18081 : : newGeoms, false, testPoints ), QgsGeometry::NothingHappened );
18082 : : }
18083 : : else
18084 : : {
18085 : 1 : QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 493825.46541286131832749, 7082214.02779923938214779 ) << QgsPoint( 492955.04876351181883365, 7082338.06309300474822521 ),
18086 : : newGeoms, false, testPoints ), QgsGeometry::InvalidBaseGeometry );
18087 : : }
18088 : 1 : QVERIFY( newGeoms.isEmpty() );
18089 : :
18090 : : // Bug https://github.com/qgis/QGIS/issues/33489
18091 : 1 : QgsGeometry g2 = QgsGeometry::fromWkt( "CompoundCurveZ ((2749546.2003820720128715 1262904.45356595050543547 100, 2749557.82053794478997588 1262920.05570670193992555 200))" );
18092 : 1 : testPoints.clear();
18093 : 1 : newGeoms.clear();
18094 : 1 : QCOMPARE( g2.splitGeometry( QgsPointSequence() << QgsPoint( 2749544.19, 1262914.79, 0 ) << QgsPoint( 2749557.64, 1262897.30, 0 ), newGeoms, false, testPoints ), QgsGeometry::Success );
18095 : 1 : QVERIFY( newGeoms.count() == 1 );
18096 : 2 : QCOMPARE( newGeoms[0].asWkt( 2 ), QStringLiteral( "LineStringZ (2749549.12 1262908.38 125.14, 2749557.82 1262920.06 200)" ) );
18097 : :
18098 : : // Test split geometry with topological editing
18099 : 1 : QVector<QgsPointXY> testPointsXY;
18100 : 1 : testPoints.clear();
18101 : 1 : newGeoms.clear();
18102 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) );
18103 : 1 : QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints ), QgsGeometry::Success );
18104 : 1 : QCOMPARE( newGeoms.count(), 1 );
18105 : 1 : QCOMPARE( testPoints.count(), 2 );
18106 : 1 : QgsGeometry::convertPointList( testPoints, testPointsXY );
18107 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18108 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18109 : :
18110 : 1 : testPointsXY.clear();
18111 : 1 : testPoints.clear();
18112 : 1 : newGeoms.clear();
18113 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) );
18114 : 1 : QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints ), QgsGeometry::Success );
18115 : 1 : QCOMPARE( newGeoms.count(), 2 );
18116 : 1 : QCOMPARE( testPoints.count(), 2 );
18117 : 1 : QgsGeometry::convertPointList( testPoints, testPointsXY );
18118 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18119 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18120 : :
18121 : : // Test split parts with topological editing
18122 : 1 : testPointsXY.clear();
18123 : 1 : testPoints.clear();
18124 : 1 : newGeoms.clear();
18125 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) );
18126 : 1 : QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints, false ), QgsGeometry::Success );
18127 : 1 : QCOMPARE( newGeoms.count(), 2 );
18128 : 1 : QCOMPARE( testPoints.count(), 2 );
18129 : 1 : QgsGeometry::convertPointList( testPoints, testPointsXY );
18130 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18131 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18132 : :
18133 : 1 : testPointsXY.clear();
18134 : 1 : testPoints.clear();
18135 : 1 : newGeoms.clear();
18136 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) );
18137 : 1 : QCOMPARE( g1.splitGeometry( QgsPointSequence() << QgsPoint( 0.0, 42.0 ) << QgsPoint( 101.0, 42.0 ), newGeoms, true, testPoints, false ), QgsGeometry::Success );
18138 : 1 : QCOMPARE( newGeoms.count(), 3 );
18139 : 1 : QCOMPARE( testPoints.count(), 2 );
18140 : 1 : QgsGeometry::convertPointList( testPoints, testPointsXY );
18141 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18142 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18143 : :
18144 : : // Repeat previous tests with QVector<QgsPointXY> instead of QgsPointSequence
18145 : : // Those tests are for the deprecated QgsGeometry::splitGeometry() variant and should be removed in QGIS 4.0
18146 : : Q_NOWARN_DEPRECATED_PUSH
18147 : 1 : testPointsXY.clear();
18148 : 1 : newGeoms.clear();
18149 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) );
18150 : 1 : QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY ), QgsGeometry::Success );
18151 : 1 : QCOMPARE( newGeoms.count(), 1 );
18152 : 1 : QCOMPARE( testPointsXY.count(), 2 );
18153 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18154 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18155 : :
18156 : 1 : testPointsXY.clear();
18157 : 1 : newGeoms.clear();
18158 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) );
18159 : 1 : QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY ), QgsGeometry::Success );
18160 : 1 : QCOMPARE( newGeoms.count(), 2 );
18161 : 1 : QCOMPARE( testPointsXY.count(), 2 );
18162 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18163 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18164 : :
18165 : : // Test split parts with topological editing
18166 : 1 : testPointsXY.clear();
18167 : 1 : newGeoms.clear();
18168 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Polygon ((1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0))" ) );
18169 : 1 : QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY, false ), QgsGeometry::Success );
18170 : 1 : QCOMPARE( newGeoms.count(), 2 );
18171 : 1 : QCOMPARE( testPointsXY.count(), 2 );
18172 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18173 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18174 : :
18175 : 1 : testPointsXY.clear();
18176 : 1 : newGeoms.clear();
18177 : 2 : g1 = QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 1.0, 1.0 100.0, 100.0 100.0, 100.0 1.0, 1.0 1.0)" ) );
18178 : 1 : QCOMPARE( g1.splitGeometry( QgsPolylineXY() << QgsPointXY( 0.0, 42.0 ) << QgsPointXY( 101.0, 42.0 ), newGeoms, true, testPointsXY, false ), QgsGeometry::Success );
18179 : 1 : QCOMPARE( newGeoms.count(), 3 );
18180 : 1 : QCOMPARE( testPointsXY.count(), 2 );
18181 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 0 ) ) ) );
18182 : 2 : QVERIFY( QgsGeometry::fromWkt( QStringLiteral( "Linestring (1.0 42.0, 100.0 42.0)" ) ).touches( QgsGeometry::fromPointXY( testPointsXY.at( 1 ) ) ) );
18183 : : Q_NOWARN_DEPRECATED_POP
18184 : 1 : }
18185 : :
18186 : 1 : void TestQgsGeometry::snappedToGrid()
18187 : : {
18188 : : // points
18189 : : {
18190 : 10 : auto check = []( QgsPoint * _a, QgsPoint const & b )
18191 : : {
18192 : 10 : std::unique_ptr<QgsPoint> a {_a};
18193 : : // because it is to check after snapping, there shouldn't be small precision errors
18194 : :
18195 : 10 : if ( !std::isnan( b.x() ) )
18196 : 10 : QVERIFY( ( float )a->x() == ( float )b.x() );
18197 : :
18198 : 10 : if ( !std::isnan( b.y() ) )
18199 : 10 : QVERIFY( ( float )a->y() == ( float )b.y() );
18200 : :
18201 : 10 : if ( !std::isnan( b.z() ) )
18202 : 3 : QVERIFY( ( float )a->z() == ( float )b.z() );
18203 : :
18204 : 10 : if ( !std::isnan( b.m() ) )
18205 : 3 : QVERIFY( ( float )a->m() == ( float )b.m() );
18206 : 10 : };
18207 : :
18208 : :
18209 : 2 : check( QgsPoint( 0, 0 ).snappedToGrid( 1, 1 ),
18210 : 1 : QgsPoint( 0, 0 ) );
18211 : :
18212 : 2 : check( QgsPoint( 1, 2.732 ).snappedToGrid( 1, 1 ),
18213 : 1 : QgsPoint( 1, 3 ) );
18214 : :
18215 : 2 : check( QgsPoint( 1.3, 6.4 ).snappedToGrid( 1, 1 ),
18216 : 1 : QgsPoint( 1, 6 ) );
18217 : :
18218 : 2 : check( QgsPoint( 1.3, 6.4 ).snappedToGrid( 1, 0 ),
18219 : 1 : QgsPoint( 1, 6.4 ) );
18220 : :
18221 : :
18222 : : // multiple checks with the same point
18223 : 1 : auto p1 = QgsPoint( 1.38, 2.4432 );
18224 : :
18225 : 2 : check( p1.snappedToGrid( 1, 1 ),
18226 : 1 : QgsPoint( 1, 2 ) );
18227 : :
18228 : 2 : check( p1.snappedToGrid( 1, 0.1 ),
18229 : 1 : QgsPoint( 1, 2.4 ) );
18230 : :
18231 : 2 : check( p1.snappedToGrid( 1, 0.01 ),
18232 : 1 : QgsPoint( 1, 2.44 ) );
18233 : :
18234 : : // Let's test more dimensions
18235 : 1 : auto p2 = QgsPoint( 4.2134212, 543.1231, 0.123, 12.944145 );
18236 : :
18237 : 1 : check( p2.snappedToGrid( 0, 0, 0, 0 ),
18238 : : p2 );
18239 : :
18240 : 2 : check( p2.snappedToGrid( 0, 0, 1, 1 ),
18241 : 1 : QgsPoint( 4.2134212, 543.1231, 0, 13 ) );
18242 : :
18243 : 2 : check( p2.snappedToGrid( 1, 0.1, 0.01, 0.001 ),
18244 : 1 : QgsPoint( 4, 543.1, 0.12, 12.944 ) );
18245 : :
18246 : 1 : }
18247 : :
18248 : : // MultiPolygon (testing QgsCollection, QgsCurvePolygon and QgsLineString)
18249 : : {
18250 : : /*
18251 : : * List of tested edge cases:
18252 : : *
18253 : : * - QgsLineString becoming a point
18254 : : * - QgsLineString losing enough points so it is no longer closed
18255 : : * - QgsCurvePolygon losing its external ring
18256 : : * - QgsCurvePolygon losing an internal ring
18257 : : * - QgsCurvePolygon losing all internal rings
18258 : : * - QgsCollection losing one of its members
18259 : : * - QgsCollection losing all its members
18260 : : */
18261 : :
18262 : 1 : auto in = QString( "MultiPolygon (((-1.2 -0.87, -0.943 0.8, 0.82 1.4, 1.2 0.9, 0.9 -0.6, -1.2 -0.87),(0.4 0, -0.4 0, 0 0.2, 0.4 0)),((2 0, 2.2 0.2, 2.2 -0.2)),((3 0, 4 0.2, 4 -0.2, 3 0)),((4 8, 3.6 4.1, 0.3 4.9, -0.2 7.8, 4 8),(6.7 7.3, 7 6.4, 5.6 5.9, 6.2 6.8, 6.7 7.3),(6 5.2, 4.9 5.3, 4.8 6.2, 6 5.2)))" );
18263 : 1 : auto out = QString( "MultiPolygon (((-1 -1, -1 1, 1 1, 1 -1, -1 -1)),((4 8, 4 4, 0 5, 0 8, 4 8),(7 7, 7 6, 6 6, 6 7, 7 7),(6 5, 5 5, 5 6, 6 5)))" );
18264 : :
18265 : 1 : auto inGeom = QgsGeometryFactory::geomFromWkt( in );
18266 : :
18267 : 1 : std::unique_ptr<QgsAbstractGeometry> snapped { inGeom->snappedToGrid( 1, 1 ) };
18268 : 1 : QCOMPARE( snapped->asWkt( 5 ), out );
18269 : 1 : }
18270 : :
18271 : : {
18272 : : // Curves
18273 : 1 : QgsGeometry curve = QgsGeometry::fromWkt( "CircularString( 68.1 415.2, 27.1 505.2, 27.1 406.2 )" );
18274 : 1 : std::unique_ptr<QgsAbstractGeometry> snapped { curve.constGet()->snappedToGrid( 1, 1 ) };
18275 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "CircularString (68 415, 27 505, 27 406)" ) );
18276 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 10, 1 ) );
18277 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "CircularString (70 415, 30 505, 30 406)" ) );
18278 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 10 ) );
18279 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "CircularString (68 420, 27 510, 27 410)" ) );
18280 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 0, 0 ) );
18281 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "CircularString (68.1 415.2, 27.1 505.2, 27.1 406.2)" ) );
18282 : :
18283 : 1 : curve = QgsGeometry::fromWkt( "CircularString (68.1 415.2, 27.1 505.2, 27.1 406.2, 35.1 410.1, 39.2 403.2)" );
18284 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1 ) );
18285 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "CircularString (68 415, 27 505, 27 406, 35 410, 39 403)" ) );
18286 : 1 : }
18287 : :
18288 : : {
18289 : : // Lines
18290 : 1 : QgsGeometry curve = QgsGeometry::fromWkt( "LineString( 68.1 415.2, 27.1 505.2, 27.1 406.2 )" );
18291 : 1 : std::unique_ptr<QgsAbstractGeometry> snapped { curve.constGet()->snappedToGrid( 1, 1 ) };
18292 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineString (68 415, 27 505, 27 406)" ) );
18293 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 10, 1 ) );
18294 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineString (70 415, 30 505, 30 406)" ) );
18295 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 10 ) );
18296 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineString (68 420, 27 510, 27 410)" ) );
18297 : :
18298 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 0, 1 ) );
18299 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineString (68.1 415, 27.1 505, 27.1 406)" ) );
18300 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 0 ) );
18301 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineString (68 415.2, 27 505.2, 27 406.2)" ) );
18302 : :
18303 : 1 : curve = QgsGeometry::fromWkt( "LineStringZ (68.1 415.2 11.2, 27.1 505.2 23.6, 27.1 406.2 39.9)" );
18304 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1 ) );
18305 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringZ (68 415 11.2, 27 505 23.6, 27 406 39.9)" ) );
18306 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1, 1 ) );
18307 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringZ (68 415 11, 27 505 24, 27 406 40)" ) );
18308 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1, 10 ) );
18309 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringZ (68 415 10, 27 505 20, 27 406 40)" ) );
18310 : :
18311 : 1 : curve = QgsGeometry::fromWkt( "LineStringM (68.1 415.2 11.2, 27.1 505.2 23.6, 27.1 406.2 39.9)" );
18312 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1 ) );
18313 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringM (68 415 11.2, 27 505 23.6, 27 406 39.9)" ) );
18314 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1, 0, 1 ) );
18315 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringM (68 415 11, 27 505 24, 27 406 40)" ) );
18316 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1, 0, 10 ) );
18317 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringM (68 415 10, 27 505 20, 27 406 40)" ) );
18318 : :
18319 : 1 : curve = QgsGeometry::fromWkt( "LineStringZM (68.1 415.2 11.2 56.7, 27.1 505.2 23.6 49.1, 27.1 406.2 39.9 32.4)" );
18320 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1 ) );
18321 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringZM (68 415 11.2 56.7, 27 505 23.6 49.1, 27 406 39.9 32.4)" ) );
18322 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1, 1, 1 ) );
18323 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringZM (68 415 11 57, 27 505 24 49, 27 406 40 32)" ) );
18324 : 1 : snapped.reset( curve.constGet()->snappedToGrid( 1, 1, 10, 10 ) );
18325 : 2 : QCOMPARE( snapped->asWkt( 5 ), QStringLiteral( "LineStringZM (68 415 10 60, 27 505 20 50, 27 406 40 30)" ) );
18326 : 1 : }
18327 : :
18328 : : //compound curve
18329 : : {
18330 : : // Curves
18331 : 1 : QgsGeometry curve = QgsGeometry::fromWkt( "CompoundCurve(LineString(59.1 402.1, 68.1 415.2),CircularString( 68.1 415.2, 27.1 505.2, 27.1 406.2))" );
18332 : 1 : std::unique_ptr<QgsAbstractGeometry> snapped { curve.constGet()->snappedToGrid( 1, 1 ) };
18333 : 2 : QCOMPARE( snapped->asWkt(), QStringLiteral( "CompoundCurve ((59 402, 68 415),CircularString (68 415, 27 505, 27 406))" ) );
18334 : 1 : }
18335 : 1 : }
18336 : :
18337 : 1 : void TestQgsGeometry::convertGeometryCollectionToSubclass()
18338 : : {
18339 : 2 : QgsGeometry gc0 = QgsGeometry::fromWkt( QStringLiteral( "GeometryCollection(Point(1 1), Polygon((2 2, 3 3, 2 3, 2 2)))" ) );
18340 : :
18341 : 1 : QgsGeometry gc1 = gc0;
18342 : 1 : QVERIFY( gc1.convertGeometryCollectionToSubclass( QgsWkbTypes::PointGeometry ) );
18343 : 2 : QCOMPARE( gc1.asWkt(), QStringLiteral( "MultiPoint ((1 1))" ) );
18344 : :
18345 : 1 : QgsGeometry gc2 = gc0;
18346 : 1 : QVERIFY( gc2.convertGeometryCollectionToSubclass( QgsWkbTypes::PolygonGeometry ) );
18347 : 2 : QCOMPARE( gc2.asWkt(), QStringLiteral( "MultiPolygon (((2 2, 3 3, 2 3, 2 2)))" ) );
18348 : :
18349 : 1 : QgsGeometry gc3 = gc0;
18350 : 1 : QVERIFY( gc3.convertGeometryCollectionToSubclass( QgsWkbTypes::LineGeometry ) );
18351 : 2 : QCOMPARE( gc3.asWkt(), QStringLiteral( "MultiLineString EMPTY" ) );
18352 : 1 : QVERIFY( gc3.isEmpty() );
18353 : :
18354 : : // trying to convert a geometry that is not a geometry collection
18355 : 2 : QgsGeometry wrong = QgsGeometry::fromWkt( QStringLiteral( "Point(1 2)" ) );
18356 : 1 : QVERIFY( !wrong.convertGeometryCollectionToSubclass( QgsWkbTypes::PolygonGeometry ) );
18357 : 1 : }
18358 : :
18359 : 1 : void TestQgsGeometry::emptyJson()
18360 : : {
18361 : 1 : QString expected;
18362 : 2 : expected = QStringLiteral( "{\"coordinates\":[],\"type\":\"LineString\"}" );
18363 : 1 : QCOMPARE( QgsCircularString().asJson(), expected );
18364 : 1 : QCOMPARE( QgsCompoundCurve().asJson(), expected );
18365 : 1 : QCOMPARE( QgsLineString().asJson(), expected );
18366 : :
18367 : 2 : expected = QStringLiteral( "{\"geometries\":[],\"type\":\"GeometryCollection\"}" );
18368 : 1 : QCOMPARE( QgsGeometryCollection().asJson(), expected );
18369 : :
18370 : 2 : expected = QStringLiteral( "{\"coordinates\":[],\"type\":\"MultiLineString\"}" );
18371 : 1 : QCOMPARE( QgsMultiCurve().asJson(), expected );
18372 : 1 : QCOMPARE( QgsMultiLineString().asJson(), expected );
18373 : :
18374 : 2 : expected = QStringLiteral( "{\"coordinates\":[],\"type\":\"MultiPoint\"}" );
18375 : 1 : QCOMPARE( QgsMultiPoint().asJson(), expected );
18376 : :
18377 : 2 : expected = QStringLiteral( "{\"coordinates\":[],\"type\":\"MultiPolygon\"}" );
18378 : 1 : QCOMPARE( QgsMultiSurface().asJson(), expected );
18379 : :
18380 : 2 : expected = QStringLiteral( "{\"coordinates\":[],\"type\":\"Point\"}" );
18381 : 1 : QCOMPARE( QgsPoint().asJson(), expected );
18382 : :
18383 : 2 : expected = QStringLiteral( "{\"coordinates\":[],\"type\":\"Polygon\"}" );
18384 : 1 : QCOMPARE( QgsCurvePolygon().asJson(), expected );
18385 : 1 : QCOMPARE( QgsPolygon().asJson(), expected );
18386 : 1 : QCOMPARE( QgsTriangle().asJson(), expected );
18387 : 1 : }
18388 : :
18389 : 1 : void TestQgsGeometry::testRandomPointsInPolygon()
18390 : : {
18391 : : // null geometry
18392 : 1 : QVector< QgsPointXY > points = QgsGeometry().randomPointsInPolygon( 100 );
18393 : 1 : QVERIFY( points.empty() );
18394 : :
18395 : : // not polygon geometry
18396 : 2 : points = QgsGeometry::fromWkt( QStringLiteral( "Point( 4 5 )" ) ).randomPointsInPolygon( 100 );
18397 : 1 : QVERIFY( points.empty() );
18398 : 2 : points = QgsGeometry::fromWkt( QStringLiteral( "LineString( 4 5, 6 7 )" ) ).randomPointsInPolygon( 100 );
18399 : 1 : QVERIFY( points.empty() );
18400 : :
18401 : : // zero point count
18402 : 2 : points = QgsGeometry::fromWkt( QStringLiteral( "Polygon(( 5 15, 10 15, 10 20, 5 20, 5 15 ))" ) ).randomPointsInPolygon( 0 );
18403 : 1 : QVERIFY( points.empty() );
18404 : :
18405 : : // valid polygon
18406 : 2 : QgsGeometry g = QgsGeometry::fromWkt( QStringLiteral( "Polygon(( 5 15, 10 15, 10 20, 5 20, 5 15 ), (6 16, 8 16, 8 18, 6 16 ))" ) );
18407 : 1 : points = g.randomPointsInPolygon( 10000 );
18408 : 1 : QCOMPARE( points.count(), 10000 );
18409 : 10001 : for ( const QgsPointXY &p : std::as_const( points ) )
18410 : 10000 : QVERIFY( g.intersects( QgsGeometry::fromPointXY( p ) ) );
18411 : :
18412 : : // valid multipolygon
18413 : 2 : g = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon((( 5 15, 10 15, 10 20, 5 20, 5 15 ), (6 16, 8 16, 8 18, 6 16 )), (( 105 115, 110 115, 110 120, 105 120, 105 115 ), (106 116, 108 116, 108 118, 106 116 )))" ) );
18414 : 1 : points = g.randomPointsInPolygon( 10000 );
18415 : 1 : QCOMPARE( points.count(), 10000 );
18416 : 1 : bool foundp1Point = false;
18417 : 1 : bool foundp2Point = false;
18418 : 10001 : for ( const QgsPointXY &p : std::as_const( points ) )
18419 : : {
18420 : 10000 : QVERIFY( g.intersects( QgsGeometry::fromPointXY( p ) ) );
18421 : 10000 : foundp1Point |= p.x() < 100;
18422 : 10000 : foundp2Point |= p.x() > 100;
18423 : : }
18424 : 1 : QVERIFY( foundp1Point );
18425 : 1 : QVERIFY( foundp2Point );
18426 : :
18427 : : // with seed
18428 : 2 : g = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon((( 5 15, 10 15, 10 20, 5 20, 5 15 ), (6 16, 8 16, 8 18, 6 16 )), (( 105 115, 110 115, 110 120, 105 120, 105 115 ), (106 116, 108 116, 108 118, 106 116 )))" ) );
18429 : 1 : QVector< QgsPointXY > points1 = g.randomPointsInPolygon( 100, 200 );
18430 : 1 : QCOMPARE( points1.count(), 100 );
18431 : 1 : QVector< QgsPointXY > points2 = g.randomPointsInPolygon( 100, 200 );
18432 : 1 : QCOMPARE( points2.count(), 100 );
18433 : 1 : QCOMPARE( points1, points2 );
18434 : :
18435 : : // no seed
18436 : 1 : points1 = g.randomPointsInPolygon( 100 );
18437 : 1 : QCOMPARE( points1.count(), 100 );
18438 : 1 : points2 = g.randomPointsInPolygon( 100 );
18439 : 1 : QCOMPARE( points2.count(), 100 );
18440 : 1 : QVERIFY( points1 != points2 );
18441 : :
18442 : : // with filter
18443 : 20147 : points = g.randomPointsInPolygon( 10000, []( const QgsPointXY & p )->bool
18444 : : {
18445 : 20146 : return p.x() > 100;
18446 : : } );
18447 : 1 : QCOMPARE( points.count(), 10000 );
18448 : 1 : foundp1Point = false;
18449 : 1 : foundp2Point = false;
18450 : 10001 : for ( const QgsPointXY &p : std::as_const( points ) )
18451 : : {
18452 : 10000 : QVERIFY( g.intersects( QgsGeometry::fromPointXY( p ) ) );
18453 : 10000 : foundp1Point |= p.x() < 100;
18454 : 10000 : foundp2Point |= p.x() > 100;
18455 : : }
18456 : 1 : QVERIFY( !foundp1Point );
18457 : 1 : QVERIFY( foundp2Point );
18458 : 1 : }
18459 : :
18460 : 1 : void TestQgsGeometry::wktParser()
18461 : : {
18462 : : // POINT
18463 : : // unbalanced parentheses
18464 : 1 : QVERIFY( QgsPoint().fromWkt( "POINT((0 1)" ) );
18465 : 1 : QVERIFY( QgsPoint().fromWkt( "POINT(0 1) )" ) );
18466 : 1 : QVERIFY( QgsPoint().fromWkt( "POINT ((0 1)" ) );
18467 : 1 : QVERIFY( QgsPoint().fromWkt( "POINT (0 1) )" ) );
18468 : : // extra parentheses
18469 : 1 : QVERIFY( QgsPoint().fromWkt( "POINT ( (5 1) )" ) );
18470 : : // not a number
18471 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT (a, b)" ) );
18472 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT (a b)" ) );
18473 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT((0, 1)" ) );
18474 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT(0, 1) )" ) );
18475 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT ((0, 1)" ) );
18476 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT (0, 1) )" ) );
18477 : 1 : QVERIFY( ! QgsPoint().fromWkt( "POINT ( (5, 1) )" ) );
18478 : :
18479 : : // valid
18480 : 1 : QgsPoint p;
18481 : 1 : QVERIFY( p.fromWkt( "POINT (5 1)" ) );
18482 : 2 : QCOMPARE( p.asWkt(), QStringLiteral( "Point (5 1)" ) );
18483 : : // extra parentheses
18484 : 1 : QVERIFY( p.fromWkt( "POINT ( (5 1) )" ) );
18485 : : // unbalanced parentheses
18486 : 1 : QVERIFY( p.fromWkt( "POINT ( (5 1)" ) );
18487 : 2 : QCOMPARE( p.asWkt(), QStringLiteral( "Point (5 1)" ) );
18488 : 1 : QVERIFY( p.fromWkt( "POINT (5 1) )" ) );
18489 : 2 : QCOMPARE( p.asWkt(), QStringLiteral( "Point (5 1)" ) );
18490 : :
18491 : 1 : QVERIFY( p.fromWkt( "POINT (5.1234 1.4321)" ) );
18492 : 2 : QCOMPARE( p.asWkt( 4 ), QStringLiteral( "Point (5.1234 1.4321)" ) );
18493 : 1 : QVERIFY( p.fromWkt( "POINT (-5.1234 -1.4321)" ) );
18494 : 2 : QCOMPARE( p.asWkt( 4 ), QStringLiteral( "Point (-5.1234 -1.4321)" ) );
18495 : 1 : QVERIFY( p.fromWkt( "POINT (-12e4 -1.4e-1)" ) );
18496 : 2 : QCOMPARE( p.asWkt( 2 ), QStringLiteral( "Point (-120000 -0.14)" ) );
18497 : :
18498 : 1 : QVERIFY( p.fromWkt( "POINT ( )" ) );
18499 : 2 : QCOMPARE( p.asWkt(), QStringLiteral( "Point EMPTY" ) );
18500 : 1 : QVERIFY( ! p.fromWkt( "POINT (a, b)" ) );
18501 : 2 : QCOMPARE( p.asWkt(), QStringLiteral( "Point EMPTY" ) );
18502 : : // LINESTRING
18503 : 1 : QVERIFY( QgsLineString().fromWkt( "LineString(0 1, 1 2) )" ) );
18504 : 1 : QVERIFY( QgsLineString().fromWkt( "LineString (0 1, 1 2) )" ) );
18505 : 1 : QVERIFY( QgsLineString().fromWkt( "LineString ( (0 1) )" ) );
18506 : 1 : QVERIFY( QgsLineString().fromWkt( "LineString ( ( 0 1, 2 3 ) )" ) );
18507 : 1 : QVERIFY( QgsMultiLineString().fromWkt( "MULTILINESTRING ((((1 2, 2 4, 4 5))" ) );
18508 : 1 : QVERIFY( QgsMultiLineString().fromWkt( "MULTILINESTRING((((1 2, 2 4, 4 5))" ) );
18509 : : // not a number
18510 : 1 : QVERIFY( ! QgsLineString().fromWkt( "LineString(0, 1) )" ) );
18511 : 1 : QVERIFY( ! QgsLineString().fromWkt( "LineString (0, 1) )" ) );
18512 : 1 : QVERIFY( ! QgsLineString().fromWkt( "LineString (a b, 3 4)" ) );
18513 : 1 : QVERIFY( ! QgsMultiLineString().fromWkt( "MULTILINESTRING ((1 2, 2 a, 4 b))" ) );
18514 : : // valid
18515 : 1 : QgsLineString l;
18516 : 1 : QVERIFY( l.fromWkt( "LINESTRING ( 1 2, 3 4 )" ) );
18517 : 2 : QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) );
18518 : : // unbalanced parentheses
18519 : 1 : QVERIFY( l.fromWkt( "LINESTRING ( ( 1 2, 3 4 )" ) );
18520 : 2 : QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) );
18521 : 1 : QVERIFY( l.fromWkt( "LINESTRING ( 1 2, 3 4 ) )" ) );
18522 : 2 : QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) );
18523 : : // extra parentheses
18524 : 1 : QVERIFY( l.fromWkt( "LINESTRING( ( 1 2, 3 4 ) )" ) );
18525 : 2 : QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) );
18526 : : // empty
18527 : 1 : QVERIFY( l.fromWkt( "LINESTRING ( )" ) );
18528 : 2 : QCOMPARE( l.asWkt(), QStringLiteral( "LineString EMPTY" ) );
18529 : 1 : QVERIFY( ! l.fromWkt( "LINESTRING ( a b, 2 3 )" ) );
18530 : 2 : QCOMPARE( l.asWkt(), QStringLiteral( "LineString EMPTY" ) );
18531 : 1 : QVERIFY( l.fromWkt( "LINESTRING ( 1e4 -2, 3 +4.5 )" ) );
18532 : 2 : QCOMPARE( l.asWkt( 1 ), QStringLiteral( "LineString (10000 -2, 3 4.5)" ) );
18533 : 1 : QgsMultiLineString m;
18534 : 1 : m.fromWkt( "MULTILINESTRING ((1 2, 2 3, 4 5))" ) ;
18535 : 1 : QVERIFY( m.fromWkt( "MULTILINESTRING ((1 2, 2 3, 4 5))" ) );
18536 : 2 : QCOMPARE( m.asWkt( 1 ), QStringLiteral( "MultiLineString ((1 2, 2 3, 4 5))" ) );
18537 : :
18538 : : // TRIANGLE
18539 : : // unbalanced parenthesis
18540 : 1 : QVERIFY( QgsTriangle().fromWkt( "Triangle( (0 1, 1 2, 3 3) )) " ) );
18541 : 1 : QVERIFY( QgsTriangle().fromWkt( "Triangle ( (0 1, 1 2, 3 3) )) " ) );
18542 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle(0 1, 1 2, 3 3) )" ) );
18543 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle (0 1, 1 2, 3 3) )" ) );
18544 : : // not a number
18545 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle ( (0 a, b 2, 3 3 )) " ) );
18546 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle ( (0 a, b 2, 3 3, 0 a )) " ) );
18547 : : // incorrect number of points
18548 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle (( 0 0, 1 1))" ) );
18549 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle (( 0 0, 1 1, 1 0, 2 3, 4 5))" ) );
18550 : 1 : QVERIFY( ! QgsTriangle().fromWkt( "Triangle (( 0 1, 2 3, 3 4, 1 0))" ) ); // four points but start and last points are different
18551 : : // valid
18552 : 1 : QgsTriangle t;
18553 : 1 : QVERIFY( t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4))" ) );
18554 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1, 2 3, 3 4))" ) );
18555 : 1 : QVERIFY( t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 1))" ) );
18556 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1, 2 3, 3 4, 0 1))" ) );
18557 : 1 : QVERIFY( t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 1))" ) );
18558 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1, 2 3, 3 4, 0 1))" ) );
18559 : 1 : QVERIFY( ! t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 3))" ) );
18560 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle EMPTY" ) );
18561 : 1 : QVERIFY( ! t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 3, 4 5))" ) );
18562 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle EMPTY" ) );
18563 : 1 : QVERIFY( ! t.fromWkt( "TRIANGLE(( 0 1, 2 3 ))" ) );
18564 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle EMPTY" ) );
18565 : 1 : QVERIFY( t.fromWkt( "TRIANGLE((0 1e3, -2 3, +3 4, 0 1e3))" ) );
18566 : 2 : QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1000, -2 3, 3 4, 0 1000))" ) );
18567 : :
18568 : : // POLYGON
18569 : : // unbalanced parenthesis
18570 : 1 : QVERIFY( QgsPolygon().fromWkt( "Polygon( (0 1, 1 2, 3 3) )) " ) );
18571 : 1 : QVERIFY( QgsPolygon().fromWkt( "Polygon ( (0 1, 1 2, 3 3) )) " ) );
18572 : 1 : QVERIFY( ! QgsPolygon().fromWkt( "Polygon(0 1, 1 2, 3 3) )" ) );
18573 : 1 : QVERIFY( ! QgsPolygon().fromWkt( "Polygon (0 1, 1 2, 3 3) )" ) );
18574 : : // not a number
18575 : 1 : QVERIFY( ! QgsPolygon().fromWkt( "Polygon ( (0 a, b 2, 3 3 )) " ) );
18576 : 1 : QVERIFY( ! QgsPolygon().fromWkt( "Polygon ( (0 a, b 2, 3 3, 0 a )) " ) );
18577 : : // valid
18578 : 1 : QgsPolygon poly;
18579 : 1 : QVERIFY( poly.fromWkt( "Polygon(( 0 1, 2 3, 3 4))" ) );
18580 : 2 : QCOMPARE( poly.asWkt(), QStringLiteral( "Polygon ((0 1, 2 3, 3 4))" ) ); // TODO: A polygon must be closed
18581 : 1 : QVERIFY( poly.fromWkt( "Polygon(( 0 1, 2 3, 3 4, 0 1))" ) );
18582 : 2 : QCOMPARE( poly.asWkt(), QStringLiteral( "Polygon ((0 1, 2 3, 3 4, 0 1))" ) );
18583 : 1 : QVERIFY( poly.fromWkt( "Polygon((0 1e3, -2 3, +3 4, 0 1))" ) );
18584 : 2 : QCOMPARE( poly.asWkt(), QStringLiteral( "Polygon ((0 1000, -2 3, 3 4, 0 1))" ) );
18585 : :
18586 : : // Circular string
18587 : : // unbalanced parenthesis
18588 : 1 : QVERIFY( QgsCircularString().fromWkt( "CircularString(0 1, 1 2, 3 3) )" ) );
18589 : 1 : QVERIFY( QgsCircularString().fromWkt( "CircularString (0 1, 1 2, 3 3) )" ) );
18590 : 1 : QVERIFY( QgsCircularString().fromWkt( "CircularString( (0 1, 1 2, 3 3) )) " ) );
18591 : 1 : QVERIFY( QgsCircularString().fromWkt( "CircularString ( (0 1, 1 2, 3 3) )) " ) );
18592 : : // not a number
18593 : 1 : QVERIFY( ! QgsCircularString().fromWkt( "CircularString (0 a, b 2, 3 3) " ) );
18594 : 1 : QVERIFY( ! QgsCircularString().fromWkt( "CircularString (0 a, b 2, 3 3, 0 a) " ) );
18595 : : // valid
18596 : 1 : QgsCircularString c;
18597 : 1 : QVERIFY( c.fromWkt( "CircularString( 0 1, 2 3, 3 4)" ) );
18598 : 2 : QCOMPARE( c.asWkt(), QStringLiteral( "CircularString (0 1, 2 3, 3 4)" ) );
18599 : 1 : QVERIFY( c.fromWkt( "CircularString(0 1e3, -2 3, +3 4)" ) );
18600 : 2 : QCOMPARE( c.asWkt(), QStringLiteral( "CircularString (0 1000, -2 3, 3 4)" ) );
18601 : :
18602 : 1 : QVERIFY( c.fromWkt( "CircularString ((0 0,1 1,2 0))" ) ); // Added from an old test with an invalid wkt, but allowed in QGIS https://github.com/qgis/QGIS/pull/38439/files/59aab9dc9cc58bdc98e6d8091840bc129564ed2f#diff-fe3aa1328ee04f0eb00a1b1d59c0ea71L4247
18603 : 2 : QCOMPARE( c.asWkt(), QStringLiteral( "CircularString (0 0, 1 1, 2 0)" ) );
18604 : :
18605 : : // multipoint
18606 : 1 : QgsMultiPoint mp;
18607 : 1 : QVERIFY( ! mp.fromWkt( "MULTIPOINT (((10 40), (40 30), (20 20), (30 10))" ) );
18608 : 1 : QVERIFY( ! mp.fromWkt( "MULTIPOINT (((10 40), (40 30), (xx20 20), (30 10))" ) );
18609 : 1 : QVERIFY( ! mp.fromWkt( "MULTIPOINT ((10 40, 40 30, 20 20, 30 10)" ) );
18610 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))))" ) );
18611 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT ( )" ) );
18612 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT EMPTY" ) );
18613 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))" ) );
18614 : 2 : QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((10 40),(40 30),(20 20),(30 10))" ) );
18615 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT (10 40, 40 30, 20 20, 30 10)" ) );
18616 : 2 : QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((10 40),(40 30),(20 20),(30 10))" ) );
18617 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))))" ) );
18618 : 2 : QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((10 40),(40 30),(20 20),(30 10))" ) );
18619 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT ( )" ) );
18620 : 2 : QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint EMPTY" ) );
18621 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT EMPTY" ) );
18622 : 2 : QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint EMPTY" ) );
18623 : : // Added from an old test with an invalid wkt, but allowed in QGIS https://github.com/qgis/QGIS/pull/38439/files/59aab9dc9cc58bdc98e6d8091840bc129564ed2f#diff-4444b5a772b35be43721b71a4b95d785R50
18624 : 1 : QVERIFY( mp.fromWkt( "MULTIPOINT(0 20,20 20))" ) );
18625 : 2 : QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((0 20),(20 20))" ) );
18626 : :
18627 : : // compoundcurve
18628 : 1 : QgsCompoundCurve cc;
18629 : 1 : QVERIFY( ! cc.fromWkt( "COMPOUNDCURVE((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18630 : 1 : QVERIFY( cc.fromWkt( "COMPOUNDCURVE(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) );
18631 : 2 : QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve (CircularString (0 0, 1 1, 2 2))" ) );
18632 : 1 : QVERIFY( cc.fromWkt( "COMPOUNDCURVE(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18633 : 2 : QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve (CircularString (0 0, 1 1, 2 2))" ) );
18634 : 1 : QVERIFY( cc.fromWkt( "COMPOUNDCURVE(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) );
18635 : 2 : QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve (CircularString (0 0, 1 1, 2 2),(2 2, 3 3))" ) );
18636 : 1 : QVERIFY( cc.fromWkt( "COMPOUNDCURVE ( )" ) );
18637 : 2 : QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve EMPTY" ) );
18638 : 1 : QVERIFY( cc.fromWkt( "COMPOUNDCURVE EMPTY" ) );
18639 : 2 : QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve EMPTY" ) );
18640 : : // geometrycollection
18641 : 1 : QgsGeometryCollection gc;
18642 : 1 : QVERIFY( gc.fromWkt( "GeometryCollection((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18643 : 2 : QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (GeometryCollection (CircularString (0 0, 1 1, 2 2)))" ) );
18644 : 1 : QVERIFY( gc.fromWkt( "GeometryCollection(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) );
18645 : 2 : QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (CircularString (0 0, 1 1, 2 2))" ) );
18646 : 1 : QVERIFY( gc.fromWkt( "GeometryCollection(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18647 : 2 : QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (CircularString (0 0, 1 1, 2 2))" ) );
18648 : 1 : QVERIFY( gc.fromWkt( "GeometryCollection(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) );
18649 : 2 : QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (CircularString (0 0, 1 1, 2 2),LineString (2 2, 3 3))" ) );
18650 : 1 : QVERIFY( gc.fromWkt( "GeometryCollection ( )" ) );
18651 : 2 : QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection EMPTY" ) );
18652 : 1 : QVERIFY( gc.fromWkt( "GeometryCollection EMPTY" ) );
18653 : 2 : QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection EMPTY" ) );
18654 : : // curvepolygon
18655 : 1 : QgsCurvePolygon cp;
18656 : 1 : QVERIFY( ! cp.fromWkt( "CurvePolygon((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18657 : 1 : QVERIFY( cp.fromWkt( "CurvePolygon(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) );
18658 : 2 : QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon (CircularString (0 0, 1 1, 2 2))" ) );
18659 : 1 : QVERIFY( cp.fromWkt( "CurvePolygon(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18660 : 2 : QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon (CircularString (0 0, 1 1, 2 2))" ) );
18661 : 1 : QVERIFY( cp.fromWkt( "CurvePolygon(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) );
18662 : 2 : QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon (CircularString (0 0, 1 1, 2 2),(2 2, 3 3))" ) );
18663 : 1 : QVERIFY( cp.fromWkt( "CurvePolygon ( )" ) );
18664 : 2 : QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon EMPTY" ) );
18665 : 1 : QVERIFY( cp.fromWkt( "CurvePolygon EMPTY" ) );
18666 : 2 : QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon EMPTY" ) );
18667 : : // multicurve
18668 : 1 : QgsMultiCurve mc;
18669 : 1 : QVERIFY( ! mc.fromWkt( "MultiCurve((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18670 : 1 : QVERIFY( mc.fromWkt( "MultiCurve(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) );
18671 : 2 : QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve (CircularString (0 0, 1 1, 2 2))" ) );
18672 : 1 : QVERIFY( mc.fromWkt( "MultiCurve(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) );
18673 : 2 : QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve (CircularString (0 0, 1 1, 2 2))" ) );
18674 : 1 : QVERIFY( mc.fromWkt( "MultiCurve(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) );
18675 : 2 : QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve (CircularString (0 0, 1 1, 2 2),LineString (2 2, 3 3))" ) );
18676 : 1 : QVERIFY( mc.fromWkt( "MultiCurve ( )" ) );
18677 : 2 : QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve EMPTY" ) );
18678 : 1 : QVERIFY( mc.fromWkt( "MultiCurve EMPTY" ) );
18679 : 2 : QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve EMPTY" ) );
18680 : : // multisurface
18681 : 1 : QgsMultiSurface ms;
18682 : 1 : QVERIFY( ! ms.fromWkt( "MultiSurface((Polygon( 0 0, 1 1, 2 2))" ) );
18683 : 1 : QVERIFY( ms.fromWkt( "MultiSurface(Polygon(( 0 0, 1 1, 2 2)))" ) );
18684 : 2 : QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface (Polygon ((0 0, 1 1, 2 2)))" ) );
18685 : 1 : QVERIFY( ms.fromWkt( "MultiSurface(Polygon(( 0 0, 1 1, 2 2)))" ) );
18686 : 2 : QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface (Polygon ((0 0, 1 1, 2 2)))" ) );
18687 : 1 : QVERIFY( ms.fromWkt( "MultiSurface(Polygon(( 0 0, 1 1, 2 2)), Polygon((2 2, 3 3, 3 2)))" ) );
18688 : 2 : QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface (Polygon ((0 0, 1 1, 2 2)),Polygon ((2 2, 3 3, 3 2)))" ) );
18689 : 1 : QVERIFY( ms.fromWkt( "MultiSurface ( )" ) );
18690 : 2 : QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface EMPTY" ) );
18691 : 1 : QVERIFY( ms.fromWkt( "MultiSurface EMPTY" ) );
18692 : 2 : QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface EMPTY" ) );
18693 : : // multipolygon
18694 : 1 : QgsMultiPolygon mpoly;
18695 : 1 : QVERIFY( ! mpoly.fromWkt( "MultiPolygon((Polygon( 0 0, 1 1, 2 2))" ) );
18696 : 1 : QVERIFY( mpoly.fromWkt( "MultiPolygon(Polygon(( 0 0, 1 1, 2 2)))" ) );
18697 : 2 : QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 1 1, 2 2)))" ) );
18698 : 1 : QVERIFY( mpoly.fromWkt( "MultiPolygon(Polygon(( 0 0, 1 1, 2 2)))" ) );
18699 : 2 : QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 1 1, 2 2)))" ) );
18700 : 1 : QVERIFY( mpoly.fromWkt( "MultiPolygon(Polygon(( 0 0, 1 1, 2 2)), Polygon((2 2, 3 3, 3 2)))" ) );
18701 : 2 : QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 1 1, 2 2)),((2 2, 3 3, 3 2)))" ) );
18702 : 1 : QVERIFY( mpoly.fromWkt( "MultiPolygon ( )" ) );
18703 : 2 : QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) );
18704 : 1 : QVERIFY( mpoly.fromWkt( "MultiPolygon EMPTY" ) );
18705 : 2 : QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) );
18706 : :
18707 : : // multilinestring
18708 : 1 : QgsMultiLineString mline;
18709 : 1 : QVERIFY( ! mline.fromWkt( "MultiLineString((LineString( 0 0, 1 1, 2 2))" ) );
18710 : 1 : QVERIFY( mline.fromWkt( "MultiLineString(LineString(( 0 0, 1 1, 2 2)))" ) );
18711 : 2 : QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString ((0 0, 1 1, 2 2))" ) );
18712 : 1 : QVERIFY( mline.fromWkt( "MultiLineString(LineString(( 0 0, 1 1, 2 2)))" ) );
18713 : 2 : QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString ((0 0, 1 1, 2 2))" ) );
18714 : 1 : QVERIFY( mline.fromWkt( "MultiLineString(LineString(( 0 0, 1 1, 2 2)), LineString((2 2, 3 3, 3 2)))" ) );
18715 : 2 : QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString ((0 0, 1 1, 2 2),(2 2, 3 3, 3 2))" ) );
18716 : 1 : QVERIFY( mline.fromWkt( "MultiLineString ( )" ) );
18717 : 2 : QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString EMPTY" ) );
18718 : 1 : QVERIFY( mline.fromWkt( "MultiLineString EMPTY" ) );
18719 : 2 : QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString EMPTY" ) );
18720 : 1 : }
18721 : 1 : QGSTEST_MAIN( TestQgsGeometry )
18722 : : #include "testqgsgeometry.moc"
|