mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-14 00:52:04 +00:00
FuzzySkin hole + Fix: Painted artifacts and with Sacrificial layer issues (#12479)
This commit is contained in:
@@ -13121,6 +13121,9 @@ msgstr ""
|
||||
msgid "Contour"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hole"
|
||||
msgstr ""
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -15232,6 +15232,9 @@ msgstr "Només pintat"
|
||||
msgid "Contour"
|
||||
msgstr "Contorn"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Forat"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Contorn i forat"
|
||||
|
||||
|
||||
@@ -14821,6 +14821,9 @@ msgstr "Painted only"
|
||||
msgid "Contour"
|
||||
msgstr "Obrys"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Otvor"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Obrys a otvor"
|
||||
|
||||
|
||||
@@ -15357,6 +15357,9 @@ msgstr "Nur lackiert"
|
||||
msgid "Contour"
|
||||
msgstr "Kontur"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Loch"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Kontur und Loch"
|
||||
|
||||
|
||||
@@ -13403,6 +13403,9 @@ msgstr ""
|
||||
msgid "Contour"
|
||||
msgstr ""
|
||||
|
||||
msgid "Hole"
|
||||
msgstr ""
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -15294,6 +15294,9 @@ msgstr "Solo pintado"
|
||||
msgid "Contour"
|
||||
msgstr "Contorno"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Orificio"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Contorno y orificio"
|
||||
|
||||
|
||||
@@ -15433,6 +15433,9 @@ msgstr "Peint uniquement"
|
||||
msgid "Contour"
|
||||
msgstr "Contour"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Trou"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Contour et trou"
|
||||
|
||||
|
||||
@@ -15122,6 +15122,9 @@ msgstr "Csak festett"
|
||||
msgid "Contour"
|
||||
msgstr "Kontúr"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Lyuk"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Kontúr és lyuk"
|
||||
|
||||
|
||||
@@ -15319,6 +15319,9 @@ msgstr "Solo verniciato"
|
||||
msgid "Contour"
|
||||
msgstr "Contorno"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Foro"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Contorno e foro"
|
||||
|
||||
|
||||
@@ -14093,6 +14093,9 @@ msgstr "塗装のみ"
|
||||
msgid "Contour"
|
||||
msgstr "輪郭"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "穴"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "輪郭と穴"
|
||||
|
||||
|
||||
@@ -14240,6 +14240,9 @@ msgstr "도색만"
|
||||
msgid "Contour"
|
||||
msgstr "윤곽"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "구멍"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "윤곽 및 구멍"
|
||||
|
||||
|
||||
@@ -15043,6 +15043,9 @@ msgstr "Tik dažytas"
|
||||
msgid "Contour"
|
||||
msgstr "Kontūras"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Skylė"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Kontūras ir skylė"
|
||||
|
||||
|
||||
@@ -15043,6 +15043,9 @@ msgstr "Alleen geverfd"
|
||||
msgid "Contour"
|
||||
msgstr "Contour"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Gat"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Contour en gat"
|
||||
|
||||
|
||||
@@ -14539,6 +14539,9 @@ msgstr "Tylko malowane"
|
||||
msgid "Contour"
|
||||
msgstr "Kontur"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Otwory"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Kontur i otwory"
|
||||
|
||||
|
||||
@@ -15186,6 +15186,9 @@ msgstr "Somente pintado"
|
||||
msgid "Contour"
|
||||
msgstr "Contorno"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Furo"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Contorno e furo"
|
||||
|
||||
|
||||
@@ -15501,6 +15501,9 @@ msgstr "Вручную"
|
||||
msgid "Contour"
|
||||
msgstr "Контур"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Отверстия"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Контур и отверстия"
|
||||
|
||||
|
||||
@@ -14883,6 +14883,9 @@ msgstr "Endast målad"
|
||||
msgid "Contour"
|
||||
msgstr "Kontur"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Hål"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Kontur och hål"
|
||||
|
||||
|
||||
@@ -13339,6 +13339,9 @@ msgstr "Sadece boyalı"
|
||||
msgid "Contour"
|
||||
msgstr "Kontur"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Delik"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Kontur ve delik"
|
||||
|
||||
|
||||
@@ -14536,6 +14536,9 @@ msgstr "Тільки пофарбовані"
|
||||
msgid "Contour"
|
||||
msgstr "Контур"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Отвір"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Контур та отвір"
|
||||
|
||||
|
||||
@@ -14730,6 +14730,9 @@ msgstr "Chỉ được sơn"
|
||||
msgid "Contour"
|
||||
msgstr "Đường viền"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "Lỗ"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "Đường viền và lỗ"
|
||||
|
||||
|
||||
@@ -13894,6 +13894,9 @@ msgstr "仅涂漆"
|
||||
msgid "Contour"
|
||||
msgstr "轮廓"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "孔"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "轮廓和孔"
|
||||
|
||||
|
||||
@@ -14006,6 +14006,9 @@ msgstr "僅塗漆"
|
||||
msgid "Contour"
|
||||
msgstr "輪廓"
|
||||
|
||||
msgid "Hole"
|
||||
msgstr "孔洞"
|
||||
|
||||
msgid "Contour and hole"
|
||||
msgstr "輪廓和孔"
|
||||
|
||||
|
||||
@@ -418,7 +418,13 @@ void group_region_by_fuzzify(PerimeterGenerator& g)
|
||||
g.has_fuzzy_skin = false;
|
||||
g.has_fuzzy_hole = false;
|
||||
|
||||
std::unordered_map<FuzzySkinConfig, SurfacesPtr> regions;
|
||||
struct ConfigSurfaces {
|
||||
FuzzySkinConfig config;
|
||||
SurfacesPtr surfaces;
|
||||
};
|
||||
|
||||
std::vector<ConfigSurfaces> regions;
|
||||
regions.reserve(g.compatible_regions->size());
|
||||
for (auto region : *g.compatible_regions) {
|
||||
const auto& region_config = region->region().config();
|
||||
const FuzzySkinConfig cfg{region_config.fuzzy_skin,
|
||||
@@ -434,26 +440,36 @@ void group_region_by_fuzzify(PerimeterGenerator& g)
|
||||
region_config.fuzzy_skin_ripple_offset,
|
||||
region_config.fuzzy_skin_layers_between_ripple_offset,
|
||||
g.layer_id};
|
||||
auto& surfaces = regions[cfg];
|
||||
|
||||
auto it = std::find_if(regions.begin(), regions.end(), [&cfg](const ConfigSurfaces& item) {
|
||||
return item.config == cfg;
|
||||
});
|
||||
if (it == regions.end()) {
|
||||
regions.push_back({cfg, {}});
|
||||
it = regions.end() - 1;
|
||||
}
|
||||
|
||||
auto& surfaces = it->surfaces;
|
||||
for (const auto& surface : region->slices.surfaces) {
|
||||
surfaces.push_back(&surface);
|
||||
}
|
||||
|
||||
if (cfg.type != FuzzySkinType::None && cfg.type != FuzzySkinType::Disabled_fuzzy) {
|
||||
if (should_fuzzify(cfg, g.layer_id, 0, true)) {
|
||||
g.has_fuzzy_skin = true;
|
||||
if (cfg.type != FuzzySkinType::External) {
|
||||
g.has_fuzzy_hole = true;
|
||||
}
|
||||
}
|
||||
if (should_fuzzify(cfg, g.layer_id, 0, false)) {
|
||||
g.has_fuzzy_hole = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (regions.size() == 1) { // optimization
|
||||
g.regions_by_fuzzify[regions.begin()->first] = {};
|
||||
g.regions_by_fuzzify.push_back({regions.front().config, {}});
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& it : regions) {
|
||||
g.regions_by_fuzzify[it.first] = offset_ex(it.second, ClipperSafetyOffset);
|
||||
g.regions_by_fuzzify.reserve(regions.size());
|
||||
for (const auto& region : regions) {
|
||||
g.regions_by_fuzzify.push_back({region.config, offset_ex(region.surfaces, ClipperSafetyOffset)});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,12 +485,79 @@ bool should_fuzzify(const FuzzySkinConfig& config, const int layer_id, const siz
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool fuzzify_contours = loop_idx == 0 || fuzziy_type == FuzzySkinType::AllWalls;
|
||||
const bool fuzzify_holes = fuzzify_contours && (fuzziy_type == FuzzySkinType::All || fuzziy_type == FuzzySkinType::AllWalls);
|
||||
const bool fuzzify_contours = (loop_idx == 0 && fuzziy_type != FuzzySkinType::Hole) || fuzziy_type == FuzzySkinType::AllWalls;
|
||||
const bool fuzzify_holes = (fuzziy_type == FuzzySkinType::Hole || fuzziy_type == FuzzySkinType::All || fuzziy_type == FuzzySkinType::AllWalls)
|
||||
&& (loop_idx == 0 || fuzziy_type == FuzzySkinType::AllWalls);
|
||||
|
||||
return is_contour ? fuzzify_contours : fuzzify_holes;
|
||||
}
|
||||
|
||||
struct MergedFuzzyRegion {
|
||||
const FuzzySkinConfig *config;
|
||||
ExPolygons expolygons;
|
||||
};
|
||||
|
||||
// Compare whether two configs produce the same fuzzy effect (ignoring type/first_layer
|
||||
// which only control which loops get fuzzified, not the noise itself).
|
||||
static bool same_fuzzy_effect(const FuzzySkinConfig& a, const FuzzySkinConfig& b)
|
||||
{
|
||||
return a.thickness == b.thickness
|
||||
&& a.point_distance == b.point_distance
|
||||
&& a.noise_type == b.noise_type
|
||||
&& a.noise_scale == b.noise_scale
|
||||
&& a.noise_octaves == b.noise_octaves
|
||||
&& a.noise_persistence == b.noise_persistence
|
||||
&& a.mode == b.mode
|
||||
&& a.ripples_per_layer == b.ripples_per_layer
|
||||
&& a.ripple_offset == b.ripple_offset
|
||||
&& a.layers_between_ripple_offset == b.layers_between_ripple_offset;
|
||||
}
|
||||
|
||||
static std::vector<MergedFuzzyRegion> collect_merged_fuzzy_regions(const std::vector<std::pair<FuzzySkinConfig, ExPolygons>>& regions,
|
||||
const int layer_id,
|
||||
const size_t loop_idx,
|
||||
const bool is_contour)
|
||||
{
|
||||
// Merge regions that produce identical fuzzy effects (differ only in type).
|
||||
// When the style (e.g. External) and a painted region (All) both fuzzify this loop
|
||||
// with the same noise parameters, merging their ExPolygons avoids splitting the
|
||||
// perimeter at the painted boundary — eliminating discontinuity artifacts.
|
||||
std::vector<MergedFuzzyRegion> merged_regions;
|
||||
merged_regions.reserve(regions.size());
|
||||
for (const auto& region : regions) {
|
||||
if (!should_fuzzify(region.first, layer_id, loop_idx, is_contour)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool merged = false;
|
||||
for (auto& merged_region : merged_regions) {
|
||||
if (same_fuzzy_effect(*merged_region.config, region.first)) {
|
||||
if (merged_region.expolygons.empty()) {
|
||||
// Already full coverage, nothing to add.
|
||||
} else if (region.second.empty()) {
|
||||
merged_region.expolygons.clear();
|
||||
} else {
|
||||
append(merged_region.expolygons, region.second);
|
||||
}
|
||||
merged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!merged) {
|
||||
merged_regions.push_back({®ion.first, region.second});
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& merged_region : merged_regions) {
|
||||
if (!merged_region.expolygons.empty()) {
|
||||
merged_region.expolygons = union_ex(merged_region.expolygons);
|
||||
}
|
||||
}
|
||||
|
||||
return merged_regions;
|
||||
}
|
||||
|
||||
Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perimeter_generator, const size_t loop_idx, const bool is_contour)
|
||||
{
|
||||
Polygon fuzzified;
|
||||
@@ -493,22 +576,30 @@ Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perim
|
||||
return fuzzified;
|
||||
}
|
||||
|
||||
// Find all affective regions
|
||||
std::vector<std::pair<const FuzzySkinConfig&, const ExPolygons&>> fuzzified_regions;
|
||||
fuzzified_regions.reserve(regions.size());
|
||||
for (const auto& region : regions) {
|
||||
if (should_fuzzify(region.first, perimeter_generator.layer_id, loop_idx, is_contour)) {
|
||||
fuzzified_regions.emplace_back(region.first, region.second);
|
||||
}
|
||||
}
|
||||
if (fuzzified_regions.empty()) {
|
||||
// Merge regions that produce identical fuzzy effects (differ only in type).
|
||||
// When the style (e.g. External) and a painted region (All) both fuzzify this loop
|
||||
// with the same noise parameters, merging their ExPolygons avoids splitting the
|
||||
// perimeter at the painted boundary — eliminating discontinuity artifacts.
|
||||
auto merged_regions = collect_merged_fuzzy_regions(regions, perimeter_generator.layer_id, loop_idx, is_contour);
|
||||
if (merged_regions.empty()) {
|
||||
return polygon;
|
||||
}
|
||||
|
||||
// Fast path: single merged region — apply directly without splitting
|
||||
if (merged_regions.size() == 1) {
|
||||
const auto& mr = merged_regions.front();
|
||||
if (mr.expolygons.empty()) {
|
||||
fuzzified = polygon;
|
||||
fuzzy_polyline(fuzzified.points, true, slice_z, *mr.config);
|
||||
return fuzzified;
|
||||
}
|
||||
// Fall through to split_line with a single region below
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FUZZY
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto& r : fuzzified_regions) {
|
||||
for (const auto& r : merged_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,
|
||||
@@ -517,18 +608,26 @@ Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perim
|
||||
bbox);
|
||||
svg.draw_outline(perimeter_generator.slices->surfaces);
|
||||
svg.draw_outline(polygon, "green");
|
||||
svg.draw(r.second, "red", 0.5);
|
||||
svg.draw_outline(r.second, "red");
|
||||
svg.draw(r.expolygons, "red", 0.5);
|
||||
svg.draw_outline(r.expolygons, "red");
|
||||
svg.Close();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Make each region's ExPolygons exclusive so overlapping regions don't double-fuzz
|
||||
// the same perimeter section. Later regions in the list take priority over earlier ones
|
||||
// in overlapping areas (matching modifier precedence order).
|
||||
for (size_t i = 0; i < merged_regions.size(); ++i)
|
||||
for (size_t j = i + 1; j < merged_regions.size(); ++j)
|
||||
if (!merged_regions[i].expolygons.empty() && !merged_regions[j].expolygons.empty())
|
||||
merged_regions[i].expolygons = diff_ex(merged_regions[i].expolygons, merged_regions[j].expolygons);
|
||||
|
||||
// Split the loops into lines with different config, and fuzzy them separately
|
||||
fuzzified = polygon;
|
||||
for (const auto& r : fuzzified_regions) {
|
||||
auto splitted = Algorithm::split_line(fuzzified, r.second, true);
|
||||
for (const auto& r : merged_regions) {
|
||||
auto splitted = Algorithm::split_line(fuzzified, r.expolygons, true);
|
||||
if (splitted.empty()) {
|
||||
// No intersection, skip
|
||||
continue;
|
||||
@@ -537,7 +636,7 @@ Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perim
|
||||
// Fuzzy splitted polygon
|
||||
if (std::all_of(splitted.begin(), splitted.end(), [](const Algorithm::SplitLineJunction& j) { return j.clipped; })) {
|
||||
// The entire polygon is fuzzified
|
||||
fuzzy_polyline(fuzzified.points, true, slice_z, r.first);
|
||||
fuzzy_polyline(fuzzified.points, true, slice_z, *r.config);
|
||||
} else {
|
||||
// Start from a non-clipped junction so wrapped clipped segments do
|
||||
// not need an artificial reconnection across the seam.
|
||||
@@ -554,7 +653,7 @@ Polygon apply_fuzzy_skin(const Polygon& polygon, const PerimeterGenerator& perim
|
||||
const auto fuzzy_current_segment = [&segment, &fuzzified, &r, slice_z]() {
|
||||
fuzzified.points.push_back(segment.front());
|
||||
const auto back = segment.back();
|
||||
fuzzy_polyline(segment, false, slice_z, r.first);
|
||||
fuzzy_polyline(segment, false, slice_z, *r.config);
|
||||
fuzzified.points.insert(fuzzified.points.end(), segment.begin(), segment.end());
|
||||
fuzzified.points.push_back(back);
|
||||
segment.clear();
|
||||
@@ -593,20 +692,23 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
if (fuzzify)
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, config);
|
||||
} else {
|
||||
// Find all affective regions
|
||||
std::vector<std::pair<const FuzzySkinConfig&, const ExPolygons&>> fuzzified_regions;
|
||||
fuzzified_regions.reserve(regions.size());
|
||||
for (const auto& region : regions) {
|
||||
if (should_fuzzify(region.first, perimeter_generator.layer_id, extrusion->inset_idx, is_contour)) {
|
||||
fuzzified_regions.emplace_back(region.first, region.second);
|
||||
// Merge regions that produce identical fuzzy effects (differ only in type).
|
||||
// When the style (e.g. External) and a painted region (All) both fuzzify this loop
|
||||
// with the same noise parameters, merging avoids splitting the perimeter at the
|
||||
// painted boundary — eliminating discontinuity artifacts.
|
||||
auto merged_regions = collect_merged_fuzzy_regions(regions, perimeter_generator.layer_id, extrusion->inset_idx, is_contour);
|
||||
if (!merged_regions.empty()) {
|
||||
|
||||
// Fast path: single merged region — apply directly without splitting
|
||||
if (merged_regions.size() == 1 && merged_regions.front().expolygons.empty()) {
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, *merged_regions.front().config);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!fuzzified_regions.empty()) {
|
||||
|
||||
|
||||
#ifdef DEBUG_FUZZY
|
||||
{
|
||||
int i = 0;
|
||||
for (const auto& r : fuzzified_regions) {
|
||||
for (const auto& r : merged_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,
|
||||
@@ -623,17 +725,25 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
|
||||
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.draw(r.expolygons, "red", 0.5);
|
||||
svg.draw_outline(r.expolygons, "red");
|
||||
svg.Close();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Make each region's ExPolygons exclusive so overlapping regions don't double-fuzz
|
||||
// the same perimeter section. Later regions in the list take priority over earlier ones
|
||||
// in overlapping areas.
|
||||
for (size_t i = 0; i < merged_regions.size(); ++i)
|
||||
for (size_t j = i + 1; j < merged_regions.size(); ++j)
|
||||
if (!merged_regions[i].expolygons.empty() && !merged_regions[j].expolygons.empty())
|
||||
merged_regions[i].expolygons = diff_ex(merged_regions[i].expolygons, merged_regions[j].expolygons);
|
||||
|
||||
// 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);
|
||||
for (const auto& r : merged_regions) {
|
||||
const auto splitted = Algorithm::split_line(*extrusion, r.expolygons, false);
|
||||
if (splitted.empty()) {
|
||||
// No intersection, skip
|
||||
continue;
|
||||
@@ -642,7 +752,7 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
// Fuzzy splitted extrusion
|
||||
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);
|
||||
fuzzy_extrusion_line(extrusion->junctions, slice_z, *r.config);
|
||||
continue;
|
||||
} else {
|
||||
const auto current_ext = extrusion->junctions;
|
||||
@@ -655,7 +765,7 @@ void apply_fuzzy_skin(Arachne::ExtrusionLine* extrusion, const PerimeterGenerato
|
||||
const auto front = segment.front();
|
||||
const auto back = segment.back();
|
||||
|
||||
fuzzy_extrusion_line(segment, slice_z, r.first, false);
|
||||
fuzzy_extrusion_line(segment, slice_z, *r.config, false);
|
||||
// Orca: only add non fuzzy point if it's not in the extrusion closing point.
|
||||
if (!extrusion->junctions.empty() && extrusion->junctions.front().p != front.p) {
|
||||
extrusion->junctions.push_back(front);
|
||||
|
||||
@@ -250,6 +250,23 @@ void Layer::make_perimeters()
|
||||
//BBS: Separate fill_no_overlap
|
||||
(*l)->fill_no_overlap_expolygons = intersection_ex((*l)->slices.surfaces, fill_no_overlap);
|
||||
}
|
||||
|
||||
// When counterbore hole bridging (chbFilled) is active, process_no_bridge may
|
||||
// create fill surfaces that extend beyond all region slices (e.g. by clearing
|
||||
// holes in the bridge expolygon). These "extra" fills are lost during the
|
||||
// intersection-based splitting above. Recover them and assign to the first
|
||||
// merged region so the sacrificial bridge layer is not broken.
|
||||
if (layerm_config->region().config().counterbore_hole_bridging.value != chbNone) {
|
||||
Polygons all_region_slices_p;
|
||||
for (LayerRegion *l : layerms)
|
||||
polygons_append(all_region_slices_p, to_polygons(l->slices.surfaces));
|
||||
ExPolygons extra_fill = diff_ex(fill_surfaces.surfaces, all_region_slices_p, ApplySafetyOffset::Yes);
|
||||
if (!extra_fill.empty()) {
|
||||
append(layerms.front()->fill_expolygons, extra_fill);
|
||||
layerms.front()->fill_expolygons = union_ex(layerms.front()->fill_expolygons);
|
||||
layerms.front()->fill_surfaces.append(std::move(extra_fill), fill_surfaces.surfaces.front());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,8 @@ public:
|
||||
|
||||
bool has_fuzzy_skin = false;
|
||||
bool has_fuzzy_hole = false;
|
||||
std::unordered_map<FuzzySkinConfig, ExPolygons> regions_by_fuzzify;
|
||||
// Preserve construction order so overlap precedence remains deterministic.
|
||||
std::vector<std::pair<FuzzySkinConfig, ExPolygons>> regions_by_fuzzify;
|
||||
|
||||
PerimeterGenerator(
|
||||
// Input:
|
||||
|
||||
@@ -172,6 +172,7 @@ CONFIG_OPTION_ENUM_DEFINE_STATIC_MAPS(PowerLossRecoveryMode)
|
||||
static t_config_enum_values s_keys_map_FuzzySkinType {
|
||||
{ "none", int(FuzzySkinType::None) },
|
||||
{ "external", int(FuzzySkinType::External) },
|
||||
{ "hole", int(FuzzySkinType::Hole) },
|
||||
{ "all", int(FuzzySkinType::All) },
|
||||
{ "allwalls", int(FuzzySkinType::AllWalls)},
|
||||
{ "disabled_fuzzy", int(FuzzySkinType::Disabled_fuzzy)}
|
||||
@@ -3354,11 +3355,13 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_keys_map = &ConfigOptionEnum<FuzzySkinType>::get_enum_values();
|
||||
def->enum_values.push_back("none");
|
||||
def->enum_values.push_back("external");
|
||||
def->enum_values.push_back("hole");
|
||||
def->enum_values.push_back("all");
|
||||
def->enum_values.push_back("allwalls");
|
||||
def->enum_values.push_back("disabled_fuzzy");
|
||||
def->enum_labels.push_back(L("Painted only"));
|
||||
def->enum_labels.push_back(L("Contour"));
|
||||
def->enum_labels.push_back(L("Hole"));
|
||||
def->enum_labels.push_back(L("Contour and hole"));
|
||||
def->enum_labels.push_back(L("All walls"));
|
||||
def->enum_labels.push_back(L("Disabled"));
|
||||
|
||||
@@ -39,6 +39,7 @@ enum GCodeFlavor : unsigned char {
|
||||
enum class FuzzySkinType {
|
||||
None,
|
||||
External,
|
||||
Hole,
|
||||
All,
|
||||
AllWalls,
|
||||
Disabled_fuzzy,
|
||||
|
||||
Reference in New Issue
Block a user