diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 10ceda5837a..1ccfacf3b5b 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -370,6 +370,7 @@ struct SurfaceFillParams int texture_mapping_top_surface_component_count = 0; int texture_mapping_top_surface_contoning_flat_surface_infill_mode = TextureMappingZone::SlicerDefaultTopSurfaceContoningFlatSurfaceInfillMode; bool texture_mapping_top_surface_contoning_no_edge_overlap = false; + bool texture_mapping_top_surface_contoning_partition_color_regions = TextureMappingZone::DefaultTopSurfaceContoningPartitionColorRegionsEnabled; bool operator<(const SurfaceFillParams &rhs) const { #define RETURN_COMPARE_NON_EQUAL(KEY) if (this->KEY < rhs.KEY) return true; if (this->KEY > rhs.KEY) return false; @@ -417,6 +418,7 @@ struct SurfaceFillParams RETURN_COMPARE_NON_EQUAL(texture_mapping_top_surface_component_count); RETURN_COMPARE_NON_EQUAL(texture_mapping_top_surface_contoning_flat_surface_infill_mode); RETURN_COMPARE_NON_EQUAL(texture_mapping_top_surface_contoning_no_edge_overlap); + RETURN_COMPARE_NON_EQUAL(texture_mapping_top_surface_contoning_partition_color_regions); return false; } @@ -458,7 +460,8 @@ struct SurfaceFillParams this->texture_mapping_top_surface_component_index == rhs.texture_mapping_top_surface_component_index && this->texture_mapping_top_surface_component_count == rhs.texture_mapping_top_surface_component_count && this->texture_mapping_top_surface_contoning_flat_surface_infill_mode == rhs.texture_mapping_top_surface_contoning_flat_surface_infill_mode && - this->texture_mapping_top_surface_contoning_no_edge_overlap == rhs.texture_mapping_top_surface_contoning_no_edge_overlap; + this->texture_mapping_top_surface_contoning_no_edge_overlap == rhs.texture_mapping_top_surface_contoning_no_edge_overlap && + this->texture_mapping_top_surface_contoning_partition_color_regions == rhs.texture_mapping_top_surface_contoning_partition_color_regions; } }; @@ -515,6 +518,7 @@ struct TopSurfaceImageRegionPlan { bool contoning_blue_noise_error_diffusion_enabled = false; bool contoning_supersampled_cells_enabled = false; bool contoning_polygonize_color_regions_enabled = false; + bool contoning_partition_color_regions_enabled = TextureMappingZone::DefaultTopSurfaceContoningPartitionColorRegionsEnabled; bool contoning_fast_mode_enabled = TextureMappingZone::DefaultTopSurfaceContoningFastModeEnabled; int contoning_polygonization_mode = TextureMappingZone::DefaultTopSurfaceContoningPolygonizationMode; int contoning_polygonize_resolution = TextureMappingZone::DefaultTopSurfaceContoningPolygonizeResolution; @@ -8656,7 +8660,7 @@ static std::vector top_surface_image_region_plans( plan.contoning_flat_surface_infill_mode = std::clamp(zone->effective_top_surface_contoning_flat_surface_infill_mode(), int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinear), - int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary)); + int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair)); plan.contoning_layer_phase_enabled = zone->effective_top_surface_contoning_layer_phase_enabled(); plan.contoning_varied_infill_angles_enabled = zone->top_surface_contoning_varied_infill_angles_enabled; plan.contoning_blue_noise_error_diffusion_enabled = @@ -8664,6 +8668,8 @@ static std::vector top_surface_image_region_plans( plan.contoning_supersampled_cells_enabled = zone->effective_top_surface_contoning_supersampled_cells_enabled(); plan.contoning_polygonize_color_regions_enabled = zone->top_surface_contoning_polygonize_color_regions_enabled; + plan.contoning_partition_color_regions_enabled = + zone->effective_top_surface_contoning_partition_color_regions_enabled(); plan.contoning_fast_mode_enabled = zone->effective_top_surface_contoning_fast_mode_enabled(); plan.contoning_polygonization_mode = zone->effective_top_surface_contoning_polygonization_mode(); plan.contoning_polygonize_resolution = @@ -9299,6 +9305,17 @@ static bool top_surface_image_contoning_rectilinear_with_boundary_mode(int mode) return mode == int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary); } +static bool top_surface_image_contoning_rectilinear_with_repair_mode(int mode) +{ + return mode == int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair); +} + +static bool top_surface_image_contoning_rectilinear_repair_mode(int mode) +{ + return top_surface_image_contoning_rectilinear_with_boundary_mode(mode) || + top_surface_image_contoning_rectilinear_with_repair_mode(mode); +} + struct TopSurfaceImageRectilinearBoundaryKey { size_t region_id = size_t(-1); unsigned int zone_id = 0; @@ -9497,6 +9514,7 @@ static ExtrusionEntitiesPtr top_surface_image_rectilinear_boundary_collections( static std::map top_surface_image_rectilinear_boundary_groups(const Layer &layer, const std::vector &surface_fills, + bool repair_only, const ThrowIfCanceled *throw_if_canceled) { std::map groups; @@ -9506,10 +9524,15 @@ top_surface_image_rectilinear_boundary_groups(const Layer &layer, fill.region_id >= layer.regions().size() || !fill.params.texture_mapping_top_surface_image || !fill.params.texture_mapping_top_surface_contoning || - !top_surface_image_contoning_rectilinear_with_boundary_mode( - fill.params.texture_mapping_top_surface_contoning_flat_surface_infill_mode) || fill.params.texture_mapping_top_surface_component_id == 0) continue; + const bool matching_mode = repair_only ? + top_surface_image_contoning_rectilinear_repair_mode( + fill.params.texture_mapping_top_surface_contoning_flat_surface_infill_mode) : + top_surface_image_contoning_rectilinear_with_boundary_mode( + fill.params.texture_mapping_top_surface_contoning_flat_surface_infill_mode); + if (!matching_mode) + continue; TopSurfaceImageRectilinearBoundaryKey key; key.region_id = fill.region_id; key.zone_id = fill.params.texture_mapping_top_surface_zone_id; @@ -9651,7 +9674,17 @@ static ExPolygons top_surface_image_rectilinear_repair_leftover( return covered.empty() ? intended : top_surface_clip_diff_ex(intended, covered, ApplySafetyOffset::Yes); } +static std::unique_ptr top_surface_image_rectilinear_arachne_repair_collection( + const ExPolygons &area, + const SurfaceFillParams ¶ms, + const PrintConfig &print_config, + const PrintObjectConfig &object_config, + int layer_id, + const ThrowIfCanceled *throw_if_canceled); + static ExtrusionEntitiesPtr top_surface_image_rectilinear_repair_collections( + const Layer &layer, + const TopSurfaceImageRectilinearBoundaryKey &key, const TopSurfaceImageRectilinearBoundaryGroup &group, const ExPolygons &leftover, const ThrowIfCanceled *throw_if_canceled) @@ -9683,22 +9716,43 @@ static ExtrusionEntitiesPtr top_surface_image_rectilinear_repair_collections( ExtrusionEntityCollection *collection = new ExtrusionEntityCollection(); collection->no_sort = true; collection->texture_mapping_extruder_override = int(component_area.first) - 1; - for (const ExPolygon &expolygon : area) { - check_canceled(throw_if_canceled); - top_surface_image_append_rectilinear_repair_lines(*collection, expolygon, params, throw_if_canceled); - } - Polygons line_covered_polygons; - collection->polygons_covered_by_spacing(line_covered_polygons, float(scale_(0.02))); - ExPolygons loop_area = area; - if (!line_covered_polygons.empty()) { - ExPolygons line_covered = - top_surface_clip_intersection_ex(top_surface_clip_union_ex(line_covered_polygons), area, ApplySafetyOffset::Yes); - if (!line_covered.empty()) - loop_area = top_surface_clip_diff_ex(area, line_covered, ApplySafetyOffset::Yes); - } - for (const ExPolygon &expolygon : loop_area) { - check_canceled(throw_if_canceled); - top_surface_image_append_rectilinear_repair_loops(*collection, expolygon, params); + if (top_surface_image_contoning_rectilinear_with_repair_mode( + group.params.texture_mapping_top_surface_contoning_flat_surface_infill_mode) && + key.region_id < layer.regions().size() && + layer.regions()[key.region_id] != nullptr && + layer.object() != nullptr && + layer.object()->print() != nullptr) { + std::unique_ptr arachne_collection = + top_surface_image_rectilinear_arachne_repair_collection(area, + params, + layer.object()->print()->config(), + layer.object()->config(), + int(layer.id()), + throw_if_canceled); + if (arachne_collection != nullptr) { + collection->entities.insert(collection->entities.end(), + arachne_collection->entities.begin(), + arachne_collection->entities.end()); + arachne_collection->entities.clear(); + } + } else { + for (const ExPolygon &expolygon : area) { + check_canceled(throw_if_canceled); + top_surface_image_append_rectilinear_repair_lines(*collection, expolygon, params, throw_if_canceled); + } + Polygons line_covered_polygons; + collection->polygons_covered_by_spacing(line_covered_polygons, float(scale_(0.02))); + ExPolygons loop_area = area; + if (!line_covered_polygons.empty()) { + ExPolygons line_covered = + top_surface_clip_intersection_ex(top_surface_clip_union_ex(line_covered_polygons), area, ApplySafetyOffset::Yes); + if (!line_covered.empty()) + loop_area = top_surface_clip_diff_ex(area, line_covered, ApplySafetyOffset::Yes); + } + for (const ExPolygon &expolygon : loop_area) { + check_canceled(throw_if_canceled); + top_surface_image_append_rectilinear_repair_loops(*collection, expolygon, params); + } } if (collection->empty()) { delete collection; @@ -9725,7 +9779,11 @@ static void top_surface_image_append_rectilinear_repair_collections(Layer &layer if (leftover.empty()) continue; ExtrusionEntitiesPtr collections = - top_surface_image_rectilinear_repair_collections(entry.second, leftover, throw_if_canceled); + top_surface_image_rectilinear_repair_collections(layer, + entry.first, + entry.second, + leftover, + throw_if_canceled); if (!collections.empty()) repairs.emplace_back(entry.first.region_id, std::move(collections)); } @@ -10046,8 +10104,12 @@ static SurfaceFillParams top_surface_image_params_for_slice(const Layer &layer, params.texture_mapping_top_surface_component_index = int(slice.component_index); params.texture_mapping_top_surface_component_count = int(slice.component_count); params.texture_mapping_top_surface_contoning_flat_surface_infill_mode = plan.contoning_flat_surface_infill_mode; + params.texture_mapping_top_surface_contoning_partition_color_regions = + slice.contoning && plan.contoning_partition_color_regions_enabled; params.texture_mapping_top_surface_contoning_no_edge_overlap = - slice.contoning && plan.contoning_polygonize_color_regions_enabled; + slice.contoning && + !plan.contoning_partition_color_regions_enabled && + plan.contoning_polygonize_color_regions_enabled; return params; } @@ -10716,6 +10778,83 @@ static std::unique_ptr top_surface_image_boundary_ski return collection; } +static std::unique_ptr top_surface_image_rectilinear_arachne_repair_collection( + const ExPolygons &area, + const SurfaceFillParams ¶ms, + const PrintConfig &print_config, + const PrintObjectConfig &object_config, + int layer_id, + const ThrowIfCanceled *throw_if_canceled) +{ + check_canceled(throw_if_canceled); + std::unique_ptr collection(new ExtrusionEntityCollection()); + collection->no_sort = true; + if (area.empty()) + return collection; + + const float min_width = std::clamp(params.texture_mapping_top_surface_min_width_mm, + TextureMappingZone::MinTopSurfaceImageLineWidthMm, + TextureMappingZone::MaxTopSurfaceImageLineWidthMm); + const float max_width = std::clamp(params.texture_mapping_top_surface_max_width_mm, + min_width, + TextureMappingZone::MaxTopSurfaceImageLineWidthMm); + const Flow max_flow = Flow(max_width, params.flow.height(), params.flow.nozzle_diameter()); + const Flow min_flow = Flow(min_width, params.flow.height(), params.flow.nozzle_diameter()); + const coord_t preferred_spacing = std::max(1, max_flow.scaled_spacing()); + const coordf_t min_spacing = std::max(1.0, min_flow.scaled_spacing()); + const coordf_t max_spacing = std::max(min_spacing, max_flow.scaled_spacing()); + Polygons outline = to_polygons(area); + if (outline.empty()) + return collection; + + Arachne::WallToolPathsParams input_params = + Arachne::make_paths_params(layer_id, object_config, print_config); + input_params.min_bead_width = min_width; + if (!std::isfinite(input_params.min_feature_size) || input_params.min_feature_size <= 0.f) + input_params.min_feature_size = min_width * 0.5f; + else + input_params.min_feature_size = std::min(input_params.min_feature_size, min_width * 0.5f); + input_params.min_length_factor = + (!std::isfinite(input_params.min_length_factor) || input_params.min_length_factor <= 0.f) ? + 0.5f : + std::min(input_params.min_length_factor, 0.5f); + input_params.wall_distribution_count = std::max(1, input_params.wall_distribution_count); + input_params.is_top_or_bottom_layer = true; + + Arachne::WallToolPaths wall_tool_paths(outline, + preferred_spacing, + preferred_spacing, + 1, + 0, + params.flow.height(), + input_params); + std::vector loops = wall_tool_paths.getToolPaths(); + ThickPolylines thick_polylines; + for (Arachne::VariableWidthLines &loop : loops) { + check_canceled(throw_if_canceled); + for (const Arachne::ExtrusionLine &wall : loop) { + if (wall.size() < 2) + continue; + ThickPolyline thick_polyline = Arachne::to_thick_polyline(wall); + if (thick_polyline.points.size() < 2 || thick_polyline.width.empty()) + continue; + for (coordf_t &width : thick_polyline.width) + width = std::clamp(width, min_spacing, max_spacing); + if (thick_polyline.is_valid()) + thick_polylines.emplace_back(std::move(thick_polyline)); + } + } + variable_width(thick_polylines, + params.extrusion_role, + max_flow, + collection->entities); + const float min_length_mm = + std::max(0.18f, std::min(0.75f, min_width * 0.55f)); + top_surface_image_filter_short_boundary_skin_entities(*collection, min_length_mm); + top_surface_image_reorder_boundary_skin_entities(*collection); + return collection; +} + static void apply_top_surface_image_collection_metadata(ExtrusionEntityCollection &collection, const SurfaceFillParams ¶ms, const std::optional &context, @@ -11913,7 +12052,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, #endif /* SLIC3R_DEBUG_SLICE_PROCESSING */ const std::map rectilinear_boundary_groups = - top_surface_image_rectilinear_boundary_groups(*this, surface_fills, throw_if_canceled_ptr); + top_surface_image_rectilinear_boundary_groups(*this, surface_fills, false, throw_if_canceled_ptr); + const std::map rectilinear_repair_groups = + top_surface_image_rectilinear_boundary_groups(*this, surface_fills, true, throw_if_canceled_ptr); top_surface_image_append_rectilinear_boundary_collections(*this, rectilinear_boundary_groups, throw_if_canceled_ptr); for (SurfaceFill &surface_fill : surface_fills) { @@ -12093,6 +12234,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, fill_entities.push_back(collection.release()); } } else if (surface_fill.params.texture_mapping_top_surface_contoning && + !surface_fill.params.texture_mapping_top_surface_contoning_partition_color_regions && top_surface_image_contoning_spiral_mode( surface_fill.params.texture_mapping_top_surface_contoning_flat_surface_infill_mode)) { ExPolygons leftover; @@ -12158,7 +12300,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillParams fallback_params = params; fallback_params.flow = fallback_flow; fallback_params.pattern = ipRectilinear; - fallback_params.no_edge_overlap = true; + fallback_params.no_edge_overlap = + !surface_fill.params.texture_mapping_top_surface_contoning_partition_color_regions; ExtrusionEntitiesPtr hybrid_interior_entities; if (!hybrid_boundary_skin && collection && !collection->empty()) { apply_top_surface_image_collection_metadata(*collection, surface_fill.params, std::nullopt, throw_if_canceled_ptr); @@ -12216,7 +12359,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, } } - top_surface_image_append_rectilinear_repair_collections(*this, rectilinear_boundary_groups, throw_if_canceled_ptr); + top_surface_image_append_rectilinear_repair_collections(*this, rectilinear_repair_groups, throw_if_canceled_ptr); // add thin fill regions // Unpacks the collection, creates multiple collections per path. diff --git a/src/libslic3r/TextureMapping.cpp b/src/libslic3r/TextureMapping.cpp index 0b5be5df89b..3de4b439f9a 100644 --- a/src/libslic3r/TextureMapping.cpp +++ b/src/libslic3r/TextureMapping.cpp @@ -765,11 +765,13 @@ static std::string top_surface_contoning_flat_surface_infill_mode_name(int mode) { switch (clamp_int(mode, int(TextureMappingZone::ContoningFlatSurfaceInfillDefault), - int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary))) { + int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair))) { case int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinear): return "rectilinear"; case int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary): return "rectilinear_with_boundary"; + case int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair): + return "rectilinear_with_repair"; case int(TextureMappingZone::ContoningFlatSurfaceInfillConcentric): return "concentric"; case int(TextureMappingZone::ContoningFlatSurfaceInfillBoundarySkinFixed): @@ -791,6 +793,8 @@ static int top_surface_contoning_flat_surface_infill_mode_from_name(const std::s return int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinear); if (name == "rectilinear_with_boundary" || name == "rectilinear_boundary") return int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary); + if (name == "rectilinear_with_repair" || name == "rectilinear_repair") + return int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair); if (name == "concentric") return int(TextureMappingZone::ContoningFlatSurfaceInfillConcentric); if (name == "boundary_skin" || name == "boundary_skin_variable") @@ -1802,6 +1806,8 @@ bool TextureMappingZone::operator==(const TextureMappingZone &rhs) const effective_top_surface_contoning_supersampled_cells_enabled() == rhs.effective_top_surface_contoning_supersampled_cells_enabled() && top_surface_contoning_polygonize_color_regions_enabled == rhs.top_surface_contoning_polygonize_color_regions_enabled && + effective_top_surface_contoning_partition_color_regions_enabled() == + rhs.effective_top_surface_contoning_partition_color_regions_enabled() && effective_top_surface_contoning_fast_mode_enabled() == rhs.effective_top_surface_contoning_fast_mode_enabled() && effective_top_surface_contoning_polygonization_mode() == rhs.effective_top_surface_contoning_polygonization_mode() && TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(top_surface_contoning_polygonize_resolution) == @@ -2216,6 +2222,8 @@ std::string TextureMappingManager::serialize_entries() zone.effective_top_surface_contoning_supersampled_cells_enabled(); texture["top_surface_contoning_polygonize_color_regions_enabled"] = zone.top_surface_contoning_polygonize_color_regions_enabled; + texture["top_surface_contoning_partition_color_regions_enabled"] = + zone.effective_top_surface_contoning_partition_color_regions_enabled(); texture["top_surface_contoning_fast_mode_enabled"] = zone.effective_top_surface_contoning_fast_mode_enabled(); texture["top_surface_contoning_polygonization_mode"] = @@ -2520,7 +2528,7 @@ void TextureMappingManager::load_entries(const std::string &serialized, flat_surface_infill_mode_it->get() : TextureMappingZone::DefaultTopSurfaceContoningFlatSurfaceInfillMode, int(TextureMappingZone::ContoningFlatSurfaceInfillDefault), - int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary)); + int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair)); zone.top_surface_contoning_layer_phase_enabled = texture.value("top_surface_contoning_layer_phase_enabled", TextureMappingZone::DefaultTopSurfaceContoningLayerPhaseEnabled); @@ -2536,6 +2544,9 @@ void TextureMappingManager::load_entries(const std::string &serialized, zone.top_surface_contoning_polygonize_color_regions_enabled = texture.value("top_surface_contoning_polygonize_color_regions_enabled", TextureMappingZone::DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled); + zone.top_surface_contoning_partition_color_regions_enabled = + texture.value("top_surface_contoning_partition_color_regions_enabled", + TextureMappingZone::DefaultTopSurfaceContoningPartitionColorRegionsEnabled); zone.top_surface_contoning_fast_mode_enabled = texture.value("top_surface_contoning_fast_mode_enabled", TextureMappingZone::DefaultTopSurfaceContoningFastModeEnabled); diff --git a/src/libslic3r/TextureMapping.hpp b/src/libslic3r/TextureMapping.hpp index 21e084e3e0c..44ff57ae4d3 100644 --- a/src/libslic3r/TextureMapping.hpp +++ b/src/libslic3r/TextureMapping.hpp @@ -89,7 +89,8 @@ struct TextureMappingZone ContoningFlatSurfaceInfillBoundarySkinVariable = 4, ContoningFlatSurfaceInfillSpiral = 5, ContoningFlatSurfaceInfillBoundarySkinHybrid = 6, - ContoningFlatSurfaceInfillRectilinearWithBoundary = 7 + ContoningFlatSurfaceInfillRectilinearWithBoundary = 7, + ContoningFlatSurfaceInfillRectilinearWithRepair = 8 }; enum TopSurfaceContoningColorPredictionMode : uint8_t { @@ -215,12 +216,13 @@ struct TextureMappingZone static constexpr bool DefaultTopSurfaceContoningRecolorSurroundingPerimeters = false; static constexpr int DefaultTopSurfaceContoningPerimeterMode = int(ContoningPerimeterDividedLine); static constexpr int DefaultTopSurfaceContoningFlatSurfaceInfillMode = int(ContoningFlatSurfaceInfillDefault); - static constexpr int SlicerDefaultTopSurfaceContoningFlatSurfaceInfillMode = int(ContoningFlatSurfaceInfillRectilinear); + static constexpr int SlicerDefaultTopSurfaceContoningFlatSurfaceInfillMode = int(ContoningFlatSurfaceInfillBoundarySkinVariable); static constexpr bool DefaultTopSurfaceContoningLayerPhaseEnabled = false; static constexpr bool DefaultTopSurfaceContoningVariedInfillAnglesEnabled = false; static constexpr bool DefaultTopSurfaceContoningBlueNoiseErrorDiffusionEnabled = false; static constexpr bool DefaultTopSurfaceContoningSupersampledCellsEnabled = false; static constexpr bool DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled = true; + static constexpr bool DefaultTopSurfaceContoningPartitionColorRegionsEnabled = false; static constexpr bool DefaultTopSurfaceContoningFastModeEnabled = true; static constexpr int DefaultTopSurfaceContoningPolygonizationMode = int(ContoningPolygonizationMidGaussianSharedChainFit); @@ -292,7 +294,7 @@ struct TextureMappingZone { const int clamped_mode = std::clamp(mode, int(ContoningFlatSurfaceInfillDefault), - int(ContoningFlatSurfaceInfillRectilinearWithBoundary)); + int(ContoningFlatSurfaceInfillRectilinearWithRepair)); if (ShowExperimentalTopSurfaceContoningOptions) return clamped_mode; return clamped_mode == int(ContoningFlatSurfaceInfillRectilinear) || @@ -361,6 +363,11 @@ struct TextureMappingZone return ShowExperimentalTopSurfaceContoningOptions ? value : true; } + static bool effective_top_surface_contoning_partition_color_regions_enabled(bool value) + { + return ShowExperimentalTopSurfaceContoningOptions ? value : false; + } + static constexpr int normalize_top_surface_contoning_polygonization_mode(int mode) { return mode == int(ContoningPolygonizationVectorBorderSharedGaussianPartition) || @@ -493,6 +500,7 @@ struct TextureMappingZone bool top_surface_contoning_blue_noise_error_diffusion_enabled = DefaultTopSurfaceContoningBlueNoiseErrorDiffusionEnabled; bool top_surface_contoning_supersampled_cells_enabled = DefaultTopSurfaceContoningSupersampledCellsEnabled; bool top_surface_contoning_polygonize_color_regions_enabled = DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled; + bool top_surface_contoning_partition_color_regions_enabled = DefaultTopSurfaceContoningPartitionColorRegionsEnabled; bool top_surface_contoning_fast_mode_enabled = DefaultTopSurfaceContoningFastModeEnabled; int top_surface_contoning_polygonization_mode = DefaultTopSurfaceContoningPolygonizationMode; int top_surface_contoning_polygonize_resolution = DefaultTopSurfaceContoningPolygonizeResolution; @@ -662,6 +670,12 @@ struct TextureMappingZone top_surface_contoning_fast_mode_enabled); } + bool effective_top_surface_contoning_partition_color_regions_enabled() const + { + return TextureMappingZone::effective_top_surface_contoning_partition_color_regions_enabled( + top_surface_contoning_partition_color_regions_enabled); + } + int effective_top_surface_contoning_polygonization_mode() const { return TextureMappingZone::effective_top_surface_contoning_polygonization_mode( @@ -718,6 +732,7 @@ struct TextureMappingZone top_surface_contoning_blue_noise_error_diffusion_enabled = false; top_surface_contoning_supersampled_cells_enabled = false; top_surface_contoning_fast_mode_enabled = true; + top_surface_contoning_partition_color_regions_enabled = true; } else if (top_surface_contoning_replace_top_perimeters_with_infill) { top_surface_contoning_recolor_surrounding_perimeters = false; } @@ -790,6 +805,7 @@ struct TextureMappingZone top_surface_contoning_blue_noise_error_diffusion_enabled = DefaultTopSurfaceContoningBlueNoiseErrorDiffusionEnabled; top_surface_contoning_supersampled_cells_enabled = DefaultTopSurfaceContoningSupersampledCellsEnabled; top_surface_contoning_polygonize_color_regions_enabled = DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled; + top_surface_contoning_partition_color_regions_enabled = DefaultTopSurfaceContoningPartitionColorRegionsEnabled; top_surface_contoning_fast_mode_enabled = DefaultTopSurfaceContoningFastModeEnabled; top_surface_contoning_polygonization_mode = DefaultTopSurfaceContoningPolygonizationMode; top_surface_contoning_polygonize_resolution = DefaultTopSurfaceContoningPolygonizeResolution; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 32231c4fc7b..de6b85c2514 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2450,6 +2450,7 @@ public: bool top_surface_contoning_blue_noise_error_diffusion_enabled, bool top_surface_contoning_supersampled_cells_enabled, bool top_surface_contoning_polygonize_color_regions_enabled, + bool top_surface_contoning_partition_color_regions_enabled, bool top_surface_contoning_fast_mode_enabled, int top_surface_contoning_polygonization_mode, int top_surface_contoning_polygonize_resolution, @@ -3119,12 +3120,15 @@ public: contoning_flat_infill_choices.Add(label); m_top_surface_contoning_flat_surface_infill_modes.push_back(mode); }; - add_contoning_flat_infill_choice(_L("Default (Rectilinear)"), + add_contoning_flat_infill_choice(_L("Default (Boundary Skin - variable width)"), int(TextureMappingZone::ContoningFlatSurfaceInfillDefault)); - add_contoning_flat_infill_choice(_L("Rectilinear"), + add_contoning_flat_infill_choice(_L("Rectilinear (faster to print, may leave small holes)"), int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinear)); + if (TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) + add_contoning_flat_infill_choice(_L("Rectilinear with repair"), + int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair)); if (!TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) - add_contoning_flat_infill_choice(_L("Boundary Skin (variable width) - not recommended"), + add_contoning_flat_infill_choice(_L("Boundary Skin (variable width)"), int(TextureMappingZone::ContoningFlatSurfaceInfillBoundarySkinVariable)); if (TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) { add_contoning_flat_infill_choice(_L("Concentric"), @@ -3345,6 +3349,17 @@ public: 0, wxEXPAND | wxTOP | wxBOTTOM, gap / 2); + if (TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) { + m_top_surface_contoning_partition_color_regions_checkbox = + new wxCheckBox(m_top_surface_contoning_checkboxes_panel, wxID_ANY, _L("Partition color regions before fill")); + m_top_surface_contoning_partition_color_regions_checkbox->SetValue(top_surface_contoning_partition_color_regions_enabled); + m_top_surface_contoning_partition_color_regions_checkbox->SetMinSize( + wxSize(-1, std::max(m_top_surface_contoning_partition_color_regions_checkbox->GetBestSize().GetHeight(), FromDIP(24)))); + contoning_checkboxes_root->Add(m_top_surface_contoning_partition_color_regions_checkbox, + 0, + wxEXPAND | wxTOP | wxBOTTOM, + gap / 2); + } m_top_surface_contoning_polygonize_resolution_panel = new wxPanel(m_top_surface_contoning_checkboxes_panel, wxID_ANY); auto *contoning_polygonize_resolution_row = new wxBoxSizer(wxHORIZONTAL); m_top_surface_contoning_polygonize_resolution_panel->SetSizer(contoning_polygonize_resolution_row); @@ -3353,17 +3368,9 @@ public: wxALIGN_CENTER_VERTICAL | wxRIGHT, gap); wxArrayString contoning_polygonize_resolution_choices; - contoning_polygonize_resolution_choices.Add(_L("1x")); - contoning_polygonize_resolution_choices.Add(_L("2x")); - contoning_polygonize_resolution_choices.Add(_L("3x")); - contoning_polygonize_resolution_choices.Add(_L("4x")); - contoning_polygonize_resolution_choices.Add(_L("8x (slow)")); m_top_surface_contoning_polygonize_resolution_choice = new wxChoice(m_top_surface_contoning_polygonize_resolution_panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, contoning_polygonize_resolution_choices); - const int polygonize_resolution = TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(top_surface_contoning_polygonize_resolution); - m_top_surface_contoning_polygonize_resolution_choice->SetSelection( - polygonize_resolution == 1 ? 0 : - (polygonize_resolution == 2 ? 1 : (polygonize_resolution == 3 ? 2 : (polygonize_resolution == 4 ? 3 : 4)))); + update_top_surface_contoning_polygonize_resolution_choices(top_surface_contoning_polygonize_resolution); contoning_polygonize_resolution_row->Add(m_top_surface_contoning_polygonize_resolution_choice, 1, wxEXPAND); contoning_checkboxes_root->Add(m_top_surface_contoning_polygonize_resolution_panel, 0, @@ -3459,6 +3466,11 @@ public: update_top_surface_image_options_visibility(true); }); } + if (m_top_surface_contoning_flat_surface_infill_choice != nullptr) { + m_top_surface_contoning_flat_surface_infill_choice->Bind(wxEVT_CHOICE, [this](wxCommandEvent &) { + update_top_surface_image_options_visibility(true); + }); + } if (m_top_surface_contoning_surface_scatter_checkbox != nullptr) { m_top_surface_contoning_surface_scatter_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) { queue_top_surface_contoning_message_update(true); @@ -3951,6 +3963,14 @@ public: m_top_surface_contoning_polygonize_color_regions_checkbox->GetValue() : TextureMappingZone::DefaultTopSurfaceContoningPolygonizeColorRegionsEnabled; } + bool top_surface_contoning_partition_color_regions_enabled() const + { + if (!TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) + return false; + return m_top_surface_contoning_partition_color_regions_checkbox != nullptr ? + m_top_surface_contoning_partition_color_regions_checkbox->GetValue() : + TextureMappingZone::DefaultTopSurfaceContoningPartitionColorRegionsEnabled; + } bool top_surface_contoning_fast_mode_enabled() const { if (!TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions) @@ -3971,14 +3991,9 @@ public: if (m_top_surface_contoning_polygonize_resolution_choice == nullptr) return TextureMappingZone::DefaultTopSurfaceContoningPolygonizeResolution; const int selection = m_top_surface_contoning_polygonize_resolution_choice->GetSelection(); - switch (selection) { - case 0: return 1; - case 1: return 2; - case 2: return 3; - case 3: return 4; - case 4: return 8; - default: return TextureMappingZone::DefaultTopSurfaceContoningPolygonizeResolution; - } + return selection >= 0 && size_t(selection) < m_top_surface_contoning_polygonize_resolution_values.size() ? + m_top_surface_contoning_polygonize_resolution_values[size_t(selection)] : + TextureMappingZone::DefaultTopSurfaceContoningPolygonizeResolution; } bool top_surface_contoning_surface_anchored_stacks_enabled() const { @@ -4927,6 +4942,44 @@ private: } } + void update_top_surface_contoning_polygonize_resolution_choices(int preferred_resolution) + { + if (m_top_surface_contoning_polygonize_resolution_choice == nullptr) + return; + + const bool allow_x8 = TextureMappingZone::ShowExperimentalTopSurfaceContoningOptions || + TextureMappingZone::effective_top_surface_contoning_flat_surface_infill_mode( + top_surface_contoning_flat_surface_infill_mode()) == + int(TextureMappingZone::ContoningFlatSurfaceInfillBoundarySkinVariable); + int resolution = TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(preferred_resolution); + if (!allow_x8 && resolution == 8) + resolution = 4; + + m_top_surface_contoning_polygonize_resolution_choice->Clear(); + m_top_surface_contoning_polygonize_resolution_values.clear(); + + auto append_resolution = [this](const wxString &label, int value) { + m_top_surface_contoning_polygonize_resolution_choice->Append(label); + m_top_surface_contoning_polygonize_resolution_values.push_back(value); + }; + + append_resolution(_L("1x"), 1); + append_resolution(_L("2x"), 2); + append_resolution(_L("3x"), 3); + append_resolution(_L("4x"), 4); + if (allow_x8) + append_resolution(_L("8x (slow)"), 8); + + int selection = 0; + for (size_t idx = 0; idx < m_top_surface_contoning_polygonize_resolution_values.size(); ++idx) { + if (m_top_surface_contoning_polygonize_resolution_values[idx] == resolution) { + selection = int(idx); + break; + } + } + m_top_surface_contoning_polygonize_resolution_choice->SetSelection(selection); + } + void update_top_surface_image_options_visibility(bool fit_dialog) { const bool enabled = @@ -4968,6 +5021,7 @@ private: m_top_surface_contoning_pattern_filaments_spin->Enable(contoning); if (m_top_surface_contoning_flat_surface_infill_choice != nullptr) m_top_surface_contoning_flat_surface_infill_choice->Enable(contoning); + update_top_surface_contoning_polygonize_resolution_choices(top_surface_contoning_polygonize_resolution()); if (m_top_surface_contoning_checkboxes_panel != nullptr) m_top_surface_contoning_checkboxes_panel->Show(contoning); if (m_top_surface_contoning_color_lower_surfaces_checkbox != nullptr) { @@ -5052,6 +5106,10 @@ private: m_top_surface_contoning_polygonize_color_regions_checkbox->Show(contoning); m_top_surface_contoning_polygonize_color_regions_checkbox->Enable(contoning); } + if (m_top_surface_contoning_partition_color_regions_checkbox != nullptr) { + m_top_surface_contoning_partition_color_regions_checkbox->Show(contoning); + m_top_surface_contoning_partition_color_regions_checkbox->Enable(contoning); + } const bool polygonize_color_regions = contoning && m_top_surface_contoning_polygonize_color_regions_checkbox != nullptr && @@ -5167,11 +5225,13 @@ private: wxCheckBox *m_top_surface_contoning_blue_noise_error_diffusion_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_supersampled_cells_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_polygonize_color_regions_checkbox {nullptr}; + wxCheckBox *m_top_surface_contoning_partition_color_regions_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_fast_mode_checkbox {nullptr}; wxPanel *m_top_surface_contoning_polygonization_mode_panel {nullptr}; wxChoice *m_top_surface_contoning_polygonization_mode_choice {nullptr}; wxPanel *m_top_surface_contoning_polygonize_resolution_panel {nullptr}; wxChoice *m_top_surface_contoning_polygonize_resolution_choice {nullptr}; + std::vector m_top_surface_contoning_polygonize_resolution_values; wxCheckBox *m_top_surface_contoning_surface_anchored_stacks_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_surface_anchored_stack_optimizations_checkbox {nullptr}; wxCheckBox *m_top_surface_contoning_beam_search_stack_expansion_checkbox {nullptr}; @@ -10235,6 +10295,7 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) updated.top_surface_contoning_blue_noise_error_diffusion_enabled, updated.top_surface_contoning_supersampled_cells_enabled, updated.top_surface_contoning_polygonize_color_regions_enabled, + updated.top_surface_contoning_partition_color_regions_enabled, updated.top_surface_contoning_fast_mode_enabled, updated.top_surface_contoning_polygonization_mode, updated.top_surface_contoning_polygonize_resolution, @@ -10321,6 +10382,8 @@ void Sidebar::update_texture_mapping_panel(bool sync_manager) dlg.top_surface_contoning_supersampled_cells_enabled(); updated.top_surface_contoning_polygonize_color_regions_enabled = dlg.top_surface_contoning_polygonize_color_regions_enabled(); + updated.top_surface_contoning_partition_color_regions_enabled = + dlg.top_surface_contoning_partition_color_regions_enabled(); updated.top_surface_contoning_fast_mode_enabled = dlg.top_surface_contoning_fast_mode_enabled(); updated.top_surface_contoning_polygonization_mode =