LCOV - code coverage report
Current view: top level - include/ad/map/point - EdgeOperation.hpp (source / functions) Hit Total Coverage
Test: ad_map_access Lines: 182 198 91.9 %
Date: 2022-10-04 09:48:07 Functions: 22 24 91.7 %
Branches: 179 344 52.0 %

           Branch data     Line data    Source code
       1                 :            : // ----------------- BEGIN LICENSE BLOCK ---------------------------------
       2                 :            : //
       3                 :            : // Copyright (C) 2018-2021 Intel Corporation
       4                 :            : //
       5                 :            : // SPDX-License-Identifier: MIT
       6                 :            : //
       7                 :            : // ----------------- END LICENSE BLOCK -----------------------------------
       8                 :            : /**
       9                 :            :  * @file
      10                 :            :  */
      11                 :            : 
      12                 :            : #pragma once
      13                 :            : 
      14                 :            : #include <utility>
      15                 :            : #include <vector>
      16                 :            : #include "ad/map/point/PointOperation.hpp"
      17                 :            : #include "ad/physics/MetricRange.hpp"
      18                 :            : #include "ad/physics/Operation.hpp"
      19                 :            : #include "ad/physics/ParametricRange.hpp"
      20                 :            : #include "ad/physics/ParametricValueValidInputRange.hpp"
      21                 :            : #include "ad/physics/RangeOperation.hpp"
      22                 :            : 
      23                 :            : /** @brief namespace ad */
      24                 :            : namespace ad {
      25                 :            : /** @brief namespace map */
      26                 :            : namespace map {
      27                 :            : /** @brief namespace point */
      28                 :            : namespace point {
      29                 :            : 
      30                 :            : /**
      31                 :            :  * @brief The edge point border distance
      32                 :            :  */
      33                 :            : physics::Distance const cEdgePointBorderDistance{0.1};
      34                 :            : 
      35                 :            : /**
      36                 :            :  * @brief Find point nearest to the line formed by two points.
      37                 :            :  *
      38                 :            :  * @param[in] a point to search for
      39                 :            :  * @param[in] pt0 First point of the line.
      40                 :            :  * @param[in] pt1 Second point of the line.
      41                 :            :  * @returns Value of t;  nearest point to a can be calculated as (1-t)*pt0+t*pt1.
      42                 :            :  */
      43                 :            : template <typename PointType>
      44                 :   23422701 : physics::RatioValue findNearestPointOnEdge(PointType const &a, const PointType &pt0, const PointType &pt1)
      45                 :            : {
      46         [ +  - ]:   23422701 :   PointType line = pt1 - pt0;
      47         [ +  - ]:   23422701 :   PointType pt02a = a - pt0;
      48                 :   23422701 :   auto const divisor = vectorDotProduct(line, line);
      49   [ +  -  +  + ]:   23422701 :   if (physics::Distance(divisor) > physics::Distance(0))
      50                 :            :   {
      51                 :   23159201 :     auto const dividend = vectorDotProduct(pt02a, line);
      52                 :   23159201 :     auto result = dividend / divisor;
      53                 :   23159201 :     return physics::RatioValue(result);
      54                 :            :   }
      55                 :            :   else
      56                 :            :   {
      57                 :     263453 :     return physics::RatioValue(0.5);
      58                 :            :   }
      59                 :            : }
      60                 :            : 
      61                 :            : /**
      62                 :            :  * @brief Find point nearest to the segment formed by two points.
      63                 :            :  *
      64                 :            :  * @param[in] a point to search for
      65                 :            :  * @param[in] pt0 First point of the segment.
      66                 :            :  * @param[in] pt1 Second point of the segment.
      67                 :            :  * @returns Value of 0<=t<=1;  nearest point to this can be calculated as (1-t)*pt0+t*pt1.
      68                 :            :  *
      69                 :            :  */
      70                 :            : template <typename PointType>
      71                 :   22953701 : physics::ParametricValue findNearestPointOnSegment(PointType const &a, const PointType &pt0, const PointType &pt1)
      72                 :            : {
      73         [ +  - ]:   22953701 :   auto const t = findNearestPointOnEdge(a, pt0, pt1);
      74   [ +  -  +  + ]:   22953701 :   if (t < physics::RatioValue(0.))
      75                 :            :   {
      76                 :   10048700 :     return physics::ParametricValue(0.);
      77                 :            :   }
      78   [ +  -  +  + ]:   12904901 :   else if (t > physics::RatioValue(1.))
      79                 :            :   {
      80                 :   10462300 :     return physics::ParametricValue(1.);
      81                 :            :   }
      82                 :            :   else
      83                 :            :   {
      84                 :    2442601 :     return physics::ParametricValue(static_cast<double>(t));
      85                 :            :   }
      86                 :            : }
      87                 :            : 
      88                 :            : /**
      89                 :            :  * @brief Calculate the length of an edge
      90                 :            :  * @param[in] edge The input edge to operate on.
      91                 :            :  * @return The length of the edge
      92                 :            :  */
      93                 :      53344 : template <typename PointType> physics::Distance calculateEdgeLength(std::vector<PointType> const &edge)
      94                 :            : {
      95                 :      53344 :   physics::Distance length(0.);
      96         [ +  + ]:     490740 :   for (auto i = 1u; i < edge.size(); ++i)
      97                 :            :   {
      98   [ +  -  +  - ]:     437396 :     length += distance(edge[i - 1u], edge[i]);
      99                 :            :   }
     100                 :      53344 :   return length;
     101                 :            : }
     102                 :            : 
     103                 :            : /**
     104                 :            :  * @brief Get the parametric edge points
     105                 :            :  * @param[in] edge The input edge to operate on.
     106                 :            :  * @return Vector of parametric values on the edge.
     107                 :            :  */
     108                 :            : template <typename PointType>
     109                 :         16 : std::vector<physics::ParametricValue> getParametricEdgePoints(std::vector<PointType> const &edge)
     110                 :            : {
     111                 :         16 :   std::vector<physics::ParametricValue> resultPoints;
     112         [ +  - ]:         16 :   resultPoints.reserve(edge.size());
     113         [ +  - ]:         16 :   resultPoints.push_back(physics::ParametricValue(0.));
     114                 :         16 :   physics::Distance length(0.);
     115         [ +  + ]:         38 :   for (auto i = 1u; i < edge.size(); ++i)
     116                 :            :   {
     117   [ +  -  +  - ]:         22 :     length += distance(edge[i - 1u], edge[i]);
     118         [ +  - ]:         22 :     resultPoints.push_back(physics::ParametricValue(static_cast<double>(length)));
     119                 :            :   }
     120                 :            : 
     121         [ +  + ]:         38 :   for (auto i = 1u; i < edge.size(); ++i)
     122                 :            :   {
     123   [ +  -  +  - ]:         22 :     if (length > physics::Distance(0.))
     124                 :            :     {
     125         [ +  - ]:         22 :       resultPoints[i] = resultPoints[i] / static_cast<double>(length);
     126                 :            :     }
     127                 :            :   }
     128                 :         32 :   return resultPoints;
     129                 :            : }
     130                 :            : 
     131                 :            : /**
     132                 :            :  * @brief Calculates parametric point on the edge.
     133                 :            :  * @param[in] edge The input edge to operate on.
     134                 :            :  * @param[in] t Parameter. 0 will return first point, and 1 last point on the edge.
     135                 :            :  * @return Parametric point on the edge.
     136                 :            :  */
     137                 :            : template <typename PointType>
     138                 :    5131463 : PointType getParametricPoint(std::vector<PointType> const &edge,
     139                 :            :                              physics::Distance const &edgeLength,
     140                 :            :                              const physics::ParametricValue &t)
     141                 :            : {
     142         [ +  + ]:    5131463 :   if (!edge.empty())
     143                 :            :   {
     144                 :    5131463 :     physics::Distance length(0);
     145         [ +  - ]:    5131463 :     physics::Distance length_t = edgeLength * t;
     146         [ +  + ]:   25519503 :     for (size_t i = 0; i < edge.size() - 1; i++)
     147                 :            :     {
     148                 :   25519303 :       const auto &pt0 = edge[i];
     149                 :   25519303 :       const auto &pt1 = edge[i + 1];
     150         [ +  - ]:   25519303 :       auto d = distance(pt0, pt1);
     151   [ +  -  +  + ]:   25519303 :       if (d != physics::Distance(0.))
     152                 :            :       {
     153         [ +  - ]:   25519003 :         auto length_1 = length + d;
     154   [ +  -  +  + ]:   25519003 :         if (length_1 >= length_t)
     155                 :            :         {
     156         [ +  - ]:    5131213 :           auto d_t = length_t - length;
     157         [ +  - ]:    5131213 :           physics::ParametricValue tt(d_t / d);
     158         [ +  - ]:    5131213 :           return vectorInterpolate(pt0, pt1, tt);
     159                 :            :         }
     160                 :            :         else
     161                 :            :         {
     162                 :   20387800 :           length = length_1;
     163                 :            :         }
     164                 :            :       }
     165                 :            :     }
     166                 :        252 :     return edge.back();
     167                 :            :   }
     168                 :            :   else
     169                 :            :   {
     170                 :          1 :     return PointType();
     171                 :            :   }
     172                 :            : }
     173                 :            : 
     174                 :            : /**
     175                 :            :  * @brief Calculates parametric point on the edge.
     176                 :            :  * @param[in] edge The input edge to operate on.
     177                 :            :  * @param[in] t Parameter. 0 will return first point, and 1 last point on the edge.
     178                 :            :  * @return Parametric point on the edge.
     179                 :            :  */
     180                 :            : template <typename PointType>
     181                 :          0 : PointType getParametricPoint(std::vector<PointType> const &edge, const physics::ParametricValue &t)
     182                 :            : {
     183         [ #  # ]:          0 :   return getParametricPoint(edge, calculateEdgeLength(edge), t);
     184                 :            : }
     185                 :            : 
     186                 :            : /**
     187                 :            :  * @brief Generates sub-edge for given range.
     188                 :            :  * @param[in] edge The input edge to operate on.
     189                 :            :  * @param[in] trange Specifies parametric range.
     190                 :            :  * @return Sub-geometry.
     191                 :            :  */
     192                 :            : template <typename PointType>
     193                 :       5638 : std::vector<PointType> getParametricRange(std::vector<PointType> const &edge,
     194                 :            :                                           physics::Distance const &edgeLength,
     195                 :            :                                           const physics::ParametricRange &trange)
     196                 :            : {
     197                 :            :   typedef std::vector<PointType> EdgeType;
     198         [ +  - ]:       5638 :   if (!edge.empty())
     199                 :            :   {
     200                 :       5638 :     EdgeType pts;
     201                 :       5638 :     physics::Distance length(0);
     202         [ +  - ]:       5638 :     physics::Distance length_t_start = edgeLength * trange.minimum;
     203                 :       5638 :     size_t i = 0;
     204   [ +  -  +  -  :       5654 :     for (; i < edge.size() - 1 && pts.empty(); i++)
                   +  - ]
     205                 :            :     {
     206                 :       5654 :       const PointType &pt0 = edge[i];
     207                 :       5654 :       const PointType &pt1 = edge[i + 1];
     208         [ +  - ]:       5654 :       physics::Distance d = distance(pt0, pt1);
     209         [ +  - ]:       5654 :       physics::Distance length_1 = length + d;
     210   [ +  -  +  + ]:       5654 :       if (length_1 >= length_t_start)
     211                 :            :       {
     212   [ +  -  +  + ]:       5638 :         if (d != physics::Distance(0))
     213                 :            :         {
     214         [ +  - ]:       5632 :           physics::Distance d_t = length_t_start - length;
     215         [ +  - ]:       5632 :           physics::ParametricValue tt(d_t / d);
     216         [ +  - ]:       5632 :           PointType pt_start = vectorInterpolate(pt0, pt1, tt);
     217         [ +  - ]:       5632 :           pts.push_back(pt_start);
     218                 :            :         }
     219                 :            :         else
     220                 :            :         {
     221         [ +  - ]:          6 :           pts.push_back(pt1);
     222                 :            :         }
     223                 :       5638 :         break;
     224                 :            :       }
     225                 :            :       else
     226                 :            :       {
     227                 :         16 :         length = length_1;
     228                 :            :       }
     229                 :            :     }
     230         [ +  - ]:       5638 :     if (!pts.empty())
     231                 :            :     {
     232         [ +  - ]:       5638 :       physics::Distance length_t_end = edgeLength * trange.maximum;
     233         [ +  - ]:      54599 :       for (; i < edge.size() - 1; i++)
     234                 :            :       {
     235                 :      54599 :         const PointType &pt0 = edge[i];
     236                 :      54599 :         const PointType &pt1 = edge[i + 1];
     237         [ +  - ]:      54599 :         physics::Distance d = distance(pt0, pt1);
     238         [ +  - ]:      54599 :         physics::Distance length_1 = length + d;
     239   [ +  -  +  + ]:      54599 :         if (length_1 >= length_t_end)
     240                 :            :         {
     241   [ +  -  +  + ]:       5638 :           if (d != physics::Distance(0))
     242                 :            :           {
     243         [ +  - ]:       5632 :             physics::Distance d_t = length_t_end - length;
     244         [ +  - ]:       5632 :             physics::ParametricValue tt(d_t / d);
     245         [ +  - ]:       5632 :             PointType pt_end = vectorInterpolate(pt0, pt1, tt);
     246         [ +  - ]:       5632 :             pts.push_back(pt_end);
     247                 :            :           }
     248                 :            :           else
     249                 :            :           {
     250         [ +  - ]:          6 :             pts.push_back(pt1);
     251                 :            :           }
     252                 :       5638 :           return pts;
     253                 :            :         }
     254                 :            :         else
     255                 :            :         {
     256         [ +  - ]:      48961 :           pts.push_back(pt1);
     257                 :      48961 :           length = length_1;
     258                 :            :         }
     259                 :            :       }
     260         [ #  # ]:          0 :       pts.push_back(edge.back());
     261                 :          0 :       return pts;
     262                 :            :     }
     263                 :            :   }
     264                 :          0 :   return EdgeType();
     265                 :            : }
     266                 :            : 
     267                 :            : /**
     268                 :            :  * @brief Generates sub-edge for given range.
     269                 :            :  * @param[in] edge The input edge to operate on.
     270                 :            :  * @param[in] trange Specifies parametric range.
     271                 :            :  * @return Sub-geometry.
     272                 :            :  */
     273                 :            : template <typename PointType>
     274                 :       5590 : std::vector<PointType> getParametricRange(std::vector<PointType> const &edge, const physics::ParametricRange &trange)
     275                 :            : {
     276         [ +  - ]:      11180 :   return getParametricRange(edge, calculateEdgeLength(edge), trange);
     277                 :            : }
     278                 :            : 
     279                 :            : /**
     280                 :            :  * @brief Finds point on geometry nearest to given point.
     281                 :            :  * @param[in] pt Point of interest.
     282                 :            :  * @returns Parametric point on geometry nearest to the pt.
     283                 :            :  *          Can be invalid (if pt is Invalid(), geometry is empty etc.).
     284                 :            :  */
     285                 :            : template <typename PointType>
     286                 :            : physics::ParametricValue
     287                 :    2630711 : findNearestPointOnEdge(std::vector<PointType> const &edge, physics::Distance const &edgeLength, const PointType &pt)
     288                 :            : {
     289         [ +  - ]:    2630711 :   if (isValid(pt))
     290                 :            :   {
     291         [ -  + ]:    2630711 :     if (edge.size() == 0)
     292                 :            :     {
     293                 :          0 :       return physics::ParametricValue();
     294                 :            :     }
     295   [ +  -  +  -  :    2630711 :     else if ((edge.size() == 1) || (edgeLength == physics::Distance(0.)))
             +  +  +  + ]
     296                 :            :     {
     297                 :        126 :       return physics::ParametricValue(0);
     298                 :            :     }
     299                 :            :     else
     300                 :            :     {
     301         [ +  - ]:    2630581 :       physics::ParametricValue t_one = findNearestPointOnSegment(pt, edge[0], edge[1]);
     302         [ +  - ]:    2630581 :       PointType pt_nearest = vectorInterpolate(edge[0], edge[1], t_one);
     303         [ +  - ]:    2630581 :       physics::Distance d_nearest = distance(pt, pt_nearest);
     304         [ +  - ]:    2630581 :       physics::Distance offset_nearest = distance(pt_nearest, edge[0]);
     305                 :    2630581 :       physics::Distance running_offset = physics::Distance(0);
     306         [ +  + ]:   22953701 :       for (size_t i = 1; i + 1 < edge.size(); i++)
     307                 :            :       {
     308         [ +  - ]:   20323100 :         physics::ParametricValue t = findNearestPointOnSegment(pt, edge[i], edge[i + 1]);
     309         [ +  - ]:   20323100 :         PointType pt_candidate = vectorInterpolate(edge[i], edge[i + 1], t);
     310         [ +  - ]:   20323100 :         physics::Distance d = distance(pt_candidate, pt);
     311   [ +  -  +  - ]:   20323100 :         running_offset += distance(edge[i - 1], edge[i]);
     312   [ +  -  +  + ]:   20323100 :         if (d < d_nearest)
     313                 :            :         {
     314                 :   10115200 :           pt_nearest = pt_candidate;
     315                 :   10115200 :           d_nearest = d;
     316   [ +  -  +  - ]:   10115200 :           offset_nearest = running_offset + distance(pt_nearest, edge[i]);
     317                 :            :         }
     318                 :            :       }
     319         [ +  - ]:    2630581 :       return physics::ParametricValue(offset_nearest / edgeLength);
     320                 :            :     }
     321                 :            :   }
     322                 :            :   else
     323                 :            :   {
     324                 :          0 :     return physics::ParametricValue();
     325                 :            :   }
     326                 :            : }
     327                 :            : 
     328                 :            : /**
     329                 :            :  * @brief Find the nearest point on an edge
     330                 :            :  * @param[in] edge The input edge to operate on.
     331                 :            :  * @param[in] pt Point of interest.
     332                 :            :  * @returns Parametric point on geometry nearest to the pt.
     333                 :            :  *          Can be invalid (if pt is Invalid(), geometry is empty etc.).
     334                 :            :  */
     335                 :            : template <typename PointType>
     336                 :            : physics::ParametricValue findNearestPointOnEdge(std::vector<PointType> const &edge, const PointType &pt)
     337                 :            : {
     338                 :            :   return findNearestPointOnEdge(edge, calculateEdgeLength(edge), pt);
     339                 :            : }
     340                 :            : 
     341                 :            : /**
     342                 :            :  * @brief Calculate the width range and the average width of a pair of edges
     343                 :            :  *
     344                 :            :  * At maximum 100 supporting points are taken into account to calculate this.
     345                 :            :  *
     346                 :            :  * @param[in] leftEdge the left-hand border edge as basis for the calculation
     347                 :            :  * @param[in] leftEdgeLength the length of the left-hand border edge
     348                 :            :  * @param[in] rightEdge the right-hand border edge as basis for the calculation
     349                 :            :  * @param[in] rightEdgeLength the length of the left-hand border edge
     350                 :            :  *
     351                 :            :  * @returns pair containing the range of the width and the average width between the two input edges.
     352                 :            :  */
     353                 :            : template <typename PointType>
     354                 :      23501 : std::pair<physics::MetricRange, physics::Distance> calculateWidthRange(std::vector<PointType> const &edgeLeft,
     355                 :            :                                                                        physics::Distance const &edgeLeftLength,
     356                 :            :                                                                        std::vector<PointType> const &edgeRight,
     357                 :            :                                                                        physics::Distance const &edgeRightLength)
     358                 :            : {
     359         [ +  - ]:      23501 :   physics::MetricRange widthRange;
     360                 :      23501 :   widthRange.minimum = std::numeric_limits<physics::Distance>::max();
     361                 :      23501 :   widthRange.maximum = physics::Distance(0.);
     362                 :      23501 :   physics::Distance widthSum(0.);
     363                 :      23501 :   size_t widthSumCount(0u);
     364                 :      23501 :   physics::ParametricValue parametricStepsize(0.5);
     365   [ +  -  +  - ]:      23501 :   auto length = (edgeLeftLength + edgeRightLength) * 0.5;
     366   [ +  -  +  + ]:      23501 :   if (length > physics::Distance(1.))
     367                 :            :   {
     368                 :      22424 :     parametricStepsize
     369         [ +  - ]:      22424 :       = std::max(physics::ParametricValue(0.01), physics::ParametricValue(1. / static_cast<double>(length)));
     370                 :            :   }
     371                 :      23501 :   physics::ParametricValue longitudinalOffset(0.);
     372                 :      23501 :   bool endReached = false;
     373                 :     815659 :   do
     374                 :            :   {
     375         [ +  - ]:     839160 :     auto const pt0 = getParametricPoint(edgeLeft, edgeLeftLength, longitudinalOffset);
     376         [ +  - ]:     839160 :     auto const pt1 = getParametricPoint(edgeRight, edgeRightLength, longitudinalOffset);
     377   [ +  -  +  -  :     839160 :     if (!isValid(pt1) || !isValid(pt1))
          +  -  -  +  -  
                      + ]
     378                 :            :     {
     379   [ #  #  #  # ]:          0 :       return std::make_pair(physics::MetricRange(), physics::Distance());
     380                 :            :     }
     381         [ +  - ]:     839160 :     auto const centerPoint = point::vectorInterpolate(pt0, pt1, physics::ParametricValue(0.5));
     382   [ +  -  -  + ]:     839160 :     if (!isValid(centerPoint))
     383                 :            :     {
     384   [ #  #  #  # ]:          0 :       return std::make_pair(physics::MetricRange(), physics::Distance());
     385                 :            :     }
     386         [ +  - ]:     839160 :     auto const longTLeft = findNearestPointOnEdge(edgeLeft, edgeLeftLength, centerPoint);
     387         [ +  - ]:     839160 :     auto const longTRight = findNearestPointOnEdge(edgeRight, edgeRightLength, centerPoint);
     388   [ +  -  +  -  :     839160 :     if (!isRangeValid(longTLeft) || !isRangeValid(longTRight))
          +  -  -  +  -  
                      + ]
     389                 :            :     {
     390   [ #  #  #  # ]:          0 :       return std::make_pair(physics::MetricRange(), physics::Distance());
     391                 :            :     }
     392         [ +  - ]:     839160 :     auto const pointOnLeftEdge = getParametricPoint(edgeLeft, edgeLeftLength, longTLeft);
     393         [ +  - ]:     839160 :     auto const pointOnRightEdge = getParametricPoint(edgeRight, edgeRightLength, longTRight);
     394   [ +  -  +  -  :     839160 :     if (!isValid(pointOnLeftEdge) || !isValid(pointOnRightEdge))
          +  -  -  +  -  
                      + ]
     395                 :            :     {
     396   [ #  #  #  # ]:          0 :       return std::make_pair(physics::MetricRange(), physics::Distance());
     397                 :            :     }
     398         [ +  - ]:     839160 :     physics::Distance const width = distance(pointOnLeftEdge, pointOnRightEdge);
     399         [ +  - ]:     839160 :     unionRangeWith(widthRange, width);
     400         [ +  - ]:     839160 :     widthSum += width;
     401                 :     839160 :     widthSumCount++;
     402   [ +  -  +  + ]:     839160 :     if (longitudinalOffset < physics::ParametricValue(1.))
     403                 :            :     {
     404         [ +  - ]:     815659 :       longitudinalOffset += parametricStepsize;
     405   [ +  -  +  + ]:     815659 :       if (longitudinalOffset > physics::ParametricValue(1.))
     406                 :            :       {
     407                 :      18804 :         longitudinalOffset = physics::ParametricValue(1.);
     408                 :            :       }
     409                 :            :     }
     410                 :            :     else
     411                 :            :     {
     412                 :      23501 :       endReached = true;
     413                 :            :     }
     414         [ +  + ]:     839160 :   } while (!endReached);
     415                 :            : 
     416         [ +  - ]:      23501 :   auto averageWidth = (widthSum / static_cast<double>(widthSumCount));
     417                 :            : 
     418         [ +  - ]:      23501 :   return std::make_pair(widthRange, averageWidth);
     419                 :            : }
     420                 :            : 
     421                 :            : /**
     422                 :            :  * @brief Get an edge between the two given border edges with corresponding lateralAlignment
     423                 :            :  *
     424                 :            :  * The left and right edges are usually the borders of some road section.
     425                 :            :  * This function then calculates a new edge in between two other edges providing e.g. the center edge
     426                 :            :  * (lateralAlgignment=0.5)
     427                 :            :  * or edge with other lateral shift.
     428                 :            :  *
     429                 :            :  * @param[in] leftEdge the left-hand border edge as basis for the calculation
     430                 :            :  * @param[in] leftEdgeLength the length of the left-hand border edge
     431                 :            :  * @param[in] rightEdge the right-hand border edge as basis for the calculation
     432                 :            :  * @param[in] rightEdgeLength the length of the left-hand border edge
     433                 :            :  * @param[in] lateralAlignment the lateral alignment as TParam [0.;1.] used to calculate the resulting edge.
     434                 :            :  *   The lateral alignment is relative to the left edge. If lateralAlignment is 1., the left edge is returned,
     435                 :            :  *   if lateralAlignment is 0., the right edge is returned
     436                 :            :  *
     437                 :            :  * @throws std::invalid_argument if the lateralAlignment parameter is smaller than 0. or larger than 1.
     438                 :            :  */
     439                 :            : template <typename PointType>
     440                 :          2 : std::vector<PointType> getLateralAlignmentEdge(std::vector<PointType> const &leftEdge,
     441                 :            :                                                physics::Distance const &leftEdgeLength,
     442                 :            :                                                std::vector<PointType> const &rightEdge,
     443                 :            :                                                physics::Distance const &rightEdgeLength,
     444                 :            :                                                physics::ParametricValue const lateralAlignment)
     445                 :            : {
     446                 :            :   typedef std::vector<PointType> EdgeType;
     447                 :            : 
     448   [ +  -  -  + ]:          2 :   if (!withinValidInputRange(lateralAlignment))
     449                 :            :   {
     450                 :            :     throw std::invalid_argument("ad::map::point::getLateralAlignmentEdge()"
     451         [ #  # ]:          0 :                                 " the given lateralAlignment is out of range");
     452                 :            :   }
     453                 :            : 
     454                 :            :   EdgeType const *primary;
     455                 :            :   EdgeType const *secondary;
     456                 :          2 :   physics::Distance primaryLength;
     457                 :          2 :   physics::Distance secondaryLength;
     458                 :          2 :   physics::ParametricValue lateralOffset = lateralAlignment;
     459         [ +  + ]:          2 :   if (leftEdge.size() > rightEdge.size())
     460                 :            :   {
     461                 :          1 :     primary = &leftEdge;
     462                 :          1 :     primaryLength = leftEdgeLength;
     463                 :          1 :     secondary = &rightEdge;
     464                 :          1 :     secondaryLength = rightEdgeLength;
     465         [ +  - ]:          1 :     lateralOffset = physics::ParametricValue(1.) - lateralAlignment;
     466                 :            :   }
     467                 :            :   else
     468                 :            :   {
     469                 :          1 :     primary = &rightEdge;
     470                 :          1 :     primaryLength = rightEdgeLength;
     471                 :          1 :     secondary = &leftEdge;
     472                 :          1 :     secondaryLength = leftEdgeLength;
     473                 :            :   }
     474                 :            : 
     475         [ +  - ]:          4 :   std::vector<physics::ParametricValue> const primaryParametric = getParametricEdgePoints(*primary);
     476                 :          2 :   EdgeType alignmentEdge;
     477         [ +  - ]:          2 :   alignmentEdge.reserve(primaryParametric.size());
     478         [ +  + ]:          7 :   for (size_t i = 0; i < primaryParametric.size(); i++)
     479                 :            :   {
     480         [ +  - ]:          5 :     PointType const &pri = primary->at(i);
     481         [ +  - ]:          5 :     PointType const sec = getParametricPoint(*secondary, secondaryLength, primaryParametric[i]);
     482         [ +  - ]:          5 :     PointType const alignmentPoint = vectorInterpolate(pri, sec, lateralOffset);
     483         [ +  - ]:          5 :     alignmentEdge.push_back(alignmentPoint);
     484                 :            :   }
     485                 :          4 :   return alignmentEdge;
     486                 :            : }
     487                 :            : 
     488                 :            : /**
     489                 :            :  * @brief Get an edge between the two given border edges with corresponding lateralAlignment
     490                 :            :  *
     491                 :            :  * The left and right edges are usually the borders of some road section.
     492                 :            :  * This function then calculates a new edge in between two other edges providing e.g. the center edge
     493                 :            :  * (lateralAlgignment=0.5)
     494                 :            :  * or edge with other lateral shift.
     495                 :            :  *
     496                 :            :  * Note: if the length of the edges are already know, the overloaded getLateralAlignmentEdge() function can be called.
     497                 :            :  *
     498                 :            :  * @param[in] leftEdge the left-hand border edge as basis for the calculation
     499                 :            :  * @param[in] rightEdge the right-hand border edge as basis for the calculation
     500                 :            :  * @param[in] lateralAlignment the lateral alignment as TParam [0.;1.] used to calculate the resulting edge.
     501                 :            :  *   The lateral alignment is relative to the left edge. If lateralAlignment is 1., the left edge is returned,
     502                 :            :  *   if lateralAlignment is 0., the right edge is returned
     503                 :            :  *
     504                 :            :  * @throws std::invalid_argument if the lateralAlignment parameter is smaller than 0. or larger than 1.
     505                 :            :  */
     506                 :            : template <typename PointType>
     507                 :          1 : std::vector<PointType> getLateralAlignmentEdge(std::vector<PointType> const &leftEdge,
     508                 :            :                                                std::vector<PointType> const &rightEdge,
     509                 :            :                                                physics::ParametricValue const lateralAlignment)
     510                 :            : {
     511                 :            :   return getLateralAlignmentEdge(
     512   [ +  -  +  - ]:          2 :     leftEdge, calculateEdgeLength(leftEdge), rightEdge, calculateEdgeLength(rightEdge), lateralAlignment);
     513                 :            : }
     514                 :            : 
     515                 :            : /**
     516                 :            :  * @brief get a normalized vector representing the edge direction at edge start
     517                 :            :  *
     518                 :            :  * If the number of edge points is <= 1, zero is returned.
     519                 :            :  * If the two start points of the edge are too close to each other, a third point is used if possible to increase
     520                 :            :  * the accuracy.
     521                 :            :  */
     522                 :          8 : template <typename PointType> PointType getEdgeStartDirectionalVector(std::vector<PointType> const edge)
     523                 :            : {
     524         [ -  + ]:          8 :   if (edge.size() <= 1u)
     525                 :            :   {
     526         [ #  # ]:          0 :     return PointType();
     527                 :            :   }
     528                 :            : 
     529         [ +  - ]:          8 :   auto edgeStartVec = edge[1u] - edge[0u];
     530                 :            :   // in case the end points are too near to each other we take another point into account if possible
     531   [ +  -  +  -  :          8 :   if ((vectorLength(edgeStartVec) < cEdgePointBorderDistance) && (edge.size() > 2u))
          -  +  -  -  -  
                      + ]
     532                 :            :   {
     533         [ #  # ]:          0 :     edgeStartVec = edge[2u] - edge[0u];
     534                 :            :   }
     535         [ +  - ]:          8 :   return vectorNorm(edgeStartVec);
     536                 :            : }
     537                 :            : 
     538                 :            : /**
     539                 :            :  * @brief get a normalized vector representing the edge direction at edge end
     540                 :            :  *
     541                 :            :  * If the number of edge points is <= 1, zero is returned.
     542                 :            :  * If the two end points of the edge are too close to each other, a third point is used if possible to increase
     543                 :            :  * the accuracy.
     544                 :            :  */
     545                 :          8 : template <typename PointType> PointType getEdgeEndDirectionalVector(std::vector<PointType> const edge)
     546                 :            : {
     547         [ -  + ]:          8 :   if (edge.size() <= 1u)
     548                 :            :   {
     549         [ #  # ]:          0 :     return PointType();
     550                 :            :   }
     551                 :            : 
     552         [ +  - ]:          8 :   auto edgeEndVec = edge[edge.size() - 1u] - edge[edge.size() - 2u];
     553                 :            :   // in case the end points are too near to each other we take another point into account if possible
     554   [ +  -  +  -  :          8 :   if ((vectorLength(edgeEndVec) < cEdgePointBorderDistance) && (edge.size() > 2u))
          -  +  -  -  -  
                      + ]
     555                 :            :   {
     556         [ #  # ]:          0 :     edgeEndVec = edge[edge.size() - 1u] - edge[edge.size() - 3u];
     557                 :            :   }
     558         [ +  - ]:          8 :   return vectorNorm(edgeEndVec);
     559                 :            : }
     560                 :            : 
     561                 :            : } // namespace point
     562                 :            : } // namespace map
     563                 :            : } // namespace ad

Generated by: LCOV version 1.14