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,61 +329,47 @@ void removeSmallAreas(Polygons &thiss, const double min_area_size, const bool re
|
|||||||
};
|
};
|
||||||
|
|
||||||
auto new_end = thiss.end();
|
auto new_end = thiss.end();
|
||||||
if(remove_holes)
|
if (remove_holes) {
|
||||||
{
|
for (auto it = thiss.begin(); it < new_end;) {
|
||||||
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) {
|
||||||
// All polygons smaller than target are removed by replacing them with a polygon from the back of the vector
|
--new_end;
|
||||||
if(fabs(ClipperLib::Area(to_path(*it))) < min_area_size)
|
|
||||||
{
|
|
||||||
new_end--;
|
|
||||||
*it = std::move(*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
|
// 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;
|
std::vector<Polygon> small_holes;
|
||||||
for(auto it = thiss.begin(); it < new_end; it++) {
|
for (auto it = thiss.begin(); it < new_end;) {
|
||||||
double area = ClipperLib::Area(to_path(*it));
|
if (double area = ClipperLib::Area(to_path(*it)); fabs(area) < min_area_size) {
|
||||||
if (fabs(area) < min_area_size)
|
if (area >= 0) {
|
||||||
{
|
--new_end;
|
||||||
if(area >= 0)
|
if (it < new_end) {
|
||||||
{
|
|
||||||
new_end--;
|
|
||||||
if(it < new_end) {
|
|
||||||
std::swap(*new_end, *it);
|
std::swap(*new_end, *it);
|
||||||
it--;
|
continue;
|
||||||
}
|
} else { // Don't self-swap the last Path
|
||||||
else
|
|
||||||
{ // Don't self-swap the last Path
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
small_holes.push_back(*it);
|
small_holes.push_back(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes small holes that have their first point inside one of the removed outlines
|
// 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
|
// Iterating in reverse ensures that unprocessed small holes won't be moved
|
||||||
const auto removed_outlines_start = new_end;
|
const auto removed_outlines_start = new_end;
|
||||||
for(auto hole_it = small_holes.rbegin(); hole_it < small_holes.rend(); hole_it++)
|
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++)
|
||||||
for(auto outline_it = removed_outlines_start; outline_it < thiss.end() ; outline_it++)
|
if (Polygon(*outline_it).contains(*hole_it->begin())) {
|
||||||
{
|
|
||||||
if(Polygon(*outline_it).contains(*hole_it->begin())) {
|
|
||||||
new_end--;
|
new_end--;
|
||||||
*hole_it = std::move(*new_end);
|
*hole_it = std::move(*new_end);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
thiss.resize(new_end-thiss.begin());
|
thiss.resize(new_end-thiss.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,3 +389,38 @@ TEST_CASE("Arachne - #8633 - Shorter open perimeter", "[ArachneShorterOpenPerime
|
|||||||
#endif
|
#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