Skip to content

Commit

Permalink
fixes, switch to remove outliers on gcode preview (vol flow)
Browse files Browse the repository at this point in the history
  • Loading branch information
supermerill committed Feb 7, 2024
2 parents 843c421 + c583085 commit 3c0076e
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 47 deletions.
4 changes: 3 additions & 1 deletion src/libslic3r/AppConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,9 @@ void AppConfig::save()
// Returns "undefined" if the thread naming functionality is not supported by the operating system.
std::optional<std::string> current_thread_name = get_current_thread_name();
if (current_thread_name && *current_thread_name != "slic3r_main")
throw CriticalException("Calling AppConfig::save() from a worker thread!");
//in win11, it seems that the gui event thread isn't named 'slic3r_main'
BOOST_LOG_TRIVIAL(warning) << "AppConfig::save() from thread '" << *current_thread_name << "' instead of 'slic3r_main'\n";
//throw CriticalException("Calling AppConfig::save() from a worker thread!");
}

// The config is first written to a file with a PID suffix and then moved
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct SurfaceFillParams : FillParams
RETURN_COMPARE_NON_EQUAL(config->bridge_speed);
RETURN_COMPARE_NON_EQUAL(config->bridge_speed_internal);
RETURN_COMPARE_NON_EQUAL(config->gap_fill_speed);
RETURN_COMPARE_NON_EQUAL(config->print_extrusion_multiplier);
}
assert(*this == rhs);
return false;
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ void Layer::make_perimeters()
&& config.perimeter_loop_seam == other_config.perimeter_loop_seam
&& config.perimeter_overlap == other_config.perimeter_overlap
&& config.perimeter_speed == other_config.perimeter_speed // it os mandatory? can't this be set at gcode.cpp?
&& config.print_extrusion_multiplier == other_config.print_extrusion_multiplier
&& config.small_perimeter_speed == other_config.small_perimeter_speed
&& config.small_perimeter_min_length == other_config.small_perimeter_min_length
&& config.small_perimeter_max_length == other_config.small_perimeter_max_length
Expand Down
38 changes: 30 additions & 8 deletions src/libslic3r/PerimeterGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3056,6 +3056,25 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
std::vector<ExtrusionPath> paths;
const Point* first_point = nullptr;
coordf_t resolution_sqr;
//TODO real travel with role & width
void ensure_travel_to(const Point &pt) {
assert(!paths.empty());
Point last_point = paths.back().last_point();
if (last_point != pt) {
if (last_point.distance_to_square(pt) < resolution_sqr) {
paths.back().polyline.set_points().back() = pt;
} else {
//add travel
ExtrusionPath travel(paths.back().role(), false);
travel.width = paths.back().width;
travel.height = paths.back().height;
travel.mm3_per_mm = 0;
travel.polyline.append(last_point);
travel.polyline.append(pt);
paths.push_back(travel);
}
}
}
virtual void use(ExtrusionPath &path) override {
//ensure the loop is continue.
if (first_point != nullptr) {
Expand Down Expand Up @@ -3256,16 +3275,19 @@ void PerimeterGenerator::_merge_thin_walls(ExtrusionEntityCollection &extrusions
change_flow.first_point = &point;
change_flow.percent_extrusion = 1;
change_flow.use(tws);
//add move back
// ChangeFlow added the first move if needed, now add the second
change_flow.ensure_travel_to(point);
//add move around
searcher.search_result.loop->paths.insert(searcher.search_result.loop->paths.begin() + idx_path_to_add,
change_flow.paths.begin(), change_flow.paths.end());
//add move to
if (poly_after.first_point() != point) {
assert(poly_after.first_point().coincides_with_epsilon(point));
assert(searcher.search_result.loop->paths.size() > idx_path_to_add);
assert(poly_after.first_point().coincides_with_epsilon(searcher.search_result.loop->paths[idx_path_to_add].polyline.set_points().front()));
searcher.search_result.loop->paths[idx_path_to_add].polyline.set_points().front() = poly_after.first_point();
}
////add move to -> ??? i don't remember why i wrote that, so here it's removed.
assert(poly_after.first_point() == point);
//if (poly_after.first_point() != point) {
// assert(poly_after.first_point().coincides_with_epsilon(point));
// assert(searcher.search_result.loop->paths.size() > idx_path_to_add);
// assert(poly_after.first_point().coincides_with_epsilon(searcher.search_result.loop->paths[idx_path_to_add].polyline.set_points().front()));
// searcher.search_result.loop->paths[idx_path_to_add].polyline.set_points().front() = poly_after.first_point();
//}
#if _DEBUG
searcher.search_result.loop->visit(LoopAssertVisitor{});
#endif
Expand Down
159 changes: 134 additions & 25 deletions src/slic3r/GUI/GCodeViewer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,85 @@ void GCodeViewer::TBuffer::add_path(const GCodeProcessorResult::MoveVertex& move
}


float GCodeViewer::Extrusions::Range::step_size(bool log) const
void GCodeViewer::Extrusions::Range::update_from(const float value)
{
if (value != max && value != min)
++count;
min = std::min(min, value);
max = std::max(max, value);

total_count++;
// don't keep outliers
uint8_t idx = std::min(19, std::max(0, int(9 + log2(min))));
counts[idx]++;
mins[idx] = std::min(mins[idx], value);
maxs[idx] = std::max(maxs[idx], value);
}
void GCodeViewer::Extrusions::Range::reset()
{
min = FLT_MAX;
max = -FLT_MAX;
count = 0;
total_count = 0;
for (size_t idx = 0; idx < 20; idx++) {
counts[idx] = 0;
maxs[idx] = -FLT_MAX;
mins[idx] = FLT_MAX;
}
}

float GCodeViewer::Extrusions::Range::get_max_no_outliers(float ratio_outlier) const
{
size_t min_number = ratio_outlier * total_count / 20;
for (size_t idx = 19; idx < 20; --idx) {
if (counts[idx] > min_number) {
return maxs[idx];
}
}
assert(false);
return max;
}

float GCodeViewer::Extrusions::Range::get_min_no_outliers(float ratio_outlier) const
{
size_t min_number = ratio_outlier * total_count / 20;
for (size_t idx = 0; idx < 20; ++idx) {
if (counts[idx] > min_number) {
return mins[idx];
}
}
assert(false);
return min;
}

float GCodeViewer::Extrusions::Range::step_size_no_outliers(float ratio_outlier, bool log) const
{
return step_size(get_min_no_outliers(ratio_outlier), get_max_no_outliers(ratio_outlier), log);
}

GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at_no_outliers(float value,
float ratio_outlier,
bool log) const
{
return get_color_at(get_min_no_outliers(ratio_outlier), get_max_no_outliers(ratio_outlier), value, log);
}

float GCodeViewer::Extrusions::Range::step_size(float min, float max, bool log)
{
if (log)
{
float min_range = min;
if (min_range == 0)
min_range = 0.001f;
return (std::log(max / min_range) / (static_cast<float>(Range_Colors.size()) - 1.0f));
return (std::log(max / min_range) / (static_cast<float>(GCodeViewer::Range_Colors.size()) - 1.0f));
} else
return (max - min) / (static_cast<float>(Range_Colors.size()) - 1.0f);
return (max - min) / (static_cast<float>(GCodeViewer::Range_Colors.size()) - 1.0f);
}

GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value, bool log) const
GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float min, float max, float value, bool log)
{
// Input value scaled to the colors range
const float step = step_size(log);
const float step = step_size(min, max, log);
float global_t;
if (log)
{
Expand Down Expand Up @@ -2265,16 +2328,26 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
switch (m_view_type)
{
case EViewType::FeatureType: { color = Extrusion_Role_Colors[static_cast<unsigned int>(path.role)]; break; }
case EViewType::Height: { color = m_extrusions.ranges.height.get_color_at(path.height); break; }
case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at(path.width); break; }
case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at(path.feedrate); break; }
case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at(path.fan_speed); break; }
case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at(path.temperature); break; }
case EViewType::LayerTime: { color = m_extrusions.ranges.layer_duration.get_color_at(path.layer_time); break; }
case EViewType::LayerTimeLog: { color = m_extrusions.ranges.layer_duration.get_color_at(path.layer_time, true); break; }
case EViewType::Chronology: { color = m_extrusions.ranges.elapsed_time.get_color_at(path.elapsed_time); break; }
case EViewType::VolumetricRate: { color = m_extrusions.ranges.volumetric_rate.get_color_at(path.volumetric_rate); break; }
case EViewType::VolumetricFlow: { color = m_extrusions.ranges.volumetric_flow.get_color_at(path.volumetric_flow); break; }
case EViewType::Height: { color = m_extrusions.ranges.height.get_color_at_with_outliers(path.height); break; }
case EViewType::Width: { color = m_extrusions.ranges.width.get_color_at_with_outliers(path.width); break; }
case EViewType::Feedrate: { color = m_extrusions.ranges.feedrate.get_color_at_with_outliers(path.feedrate); break; }
case EViewType::FanSpeed: { color = m_extrusions.ranges.fan_speed.get_color_at_with_outliers(path.fan_speed); break; }
case EViewType::Temperature: { color = m_extrusions.ranges.temperature.get_color_at_with_outliers(path.temperature); break; }
case EViewType::LayerTime: { color = m_extrusions.ranges.layer_duration.get_color_at_with_outliers(path.layer_time); break; }
case EViewType::LayerTimeLog: { color = m_extrusions.ranges.layer_duration.get_color_at_with_outliers(path.layer_time, true); break; }
case EViewType::Chronology: { color = m_extrusions.ranges.elapsed_time.get_color_at_with_outliers(path.elapsed_time); break; }
case EViewType::VolumetricRate: {
color = m_outliers_allowed ?
m_extrusions.ranges.volumetric_rate.get_color_at_with_outliers(path.volumetric_rate) :
m_extrusions.ranges.volumetric_rate.get_color_at_no_outliers(path.volumetric_rate);
break;
}
case EViewType::VolumetricFlow: {
color = m_outliers_allowed ?
m_extrusions.ranges.volumetric_flow.get_color_at_with_outliers(path.volumetric_flow) :
m_extrusions.ranges.volumetric_flow.get_color_at_no_outliers(path.volumetric_flow);
break;
}
case EViewType::Tool: { color = m_tool_colors[path.extruder_id]; break; }
case EViewType::Filament: { color = m_filament_colors[path.extruder_id]; break; }
case EViewType::ColorPrint: {
Expand Down Expand Up @@ -3129,6 +3202,7 @@ void GCodeViewer::render_legend(float& legend_height)
const PrintEstimatedStatistics::Mode& time_mode = m_print_statistics.modes[static_cast<size_t>(m_time_estimate_mode)];
bool show_estimated_time = time_mode.time > 0.0f && (m_view_type == EViewType::FeatureType ||
(m_view_type == EViewType::ColorPrint && !time_mode.custom_gcode_times.empty()));
bool show_switch_show_outliers = (m_view_type == EViewType::VolumetricFlow || m_view_type == EViewType::VolumetricRate);

const float icon_size = ImGui::GetTextLineHeight();
const float percent_bar_size = 2.0f * ImGui::GetTextLineHeight();
Expand Down Expand Up @@ -3229,7 +3303,7 @@ void GCodeViewer::render_legend(float& legend_height)
ImGui::PopStyleVar();
};

