6 #include <Eigen/Geometry>
7 #include <SimoxUtility/algorithm/apply.hpp>
12 #include "range/v3/algorithm/find.hpp"
13 #include "range/v3/numeric/iota.hpp"
19 points(points), params(params)
22 indices.resize(points.size());
23 ranges::iota(indices, 0);
32 const auto maxIterConditionReached = [&]()
45 if (maxIterConditionReached())
49 .iterations = iterations};
52 if (not approximateStep())
56 .iterations = iterations,
57 .reductionFactor = 1.F -
static_cast<float>(indices.size()) /
58 static_cast<float>(points.size())};
65 ChainApproximation::Triplets
66 ChainApproximation::getTriplets()
const
68 const int nIndices =
static_cast<int>(indices.size());
76 triplets.reserve(indices.size());
83 triplets.emplace_back(indices.back(), indices.front(), indices.at(1));
86 for (
int i = 1; i < (nIndices - 1); i++)
88 triplets.emplace_back(indices.at(i - 1), indices.at(i), indices.at(i + 1));
92 triplets.emplace_back(indices.back(), indices.front(), indices.at(1));
98 ChainApproximation::computeDistances(
const ChainApproximation::Triplets& triplets)
100 std::vector<float> distances;
101 distances.reserve(triplets.size());
105 std::back_inserter(distances),
106 [&](
const auto& triplet) { return computeDistance(triplet); });
111 ChainApproximation::computeDistance(
const ChainApproximation::Triplet& triplet)
const
113 using Line = Eigen::ParametrizedLine<float, 2>;
115 const Eigen::Vector2f& ptBefore = points.at(triplet.a);
116 const Eigen::Vector2f& ptPivot = points.at(triplet.b);
117 const Eigen::Vector2f& ptAfter = points.at(triplet.c);
119 const auto line = Line::Through(ptBefore, ptAfter);
120 return line.distance(ptPivot);
124 ChainApproximation::approximateStep()
126 const size_t nIndices = indices.size();
132 const Triplets triplets = getTriplets();
133 const std::vector<float> distances = computeDistances(triplets);
136 const int n =
static_cast<int>(triplets.size());
138 std::vector<int> indicesToBeRemoved;
141 for (
int i = 1; i < n - 1; i++)
143 const auto&
distance = distances.at(i);
154 indicesToBeRemoved.emplace_back(triplets.at(i).b);
159 if (indicesToBeRemoved.empty())
164 const auto isMatch = [&](
const int& idx) ->
bool
165 {
return ranges::find(indicesToBeRemoved, idx) != indicesToBeRemoved.end(); };
167 indices.erase(std::remove_if(indices.begin(), indices.end(), isMatch), indices.end());
174 return simox::alg::apply(indices, [&](
const auto& idx) {
return points.at(idx); });
182 const std::string condStr = [&res]() -> std::string
188 case TerminationCondition::Converged:
191 case TerminationCondition::IterationLimit:
192 repr =
"IterationLimit";
198 str <<
"ApproximationResult: ["
199 <<
"condition: " << condStr <<
" | "