bugfix in progress

This commit is contained in:
Rad
2026-04-19 17:50:18 +02:00
parent 6ae8ab3455
commit d370edb5b2
2 changed files with 150 additions and 4 deletions

View File

@@ -30,6 +30,14 @@ namespace Slic3r {
using namespace Slic3r::Feature::FuzzySkin;
static bool is_gap_fill_allowed_for_surface(const PrintObjectConfig* config, const SurfaceType surface_type)
{
if (config == nullptr || config->gap_fill_target.value == gftNowhere)
return false;
return surface_type != stInternalSolid || config->gap_fill_target.value == gftEverywhere;
}
static void append_collapsed_infill_gap_fill(const ExPolygons &areas,
const Flow &flow,
const double simplify_resolution,
@@ -1706,7 +1714,7 @@ void PerimeterGenerator::process_classic()
not_filled_exp,
float(-inset - min_perimeter_infill_spacing / 2.),
float(min_perimeter_infill_spacing / 2.));
if (infill_exp.empty() && has_gap_fill) {
if (infill_exp.empty() && has_gap_fill && is_gap_fill_allowed_for_surface(object_config, surface.surface_type)) {
ExPolygons gap_fill_source = not_filled_exp.empty() ? collapsed_gap_fill_source : not_filled_exp;
if (gap_fill_source.empty())
gap_fill_source = ExPolygons { surface.expolygon };
@@ -2581,7 +2589,8 @@ void PerimeterGenerator::process_arachne()
not_filled_exp,
float(-min_perimeter_infill_spacing / 2.),
float(inset + min_perimeter_infill_spacing / 2.));
if (infill_exp.empty() && this->config->gap_infill_speed.value > 0) {
if (infill_exp.empty() && this->config->gap_infill_speed.value > 0 &&
is_gap_fill_allowed_for_surface(object_config, surface.surface_type)) {
ExPolygons gap_fill_source = not_filled_exp.empty() ? collapsed_gap_fill_source : not_filled_exp;
if (gap_fill_source.empty())
gap_fill_source = ExPolygons { surface.expolygon };

View File

@@ -1,7 +1,119 @@
#include "VariableWidth.hpp"
#include "BoundingBox.hpp"
namespace Slic3r {
static Points closed_loop_points(const ThickPolyline& thick_polyline)
{
Points points = thick_polyline.points;
if (points.size() > 1 && points.front() == points.back())
points.pop_back();
return points;
}
static bool points_match_cyclic(const Points& lhs, const Points& rhs, const coord_t point_tolerance, const bool reversed)
{
if (lhs.size() != rhs.size() || lhs.empty())
return false;
const double tolerance_sq = double(point_tolerance) * double(point_tolerance);
for (size_t start = 0; start < rhs.size(); ++start) {
if ((lhs.front() - rhs[start]).cast<double>().squaredNorm() > tolerance_sq)
continue;
bool matches = true;
for (size_t i = 0; i < lhs.size(); ++i) {
const size_t rhs_idx = reversed ? (start + rhs.size() - i) % rhs.size() : (start + i) % rhs.size();
if ((lhs[i] - rhs[rhs_idx]).cast<double>().squaredNorm() > tolerance_sq) {
matches = false;
break;
}
}
if (matches)
return true;
}
return false;
}
static bool are_near_duplicate_closed_gap_fill_loops(const ThickPolyline& lhs, const ThickPolyline& rhs)
{
if (!lhs.is_closed() || !rhs.is_closed())
return false;
const Points lhs_points = closed_loop_points(lhs);
const Points rhs_points = closed_loop_points(rhs);
if (lhs_points.size() < 3 || lhs_points.size() != rhs_points.size())
return false;
const coord_t bbox_tolerance = scale_(0.05);
const coord_t point_tolerance = scale_(0.05);
const double length_tolerance = double(scale_(0.20));
const BoundingBox lhs_bbox(lhs_points);
const BoundingBox rhs_bbox(rhs_points);
if (!lhs_bbox.defined || !rhs_bbox.defined)
return false;
if (std::abs(lhs_bbox.min.x() - rhs_bbox.min.x()) > bbox_tolerance ||
std::abs(lhs_bbox.min.y() - rhs_bbox.min.y()) > bbox_tolerance ||
std::abs(lhs_bbox.max.x() - rhs_bbox.max.x()) > bbox_tolerance ||
std::abs(lhs_bbox.max.y() - rhs_bbox.max.y()) > bbox_tolerance)
return false;
if (std::abs(length(lhs_points) - length(rhs_points)) > length_tolerance)
return false;
const double area_tolerance = double(scale_(0.05)) * std::max(length(lhs_points), length(rhs_points));
if (std::abs(std::abs(area(lhs_points)) - std::abs(area(rhs_points))) > area_tolerance)
return false;
return points_match_cyclic(lhs_points, rhs_points, point_tolerance, false) ||
points_match_cyclic(lhs_points, rhs_points, point_tolerance, true);
}
static ExtrusionPaths closed_gap_fill_loop_to_extrusion_paths(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow)
{
ExtrusionPaths paths;
if (!thick_polyline.is_closed())
return paths;
ThickLines lines = thick_polyline.thicklines();
if (lines.empty())
return paths;
double total_length = 0.0;
double weighted_width_sum = 0.0;
for (const ThickLine& line : lines) {
const coordf_t line_len = line.length();
if (line_len < SCALED_EPSILON)
continue;
total_length += line_len;
weighted_width_sum += line_len * 0.5 * (line.a_width + line.b_width);
}
if (total_length <= SCALED_EPSILON)
return paths;
ExtrusionPath path(role);
path.polyline.points = thick_polyline.points;
if (!path.polyline.is_valid())
return paths;
const double average_width = weighted_width_sum / total_length;
const Flow new_flow = (role == erOverhangPerimeter && flow.bridge()) ?
flow :
flow.with_width(unscale<float>(average_width) + flow.height() * float(1. - 0.25 * PI));
path.mm3_per_mm = new_flow.mm3_per_mm();
path.width = new_flow.width();
path.height = new_flow.height();
paths.emplace_back(std::move(path));
return paths;
}
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline& thick_polyline, ExtrusionRole role, const Flow& flow, const float tolerance, const float merge_tolerance)
{
ExtrusionMultiPath multi_path;
@@ -219,8 +331,33 @@ void variable_width(const ThickPolylines& polylines, ExtrusionRole role, const F
// variable extrusion within a single move; this value shall only affect the amount
// of segments, and any pruning shall be performed before we apply this tolerance.
const float tolerance = float(scale_(0.05));
for (const ThickPolyline& p : polylines) {
ExtrusionPaths paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
const ThickPolylines* source_polylines = &polylines;
ThickPolylines deduplicated_gap_fill_loops;
if (role == erGapFill && polylines.size() > 1) {
deduplicated_gap_fill_loops.reserve(polylines.size());
for (const ThickPolyline& polyline : polylines) {
bool is_duplicate = false;
for (const ThickPolyline& kept : deduplicated_gap_fill_loops) {
if (are_near_duplicate_closed_gap_fill_loops(polyline, kept)) {
is_duplicate = true;
break;
}
}
if (!is_duplicate)
deduplicated_gap_fill_loops.emplace_back(polyline);
}
source_polylines = &deduplicated_gap_fill_loops;
}
for (const ThickPolyline& p : *source_polylines) {
ExtrusionPaths paths;
if (role == erGapFill && p.is_closed())
paths = closed_gap_fill_loop_to_extrusion_paths(p, role, flow);
if (paths.empty())
paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
// Append paths to collection.
if (!paths.empty()) {
if (paths.front().first_point() == paths.back().last_point())