8#include <range/v3/view/enumerate.hpp>
9#include <range/v3/view/sliding.hpp>
25 inputFeatures(
std::move(features)), chainApproximationParams(chainApproximationParams)
31 inputFeatures(features), chainApproximationParams(chainApproximationParams)
38 ARMARX_DEBUG <<
"Starting merge of " << inputFeatures.size() <<
" features";
41 for (
const auto [i, f] : ranges::views::enumerate(inputFeatures))
43 std::optional<std::size_t> lastFeature = std::nullopt;
44 for (
const auto& p : f.points)
46 if (
auto res = checkPoint(p, i, lastFeature); res)
48 uf.unite(i, res.value());
49 lastFeature = res.value();
54 for (
const auto [i, f] : ranges::views::enumerate(inputFeatures))
56 std::size_t representative = uf.find(i);
57 if (i != representative)
59 ARMARX_DEBUG <<
"add feature " << i <<
" to feature " << representative;
60 addToFeature(inputFeatures[representative], f);
64 std::vector<Features> merged;
65 for (
const auto [i, f] : ranges::views::enumerate(inputFeatures))
74 recalculateFeatures(merged);
76 ARMARX_DEBUG <<
"Merged " << inputFeatures.size() <<
" features into " << merged.size();
82 const std::vector<Eigen::Vector2f>& vertices)
87 const auto signum = [](
float x)
91 return x > 0 ? 1 : -1;
94 const auto checkSide = [&](
const Eigen::Vector2f& a,
const Eigen::Vector2f& b)
95 {
return signum((p.x() - a.x()) * (b.y() - a.y()) - (p.y() - a.y()) * (b.x() - a.x())); };
97 float previousSide = 0;
98 for (
const auto edge : vertices | ranges::views::sliding(2))
100 int d = checkSide(edge[0], edge[1]);
104 if (previousSide != 0 && d != previousSide)
110 int d = checkSide(vertices.back(), vertices.front());
113 return d == previousSide;
116 std::optional<std::size_t>
117 FeatureMerger::checkPoint(
const Eigen::Vector2f p,
119 const std::optional<std::size_t> checkFirst)
128 const auto convexHullOpt = inputFeatures[checkFirst.value()].convexHull;
130 if (convexHullOpt.has_value() and
insideConvexPoly(p, convexHullOpt->vertices))
132 return checkFirst.value();
136 for (
const auto [i, f] : ranges::views::enumerate(inputFeatures))
139 if (i == ignore || (checkFirst && i == checkFirst.value()))
144 const auto convexHullOpt = f.convexHull;
146 if (convexHullOpt.has_value() and
insideConvexPoly(p, convexHullOpt->vertices))
157 f.points.insert(f.points.end(), toAdd.points.begin(), toAdd.points.end());
159 f.convexHull = std::nullopt;
160 f.circle = std::nullopt;
161 f.ellipsoid = std::nullopt;
162 f.chain = std::nullopt;
166 FeatureMerger::recalculateFeatures(std::vector<Features>& features)
169 for (
auto& f : features)
189 f.points, f.convexHull, chainApproximationParams);
detail::ChainApproximationParams Params
#define ARMARX_CHECK_LESS(lhs, rhs)
This macro evaluates whether lhs is less (<) than rhs and if it turns out to be false it will throw a...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
This file offers overloads of toIce() and fromIce() functions for STL container types.