Branch data Line data Source code
1 : : /***************************************************************************
2 : : testqgsgeometryutils.cpp
3 : : --------------------------------------
4 : : Date : 16 Jan 2015
5 : : Copyright : (C) 2015 by Marco Hugentobler
6 : : Email : marco at sourcepole dot ch
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 : :
16 : : #include <math.h>
17 : :
18 : : #include "qgstest.h"
19 : : #include <QObject>
20 : : #include "qgsgeometryutils.h"
21 : : #include "qgslinestring.h"
22 : : #include "qgspolygon.h"
23 : : #include "qgsmultipolygon.h"
24 : :
25 : 2 : class TestQgsGeometryUtils: public QObject
26 : : {
27 : : Q_OBJECT
28 : : public:
29 : : QString elemToString( const QDomElement &elem ) const;
30 : :
31 : : private slots:
32 : : void testExtractLinestrings();
33 : : void testCircleClockwise_data();
34 : : void testCircleClockwise();
35 : : void testAngleOnCircle_data();
36 : : void testAngleOnCircle();
37 : : void testLeftOfLine_data();
38 : : void testLeftOfLine();
39 : : void testSegmentMidPoint_data();
40 : : void testSegmentMidPoint();
41 : : void testSegmentMidPointCenter();
42 : : void testCircleLength_data();
43 : : void testCircleLength();
44 : : void testNormalizedAngle_data();
45 : : void testNormalizedAngle();
46 : : void testLineAngle_data();
47 : : void testLineAngle();
48 : : void testLinePerpendicularAngle_data();
49 : : void testLinePerpendicularAngle();
50 : : void testAverageAngle_data();
51 : : void testAverageAngle();
52 : : void testDistanceToVertex();
53 : : void testVerticesAtDistance();
54 : : void testCircleCenterRadius_data();
55 : : void testCircleCenterRadius();
56 : : void testSqrDistToLine();
57 : : void testAngleThreePoints();
58 : : void testMidPoint();
59 : : void testGradient();
60 : : void testCoefficients();
61 : : void testPerpendicularSegment();
62 : : void testClosestPoint();
63 : : void testlinesIntersection3D();
64 : : void testSegmentIntersection();
65 : : void testLineCircleIntersection();
66 : : void testCircleCircleIntersection();
67 : : void testTangentPointAndCircle();
68 : : void testCircleCircleOuterTangents();
69 : : void testCircleCircleInnerTangents();
70 : : void testGml();
71 : : void testInterpolatePointOnLineQgsPoint();
72 : : void testInterpolatePointOnLine();
73 : : void testInterpolatePointOnLineByValue();
74 : : void testPointOnLineWithDistance();
75 : : void interpolatePointOnArc();
76 : : void testSegmentizeArcHalfCircle();
77 : : void testSegmentizeArcHalfCircleOtherDirection();
78 : : void testSegmentizeArcFullCircle();
79 : : void testTriangleArea_data();
80 : : void testTriangleArea();
81 : : void testWeightedPointInTriangle_data();
82 : : void testWeightedPointInTriangle();
83 : : void testPointContinuesArc();
84 : : void testBisector();
85 : : void testAngleBisector();
86 : : void testPerpendicularOffsetPoint();
87 : : void testClosestSideOfRectangle();
88 : : };
89 : :
90 : :
91 : 4 : QString TestQgsGeometryUtils::elemToString( const QDomElement &elem ) const
92 : : {
93 : 4 : QString s;
94 : 4 : QTextStream stream( &s );
95 : 4 : elem.save( stream, -1 );
96 : :
97 : 4 : return s;
98 : 4 : }
99 : :
100 : 1 : void TestQgsGeometryUtils::testExtractLinestrings()
101 : : {
102 : 1 : QgsLineString *outerRing1 = new QgsLineString();
103 : 1 : outerRing1->setPoints( QVector<QgsPoint>() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) );
104 : 1 : QgsPolygon *polygon1 = new QgsPolygon();
105 : 1 : polygon1->setExteriorRing( outerRing1 );
106 : :
107 : 1 : QgsLineString *outerRing2 = new QgsLineString();
108 : 1 : outerRing2->setPoints( QVector<QgsPoint>() << QgsPoint( 10, 10 ) << QgsPoint( 10, 20 ) << QgsPoint( 20, 20 ) << QgsPoint( 20, 10 ) << QgsPoint( 10, 10 ) );
109 : 1 : QgsPolygon *polygon2 = new QgsPolygon();
110 : 1 : polygon2->setExteriorRing( outerRing2 );
111 : :
112 : 1 : QgsLineString *innerRing2 = new QgsLineString();
113 : 1 : innerRing2->setPoints( QVector<QgsPoint>() << QgsPoint( 14, 14 ) << QgsPoint( 14, 16 ) << QgsPoint( 16, 16 ) << QgsPoint( 16, 14 ) << QgsPoint( 14, 14 ) );
114 : 1 : polygon2->setInteriorRings( QVector<QgsCurve *>() << innerRing2 );
115 : :
116 : 1 : QgsMultiPolygon mpg;
117 : 1 : mpg.addGeometry( polygon1 );
118 : 1 : mpg.addGeometry( polygon2 );
119 : :
120 : 1 : QVector<QgsLineString *> linestrings = QgsGeometryUtils::extractLineStrings( &mpg );
121 : 1 : QCOMPARE( linestrings.count(), 3 );
122 : 1 : qDeleteAll( linestrings );
123 : 1 : }
124 : :
125 : 1 : void TestQgsGeometryUtils::testLeftOfLine_data()
126 : : {
127 : 1 : QTest::addColumn<double>( "x" );
128 : 1 : QTest::addColumn<double>( "y" );
129 : 1 : QTest::addColumn<double>( "x1" );
130 : 1 : QTest::addColumn<double>( "y1" );
131 : 1 : QTest::addColumn<double>( "x2" );
132 : 1 : QTest::addColumn<double>( "y2" );
133 : 1 : QTest::addColumn<bool>( "expectedResult" );
134 : :
135 : 1 : QTest::newRow( "leftOfLine1" ) << 0.0 << 0.0 << 0.0 << 2.0 << 1.0 << 0.0 << false;
136 : 1 : QTest::newRow( "leftOfLine1" ) << 0.0 << 0.0 << 1.0 << 0.0 << 0.0 << 2.0 << true;
137 : 1 : }
138 : :
139 : 2 : void TestQgsGeometryUtils::testLeftOfLine()
140 : : {
141 : 2 : QFETCH( double, x );
142 : 2 : QFETCH( double, y );
143 : 2 : QFETCH( double, x1 );
144 : 2 : QFETCH( double, y1 );
145 : 2 : QFETCH( double, x2 );
146 : 2 : QFETCH( double, y2 );
147 : 2 : QFETCH( bool, expectedResult );
148 : :
149 : 2 : QCOMPARE( QgsGeometryUtils::leftOfLine( x, y, x1, y1, x2, y2 ) < 0, expectedResult );
150 : 2 : }
151 : :
152 : 1 : void TestQgsGeometryUtils::testCircleClockwise_data()
153 : : {
154 : 1 : QTest::addColumn<double>( "angle1" );
155 : 1 : QTest::addColumn<double>( "angle2" );
156 : 1 : QTest::addColumn<double>( "angle3" );
157 : 1 : QTest::addColumn<bool>( "expectedResult" );
158 : :
159 : 1 : QTest::newRow( "circleClockwise1" ) << 10.0 << 300.0 << 270.0 << true;
160 : 1 : QTest::newRow( "circleClockwise2" ) << 270.0 << 300.0 << 10.0 << false;
161 : 1 : QTest::newRow( "circleClockwise3" ) << 260.0 << 245.0 << 243.0 << true;
162 : 1 : QTest::newRow( "circleClockwise4" ) << -90.0 << 0.0 << 90.0 << false;
163 : 1 : QTest::newRow( "circleClockwise5" ) << 0.0 << 90.0 << 180.0 << false;
164 : 1 : }
165 : :
166 : 5 : void TestQgsGeometryUtils::testCircleClockwise()
167 : : {
168 : 5 : QFETCH( double, angle1 );
169 : 5 : QFETCH( double, angle2 );
170 : 5 : QFETCH( double, angle3 );
171 : 5 : QFETCH( bool, expectedResult );
172 : :
173 : 5 : QCOMPARE( QgsGeometryUtils::circleClockwise( angle1, angle2, angle3 ), expectedResult );
174 : 5 : }
175 : :
176 : 1 : void TestQgsGeometryUtils::testAngleOnCircle_data()
177 : : {
178 : 1 : QTest::addColumn<double>( "angle" );
179 : 1 : QTest::addColumn<double>( "angle1" );
180 : 1 : QTest::addColumn<double>( "angle2" );
181 : 1 : QTest::addColumn<double>( "angle3" );
182 : 1 : QTest::addColumn<bool>( "expectedResult" );
183 : :
184 : 1 : QTest::newRow( "angleOnCircle1" ) << 280.0 << 10.0 << 300.0 << 270.0 << true;
185 : 1 : QTest::newRow( "angleOnCircle2" ) << 235.0 << 10.0 << 300.0 << 270.0 << false;
186 : 1 : QTest::newRow( "angleOnCircle3" ) << 280.0 << 45.0 << 175.0 << 35.0 << true;
187 : 1 : QTest::newRow( "angleOnCircle4" ) << 40.0 << 45.0 << 175.0 << 35.0 << false;
188 : 1 : QTest::newRow( "angleOnCircle5" ) << 335.0 << 350.0 << 175.0 << 320.0 << false;
189 : 1 : QTest::newRow( "angleOnCircle6" ) << 170.0 << 140.0 << 355.0 << 205.0 << false;
190 : 1 : }
191 : :
192 : 6 : void TestQgsGeometryUtils::testAngleOnCircle()
193 : : {
194 : 6 : QFETCH( double, angle );
195 : 6 : QFETCH( double, angle1 );
196 : 6 : QFETCH( double, angle2 );
197 : 6 : QFETCH( double, angle3 );
198 : 6 : QFETCH( bool, expectedResult );
199 : :
200 : 6 : QCOMPARE( QgsGeometryUtils::angleOnCircle( angle, angle1, angle2, angle3 ), expectedResult );
201 : 6 : }
202 : :
203 : 1 : void TestQgsGeometryUtils::testSegmentMidPoint_data()
204 : : {
205 : 1 : QTest::addColumn<double>( "pt1x" );
206 : 1 : QTest::addColumn<double>( "pt1y" );
207 : 1 : QTest::addColumn<double>( "pt2x" );
208 : 1 : QTest::addColumn<double>( "pt2y" );
209 : 1 : QTest::addColumn<double>( "radius" );
210 : 1 : QTest::addColumn<double>( "mouseX" );
211 : 1 : QTest::addColumn<double>( "mouseY" );
212 : 1 : QTest::addColumn<double>( "expectedX" );
213 : 1 : QTest::addColumn<double>( "expectedY" );
214 : :
215 : 1 : QTest::newRow( "testSegmentMidPoint1" ) << 0.0 << 0.0 << 1.0 << 0.0 << 0.5 << 1.0 << 0.0 << 0.5 << 0.5;
216 : 1 : }
217 : :
218 : 1 : void TestQgsGeometryUtils::testSegmentMidPoint()
219 : : {
220 : 1 : QFETCH( double, pt1x );
221 : 1 : QFETCH( double, pt1y );
222 : 1 : QFETCH( double, pt2x );
223 : 1 : QFETCH( double, pt2y );
224 : 1 : QFETCH( double, radius );
225 : 1 : QFETCH( double, mouseX );
226 : 1 : QFETCH( double, mouseY );
227 : 1 : QFETCH( double, expectedX );
228 : 1 : QFETCH( double, expectedY );
229 : :
230 : 1 : QgsPoint midPoint;
231 : 2 : bool ok = QgsGeometryUtils::segmentMidPoint( QgsPoint( pt1x, pt1y ), QgsPoint( pt2x, pt2y ),
232 : 1 : midPoint, radius, QgsPoint( mouseX, mouseY ) );
233 : :
234 : 1 : QVERIFY( ok );
235 : 1 : QGSCOMPARENEAR( midPoint.x(), expectedX, 4 * std::numeric_limits<double>::epsilon() );
236 : 1 : QGSCOMPARENEAR( midPoint.y(), expectedY, 4 * std::numeric_limits<double>::epsilon() );
237 : 1 : }
238 : :
239 : 1 : void TestQgsGeometryUtils::testSegmentMidPointCenter()
240 : : {
241 : 1 : QgsPoint mid = QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21 ), QgsPoint( 11, 20 ), QgsPoint( 10, 20 ) );
242 : 1 : QGSCOMPARENEAR( mid.x(), 10.7071, 0.0001 );
243 : 1 : QGSCOMPARENEAR( mid.y(), 20.7071, 0.0001 );
244 : 1 : QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21 ), QgsPoint( 11, 20 ), QgsPoint( 10, 20 ), false );
245 : 1 : QGSCOMPARENEAR( mid.x(), 10.7071, 0.0001 );
246 : 1 : QGSCOMPARENEAR( mid.y(), 20.7071, 0.0001 );
247 : 1 : mid = QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21 ), QgsPoint( 9, 20 ), QgsPoint( 10, 20 ) );
248 : 1 : QGSCOMPARENEAR( mid.x(), 9.292893, 0.0001 );
249 : 1 : QGSCOMPARENEAR( mid.y(), 20.7071, 0.0001 );
250 : 1 : mid = QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21 ), QgsPoint( 10, 19 ), QgsPoint( 10, 20 ) );
251 : 1 : QGSCOMPARENEAR( mid.x(), 11.0, 0.0001 );
252 : 1 : QGSCOMPARENEAR( mid.y(), 20.0, 0.0001 );
253 : 1 : mid = QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21 ), QgsPoint( 10, 21 ), QgsPoint( 10, 20 ) );
254 : 1 : QGSCOMPARENEAR( mid.x(), 10.0, 0.0001 );
255 : 1 : QGSCOMPARENEAR( mid.y(), 21.0, 0.0001 );
256 : 1 : mid = QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21 ), QgsPoint( 10, 21 ), QgsPoint( 10, 21 ) );
257 : 1 : QGSCOMPARENEAR( mid.x(), 10.0, 0.0001 );
258 : 1 : QGSCOMPARENEAR( mid.y(), 21.0, 0.0001 );
259 : 1 : mid = QgsGeometryUtils::segmentMidPointFromCenter( QgsPoint( 10, 21, 3, 4 ), QgsPoint( 11, 20, 5, 6 ), QgsPoint( 10, 20, 7, 8 ) );
260 : 1 : QGSCOMPARENEAR( mid.x(), 10.7071, 0.0001 );
261 : 1 : QGSCOMPARENEAR( mid.y(), 20.7071, 0.0001 );
262 : 1 : QCOMPARE( mid.z(), 7.0 );
263 : 1 : QCOMPARE( mid.m(), 8.0 );
264 : 1 : }
265 : :
266 : 1 : void TestQgsGeometryUtils::testCircleLength_data()
267 : : {
268 : 1 : QTest::addColumn<double>( "x1" );
269 : 1 : QTest::addColumn<double>( "y1" );
270 : 1 : QTest::addColumn<double>( "x2" );
271 : 1 : QTest::addColumn<double>( "y2" );
272 : 1 : QTest::addColumn<double>( "x3" );
273 : 1 : QTest::addColumn<double>( "y3" );
274 : 1 : QTest::addColumn<double>( "expected" );
275 : :
276 : 1 : QTest::newRow( "circleLength1" ) << 1.0 << 0.0 << -1.0 << 0.0 << 0.0 << 1.0 << ( 2 * M_PI * 0.75 );
277 : 1 : QTest::newRow( "circleLength2" ) << 0.0 << 1.0 << -1.0 << 0.0 << 1.0 << 0.0 << ( 2 * M_PI * 0.75 );
278 : 1 : }
279 : :
280 : 2 : void TestQgsGeometryUtils::testCircleLength()
281 : : {
282 : 2 : QFETCH( double, x1 );
283 : 2 : QFETCH( double, y1 );
284 : 2 : QFETCH( double, x2 );
285 : 2 : QFETCH( double, y2 );
286 : 2 : QFETCH( double, x3 );
287 : 2 : QFETCH( double, y3 );
288 : 2 : QFETCH( double, expected );
289 : :
290 : 2 : QGSCOMPARENEAR( expected, QgsGeometryUtils::circleLength( x1, y1, x2, y2, x3, y3 ), 4 * std::numeric_limits<double>::epsilon() );
291 : 2 : }
292 : :
293 : 1 : void TestQgsGeometryUtils::testNormalizedAngle_data()
294 : : {
295 : 1 : QTest::addColumn<double>( "input" );
296 : 1 : QTest::addColumn<double>( "expected" );
297 : 1 : QTest::newRow( "normalizedAngle 0" ) << 0.0 << 0.0;
298 : 1 : QTest::newRow( "normalizedAngle 1.5708" ) << 1.5708 << 1.5708;
299 : 1 : QTest::newRow( "normalizedAngle 3.1416" ) << 3.1416 << 3.1416;
300 : 1 : QTest::newRow( "normalizedAngle 4.7124" ) << 4.7124 << 4.7124;
301 : 1 : QTest::newRow( "normalizedAngle 2 * M_PI" ) << 2 * M_PI << 0.0;
302 : 1 : QTest::newRow( "normalizedAngle 6.80678" ) << 6.80678 << 0.5236;
303 : 1 : QTest::newRow( "normalizedAngle 12.5664" ) << 12.5664 << 0.0;
304 : 1 : QTest::newRow( "normalizedAngle 12.7409" ) << 12.7409 << 0.174533;
305 : 1 : QTest::newRow( "normalizedAngle -0.174533" ) << -0.174533 << 6.10865;
306 : 1 : QTest::newRow( "normalizedAngle -6.28318" ) << -6.28318 << 0.0;
307 : 1 : QTest::newRow( "normalizedAngle -6.45772" ) << -6.45772 << 6.10865;
308 : 1 : QTest::newRow( "normalizedAngle -13.2645" ) << -13.2645 << 5.58505;
309 : 1 : }
310 : :
311 : 12 : void TestQgsGeometryUtils::testNormalizedAngle()
312 : : {
313 : 12 : QFETCH( double, input );
314 : 12 : QFETCH( double, expected );
315 : 12 : QGSCOMPARENEAR( expected, QgsGeometryUtils::normalizedAngle( input ), 0.0001 );
316 : 12 : }
317 : :
318 : 1 : void TestQgsGeometryUtils::testLineAngle_data()
319 : : {
320 : 1 : QTest::addColumn<double>( "x1" );
321 : 1 : QTest::addColumn<double>( "y1" );
322 : 1 : QTest::addColumn<double>( "x2" );
323 : 1 : QTest::addColumn<double>( "y2" );
324 : 1 : QTest::addColumn<double>( "expected" );
325 : :
326 : 1 : QTest::newRow( "lineAngle undefined" ) << 0.0 << 0.0 << 0.0 << 0.0 << -99999.0; //value is unimportant, we just don't want a crash
327 : 1 : QTest::newRow( "lineAngle1" ) << 0.0 << 0.0 << 10.0 << 10.0 << 45.0;
328 : 1 : QTest::newRow( "lineAngle2" ) << 0.0 << 0.0 << 10.0 << 0.0 << 90.0;
329 : 1 : QTest::newRow( "lineAngle3" ) << 0.0 << 0.0 << 10.0 << -10.0 << 135.0;
330 : 1 : QTest::newRow( "lineAngle4" ) << 0.0 << 0.0 << 0.0 << -10.0 << 180.0;
331 : 1 : QTest::newRow( "lineAngle5" ) << 0.0 << 0.0 << -10.0 << -10.0 << 225.0;
332 : 1 : QTest::newRow( "lineAngle6" ) << 0.0 << 0.0 << -10.0 << 0.0 << 270.0;
333 : 1 : QTest::newRow( "lineAngle7" ) << 0.0 << 0.0 << -10.0 << 10.0 << 315.0;
334 : 1 : QTest::newRow( "lineAngle8" ) << 0.0 << 0.0 << 0.0 << 10.0 << 0.0;
335 : 1 : }
336 : :
337 : 9 : void TestQgsGeometryUtils::testLineAngle()
338 : : {
339 : 9 : QFETCH( double, x1 );
340 : 9 : QFETCH( double, y1 );
341 : 9 : QFETCH( double, x2 );
342 : 9 : QFETCH( double, y2 );
343 : 9 : QFETCH( double, expected );
344 : :
345 : 9 : double lineAngle = QgsGeometryUtils::lineAngle( x1, y1, x2, y2 ) * 180 / M_PI;
346 : 9 : if ( expected > -99999 )
347 : 8 : QGSCOMPARENEAR( lineAngle, expected, 4 * std::numeric_limits<double>::epsilon() );
348 : 9 : }
349 : :
350 : 1 : void TestQgsGeometryUtils::testLinePerpendicularAngle_data()
351 : : {
352 : 1 : QTest::addColumn<double>( "x1" );
353 : 1 : QTest::addColumn<double>( "y1" );
354 : 1 : QTest::addColumn<double>( "x2" );
355 : 1 : QTest::addColumn<double>( "y2" );
356 : 1 : QTest::addColumn<double>( "expected" );
357 : :
358 : 1 : QTest::newRow( "linePerpendicularAngle undefined" ) << 0.0 << 0.0 << 0.0 << 0.0 << -99999.0; //value is unimportant, we just don't want a crash
359 : 1 : QTest::newRow( "linePerpendicularAngle1" ) << 0.0 << 0.0 << 10.0 << 10.0 << 135.0;
360 : 1 : QTest::newRow( "linePerpendicularAngle2" ) << 0.0 << 0.0 << 10.0 << 0.0 << 180.0;
361 : 1 : QTest::newRow( "linePerpendicularAngle3" ) << 0.0 << 0.0 << 10.0 << -10.0 << 225.0;
362 : 1 : QTest::newRow( "linePerpendicularAngle4" ) << 0.0 << 0.0 << 0.0 << -10.0 << 270.0;
363 : 1 : QTest::newRow( "linePerpendicularAngle5" ) << 0.0 << 0.0 << -10.0 << -10.0 << 315.0;
364 : 1 : QTest::newRow( "linePerpendicularAngle6" ) << 0.0 << 0.0 << -10.0 << 0.0 << 0.0;
365 : 1 : QTest::newRow( "linePerpendicularAngle7" ) << 0.0 << 0.0 << -10.0 << 10.0 << 45.0;
366 : 1 : QTest::newRow( "linePerpendicularAngle8" ) << 0.0 << 0.0 << 0.0 << 10.0 << 90.0;
367 : 1 : }
368 : :
369 : 9 : void TestQgsGeometryUtils::testLinePerpendicularAngle()
370 : : {
371 : 9 : QFETCH( double, x1 );
372 : 9 : QFETCH( double, y1 );
373 : 9 : QFETCH( double, x2 );
374 : 9 : QFETCH( double, y2 );
375 : 9 : QFETCH( double, expected );
376 : :
377 : 9 : double pAngle = QgsGeometryUtils::linePerpendicularAngle( x1, y1, x2, y2 ) * 180 / M_PI;
378 : 9 : if ( expected > -99999 )
379 : 8 : QGSCOMPARENEAR( pAngle, expected, 0.01 );
380 : 9 : }
381 : :
382 : 1 : void TestQgsGeometryUtils::testAverageAngle_data()
383 : : {
384 : 1 : QTest::addColumn<double>( "angle1" );
385 : 1 : QTest::addColumn<double>( "angle2" );
386 : 1 : QTest::addColumn<double>( "expected" );
387 : :
388 : 1 : QTest::newRow( "testAverageAngle1" ) << 0.0 << 0.0 << 0.0;
389 : 1 : QTest::newRow( "testAverageAngle2" ) << 0.0 << 360.0 << 0.0;
390 : 1 : QTest::newRow( "testAverageAngle3" ) << 0.0 << 720.0 << 0.0;
391 : 1 : QTest::newRow( "testAverageAngle4" ) << 360.0 << 0.0 << 0.0;
392 : 1 : QTest::newRow( "testAverageAngle5" ) << -360.0 << 0.0 << 0.0;
393 : 1 : QTest::newRow( "testAverageAngle6" ) << -360.0 << -360.0 << 0.0;
394 : 1 : QTest::newRow( "testAverageAngle7" ) << 0.0 << 180.0 << 90.0;
395 : 1 : QTest::newRow( "testAverageAngle8" ) << 0.0 << -179.999999999999 << 270.0;
396 : 1 : QTest::newRow( "testAverageAngle9" ) << 315.0 << 270.0 << 292.5;
397 : 1 : QTest::newRow( "testAverageAngle10" ) << 45.0 << 135.0 << 90.0;
398 : 1 : QTest::newRow( "testAverageAngle11" ) << 315.0 << 45.0 << 0.0;
399 : 1 : QTest::newRow( "testAverageAngle12" ) << 45.0 << 315.0 << 0.0;
400 : 1 : QTest::newRow( "testAverageAngle13" ) << 315.0 << 270.0 << 292.5;
401 : 1 : QTest::newRow( "testAverageAngle14" ) << 140.0 << 240.0 << 190.0;
402 : 1 : QTest::newRow( "testAverageAngle15" ) << 240.0 << 140.0 << 190.0;
403 : 1 : }
404 : :
405 : 15 : void TestQgsGeometryUtils::testAverageAngle()
406 : : {
407 : 15 : QFETCH( double, angle1 );
408 : 15 : QFETCH( double, angle2 );
409 : 15 : QFETCH( double, expected );
410 : :
411 : 15 : double averageAngle = QgsGeometryUtils::averageAngle( angle1 * M_PI / 180.0, angle2 * M_PI / 180.0 ) * 180.0 / M_PI;
412 : 15 : QGSCOMPARENEAR( averageAngle, expected, 0.0000000001 );
413 : 15 : }
414 : :
415 : 1 : void TestQgsGeometryUtils::testDistanceToVertex()
416 : : {
417 : : //test with linestring
418 : 1 : QgsLineString *outerRing1 = new QgsLineString();
419 : 1 : outerRing1->setPoints( QVector<QgsPoint>() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) );
420 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 0, 0 ) ), 0.0 );
421 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 0, 1 ) ), 1.0 );
422 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 0, 2 ) ), 2.0 );
423 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 0, 3 ) ), 3.0 );
424 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 0, 4 ) ), 4.0 );
425 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 0, 5 ) ), -1.0 );
426 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( *outerRing1, QgsVertexId( 0, 1, 1 ) ), -1.0 );
427 : :
428 : : //test with polygon
429 : 1 : QgsPolygon polygon1;
430 : 1 : polygon1.setExteriorRing( outerRing1 );
431 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 0, 0 ) ), 0.0 );
432 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 0, 1 ) ), 1.0 );
433 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 0, 2 ) ), 2.0 );
434 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 0, 3 ) ), 3.0 );
435 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 0, 4 ) ), 4.0 );
436 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 0, 5 ) ), -1.0 );
437 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( polygon1, QgsVertexId( 0, 1, 1 ) ), -1.0 );
438 : :
439 : : //test with point
440 : 1 : QgsPoint point( 1, 2 );
441 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( point, QgsVertexId( 0, 0, 0 ) ), 0.0 );
442 : 1 : QCOMPARE( QgsGeometryUtils::distanceToVertex( point, QgsVertexId( 0, 0, 1 ) ), -1.0 );
443 : 1 : }
444 : :
445 : 1 : void TestQgsGeometryUtils::testVerticesAtDistance()
446 : : {
447 : : //test with linestring
448 : 1 : QgsLineString *outerRing1 = new QgsLineString();
449 : 1 : QgsVertexId previous;
450 : 1 : QgsVertexId next;
451 : 1 : QVERIFY( !QgsGeometryUtils::verticesAtDistance( *outerRing1, .5, previous, next ) );
452 : :
453 : 1 : outerRing1->setPoints( QVector<QgsPoint>() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 3, 1 ) );
454 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, .5, previous, next ) );
455 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
456 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
457 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 1.5, previous, next ) );
458 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
459 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
460 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 2.5, previous, next ) );
461 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
462 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
463 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 3.5, previous, next ) );
464 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
465 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
466 : 1 : QVERIFY( ! QgsGeometryUtils::verticesAtDistance( *outerRing1, 4.5, previous, next ) );
467 : :
468 : : // test exact hits
469 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 0, previous, next ) );
470 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
471 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 0 ) );
472 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 1, previous, next ) );
473 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
474 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
475 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 2, previous, next ) );
476 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
477 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
478 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 3, previous, next ) );
479 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
480 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
481 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *outerRing1, 4, previous, next ) );
482 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
483 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
484 : 1 : delete outerRing1;
485 : :
486 : : // test closed line
487 : 1 : QgsLineString *closedRing1 = new QgsLineString();
488 : 1 : closedRing1->setPoints( QVector<QgsPoint>() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) );
489 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *closedRing1, 0, previous, next ) );
490 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
491 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 0 ) );
492 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( *closedRing1, 4, previous, next ) );
493 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
494 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
495 : :
496 : : // test with polygon
497 : 1 : QgsPolygon polygon1;
498 : 1 : polygon1.setExteriorRing( closedRing1 );
499 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, .5, previous, next ) );
500 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
501 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
502 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 1.5, previous, next ) );
503 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 1 ) );
504 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 2 ) );
505 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 2.5, previous, next ) );
506 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 2 ) );
507 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 3 ) );
508 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 3.5, previous, next ) );
509 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 3 ) );
510 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
511 : 1 : QVERIFY( ! QgsGeometryUtils::verticesAtDistance( polygon1, 4.5, previous, next ) );
512 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 0, previous, next ) );
513 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
514 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 0 ) );
515 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 4, previous, next ) );
516 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
517 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
518 : :
519 : : // with ring
520 : 1 : QgsLineString *ring1 = new QgsLineString();
521 : 1 : ring1->setPoints( QVector<QgsPoint>() << QgsPoint( 1.1, 1.1 ) << QgsPoint( 1.1, 1.2 ) << QgsPoint( 1.2, 1.2 ) << QgsPoint( 1.2, 1.1 ) << QgsPoint( 1.1, 1.1 ) );
522 : 1 : polygon1.addInteriorRing( ring1 );
523 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 4, previous, next ) );
524 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 4 ) );
525 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 4 ) );
526 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 4.01, previous, next ) );
527 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 0 ) );
528 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 1 ) );
529 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( polygon1, 4.11, previous, next ) );
530 : 1 : QCOMPARE( previous, QgsVertexId( 0, 1, 1 ) );
531 : 1 : QCOMPARE( next, QgsVertexId( 0, 1, 2 ) );
532 : :
533 : : // multipolygon
534 : 1 : outerRing1 = new QgsLineString();
535 : 1 : outerRing1->setPoints( QVector<QgsPoint>() << QgsPoint( 1, 1 ) << QgsPoint( 1, 2 ) << QgsPoint( 2, 2 ) << QgsPoint( 2, 1 ) << QgsPoint( 1, 1 ) );
536 : 1 : QgsPolygon *polygon2 = new QgsPolygon();
537 : 1 : polygon2->setExteriorRing( outerRing1 );
538 : :
539 : 1 : QgsLineString *outerRing2 = new QgsLineString();
540 : 1 : outerRing2->setPoints( QVector<QgsPoint>() << QgsPoint( 10, 10 ) << QgsPoint( 10, 20 ) << QgsPoint( 20, 20 ) << QgsPoint( 20, 10 ) << QgsPoint( 10, 10 ) );
541 : 1 : QgsPolygon *polygon3 = new QgsPolygon();
542 : 1 : polygon3->setExteriorRing( outerRing2 );
543 : :
544 : 1 : QgsLineString *innerRing2 = new QgsLineString();
545 : 1 : innerRing2->setPoints( QVector<QgsPoint>() << QgsPoint( 14, 14 ) << QgsPoint( 14, 16 ) << QgsPoint( 16, 16 ) << QgsPoint( 16, 14 ) << QgsPoint( 14, 14 ) );
546 : 1 : polygon3->setInteriorRings( QVector<QgsCurve *>() << innerRing2 );
547 : :
548 : 1 : QgsMultiPolygon mpg;
549 : 1 : mpg.addGeometry( polygon2 );
550 : 1 : mpg.addGeometry( polygon3 );
551 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( mpg, 0.1, previous, next ) );
552 : 1 : QCOMPARE( previous, QgsVertexId( 0, 0, 0 ) );
553 : 1 : QCOMPARE( next, QgsVertexId( 0, 0, 1 ) );
554 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( mpg, 5, previous, next ) );
555 : 1 : QCOMPARE( previous, QgsVertexId( 1, 0, 0 ) );
556 : 1 : QCOMPARE( next, QgsVertexId( 1, 0, 1 ) );
557 : 1 : QVERIFY( QgsGeometryUtils::verticesAtDistance( mpg, 45, previous, next ) );
558 : 1 : QCOMPARE( previous, QgsVertexId( 1, 1, 0 ) );
559 : 1 : QCOMPARE( next, QgsVertexId( 1, 1, 1 ) );
560 : :
561 : : //test with point
562 : 1 : QgsPoint point( 1, 2 );
563 : 1 : QVERIFY( !QgsGeometryUtils::verticesAtDistance( point, .5, previous, next ) );
564 : 1 : }
565 : :
566 : 1 : void TestQgsGeometryUtils::testCircleCenterRadius_data()
567 : : {
568 : 1 : QTest::addColumn<double>( "x1" );
569 : 1 : QTest::addColumn<double>( "y1" );
570 : 1 : QTest::addColumn<double>( "x2" );
571 : 1 : QTest::addColumn<double>( "y2" );
572 : 1 : QTest::addColumn<double>( "x3" );
573 : 1 : QTest::addColumn<double>( "y3" );
574 : 1 : QTest::addColumn<double>( "expectedRadius" );
575 : 1 : QTest::addColumn<double>( "expectedCenterX" );
576 : 1 : QTest::addColumn<double>( "expectedCenterY" );
577 : :
578 : 1 : QTest::newRow( "circleCenterRadius1" ) << 1.0 << 1.0 << 5.0 << 7.0 << 1.0 << 1.0 << std::sqrt( 13.0 ) << 3.0 << 4.0;
579 : 1 : QTest::newRow( "circleCenterRadius1" ) << 0.0 << 2.0 << 2.0 << 2.0 << 0.0 << 2.0 << 1.0 << 1.0 << 2.0;
580 : 1 : }
581 : :
582 : 2 : void TestQgsGeometryUtils::testCircleCenterRadius()
583 : : {
584 : 2 : QFETCH( double, x1 );
585 : 2 : QFETCH( double, y1 );
586 : 2 : QFETCH( double, x2 );
587 : 2 : QFETCH( double, y2 );
588 : 2 : QFETCH( double, x3 );
589 : 2 : QFETCH( double, y3 );
590 : 2 : QFETCH( double, expectedRadius );
591 : 2 : QFETCH( double, expectedCenterX );
592 : 2 : QFETCH( double, expectedCenterY );
593 : :
594 : : double radius, centerX, centerY;
595 : 2 : QgsGeometryUtils::circleCenterRadius( QgsPoint( x1, y1 ), QgsPoint( x2, y2 ), QgsPoint( x3, y3 ), radius, centerX, centerY );
596 : 2 : QGSCOMPARENEAR( expectedRadius, radius, 4 * std::numeric_limits<double>::epsilon() );
597 : 2 : QGSCOMPARENEAR( expectedCenterX, centerX, 4 * std::numeric_limits<double>::epsilon() );
598 : 2 : QGSCOMPARENEAR( expectedCenterY, centerY, 4 * std::numeric_limits<double>::epsilon() );
599 : 2 : }
600 : :
601 : : //QgsGeometryUtils::sqrDistToLine
602 : 1 : void TestQgsGeometryUtils::testSqrDistToLine()
603 : : {
604 : :
605 : : // See https://github.com/qgis/QGIS/issues/21967#issuecomment-495853991
606 : 1 : QgsPointXY qp( 771938, 6.95593e+06 );
607 : 1 : QgsPointXY p1( 771946, 6.95593e+06 );
608 : 1 : QgsPointXY p2( 771904, 6.95595e+06 );
609 : 1 : double rx = 0, ry = 0;
610 : 1 : double epsilon = 1e-18;
611 : 2 : double sqrDist = QgsGeometryUtils::sqrDistToLine( qp.x(), qp.y(),
612 : 1 : p1.x(), p1.y(),
613 : 1 : p2.x(), p2.y(),
614 : 1 : rx, ry, epsilon );
615 : 1 : QGSCOMPARENEAR( sqrDist, 11.83, 0.01 );
616 : 1 : }
617 : :
618 : 1 : void TestQgsGeometryUtils::testAngleThreePoints()
619 : : {
620 : 1 : QgsPointXY p1( 0, 0 );
621 : 1 : QgsPointXY p2( 1, 0 );
622 : 1 : QgsPointXY p3( 1, 1 );
623 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() ), M_PI / 2.0, 0.00000001 );
624 : 1 : p3 = QgsPointXY( 1, -1 );
625 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() ), 3 * M_PI / 2.0, 0.00000001 );
626 : 1 : p3 = QgsPointXY( 2, 0 );
627 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() ), M_PI, 0.00000001 );
628 : 1 : p3 = QgsPointXY( 0, 0 );
629 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() ), 0.0, 0.00000001 );
630 : 1 : p3 = QgsPointXY( 1, 0 );
631 : : //undefined, but want no crash
632 : 1 : ( void )QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() );
633 : 1 : p2 = QgsPointXY( 0, 0 );
634 : 1 : ( void )QgsGeometryUtils::angleBetweenThreePoints( p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y() );
635 : 1 : }
636 : :
637 : 1 : void TestQgsGeometryUtils::testMidPoint()
638 : : {
639 : 1 : QgsPoint p1( 4, 6 );
640 : 1 : QCOMPARE( QgsGeometryUtils::midpoint( p1, QgsPoint( 2, 2 ) ), QgsPoint( 3, 4 ) );
641 : 1 : QCOMPARE( QgsGeometryUtils::midpoint( QgsPoint( 4, 6, 0 ), QgsPoint( QgsWkbTypes::PointZ, 2, 2, 2 ) ), QgsPoint( QgsWkbTypes::PointZ, 3, 4, 1 ) );
642 : 1 : QCOMPARE( QgsGeometryUtils::midpoint( QgsPoint( QgsWkbTypes::PointM, 4, 6, 0, 0 ), QgsPoint( QgsWkbTypes::PointM, 2, 2, 0, 2 ) ), QgsPoint( QgsWkbTypes::PointM, 3, 4, 0, 1 ) );
643 : 1 : QCOMPARE( QgsGeometryUtils::midpoint( QgsPoint( QgsWkbTypes::PointZM, 4, 6, 0, 0 ), QgsPoint( QgsWkbTypes::PointZM, 2, 2, 2, 2 ) ), QgsPoint( QgsWkbTypes::PointZM, 3, 4, 1, 1 ) );
644 : 1 : }
645 : :
646 : 1 : void TestQgsGeometryUtils::testGradient()
647 : : {
648 : 1 : QVERIFY( QgsGeometryUtils::gradient( QgsPoint( 4, 6 ), QgsPoint( 4, 8 ) ) == INFINITY );
649 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::gradient( QgsPoint( 2, 8 ), QgsPoint( 3, 20 ) ), 12, 0.00000001 );
650 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::gradient( QgsPoint( 2, -88 ), QgsPoint( 4, -4 ) ), 42, 0.00000001 );
651 : 1 : QGSCOMPARENEAR( QgsGeometryUtils::gradient( QgsPoint( 4, 6 ), QgsPoint( 8, 6 ) ), 0, 0.00000001 );
652 : 1 : }
653 : :
654 : 1 : void TestQgsGeometryUtils::testCoefficients()
655 : : {
656 : : double a, b, c;
657 : :
658 : : // pt1.x == pt2.x
659 : 1 : QgsGeometryUtils::coefficients( QgsPoint( 4, 6 ), QgsPoint( 4, 8 ), a, b, c );
660 : 1 : QGSCOMPARENEAR( a, 1, 0.00000001 );
661 : 1 : QGSCOMPARENEAR( b, 0, 0.00000001 );
662 : 1 : QGSCOMPARENEAR( c, -4, 0.00000001 );
663 : :
664 : : // pt1.y == pt2.y
665 : 1 : QgsGeometryUtils::coefficients( QgsPoint( 6, 4 ), QgsPoint( 8, 4 ), a, b, c );
666 : 1 : QGSCOMPARENEAR( a, 0, 0.00000001 );
667 : 1 : QGSCOMPARENEAR( b, 1, 0.00000001 );
668 : 1 : QGSCOMPARENEAR( c, -4, 0.00000001 );
669 : :
670 : : // else
671 : 1 : QgsGeometryUtils::coefficients( QgsPoint( 6, 4 ), QgsPoint( 4, 8 ), a, b, c );
672 : 1 : QGSCOMPARENEAR( a, -4, 0.00000001 );
673 : 1 : QGSCOMPARENEAR( b, -2, 0.00000001 );
674 : 1 : QGSCOMPARENEAR( c, 32, 0.00000001 );
675 : 1 : QgsGeometryUtils::coefficients( QgsPoint( -4, -2 ), QgsPoint( 4, 2 ), a, b, c );
676 : 1 : QGSCOMPARENEAR( a, -4, 0.00000001 );
677 : 1 : QGSCOMPARENEAR( b, 8, 0.00000001 );
678 : 1 : QGSCOMPARENEAR( c, 0, 0.00000001 );
679 : 1 : }
680 : 1 : void TestQgsGeometryUtils::testPerpendicularSegment()
681 : : {
682 : 1 : QgsPoint p1( 3, 13 );
683 : 1 : QgsPoint s1( 2, 3 );
684 : 1 : QgsPoint s2( 7, 11 );
685 : :
686 : 1 : QgsLineString line_r = QgsGeometryUtils::perpendicularSegment( p1, s1, s2 );
687 : :
688 : : // default case
689 : 1 : QgsLineString line;
690 : 1 : line.addVertex( p1 );
691 : 1 : line.addVertex( QgsPoint( 6.7753, 10.6404 ) );
692 : 1 : QGSCOMPARENEARPOINT( line.pointN( 0 ), line_r.pointN( 0 ), 0.0001 );
693 : 1 : QGSCOMPARENEARPOINT( line.pointN( 1 ), line_r.pointN( 1 ), 0.0001 );
694 : :
695 : : // perpendicular line don't intersect segment
696 : 1 : line.clear();
697 : 1 : p1 = QgsPoint( 11, 11 );
698 : 1 : line_r = QgsGeometryUtils::perpendicularSegment( p1, s1, s2 );
699 : 1 : line.addVertex( p1 );
700 : 1 : line.addVertex( QgsPoint( 8.1236, 12.7978 ) );
701 : 1 : QGSCOMPARENEARPOINT( line.pointN( 0 ), line_r.pointN( 0 ), 0.0001 );
702 : 1 : QGSCOMPARENEARPOINT( line.pointN( 1 ), line_r.pointN( 1 ), 0.0001 );
703 : :
704 : : // horizontal
705 : 1 : s1 = QgsPoint( -3, 3 );
706 : 1 : s2 = QgsPoint( 2, 3 );
707 : 1 : line.clear();
708 : 1 : p1 = QgsPoint( 3, 13 );
709 : 1 : line_r = QgsGeometryUtils::perpendicularSegment( p1, s1, s2 );
710 : 1 : line.addVertex( p1 );
711 : 1 : line.addVertex( QgsPoint( 3, 3 ) );
712 : 1 : QCOMPARE( line.pointN( 0 ), line_r.pointN( 0 ) );
713 : 1 : QCOMPARE( line.pointN( 1 ), line_r.pointN( 1 ) );
714 : :
715 : : // vertical
716 : 1 : s1 = QgsPoint( 3, 13 );
717 : 1 : s2 = QgsPoint( 3, 3 );
718 : 1 : line.clear();
719 : 1 : p1 = QgsPoint( -7, 8 );
720 : 1 : line_r = QgsGeometryUtils::perpendicularSegment( p1, s1, s2 );
721 : 1 : line.addVertex( p1 );
722 : 1 : line.addVertex( QgsPoint( 3, 8 ) );
723 : 1 : QCOMPARE( line.pointN( 0 ), line_r.pointN( 0 ) );
724 : 1 : QCOMPARE( line.pointN( 1 ), line_r.pointN( 1 ) );
725 : 1 : }
726 : :
727 : 1 : void TestQgsGeometryUtils::testClosestPoint()
728 : : {
729 : 2 : QgsLineString linestringZ( QVector<QgsPoint>()
730 : 1 : << QgsPoint( 1, 1, 1 )
731 : 1 : << QgsPoint( 1, 3, 2 ) );
732 : :
733 : 1 : QgsPoint pt1 = QgsGeometryUtils::closestPoint( linestringZ, QgsPoint( 1, 0 ) );
734 : 1 : QGSCOMPARENEAR( pt1.z(), 1, 0.0001 );
735 : 1 : QVERIFY( std::isnan( pt1.m() ) );
736 : :
737 : 2 : QgsLineString linestringM( QVector<QgsPoint>()
738 : 1 : << QgsPoint( 1, 1, std::numeric_limits<double>::quiet_NaN(), 1 )
739 : 1 : << QgsPoint( 1, 3, std::numeric_limits<double>::quiet_NaN(), 2 ) );
740 : :
741 : 1 : QgsPoint pt2 = QgsGeometryUtils::closestPoint( linestringM, QgsPoint( 1, 4 ) );
742 : 1 : QVERIFY( std::isnan( pt2.z() ) );
743 : 1 : QGSCOMPARENEAR( pt2.m(), 2, 0.0001 );
744 : :
745 : 2 : QgsLineString linestringZM( QVector<QgsPoint>()
746 : 1 : << QgsPoint( 1, 1, 1, 1 )
747 : 1 : << QgsPoint( 1, 3, 2, 2 ) );
748 : :
749 : 1 : QgsPoint pt3 = QgsGeometryUtils::closestPoint( linestringZM, QgsPoint( 2, 2 ) );
750 : 1 : QGSCOMPARENEAR( pt3.z(), 1.5, 0.0001 );
751 : 1 : QGSCOMPARENEAR( pt3.m(), 1.5, 0.0001 );
752 : :
753 : 2 : QgsLineString linestringDuplicatedPoint( QVector<QgsPoint>()
754 : 1 : << QgsPoint( 1, 1, 1, 1 )
755 : 1 : << QgsPoint( 1, 1, 1, 1 )
756 : 1 : << QgsPoint( 1, 3, 2, 2 ) );
757 : :
758 : 1 : QgsPoint pt4 = QgsGeometryUtils::closestPoint( linestringDuplicatedPoint, QgsPoint( 1, 0 ) );
759 : 1 : QGSCOMPARENEAR( pt4.z(), 1, 0.0001 );
760 : 1 : QGSCOMPARENEAR( pt4.m(), 1, 0.0001 );
761 : 1 : }
762 : :
763 : 1 : void TestQgsGeometryUtils::testlinesIntersection3D()
764 : : {
765 : 1 : QgsVector3D x;
766 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 0, 0, 10 ), QgsVector3D( 5, 0, 10 ), QgsVector3D( 2, 1, 10 ), QgsVector3D( 2, 3, 10 ), x ) );
767 : 1 : QVERIFY( x == QgsVector3D( 2.0, 0.0, 10.0 ) );
768 : :
769 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 0, 0, 10 ), QgsVector3D( 5, 0, 10 ), QgsVector3D( 2, 1, 10 ), QgsVector3D( 2, 0, 10 ), x ) );
770 : 1 : QVERIFY( x == QgsVector3D( 2.0, 0.0, 10.0 ) );
771 : :
772 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 0, 0, 10 ), QgsVector3D( 5, 0, 10 ), QgsVector3D( 0, 1, 10 ), QgsVector3D( 0, 3, 10 ), x ) );
773 : 1 : QVERIFY( x == QgsVector3D( 0.0, 0.0, 10.0 ) );
774 : :
775 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 0, 0, 10 ), QgsVector3D( 5, 0, 10 ), QgsVector3D( 0, 1, 10 ), QgsVector3D( 0, 0, 10 ), x ) );
776 : 1 : QVERIFY( x == QgsVector3D( 0.0, 0.0, 10.0 ) );
777 : :
778 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 0, 0, 10 ), QgsVector3D( 5, 0, 10 ), QgsVector3D( 5, 1, 10 ), QgsVector3D( 5, 3, 10 ), x ) );
779 : 1 : QVERIFY( x == QgsVector3D( 5.0, 0.0, 10.0 ) );
780 : :
781 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 0, 0, 10 ), QgsVector3D( 5, 0, 10 ), QgsVector3D( 5, 1, 10 ), QgsVector3D( 5, 0, 10 ), x ) );
782 : 1 : QVERIFY( x == QgsVector3D( 5.0, 0.0, 10.0 ) );
783 : :
784 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 1, 1, 10 ), QgsVector3D( 2, 2, 10 ), QgsVector3D( 3, 1, 10 ), QgsVector3D( 3, 2, 10 ), x ) );
785 : 1 : QVERIFY( x == QgsVector3D( 3.0, 3.0, 10.0 ) );
786 : :
787 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 1, 1, 10 ), QgsVector3D( 2, 2, 10 ), QgsVector3D( 3, 2, 10 ), QgsVector3D( 3, 1, 10 ), x ) );
788 : 1 : QVERIFY( x == QgsVector3D( 3.0, 3.0, 10.0 ) );
789 : :
790 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 5, 5, 5 ), QgsVector3D( 0, 0, 0 ), QgsVector3D( 0, 5, 5 ), QgsVector3D( 5, 0, 0 ), x ) );
791 : 1 : QVERIFY( x == QgsVector3D( 2.5, 2.5, 2.5 ) );
792 : :
793 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 2.5, 2.5, 2.5 ), QgsVector3D( 0, 5, 0 ), QgsVector3D( 2.5, 2.5, 2.5 ), QgsVector3D( 5, 0, 0 ), x ) );
794 : 1 : QVERIFY( x == QgsVector3D( 2.5, 2.5, 2.5 ) );
795 : :
796 : 1 : QVERIFY( QgsGeometryUtils::linesIntersection3D( QgsVector3D( 2.5, 2.5, 2.5 ), QgsVector3D( 5, 0, 0 ), QgsVector3D( 0, 5, 5 ), QgsVector3D( 5, 5, 5 ), x ) );
797 : 1 : QVERIFY( x == QgsVector3D( 0.0, 5.0, 5.0 ) );
798 : :
799 : 1 : }
800 : :
801 : 1 : void TestQgsGeometryUtils::testSegmentIntersection()
802 : : {
803 : 1 : const double epsilon = 1e-8;
804 : 1 : bool intersection = false, isIntersect = false;
805 : 1 : QgsPoint inter;
806 : : // null
807 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 5, 5 ), QgsPoint( 5, 5 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon );
808 : 1 : QVERIFY( !intersection );
809 : 1 : QVERIFY( !isIntersect );
810 : 1 : QVERIFY( inter == QgsPoint() );
811 : 1 : inter = QgsPoint();
812 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 5, 5 ), QgsPoint( 5, 5 ), inter, isIntersect, epsilon, true );
813 : 1 : QVERIFY( !intersection );
814 : 1 : QVERIFY( !isIntersect );
815 : 1 : QVERIFY( inter == QgsPoint() );
816 : : // parallel
817 : 1 : inter = QgsPoint();
818 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon );
819 : 1 : QVERIFY( !intersection );
820 : 1 : QVERIFY( !isIntersect );
821 : 1 : QVERIFY( inter == QgsPoint() );
822 : 1 : inter = QgsPoint();
823 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon, true );
824 : 1 : QVERIFY( !intersection );
825 : 1 : QVERIFY( !isIntersect );
826 : 1 : QVERIFY( inter == QgsPoint() );
827 : 1 : inter = QgsPoint();
828 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 0, 1 ), QgsPoint( 1, 2 ), inter, isIntersect, epsilon );
829 : 1 : QVERIFY( !intersection );
830 : 1 : QVERIFY( !isIntersect );
831 : 1 : QVERIFY( inter == QgsPoint() );
832 : 1 : inter = QgsPoint();
833 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 1, 1 ), QgsPoint( -1, -1 ), inter, isIntersect, epsilon );
834 : 1 : QVERIFY( !intersection );
835 : 1 : QVERIFY( !isIntersect );
836 : 1 : QVERIFY( inter == QgsPoint() );
837 : 1 : inter = QgsPoint();
838 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 1, 1 ), QgsPoint( 0, 0 ), inter, isIntersect, epsilon );
839 : 1 : QVERIFY( !intersection );
840 : 1 : QVERIFY( !isIntersect );
841 : 1 : QVERIFY( inter == QgsPoint() );
842 : : // contigus
843 : 1 : inter = QgsPoint();
844 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon );
845 : 1 : QVERIFY( !intersection );
846 : 1 : QVERIFY( isIntersect );
847 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
848 : 1 : inter = QgsPoint();
849 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true );
850 : 1 : QVERIFY( intersection );
851 : 1 : QVERIFY( isIntersect );
852 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
853 : 1 : inter = QgsPoint();
854 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon );
855 : 1 : QVERIFY( !intersection );
856 : 1 : QVERIFY( isIntersect );
857 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
858 : 1 : inter = QgsPoint();
859 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true );
860 : 1 : QVERIFY( intersection );
861 : 1 : QVERIFY( isIntersect );
862 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
863 : 1 : inter = QgsPoint();
864 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon );
865 : 1 : QVERIFY( !intersection );
866 : 1 : QVERIFY( isIntersect );
867 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
868 : 1 : inter = QgsPoint();
869 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true );
870 : 1 : QVERIFY( intersection );
871 : 1 : QVERIFY( isIntersect );
872 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
873 : 1 : inter = QgsPoint();
874 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon );
875 : 1 : QVERIFY( !intersection );
876 : 1 : QVERIFY( isIntersect );
877 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
878 : 1 : inter = QgsPoint();
879 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true );
880 : 1 : QVERIFY( intersection );
881 : 1 : QVERIFY( isIntersect );
882 : 1 : QVERIFY( inter == QgsPoint( 0, 5 ) );
883 : : // colinear
884 : 1 : inter = QgsPoint();
885 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 0, 6 ), inter, isIntersect, epsilon );
886 : 1 : QVERIFY( !intersection );
887 : 1 : QVERIFY( !isIntersect );
888 : 1 : QVERIFY( inter == QgsPoint() );
889 : 1 : inter = QgsPoint();
890 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 0, 6 ), inter, isIntersect, epsilon, true );
891 : 1 : QVERIFY( !intersection );
892 : 1 : QVERIFY( !isIntersect );
893 : 1 : QVERIFY( inter == QgsPoint() );
894 : : // improper
895 : 1 : inter = QgsPoint();
896 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon );
897 : 1 : QVERIFY( !intersection );
898 : 1 : QVERIFY( isIntersect );
899 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
900 : 1 : inter = QgsPoint();
901 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true );
902 : 1 : QVERIFY( intersection );
903 : 1 : QVERIFY( isIntersect );
904 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
905 : :
906 : 1 : inter = QgsPoint();
907 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon );
908 : 1 : QVERIFY( !intersection );
909 : 1 : QVERIFY( isIntersect );
910 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
911 : 1 : inter = QgsPoint();
912 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true );
913 : 1 : QVERIFY( intersection );
914 : 1 : QVERIFY( isIntersect );
915 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
916 : :
917 : 1 : inter = QgsPoint();
918 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon );
919 : 1 : QVERIFY( !intersection );
920 : 1 : QVERIFY( isIntersect );
921 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
922 : 1 : inter = QgsPoint();
923 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true );
924 : 1 : QVERIFY( intersection );
925 : 1 : QVERIFY( isIntersect );
926 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
927 : :
928 : 1 : inter = QgsPoint();
929 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), inter, isIntersect, epsilon );
930 : 1 : QVERIFY( !intersection );
931 : 1 : QVERIFY( isIntersect );
932 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
933 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), inter, isIntersect, epsilon, true );
934 : 1 : QVERIFY( intersection );
935 : 1 : QVERIFY( isIntersect );
936 : 1 : QVERIFY( inter == QgsPoint( 0, 2 ) );
937 : : // normal
938 : 1 : inter = QgsPoint();
939 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), inter, isIntersect, epsilon );
940 : 1 : QVERIFY( intersection );
941 : 1 : QVERIFY( isIntersect );
942 : 1 : QVERIFY( inter == QgsPoint( 0, 0 ) );
943 : 1 : inter = QgsPoint();
944 : 1 : intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), inter, isIntersect, epsilon, true );
945 : 1 : QVERIFY( intersection );
946 : 1 : QVERIFY( isIntersect );
947 : 1 : QVERIFY( inter == QgsPoint( 0, 0 ) );
948 : 1 : }
949 : :
950 : 1 : void TestQgsGeometryUtils::testLineCircleIntersection()
951 : : {
952 : 1 : QgsPointXY center = QgsPoint( 2, 2 );
953 : 1 : double radius = 2.0;
954 : 1 : QgsPointXY linePoint1 = QgsPoint( 0, 2 );
955 : 1 : QgsPointXY linePoint2 = QgsPoint( 2, 2 );
956 : 1 : QgsPointXY intersection = QgsPoint( 3, 3 );
957 : 1 : bool isIntersection = QgsGeometryUtils::lineCircleIntersection( center, radius, linePoint1, linePoint2, intersection );
958 : 1 : QVERIFY( isIntersection );
959 : 1 : QVERIFY( intersection == QgsPointXY( 4, 2 ) );
960 : :
961 : 1 : linePoint1 = QgsPoint( 5, 0 );
962 : 1 : linePoint2 = QgsPoint( 5, 2 );
963 : 1 : isIntersection = QgsGeometryUtils::lineCircleIntersection( center, radius, linePoint1, linePoint2, intersection );
964 : 1 : QVERIFY( !isIntersection );
965 : 1 : }
966 : :
967 : 1 : void TestQgsGeometryUtils::testCircleCircleIntersection()
968 : : {
969 : 1 : QgsPointXY int1;
970 : 1 : QgsPointXY int2;
971 : :
972 : : // no intersections
973 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleIntersections( QgsPointXY( 0, 0 ), 1, QgsPointXY( 2, 0 ), 0.5, int1, int2 ), 0 );
974 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleIntersections( QgsPointXY( 0, 0 ), 1, QgsPointXY( 0.5, 0.1 ), 0.2, int1, int2 ), 0 );
975 : : // one intersection
976 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleIntersections( QgsPointXY( 0, 0 ), 1, QgsPointXY( 3, 0 ), 2, int1, int2 ), 1 );
977 : 1 : QCOMPARE( int1, QgsPointXY( 1, 0 ) );
978 : 1 : QCOMPARE( int2, QgsPointXY( 1, 0 ) );
979 : : // two intersections
980 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleIntersections( QgsPointXY( 5, 3 ), 2, QgsPointXY( 7, -1 ), 4, int1, int2 ), 2 );
981 : 1 : QGSCOMPARENEAR( int1.x(), 3.8, 0.001 );
982 : 1 : QGSCOMPARENEAR( int1.y(), 1.4, 0.001 );
983 : 1 : QGSCOMPARENEAR( int2.x(), 7.0, 0.001 );
984 : 1 : QGSCOMPARENEAR( int2.y(), 3.0, 0.001 );
985 : 1 : }
986 : :
987 : 1 : void TestQgsGeometryUtils::testTangentPointAndCircle()
988 : : {
989 : 1 : QgsPointXY t1;
990 : 1 : QgsPointXY t2;
991 : 1 : QVERIFY( !QgsGeometryUtils::tangentPointAndCircle( QgsPointXY( 1, 2 ), 4, QgsPointXY( 1, 2 ), t1, t2 ) );
992 : 1 : QVERIFY( QgsGeometryUtils::tangentPointAndCircle( QgsPointXY( 1, 2 ), 4, QgsPointXY( 8, 4 ), t1, t2 ) );
993 : 1 : QGSCOMPARENEAR( t1.x(), 4.03, 0.01 );
994 : 1 : QGSCOMPARENEAR( t1.y(), -0.61, 0.01 );
995 : 1 : QGSCOMPARENEAR( t2.x(), 2.2, 0.01 );
996 : 1 : QGSCOMPARENEAR( t2.y(), 5.82, 0.01 );
997 : 1 : }
998 : :
999 : 1 : void TestQgsGeometryUtils::testCircleCircleOuterTangents()
1000 : : {
1001 : 1 : QgsPointXY l1p1;
1002 : 1 : QgsPointXY l1p2;
1003 : 1 : QgsPointXY l2p1;
1004 : 1 : QgsPointXY l2p2;
1005 : :
1006 : : // no tangents
1007 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleOuterTangents( QgsPointXY( 1, 2 ), 4, QgsPointXY( 2, 3 ), 1, l1p1, l1p2, l2p1, l2p2 ), 0 );
1008 : :
1009 : : // tangents
1010 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleOuterTangents( QgsPointXY( 1, 2 ), 1, QgsPointXY( 10, 3 ), 4, l1p1, l1p2, l2p1, l2p2 ), 2 );
1011 : 1 : QGSCOMPARENEAR( l1p1.x(), 0.566, 0.01 );
1012 : 1 : QGSCOMPARENEAR( l1p1.y(), 2.901, 0.01 );
1013 : 1 : QGSCOMPARENEAR( l1p2.x(), 8.266, 0.01 );
1014 : 1 : QGSCOMPARENEAR( l1p2.y(), 6.604, 0.01 );
1015 : 1 : QGSCOMPARENEAR( l2p1.x(), 0.7749, 0.01 );
1016 : 1 : QGSCOMPARENEAR( l2p1.y(), 1.025, 0.01 );
1017 : 1 : QGSCOMPARENEAR( l2p2.x(), 9.099, 0.01 );
1018 : 1 : QGSCOMPARENEAR( l2p2.y(), -0.897, 0.01 );
1019 : :
1020 : : // larger circle first
1021 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleOuterTangents( QgsPointXY( 10, 3 ), 4, QgsPointXY( 1, 2 ), 1, l1p1, l1p2, l2p1, l2p2 ), 2 );
1022 : 1 : QGSCOMPARENEAR( l1p1.x(), 0.566, 0.01 );
1023 : 1 : QGSCOMPARENEAR( l1p1.y(), 2.901, 0.01 );
1024 : 1 : QGSCOMPARENEAR( l1p2.x(), 8.266, 0.01 );
1025 : 1 : QGSCOMPARENEAR( l1p2.y(), 6.604, 0.01 );
1026 : 1 : QGSCOMPARENEAR( l2p1.x(), 0.7749, 0.01 );
1027 : 1 : QGSCOMPARENEAR( l2p1.y(), 1.025, 0.01 );
1028 : 1 : QGSCOMPARENEAR( l2p2.x(), 9.099, 0.01 );
1029 : 1 : QGSCOMPARENEAR( l2p2.y(), -0.897, 0.01 );
1030 : 1 : }
1031 : :
1032 : 1 : void TestQgsGeometryUtils::testCircleCircleInnerTangents()
1033 : : {
1034 : 1 : QgsPointXY l1p1;
1035 : 1 : QgsPointXY l1p2;
1036 : 1 : QgsPointXY l2p1;
1037 : 1 : QgsPointXY l2p2;
1038 : :
1039 : : // no tangents, intersecting circles
1040 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( 1, 2 ), 4, QgsPointXY( 2, 3 ), 1, l1p1, l1p2, l2p1, l2p2 ), 0 );
1041 : :
1042 : : // no tangents, same circles
1043 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( 1, 2 ), 4, QgsPointXY( 1, 2 ), 4, l1p1, l1p2, l2p1, l2p2 ), 0 );
1044 : :
1045 : : // no tangents, touching circles
1046 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( 0, 0 ), 4, QgsPointXY( 0, 8 ), 4, l1p1, l1p2, l2p1, l2p2 ), 0 );
1047 : :
1048 : : // tangents
1049 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( 1, 2 ), 1, QgsPointXY( 10, 3 ), 4, l1p1, l1p2, l2p1, l2p2 ), 2 );
1050 : 1 : QGSCOMPARENEAR( l1p1.x(), 7.437, 0.01 );
1051 : 1 : QGSCOMPARENEAR( l1p1.y(), 6.071, 0.01 );
1052 : 1 : QGSCOMPARENEAR( l1p2.x(), 1.641, 0.01 );
1053 : 1 : QGSCOMPARENEAR( l1p2.y(), 1.232, 0.01 );
1054 : 1 : QGSCOMPARENEAR( l2p1.x(), 8.173, 0.01 );
1055 : 1 : QGSCOMPARENEAR( l2p1.y(), -0.558, 0.01 );
1056 : 1 : QGSCOMPARENEAR( l2p2.x(), 1.457, 0.01 );
1057 : 1 : QGSCOMPARENEAR( l2p2.y(), 2.89, 0.01 );
1058 : :
1059 : : // tangents, larger circle first
1060 : 1 : QCOMPARE( QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( 10, 3 ), 4, QgsPointXY( 1, 2 ), 1, l1p1, l1p2, l2p1, l2p2 ), 2 );
1061 : 1 : QGSCOMPARENEAR( l1p1.x(), 7.437, 0.01 );
1062 : 1 : QGSCOMPARENEAR( l1p1.y(), 6.071, 0.01 );
1063 : 1 : QGSCOMPARENEAR( l1p2.x(), 1.641, 0.01 );
1064 : 1 : QGSCOMPARENEAR( l1p2.y(), 1.232, 0.01 );
1065 : 1 : QGSCOMPARENEAR( l2p1.x(), 8.173, 0.01 );
1066 : 1 : QGSCOMPARENEAR( l2p1.y(), -0.558, 0.01 );
1067 : 1 : QGSCOMPARENEAR( l2p2.x(), 1.457, 0.01 );
1068 : 1 : QGSCOMPARENEAR( l2p2.y(), 2.89, 0.01 );
1069 : 1 : }
1070 : :
1071 : 1 : void TestQgsGeometryUtils::testGml()
1072 : : {
1073 : 1 : QgsPoint point = QgsPoint( 1, 2 );
1074 : 1 : QDomDocument doc;
1075 : 2 : QDomElement elm = QgsGeometryUtils::pointsToGML2( QgsPointSequence( ) << point, doc, 2, QStringLiteral( "gml" ) );
1076 : 2 : QString expectedGML2( QStringLiteral( "<coordinates xmlns=\"gml\" cs=\",\" ts=\" \">1,2</coordinates>" ) );
1077 : 3 : QGSCOMPAREGML( elemToString( elm ), expectedGML2 );
1078 : 2 : elm = QgsGeometryUtils::pointsToGML2( QgsPointSequence( ) << point, doc, 2, QStringLiteral( "gml" ), QgsAbstractGeometry::AxisOrder::YX );
1079 : 2 : QString expectedGML2_inverted( QStringLiteral( "<coordinates xmlns=\"gml\" cs=\",\" ts=\" \">2,1</coordinates>" ) );
1080 : 3 : QGSCOMPAREGML( elemToString( elm ), expectedGML2_inverted );
1081 : :
1082 : 2 : elm = QgsGeometryUtils::pointsToGML3( QgsPointSequence( ) << point, doc, 2, QStringLiteral( "gml" ), false, QgsAbstractGeometry::AxisOrder::XY );
1083 : 2 : QString expectedGML3( QStringLiteral( "<posList xmlns=\"gml\" srsDimension=\"2\">1 2</posList>" ) );
1084 : 3 : QGSCOMPAREGML( elemToString( elm ), expectedGML3 );
1085 : 2 : elm = QgsGeometryUtils::pointsToGML3( QgsPointSequence( ) << point, doc, 2, QStringLiteral( "gml" ), false, QgsAbstractGeometry::AxisOrder::YX );
1086 : 2 : QString expectedGML3_inverted( QStringLiteral( "<posList xmlns=\"gml\" srsDimension=\"2\">2 1</posList>" ) );
1087 : 3 : QGSCOMPAREGML( elemToString( elm ), expectedGML3_inverted );
1088 : 1 : }
1089 : :
1090 : 1 : void TestQgsGeometryUtils::testInterpolatePointOnLineQgsPoint()
1091 : : {
1092 : 1 : QgsPoint p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( 10, 0 ), 0 );
1093 : 1 : QCOMPARE( p.x(), 0.0 );
1094 : 1 : QCOMPARE( p.y(), 0.0 );
1095 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( 10, 0 ), 1 );
1096 : 1 : QCOMPARE( p.x(), 10.0 );
1097 : 1 : QCOMPARE( p.y(), 0.0 );
1098 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( 0, 10 ), 0 );
1099 : 1 : QCOMPARE( p.x(), 0.0 );
1100 : 1 : QCOMPARE( p.y(), 0.0 );
1101 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( 0, 10 ), 1 );
1102 : 1 : QCOMPARE( p.x(), 0.0 );
1103 : 1 : QCOMPARE( p.y(), 10.0 );
1104 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), 0.5 );
1105 : 1 : QCOMPARE( p.x(), -5.0 );
1106 : 1 : QCOMPARE( p.y(), -3.0 );
1107 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), 0.2 );
1108 : 1 : QCOMPARE( p.x(), -2.0 );
1109 : 1 : QCOMPARE( p.y(), -1.2 );
1110 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), 2 );
1111 : 1 : QCOMPARE( p.x(), -20.0 );
1112 : 1 : QCOMPARE( p.y(), -12.0 );
1113 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), -1 );
1114 : 1 : QCOMPARE( p.x(), 10.0 );
1115 : 1 : QCOMPARE( p.y(), 6.0 );
1116 : : // with m
1117 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0, 0, 5, QgsWkbTypes::PointM ), QgsPoint( -10, -6, 0, 10, QgsWkbTypes::PointM ), 0.4 );
1118 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointM );
1119 : 1 : QCOMPARE( p.x(), -4.0 );
1120 : 1 : QCOMPARE( p.y(), -2.4 );
1121 : 1 : QCOMPARE( p.m(), 7.0 );
1122 : : // with z
1123 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0, 5, 0, QgsWkbTypes::PointZ ), QgsPoint( -10, -6, 10, 0, QgsWkbTypes::PointZ ), 0.4 );
1124 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZ );
1125 : 1 : QCOMPARE( p.x(), -4.0 );
1126 : 1 : QCOMPARE( p.y(), -2.4 );
1127 : 1 : QCOMPARE( p.z(), 7.0 );
1128 : : // with zm
1129 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( QgsPoint( 0, 0, 5, 10, QgsWkbTypes::PointZM ), QgsPoint( -10, -6, 10, 5, QgsWkbTypes::PointZM ), 0.4 );
1130 : 1 : QCOMPARE( p.wkbType(), QgsWkbTypes::PointZM );
1131 : 1 : QCOMPARE( p.x(), -4.0 );
1132 : 1 : QCOMPARE( p.y(), -2.4 );
1133 : 1 : QCOMPARE( p.z(), 7.0 );
1134 : 1 : QCOMPARE( p.m(), 8.0 );
1135 : 1 : }
1136 : :
1137 : 1 : void TestQgsGeometryUtils::testInterpolatePointOnLine()
1138 : : {
1139 : 1 : QgsPointXY p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, 10, 0, 0 );
1140 : 1 : QCOMPARE( p.x(), 0.0 );
1141 : 1 : QCOMPARE( p.y(), 0.0 );
1142 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, 10, 0, 1 );
1143 : 1 : QCOMPARE( p.x(), 10.0 );
1144 : 1 : QCOMPARE( p.y(), 0.0 );
1145 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, 0, 10, 0 );
1146 : 1 : QCOMPARE( p.x(), 0.0 );
1147 : 1 : QCOMPARE( p.y(), 0.0 );
1148 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, 0, 10, 1 );
1149 : 1 : QCOMPARE( p.x(), 0.0 );
1150 : 1 : QCOMPARE( p.y(), 10.0 );
1151 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, -10, -6, 0.5 );
1152 : 1 : QCOMPARE( p.x(), -5.0 );
1153 : 1 : QCOMPARE( p.y(), -3.0 );
1154 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, -10, -6, 0.2 );
1155 : 1 : QCOMPARE( p.x(), -2.0 );
1156 : 1 : QCOMPARE( p.y(), -1.2 );
1157 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, -10, -6, 2 );
1158 : 1 : QCOMPARE( p.x(), -20.0 );
1159 : 1 : QCOMPARE( p.y(), -12.0 );
1160 : 1 : p = QgsGeometryUtils::interpolatePointOnLine( 0, 0, -10, -6, -1 );
1161 : 1 : QCOMPARE( p.x(), 10.0 );
1162 : 1 : QCOMPARE( p.y(), 6.0 );
1163 : 1 : }
1164 : :
1165 : 1 : void TestQgsGeometryUtils::testInterpolatePointOnLineByValue()
1166 : : {
1167 : 1 : QgsPointXY p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 0, 10, 0, 1, 0 );
1168 : 1 : QCOMPARE( p.x(), 0.0 );
1169 : 1 : QCOMPARE( p.y(), 0.0 );
1170 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 0, 10, 0, 1, 1 );
1171 : 1 : QCOMPARE( p.x(), 10.0 );
1172 : 1 : QCOMPARE( p.y(), 0.0 );
1173 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 5, 0, 10, 15, 5 );
1174 : 1 : QCOMPARE( p.x(), 0.0 );
1175 : 1 : QCOMPARE( p.y(), 0.0 );
1176 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 15, 0, 10, 5, 5 );
1177 : 1 : QCOMPARE( p.x(), 0.0 );
1178 : 1 : QCOMPARE( p.y(), 10.0 );
1179 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 1, -10, -6, 3, 2 );
1180 : 1 : QCOMPARE( p.x(), -5.0 );
1181 : 1 : QCOMPARE( p.y(), -3.0 );
1182 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 1, -10, -6, 3, 1.4 );
1183 : 1 : QCOMPARE( p.x(), -2.0 );
1184 : 1 : QCOMPARE( p.y(), -1.2 );
1185 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 3, -10, -6, 1, 2 );
1186 : 1 : QCOMPARE( p.x(), -5.0 );
1187 : 1 : QCOMPARE( p.y(), -3.0 );
1188 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 1, -10, -6, 3, -1 );
1189 : 1 : QCOMPARE( p.x(), 10.0 );
1190 : 1 : QCOMPARE( p.y(), 6.0 );
1191 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 1, -10, -6, 3, 5 );
1192 : 1 : QCOMPARE( p.x(), -20.0 );
1193 : 1 : QCOMPARE( p.y(), -12.0 );
1194 : : // v1 == v2, test for no crash
1195 : 1 : p = QgsGeometryUtils::interpolatePointOnLineByValue( 0, 0, 1, -10, -6, 1, 1 );
1196 : 1 : QCOMPARE( p.x(), 0.0 );
1197 : 1 : QCOMPARE( p.y(), 0.0 );
1198 : 1 : }
1199 : :
1200 : 1 : void TestQgsGeometryUtils::testPointOnLineWithDistance()
1201 : : {
1202 : 1 : QgsPoint p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 0, 0 ), QgsPoint( 10, 0 ), 0 );
1203 : 1 : QCOMPARE( p.x(), 0.0 );
1204 : 1 : QCOMPARE( p.y(), 0.0 );
1205 : : double x;
1206 : : double y;
1207 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 0, 0, 10, 0, 0, x, y );
1208 : 1 : QCOMPARE( x, 0.0 );
1209 : 1 : QCOMPARE( y, 0.0 );
1210 : :
1211 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 2, 3 ), QgsPoint( 12, 3 ), 10 );
1212 : 1 : QCOMPARE( p.x(), 12.0 );
1213 : 1 : QCOMPARE( p.y(), 3.0 );
1214 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 2, 3, 12, 3, 10, x, y );
1215 : 1 : QCOMPARE( x, 12.0 );
1216 : 1 : QCOMPARE( y, 3.0 );
1217 : :
1218 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 0, 0 ), QgsPoint( 0, 10 ), 0 );
1219 : 1 : QCOMPARE( p.x(), 0.0 );
1220 : 1 : QCOMPARE( p.y(), 0.0 );
1221 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 0, 0, 0, 10, 0, x, y );
1222 : 1 : QCOMPARE( x, 0.0 );
1223 : 1 : QCOMPARE( y, 0.0 );
1224 : :
1225 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 0, 0 ), QgsPoint( 0, 10 ), 10 );
1226 : 1 : QCOMPARE( p.x(), 0.0 );
1227 : 1 : QCOMPARE( p.y(), 10.0 );
1228 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 0, 0, 0, 10, 10, x, y );
1229 : 1 : QCOMPARE( x, 0.0 );
1230 : 1 : QCOMPARE( y, 10.0 );
1231 : :
1232 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 2, 1 ), QgsPoint( -8, -5 ), 5 );
1233 : 1 : QGSCOMPARENEAR( p.x(), -2.28746, 0.0001 );
1234 : 1 : QGSCOMPARENEAR( p.y(), -1.57248, 0.0001 );
1235 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 2, 1, -8, -5, 5, x, y );
1236 : 1 : QGSCOMPARENEAR( x, -2.28746, 0.0001 );
1237 : 1 : QGSCOMPARENEAR( y, -1.57248, 0.0001 );
1238 : : double z, z1, z2;
1239 : : double m, m1, m2;
1240 : 1 : z1 = 12;
1241 : 1 : z2 = 2;
1242 : 1 : m1 = 11;
1243 : 1 : m2 = 15;
1244 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 2, 1, -8, -5, 5, x, y, &z1, &z2, &z );
1245 : 1 : QGSCOMPARENEAR( x, -2.28746, 0.0001 );
1246 : 1 : QGSCOMPARENEAR( y, -1.57248, 0.0001 );
1247 : 1 : QGSCOMPARENEAR( z, 7.712535, 0.0001 );
1248 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 2, 1, -8, -5, 5, x, y, nullptr, nullptr, nullptr, &m1, &m2, &m );
1249 : 1 : QGSCOMPARENEAR( x, -2.28746, 0.0001 );
1250 : 1 : QGSCOMPARENEAR( y, -1.57248, 0.0001 );
1251 : 1 : QGSCOMPARENEAR( m, 12.714986, 0.0001 );
1252 : 1 : z = 0;
1253 : 1 : m = 0;
1254 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 2, 1, -8, -5, 5, x, y, &z1, &z2, &z, &m1, &m2, &m );
1255 : 1 : QGSCOMPARENEAR( x, -2.28746, 0.0001 );
1256 : 1 : QGSCOMPARENEAR( y, -1.57248, 0.0001 );
1257 : 1 : QGSCOMPARENEAR( z, 7.712535, 0.0001 );
1258 : 1 : QGSCOMPARENEAR( m, 12.714986, 0.0001 );
1259 : :
1260 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), 2 );
1261 : 1 : QGSCOMPARENEAR( p.x(), -1.71499, 0.0001 );
1262 : 1 : QGSCOMPARENEAR( p.y(), -1.02899, 0.0001 );
1263 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 0, 0, -10, -6, 2, x, y );
1264 : 1 : QGSCOMPARENEAR( x, -1.71499, 0.0001 );
1265 : 1 : QGSCOMPARENEAR( y, -1.02899, 0.0001 );
1266 : :
1267 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), 20 );
1268 : 1 : QGSCOMPARENEAR( p.x(), -17.1499, 0.0001 );
1269 : 1 : QGSCOMPARENEAR( p.y(), -10.2899, 0.0001 );
1270 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 0, 0, -10, -6, 20, x, y );
1271 : 1 : QGSCOMPARENEAR( x, -17.1499, 0.0001 );
1272 : 1 : QGSCOMPARENEAR( y, -10.2899, 0.0001 );
1273 : :
1274 : 1 : p = QgsGeometryUtils::pointOnLineWithDistance( QgsPoint( 0, 0 ), QgsPoint( -10, -6 ), -10 );
1275 : 1 : QGSCOMPARENEAR( p.x(), 8.57493, 0.0001 );
1276 : 1 : QGSCOMPARENEAR( p.y(), 5.14496, 0.0001 );
1277 : 1 : QgsGeometryUtils::pointOnLineWithDistance( 0, 0, -10, -6, -10, x, y );
1278 : 1 : QGSCOMPARENEAR( x, 8.57493, 0.0001 );
1279 : 1 : QGSCOMPARENEAR( y, 5.14496, 0.0001 );
1280 : :
1281 : 1 : }
1282 : :
1283 : 1 : void TestQgsGeometryUtils::interpolatePointOnArc()
1284 : : {
1285 : 1 : QgsPoint p;
1286 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0, 1, 2 ), QgsPoint( 11, 1, 3, 4 ), QgsPoint( 12, 0, 13, 14 ), 0 );
1287 : 1 : QGSCOMPARENEAR( p.x(), 10.0, 0.00001 );
1288 : 1 : QGSCOMPARENEAR( p.y(), 0.0, 0.00001 );
1289 : 1 : QGSCOMPARENEAR( p.z(), 1.0, 0.00001 );
1290 : 1 : QGSCOMPARENEAR( p.m(), 2.0, 0.00001 );
1291 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0, 1, 2 ), QgsPoint( 11, 1, 3, 4 ), QgsPoint( 12, 0, 13, 14 ), 1 );
1292 : 1 : QGSCOMPARENEAR( p.x(), 10.459698, 0.00001 );
1293 : 1 : QGSCOMPARENEAR( p.y(), 0.841471, 0.00001 );
1294 : 1 : QGSCOMPARENEAR( p.z(), 2.273240, 0.00001 );
1295 : 1 : QGSCOMPARENEAR( p.m(), 3.273240, 0.00001 );
1296 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0, 1, 2 ), QgsPoint( 11, 1, 3, 4 ), QgsPoint( 12, 0, 13, 14 ), 2 );
1297 : 1 : QGSCOMPARENEAR( p.x(), 11.416147, 0.00001 );
1298 : 1 : QGSCOMPARENEAR( p.y(), 0.909297, 0.00001 );
1299 : 1 : QGSCOMPARENEAR( p.z(), 5.732395, 0.00001 );
1300 : 1 : QGSCOMPARENEAR( p.m(), 6.732395, 0.00001 );
1301 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 11, 1 ), QgsPoint( 12, 0 ), 3.141592 );
1302 : 1 : QGSCOMPARENEAR( p.x(), 12.0, 0.00001 );
1303 : 1 : QGSCOMPARENEAR( p.y(), 0.0, 0.00001 );
1304 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 11, 1 ), QgsPoint( 12, 0 ), 3.2 );
1305 : 1 : QGSCOMPARENEAR( p.x(), 11.998295, 0.00001 );
1306 : 1 : QGSCOMPARENEAR( p.y(), -0.058374, 0.00001 );
1307 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 11, 1 ), QgsPoint( 12, 0 ), 5 );
1308 : 1 : QGSCOMPARENEAR( p.x(), 10.716338, 0.00001 );
1309 : 1 : QGSCOMPARENEAR( p.y(), -0.958924, 0.00001 );
1310 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0, 1, 2 ), QgsPoint( 11, 1, 3, 4 ), QgsPoint( 12, 0, 13, 14 ), 3.141592 * 2 );
1311 : 1 : QGSCOMPARENEAR( p.x(), 10, 0.00001 );
1312 : 1 : QGSCOMPARENEAR( p.y(), 0, 0.00001 );
1313 : 1 : QGSCOMPARENEAR( p.z(), 32.99999, 0.00001 );
1314 : 1 : QGSCOMPARENEAR( p.m(), 33.999992, 0.00001 );
1315 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 8, 2 ), QgsPoint( 6, 0 ), 0 );
1316 : 1 : QGSCOMPARENEAR( p.x(), 10.0, 0.00001 );
1317 : 1 : QGSCOMPARENEAR( p.y(), 0.0, 0.00001 );
1318 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 8, 2 ), QgsPoint( 6, 0 ), 1 );
1319 : 1 : QGSCOMPARENEAR( p.x(), 9.755165, 0.00001 );
1320 : 1 : QGSCOMPARENEAR( p.y(), 0.958851, 0.00001 );
1321 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 8, 2 ), QgsPoint( 6, 0 ), 3.141592 );
1322 : 1 : QGSCOMPARENEAR( p.x(), 8.0, 0.00001 );
1323 : 1 : QGSCOMPARENEAR( p.y(), 2.0, 0.00001 );
1324 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 8, 2 ), QgsPoint( 6, 0 ), 3.141592 * 2 );
1325 : 1 : QGSCOMPARENEAR( p.x(), 6.0, 0.00001 );
1326 : 1 : QGSCOMPARENEAR( p.y(), 0.0, 0.00001 );
1327 : 1 : p = QgsGeometryUtils::interpolatePointOnArc( QgsPoint( 10, 0 ), QgsPoint( 8, 2 ), QgsPoint( 6, 0 ), 3.141592 * 3 );
1328 : 1 : QGSCOMPARENEAR( p.x(), 8.0, 0.00001 );
1329 : 1 : QGSCOMPARENEAR( p.y(), -2.0, 0.00001 );
1330 : 1 : }
1331 : :
1332 : 1 : void TestQgsGeometryUtils::testSegmentizeArcHalfCircle()
1333 : : {
1334 : 1 : QgsPointSequence points;
1335 : 1 : const double xoff = 1;
1336 : 1 : const double yoff = 100;
1337 : 2 : QgsGeometryUtils::segmentizeArc( QgsPoint( xoff + 0, yoff + 0 ),
1338 : 1 : QgsPoint( xoff + 1, yoff + 1 ),
1339 : 1 : QgsPoint( xoff + 2, yoff + 0 ),
1340 : : points, 0.1,
1341 : : QgsAbstractGeometry::MaximumDifference, false, false );
1342 : 1 : QCOMPARE( points.size(), 5 );
1343 : 1 : QGSCOMPARENEAR( points[0].x(), xoff + 0.0, 0.00001 );
1344 : 1 : QGSCOMPARENEAR( points[0].y(), yoff + 0.0, 0.00001 );
1345 : 1 : QGSCOMPARENEAR( points[1].x(), xoff + 1 - sqrt( 2 ) / 2, 0.00001 );
1346 : 1 : QGSCOMPARENEAR( points[1].y(), yoff + sqrt( 2 ) / 2, 0.00001 );
1347 : 1 : QGSCOMPARENEAR( points[2].x(), xoff + 1.0, 0.00001 );
1348 : 1 : QGSCOMPARENEAR( points[2].y(), yoff + 1.0, 0.00001 );
1349 : 1 : QGSCOMPARENEAR( points[3].x(), xoff + 1 + sqrt( 2 ) / 2, 0.00001 );
1350 : 1 : QGSCOMPARENEAR( points[3].y(), yoff + sqrt( 2 ) / 2, 0.00001 );
1351 : 1 : QGSCOMPARENEAR( points[4].x(), xoff + 2.0, 0.00001 );
1352 : 1 : QGSCOMPARENEAR( points[4].y(), yoff + 0.0, 0.00001 );
1353 : 1 : }
1354 : :
1355 : 1 : void TestQgsGeometryUtils::testSegmentizeArcHalfCircleOtherDirection()
1356 : : {
1357 : 1 : QgsPointSequence points;
1358 : 1 : const double xoff = 1;
1359 : 1 : const double yoff = 100;
1360 : 2 : QgsGeometryUtils::segmentizeArc( QgsPoint( xoff + 0, yoff + 0 ),
1361 : 1 : QgsPoint( xoff + 1, yoff - 1 ),
1362 : 1 : QgsPoint( xoff + 2, yoff + 0 ),
1363 : : points, 0.1,
1364 : : QgsAbstractGeometry::MaximumDifference, false, false );
1365 : 1 : QCOMPARE( points.size(), 5 );
1366 : 1 : QGSCOMPARENEAR( points[0].x(), xoff + 0.0, 0.00001 );
1367 : 1 : QGSCOMPARENEAR( points[0].y(), yoff + 0.0, 0.00001 );
1368 : 1 : QGSCOMPARENEAR( points[1].x(), xoff + 1 - sqrt( 2 ) / 2, 0.00001 );
1369 : 1 : QGSCOMPARENEAR( points[1].y(), yoff + -sqrt( 2 ) / 2, 0.00001 );
1370 : 1 : QGSCOMPARENEAR( points[2].x(), xoff + 1.0, 0.00001 );
1371 : 1 : QGSCOMPARENEAR( points[2].y(), yoff + -1.0, 0.00001 );
1372 : 1 : QGSCOMPARENEAR( points[3].x(), xoff + 1 + sqrt( 2 ) / 2, 0.00001 );
1373 : 1 : QGSCOMPARENEAR( points[3].y(), yoff + -sqrt( 2 ) / 2, 0.00001 );
1374 : 1 : QGSCOMPARENEAR( points[4].x(), xoff + 2.0, 0.00001 );
1375 : 1 : QGSCOMPARENEAR( points[4].y(), yoff + 0.0, 0.00001 );
1376 : 1 : }
1377 : :
1378 : 1 : void TestQgsGeometryUtils::testSegmentizeArcFullCircle()
1379 : : {
1380 : 1 : QgsPointSequence points;
1381 : 1 : const double xoff = 1;
1382 : 1 : const double yoff = 100;
1383 : 2 : QgsGeometryUtils::segmentizeArc( QgsPoint( xoff + 0, yoff + 0 ),
1384 : 1 : QgsPoint( xoff + 2, yoff + 0 ),
1385 : 1 : QgsPoint( xoff + 0, yoff + 0 ),
1386 : : points, 0.4,
1387 : : QgsAbstractGeometry::MaximumDifference, false, false );
1388 : 1 : QCOMPARE( points.size(), 5 );
1389 : 1 : QGSCOMPARENEAR( points[0].x(), xoff + 0.0, 0.00001 );
1390 : 1 : QGSCOMPARENEAR( points[0].y(), yoff + 0.0, 0.00001 );
1391 : 1 : QGSCOMPARENEAR( points[1].x(), xoff + 1.0, 0.00001 );
1392 : 1 : QGSCOMPARENEAR( points[1].y(), yoff + -1.0, 0.00001 );
1393 : 1 : QGSCOMPARENEAR( points[2].x(), xoff + 2.0, 0.00001 );
1394 : 1 : QGSCOMPARENEAR( points[2].y(), yoff + 0.0, 0.00001 );
1395 : 1 : QGSCOMPARENEAR( points[3].x(), xoff + 1.0, 0.00001 );
1396 : 1 : QGSCOMPARENEAR( points[3].y(), yoff + 1.0, 0.00001 );
1397 : 1 : QGSCOMPARENEAR( points[4].x(), xoff + 0.0, 0.00001 );
1398 : 1 : QGSCOMPARENEAR( points[4].y(), yoff + 0.0, 0.00001 );
1399 : 1 : }
1400 : :
1401 : 1 : void TestQgsGeometryUtils::testTriangleArea_data()
1402 : : {
1403 : 1 : QTest::addColumn<double>( "aX" );
1404 : 1 : QTest::addColumn<double>( "aY" );
1405 : 1 : QTest::addColumn<double>( "bX" );
1406 : 1 : QTest::addColumn<double>( "bY" );
1407 : 1 : QTest::addColumn<double>( "cX" );
1408 : 1 : QTest::addColumn<double>( "cY" );
1409 : 1 : QTest::addColumn<double>( "expectedResult" );
1410 : :
1411 : 1 : QTest::newRow( "area 1" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 222.5;
1412 : 1 : QTest::newRow( "area 2" ) << 23.0 << 30.0 << 15.0 << 15.0 << 50.0 << 25.0 << 222.5;
1413 : 1 : QTest::newRow( "area 3" ) << 15.0 << 15.0 << 50.0 << 25.0 << 23.0 << 30.0 << 222.5;
1414 : 1 : QTest::newRow( "area 4" ) << -15.0 << 15.0 << -50.0 << 25.0 << -23.0 << 30.0 << 222.5;
1415 : 1 : QTest::newRow( "area 5" ) << 15.0 << 15.0 << 15.0 << 15.0 << 15.0 << 15.0 << 0.0;
1416 : 1 : QTest::newRow( "area 6" ) << 29.0 << 23.0 << 35.0 << 18.0 << 29.0 << 10.0 << 39.0;
1417 : 1 : }
1418 : :
1419 : 6 : void TestQgsGeometryUtils::testTriangleArea()
1420 : : {
1421 : 6 : QFETCH( double, aX );
1422 : 6 : QFETCH( double, aY );
1423 : 6 : QFETCH( double, bX );
1424 : 6 : QFETCH( double, bY );
1425 : 6 : QFETCH( double, cX );
1426 : 6 : QFETCH( double, cY );
1427 : 6 : QFETCH( double, expectedResult );
1428 : :
1429 : 6 : QGSCOMPARENEAR( QgsGeometryUtils::triangleArea( aX, aY, bX, bY, cX, cY ), expectedResult, 0.0000001 );
1430 : 6 : }
1431 : :
1432 : 1 : void TestQgsGeometryUtils::testWeightedPointInTriangle_data()
1433 : : {
1434 : 1 : QTest::addColumn<double>( "aX" );
1435 : 1 : QTest::addColumn<double>( "aY" );
1436 : 1 : QTest::addColumn<double>( "bX" );
1437 : 1 : QTest::addColumn<double>( "bY" );
1438 : 1 : QTest::addColumn<double>( "cX" );
1439 : 1 : QTest::addColumn<double>( "cY" );
1440 : 1 : QTest::addColumn<double>( "weightB" );
1441 : 1 : QTest::addColumn<double>( "weightC" );
1442 : 1 : QTest::addColumn<double>( "expectedX" );
1443 : 1 : QTest::addColumn<double>( "expectedY" );
1444 : :
1445 : 1 : QTest::newRow( "weighted 1" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.0 << 0.0 << 15.0 << 15.0;
1446 : 1 : QTest::newRow( "weighted 2" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.5 << 0.0 << 19.0 << 22.5;
1447 : 1 : QTest::newRow( "weighted 3" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 1.0 << 0.0 << 23.0 << 30.0;
1448 : 1 : QTest::newRow( "weighted 4" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.0 << 0.5 << 32.5 << 20.0;
1449 : 1 : QTest::newRow( "weighted 5" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.0 << 1.0 << 50.0 << 25.0;
1450 : 1 : QTest::newRow( "weighted 6" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 0.5 << 0.5 << 36.5 << 27.5;
1451 : 1 : QTest::newRow( "weighted 7" ) << 15.0 << 15.0 << 23.0 << 30.0 << 50.0 << 25.0 << 1.0 << 1.0 << 15.0 << 15.0;
1452 : 1 : QTest::newRow( "weighted 8" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 25.0 << 0.0 << 0.0 << 15.0 << 16.0;
1453 : 1 : QTest::newRow( "weighted 9" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 25.0 << 1.0 << 0.0 << 15.0 << 16.0;
1454 : 1 : QTest::newRow( "weighted 10" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 16.0 << 0.0 << 1.0 << 15.0 << 16.0;
1455 : 1 : QTest::newRow( "weighted 11" ) << 15.0 << 16.0 << 15.0 << 16.0 << 15.0 << 16.0 << 1.0 << 1.0 << 15.0 << 16.0;
1456 : 1 : QTest::newRow( "weighted 12" ) << -15.0 << -15.0 << -23.0 << -30.0 << -50.0 << -25.0 << 0.5 << 0.5 << -36.5 << -27.5;
1457 : 1 : }
1458 : :
1459 : 12 : void TestQgsGeometryUtils::testWeightedPointInTriangle()
1460 : : {
1461 : 12 : QFETCH( double, aX );
1462 : 12 : QFETCH( double, aY );
1463 : 12 : QFETCH( double, bX );
1464 : 12 : QFETCH( double, bY );
1465 : 12 : QFETCH( double, cX );
1466 : 12 : QFETCH( double, cY );
1467 : 12 : QFETCH( double, weightB );
1468 : 12 : QFETCH( double, weightC );
1469 : 12 : QFETCH( double, expectedX );
1470 : 12 : QFETCH( double, expectedY );
1471 : :
1472 : : double x, y;
1473 : 12 : QgsGeometryUtils::weightedPointInTriangle( aX, aY, bX, bY, cX, cY, weightB, weightC, x, y );
1474 : 12 : QGSCOMPARENEAR( x, expectedX, 0.0000001 );
1475 : 12 : QGSCOMPARENEAR( y, expectedY, 0.0000001 );
1476 : 12 : }
1477 : :
1478 : 1 : void TestQgsGeometryUtils::testPointContinuesArc()
1479 : : {
1480 : : // normal arcs
1481 : 1 : QVERIFY( QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 2, 0 ), QgsPoint( 1, -1 ), 0.000000001, 0.000001 ) );
1482 : 1 : QVERIFY( QgsGeometryUtils::pointContinuesArc( QgsPoint( 2, 0 ), QgsPoint( 1, 1 ), QgsPoint( 0, 0 ), QgsPoint( 1, -1 ), 0.000000001, 0.000001 ) );
1483 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 2, 0 ), QgsPoint( 3, 0 ), 0.000000001, 0.000001 ) );
1484 : 1 : QVERIFY( QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 0.29289321881, 0.707106781 ), QgsPoint( 1, 1 ), QgsPoint( 1.707106781, 0.707106781 ), 0.00001, 0.00001 ) );
1485 : :
1486 : : // irregular spacing
1487 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 0.29289321881, 0.707106781 ), QgsPoint( 1, 1 ), QgsPoint( 1, -1 ), 0.00001, 0.00001 ) );
1488 : :
1489 : : // inside current arc
1490 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 0.29289321881, 0.707106781 ), QgsPoint( 1, 1 ), QgsPoint( 0.29289321881, 0.707106781 ), 0.00001, 0.00001 ) );
1491 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 0.29289321881, 0.707106781 ), QgsPoint( 1, 1 ), QgsPoint( 1, 1 ), 0.00001, 0.00001 ) );
1492 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 0.29289321881, 0.707106781 ), QgsPoint( 1, 1 ), QgsPoint( 0, 0 ), 0.00001, 0.00001 ) );
1493 : :
1494 : : // colinear points
1495 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 0.5, 0.5 ), QgsPoint( 1, 1 ), QgsPoint( 1.5, 1.5 ), 0.00001, 0.00001 ) );
1496 : :
1497 : : // with a bit more tolerance
1498 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 2, 0 ), QgsPoint( 1.01, -1 ), 0.000000001, 0.05 ) );
1499 : 1 : QVERIFY( QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 2, 0 ), QgsPoint( 1.01, -1 ), 0.1, 0.05 ) );
1500 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 2, 0 ), QgsPoint( 1.01, -1 ), 0.1, 0.000001 ) );
1501 : 1 : QVERIFY( !QgsGeometryUtils::pointContinuesArc( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 2, 0 ), QgsPoint( 1.01, -1 ), 0.000000001, 0.05 ) );
1502 : 1 : }
1503 : :
1504 : 1 : void TestQgsGeometryUtils::testBisector()
1505 : : {
1506 : : double x, y;
1507 : 1 : QVERIFY( QgsGeometryUtils::bisector( 5, 5, 0, 0, -7, 11, x, y ) );
1508 : 1 : QGSCOMPARENEAR( x, -2.416, 10e-3 );
1509 : 1 : QGSCOMPARENEAR( y, 3.797, 10e-3 );
1510 : :
1511 : 1 : QVERIFY( QgsGeometryUtils::bisector( 2.5, 2, 0, 0, 5, 0, x, y ) );
1512 : 1 : QGSCOMPARENEAR( x, 2.5, 10e-3 );
1513 : 1 : QGSCOMPARENEAR( y, 0, 10e-3 );
1514 : :
1515 : : // collinear
1516 : 1 : QVERIFY( !QgsGeometryUtils::bisector( 5, 5, 0, 0, 1, 1, x, y ) );
1517 : 1 : }
1518 : :
1519 : 1 : void TestQgsGeometryUtils::testAngleBisector()
1520 : : {
1521 : : double x, y, angle;
1522 : 1 : QVERIFY( QgsGeometryUtils::angleBisector( 0, 0, 0, 5, 0, 0, 5, 0, x, y, angle ) );
1523 : 1 : QGSCOMPARENEAR( x, 0.0, 10e-3 );
1524 : 1 : QGSCOMPARENEAR( y, 0.0, 10e-3 );
1525 : 1 : QGSCOMPARENEAR( angle, 45.0, 10e-3 );
1526 : :
1527 : 1 : QVERIFY( QgsGeometryUtils::angleBisector( 0, 0, 5, 0, 2.5, 0, 7.5, 5, x, y, angle ) );
1528 : 1 : QGSCOMPARENEAR( x, 2.5, 10e-3 );
1529 : 1 : QGSCOMPARENEAR( y, 0.0, 10e-3 );
1530 : 1 : QGSCOMPARENEAR( angle, 67.5, 10e-3 );
1531 : :
1532 : 1 : QVERIFY( QgsGeometryUtils::angleBisector( 0, 0, 5, 0, 15, -5, 7.5, 5, x, y, angle ) );
1533 : 1 : QGSCOMPARENEAR( x, 11.25, 10e-3 );
1534 : 1 : QGSCOMPARENEAR( y, 0.0, 10e-3 );
1535 : 1 : QGSCOMPARENEAR( angle, 26.565, 10e-3 );
1536 : :
1537 : : // collinear
1538 : 1 : QVERIFY( !QgsGeometryUtils::angleBisector( 0, 0, 5, 0, 5, 5, 10, 5, x, y, angle ) );
1539 : 1 : QVERIFY( !QgsGeometryUtils::angleBisector( 0, 0, 5, 0, 6, 0, 10, 0, x, y, angle ) );
1540 : 1 : }
1541 : :
1542 : 1 : void TestQgsGeometryUtils::testPerpendicularOffsetPoint()
1543 : : {
1544 : : double x, y;
1545 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 1, 5, 11, 5, 0.5, 2, &x, &y );
1546 : 1 : QGSCOMPARENEAR( x, 6.0, 10e-3 );
1547 : 1 : QGSCOMPARENEAR( y, 3.0, 10e-3 );
1548 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 1, 5, 11, 5, 0.5, -2, &x, &y );
1549 : 1 : QGSCOMPARENEAR( x, 6.0, 10e-3 );
1550 : 1 : QGSCOMPARENEAR( y, 7.0, 10e-3 );
1551 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 1, 5, 11, 5, 0.1, 2, &x, &y );
1552 : 1 : QGSCOMPARENEAR( x, 2.0, 10e-3 );
1553 : 1 : QGSCOMPARENEAR( y, 3.0, 10e-3 );
1554 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 1, 5, 11, 5, 0.9, 2, &x, &y );
1555 : 1 : QGSCOMPARENEAR( x, 10.0, 10e-3 );
1556 : 1 : QGSCOMPARENEAR( y, 3.0, 10e-3 );
1557 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 1, 5, 11, 5, 0.0, 2, &x, &y );
1558 : 1 : QGSCOMPARENEAR( x, 1.0, 10e-3 );
1559 : 1 : QGSCOMPARENEAR( y, 3.0, 10e-3 );
1560 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 1, 5, 11, 5, 1.0, 2, &x, &y );
1561 : 1 : QGSCOMPARENEAR( x, 11.0, 10e-3 );
1562 : 1 : QGSCOMPARENEAR( y, 3.0, 10e-3 );
1563 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 5, 1, 5, 11, 0.5, 2, &x, &y );
1564 : 1 : QGSCOMPARENEAR( x, 7.0, 10e-3 );
1565 : 1 : QGSCOMPARENEAR( y, 6.0, 10e-3 );
1566 : 1 : QgsGeometryUtils::perpendicularOffsetPointAlongSegment( 5, 1, 5, 11, 0.5, -2, &x, &y );
1567 : 1 : QGSCOMPARENEAR( x, 3.0, 10e-3 );
1568 : 1 : QGSCOMPARENEAR( y, 6.0, 10e-3 );
1569 : 1 : }
1570 : :
1571 : 1 : void TestQgsGeometryUtils::testClosestSideOfRectangle()
1572 : : {
1573 : : // outside rect
1574 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 1, -19 ), 7 );
1575 : :
1576 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 1, -17 ), 7 );
1577 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 9, -17 ), 8 );
1578 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 9, -1 ), 1 );
1579 : :
1580 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 1, -21 ), 7 );
1581 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 9, -21 ), 6 );
1582 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 9, -22 ), 5 );
1583 : :
1584 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 14, -1 ), 1 );
1585 : :
1586 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 18, -1 ), 1 );
1587 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 17, -17 ), 2 );
1588 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 20, -17 ), 3 );
1589 : :
1590 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 18, -19 ), 3 );
1591 : :
1592 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 18, -21 ), 3 );
1593 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 17, -21 ), 4 );
1594 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 17, -25 ), 5 );
1595 : :
1596 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 14, -21 ), 5 );
1597 : :
1598 : : // inside rect
1599 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 10.5, -19 ), 7 );
1600 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 16.5, -19 ), 3 );
1601 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 14, -18.5 ), 1 );
1602 : 1 : QCOMPARE( QgsGeometryUtils::closestSideOfRectangle( 16, -20, 10, -18, 14, -19.5 ), 5 );
1603 : 1 : }
1604 : :
1605 : 1 : QGSTEST_MAIN( TestQgsGeometryUtils )
1606 : : #include "testqgsgeometryutils.moc"
|