LCOV - code coverage report
Current view: top level - src/common/autoware_auto_geometry/include/geometry - hull_pockets.hpp (source / functions) Hit Total Coverage
Test: coverage.filtered Lines: 24 24 100.0 %
Date: 2022-02-08 20:14:05 Functions: 3 3 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 19 28 67.9 %

           Branch data     Line data    Source code
       1                 :            : // Copyright 2020 Embotech AG, Zurich, Switzerland. All rights reserved.
       2                 :            : //
       3                 :            : // Licensed under the Apache License, Version 2.0 (the "License");
       4                 :            : // you may not use this file except in compliance with the License.
       5                 :            : // You may obtain a copy of the License at
       6                 :            : //
       7                 :            : //     http://www.apache.org/licenses/LICENSE-2.0
       8                 :            : //
       9                 :            : // Unless required by applicable law or agreed to in writing, software
      10                 :            : // distributed under the License is distributed on an "AS IS" BASIS,
      11                 :            : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12                 :            : // See the License for the specific language governing permissions and
      13                 :            : // limitations under the License.
      14                 :            : //
      15                 :            : // Co-developed by Tier IV, Inc. and Apex.AI, Inc.
      16                 :            : 
      17                 :            : /// \file
      18                 :            : /// \brief This file implements an algorithm for getting a list of "pockets" in the convex
      19                 :            : ///        hull of a non-convex simple polygon.
      20                 :            : 
      21                 :            : #ifndef GEOMETRY__HULL_POCKETS_HPP_
      22                 :            : #define GEOMETRY__HULL_POCKETS_HPP_
      23                 :            : 
      24                 :            : #include <common/types.hpp>
      25                 :            : #include <geometry/common_2d.hpp>
      26                 :            : #include <vector>
      27                 :            : #include <utility>
      28                 :            : #include <limits>
      29                 :            : #include <algorithm>
      30                 :            : #include <iterator>
      31                 :            : 
      32                 :            : using autoware::common::types::float32_t;
      33                 :            : 
      34                 :            : namespace autoware
      35                 :            : {
      36                 :            : namespace common
      37                 :            : {
      38                 :            : namespace geometry
      39                 :            : {
      40                 :            : 
      41                 :            : 
      42                 :            : /// \brief Compute a list of "pockets" of a simple polygon
      43                 :            : ///   (https://en.wikipedia.org/wiki/Simple_polygon), that is, the areas that make
      44                 :            : ///   up the difference between the polygon and its convex hull.
      45                 :            : ///   This currently has a bug:
      46                 :            : //    * "Rollover" is not properly handled - if a pocket contains the segment from
      47                 :            : //      the last point in the list to the first point (which is still part of the
      48                 :            : //      polygon), that does not get added
      49                 :            : ///
      50                 :            : /// \param[in] polygon_start Start iterator for the simple polygon (has to be on convex hull)
      51                 :            : /// \param[in] polygon_end End iterator for the simple polygon
      52                 :            : /// \param[in] convex_hull_start Start iterator for the convex hull of the simple polygon
      53                 :            : /// \param[in] convex_hull_end End iterator for the convex hull of the simple polygon
      54                 :            : /// \return A vector of vectors of the iterator value type. Each inner vector contains the points
      55                 :            : ///         for one pocket. We return by value instead of as iterator pairs, because it is possible
      56                 :            : ///         that the edge connecting the final point in the list and the first point in the list is
      57                 :            : ///         part of a pocket as well, and this is awkward to represent using iterators into the
      58                 :            : ///         original collection.
      59                 :            : ///
      60                 :            : /// \tparam Iter1 Iterator to a point type
      61                 :            : /// \tparam Iter2 Iterator to a point type (can be the same as Iter1, but does not need to be)
      62                 :            : template<typename Iter1, typename Iter2>
      63                 :          5 : typename std::vector<std::vector<typename std::iterator_traits<Iter1>::value_type>> hull_pockets(
      64                 :            :   const Iter1 polygon_start,
      65                 :            :   const Iter1 polygon_end,
      66                 :            :   const Iter2 convex_hull_start,
      67                 :            :   const Iter2 convex_hull_end
      68                 :            : )
      69                 :            : {
      70                 :          5 :   auto pockets = std::vector<std::vector<typename std::iterator_traits<Iter1>::value_type>>{};
      71   [ +  -  +  + ]:          5 :   if (std::distance(polygon_start, polygon_end) <= 3) {
      72                 :          1 :     return pockets;
      73                 :            :   }
      74                 :            : 
      75                 :            :   // Function to check whether a point is in the convex hull.
      76                 :         29 :   const auto in_convex_hull = [convex_hull_start, convex_hull_end](Iter1 p) {
      77                 :         25 :       return std::any_of(
      78                 :         90 :         convex_hull_start, convex_hull_end, [p](auto hull_entry)
      79                 :            :         {
      80                 :         90 :           return norm_2d(
      81                 :         90 :             minus_2d(
      82                 :            :               hull_entry,
      83                 :         90 :               *p)) < std::numeric_limits<float32_t>::epsilon();
      84                 :         25 :         });
      85                 :            :     };
      86                 :            : 
      87                 :            :   // We go through the points of the polygon only once, adding pockets to the list of pockets
      88                 :            :   // as we detect them.
      89                 :          8 :   std::vector<typename std::iterator_traits<Iter1>::value_type> current_pocket{};
      90   [ +  +  +  - ]:         29 :   for (auto it = polygon_start; it != polygon_end; it = std::next(it)) {
      91   [ +  -  +  + ]:         25 :     if (in_convex_hull(it)) {
      92         [ +  + ]:         20 :       if (current_pocket.size() > 1) {
      93         [ +  - ]:          3 :         current_pocket.emplace_back(*it);
      94         [ +  - ]:          3 :         pockets.push_back(current_pocket);
      95                 :            :       }
      96                 :         20 :       current_pocket.clear();
      97         [ +  - ]:         20 :       current_pocket.emplace_back(*it);
      98                 :            :     } else {
      99         [ +  - ]:          5 :       current_pocket.emplace_back(*it);
     100                 :            :     }
     101                 :            :   }
     102                 :            : 
     103                 :            :   // At this point, we have reached the end of the polygon, but have not considered the connection
     104                 :            :   // of the final point back to the first. In case the first point is part of a pocket as well, we
     105                 :            :   // have some points left in current_pocket, and we add one final pocket that is made up by those
     106                 :            :   // points plus the first point in the collection.
     107         [ +  + ]:          4 :   if (current_pocket.size() > 1) {
     108         [ +  - ]:          1 :     current_pocket.push_back(*polygon_start);
     109         [ +  - ]:          1 :     pockets.push_back(current_pocket);
     110                 :            :   }
     111                 :            : 
     112                 :          4 :   return pockets;
     113                 :            : }
     114                 :            : }  // namespace geometry
     115                 :            : }  // namespace common
     116                 :            : }  // namespace autoware
     117                 :            : 
     118                 :            : #endif  // GEOMETRY__HULL_POCKETS_HPP_

Generated by: LCOV version 1.14