LCOV - code coverage report
Current view: top level - unittest/src/utils/geom - PositionVectorTest.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 426 427 99.8 %
Date: 2024-05-04 15:27:10 Functions: 19 19 100.0 %

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

Generated by: LCOV version 1.14