ENH: add wrapping detection

jira: STUDIO-13192
Change-Id: I0fb5692b18cdb3b7af624a831dcfb0f635b165f0
(cherry picked from commit 89a8b6ea5e34340cba3750416ce3100dcc39f5c2)
(cherry picked from commit 50bc8c10a7b4ddc0b2dfe9cbab438b9d307b7fc0)
This commit is contained in:
zhimin.zeng
2025-07-05 14:52:21 +08:00
committed by Noisyfox
parent 070a8e62a1
commit 1ccdf7b43b
31 changed files with 323 additions and 50 deletions

View File

@@ -36,6 +36,7 @@
#include "nlohmann/json.hpp"
#include "GCode/ConflictChecker.hpp"
#include "ParameterUtils.hpp"
#include <codecvt>
@@ -136,6 +137,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"inner_wall_acceleration",
"initial_layer_acceleration",
"top_surface_acceleration",
"enable_wrapping_detection",
"bridge_acceleration",
"travel_acceleration",
"sparse_infill_acceleration",
@@ -150,6 +152,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"gcode_add_line_number",
"layer_change_gcode",
"time_lapse_gcode",
"wrapping_detection_gcode",
"fan_min_speed",
"fan_max_speed",
"printable_height",
@@ -919,6 +922,13 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
std::for_each(exclude_polys.begin(), exclude_polys.end(),
[&print_origin](Polygon& p) { p.translate(scale_(print_origin.x()), scale_(print_origin.y())); });
Pointfs wrapping_detection_area = get_wrapping_detection_area(print_config.wrapping_detection_path.values, print_config.extruder_clearance_radius.value / 2);
Polygon wrapping_poly;
for (size_t i = 0; i < wrapping_detection_area.size(); ++i) {
auto pt = wrapping_detection_area[i];
wrapping_poly.points.emplace_back(scale_(pt.x() + print_origin.x()), scale_(pt.y() + print_origin.y()));
}
std::map<const PrintInstance*, Polygon> map_model_object_to_convex_hull;
// sequential_print_horizontal_clearance_valid
Polygons convex_hulls_other;
@@ -959,6 +969,11 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
warning->object = inst->model_instance->get_object();
}*/
}
if (!intersection(wrapping_poly, convex_hull).empty()) {
return {inst->model_instance->get_object()->name + L(" is too close to wrapping detection area, there may be collisions when printing.") + "\n",
inst->model_instance->get_object()};
}
convex_hulls_other.emplace_back(convex_hull);
}
@@ -991,7 +1006,9 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
convex_hulls_temp.push_back(wipe_tower_convex_hull);
} else {
//here, wipe_tower_polygon is not always convex.
Polygon wipe_tower_polygon = print.wipe_tower_data().wipe_tower_mesh_data->bottom;
Polygon wipe_tower_polygon;
if (print.wipe_tower_data().wipe_tower_mesh_data)
wipe_tower_polygon = print.wipe_tower_data().wipe_tower_mesh_data->bottom;
wipe_tower_polygon.translate(Point(scale_(x), scale_(y)));
convex_hulls_temp.push_back(wipe_tower_polygon);
}
@@ -1007,7 +1024,9 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
}*/
return {L("Prime Tower") + L(" is too close to exclusion area, and collisions will be caused.\n")};
}
if (!intersection({wrapping_poly}, convex_hulls_temp).empty()) {
return {L("Prime Tower") + L(" is too close to wrapping detection area, and collisions will be caused.\n")};
}
return {};
}
@@ -1141,10 +1160,13 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
}
}
if (m_config.print_sequence == PrintSequence::ByObject) {
if (m_config.print_sequence == PrintSequence::ByObject && m_objects.size() > 1) {
if (m_config.timelapse_type == TimelapseType::tlSmooth)
return {L("Smooth mode of timelapse is not supported when \"by object\" sequence is enabled.")};
if (m_config.enable_wrapping_detection)
return {L("Wrapping detection is not supported when \"by object\" sequence is enabled.")};
//BBS: refine seq-print validation logic
auto ret = sequential_print_clearance_valid(*this, collison_polygons, height_polygons);
if (!ret.string.empty()) {
@@ -2890,6 +2912,9 @@ size_t Print::get_extruder_id(unsigned int filament_id) const
bool Print::has_wipe_tower() const
{
if (m_config.enable_prime_tower.value == true) {
if (m_config.enable_wrapping_detection.value)
return true;
if (enable_timelapse_print())
return true;
@@ -3016,7 +3041,7 @@ void Print::_make_wipe_tower()
if (!bUseWipeTower2) {
// in BBL machine, wipe tower is only use to prime extruder. So just use a global wipe volume.
WipeTower wipe_tower(m_config, m_plate_index, m_origin, m_wipe_tower_data.tool_ordering.first_extruder(),
m_wipe_tower_data.tool_ordering.empty() ? 0.f : m_wipe_tower_data.tool_ordering.back().print_z);
m_wipe_tower_data.tool_ordering.empty() ? 0.f : m_wipe_tower_data.tool_ordering.back().print_z, m_wipe_tower_data.tool_ordering.all_extruders());
wipe_tower.set_has_tpu_filament(this->has_tpu_filament());
wipe_tower.set_filament_map(this->get_filament_maps());
// Set the extruder & material properties at the wipe tower object.
@@ -3087,7 +3112,7 @@ void Print::_make_wipe_tower()
layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this);
// if enable timelapse, slice all layer
if (enable_timelapse_print()) {
if (m_config.enable_wrapping_detection || enable_timelapse_print()) {
if (layer_tools.wipe_tower_partitions == 0) wipe_tower.set_last_layer_extruder_fill(false);
continue;
}