LCOV - code coverage report
Current view: top level - unittest/src/utils/geom - PositionVectorTest.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 99.8 % 466 465
Test Date: 2025-12-06 15:35:27 Functions: 100.0 % 21 21

            Line data    Source code
       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           19 : class PositionVectorTest : public testing::Test {
      58              : protected :
      59              :     PositionVector* vectorPolygon;
      60              :     PositionVector* vectorLine;
      61              :     PositionVector* vectorTrianglePositiveCoords;
      62              :     PositionVector* vectorTriangleNegativeCoords;
      63              :     PositionVector* vectorRectangleOriginAlignedCorners;
      64              : 
      65           19 :     virtual void SetUp() {
      66           19 :         vectorPolygon = new PositionVector();
      67           19 :         vectorPolygon->push_back(Position(0, 0));
      68           19 :         vectorPolygon->push_back(Position(0, 2));
      69           19 :         vectorPolygon->push_back(Position(2, 4));
      70           19 :         vectorPolygon->push_back(Position(4, 2));
      71           19 :         vectorPolygon->push_back(Position(4, 0));
      72              : 
      73           19 :         vectorLine = new PositionVector();
      74           19 :         vectorLine->push_back(Position(0, 0));
      75           19 :         vectorLine->push_back(Position(2, 2));
      76              : 
      77           19 :         vectorTrianglePositiveCoords = new PositionVector();
      78           19 :         vectorTrianglePositiveCoords->push_back(Position(1, 1));
      79           19 :         vectorTrianglePositiveCoords->push_back(Position(3, 0));
      80           19 :         vectorTrianglePositiveCoords->push_back(Position(2, 3));
      81              : 
      82           19 :         vectorTriangleNegativeCoords = new PositionVector();
      83           19 :         vectorTriangleNegativeCoords->push_back(Position(2, -1));
      84           19 :         vectorTriangleNegativeCoords->push_back(Position(1, -1));
      85           19 :         vectorTriangleNegativeCoords->push_back(Position(2, -3));
      86              : 
      87           19 :         vectorRectangleOriginAlignedCorners = new PositionVector();
      88           19 :         vectorRectangleOriginAlignedCorners->push_back(Position(1, 1));
      89           19 :         vectorRectangleOriginAlignedCorners->push_back(Position(3, 1));
      90           19 :         vectorRectangleOriginAlignedCorners->push_back(Position(3, 3));
      91           19 :         vectorRectangleOriginAlignedCorners->push_back(Position(1, 3));
      92           19 :     }
      93              : 
      94           19 :     virtual void TearDown() {
      95           19 :         delete vectorPolygon;
      96           19 :         delete vectorLine;
      97           19 :         delete vectorTrianglePositiveCoords;
      98           19 :         delete vectorTriangleNegativeCoords;
      99           19 :         delete vectorRectangleOriginAlignedCorners;
     100           19 :     }
     101              : 
     102              : };
     103              : 
     104              : /* Test the method 'around'*/
     105            1 : TEST_F(PositionVectorTest, test_method_around) {
     106              : 
     107            1 :     EXPECT_TRUE(vectorPolygon->around(Position(1, 1)));
     108            1 :     EXPECT_TRUE(vectorPolygon->around(Position(1, 2)));
     109            1 :     EXPECT_FALSE(vectorPolygon->around(Position(4, 4)));
     110            1 :     EXPECT_FALSE(vectorPolygon->around(Position(0, 0)));
     111              : 
     112            1 :     EXPECT_FALSE(vectorLine->around(Position(1, 1)));
     113            1 :     EXPECT_FALSE(vectorLine->around(Position(0, 2)));
     114              : 
     115              :     // with positive offset
     116            1 :     EXPECT_TRUE(vectorPolygon->around(Position(4, 2), 1));
     117            1 :     EXPECT_FALSE(vectorPolygon->around(Position(5, 2), 1));
     118              :     // what was true remains true
     119            1 :     EXPECT_TRUE(vectorPolygon->around(Position(1, 1), POSITION_EPS));
     120            1 :     EXPECT_TRUE(vectorPolygon->around(Position(1, 2), POSITION_EPS));
     121              : 
     122              :     // with negative offset
     123            1 :     EXPECT_FALSE(vectorPolygon->around(Position(4, 2), -POSITION_EPS));
     124            1 :     EXPECT_TRUE(vectorPolygon->around(Position(1, 1), -1));
     125            1 :     EXPECT_FALSE(vectorPolygon->around(Position(0.5, 0.5), -1));
     126            1 : }
     127              : 
     128              : /* Test the method 'area'*/
     129            1 : TEST_F(PositionVectorTest, test_method_area) {
     130            1 :     PositionVector square;
     131            1 :     square.push_back(Position(0, 0));
     132            1 :     square.push_back(Position(1, 0));
     133            1 :     square.push_back(Position(1, 1));
     134            1 :     square.push_back(Position(0, 1)); // open
     135            1 :     EXPECT_DOUBLE_EQ(square.area(), 1);
     136            1 :     square.push_back(Position(0, 0)); // closed
     137            1 :     EXPECT_DOUBLE_EQ(square.area(), 1);
     138            1 : }
     139              : 
     140              : /* Test the method 'scaleRelative'.*/
     141            1 : TEST_F(PositionVectorTest, test_method_scaleRelative) {
     142            1 :     PositionVector square;
     143            1 :     square.push_back(Position(0, 0));
     144            1 :     square.push_back(Position(1, 0));
     145            1 :     square.push_back(Position(1, 1));
     146            1 :     square.push_back(Position(0, 1));
     147            1 :     square.push_back(Position(0, 0));
     148            1 :     EXPECT_DOUBLE_EQ(square.area(), 1);
     149            1 :     square.scaleRelative(3);
     150            1 :     EXPECT_DOUBLE_EQ(square.area(), 9);
     151              : 
     152            2 :     PositionVector expected;
     153            1 :     expected.push_back(Position(-1, -1));
     154            1 :     expected.push_back(Position(2, -1));
     155            1 :     expected.push_back(Position(2, 2));
     156            1 :     expected.push_back(Position(-1, 2));
     157            1 :     expected.push_back(Position(-1, -1));
     158              : 
     159            2 :     EXPECT_EQ(expected.getCentroid(), square.getCentroid());
     160            6 :     for (int i = 0; i < (int)square.size(); i++) {
     161            5 :         EXPECT_DOUBLE_EQ(expected[i].x(), square[i].x());
     162            5 :         EXPECT_DOUBLE_EQ(expected[i].y(), square[i].y());
     163              :     }
     164            1 : }
     165              : 
     166              : /* Test the method 'getCentroid'.*/
     167            1 : TEST_F(PositionVectorTest, test_method_getCentroid) {
     168            1 :     PositionVector square;
     169            1 :     square.push_back(Position(0, 0));
     170            1 :     square.push_back(Position(1, 0));
     171            1 :     square.push_back(Position(1, 1));
     172            1 :     square.push_back(Position(0, 1));
     173            2 :     EXPECT_EQ(Position(0.5, 0.5), square.getCentroid());
     174              : 
     175            1 :     Position pos2 = vectorLine->getCentroid();
     176            1 :     EXPECT_DOUBLE_EQ(1, pos2.x());
     177            1 :     EXPECT_DOUBLE_EQ(1, pos2.y());
     178            1 : }
     179              : 
     180              : /* Test the method 'getPolygonCenter'.*/
     181            1 : TEST_F(PositionVectorTest, test_method_getPolygonCenter) {
     182            1 :     Position pos = vectorPolygon->getPolygonCenter();
     183            1 :     EXPECT_DOUBLE_EQ(2, pos.x());
     184            1 :     EXPECT_DOUBLE_EQ(1.6, pos.y());
     185            1 :     Position pos2 = vectorLine->getPolygonCenter();
     186            1 :     EXPECT_DOUBLE_EQ(1, pos2.x());
     187            1 :     EXPECT_DOUBLE_EQ(1, pos2.y());
     188            1 : }
     189              : 
     190              : 
     191              : /* Test the method 'getBoxBoundary'*/
     192            1 : TEST_F(PositionVectorTest, test_method_getBoxBoundary) {
     193            1 :     Boundary bound = vectorPolygon->getBoxBoundary();
     194            1 :     EXPECT_DOUBLE_EQ(bound.xmax(), 4);
     195            1 :     EXPECT_DOUBLE_EQ(bound.xmin(), 0);
     196            1 :     EXPECT_DOUBLE_EQ(bound.ymax(), 4);
     197            1 :     EXPECT_DOUBLE_EQ(bound.ymin(), 0);
     198            1 : }
     199              : 
     200              : /* Test the method 'splitAt'*/
     201            1 : TEST_F(PositionVectorTest, test_method_splitAt) {
     202            1 :     PositionVector vec;
     203            1 :     vec.push_back(Position(0, 0));
     204            1 :     vec.push_back(Position(2, 0));
     205            1 :     vec.push_back(Position(5, 0));
     206              :     double smallDiff = POSITION_EPS / 2;
     207            1 :     std::pair<PositionVector, PositionVector> result;
     208              :     // split in first segment
     209            2 :     result = vec.splitAt(1);
     210            1 :     EXPECT_EQ(2, (int)result.first.size());
     211            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     212            1 :     EXPECT_DOUBLE_EQ(1., result.first[1].x());
     213            1 :     EXPECT_EQ(3, (int)result.second.size());
     214            1 :     EXPECT_DOUBLE_EQ(1., result.second[0].x());
     215            1 :     EXPECT_DOUBLE_EQ(2., result.second[1].x());
     216            1 :     EXPECT_DOUBLE_EQ(5., result.second[2].x());
     217              :     // split in second segment
     218            2 :     result = vec.splitAt(4);
     219            1 :     EXPECT_EQ(3, (int)result.first.size());
     220            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     221            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     222            1 :     EXPECT_DOUBLE_EQ(4., result.first[2].x());
     223            1 :     EXPECT_EQ(2, (int)result.second.size());
     224            1 :     EXPECT_DOUBLE_EQ(4., result.second[0].x());
     225            1 :     EXPECT_DOUBLE_EQ(5., result.second[1].x());
     226              :     // split close before inner point
     227            2 :     result = vec.splitAt(2 - smallDiff);
     228            1 :     EXPECT_EQ(2, (int)result.first.size());
     229            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     230            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     231            1 :     EXPECT_EQ(2, (int)result.second.size());
     232            1 :     EXPECT_DOUBLE_EQ(2., result.second[0].x());
     233            1 :     EXPECT_DOUBLE_EQ(5., result.second[1].x());
     234              :     // split close after inner point
     235            2 :     result = vec.splitAt(2 + smallDiff);
     236            1 :     EXPECT_EQ(2, (int)result.first.size());
     237            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     238            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     239            1 :     EXPECT_EQ(2, (int)result.second.size());
     240            1 :     EXPECT_DOUBLE_EQ(2., result.second[0].x());
     241            1 :     EXPECT_DOUBLE_EQ(5., result.second[1].x());
     242              : 
     243              :     // catch a bug
     244            1 :     vec.push_back(Position(6, 0));
     245            1 :     vec.push_back(Position(8, 0));
     246              :     // split at inner point
     247            2 :     result = vec.splitAt(5);
     248            1 :     EXPECT_EQ(3, (int)result.first.size());
     249            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     250            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     251            1 :     EXPECT_DOUBLE_EQ(5., result.first[2].x());
     252            1 :     EXPECT_EQ(3, (int)result.second.size());
     253            1 :     EXPECT_DOUBLE_EQ(5., result.second[0].x());
     254            1 :     EXPECT_DOUBLE_EQ(6., result.second[1].x());
     255            1 :     EXPECT_DOUBLE_EQ(8., result.second[2].x());
     256              : 
     257              :     // split short vector
     258            2 :     PositionVector vec2;
     259            1 :     vec2.push_back(Position(0, 0));
     260            1 :     vec2.push_back(Position(2, 0));
     261            2 :     result = vec2.splitAt(1);
     262            1 :     EXPECT_EQ(2, (int)result.first.size());
     263            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     264            1 :     EXPECT_DOUBLE_EQ(1., result.first[1].x());
     265            1 :     EXPECT_EQ(2, (int)result.second.size());
     266            1 :     EXPECT_DOUBLE_EQ(1., result.second[0].x());
     267            1 :     EXPECT_DOUBLE_EQ(2., result.second[1].x());
     268              : 
     269              :     // split very short vector
     270            2 :     PositionVector vec3;
     271            1 :     vec3.push_back(Position(0, 0));
     272            1 :     vec3.push_back(Position(POSITION_EPS, 0));
     273              :     // supress expected warning
     274            1 :     MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
     275            1 :     result = vec3.splitAt(smallDiff);
     276            2 :     MsgHandler::getWarningInstance()->addRetriever(&OutputDevice::getDevice("stderr"));
     277              : 
     278            1 :     EXPECT_EQ(2, (int)result.first.size());
     279            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     280            1 :     EXPECT_DOUBLE_EQ(smallDiff, result.first[1].x());
     281            1 :     EXPECT_EQ(2, (int)result.second.size());
     282            1 :     EXPECT_DOUBLE_EQ(smallDiff, result.second[0].x());
     283            1 :     EXPECT_DOUBLE_EQ(POSITION_EPS, result.second[1].x());
     284            1 : }
     285              : 
     286              : 
     287              : /* Test the method 'intersectsAtLengths2D'*/
     288            1 : TEST_F(PositionVectorTest, test_method_intersectsAtLengths2D) {
     289            1 :     PositionVector vec1;
     290            1 :     vec1.push_back(Position(0, 0, 42));
     291            1 :     vec1.push_back(Position(100, 0, 0));
     292              : 
     293            1 :     PositionVector vec2;
     294            1 :     vec2.push_back(Position(0, 0, 0));
     295            1 :     vec2.push_back(Position(3, 1, 0));
     296            1 :     EXPECT_DOUBLE_EQ(0, vec1.intersectsAtLengths2D(vec2)[0]);
     297            1 : }
     298              : 
     299              : 
     300              : /* Test the method 'nearest_offset_to_point2D'*/
     301            1 : TEST_F(PositionVectorTest, test_method_nearest_offset_to_point2D) {
     302            1 :     PositionVector vec1;
     303            1 :     vec1.push_back(Position(0, 1, 0));
     304            1 :     vec1.push_back(Position(0, 0, 0));
     305            1 :     vec1.push_back(Position(1, 0, 0));
     306              : 
     307            1 :     EXPECT_DOUBLE_EQ(1, vec1.nearest_offset_to_point2D(Position(-1, -1), false));
     308            1 :     EXPECT_DOUBLE_EQ(1, vec1.nearest_offset_to_point2D(Position(-1, -1), true));
     309            1 :     EXPECT_DOUBLE_EQ(2, vec1.nearest_offset_to_point2D(Position(2, 1), false));
     310            1 :     EXPECT_DOUBLE_EQ(0, vec1.nearest_offset_to_point2D(Position(2, 1), true));
     311            1 :     EXPECT_DOUBLE_EQ(2, vec1.nearest_offset_to_point2D(Position(3, 2), false));
     312            1 :     EXPECT_DOUBLE_EQ(-1, vec1.nearest_offset_to_point2D(Position(3, 2), true));
     313            1 : }
     314              : 
     315              : 
     316            1 : TEST_F(PositionVectorTest, test_method_extrapolate2D) {
     317            1 :     PositionVector vec1;
     318            1 :     vec1.push_back(Position(0, 1, 0));
     319            1 :     vec1.push_back(Position(0, 0, 0));
     320            1 :     vec1.push_back(Position(1, 0, 0));
     321            1 :     vec1.extrapolate2D(1);
     322            2 :     EXPECT_EQ(Position(0, 2, 0), vec1[0]);
     323            2 :     EXPECT_EQ(Position(0, 0, 0), vec1[1]);
     324            2 :     EXPECT_EQ(Position(2, 0, 0), vec1[2]);
     325              : 
     326            2 :     PositionVector vec2;
     327            1 :     vec2.push_back(Position(0, 1, 0));
     328            1 :     vec2.push_back(Position(0, 0, 1));
     329            0 :     vec2.push_back(Position(1, 0, 0));
     330            1 :     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            2 :     PositionVector vec3;
     336            1 :     vec3.push_back(Position(-.5, 1));
     337            1 :     vec3.push_back(Position(-.5, -.5));
     338            1 :     vec3.push_back(Position(1, -.5));
     339            1 :     vec3.extrapolate2D(.5);
     340            2 :     EXPECT_EQ(Position(-.5, 1.5), vec3[0]);
     341            2 :     EXPECT_EQ(Position(-.5, -.5), vec3[1]);
     342            2 :     EXPECT_EQ(Position(1.5, -.5), vec3[2]);
     343              : 
     344            1 : }
     345              : 
     346              : 
     347              : /* Test the method 'move2side'*/
     348            1 : TEST_F(PositionVectorTest, test_method_move2side) {
     349            1 :     PositionVector vec1;
     350            1 :     vec1.push_back(Position(0, 1, 0));
     351            1 :     vec1.push_back(Position(0, 0, 0));
     352            1 :     vec1.push_back(Position(1, 0, 0));
     353            1 :     vec1.move2side(.5);
     354            2 :     EXPECT_EQ(Position(-.5, 1), vec1[0]);
     355            2 :     EXPECT_EQ(Position(-.5, -.5), vec1[1]);
     356            2 :     EXPECT_EQ(Position(1, -.5), vec1[2]);
     357            1 :     vec1.move2side(-1);
     358            2 :     EXPECT_EQ(Position(.5, 1), vec1[0]);
     359            2 :     EXPECT_EQ(Position(.5, .5), vec1[1]);
     360            2 :     EXPECT_EQ(Position(1, .5), vec1[2]);
     361              : 
     362              :     // parallel case
     363            2 :     PositionVector vec2;
     364            1 :     vec2.push_back(Position(0, 0, 0));
     365            1 :     vec2.push_back(Position(1, 0, 0));
     366            1 :     vec2.push_back(Position(3, 0, 0));
     367            1 :     vec2.move2side(.5);
     368            2 :     EXPECT_EQ(Position(0, -.5), vec2[0]);
     369            2 :     EXPECT_EQ(Position(1, -.5), vec2[1]);
     370            2 :     EXPECT_EQ(Position(3, -.5), vec2[2]);
     371            1 :     vec2.move2side(-1);
     372            2 :     EXPECT_EQ(Position(0, .5), vec2[0]);
     373            2 :     EXPECT_EQ(Position(1, .5), vec2[1]);
     374            2 :     EXPECT_EQ(Position(3, .5), vec2[2]);
     375              : 
     376              :     // counterparallel case
     377              :     {
     378            1 :         PositionVector vec3;
     379            1 :         vec3.push_back(Position(0, 0, 0));
     380            1 :         vec3.push_back(Position(3, 0, 0));
     381            1 :         vec3.push_back(Position(1, 0, 0));
     382            1 :         vec3.move2side(.5);
     383              :         // clipping removal eliminates the middle point
     384            2 :         EXPECT_EQ(Position(0, -.5), vec3[0]);
     385            2 :         EXPECT_EQ(Position(1, -.5), vec3[1]);
     386            1 :     }
     387              :     // bad input: subsequent identical points
     388              :     {
     389            1 :         PositionVector vec4;
     390            1 :         vec4.push_back(Position(0, 0, 0));
     391            1 :         vec4.push_back(Position(0, 0, 0));
     392            1 :         vec4.push_back(Position(1, 0, 0));
     393            1 :         vec4.move2side(-2);
     394            1 :         EXPECT_EQ(2, (int)vec4.size());
     395            2 :         EXPECT_EQ(Position(0, 2), vec4[0]);
     396            2 :         EXPECT_EQ(Position(1, 2), vec4[1]);
     397            1 :     }
     398            1 : }
     399              : 
     400              : /* Test the method 'transformToVectorCoordinates'*/
     401            1 : TEST_F(PositionVectorTest, test_method_transformToVectorCoordinates) {
     402              :     {
     403            1 :         PositionVector vec1;
     404            1 :         vec1.push_back(Position(1, 0));
     405            1 :         vec1.push_back(Position(10, 0));
     406            1 :         vec1.push_back(Position(10, 5));
     407            1 :         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            2 :         EXPECT_EQ(Position(3, 0),  vec1.transformToVectorCoordinates(on));
     419            2 :         EXPECT_EQ(Position(3, -1),  vec1.transformToVectorCoordinates(left));
     420            2 :         EXPECT_EQ(Position(3, 1),  vec1.transformToVectorCoordinates(right));
     421            2 :         EXPECT_EQ(Position(3, -2),  vec1.transformToVectorCoordinates(left2));
     422            2 :         EXPECT_EQ(Position(3, 2),  vec1.transformToVectorCoordinates(right2));
     423            2 :         EXPECT_EQ(Position(9, 5),  vec1.transformToVectorCoordinates(cornerRight));
     424            2 :         EXPECT_EQ(Position(14, -5),  vec1.transformToVectorCoordinates(cornerLeft));
     425              : 
     426            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(before));
     427            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(beyond));
     428            2 :         EXPECT_EQ(Position(-1, 1),  vec1.transformToVectorCoordinates(before, true));
     429            2 :         EXPECT_EQ(Position(28, -4),  vec1.transformToVectorCoordinates(beyond, true));
     430            1 :     }
     431              : 
     432              :     {
     433            1 :         PositionVector vec1; // the same tests as before, mirrored on x-axis
     434            1 :         vec1.push_back(Position(1, 0));
     435            1 :         vec1.push_back(Position(10, 0));
     436            1 :         vec1.push_back(Position(10, -5));
     437            1 :         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            2 :         EXPECT_EQ(Position(3, 0),  vec1.transformToVectorCoordinates(on));
     449            2 :         EXPECT_EQ(Position(3, 1),  vec1.transformToVectorCoordinates(left));
     450            2 :         EXPECT_EQ(Position(3, -1),  vec1.transformToVectorCoordinates(right));
     451            2 :         EXPECT_EQ(Position(3, 2),  vec1.transformToVectorCoordinates(left2));
     452            2 :         EXPECT_EQ(Position(3, -2),  vec1.transformToVectorCoordinates(right2));
     453            2 :         EXPECT_EQ(Position(9, -5),  vec1.transformToVectorCoordinates(cornerRight));
     454            2 :         EXPECT_EQ(Position(14, 5),  vec1.transformToVectorCoordinates(cornerLeft));
     455              : 
     456            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(before));
     457            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(beyond));
     458            2 :         EXPECT_EQ(Position(-1, -1),  vec1.transformToVectorCoordinates(before, true));
     459            2 :         EXPECT_EQ(Position(28, 4),  vec1.transformToVectorCoordinates(beyond, true));
     460            1 :     }
     461            1 : }
     462              : 
     463              : 
     464              : /* Test the method 'distance'*/
     465            1 : TEST_F(PositionVectorTest, test_method_distance) {
     466              :     {
     467            1 :         PositionVector vec1;
     468            1 :         vec1.push_back(Position(1, 0));
     469            1 :         vec1.push_back(Position(10, 0));
     470            1 :         vec1.push_back(Position(10, 5));
     471            1 :         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            1 :         EXPECT_EQ(0, vec1.distance2D(on));
     483            1 :         EXPECT_EQ(1, vec1.distance2D(left));
     484            1 :         EXPECT_EQ(1, vec1.distance2D(right));
     485            1 :         EXPECT_EQ(2, vec1.distance2D(left2));
     486            1 :         EXPECT_EQ(2, vec1.distance2D(right2));
     487            1 :         EXPECT_EQ(5, vec1.distance2D(cornerRight));
     488            1 :         EXPECT_EQ(5, vec1.distance2D(cornerLeft));
     489              : 
     490            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(before, true));
     491            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(beyond, true));
     492            1 :         EXPECT_EQ(5, vec1.distance2D(before));
     493            1 :         EXPECT_EQ(5, vec1.distance2D(beyond));
     494            1 :     }
     495              : 
     496              :     {
     497            1 :         PositionVector vec1; // the same tests as before, mirrored on x-axis
     498            1 :         vec1.push_back(Position(1, 0));
     499            1 :         vec1.push_back(Position(10, 0));
     500            1 :         vec1.push_back(Position(10, -5));
     501            1 :         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            1 :         EXPECT_EQ(0, vec1.distance2D(on));
     513            1 :         EXPECT_EQ(1, vec1.distance2D(left));
     514            1 :         EXPECT_EQ(1, vec1.distance2D(right));
     515            1 :         EXPECT_EQ(2, vec1.distance2D(left2));
     516            1 :         EXPECT_EQ(2, vec1.distance2D(right2));
     517            1 :         EXPECT_EQ(5, vec1.distance2D(cornerRight));
     518            1 :         EXPECT_EQ(5, vec1.distance2D(cornerLeft));
     519              : 
     520            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(before, true));
     521            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(beyond, true));
     522            1 :         EXPECT_EQ(5, vec1.distance2D(before));
     523            1 :         EXPECT_EQ(5, vec1.distance2D(beyond));
     524            1 :     }
     525            1 : }
     526              : 
     527              : 
     528              : /* Test the method 'distance'*/
     529            1 : TEST_F(PositionVectorTest, test_method_distances) {
     530              :     {
     531            1 :         PositionVector vec1;
     532            1 :         vec1.push_back(Position(0, 0));
     533            1 :         vec1.push_back(Position(10, 0));
     534              : 
     535            1 :         PositionVector vec2;
     536            1 :         vec2.push_back(Position(1, 0));
     537            1 :         vec2.push_back(Position(5, 2));
     538            1 :         vec2.push_back(Position(10, 0));
     539            1 :         vec2.push_back(Position(14, 3));
     540              : 
     541            1 :         PositionVector vec3;
     542              : 
     543              :         std::vector<double> res1;
     544            1 :         res1.push_back(1);
     545            1 :         res1.push_back(0);
     546            1 :         res1.push_back(0);
     547            1 :         res1.push_back(2);
     548            1 :         res1.push_back(0);
     549            1 :         res1.push_back(5);
     550            9 :         EXPECT_DOUBLEVEC_EQUAL(res1,  vec1.distances(vec2));
     551              : 
     552              : 
     553            1 :         std::vector<double> res2;
     554              :         //invalid: res1.push_back(1);
     555            1 :         res2.push_back(0);
     556            1 :         res2.push_back(0);
     557            1 :         res2.push_back(2);
     558            1 :         res2.push_back(0);
     559              :         //invalid: res2.push_back(5);
     560            7 :         EXPECT_DOUBLEVEC_EQUAL(res2,  vec1.distances(vec2, true));
     561              : 
     562              : 
     563            1 :         std::vector<double> res3;
     564            1 :         res3.push_back(std::numeric_limits<double>::max());
     565            1 :         res3.push_back(std::numeric_limits<double>::max());
     566            5 :         EXPECT_DOUBLEVEC_EQUAL(res3,  vec1.distances(vec3));
     567            1 :     }
     568              : 
     569            1 : }
     570              : 
     571              : 
     572              : /* Test the method 'overlapsWith'*/
     573            1 : TEST_F(PositionVectorTest, test_method_overlapsWith) {
     574            1 :     PositionVector vec1;
     575            1 :     vec1.push_back(Position(1, 2));
     576            1 :     vec1.push_back(Position(3, 2));
     577            1 :     vec1.push_back(Position(3, 6));
     578            1 :     vec1.push_back(Position(1, 6));
     579              : 
     580            1 :     PositionVector vec2;
     581            1 :     vec2.push_back(Position(10, 17));
     582            1 :     vec2.push_back(Position(13, 17));
     583            1 :     vec2.push_back(Position(13, 16));
     584            1 :     vec2.push_back(Position(10, 16));
     585              : 
     586            1 :     PositionVector vec3;
     587            1 :     vec3.push_back(Position(-1, -7));
     588            1 :     vec3.push_back(Position(2, -7));
     589            1 :     vec3.push_back(Position(2,  4));
     590            1 :     vec3.push_back(Position(-1,  4));
     591              : 
     592            1 :     PositionVector vec4;
     593            1 :     vec4.push_back(Position(0, 3));
     594            1 :     vec4.push_back(Position(4, 3));
     595            1 :     vec4.push_back(Position(4, 5));
     596            1 :     vec4.push_back(Position(0, 5));
     597              : 
     598            1 :     PositionVector vec5;
     599            1 :     vec5.push_back(Position(4, 2));
     600            1 :     vec5.push_back(Position(5, 2));
     601            1 :     vec5.push_back(Position(5, 7));
     602            1 :     vec5.push_back(Position(4, 7));
     603              : 
     604            1 :     PositionVector vec6;
     605            1 :     vec6.push_back(Position(4, 0));
     606            1 :     vec6.push_back(Position(4, 8));
     607            1 :     vec6.push_back(Position(-4, 8));
     608              : 
     609            1 :     PositionVector empty;
     610              : 
     611            1 :     EXPECT_TRUE(vec1.overlapsWith(vec1));
     612            1 :     EXPECT_FALSE(vec1.overlapsWith(vec2));
     613            1 :     EXPECT_TRUE(vec1.overlapsWith(vec3));
     614            1 :     EXPECT_TRUE(vec1.overlapsWith(vec4));
     615            1 :     EXPECT_FALSE(vec1.overlapsWith(vec5, 0));
     616            1 :     EXPECT_TRUE(vec1.overlapsWith(vec6)); // overlapsWith implicitly closes the shape of vec6
     617            1 :     EXPECT_TRUE(vec6.overlapsWith(vec1)); // overlapsWith implicitly closes the shape of vec6
     618              :     // growth is from centroid and thus different from Boundary behavior
     619            1 :     EXPECT_FALSE(vec1.overlapsWith(vec5, 1));
     620            1 :     EXPECT_TRUE(vec1.overlapsWith(vec5, 3));
     621            1 :     EXPECT_TRUE(vec1.overlapsWith(vec5, 6));
     622            1 :     EXPECT_FALSE(vec1.overlapsWith(empty));
     623            1 : }
     624              : 
     625              : 
     626              : /* Test the method 'sortAsPolyCWByAngle'*/
     627            1 : TEST_F(PositionVectorTest, test_method_sortAsPolyCWByAngle) {
     628            1 :     PositionVector vectorTrianglePositiveCoordsClockwiseOrdered;
     629            1 :     vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(2, 3));
     630            1 :     vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(3, 0));
     631            1 :     vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(1, 1));
     632            1 :     vectorTrianglePositiveCoords->sortAsPolyCWByAngle();
     633           12 :     EXPECT_POSITIONVEC_EQUAL((*vectorTrianglePositiveCoords), vectorTrianglePositiveCoordsClockwiseOrdered);
     634              : 
     635            2 :     PositionVector vectorTriangleNegativeCoordsClockwiseOrdered;
     636            1 :     vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(1, -1));
     637            1 :     vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(2, -1));
     638            1 :     vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(2, -3));
     639            1 :     vectorTriangleNegativeCoords->sortAsPolyCWByAngle();
     640           12 :     EXPECT_POSITIONVEC_EQUAL((*vectorTriangleNegativeCoords), vectorTriangleNegativeCoordsClockwiseOrdered);
     641              : 
     642            2 :     PositionVector vectorRectangleOriginAlignedCornersClockwiseOrdered;
     643            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(1, 3));
     644            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(3, 3));
     645            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(3, 1));
     646            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(1, 1));
     647            1 :     vectorRectangleOriginAlignedCorners->sortAsPolyCWByAngle();
     648           15 :     EXPECT_POSITIONVEC_EQUAL((*vectorRectangleOriginAlignedCorners), vectorRectangleOriginAlignedCornersClockwiseOrdered);
     649            1 : }
     650              : 
     651              : 
     652              : /* Test the method 'isClockwiseOriented'*/
     653            1 : TEST_F(PositionVectorTest, test_method_isClockwiseOriented) {
     654            1 :     EXPECT_FALSE(vectorTrianglePositiveCoords->isClockwiseOriented());
     655            1 :     EXPECT_FALSE(vectorTriangleNegativeCoords->isClockwiseOriented());
     656            1 :     EXPECT_FALSE(vectorRectangleOriginAlignedCorners->isClockwiseOriented());
     657            1 : }
     658              : 
     659              : 
     660              : /* Test the method 'simplified'*/
     661            2 : TEST_F(PositionVectorTest, test_method_simplified) {
     662            1 :     const PositionVector vec1(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2)});
     663            1 :     const PositionVector result = vec1.simplified();
     664            1 :     EXPECT_EQ(3, (int)result.size());
     665            2 :     const PositionVector vec2(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2), Position(1, 2)});
     666            2 :     const PositionVector result2 = vec2.simplified();
     667            1 :     EXPECT_EQ(4, (int)result2.size());
     668            2 :     const PositionVector vec3(std::vector<Position> {Position(1, 2), Position(1, 3), Position(1, 4), Position(1, 5)});
     669            2 :     const PositionVector result3 = vec3.simplified();
     670              :     // std::cout << result3 << std::endl;
     671            1 :     EXPECT_EQ(3, (int)result3.size());
     672              : 
     673            2 :     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            2 :                                                     });
     676            2 :     const PositionVector result4 = vec4.simplified();
     677            1 :     EXPECT_EQ(3, (int)result4.size());
     678            1 : }
     679              : 
     680              : 
     681              : /* Test the method 'simplified2'*/
     682            2 : TEST_F(PositionVectorTest, test_method_simplified2) {
     683            1 :     const PositionVector vec1(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2)});
     684            1 :     const PositionVector result = vec1.simplified2(true);
     685            1 :     EXPECT_EQ(2, (int)result.size());
     686            2 :     const PositionVector vec2(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2), Position(1, 2)});
     687            2 :     const PositionVector result2 = vec2.simplified2(true);
     688            1 :     EXPECT_EQ(2, (int)result2.size());
     689            2 :     const PositionVector vec3(std::vector<Position> {Position(1, 2), Position(1, 3), Position(1, 4), Position(1, 5)});
     690            2 :     const PositionVector result3 = vec3.simplified2(true);
     691              :     // std::cout << result3 << std::endl;
     692            1 :     EXPECT_EQ(2, (int)result3.size());
     693            1 :     EXPECT_DOUBLE_EQ(2., result3.front().y());
     694            1 :     EXPECT_DOUBLE_EQ(5., result3.back().y());
     695              : 
     696            2 :     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            2 :                                                     });
     699            2 :     const PositionVector result4 = vec4.simplified2(true);
     700            1 :     EXPECT_EQ(3, (int)result4.size());
     701            1 :     EXPECT_DOUBLE_EQ(0., result4.front().y());
     702            1 :     EXPECT_DOUBLE_EQ(8., result4[1].y());
     703            1 :     EXPECT_DOUBLE_EQ(4., result4.back().y());
     704            1 : }
        

Generated by: LCOV version 2.0-1