Fix of #8597 - Assert on Windows about decrementing of std::vector::begin() in a specific case.
This commit is contained in:
parent
e838acdcd1
commit
f60b88ba3e
@ -329,60 +329,46 @@ void removeSmallAreas(Polygons &thiss, const double min_area_size, const bool re
|
||||
};
|
||||
|
||||
auto new_end = thiss.end();
|
||||
if(remove_holes)
|
||||
{
|
||||
for(auto it = thiss.begin(); it < new_end; it++)
|
||||
{
|
||||
// All polygons smaller than target are removed by replacing them with a polygon from the back of the vector
|
||||
if(fabs(ClipperLib::Area(to_path(*it))) < min_area_size)
|
||||
{
|
||||
new_end--;
|
||||
if (remove_holes) {
|
||||
for (auto it = thiss.begin(); it < new_end;) {
|
||||
// All polygons smaller than target are removed by replacing them with a polygon from the back of the vector.
|
||||
if (fabs(ClipperLib::Area(to_path(*it))) < min_area_size) {
|
||||
--new_end;
|
||||
*it = std::move(*new_end);
|
||||
it--; // wind back the iterator such that the polygon just swaped in is checked next
|
||||
continue; // Don't increment the iterator such that the polygon just swapped in is checked next.
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// For each polygon, computes the signed area, move small outlines at the end of the vector and keep pointer on small holes
|
||||
std::vector<Polygon> small_holes;
|
||||
for(auto it = thiss.begin(); it < new_end; it++) {
|
||||
double area = ClipperLib::Area(to_path(*it));
|
||||
if (fabs(area) < min_area_size)
|
||||
{
|
||||
if(area >= 0)
|
||||
{
|
||||
new_end--;
|
||||
if(it < new_end) {
|
||||
for (auto it = thiss.begin(); it < new_end;) {
|
||||
if (double area = ClipperLib::Area(to_path(*it)); fabs(area) < min_area_size) {
|
||||
if (area >= 0) {
|
||||
--new_end;
|
||||
if (it < new_end) {
|
||||
std::swap(*new_end, *it);
|
||||
it--;
|
||||
}
|
||||
else
|
||||
{ // Don't self-swap the last Path
|
||||
continue;
|
||||
} else { // Don't self-swap the last Path
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
small_holes.push_back(*it);
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
// Removes small holes that have their first point inside one of the removed outlines
|
||||
// Iterating in reverse ensures that unprocessed small holes won't be moved
|
||||
const auto removed_outlines_start = new_end;
|
||||
for(auto hole_it = small_holes.rbegin(); hole_it < small_holes.rend(); hole_it++)
|
||||
{
|
||||
for(auto outline_it = removed_outlines_start; outline_it < thiss.end() ; outline_it++)
|
||||
{
|
||||
if(Polygon(*outline_it).contains(*hole_it->begin())) {
|
||||
for (auto hole_it = small_holes.rbegin(); hole_it < small_holes.rend(); hole_it++)
|
||||
for (auto outline_it = removed_outlines_start; outline_it < thiss.end(); outline_it++)
|
||||
if (Polygon(*outline_it).contains(*hole_it->begin())) {
|
||||
new_end--;
|
||||
*hole_it = std::move(*new_end);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
thiss.resize(new_end-thiss.begin());
|
||||
}
|
||||
|
@ -389,3 +389,38 @@ TEST_CASE("Arachne - #8633 - Shorter open perimeter", "[ArachneShorterOpenPerime
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// This test case was distilled from GitHub issue #8597.
|
||||
// There was just an issue with decrementing std::vector::begin() in a specific case.
|
||||
TEST_CASE("Arachne - #8597 - removeSmallAreas", "[ArachneRemoveSmallAreas8597]") {
|
||||
const Polygon poly_0 = {
|
||||
Point(-38768167, -3636556),
|
||||
Point(-38763631, -3617883),
|
||||
Point(-38763925, -3617820),
|
||||
Point(-38990169, -3919539),
|
||||
Point(-38928506, -3919539),
|
||||
};
|
||||
|
||||
const Polygon poly_1 = {
|
||||
Point(-39521732, -4480560),
|
||||
Point(-39383333, -4398498),
|
||||
Point(-39119825, -3925307),
|
||||
Point(-39165608, -3926212),
|
||||
Point(-39302205, -3959445),
|
||||
Point(-39578719, -4537002),
|
||||
};
|
||||
|
||||
Polygons polygons = {poly_0, poly_1};
|
||||
coord_t spacing = 407079;
|
||||
coord_t inset_count = 2;
|
||||
|
||||
Arachne::WallToolPaths wallToolPaths(polygons, spacing, spacing, inset_count, 0, 0.2, PrintObjectConfig::defaults(), PrintConfig::defaults());
|
||||
wallToolPaths.generate();
|
||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||
|
||||
#ifdef ARACHNE_DEBUG_OUT
|
||||
export_perimeters_to_svg(debug_out_path("arachne-remove-small-areas-8597.svg"), polygons, perimeters, union_ex(wallToolPaths.getInnerContour()));
|
||||
#endif
|
||||
|
||||
REQUIRE(perimeters.size() == 1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user