Patching the new Layer::sort_perimeters_into_islands() for super
ugly models. Fixes #9561, #9562
This commit is contained in:
parent
991aedd37c
commit
340b685a0d
@ -31,6 +31,9 @@ public:
|
||||
virtual void reverse() = 0;
|
||||
virtual const Point& first_point() const = 0;
|
||||
virtual const Point& last_point() const = 0;
|
||||
// Returns an approximately middle point of a path, loop or an extrusion collection.
|
||||
// Used to get a sample point of an extrusion or extrusion collection, which is possibly deep inside its island.
|
||||
virtual const Point& middle_point() const = 0;
|
||||
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
|
||||
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
||||
virtual void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const = 0;
|
||||
@ -81,6 +84,7 @@ public:
|
||||
void reverse() override { this->polyline.reverse(); }
|
||||
const Point& first_point() const override { return this->polyline.points.front(); }
|
||||
const Point& last_point() const override { return this->polyline.points.back(); }
|
||||
const Point& middle_point() const override { return this->polyline.points[this->polyline.size() / 2]; }
|
||||
size_t size() const { return this->polyline.size(); }
|
||||
bool empty() const { return this->polyline.empty(); }
|
||||
bool is_closed() const { return ! this->empty() && this->polyline.points.front() == this->polyline.points.back(); }
|
||||
@ -153,6 +157,7 @@ public:
|
||||
void reverse() override;
|
||||
const Point& first_point() const override { return this->paths.front().polyline.points.front(); }
|
||||
const Point& last_point() const override { return this->paths.back().polyline.points.back(); }
|
||||
const Point& middle_point() const override { auto &path = this->paths[this->paths.size() / 2]; return path.polyline.points[path.polyline.size() / 2]; }
|
||||
size_t size() const { return this->paths.size(); }
|
||||
bool empty() const { return this->paths.empty(); }
|
||||
double length() const override;
|
||||
@ -204,6 +209,7 @@ public:
|
||||
void reverse() override;
|
||||
const Point& first_point() const override { return this->paths.front().polyline.points.front(); }
|
||||
const Point& last_point() const override { assert(this->first_point() == this->paths.back().polyline.points.back()); return this->first_point(); }
|
||||
const Point& middle_point() const override { auto& path = this->paths[this->paths.size() / 2]; return path.polyline.points[path.polyline.size() / 2]; }
|
||||
Polygon polygon() const;
|
||||
double length() const override;
|
||||
bool split_at_vertex(const Point &point, const double scaled_epsilon = scaled<double>(0.001));
|
||||
|
@ -102,6 +102,7 @@ public:
|
||||
void reverse() override;
|
||||
const Point& first_point() const override { return this->entities.front()->first_point(); }
|
||||
const Point& last_point() const override { return this->entities.back()->last_point(); }
|
||||
const Point& middle_point() const override { return this->entities[this->entities.size() / 2]->middle_point(); }
|
||||
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
|
||||
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
||||
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
|
||||
|
@ -578,7 +578,7 @@ void Layer::sort_perimeters_into_islands(
|
||||
// Take a sample deep inside its island if available. Infills are usually quite far from the island boundary.
|
||||
for (uint32_t iexpoly : fill_expolygons_ranges[islice])
|
||||
if (const ExPolygon &expoly = fill_expolygons[iexpoly]; ! expoly.empty()) {
|
||||
sample = expoly.contour.points.front();
|
||||
sample = expoly.contour.points[expoly.contour.points.size() / 2];
|
||||
sample_set = true;
|
||||
break;
|
||||
}
|
||||
@ -589,12 +589,12 @@ void Layer::sort_perimeters_into_islands(
|
||||
if (ee.is_collection()) {
|
||||
for (const ExtrusionEntity *ee2 : dynamic_cast<const ExtrusionEntityCollection&>(ee).entities)
|
||||
if (! ee2->role().is_external()) {
|
||||
sample = ee2->first_point();
|
||||
sample = ee2->middle_point();
|
||||
sample_set = true;
|
||||
goto loop_end;
|
||||
}
|
||||
} else if (! ee.role().is_external()) {
|
||||
sample = ee.first_point();
|
||||
sample = ee.middle_point();
|
||||
sample_set = true;
|
||||
break;
|
||||
}
|
||||
@ -603,12 +603,12 @@ void Layer::sort_perimeters_into_islands(
|
||||
if (! sample_set) {
|
||||
if (! extrusions.second.empty()) {
|
||||
// If there is no inner perimeter, take a sample of some gap fill extrusion.
|
||||
sample = this_layer_region.thin_fills().entities[*extrusions.second.begin()]->first_point();
|
||||
sample = this_layer_region.thin_fills().entities[*extrusions.second.begin()]->middle_point();
|
||||
sample_set = true;
|
||||
}
|
||||
if (! sample_set && ! extrusions.first.empty()) {
|
||||
// As a last resort, take a sample of some external perimeter.
|
||||
sample = this_layer_region.perimeters().entities[*extrusions.first.begin()]->first_point();
|
||||
sample = this_layer_region.perimeters().entities[*extrusions.first.begin()]->middle_point();
|
||||
sample_set = true;
|
||||
}
|
||||
}
|
||||
@ -835,6 +835,15 @@ void Layer::sort_perimeters_into_islands(
|
||||
d2min = d2;
|
||||
lslice_idx_min = lslice_idx;
|
||||
}
|
||||
if (lslice_idx_min == -1) {
|
||||
// This should not happen, but Arachne seems to produce a perimeter point far outside its source contour.
|
||||
// As a last resort, find the closest source contours to the sample point.
|
||||
for (int lslice_idx = int(lslices_ex.size()) - 1; lslice_idx >= 0; -- lslice_idx)
|
||||
if (double d2 = (lslices[lslice_idx].point_projection(it_source_slice->second) - it_source_slice->second).cast<double>().squaredNorm(); d2 < d2min) {
|
||||
d2min = d2;
|
||||
lslice_idx_min = lslice_idx;
|
||||
}
|
||||
}
|
||||
assert(lslice_idx_min != -1);
|
||||
insert_into_island(lslice_idx_min, it_source_slice->first);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user