1 /***************************************************************************
2      testqgscurve.cpp
3      --------------------------------------
4     Date                 : 21 July 2017
5     Copyright            : (C) 2017-2019 by Sandro Santilli
6     Email                : strk @ kbt.io
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 <QObject>
16 #include <QString>
17 #include <QApplication>
18 #include <memory> // for unique_ptr
19 
20 //qgis includes...
21 #include "qgsabstractgeometry.h"
22 #include "qgscircularstring.h"
23 #include "qgsgeometry.h"
24 #include "qgsgeometryfactory.h"
25 #include "qgslinestring.h"
26 #include "qgspoint.h"
27 #include "qgstest.h"
28 
29 /**
30  * \ingroup UnitTests
31  * This is a unit test for the operations on curve geometries
32  */
33 class TestQgsCurve : public QObject
34 {
35     Q_OBJECT
36 
37   public:
38     TestQgsCurve() = default;
39 
40   private slots:
41     //void initTestCase();// will be called before the first testfunction is executed.
42     //void cleanupTestCase();// will be called after the last testfunction was executed.
43     //void init();// will be called before each testfunction is executed.
44     //void cleanup();// will be called after every testfunction.
45 
46     void curveToLine();
47 };
48 
49 
50 #define TEST_C2L(circularString, tol, toltype, exp, prec) { \
51     std::unique_ptr< QgsLineString > lineString( \
52         circularString->curveToLine(tol, toltype) \
53                                                ); \
54     QVERIFY( lineString.get() ); \
55     QString wkt_out = lineString->asWkt(prec); \
56     QCOMPARE( wkt_out, QString( exp ) ); \
57     /* Test reverse */ \
58     std::unique_ptr< QgsCircularString > reversed( \
59         circularString->reversed() \
60                                                  ); \
61     lineString.reset( \
62                       reversed->curveToLine(tol, toltype) \
63                     ); \
64     wkt_out = lineString->asWkt(prec); \
65     lineString.reset( \
66                       reversed->curveToLine(tol, toltype) \
67                     ); \
68     std::unique_ptr< QgsLineString > expgeom( \
69         dynamic_cast<QgsLineString *>( \
70                                        QgsGeometryFactory::geomFromWkt( exp ).release() \
71                                      ) \
72                                             ); \
73     expgeom.reset( expgeom->reversed() ); \
74     QString exp_reversed = expgeom->asWkt(prec); \
75     QCOMPARE( wkt_out, exp_reversed ); \
76   }
77 
curveToLine()78 void TestQgsCurve::curveToLine()
79 {
80   std::unique_ptr< QgsCircularString > circularString;
81 
82   /* input: 2 quadrants arc (180 degrees, PI radians) */
83   circularString.reset( dynamic_cast< QgsCircularString *>(
84                           QgsGeometryFactory::geomFromWkt( QStringLiteral(
85                                 "CIRCULARSTRING(0 0,100 100,200 0)"
86                               )
87                                                          ).release()
88                         ) );
89   QVERIFY( circularString.get() );
90 
91   /* op: Maximum of 10 units of difference, symmetric */
92   TEST_C2L( circularString, 10, QgsAbstractGeometry::MaximumDifference,
93             "LineString (0 0, 29.29 70.71, 100 100, 170.71 70.71, 200 0)", 2 );
94 
95   /* op: Maximum of 300 units (higher than sagitta) of difference, symmetric */
96   /* See https://github.com/qgis/QGIS/issues/31832 */
97   TEST_C2L( circularString, 300, QgsAbstractGeometry::MaximumDifference,
98             "LineString (0 0, 200 0)", 2 );
99 
100   /* op: Maximum of M_PI / 8 degrees of angle, (a)symmetric */
101   /* See https://github.com/qgis/QGIS/issues/24616 */
102   TEST_C2L( circularString, M_PI / 8, QgsAbstractGeometry::MaximumAngle,
103             "LineString (0 0, 7.61 38.27, 29.29 70.71, 61.73 92.39, 100 100, 138.27 92.39, 170.71 70.71, 192.39 38.27, 200 0)", 2 );
104 
105   /* op: Maximum of 70 degrees of angle, symmetric */
106   /* See https://github.com/qgis/QGIS/issues/24621 */
107   TEST_C2L( circularString, 70 * M_PI / 180, QgsAbstractGeometry::MaximumAngle,
108             "LineString (0 0, 50 86.6, 150 86.6, 200 0)", 2 );
109 
110   /* input: 2 arcs of 2 quadrants each (180 degrees + 180 degrees other direction) */
111   circularString.reset( dynamic_cast<QgsCircularString *>(
112                           QgsGeometryFactory::geomFromWkt( QStringLiteral(
113                                 "CIRCULARSTRING(0 0,100 100,200 0,300 -100,400 0)"
114                               ) ).release()
115                         ) );
116   QVERIFY( circularString.get() );
117 
118   /* op: Maximum of M_PI / 3 degrees of angle */
119   TEST_C2L( circularString, M_PI / 3, QgsAbstractGeometry::MaximumAngle,
120             "LineString (0 0, 50 86.6, 150 86.6, 200 0, 250 -86.6, 350 -86.6, 400 0)", 2 );
121 }
122 
123 
124 QGSTEST_MAIN( TestQgsCurve )
125 #include "testqgscurve.moc"
126