auto append_range = [append_item](const Extrusions::Range& range, unsigned int decimals) {
auto append_range = [append_item](const Extrusions::Range& range, unsigned int decimals, bool ignore_outliers) {
auto append_range_item = [append_item](int i, float value, unsigned int decimals) {
char buf[1024];
::sprintf(buf, "%.*f", decimals, value);
Expand All @@ -3244,7 +3318,7 @@ void GCodeViewer::render_legend(float& legend_height)
append_range_item(0, range.min, decimals);
}
else {
const float step_size = range.step_size();
const float step_size = ignore_outliers ? range.step_size_no_outliers() : range.step_size_with_outliers();
for (int i = static_cast<int>(Range_Colors.size()) - 1; i >= 0; --i) {
append_range_item(i, range.min + static_cast<float>(i) * step_size, decimals);
}
Expand All @@ -3259,7 +3333,7 @@ void GCodeViewer::render_legend(float& legend_height)
append_item(EItemType::Rect, Range_Colors[static_cast<int>(Range_Colors.size()) - 1], get_time_dhms(range.max));
append_item(EItemType::Rect, Range_Colors[0], get_time_dhms(range.min));
} else {
float step_size = range.step_size(is_log);
float step_size = range.step_size_with_outliers(is_log);
for (int i = static_cast<int>(Range_Colors.size()) - 1; i >= 0; --i) {
if (!is_log)
append_item(EItemType::Rect, Range_Colors[i], get_time_dhms(range.min + static_cast<float>(i) * step_size));
Expand Down Expand Up @@ -3487,16 +3561,16 @@ void GCodeViewer::render_legend(float& legend_height)
}
break;
}
case EViewType::Height: { append_range(m_extrusions.ranges.height, 3); break; }
case EViewType::Width: { append_range(m_extrusions.ranges.width, 3); break; }
case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 1); break; }
case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0); break; }
case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0); break; }
case EViewType::Height: { append_range(m_extrusions.ranges.height, 3, false); break; }
case EViewType::Width: { append_range(m_extrusions.ranges.width, 3, false); break; }
case EViewType::Feedrate: { append_range(m_extrusions.ranges.feedrate, 1, false); break; }
case EViewType::FanSpeed: { append_range(m_extrusions.ranges.fan_speed, 0, false); break; }
case EViewType::Temperature: { append_range(m_extrusions.ranges.temperature, 0, false); break; }
case EViewType::LayerTime: { append_range_time(m_extrusions.ranges.layer_duration, false); break; }
case EViewType::LayerTimeLog: { append_range_time(m_extrusions.ranges.layer_duration, true); break; }
case EViewType::Chronology: { append_range_time(m_extrusions.ranges.elapsed_time, false); break; }
case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3); break; }
case EViewType::VolumetricFlow: { append_range(m_extrusions.ranges.volumetric_flow, 3); break; }
case EViewType::VolumetricRate: { append_range(m_extrusions.ranges.volumetric_rate, 3, !m_outliers_allowed); break; }
case EViewType::VolumetricFlow: { append_range(m_extrusions.ranges.volumetric_flow, 3, !m_outliers_allowed); break; }
case EViewType::Tool:
{
// shows only extruders actually used
Expand Down Expand Up @@ -3906,6 +3980,41 @@ void GCodeViewer::render_legend(float& legend_height)
}
}
}

