mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2026-02-19 19:12:23 -07:00
FIX: Printable area check results in gcode_check_result
Added a check for Gcode traces outside the printable area after the backend slicer, allowing command-line slicers to detect abnormal results. The GCodeProcessor's m_result.gcode_check_result.error_code now includes not only dual-head print range checks, but also checks for the machine's plate print range, wrapping detection area, and height violations. jira: none Change-Id: I44072ece3b4b525c77328cec2f76e205eb559cc4 (cherry picked from commit 054f936243968687f536170374a233ec912e8e42)
This commit is contained in:
parent
c0c12fcb1f
commit
aa9fb1fd34
4 changed files with 108 additions and 42 deletions
|
|
@ -5835,7 +5835,12 @@ int CLI::run(int argc, char **argv)
|
|||
BOOST_LOG_TRIVIAL(info) << "export_gcode finished: time_using_cache update to " << time_using_cache << " secs.";
|
||||
if (gcode_result && gcode_result->gcode_check_result.error_code) {
|
||||
//found gcode error
|
||||
BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode in unprintable area of multi extruder printers!" << std::endl;
|
||||
if ((gcode_result->gcode_check_result.error_code & 0b11100)>0)
|
||||
BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode in unprintable area of the printers! gcode_result->gcode_check_result.error_code = "
|
||||
<< gcode_result->gcode_check_result.error_code << std::endl;
|
||||
else
|
||||
BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode in unprintable area of multi extruder printers! gcode_result->gcode_check_result.error_code = "
|
||||
<< gcode_result->gcode_check_result.error_code << std::endl;
|
||||
record_exit_reson(outfile_dir, CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, index + 1, cli_errors[CLI_GCODE_PATH_IN_UNPRINTABLE_AREA], sliced_info);
|
||||
flush_and_exit(CLI_GCODE_PATH_IN_UNPRINTABLE_AREA);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1929,15 +1929,14 @@ void GCode::do_export(Print* print, const char* path, GCodeProcessorResult* resu
|
|||
|
||||
m_processor.result().filament_printable_reuslt = FilamentPrintableResult(conflict_filament, bed_type_to_gcode_string(m_config.curr_bed_type));
|
||||
}
|
||||
// check gcode is valid in multi_extruder printabele area
|
||||
// check gcode is valid in machine printabele area and multi_extruder printabele area
|
||||
int extruder_size = m_print->config().nozzle_diameter.values.size();
|
||||
if (extruder_size > 1) {
|
||||
std::vector<Polygons> extruder_unprintable_polys = m_print->get_extruder_unprintable_polygons();
|
||||
m_processor.check_multi_extruder_gcode_valid(extruder_unprintable_polys,
|
||||
m_print->get_extruder_printable_height(),
|
||||
m_print->get_filament_maps(),
|
||||
m_print->get_physical_unprintable_filaments(m_print->get_slice_used_filaments(false)));
|
||||
}
|
||||
std::vector<Polygons> extruder_unprintable_polys = m_print->get_extruder_unprintable_polygons();
|
||||
Pointfs plate_printable_area = m_print->config().printable_area.values;
|
||||
Pointfs wrapping_exclude_area_points = m_print->config().wrapping_exclude_area.values;
|
||||
m_processor.check_multi_extruder_gcode_valid(extruder_size, plate_printable_area, m_print->config().printable_height.value, wrapping_exclude_area_points,
|
||||
extruder_unprintable_polys, m_print->get_extruder_printable_height(), m_print->get_filament_maps(),
|
||||
m_print->get_physical_unprintable_filaments(m_print->get_slice_used_filaments(false)));
|
||||
|
||||
m_processor.finalize(true);
|
||||
// DoExport::update_print_estimated_times_stats(m_processor, print->m_print_statistics);
|
||||
|
|
|
|||
|
|
@ -1667,13 +1667,19 @@ void GCodeProcessor::register_commands()
|
|||
}
|
||||
}
|
||||
|
||||
bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons> &unprintable_areas,
|
||||
bool GCodeProcessor::check_multi_extruder_gcode_valid(const int extruder_size,
|
||||
const Pointfs plate_printable_area,
|
||||
const double plate_printable_height,
|
||||
const Pointfs wrapping_exclude_area,
|
||||
const std::vector<Polygons> &unprintable_areas,
|
||||
const std::vector<double> &printable_heights,
|
||||
const std::vector<int> &filament_map,
|
||||
const std::vector<std::set<int>> &unprintable_filament_types)
|
||||
{
|
||||
m_result.limit_filament_maps.clear();
|
||||
m_result.gcode_check_result.reset();
|
||||
m_result.gcode_check_result.reset();// including both single extruder machine printable area check result and multi extruder result
|
||||
Polygon plate_printable_poly = Polygon::new_scale(plate_printable_area);
|
||||
Polygon wrapping_exclude_poly = Polygon::new_scale(wrapping_exclude_area);
|
||||
|
||||
m_result.limit_filament_maps.resize(filament_map.size(), 0);
|
||||
|
||||
|
|
@ -1685,11 +1691,13 @@ bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons
|
|||
struct GCodePosInfo
|
||||
{
|
||||
Points pos;
|
||||
float max_print_z;
|
||||
Points pos_custom;
|
||||
float max_print_z;
|
||||
};
|
||||
std::map<int, std::map<int, GCodePosInfo>> gcode_path_pos; // object_id, filament_id, pos
|
||||
for (const GCodeProcessorResult::MoveVertex &move : m_result.moves) {
|
||||
if (move.type == EMoveType::Extrude/* || move.type == EMoveType::Travel*/) {
|
||||
// sometimes, the start line extrude was outside the edge of plate a little, this is allowed, so do not include into the gcode_path_pos
|
||||
if (move.type == EMoveType::Extrude && !(move.object_label_id < 0 && move.extrusion_role == ExtrusionRole::erCustom) /* || move.type == EMoveType::Travel*/) {
|
||||
if (move.is_arc_move_with_interpolation_points()) {
|
||||
for (int i = 0; i < move.interpolation_points.size(); i++) {
|
||||
gcode_path_pos[move.object_label_id][int(move.extruder_id)].pos.emplace_back(to_2d(move.interpolation_points[i].cast<double>()));
|
||||
|
|
@ -1699,51 +1707,100 @@ bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector<Polygons
|
|||
gcode_path_pos[move.object_label_id][int(move.extruder_id)].pos.emplace_back(to_2d(move.position.cast<double>()));
|
||||
}
|
||||
gcode_path_pos[move.object_label_id][int(move.extruder_id)].max_print_z = std::max(gcode_path_pos[move.object_label_id][int(move.extruder_id)].max_print_z, move.print_z);
|
||||
} else if ( move.type == EMoveType::Extrude && (move.object_label_id < 0 && move.extrusion_role == ExtrusionRole::erCustom) ){
|
||||
if (move.is_arc_move_with_interpolation_points()) {
|
||||
for (int i = 0; i < move.interpolation_points.size(); i++) {
|
||||
gcode_path_pos[move.object_label_id][int(move.extruder_id)].pos_custom.emplace_back(to_2d(move.interpolation_points[i].cast<double>()));
|
||||
}
|
||||
} else {
|
||||
gcode_path_pos[move.object_label_id][int(move.extruder_id)].pos_custom.emplace_back(to_2d(move.position.cast<double>()));
|
||||
}
|
||||
gcode_path_pos[move.object_label_id][int(move.extruder_id)].max_print_z = std::max(gcode_path_pos[move.object_label_id][int(move.extruder_id)].max_print_z, move.print_z);
|
||||
}
|
||||
}
|
||||
|
||||
bool valid = true;
|
||||
Point plate_offset = Point(scale_(m_x_offset), scale_(m_y_offset));
|
||||
plate_printable_poly.translate(plate_offset);
|
||||
wrapping_exclude_poly.translate(plate_offset);
|
||||
for (auto obj_iter = gcode_path_pos.begin(); obj_iter != gcode_path_pos.end(); ++obj_iter) {
|
||||
int object_label_id = obj_iter->first;
|
||||
int object_label_id = obj_iter->first;
|
||||
const std::map<int, GCodePosInfo> &path_pos = obj_iter->second;
|
||||
for (auto iter = path_pos.begin(); iter != path_pos.end(); ++iter) {
|
||||
int extruder_id = filament_map[iter->first] - 1;
|
||||
Polygon path_poly(iter->second.pos);
|
||||
Points iter_points;//temp points
|
||||
iter_points.insert(iter_points.end(), iter->second.pos.begin(), iter->second.pos.end());// put object/wipetower extrude position in
|
||||
Polygon path_poly(iter_points);
|
||||
BoundingBox bbox = path_poly.bounding_box();
|
||||
|
||||
// check printable area
|
||||
// Simplified use bounding_box, Accurate calculation is not efficient
|
||||
for (Polygon poly : unprintable_areas[extruder_id]) {
|
||||
poly.translate(plate_offset);
|
||||
if (poly.bounding_box().overlap(bbox)) {
|
||||
m_result.gcode_check_result.error_code = 1;
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
iter_points.insert(iter_points.end(), iter->second.pos_custom.begin(), iter->second.pos_custom.end());// put custom extrude position in
|
||||
Polygon path_poly_custom(iter_points);
|
||||
BoundingBox bbox_custom = path_poly_custom.bounding_box();
|
||||
bbox_custom.offset(-scale_(1.0));//Narrow the range to provide a tolerance for the custom gcode
|
||||
bbox.merge(bbox_custom);// merge the custom gcode pos with other pos
|
||||
if (plate_printable_poly.is_valid()){
|
||||
if (!plate_printable_poly.bounding_box().contains(bbox)) {// out of the bed area
|
||||
m_result.gcode_check_result.error_code |= (1<<2);
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
filament_to_object_id.second = object_label_id;
|
||||
m_result.gcode_check_result.print_area_error_infos[extruder_id].push_back(filament_to_object_id);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
if ( iter->second.max_print_z > plate_printable_height ) { //over height
|
||||
m_result.gcode_check_result.error_code |= (1 << 3);
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
filament_to_object_id.second = object_label_id;
|
||||
m_result.gcode_check_result.print_height_error_infos[extruder_id].push_back(filament_to_object_id);
|
||||
valid = false;
|
||||
}
|
||||
if (wrapping_exclude_poly.is_valid()) {
|
||||
if (wrapping_exclude_poly.bounding_box().overlap(bbox)) { // get into the wrapping area
|
||||
m_result.gcode_check_result.error_code |= (1 << 4);
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
filament_to_object_id.second = object_label_id;
|
||||
m_result.gcode_check_result.print_area_error_infos[extruder_id].push_back(filament_to_object_id);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
// check printable height
|
||||
if (iter->second.max_print_z > printable_heights[extruder_id]) {
|
||||
m_result.gcode_check_result.error_code |= (1 << 1);
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
filament_to_object_id.second = object_label_id;
|
||||
m_result.gcode_check_result.print_height_error_infos[extruder_id].push_back(filament_to_object_id);
|
||||
m_result.limit_filament_maps[iter->first] |= (1 << extruder_id);
|
||||
valid = false;
|
||||
}
|
||||
if (extruder_size > 1) {// in multi extruder condition
|
||||
|
||||
for (int i = 0; i < unprintable_areas.size(); ++i) {
|
||||
for (Polygon poly : unprintable_areas[i]) {
|
||||
poly.translate(plate_offset);
|
||||
if (!poly.bounding_box().overlap(bbox))
|
||||
continue;
|
||||
// check printable area
|
||||
// Simplified use bounding_box, Accurate calculation is not efficient
|
||||
if (!unprintable_areas[extruder_id].empty())
|
||||
for (Polygon poly : unprintable_areas[extruder_id]) {
|
||||
poly.translate(plate_offset);
|
||||
if (poly.bounding_box().overlap(bbox)) {
|
||||
m_result.gcode_check_result.error_code |= 1;
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
filament_to_object_id.second = object_label_id;
|
||||
m_result.gcode_check_result.print_area_error_infos[extruder_id].push_back(filament_to_object_id);
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_result.limit_filament_maps[iter->first] |= (1 << i);
|
||||
// check printable height
|
||||
if ((extruder_id < printable_heights.size()) && (iter->second.max_print_z > printable_heights[extruder_id])) {
|
||||
m_result.gcode_check_result.error_code |= (1 << 1);
|
||||
std::pair<int, int> filament_to_object_id;
|
||||
filament_to_object_id.first = iter->first;
|
||||
filament_to_object_id.second = object_label_id;
|
||||
m_result.gcode_check_result.print_height_error_infos[extruder_id].push_back(filament_to_object_id);
|
||||
m_result.limit_filament_maps[iter->first] |= (1 << extruder_id);
|
||||
valid = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < unprintable_areas.size(); ++i) {
|
||||
for (Polygon poly : unprintable_areas[i]) {
|
||||
poly.translate(plate_offset);
|
||||
if (!poly.bounding_box().overlap(bbox)) continue;
|
||||
|
||||
m_result.limit_filament_maps[iter->first] |= (1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,8 @@ class Print;
|
|||
|
||||
struct GCodeCheckResult
|
||||
{
|
||||
int error_code = 0; // 0 means succeed, 0001 printable area error, 0010 printable height error
|
||||
int error_code = 0; // 0 means succeed, 0b 0001 multi extruder printable area error, 0b 0010 multi extruder printable height error,
|
||||
// 0b 0100 plate printable area error, 0b 1000 plate printable height error, 0b 10000 wrapping detection area error
|
||||
std::map<int, std::vector<std::pair<int, int>>> print_area_error_infos; // printable_area extruder_id to <filament_id - object_label_id> which cannot printed in this extruder
|
||||
std::map<int, std::vector<std::pair<int, int>>> print_height_error_infos; // printable_height extruder_id to <filament_id - object_label_id> which cannot printed in this extruder
|
||||
void reset() {
|
||||
|
|
@ -841,7 +842,11 @@ class Print;
|
|||
GCodeProcessor();
|
||||
void init_filament_maps_and_nozzle_type_when_import_only_gcode();
|
||||
// check whether the gcode path meets the filament_map grouping requirements
|
||||
bool check_multi_extruder_gcode_valid(const std::vector<Polygons> &unprintable_areas,
|
||||
bool check_multi_extruder_gcode_valid(const int extruder_size,
|
||||
const Pointfs plate_printable_area,
|
||||
const double plate_printable_height,
|
||||
const Pointfs wrapping_exclude_area,
|
||||
const std::vector<Polygons> &unprintable_areas,
|
||||
const std::vector<double> &printable_heights,
|
||||
const std::vector<int> &filament_map,
|
||||
const std::vector<std::set<int>>& unprintable_filament_types );
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue