Merge branch 'main' into Variable_Layer_Height_Tree_Support

This commit is contained in:
fewTheRememberless 2026-02-20 13:51:22 +01:00 committed by GitHub
commit ca24be9ef8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 81 additions and 25 deletions

View file

@ -111,7 +111,7 @@ void fuzzy_polyline(Points& poly, bool closed, coordf_t slice_z, const FuzzySkin
}
// Thanks Cura developers for this function.
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, const FuzzySkinConfig& cfg)
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, const FuzzySkinConfig& cfg, bool closed)
{
std::unique_ptr<noise::module::Module> noise = get_noise_module(cfg);
@ -124,9 +124,12 @@ void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice
Arachne::ExtrusionJunctions out;
out.reserve(ext_lines.size());
for (auto& p1 : ext_lines) {
if (p0->p == p1.p) { // Connect endpoints.
out.emplace_back(p1.p, p1.w, p1.perimeter_index);
continue;
// Orca: only skip the first point for closed path, open path should not skip any point
if (closed) {
if (p0->p == p1.p) { // Connect endpoints.
out.emplace_back(p1.p, p1.w, p1.perimeter_index);
continue;
}
}
// 'a' is the (next) new point between p0 and p1
@ -266,11 +269,11 @@ Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perim
BoundingBox bbox = get_extents(perimeter_generator.slices->surfaces);
bbox.offset(scale_(1.));
::Slic3r::SVG svg(debug_out_path("fuzzy_traverse_loops_%d_%d_%d_region_%d.svg", perimeter_generator.layer_id,
loop.is_contour ? 0 : 1, loop.depth, i)
is_contour ? 0 : 1, loop_idx, i)
.c_str(),
bbox);
svg.draw_outline(perimeter_generator.slices->surfaces);
svg.draw_outline(loop.polygon, "green");
svg.draw_outline(polygon, "green");
svg.draw(r.second, "red", 0.5);
svg.draw_outline(r.second, "red");
svg.Close();
@ -348,6 +351,35 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
}
}
if (!fuzzified_regions.empty()) {
#ifdef DEBUG_FUZZY
{
int i = 0;
for (const auto& r : fuzzified_regions) {
BoundingBox bbox = get_extents(perimeter_generator.slices->surfaces);
bbox.offset(scale_(1.));
::Slic3r::SVG svg(debug_out_path("fuzzy_traverse_loops_%d_%d_%d_region_%d.svg", perimeter_generator.layer_id,
is_contour ? 0 : 1, extrusion->inset_idx, i)
.c_str(),
bbox);
// Convert extrusion line to polygon for visualization
Polygon extrusion_polygon;
extrusion_polygon.points.reserve(extrusion->junctions.size());
for (const auto& junction : extrusion->junctions) {
extrusion_polygon.points.push_back(junction.p);
}
svg.draw_outline(perimeter_generator.slices->surfaces);
svg.draw_outline(extrusion_polygon, "green");
svg.draw(r.second, "red", 0.5);
svg.draw_outline(r.second, "red");
svg.Close();
i++;
}
}
#endif
// Split the loops into lines with different config, and fuzzy them separately
for (const auto& r : fuzzified_regions) {
const auto splitted = Algorithm::split_line(*extrusion, r.second, false);
@ -360,6 +392,7 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
if (std::all_of(splitted.begin(), splitted.end(), [](const Algorithm::SplitLineJunction& j) { return j.clipped; })) {
// The entire polygon is fuzzified
fuzzy_extrusion_line(extrusion->junctions, slice_z, r.first);
continue;
} else {
const auto current_ext = extrusion->junctions;
std::vector<Arachne::ExtrusionJunction> segment;
@ -367,11 +400,20 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
extrusion->junctions.clear();
const auto fuzzy_current_segment = [&segment, &extrusion, &r, slice_z]() {
extrusion->junctions.push_back(segment.front());
const auto back = segment.back();
fuzzy_extrusion_line(segment, slice_z, r.first);
// Orca: non fuzzy points to isolate fuzzy region
const auto front = segment.front();
const auto back = segment.back();
fuzzy_extrusion_line(segment, slice_z, r.first, false);
// Orca: only add non fuzzy point if it's not in the extrusion closing point.
if (extrusion->junctions.front().p != front.p) {
extrusion->junctions.push_back(front);
}
extrusion->junctions.insert(extrusion->junctions.end(), segment.begin(), segment.end());
extrusion->junctions.push_back(back);
// Orca: only add non fuzzy point if it's not in the extrusion closing point.
if (extrusion->junctions.back().p != front.p) {
extrusion->junctions.push_back(back);
}
segment.clear();
};
@ -398,6 +440,12 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
if (!segment.empty()) {
fuzzy_current_segment();
}
//Orca: ensure the loop is closed after fuzzy
if (extrusion->junctions.front().p != extrusion->junctions.back().p) {
extrusion->junctions.back().p = extrusion->junctions.front().p;
extrusion->junctions.back().w = extrusion->junctions.front().w;
}
}
}
}

