Allow top-surface min and max line width to be equal

This commit is contained in:
sentientstardust
2026-06-24 01:21:11 +01:00
parent b371c68fbf
commit 1ff08f8614
6 changed files with 92 additions and 47 deletions

View File

@@ -6127,7 +6127,8 @@ static std::optional<TopSurfaceImageContoningSourceContext> top_surface_image_co
top_surface_image_contoning_texture_sample_pitch_mm(plan),
raw_top_surface_depth_override,
TextureMappingZone::DefaultFilamentOverhangContrastPct,
TextureMappingRawSurfaceUsage::Flat);
TextureMappingRawSurfaceUsage::Flat,
true);
if (!offset_context)
return std::nullopt;
@@ -9301,12 +9302,12 @@ static std::vector<TopSurfaceImageRegionPlan> top_surface_image_region_plans(
top_surface_image_components_bottom_to_top(*zone, print_config, components));
if (plan.components_bottom_to_top.empty())
continue;
plan.max_width_mm = std::clamp(zone->top_surface_image_max_line_width_mm,
TextureMappingZone::MinTopSurfaceImageLineWidthMm,
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
plan.min_width_mm = std::clamp(zone->top_surface_image_min_line_width_mm,
TextureMappingZone::MinTopSurfaceImageLineWidthMm,
plan.max_width_mm);
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
plan.max_width_mm = std::clamp(zone->top_surface_image_max_line_width_mm,
plan.min_width_mm,
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
plan.fixed_coloring = zone->top_surface_image_fixed_coloring_filaments_active();
plan.color_upper_surfaces = zone->top_surface_contoning_colors_upper_surfaces();
plan.color_lower_surfaces = zone->top_surface_contoning_colors_lower_surfaces();

View File

@@ -2835,16 +2835,18 @@ std::string TextureMappingManager::serialize_entries()
texture["top_surface_image_printing_enabled"] = zone.top_surface_image_printing_enabled;
texture["top_surface_image_printing_method"] =
top_surface_image_printing_method_name(zone.top_surface_image_printing_method);
const float top_surface_max_width =
std::clamp(finite_or(zone.top_surface_image_max_line_width_mm,
TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm),
TextureMappingZone::MinTopSurfaceImageLineWidthMm,
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
texture["top_surface_image_min_line_width_mm"] =
const float top_surface_min_width =
std::clamp(finite_or(zone.top_surface_image_min_line_width_mm,
TextureMappingZone::DefaultTopSurfaceImageMinLineWidthMm),
TextureMappingZone::MinTopSurfaceImageLineWidthMm,
top_surface_max_width);
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
const float top_surface_max_width =
std::clamp(finite_or(zone.top_surface_image_max_line_width_mm,
TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm),
top_surface_min_width,
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
texture["top_surface_image_min_line_width_mm"] =
top_surface_min_width;
texture["top_surface_image_max_line_width_mm"] = top_surface_max_width;
texture["top_surface_image_colored_top_layers"] =
clamp_int(zone.top_surface_image_colored_top_layers,
@@ -3150,18 +3152,18 @@ void TextureMappingManager::load_entries(const std::string &serialized,
top_surface_image_printing_method_from_name(
texture.value("top_surface_image_printing_method",
top_surface_image_printing_method_name(TextureMappingZone::DefaultTopSurfaceImagePrintingMethod)));
zone.top_surface_image_max_line_width_mm =
std::clamp(finite_or(texture.value("top_surface_image_max_line_width_mm",
TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm),
TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm),
TextureMappingZone::MinTopSurfaceImageLineWidthMm,
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
zone.top_surface_image_min_line_width_mm =
std::clamp(finite_or(texture.value("top_surface_image_min_line_width_mm",
TextureMappingZone::DefaultTopSurfaceImageMinLineWidthMm),
TextureMappingZone::DefaultTopSurfaceImageMinLineWidthMm),
TextureMappingZone::MinTopSurfaceImageLineWidthMm,
zone.top_surface_image_max_line_width_mm);
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
zone.top_surface_image_max_line_width_mm =
std::clamp(finite_or(texture.value("top_surface_image_max_line_width_mm",
TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm),
TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm),
zone.top_surface_image_min_line_width_mm,
TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
zone.top_surface_image_colored_top_layers =
clamp_int(texture.value("top_surface_image_colored_top_layers",
TextureMappingZone::DefaultTopSurfaceImageColoredTopLayers),

View File

@@ -202,7 +202,7 @@ struct TextureMappingZone
static constexpr bool DefaultTopVisiblePerimeterRecolorPointSampling = true;
static constexpr bool DefaultTopSurfaceImagePrintingEnabled = false;
static constexpr int DefaultTopSurfaceImagePrintingMethod = int(TopSurfaceImageContoning);
static constexpr float MinTopSurfaceImageLineWidthMm = 0.32f;
static constexpr float MinTopSurfaceImageLineWidthMm = 0.05f;
static constexpr float MaxTopSurfaceImageLineWidthMm = 0.80f;
static constexpr float DefaultTopSurfaceImageMinLineWidthMm = 0.32f;
static constexpr float DefaultTopSurfaceImageMaxLineWidthMm = 0.64f;

View File

@@ -3476,7 +3476,8 @@ std::optional<TextureMappingOffsetContext> build_texture_mapping_offset_context_
std::optional<float> texture_sample_pitch_mm_override,
std::optional<int> raw_top_surface_depth_override,
std::optional<float> filament_overhang_contrast_pct_override,
TextureMappingRawSurfaceUsage raw_surface_usage)
TextureMappingRawSurfaceUsage raw_surface_usage,
bool allow_zero_width_delta_for_sampling)
{
const Print *print = print_object.print();
if (print == nullptr)
@@ -3637,7 +3638,8 @@ std::optional<TextureMappingOffsetContext> build_texture_mapping_offset_context_
const float max_width_delta_mm = std::max(0.f, base_outer_width_mm - safe_min_gradient_width_mm);
const float effective_max_width_delta_mm = max_width_delta_mm * global_strength_factor;
const float max_width_delta_limit_mm = std::min(effective_max_width_delta_mm, 2.f * max_allowed_distance_mm);
if (!std::isfinite(max_width_delta_limit_mm) || max_width_delta_limit_mm <= EPSILON)
if (!std::isfinite(max_width_delta_limit_mm) ||
(max_width_delta_limit_mm <= EPSILON && !allow_zero_width_delta_for_sampling))
return std::nullopt;
const bool dithering_enabled = zone.dithering_enabled && !raw_texture_mapping_mode;

View File

@@ -128,7 +128,8 @@ std::optional<TextureMappingOffsetContext> build_texture_mapping_offset_context_
std::optional<float> texture_sample_pitch_mm_override = std::nullopt,
std::optional<int> raw_top_surface_depth_override = std::nullopt,
std::optional<float> filament_overhang_contrast_pct_override = std::nullopt,
TextureMappingRawSurfaceUsage raw_surface_usage = TextureMappingRawSurfaceUsage::Side);
TextureMappingRawSurfaceUsage raw_surface_usage = TextureMappingRawSurfaceUsage::Side,
bool allow_zero_width_delta_for_sampling = false);
std::vector<float> sample_weight_field_components(const TextureMappingOffsetWeightField &weight_field,
float x_mm,

View File

@@ -3140,6 +3140,14 @@ public:
0,
wxALIGN_CENTER_VERTICAL | wxRIGHT,
gap);
const double initial_top_surface_min_line_width_mm =
std::clamp(double(top_surface_image_min_line_width_mm),
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm));
const double initial_top_surface_max_line_width_mm =
std::clamp(double(top_surface_image_max_line_width_mm),
initial_top_surface_min_line_width_mm,
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm));
m_top_surface_image_min_line_width_spin =
new wxSpinCtrlDouble(top_surface_page,
wxID_ANY,
@@ -3148,10 +3156,8 @@ public:
wxSize(FromDIP(84), -1),
wxSP_ARROW_KEYS | wxALIGN_RIGHT | wxTE_PROCESS_ENTER,
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm),
std::clamp(double(top_surface_image_min_line_width_mm),
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm)),
initial_top_surface_max_line_width_mm,
initial_top_surface_min_line_width_mm,
0.01);
m_top_surface_image_min_line_width_spin->SetDigits(2);
top_surface_width_row->Add(m_top_surface_image_min_line_width_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2);
@@ -3166,11 +3172,9 @@ public:
wxDefaultPosition,
wxSize(FromDIP(84), -1),
wxSP_ARROW_KEYS | wxALIGN_RIGHT | wxTE_PROCESS_ENTER,
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
initial_top_surface_min_line_width_mm,
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm),
std::clamp(double(top_surface_image_max_line_width_mm),
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm)),
initial_top_surface_max_line_width_mm,
0.01);
m_top_surface_image_max_line_width_spin->SetDigits(2);
top_surface_width_row->Add(m_top_surface_image_max_line_width_spin, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, gap / 2);
@@ -3715,6 +3719,22 @@ public:
update_top_surface_image_options_visibility(true);
});
}
if (m_top_surface_image_min_line_width_spin != nullptr) {
m_top_surface_image_min_line_width_spin->Bind(wxEVT_SPINCTRLDOUBLE, [this](wxSpinDoubleEvent &) {
enforce_top_surface_image_line_width_order(m_top_surface_image_min_line_width_spin);
});
m_top_surface_image_min_line_width_spin->Bind(wxEVT_TEXT, [this](wxCommandEvent &) {
enforce_top_surface_image_line_width_order(m_top_surface_image_min_line_width_spin);
});
}
if (m_top_surface_image_max_line_width_spin != nullptr) {
m_top_surface_image_max_line_width_spin->Bind(wxEVT_SPINCTRLDOUBLE, [this](wxSpinDoubleEvent &) {
enforce_top_surface_image_line_width_order(m_top_surface_image_max_line_width_spin);
});
m_top_surface_image_max_line_width_spin->Bind(wxEVT_TEXT, [this](wxCommandEvent &) {
enforce_top_surface_image_line_width_order(m_top_surface_image_max_line_width_spin);
});
}
m_top_surface_image_printing_enabled_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &) {
update_top_surface_image_options_visibility(true);
});
@@ -4013,25 +4033,25 @@ public:
}
float top_surface_image_min_line_width_mm() const
{
const double max_width = m_top_surface_image_max_line_width_spin != nullptr ?
m_top_surface_image_max_line_width_spin->GetValue() :
double(TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm);
const double value = m_top_surface_image_min_line_width_spin != nullptr ?
m_top_surface_image_min_line_width_spin->GetValue() :
double(TextureMappingZone::DefaultTopSurfaceImageMinLineWidthMm);
return float(std::clamp(value,
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
std::clamp(max_width,
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm))));
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm)));
}
float top_surface_image_max_line_width_mm() const
{
const double min_width = m_top_surface_image_min_line_width_spin != nullptr ?
m_top_surface_image_min_line_width_spin->GetValue() :
double(TextureMappingZone::DefaultTopSurfaceImageMinLineWidthMm);
const double value = m_top_surface_image_max_line_width_spin != nullptr ?
m_top_surface_image_max_line_width_spin->GetValue() :
double(TextureMappingZone::DefaultTopSurfaceImageMaxLineWidthMm);
return float(std::clamp(value,
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
std::clamp(min_width,
double(TextureMappingZone::MinTopSurfaceImageLineWidthMm),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm)),
double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm)));
}
int top_surface_image_colored_top_layers() const
@@ -5557,16 +5577,12 @@ private:
if (m_top_surface_contoning_polygonize_resolution_choice == nullptr)
return;
const int effective_flat_mode = TextureMappingZone::effective_top_surface_contoning_flat_surface_infill_mode(
top_surface_contoning_flat_surface_infill_mode());
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) ||
TextureMappingZone::effective_top_surface_contoning_flat_surface_infill_mode(
top_surface_contoning_flat_surface_infill_mode()) ==
int(TextureMappingZone::ContoningFlatSurfaceInfillBoundarySkinVariableOverlap) ||
TextureMappingZone::effective_top_surface_contoning_flat_surface_infill_mode(
top_surface_contoning_flat_surface_infill_mode()) ==
int(TextureMappingZone::ContoningFlatSurfaceInfillAdaptiveLines);
(effective_flat_mode != int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinear) &&
effective_flat_mode != int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithBoundary) &&
effective_flat_mode != int(TextureMappingZone::ContoningFlatSurfaceInfillRectilinearWithRepair));
int resolution = TextureMappingZone::normalize_top_surface_contoning_polygonize_resolution(preferred_resolution);
if (!allow_x8 && resolution == 8)
resolution = 4;
@@ -5596,6 +5612,29 @@ private:
m_top_surface_contoning_polygonize_resolution_choice->SetSelection(selection);
}
void enforce_top_surface_image_line_width_order(wxSpinCtrlDouble *changed_spin)
{
if (m_top_surface_image_min_line_width_spin == nullptr ||
m_top_surface_image_max_line_width_spin == nullptr)
return;
const double lower = double(TextureMappingZone::MinTopSurfaceImageLineWidthMm);
const double upper = double(TextureMappingZone::MaxTopSurfaceImageLineWidthMm);
double min_width = std::clamp(m_top_surface_image_min_line_width_spin->GetValue(), lower, upper);
double max_width = std::clamp(m_top_surface_image_max_line_width_spin->GetValue(), lower, upper);
if (changed_spin == m_top_surface_image_max_line_width_spin)
max_width = std::max(max_width, min_width);
else
min_width = std::min(min_width, max_width);
m_top_surface_image_min_line_width_spin->SetRange(lower, max_width);
m_top_surface_image_max_line_width_spin->SetRange(min_width, upper);
if (m_top_surface_image_min_line_width_spin->GetValue() != min_width)
m_top_surface_image_min_line_width_spin->SetValue(min_width);
if (m_top_surface_image_max_line_width_spin->GetValue() != max_width)
m_top_surface_image_max_line_width_spin->SetValue(max_width);
}
void update_top_surface_image_options_visibility(bool fit_dialog)
{
const bool enabled =