if (show_switch_show_outliers) {
ImGui::Spacing();
const bool outliers_allowed = m_outliers_allowed;
if (!outliers_allowed)
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.3333f);

ImDrawList *draw_list = ImGui::GetWindowDrawList();
ImVec2 pos = ImGui::GetCursorScreenPos();

// draw text
ImGui::SameLine();
if (ImGui::MenuItem((_u8L("Allow outliers")).c_str())) {
m_outliers_allowed = !m_outliers_allowed;
// update buffers' render paths
refresh_render_paths(false, false);
wxGetApp().plater()->update_preview_moves_slider();
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
wxGetApp().plater()->update_preview_bottom_toolbar();
} else {
// show tooltip
if (ImGui::IsItemHovered()) {
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
ImGui::BeginTooltip();
imgui.text(outliers_allowed ? _u8L("Click to disable") : _u8L("Click to enable"));
ImGui::EndTooltip();
ImGui::PopStyleColor();

// to avoid the tooltip to change size when moving the mouse
imgui.set_requires_extra_frame();
}
}
if (!outliers_allowed)
ImGui::PopStyleVar();
}

// total estimated printing time section
if (show_estimated_time) {
Expand Down
26 changes: 15 additions & 11 deletions src/slic3r/GUI/GCodeViewer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,19 +390,22 @@ class GCodeViewer
float min;
float max;
unsigned int count;
uint32_t counts[20];
uint64_t total_count;
float maxs[20];
float mins[20];

Range() { reset(); }

void update_from(const float value) {
if (value != max && value != min)
++count;
min = std::min(min, value);
max = std::max(max, value);
}
void reset() { min = FLT_MAX; max = -FLT_MAX; count = 0; }

float step_size(bool log = false) const;
Color get_color_at(float value, bool log = false) const;
void update_from(const float value);
void reset();
float get_max_no_outliers(float ratio_outlier = 0.01) const;
float get_min_no_outliers(float ratio_outlier = 0.01) const;
float step_size_no_outliers(float ratio_outlier = 0.01, bool log = false) const;
Color get_color_at_no_outliers(float value, float ratio_outlier = 0.01, bool log = false) const;
float step_size_with_outliers(float ratio_outlier = 0.01, bool log = false) const { return step_size(min, max, log); }
Color get_color_at_with_outliers(float value, float ratio_outlier = 0.01, bool log = false) const { return get_color_at(min, max, value, log); }
static float step_size(float min, float max, bool log = false);
static Color get_color_at(float min, float max, float value, bool log = false);
};

