11 #include <Eigen/Geometry>
19 points(points), params(params)
22 indices.resize(points.size());
23 std::iota(indices.begin(), indices.end(), 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); });
112 ChainApproximation::computeDistance(
const ChainApproximation::Triplet& triplet)
const
114 using Line = Eigen::ParametrizedLine<float, 2>;
116 const Eigen::Vector2f& ptBefore = points.at(triplet.a);
117 const Eigen::Vector2f& ptPivot = points.at(triplet.b);
118 const Eigen::Vector2f& ptAfter = points.at(triplet.c);
120 const auto line = Line::Through(ptBefore, ptAfter);
121 return line.distance(ptPivot);
125 ChainApproximation::approximateStep()
127 const size_t nIndices = indices.size();
133 const Triplets triplets = getTriplets();
134 const std::vector<float> distances = computeDistances(triplets);
137 const int n =
static_cast<int>(triplets.size());
139 std::vector<int> indicesToBeRemoved;
142 for (
int i = 1; i < n - 1; i++)
144 const auto&
distance = distances.at(i);
155 indicesToBeRemoved.emplace_back(triplets.at(i).b);
160 if (indicesToBeRemoved.empty())
165 const auto isMatch = [&](
const int& idx) ->
bool
167 return std::find(indicesToBeRemoved.begin(), indicesToBeRemoved.end(), idx) !=
168 indicesToBeRemoved.end();
171 indices.erase(std::remove_if(indices.begin(), indices.end(), isMatch), indices.end());
180 extractedPoints.reserve(indices.size());
184 std::back_inserter(extractedPoints),
185 [&](
const auto& idx) { return points.at(idx); });
187 return extractedPoints;
195 const std::string condStr = [&res]() -> std::string
201 case TerminationCondition::Converged:
204 case TerminationCondition::IterationLimit:
205 repr =
"IterationLimit";
211 str <<
"ApproximationResult: ["
212 <<
"condition: " << condStr <<
" | "