Fixing Polyline::split_at() to handle correctly splitting

at the first / last point.
This commit is contained in:
Vojtech Bubnik 2022-06-24 17:28:09 +02:00
parent 0c99a14b63
commit d01f6099c3

View File

@ -132,37 +132,33 @@ template void Polyline::simplify_by_visibility<ExPolygonCollection>(const ExPoly
void Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const void Polyline::split_at(const Point &point, Polyline* p1, Polyline* p2) const
{ {
if (this->points.empty()) return; if (this->size() < 2 || this->points.front() == point) {
*p1 = *this;
p2->clear();
return;
}
// find the line to split at auto min_dist2 = std::numeric_limits<double>::max();
size_t line_idx = 0; auto min_point_it = this->points.cbegin();
Point p = this->first_point(); Point prev = this->points.front();
double min = (p - point).cast<double>().norm(); for (auto it = this->points.cbegin() + 1; it != this->points.cend(); ++ it) {
Lines lines = this->lines(); Point proj = point.projection_onto(Line(prev, *it));
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line) { auto d2 = (proj - point).cast<double>().squaredNorm();
Point p_tmp = point.projection_onto(*line); if (d2 < min_dist2) {
if ((p_tmp - point).cast<double>().norm() < min) { min_dist2 = d2;
p = p_tmp; min_point_it = it;
min = (p - point).cast<double>().norm();
line_idx = line - lines.begin();
} }
prev = *it;
} }
// create first half p1->points.assign(this->points.cbegin(), min_point_it);
p1->points.clear(); if (p1->points.back() != point)
for (Lines::const_iterator line = lines.begin(); line != lines.begin() + line_idx + 1; ++line) p1->points.emplace_back(point);
if (line->a != p)
p1->points.push_back(line->a);
// we add point instead of p because they might differ because of numerical issues
// and caller might want to rely on point belonging to result polylines
p1->points.push_back(point);
// create second half p2->points = { point };
p2->points.clear(); if (*min_point_it == point)
p2->points.push_back(point); ++ min_point_it;
for (Lines::const_iterator line = lines.begin() + line_idx; line != lines.end(); ++line) { p2->points.insert(p2->points.end(), min_point_it, this->points.cend());
p2->points.push_back(line->b);
}
} }
bool Polyline::is_straight() const bool Polyline::is_straight() const