struct Ranges
Expand Down Expand Up @@ -728,6 +731,7 @@ class GCodeViewer
Shells m_shells;
EViewType m_view_type{ EViewType::FeatureType };
bool m_legend_enabled{ true };
bool m_outliers_allowed{ true };
PrintEstimatedStatistics m_print_statistics;
PrintEstimatedStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedStatistics::ETimeMode::Normal };
#if ENABLE_GCODE_VIEWER_STATISTICS
Expand Down
4 changes: 2 additions & 2 deletions version.inc
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ set(SLIC3R_APP_KEY "SuperSlicer")
set(SLIC3R_APP_CMD "superslicer")
# versions
set(SLIC3R_VERSION "2.5.59")
set(SLIC3R_VERSION_FULL "2.5.59.6")
set(SLIC3R_VERSION_FULL "2.5.59.7")
set(SLIC3R_BUILD_ID "${SLIC3R_APP_KEY}_${SLIC3R_VERSION_FULL}+UNKNOWN")
set(SLIC3R_RC_VERSION "2,5,59,6")
set(SLIC3R_RC_VERSION "2,5,59,7")
set(SLIC3R_RC_VERSION_DOTS "${SLIC3R_VERSION_FULL}")

# Same as the slicer name but for gcodeviewer
Expand Down

0 comments on commit 3c0076e

Please sign in to comment.