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 % 464 463
Test Date: 2024-11-22 15:46:21 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-2024 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 : }
     187              : 
     188              : 
     189              : /* Test the method 'getBoxBoundary'*/
     190            1 : TEST_F(PositionVectorTest, test_method_getBoxBoundary) {
     191            1 :     Boundary bound = vectorPolygon->getBoxBoundary();
     192            1 :     EXPECT_DOUBLE_EQ(bound.xmax(), 4);
     193            1 :     EXPECT_DOUBLE_EQ(bound.xmin(), 0);
     194            1 :     EXPECT_DOUBLE_EQ(bound.ymax(), 4);
     195            1 :     EXPECT_DOUBLE_EQ(bound.ymin(), 0);
     196            1 : }
     197              : 
     198              : /* Test the method 'splitAt'*/
     199            1 : TEST_F(PositionVectorTest, test_method_splitAt) {
     200            1 :     PositionVector vec;
     201            1 :     vec.push_back(Position(0, 0));
     202            1 :     vec.push_back(Position(2, 0));
     203            1 :     vec.push_back(Position(5, 0));
     204              :     double smallDiff = POSITION_EPS / 2;
     205            1 :     std::pair<PositionVector, PositionVector> result;
     206              :     // split in first segment
     207            2 :     result = vec.splitAt(1);
     208            1 :     EXPECT_EQ(2, (int)result.first.size());
     209            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     210            1 :     EXPECT_DOUBLE_EQ(1., result.first[1].x());
     211            1 :     EXPECT_EQ(3, (int)result.second.size());
     212            1 :     EXPECT_DOUBLE_EQ(1., result.second[0].x());
     213            1 :     EXPECT_DOUBLE_EQ(2., result.second[1].x());
     214            1 :     EXPECT_DOUBLE_EQ(5., result.second[2].x());
     215              :     // split in second segment
     216            2 :     result = vec.splitAt(4);
     217            1 :     EXPECT_EQ(3, (int)result.first.size());
     218            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     219            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     220            1 :     EXPECT_DOUBLE_EQ(4., result.first[2].x());
     221            1 :     EXPECT_EQ(2, (int)result.second.size());
     222            1 :     EXPECT_DOUBLE_EQ(4., result.second[0].x());
     223            1 :     EXPECT_DOUBLE_EQ(5., result.second[1].x());
     224              :     // split close before inner point
     225            2 :     result = vec.splitAt(2 - smallDiff);
     226            1 :     EXPECT_EQ(2, (int)result.first.size());
     227            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     228            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     229            1 :     EXPECT_EQ(2, (int)result.second.size());
     230            1 :     EXPECT_DOUBLE_EQ(2., result.second[0].x());
     231            1 :     EXPECT_DOUBLE_EQ(5., result.second[1].x());
     232              :     // split close after inner point
     233            2 :     result = vec.splitAt(2 + smallDiff);
     234            1 :     EXPECT_EQ(2, (int)result.first.size());
     235            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     236            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     237            1 :     EXPECT_EQ(2, (int)result.second.size());
     238            1 :     EXPECT_DOUBLE_EQ(2., result.second[0].x());
     239            1 :     EXPECT_DOUBLE_EQ(5., result.second[1].x());
     240              : 
     241              :     // catch a bug
     242            1 :     vec.push_back(Position(6, 0));
     243            1 :     vec.push_back(Position(8, 0));
     244              :     // split at inner point
     245            2 :     result = vec.splitAt(5);
     246            1 :     EXPECT_EQ(3, (int)result.first.size());
     247            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     248            1 :     EXPECT_DOUBLE_EQ(2., result.first[1].x());
     249            1 :     EXPECT_DOUBLE_EQ(5., result.first[2].x());
     250            1 :     EXPECT_EQ(3, (int)result.second.size());
     251            1 :     EXPECT_DOUBLE_EQ(5., result.second[0].x());
     252            1 :     EXPECT_DOUBLE_EQ(6., result.second[1].x());
     253            1 :     EXPECT_DOUBLE_EQ(8., result.second[2].x());
     254              : 
     255              :     // split short vector
     256            1 :     PositionVector vec2;
     257            1 :     vec2.push_back(Position(0, 0));
     258            1 :     vec2.push_back(Position(2, 0));
     259            2 :     result = vec2.splitAt(1);
     260            1 :     EXPECT_EQ(2, (int)result.first.size());
     261            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     262            1 :     EXPECT_DOUBLE_EQ(1., result.first[1].x());
     263            1 :     EXPECT_EQ(2, (int)result.second.size());
     264            1 :     EXPECT_DOUBLE_EQ(1., result.second[0].x());
     265            1 :     EXPECT_DOUBLE_EQ(2., result.second[1].x());
     266              : 
     267              :     // split very short vector
     268            2 :     PositionVector vec3;
     269            1 :     vec3.push_back(Position(0, 0));
     270            1 :     vec3.push_back(Position(POSITION_EPS, 0));
     271              :     // supress expected warning
     272            1 :     MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
     273            1 :     result = vec3.splitAt(smallDiff);
     274            2 :     MsgHandler::getWarningInstance()->addRetriever(&OutputDevice::getDevice("stderr"));
     275              : 
     276            1 :     EXPECT_EQ(2, (int)result.first.size());
     277            1 :     EXPECT_DOUBLE_EQ(0., result.first[0].x());
     278            1 :     EXPECT_DOUBLE_EQ(smallDiff, result.first[1].x());
     279            1 :     EXPECT_EQ(2, (int)result.second.size());
     280            1 :     EXPECT_DOUBLE_EQ(smallDiff, result.second[0].x());
     281            1 :     EXPECT_DOUBLE_EQ(POSITION_EPS, result.second[1].x());
     282            1 : }
     283              : 
     284              : 
     285              : /* Test the method 'intersectsAtLengths2D'*/
     286            1 : TEST_F(PositionVectorTest, test_method_intersectsAtLengths2D) {
     287            1 :     PositionVector vec1;
     288            1 :     vec1.push_back(Position(0, 0, 42));
     289            1 :     vec1.push_back(Position(100, 0, 0));
     290              : 
     291            1 :     PositionVector vec2;
     292            1 :     vec2.push_back(Position(0, 0, 0));
     293            1 :     vec2.push_back(Position(3, 1, 0));
     294            1 :     EXPECT_DOUBLE_EQ(0, vec1.intersectsAtLengths2D(vec2)[0]);
     295            1 : }
     296              : 
     297              : 
     298              : /* Test the method 'nearest_offset_to_point2D'*/
     299            1 : TEST_F(PositionVectorTest, test_method_nearest_offset_to_point2D) {
     300            1 :     PositionVector vec1;
     301            1 :     vec1.push_back(Position(0, 1, 0));
     302            1 :     vec1.push_back(Position(0, 0, 0));
     303            1 :     vec1.push_back(Position(1, 0, 0));
     304              : 
     305            1 :     EXPECT_DOUBLE_EQ(1, vec1.nearest_offset_to_point2D(Position(-1, -1), false));
     306            1 :     EXPECT_DOUBLE_EQ(1, vec1.nearest_offset_to_point2D(Position(-1, -1), true));
     307            1 :     EXPECT_DOUBLE_EQ(2, vec1.nearest_offset_to_point2D(Position(2, 1), false));
     308            1 :     EXPECT_DOUBLE_EQ(0, vec1.nearest_offset_to_point2D(Position(2, 1), true));
     309            1 :     EXPECT_DOUBLE_EQ(2, vec1.nearest_offset_to_point2D(Position(3, 2), false));
     310            1 :     EXPECT_DOUBLE_EQ(-1, vec1.nearest_offset_to_point2D(Position(3, 2), true));
     311            1 : }
     312              : 
     313              : 
     314            1 : TEST_F(PositionVectorTest, test_method_extrapolate2D) {
     315            1 :     PositionVector vec1;
     316            1 :     vec1.push_back(Position(0, 1, 0));
     317            1 :     vec1.push_back(Position(0, 0, 0));
     318            1 :     vec1.push_back(Position(1, 0, 0));
     319            1 :     vec1.extrapolate2D(1);
     320            2 :     EXPECT_EQ(Position(0, 2, 0), vec1[0]);
     321            2 :     EXPECT_EQ(Position(0, 0, 0), vec1[1]);
     322            2 :     EXPECT_EQ(Position(2, 0, 0), vec1[2]);
     323              : 
     324            2 :     PositionVector vec2;
     325            1 :     vec2.push_back(Position(0, 1, 0));
     326            1 :     vec2.push_back(Position(0, 0, 1));
     327            0 :     vec2.push_back(Position(1, 0, 0));
     328            1 :     vec2.extrapolate2D(1);
     329              : //    EXPECT_EQ(Position(0,2,0), vec2[0]);
     330              : //    EXPECT_EQ(Position(0,0,0), vec2[1]);
     331              : //    EXPECT_EQ(Position(2,0,0), vec2[2]);
     332              : 
     333            2 :     PositionVector vec3;
     334            1 :     vec3.push_back(Position(-.5, 1));
     335            1 :     vec3.push_back(Position(-.5, -.5));
     336            1 :     vec3.push_back(Position(1, -.5));
     337            1 :     vec3.extrapolate2D(.5);
     338            2 :     EXPECT_EQ(Position(-.5, 1.5), vec3[0]);
     339            2 :     EXPECT_EQ(Position(-.5, -.5), vec3[1]);
     340            2 :     EXPECT_EQ(Position(1.5, -.5), vec3[2]);
     341              : 
     342            1 : }
     343              : 
     344              : 
     345              : /* Test the method 'move2side'*/
     346            1 : TEST_F(PositionVectorTest, test_method_move2side) {
     347            1 :     PositionVector vec1;
     348            1 :     vec1.push_back(Position(0, 1, 0));
     349            1 :     vec1.push_back(Position(0, 0, 0));
     350            1 :     vec1.push_back(Position(1, 0, 0));
     351            1 :     vec1.move2side(.5);
     352            2 :     EXPECT_EQ(Position(-.5, 1), vec1[0]);
     353            2 :     EXPECT_EQ(Position(-.5, -.5), vec1[1]);
     354            2 :     EXPECT_EQ(Position(1, -.5), vec1[2]);
     355            1 :     vec1.move2side(-1);
     356            2 :     EXPECT_EQ(Position(.5, 1), vec1[0]);
     357            2 :     EXPECT_EQ(Position(.5, .5), vec1[1]);
     358            2 :     EXPECT_EQ(Position(1, .5), vec1[2]);
     359              : 
     360              :     // parallel case
     361            2 :     PositionVector vec2;
     362            1 :     vec2.push_back(Position(0, 0, 0));
     363            1 :     vec2.push_back(Position(1, 0, 0));
     364            1 :     vec2.push_back(Position(3, 0, 0));
     365            1 :     vec2.move2side(.5);
     366            2 :     EXPECT_EQ(Position(0, -.5), vec2[0]);
     367            2 :     EXPECT_EQ(Position(1, -.5), vec2[1]);
     368            2 :     EXPECT_EQ(Position(3, -.5), vec2[2]);
     369            1 :     vec2.move2side(-1);
     370            2 :     EXPECT_EQ(Position(0, .5), vec2[0]);
     371            2 :     EXPECT_EQ(Position(1, .5), vec2[1]);
     372            2 :     EXPECT_EQ(Position(3, .5), vec2[2]);
     373              : 
     374              :     // counterparallel case
     375              :     {
     376            1 :         PositionVector vec3;
     377            1 :         vec3.push_back(Position(0, 0, 0));
     378            1 :         vec3.push_back(Position(3, 0, 0));
     379            1 :         vec3.push_back(Position(1, 0, 0));
     380            1 :         vec3.move2side(.5);
     381              :         // clipping removal eliminates the middle point
     382            2 :         EXPECT_EQ(Position(0, -.5), vec3[0]);
     383            2 :         EXPECT_EQ(Position(1, -.5), vec3[1]);
     384            1 :     }
     385              :     // bad input: subsequent identical points
     386              :     {
     387            1 :         PositionVector vec4;
     388            1 :         vec4.push_back(Position(0, 0, 0));
     389            1 :         vec4.push_back(Position(0, 0, 0));
     390            1 :         vec4.push_back(Position(1, 0, 0));
     391            1 :         vec4.move2side(-2);
     392            1 :         EXPECT_EQ(2, (int)vec4.size());
     393            2 :         EXPECT_EQ(Position(0, 2), vec4[0]);
     394            2 :         EXPECT_EQ(Position(1, 2), vec4[1]);
     395            1 :     }
     396            1 : }
     397              : 
     398              : /* Test the method 'transformToVectorCoordinates'*/
     399            1 : TEST_F(PositionVectorTest, test_method_transformToVectorCoordinates) {
     400              :     {
     401            1 :         PositionVector vec1;
     402            1 :         vec1.push_back(Position(1, 0));
     403            1 :         vec1.push_back(Position(10, 0));
     404            1 :         vec1.push_back(Position(10, 5));
     405            1 :         vec1.push_back(Position(20, 5));
     406              :         Position on(4, 0);
     407              :         Position left(4, 1);
     408              :         Position right(4, -1);
     409              :         Position left2(4, 2);
     410              :         Position right2(4, -2);
     411              :         Position cornerRight(13, -4);
     412              :         Position cornerLeft(7, 9);
     413              :         Position before(0, -1);
     414              :         Position beyond(24, 9);
     415              : 
     416            2 :         EXPECT_EQ(Position(3, 0),  vec1.transformToVectorCoordinates(on));
     417            2 :         EXPECT_EQ(Position(3, -1),  vec1.transformToVectorCoordinates(left));
     418            2 :         EXPECT_EQ(Position(3, 1),  vec1.transformToVectorCoordinates(right));
     419            2 :         EXPECT_EQ(Position(3, -2),  vec1.transformToVectorCoordinates(left2));
     420            2 :         EXPECT_EQ(Position(3, 2),  vec1.transformToVectorCoordinates(right2));
     421            2 :         EXPECT_EQ(Position(9, 5),  vec1.transformToVectorCoordinates(cornerRight));
     422            2 :         EXPECT_EQ(Position(14, -5),  vec1.transformToVectorCoordinates(cornerLeft));
     423              : 
     424            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(before));
     425            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(beyond));
     426            2 :         EXPECT_EQ(Position(-1, 1),  vec1.transformToVectorCoordinates(before, true));
     427            2 :         EXPECT_EQ(Position(28, -4),  vec1.transformToVectorCoordinates(beyond, true));
     428            1 :     }
     429              : 
     430              :     {
     431            1 :         PositionVector vec1; // the same tests as before, mirrored on x-axis
     432            1 :         vec1.push_back(Position(1, 0));
     433            1 :         vec1.push_back(Position(10, 0));
     434            1 :         vec1.push_back(Position(10, -5));
     435            1 :         vec1.push_back(Position(20, -5));
     436              :         Position on(4, 0);
     437              :         Position left(4, -1);
     438              :         Position right(4, 1);
     439              :         Position left2(4, -2);
     440              :         Position right2(4, 2);
     441              :         Position cornerRight(13, 4);
     442              :         Position cornerLeft(7, -9);
     443              :         Position before(0, 1);
     444              :         Position beyond(24, -9);
     445              : 
     446            2 :         EXPECT_EQ(Position(3, 0),  vec1.transformToVectorCoordinates(on));
     447            2 :         EXPECT_EQ(Position(3, 1),  vec1.transformToVectorCoordinates(left));
     448            2 :         EXPECT_EQ(Position(3, -1),  vec1.transformToVectorCoordinates(right));
     449            2 :         EXPECT_EQ(Position(3, 2),  vec1.transformToVectorCoordinates(left2));
     450            2 :         EXPECT_EQ(Position(3, -2),  vec1.transformToVectorCoordinates(right2));
     451            2 :         EXPECT_EQ(Position(9, -5),  vec1.transformToVectorCoordinates(cornerRight));
     452            2 :         EXPECT_EQ(Position(14, 5),  vec1.transformToVectorCoordinates(cornerLeft));
     453              : 
     454            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(before));
     455            2 :         EXPECT_EQ(Position::INVALID,  vec1.transformToVectorCoordinates(beyond));
     456            2 :         EXPECT_EQ(Position(-1, -1),  vec1.transformToVectorCoordinates(before, true));
     457            2 :         EXPECT_EQ(Position(28, 4),  vec1.transformToVectorCoordinates(beyond, true));
     458            1 :     }
     459            1 : }
     460              : 
     461              : 
     462              : /* Test the method 'distance'*/
     463            1 : TEST_F(PositionVectorTest, test_method_distance) {
     464              :     {
     465            1 :         PositionVector vec1;
     466            1 :         vec1.push_back(Position(1, 0));
     467            1 :         vec1.push_back(Position(10, 0));
     468            1 :         vec1.push_back(Position(10, 5));
     469            1 :         vec1.push_back(Position(20, 5));
     470              :         Position on(4, 0);
     471              :         Position left(4, 1);
     472              :         Position right(4, -1);
     473              :         Position left2(4, 2);
     474              :         Position right2(4, -2);
     475              :         Position cornerRight(13, -4);
     476              :         Position cornerLeft(7, 9);
     477              :         Position before(-3, -3);
     478              :         Position beyond(24, 8);
     479              : 
     480            1 :         EXPECT_EQ(0, vec1.distance2D(on));
     481            1 :         EXPECT_EQ(1, vec1.distance2D(left));
     482            1 :         EXPECT_EQ(1, vec1.distance2D(right));
     483            1 :         EXPECT_EQ(2, vec1.distance2D(left2));
     484            1 :         EXPECT_EQ(2, vec1.distance2D(right2));
     485            1 :         EXPECT_EQ(5, vec1.distance2D(cornerRight));
     486            1 :         EXPECT_EQ(5, vec1.distance2D(cornerLeft));
     487              : 
     488            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(before, true));
     489            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(beyond, true));
     490            1 :         EXPECT_EQ(5, vec1.distance2D(before));
     491            1 :         EXPECT_EQ(5, vec1.distance2D(beyond));
     492            1 :     }
     493              : 
     494              :     {
     495            1 :         PositionVector vec1; // the same tests as before, mirrored on x-axis
     496            1 :         vec1.push_back(Position(1, 0));
     497            1 :         vec1.push_back(Position(10, 0));
     498            1 :         vec1.push_back(Position(10, -5));
     499            1 :         vec1.push_back(Position(20, -5));
     500              :         Position on(4, 0);
     501              :         Position left(4, -1);
     502              :         Position right(4, 1);
     503              :         Position left2(4, -2);
     504              :         Position right2(4, 2);
     505              :         Position cornerRight(13, 4);
     506              :         Position cornerLeft(7, -9);
     507              :         Position before(-3, 3);
     508              :         Position beyond(24, -8);
     509              : 
     510            1 :         EXPECT_EQ(0, vec1.distance2D(on));
     511            1 :         EXPECT_EQ(1, vec1.distance2D(left));
     512            1 :         EXPECT_EQ(1, vec1.distance2D(right));
     513            1 :         EXPECT_EQ(2, vec1.distance2D(left2));
     514            1 :         EXPECT_EQ(2, vec1.distance2D(right2));
     515            1 :         EXPECT_EQ(5, vec1.distance2D(cornerRight));
     516            1 :         EXPECT_EQ(5, vec1.distance2D(cornerLeft));
     517              : 
     518            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(before, true));
     519            1 :         EXPECT_EQ(GeomHelper::INVALID_OFFSET,  vec1.distance2D(beyond, true));
     520            1 :         EXPECT_EQ(5, vec1.distance2D(before));
     521            1 :         EXPECT_EQ(5, vec1.distance2D(beyond));
     522            1 :     }
     523            1 : }
     524              : 
     525              : 
     526              : /* Test the method 'distance'*/
     527            1 : TEST_F(PositionVectorTest, test_method_distances) {
     528              :     {
     529            1 :         PositionVector vec1;
     530            1 :         vec1.push_back(Position(0, 0));
     531            1 :         vec1.push_back(Position(10, 0));
     532              : 
     533            1 :         PositionVector vec2;
     534            1 :         vec2.push_back(Position(1, 0));
     535            1 :         vec2.push_back(Position(5, 2));
     536            1 :         vec2.push_back(Position(10, 0));
     537            1 :         vec2.push_back(Position(14, 3));
     538              : 
     539            1 :         PositionVector vec3;
     540              : 
     541              :         std::vector<double> res1;
     542            1 :         res1.push_back(1);
     543            1 :         res1.push_back(0);
     544            1 :         res1.push_back(0);
     545            1 :         res1.push_back(2);
     546            1 :         res1.push_back(0);
     547            1 :         res1.push_back(5);
     548            9 :         EXPECT_DOUBLEVEC_EQUAL(res1,  vec1.distances(vec2));
     549              : 
     550              : 
     551            1 :         std::vector<double> res2;
     552              :         //invalid: res1.push_back(1);
     553            1 :         res2.push_back(0);
     554            1 :         res2.push_back(0);
     555            1 :         res2.push_back(2);
     556            1 :         res2.push_back(0);
     557              :         //invalid: res2.push_back(5);
     558            7 :         EXPECT_DOUBLEVEC_EQUAL(res2,  vec1.distances(vec2, true));
     559              : 
     560              : 
     561            1 :         std::vector<double> res3;
     562            1 :         res3.push_back(std::numeric_limits<double>::max());
     563            1 :         res3.push_back(std::numeric_limits<double>::max());
     564            5 :         EXPECT_DOUBLEVEC_EQUAL(res3,  vec1.distances(vec3));
     565            1 :     }
     566              : 
     567            1 : }
     568              : 
     569              : 
     570              : /* Test the method 'overlapsWith'*/
     571            1 : TEST_F(PositionVectorTest, test_method_overlapsWith) {
     572            1 :     PositionVector vec1;
     573            1 :     vec1.push_back(Position(1, 2));
     574            1 :     vec1.push_back(Position(3, 2));
     575            1 :     vec1.push_back(Position(3, 6));
     576            1 :     vec1.push_back(Position(1, 6));
     577              : 
     578            1 :     PositionVector vec2;
     579            1 :     vec2.push_back(Position(10, 17));
     580            1 :     vec2.push_back(Position(13, 17));
     581            1 :     vec2.push_back(Position(13, 16));
     582            1 :     vec2.push_back(Position(10, 16));
     583              : 
     584            1 :     PositionVector vec3;
     585            1 :     vec3.push_back(Position(-1, -7));
     586            1 :     vec3.push_back(Position(2, -7));
     587            1 :     vec3.push_back(Position(2,  4));
     588            1 :     vec3.push_back(Position(-1,  4));
     589              : 
     590            1 :     PositionVector vec4;
     591            1 :     vec4.push_back(Position(0, 3));
     592            1 :     vec4.push_back(Position(4, 3));
     593            1 :     vec4.push_back(Position(4, 5));
     594            1 :     vec4.push_back(Position(0, 5));
     595              : 
     596            1 :     PositionVector vec5;
     597            1 :     vec5.push_back(Position(4, 2));
     598            1 :     vec5.push_back(Position(5, 2));
     599            1 :     vec5.push_back(Position(5, 7));
     600            1 :     vec5.push_back(Position(4, 7));
     601              : 
     602            1 :     PositionVector vec6;
     603            1 :     vec6.push_back(Position(4, 0));
     604            1 :     vec6.push_back(Position(4, 8));
     605            1 :     vec6.push_back(Position(-4, 8));
     606              : 
     607            1 :     PositionVector empty;
     608              : 
     609            1 :     EXPECT_TRUE(vec1.overlapsWith(vec1));
     610            1 :     EXPECT_FALSE(vec1.overlapsWith(vec2));
     611            1 :     EXPECT_TRUE(vec1.overlapsWith(vec3));
     612            1 :     EXPECT_TRUE(vec1.overlapsWith(vec4));
     613            1 :     EXPECT_FALSE(vec1.overlapsWith(vec5, 0));
     614            1 :     EXPECT_TRUE(vec1.overlapsWith(vec6)); // overlapsWith implicitly closes the shape of vec6
     615            1 :     EXPECT_TRUE(vec6.overlapsWith(vec1)); // overlapsWith implicitly closes the shape of vec6
     616              :     // growth is from centroid and thus different from Boundary behavior
     617            1 :     EXPECT_FALSE(vec1.overlapsWith(vec5, 1));
     618            1 :     EXPECT_TRUE(vec1.overlapsWith(vec5, 3));
     619            1 :     EXPECT_TRUE(vec1.overlapsWith(vec5, 6));
     620            1 :     EXPECT_FALSE(vec1.overlapsWith(empty));
     621            1 : }
     622              : 
     623              : 
     624              : /* Test the method 'sortAsPolyCWByAngle'*/
     625            1 : TEST_F(PositionVectorTest, test_method_sortAsPolyCWByAngle) {
     626            1 :     PositionVector vectorTrianglePositiveCoordsClockwiseOrdered;
     627            1 :     vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(2, 3));
     628            1 :     vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(3, 0));
     629            1 :     vectorTrianglePositiveCoordsClockwiseOrdered.push_back(Position(1, 1));
     630            1 :     vectorTrianglePositiveCoords->sortAsPolyCWByAngle();
     631           12 :     EXPECT_POSITIONVEC_EQUAL((*vectorTrianglePositiveCoords), vectorTrianglePositiveCoordsClockwiseOrdered);
     632              : 
     633            2 :     PositionVector vectorTriangleNegativeCoordsClockwiseOrdered;
     634            1 :     vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(1, -1));
     635            1 :     vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(2, -1));
     636            1 :     vectorTriangleNegativeCoordsClockwiseOrdered.push_back(Position(2, -3));
     637            1 :     vectorTriangleNegativeCoords->sortAsPolyCWByAngle();
     638           12 :     EXPECT_POSITIONVEC_EQUAL((*vectorTriangleNegativeCoords), vectorTriangleNegativeCoordsClockwiseOrdered);
     639              : 
     640            2 :     PositionVector vectorRectangleOriginAlignedCornersClockwiseOrdered;
     641            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(1, 3));
     642            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(3, 3));
     643            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(3, 1));
     644            1 :     vectorRectangleOriginAlignedCornersClockwiseOrdered.push_back(Position(1, 1));
     645            1 :     vectorRectangleOriginAlignedCorners->sortAsPolyCWByAngle();
     646           15 :     EXPECT_POSITIONVEC_EQUAL((*vectorRectangleOriginAlignedCorners), vectorRectangleOriginAlignedCornersClockwiseOrdered);
     647            1 : }
     648              : 
     649              : 
     650              : /* Test the method 'isClockwiseOriented'*/
     651            1 : TEST_F(PositionVectorTest, test_method_isClockwiseOriented) {
     652            1 :     EXPECT_FALSE(vectorTrianglePositiveCoords->isClockwiseOriented());
     653            1 :     EXPECT_FALSE(vectorTriangleNegativeCoords->isClockwiseOriented());
     654            1 :     EXPECT_FALSE(vectorRectangleOriginAlignedCorners->isClockwiseOriented());
     655            1 : }
     656              : 
     657              : 
     658              : /* Test the method 'simplified'*/
     659            2 : TEST_F(PositionVectorTest, test_method_simplified) {
     660            1 :     const PositionVector vec1(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2)});
     661            1 :     const PositionVector result = vec1.simplified();
     662            1 :     EXPECT_EQ(3, (int)result.size());
     663            2 :     const PositionVector vec2(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2), Position(1, 2)});
     664            2 :     const PositionVector result2 = vec2.simplified();
     665            1 :     EXPECT_EQ(4, (int)result2.size());
     666            2 :     const PositionVector vec3(std::vector<Position> {Position(1, 2), Position(1, 3), Position(1, 4), Position(1, 5)});
     667            2 :     const PositionVector result3 = vec3.simplified();
     668              :     // std::cout << result3 << std::endl;
     669            1 :     EXPECT_EQ(3, (int)result3.size());
     670              : 
     671            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),
     672              :                               Position(2. * NUMERICAL_EPS, 4), Position(3. * NUMERICAL_EPS / 2., 3), Position(NUMERICAL_EPS, 2), Position(NUMERICAL_EPS / 2., 1)
     673            2 :                                                     });
     674            2 :     const PositionVector result4 = vec4.simplified();
     675            1 :     EXPECT_EQ(3, (int)result4.size());
     676            1 : }
     677              : 
     678              : 
     679              : /* Test the method 'simplified2'*/
     680            2 : TEST_F(PositionVectorTest, test_method_simplified2) {
     681            1 :     const PositionVector vec1(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2)});
     682            1 :     const PositionVector result = vec1.simplified2(true);
     683            1 :     EXPECT_EQ(2, (int)result.size());
     684            2 :     const PositionVector vec2(std::vector<Position> {Position(1, 2), Position(1, 2), Position(1, 2), Position(1, 2)});
     685            2 :     const PositionVector result2 = vec2.simplified2(true);
     686            1 :     EXPECT_EQ(2, (int)result2.size());
     687            2 :     const PositionVector vec3(std::vector<Position> {Position(1, 2), Position(1, 3), Position(1, 4), Position(1, 5)});
     688            2 :     const PositionVector result3 = vec3.simplified2(true);
     689              :     // std::cout << result3 << std::endl;
     690            1 :     EXPECT_EQ(2, (int)result3.size());
     691            1 :     EXPECT_DOUBLE_EQ(2., result3.front().y());
     692            1 :     EXPECT_DOUBLE_EQ(5., result3.back().y());
     693              : 
     694            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),
     695              :                               Position(2. * NUMERICAL_EPS, 4), Position(3. * NUMERICAL_EPS / 2., 3), Position(NUMERICAL_EPS, 2), Position(NUMERICAL_EPS / 2., 1)
     696            2 :                                                     });
     697            2 :     const PositionVector result4 = vec4.simplified2(true);
     698            1 :     EXPECT_EQ(3, (int)result4.size());
     699            1 :     EXPECT_DOUBLE_EQ(0., result4.front().y());
     700            1 :     EXPECT_DOUBLE_EQ(8., result4[1].y());
     701            1 :     EXPECT_DOUBLE_EQ(4., result4.back().y());
     702            1 : }
        

Generated by: LCOV version 2.0-1