View file

@ -9,7 +9,7 @@ namespace Slic3r::Feature::FuzzySkin {
void fuzzy_polyline(Points& poly, bool closed, coordf_t slice_z, const FuzzySkinConfig& cfg);
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, const FuzzySkinConfig& cfg);
void fuzzy_extrusion_line(Arachne::ExtrusionJunctions& ext_lines, coordf_t slice_z, const FuzzySkinConfig& cfg, bool closed = true);
void group_region_by_fuzzify(PerimeterGenerator& g);

View file

@ -1661,7 +1661,8 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres
//m_tree->model->AddPreset(type, from_u8(presets->get_edited_preset().name), old_pt);
// Collect dirty options.
const bool deep_compare = (type == Preset::TYPE_PRINTER || type == Preset::TYPE_SLA_MATERIAL);
const bool deep_compare = (type == Preset::TYPE_PRINTER ||
type == Preset::TYPE_FILAMENT || type == Preset::TYPE_SLA_MATERIAL);
auto dirty_options = presets->current_dirty_options(deep_compare);
// process changes of extruders count
@ -1682,11 +1683,15 @@ void UnsavedChangesDialog::update_tree(Preset::Type type, PresetCollection* pres
}
for (const std::string& opt_key : dirty_options) {
const Search::Option& option = searcher.get_option(opt_key, type);
if (option.opt_key() != opt_key) {
// When founded option isn't the correct one.
// It can be for dirty_options: "default_print_profile", "printer_model", "printer_settings_id",
// because of they don't exist in searcher
const std::string lookup_key = get_pure_opt_key(opt_key);
Search::Option option = searcher.get_option(lookup_key, type);
if (get_pure_opt_key(option.opt_key()) != lookup_key)
option = searcher.get_option(opt_key, get_full_label(opt_key, new_config), type);
if (get_pure_opt_key(option.opt_key()) != lookup_key) {
// When the found option is not the requested one.
// This can happen for dirty_options such as:
// "default_print_profile", "printer_model", "printer_settings_id",
// because they do not exist in the searcher.
continue;
}
@ -2190,7 +2195,8 @@ void DiffPresetDialog::update_tree()
}
// Collect dirty options.
const bool deep_compare = (type == Preset::TYPE_PRINTER || type == Preset::TYPE_SLA_MATERIAL);
const bool deep_compare = (type == Preset::TYPE_PRINTER ||
type == Preset::TYPE_FILAMENT || type == Preset::TYPE_SLA_MATERIAL);
auto dirty_options = type == Preset::TYPE_PRINTER && left_pt == ptFFF &&
left_config.opt<ConfigOptionStrings>("extruder_colour")->values.size() < right_congig.opt<ConfigOptionStrings>("extruder_colour")->values.size() ?
presets->dirty_options(right_preset, left_preset, deep_compare) :
@ -2229,13 +2235,15 @@ void DiffPresetDialog::update_tree()
wxString left_val = get_string_value(opt_key, left_config);
wxString right_val = get_string_value(opt_key, right_congig);
Search::Option option = searcher.get_option(opt_key, get_full_label(opt_key, left_config), type);
if (option.opt_key() != opt_key) {
// temporary solution, just for testing
m_tree->Append(opt_key, type, "Undef category", "Undef group", opt_key, left_val, right_val, "undefined"); // ORCA: use low resolution compatible icon
// When founded option isn't the correct one.
// It can be for dirty_options: "default_print_profile", "printer_model", "printer_settings_id",
// because of they don't exist in searcher
const std::string lookup_key = get_pure_opt_key(opt_key);
Search::Option option = searcher.get_option(lookup_key, type);
if (get_pure_opt_key(option.opt_key()) != lookup_key)
option = searcher.get_option(opt_key, get_full_label(opt_key, left_config), type);
if (get_pure_opt_key(option.opt_key()) != lookup_key) {
// When the found option is not the requested one.
// This can happen for dirty_options such as:
// "default_print_profile", "printer_model", "printer_settings_id",
// because they do not exist in the searcher.
continue;
}
m_tree->Append(opt_key, type, option.category_local, option.group_local, option.label_local,