Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/unittest/src/utils/geom/PositionVectorTest.cpp
169684 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
4
// This program and the accompanying materials are made available under the
5
// terms of the Eclipse Public License 2.0 which is available at
6
// https://www.eclipse.org/legal/epl-2.0/
7
// This Source Code may also be made available under the following Secondary
8
// Licenses when the conditions for such availability set forth in the Eclipse
9
// Public License 2.0 are satisfied: GNU General Public License, version 2
10
// or later which is available at
11
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13
/****************************************************************************/
14
/// @file PositionVectorTest.cpp
15
/// @author Matthias Heppner
16
/// @author Michael Behrisch
17
/// @author Jakob Erdmann
18
/// @date 2009-10-24
19
///
20
// Tests the class PositionVector
21
/****************************************************************************/
22
#include <config.h>
23
24
#include <gtest/gtest.h>
25
#include <utils/geom/PositionVector.h>
26
#include <utils/geom/Boundary.h>
27
#include <utils/geom/GeomHelper.h>
28
#include <utils/common/UtilExceptions.h>
29
#include <utils/common/MsgHandler.h>
30
#include <utils/iodevices/OutputDevice.h>
31
32
33
#define EXPECT_DOUBLEVEC_EQUAL(v1, v2) \
34
{ \
35
EXPECT_EQ(v1.size(), v2.size()); \
36
if (v1.size() == v2.size()) { \
37
for (int i = 0; i < (int)v1.size(); ++i) { \
38
EXPECT_DOUBLE_EQ(v1[i], v2[i]); \
39
} \
40
} \
41
} \
42
43
44
#define EXPECT_POSITIONVEC_EQUAL(v1, v2) \
45
{ \
46
EXPECT_EQ(v1.size(), v2.size()); \
47
if (v1.size() == v2.size()) { \
48
for (int i = 0; i < (int)v1.size(); ++i) { \
49
EXPECT_DOUBLE_EQ((v1[i].x()), (v2[i].x())); \
50
EXPECT_DOUBLE_EQ((v1[i].y()), (v2[i].y())); \
51
EXPECT_DOUBLE_EQ((v1[i].z()), (v2[i].z())); \
52
} \
53
} \
54
} \
55
56
57
class PositionVectorTest : public testing::Test {
58
protected :
59
PositionVector* vectorPolygon;
60
PositionVector* vectorLine;
61
PositionVector* vectorTrianglePositiveCoords;
62
PositionVector* vectorTriangleNegativeCoords;
63
PositionVector* vectorRectangleOriginAlignedCorners;
64
65
virtual void SetUp() {
66
vectorPolygon = new PositionVector();
67
vectorPolygon->push_back(Position(0, 0));
68
vectorPolygon->push_back(Position(0, 2));
69
vectorPolygon->push_back(Position(2, 4));
70
vectorPolygon->push_back(Position(4, 2));
71
vectorPolygon->push_back(Position(4, 0));
72
73
vectorLine = new PositionVector();
74
vectorLine->push_back(Position(0, 0));
75
vectorLine->push_back(Position(2, 2));
76
77
vectorTrianglePositiveCoords = new PositionVector();
78
vectorTrianglePositiveCoords->push_back(Position(1, 1));
79
vectorTrianglePositiveCoords->push_back(Position(3, 0));
80
vectorTrianglePositiveCoords->push_back(Position(2, 3));
81
82
vectorTriangleNegativeCoords = new PositionVector();
83
vectorTriangleNegativeCoords->push_back(Position(2, -1));
84
vectorTriangleNegativeCoords->push_back(Position(1, -1));
85
vectorTriangleNegativeCoords->push_back(Position(2, -3));
86
87
vectorRectangleOriginAlignedCorners = new PositionVector();
88
vectorRectangleOriginAlignedCorners->push_back(Position(1, 1));
89
vectorRectangleOriginAlignedCorners->push_back(Position(3, 1));
90
vectorRectangleOriginAlignedCorners->push_back(Position(3, 3));
91
vectorRectangleOriginAlignedCorners->push_back(Position(1, 3));
92
}
93
94
virtual void TearDown() {
95
delete vectorPolygon;
96
delete vectorLine;
97
delete vectorTrianglePositiveCoords;
98
delete vectorTriangleNegativeCoords;
99
delete vectorRectangleOriginAlignedCorners;
100
}
101
102
};
103
104
/* Test the method 'around'*/
105
TEST_F(PositionVectorTest, test_method_around) {
106
107
EXPECT_TRUE(vectorPolygon->around(Position(1, 1)));
108
EXPECT_TRUE(vectorPolygon->around(Position(1, 2)));
109
EXPECT_FALSE(vectorPolygon->around(Position(4, 4)));
110
EXPECT_FALSE(vectorPolygon->around(Position(0, 0)));
111
112
EXPECT_FALSE(vectorLine->around(Position(1, 1)));
113
EXPECT_FALSE(vectorLine->around(Position(0, 2)));
114
115
// with positive offset
116
EXPECT_TRUE(vectorPolygon->around(Position(4, 2), 1));
117
EXPECT_FALSE(vectorPolygon->around(Position(5, 2), 1));
118
// what was true remains true
119
EXPECT_TRUE(vectorPolygon->around(Position(1, 1), POSITION_EPS));
120
EXPECT_TRUE(vectorPolygon->around(Position(1, 2), POSITION_EPS));
121
122
// with negative offset
123
EXPECT_FALSE(vectorPolygon->around(Position(4, 2), -POSITION_EPS));
124
EXPECT_TRUE(vectorPolygon->around(Position(1, 1), -1));
125
EXPECT_FALSE(vectorPolygon->around(Position(0.5, 0.5), -1));
126
}
127
128
/* Test the method 'area'*/
129
TEST_F(PositionVectorTest, test_method_area) {
130
PositionVector square;
131
square.push_back(Position(0, 0));
132
square.push_back(Position(1, 0));
133
square.push_back(Position(1, 1));
134
square.push_back(Position(0, 1)); // open
135
EXPECT_DOUBLE_EQ(square.area(), 1);
136
square.push_back(Position(0, 0)); // closed
137
EXPECT_DOUBLE_EQ(square.area(), 1);
138
}
139
140
/* Test the method 'scaleRelative'.*/
141
TEST_F(PositionVectorTest, test_method_scaleRelative) {
142
PositionVector square;
143
square.push_back(Position(0, 0));
144
square.push_back(Position(1, 0));
145
square.push_back(Position(1, 1));
146
square.push_back(Position(0, 1));
147
square.push_back(Position(0, 0));
148
EXPECT_DOUBLE_EQ(square.area(), 1);
149
square.scaleRelative(3);
150
EXPECT_DOUBLE_EQ(square.area(), 9);
151
152
PositionVector expected;
153
expected.push_back(Position(-1, -1));
154
expected.push_back(Position(2, -1));
155
expected.push_back(Position(2, 2));
156
expected.push_back(Position(-1, 2));
157
expected.push_back(Position(-1, -1));
158
159
EXPECT_EQ(expected.getCentroid(), square.getCentroid());
160
for (int i = 0; i < (int)square.size(); i++) {
161
EXPECT_DOUBLE_EQ(expected[i].x(), square[i].x());
162
EXPECT_DOUBLE_EQ(expected[i].y(), square[i].y());
163
}
164
}
165
166
/* Test the method 'getCentroid'.*/
167
TEST_F(PositionVectorTest, test_method_getCentroid) {
168
PositionVector square;
169
square.push_back(Position(0, 0));
170
square.push_back(Position(1, 0));
171
square.push_back(Position(1, 1));
172
square.push_back(Position(0, 1));
173
EXPECT_EQ(Position(0.5, 0.5), square.getCentroid());
174
175
Position pos2 = vectorLine->getCentroid();
176
EXPECT_DOUBLE_EQ(1, pos2.x());
177
EXPECT_DOUBLE_EQ(1, pos2.y());
178
}
179
180
/* Test the method 'getPolygonCenter'.*/
181
TEST_F(PositionVectorTest, test_method_getPolygonCenter) {
182
Position pos = vectorPolygon->getPolygonCenter();
183
EXPECT_DOUBLE_EQ(2, pos.x());
184
EXPECT_DOUBLE_EQ(1.6, pos.y());
185
Position pos2 = vectorLine->getPolygonCenter();
186
EXPECT_DOUBLE_EQ(1, pos2.x());
187
EXPECT_DOUBLE_EQ(1, pos2.y());
188
}
189
190
191
/* Test the method 'getBoxBoundary'*/
192
TEST_F(PositionVectorTest, test_method_getBoxBoundary) {
193
Boundary bound = vectorPolygon->getBoxBoundary();
194
EXPECT_DOUBLE_EQ(bound.xmax(), 4);
195
EXPECT_DOUBLE_EQ(bound.xmin(), 0);
196
EXPECT_DOUBLE_EQ(bound.ymax(), 4);
197
EXPECT_DOUBLE_EQ(bound.ymin(), 0);
198
}
199
200
/* Test the method 'splitAt'*/
201
TEST_F(PositionVectorTest, test_method_splitAt) {
202
PositionVector vec;
203
vec.push_back(Position(0, 0));
204
vec.push_back(Position(2, 0));
205
vec.push_back(Position(5, 0));
206
double smallDiff = POSITION_EPS / 2;
207
std::pair<PositionVector, PositionVector> result;
208
// split in first segment
209
result = vec.splitAt(1);
210
EXPECT_EQ(2, (int)result.first.size());
211
EXPECT_DOUBLE_EQ(0., result.first[0].x());
212
EXPECT_DOUBLE_EQ(1., result.first[1].x());
213
EXPECT_EQ(3, (int)result.second.size());
214
EXPECT_DOUBLE_EQ(1., result.second[0].x());
215
EXPECT_DOUBLE_EQ(2., result.second[1].x());
216
EXPECT_DOUBLE_EQ(5., result.second[2].x());
217
// split in second segment
218
result = vec.splitAt(4);
219
EXPECT_EQ(3, (int)result.first.size());
220
EXPECT_DOUBLE_EQ(0., result.first[0].x());
221
EXPECT_DOUBLE_EQ(2., result.first[1].x());
222
EXPECT_DOUBLE_EQ(4., result.first[2].x());
223
EXPECT_EQ(2, (int)result.second.size());
224
EXPECT_DOUBLE_EQ(4., result.second[0].x());
225
EXPECT_DOUBLE_EQ(5., result.second[1].x());
226
// split close before inner point
227
result = vec.splitAt(2 - smallDiff);
228
EXPECT_EQ(2, (int)result.first.size());
229
EXPECT_DOUBLE_EQ(0., result.first[0].x());
230
EXPECT_DOUBLE_EQ(2., result.first[1].x());
231
EXPECT_EQ(2, (int)result.second.size());
232
EXPECT_DOUBLE_EQ(2., result.second[0].x());
233
EXPECT_DOUBLE_EQ(5., result.second[1].x());
234
// split close after inner point
235
result = vec.splitAt(2 + smallDiff);
236
EXPECT_EQ(2, (int)result.first.size());
237
EXPECT_DOUBLE_EQ(0., result.first[0].x());
238
EXPECT_DOUBLE_EQ(2., result.first[1].x());
239
EXPECT_EQ(2, (int)result.second.size());
240
EXPECT_DOUBLE_EQ(2., result.second[0].x());
241
EXPECT_DOUBLE_EQ(5., result.second[1].x());
242
243
// catch a bug
244
vec.push_back(Position(6, 0));
245
vec.push_back(Position(8, 0));
246
// split at inner point
247
result = vec.splitAt(5);
248
EXPECT_EQ(3, (int)result.first.size());
249
EXPECT_DOUBLE_EQ(0., result.first[0].x());
250
EXPECT_DOUBLE_EQ(2., result.first[1].x());
251
EXPECT_DOUBLE_EQ(5., result.first[2].x());
252
EXPECT_EQ(3, (int)result.second.size());
253
EXPECT_DOUBLE_EQ(5., result.second[0].x());
254
EXPECT_DOUBLE_EQ(6., result.second[1].x());
255
EXPECT_DOUBLE_EQ(8., result.second[2].x());
256
257
// split short vector
258
PositionVector vec2;
259
vec2.push_back(Position(0, 0));
260
vec2.push_back(Position(2, 0));
261
result = vec2.splitAt(1);
262
EXPECT_EQ(2, (int)result.first.size());
263
EXPECT_DOUBLE_EQ(0., result.first[0].x());
264
EXPECT_DOUBLE_EQ(1., result.first[1].x());
265
EXPECT_EQ(2, (int)result.second.size());
266
EXPECT_DOUBLE_EQ(1., result.second[0].x());
267
EXPECT_DOUBLE_EQ(2., result.second[1].x());
268
269
// split very short vector
270
PositionVector vec3;
271
vec3.push_back(Position(0, 0));
272
vec3.push_back(Position(POSITION_EPS, 0));
273
// supress expected warning
274
MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
275
result = vec3.splitAt(smallDiff);
276
MsgHandler::getWarningInstance()->addRetriever(&OutputDevice::getDevice("stderr"));
277
278
EXPECT_EQ(2, (int)result.first.size());
279
EXPECT_DOUBLE_EQ(0., result.first[0].x());
280
EXPECT_DOUBLE_EQ(smallDiff, result.first[1].x());
281
EXPECT_EQ(2, (int)result.second.size());
282
EXPECT_DOUBLE_EQ(smallDiff, result.second[0].x());
283
EXPECT_DOUBLE_EQ(POSITION_EPS, result.second[1].x());
284
}
285
286
287
/* Test the method 'intersectsAtLengths2D'*/
288
TEST_F(PositionVectorTest, test_method_intersectsAtLengths2D) {
289
PositionVector vec1;
290
vec1.push_back(Position(0, 0, 42));
291
vec1.push_back(Position(100, 0, 0));
292
293
PositionVector vec2;
294
vec2.push_back(Position(0, 0, 0));
295
vec2.push_back(Position(3, 1, 0));
296
EXPECT_DOUBLE_EQ(0, vec1.intersectsAtLengths2D(vec2)[0]);
297
}
298
299
300
/* Test the method 'nearest_offset_to_point2D'*/
301
TEST_F(PositionVectorTest, test_method_nearest_offset_to_point2D) {
302
PositionVector vec1;
303
vec1.push_back(Position(0, 1, 0));
304
vec1.push_back(Position(0, 0, 0));
305
vec1.push_back(Position(1, 0, 0));
306
307
EXPECT_DOUBLE_EQ(1, vec1.nearest_offset_to_point2D(Position(-1, -1), false));
308
EXPECT_DOUBLE_EQ(1, vec1.nearest_offset_to_point2D(Position(-1, -1), true));
309
EXPECT_DOUBLE_EQ(2, vec1.nearest_offset_to_point2D(Position(2, 1), false));
310
EXPECT_DOUBLE_EQ(0, vec1.nearest_offset_to_point2D(Position(2, 1), true));
311
EXPECT_DOUBLE_EQ(2, vec1.nearest_offset_to_point2D(Position(3, 2), false));
312
EXPECT_DOUBLE_EQ(-1, vec1.nearest_offset_to_point2D(Position(3, 2), true));
313
}
314
315
316
TEST_F(PositionVectorTest, test_method_extrapolate2D) {
317
PositionVector vec1;
318
vec1.push_back(Position(0, 1, 0));
319
vec1.push_back(Position(0, 0, 0));
320
vec1.push_back(Position(1, 0, 0));
321
vec1.extrapolate2D(1);
322
EXPECT_EQ(Position(0, 2, 0), vec1[0]);
323
EXPECT_EQ(Position(0, 0, 0), vec1[1]);
324
EXPECT_EQ(Position(2, 0, 0), vec1[2]);
325
326
PositionVector vec2;
327
vec2.push_back(Position(0, 1, 0));
328
vec2.push_back(Position(0, 0, 1));
329
vec2.push_back(Position(1, 0, 0));
330
vec2.extrapolate2D(1);
331
// EXPECT_EQ(Position(0,2,0), vec2[0]);
332
// EXPECT_EQ(Position(0,0,0), vec2[1]);
333
// EXPECT_EQ(Position(2,0,0), vec2[2]);
334
335
PositionVector vec3;
336
vec3.push_back(Position(-.5, 1));
337
vec3.push_back(Position(-.5, -.5));
338
vec3.push_back(Position(1, -.5));
339
vec3.extrapolate2D(.5);
340
EXPECT_EQ(Position(-.5, 1.5), vec3[0]);
341
EXPECT_EQ(Position(-.5, -.5), vec3[1]);
342
EXPECT_EQ(Position(1.5, -.5), vec3[2]);
343
344
}
345
346
347
/* Test the method 'move2side'*/
348
TEST_F(PositionVectorTest, test_method_move2side) {
349
PositionVector vec1;
350
vec1.push_back(Position(0, 1, 0));
351
vec1.push_back(Position(0, 0, 0));
352
vec1.push_back(Position(1, 0, 0));
353
vec1.move2side(.5);
354
EXPECT_EQ(Position(-.5, 1), vec1[0]);
355
EXPECT_EQ(Position(-.5, -.5), vec1[1]);
356
EXPECT_EQ(Position(1, -.5), vec1[2]);
357
vec1.move2side(-1);
358
EXPECT_EQ(Position(.5, 1), vec1[0]);
359
EXPECT_EQ(Position(.5, .5), vec1[1]);
360
EXPECT_EQ(Position(1, .5), vec1[2]);
361
362
// parallel case
363
PositionVector vec2;
364
vec2.push_back(Position(0, 0, 0));
365
vec2.push_back(Position(1, 0, 0));
366
vec2.push_back(Position(3, 0, 0));
367
vec2.move2side(.5);
368
EXPECT_EQ(Position(0, -.5), vec2[0]);
369
EXPECT_EQ(Position(1, -.5), vec2[1]);
370
EXPECT_EQ(Position(3, -.5), vec2[2]);
371
vec2.move2side(-1);
372
EXPECT_EQ(Position(0, .5), vec2[0]);
373
EXPECT_EQ(Position(1, .5), vec2[1]);
374
EXPECT_EQ(Position(3, .5), vec2[2]);
375
376
// counterparallel case
377
{
378
PositionVector vec3;
379
vec3.push_back(Position(0, 0, 0));
380
vec3.push_back(Position(3, 0, 0));
381
vec3.push_back(Position(1, 0, 0));
382
vec3.move2side(.5);
383
// clipping removal eliminates the middle point
384
EXPECT_EQ(Position(0, -.5), vec3[0]);
385
EXPECT_EQ(Position(1, -.5), vec3[1]);
386
}
387
// bad input: subsequent identical points
388
{
389
PositionVector vec4;
390
vec4.push_back(Position(0, 0, 0));
391
vec4.push_back(Position(0, 0, 0));
392
vec4.push_back(Position(1, 0, 0));
393
vec4.move2side(-2);
394
EXPECT_EQ(2, (int)vec4.size());
395
EXPECT_EQ(Position(0, 2), vec4[0]);
396
EXPECT_EQ(Position(1, 2), vec4[1]);
397
}
398
}
399
400
/* Test the method 'transformToVectorCoordinates'*/
401
TEST_F(PositionVectorTest, test_method_transformToVectorCoordinates) {
402
{
403
PositionVector vec1;
404
vec1.push_back(Position(1, 0));
405
vec1.push_back(Position(10, 0));
406
vec1.push_back(Position(10, 5));
407
vec1.push_back(Position(20, 5));
408
Position on(4, 0);
409
Position left(4, 1);
410
Position right(4, -1);
411
Position left2(4, 2);
412
Position right2(4, -2);
413
Position cornerRight(13, -4);
414
Position cornerLeft(7, 9);
415
Position before(0, -1);
416
Position beyond(24, 9);
417
418
EXPECT_EQ(Position(3, 0), vec1.transformToVectorCoordinates(on));
419
EXPECT_EQ(Position(3, -1), vec1.transformToVectorCoordinates(left));
420
EXPECT_EQ(Position(3, 1), vec1.transformToVectorCoordinates(right));
421
EXPECT_EQ(Position(3, -2), vec1.transformToVectorCoordinates(left2));
422
EXPECT_EQ(Position(3, 2), vec1.transformToVectorCoordinates(right2));
423
EXPECT_EQ(Position(9, 5), vec1.transformToVectorCoordinates(cornerRight));
424
EXPECT_EQ(Position(14, -5), vec1.transformToVectorCoordinates(cornerLeft));
425
426
EXPECT_EQ(Position::INVALID, vec1.transformToVectorCoordinates(before));
427
EXPECT_EQ(Position::INVALID, vec1.transformToVectorCoordinates(beyond));
428
EXPECT_EQ(Position(-1, 1), vec1.transformToVectorCoordinates(before, true));
429
EXPECT_EQ(Position(28, -4), vec1.transformToVectorCoordinates(beyond, true));
430
}
431
432
{
433
PositionVector vec1; // the same tests as before, mirrored on x-axis
434
vec1.push_back(Position(1, 0));
435
vec1.push_back(Position(10, 0));
436
vec1.push_back(Position(10, -5));
437
vec1.push_back(Position(20, -5));
438
Position on(4, 0);
439
Position left(4, -1);
440
Position right(4, 1);
441
Position left2(4, -2);
442
Position right2(4, 2);
443
Position cornerRight(13, 4);
444
Position cornerLeft(7, -9);
445
Position before(0, 1);
446
Position beyond(24, -9);
447
448
EXPECT_EQ(Position(3, 0), vec1.transformToVectorCoordinates(on));
449
EXPECT_EQ(Position(3, 1), vec1.transformToVectorCoordinates(left));
450
EXPECT_EQ(Position(3, -1), vec1.transformToVectorCoordinates(right));
451
EXPECT_EQ(Position(3, 2), vec1.transformToVectorCoordinates(left2));
452
EXPECT_EQ(Position(3, -2), vec1.transformToVectorCoordinates(right2));
453
EXPECT_EQ(Position(9, -5), vec1.transformToVectorCoordinates(cornerRight));
454
EXPECT_EQ(Position(14, 5), vec1.transformToVectorCoordinates(cornerLeft));
455
456
EXPECT_EQ(Position::INVALID, vec1.transformToVectorCoordinates(before));
457
EXPECT_EQ(Position::INVALID, vec1.transformToVectorCoordinates(beyond));
458
EXPECT_EQ(Position(-1, -1), vec1.transformToVectorCoordinates(before, true));
459
EXPECT_EQ(Position(28, 4), vec1.transformToVectorCoordinates(beyond, true));
460
}
461
}
462
463
464
/* Test the method 'distance'*/
465
TEST_F(PositionVectorTest, test_method_distance) {
466
{
467
PositionVector vec1;
468
vec1.push_back(Position(1, 0));
469
vec1.push_back(Position(10, 0));
470
vec1.push_back(Position(10, 5));
471
vec1.push_back(Position(20, 5));
472
Position on(4, 0);
473
Position left(4, 1);
474
Position right(4, -1);
475
Position left2(4, 2);
476
Position right2(4, -2);
477
Position cornerRight(13, -4);
478
Position cornerLeft(7, 9);
479
Position before(-3, -3);
480
Position beyond(24, 8);
481
482
EXPECT_EQ(0, vec1.distance2D(on));
483
EXPECT_EQ(1, vec1.distance2D(left));
484
EXPECT_EQ(1, vec1.distance2D(right));
485
EXPECT_EQ(2, vec1.distance2D(left2));
486
EXPECT_EQ(2, vec1.distance2D(right2));
487
EXPECT_EQ(5, vec1.distance2D(cornerRight));
488
EXPECT_EQ(5, vec1.distance2D(cornerLeft));
489
490
EXPECT_EQ(GeomHelper::INVALID_OFFSET, vec1.distance2D(before, true));
491
EXPECT_EQ(GeomHelper::INVALID_OFFSET, vec1.distance2D(beyond, true));
492
EXPECT_EQ(5, vec1.distance2D(before));
493
EXPECT_EQ(5, vec1.distance2D(beyond));
494
}
495
496
{
497
PositionVector vec1; // the same tests as before, mirrored on x-axis
498
vec1.push_back(Position(1, 0));
499
vec1.push_back(Position(10, 0));
500
vec1.push_back(Position(10, -5));
501
vec1.push_back(Position(20, -5));
502
Position on(4, 0);
503
Position left(4, -1);
504
Position right(4, 1);
505
Position left2(4, -2);
506
Position right2(4, 2);
507
Position cornerRight(13, 4);
508
Position cornerLeft(7, -9);
509
Position before(-3, 3);
510
Position beyond(24, -8);
511
512
EXPECT_EQ(0, vec1.distance2D(on));
513
EXPECT_EQ(1, vec1.distance2D(left));
514
EXPECT_EQ(1, vec1.distance2D(right));
515
EXPECT_EQ(2, vec1.distance2D(left2));
516
EXPECT_EQ(2, vec1.distance2D(right2));
517
EXPECT_EQ(5, vec1.distance2D(cornerRight));
518
EXPECT_EQ(5, vec1.distance2D(cornerLeft));
519
520
EXPECT_EQ(GeomHelper::INVALID_OFFSET, vec1.distance2D(before, true));
521
EXPECT_EQ(GeomHelper::INVALID_OFFSET, vec1.distance2D(beyond, true));
522
EXPECT_EQ(5, vec1.distance2D(before));
523
EXPECT_EQ(5, vec1.distance2D(beyond));
524
}
525
}
526
527
528
/* Test the method 'distance'*/
529
TEST_F(PositionVectorTest, test_method_distances) {
530
{
531
PositionVector vec1;
532
vec1.push_back(Position(0, 0));
533
vec1.push_back(Position(10, 0));
534
535
PositionVector vec2;
536
vec2.push_back(Position(1, 0));
537
vec2.push_back(Position(5, 2));
538
vec2.push_back(Position(10, 0));
539
vec2.push_back(Position(14, 3));
540
541
PositionVector vec3;
542
543
std::vector<double> res1;
544
res1.push_back(1);
545
res1.push_back(0);
546
res1.push_back(0);
547
res1.push_back(2);
548
res1.push_back(0);
549
res1.push_back(5);
550
EXPECT_DOUBLEVEC_EQUAL(res1, vec1.distances(vec2));
551
552
553
std::vector<double> res2;
554
//invalid: res1.push_back(1);
555
res2.push_back(0);
556
res2.push_back(0);
557
res2.push_back(2);
558
res2.push_back(0);
559
//invalid: res2.push_back(5);
560
EXPECT_DOUBLEVEC_EQUAL(res2, vec1.distances(vec2, true));
561
562
563
std::vector<double> res3;
564
res3.push_back(std::numeric_limits<double>::max());
565
res3.push_back(std::numeric_limits<double>::max());
566
EXPECT_DOUBLEVEC_EQUAL(res3, vec1.distances(vec3));
567
}
568
569
}
570
571
572
/* Test the method 'overlapsWith'*/
573
TEST_F(PositionVectorTest, test_method_overlapsWith) {
574
PositionVector vec1;
575
vec1.push_back(Position(1, 2));
576
vec1.push_back(Position(3, 2));
577
vec1.push_back(Position(3, 6));
578
vec1.push_back(Position(1, 6));
579
580
PositionVector vec2;
581
vec2.push_back(Position(10, 17));
582
vec2.push_back(Position(13, 17));
583
vec2.push_back(Position(13, 16));
584
vec2.push_back(Position(10, 16));
585
586
PositionVector vec3;
587
vec3.push_back(Position(-1, -7));
588
vec3.push_back(Position(2, -7));
589
vec3.push_back(Position(2, 4));
590
vec3.push_back(Position(-1, 4));
591
592
PositionVector vec4;
593
vec4.push_back(Position(0, 3));
594
vec4.push_back(Position(4, 3));
595
vec4.push_back(Position(4, 5));
596
vec4.push_back(Position(0, 5));
597
598
PositionVector vec5;
599
vec5.push_back(Position(4, 2));
600
vec5.push_back(Position(5, 2));
601
vec5.push_back(Position(5, 7));
602
vec5.push_back(Position(4, 7));
603
604
PositionVector vec6;
605
vec6.push_back(Position(4, 0));
606
vec6.push_back(Position(4, 8));
607
vec6.push_back(Position(-4, 8));
608
609
PositionVector empty;
610
611
EXPECT_TRUE(vec1.overlapsWith(vec1));
612
EXPECT_FALSE(vec1.overlapsWith(vec2));
613
EXPECT_TRUE(vec1.overlapsWith(vec3));
614
EXPECT_TRUE(vec1.overlapsWith(vec4));
615
EXPECT_FALSE(vec1.overlapsWith(vec5, 0));
616
EXPECT_TRUE(vec1.overlapsWith(vec6)); // overlapsWith implicitly closes the shape of vec6
617
EXPECT_TRUE(vec6.overlapsWith(vec1)); // overlapsWith implicitly closes the shape of vec6
618
// growth is from centroid and thus different from Boundary behavior
619
EXPECT_FALSE(vec1.overlapsWith(vec5, 1));
620
EXPECT_TRUE(vec1.overlapsWith(vec5, 3));
621
EXPECT_TRUE(vec1.overlapsWith(vec5, 6));
622
EXPECT_FALSE(vec1.overlapsWith(empty));
623
}
624
625
626
/* Test the method 'sortAsPolyCWByAngle'*/
627
TEST_F(PositionVectorTest, test_method_sortAsPolyCWByAngle) {
628
PositionVector vectorTrianglePositiveCoordsClockwiseOrdered;
629
vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(2, 3));
630
vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(3, 0));
631
vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(1, 1));
632
vectorTrianglePositiveCoords->sortAsPolyCWByAngle();
633
EXPECT_POSITIONVEC_EQUAL((*vectorTrianglePositiveCoords), vectorTrianglePositiveCoordsClockwiseOrdered);
634
635
PositionVector vectorTriangleNegativeCoordsClockwiseOrdered;
636
vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(1, -1));
637
vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(2, -1));
638
vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(2, -3));
639
vectorTriangleNegativeCoords->sortAsPolyCWByAngle();
640
EXPECT_POSITIONVEC_EQUAL((*vectorTriangleNegativeCoords), vectorTriangleNegativeCoordsClockwiseOrdered);
641
642
PositionVector vectorRectangleOriginAlignedCornersClockwiseOrdered;
643
vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(1, 3));
644
vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(3, 3));
645
vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(3, 1));
646
vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(1, 1));
647
vectorRectangleOriginAlignedCorners->sortAsPolyCWByAngle();
648
EXPECT_POSITIONVEC_EQUAL((*vectorRectangleOriginAlignedCorners), vectorRectangleOriginAlignedCornersClockwiseOrdered);
649
}
650
651
652
/* Test the method 'isClockwiseOriented'*/
653
TEST_F(PositionVectorTest, test_method_isClockwiseOriented) {
654
EXPECT_FALSE(vectorTrianglePositiveCoords->isClockwiseOriented());
655
EXPECT_FALSE(vectorTriangleNegativeCoords->isClockwiseOriented());
656
EXPECT_FALSE(vectorRectangleOriginAlignedCorners->isClockwiseOriented());
657
}
658
659
660
/* Test the method 'simplified'*/
661
TEST_F(PositionVectorTest, test_method_simplified) {
662
const PositionVector vec1(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2)});
663
const PositionVector result = vec1.simplified();
664
EXPECT_EQ(3, (int)result.size());
665
const PositionVector vec2(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2), Position(1, 2)});
666
const PositionVector result2 = vec2.simplified();
667
EXPECT_EQ(4, (int)result2.size());
668
const PositionVector vec3(std::vector<Position> {Position(1, 2), Position(1, 3), Position(1, 4), Position(1, 5)});
669
const PositionVector result3 = vec3.simplified();
670
// std::cout << result3 << std::endl;
671
EXPECT_EQ(3, (int)result3.size());
672
673
const PositionVector vec4(std::vector<Position> {Position(0, 0), Position(0, 8), Position(NUMERICAL_EPS / 2., 7), Position(NUMERICAL_EPS, 6), Position(3. * NUMERICAL_EPS / 2., 5),
674
Position(2. * NUMERICAL_EPS, 4), Position(3. * NUMERICAL_EPS / 2., 3), Position(NUMERICAL_EPS, 2), Position(NUMERICAL_EPS / 2., 1)
675
});
676
const PositionVector result4 = vec4.simplified();
677
EXPECT_EQ(3, (int)result4.size());
678
}
679
680
681
/* Test the method 'simplified2'*/
682
TEST_F(PositionVectorTest, test_method_simplified2) {
683
const PositionVector vec1(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2)});
684
const PositionVector result = vec1.simplified2(true);
685
EXPECT_EQ(2, (int)result.size());
686
const PositionVector vec2(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2), Position(1, 2)});
687
const PositionVector result2 = vec2.simplified2(true);
688
EXPECT_EQ(2, (int)result2.size());
689
const PositionVector vec3(std::vector<Position> {Position(1, 2), Position(1, 3), Position(1, 4), Position(1, 5)});
690
const PositionVector result3 = vec3.simplified2(true);
691
// std::cout << result3 << std::endl;
692
EXPECT_EQ(2, (int)result3.size());
693
EXPECT_DOUBLE_EQ(2., result3.front().y());
694
EXPECT_DOUBLE_EQ(5., result3.back().y());
695
696
const PositionVector vec4(std::vector<Position> {Position(0, 0), Position(0, 8), Position(NUMERICAL_EPS / 2., 7), Position(NUMERICAL_EPS, 6), Position(3. * NUMERICAL_EPS / 2., 5),
697
Position(2. * NUMERICAL_EPS, 4), Position(3. * NUMERICAL_EPS / 2., 3), Position(NUMERICAL_EPS, 2), Position(NUMERICAL_EPS / 2., 1)
698
});
699
const PositionVector result4 = vec4.simplified2(true);
700
EXPECT_EQ(3, (int)result4.size());
701
EXPECT_DOUBLE_EQ(0., result4.front().y());
702
EXPECT_DOUBLE_EQ(8., result4[1].y());
703
EXPECT_DOUBLE_EQ(4., result4.back().y());
704
}
705
706