Tech ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - Reworked detection of collision with printbed. The detection uses now different algorithms in dependence of the printbed type (rectangular, circular, convex) to improve performance.

This commit is contained in:
enricoturri1966 2021-10-06 13:47:54 +02:00
parent 982172b878
commit 4ff13a5d63
10 changed files with 209 additions and 74 deletions

View File

@ -720,6 +720,9 @@ void GCodeProcessor::UsedFilaments::process_caches(GCodeProcessor* processor)
void GCodeProcessor::Result::reset() { void GCodeProcessor::Result::reset() {
moves = std::vector<GCodeProcessor::MoveVertex>(); moves = std::vector<GCodeProcessor::MoveVertex>();
bed_shape = Pointfs(); bed_shape = Pointfs();
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
max_print_height = 0.0f;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
settings_ids.reset(); settings_ids.reset();
extruders_count = 0; extruders_count = 0;
extruder_colors = std::vector<std::string>(); extruder_colors = std::vector<std::string>();
@ -734,6 +737,9 @@ void GCodeProcessor::Result::reset() {
moves.clear(); moves.clear();
lines_ends.clear(); lines_ends.clear();
bed_shape = Pointfs(); bed_shape = Pointfs();
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
max_print_height = 0.0f;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
settings_ids.reset(); settings_ids.reset();
extruders_count = 0; extruders_count = 0;
extruder_colors = std::vector<std::string>(); extruder_colors = std::vector<std::string>();
@ -883,6 +889,10 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height"); const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
if (first_layer_height != nullptr) if (first_layer_height != nullptr)
m_first_layer_height = std::abs(first_layer_height->value); m_first_layer_height = std::abs(first_layer_height->value);
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
m_result.max_print_height = config.max_print_height;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
} }
void GCodeProcessor::apply_config(const DynamicPrintConfig& config) void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
@ -1112,6 +1122,12 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height"); const ConfigOptionFloatOrPercent* first_layer_height = config.option<ConfigOptionFloatOrPercent>("first_layer_height");
if (first_layer_height != nullptr) if (first_layer_height != nullptr)
m_first_layer_height = std::abs(first_layer_height->value); m_first_layer_height = std::abs(first_layer_height->value);
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
const ConfigOptionFloat* max_print_height = config.option<ConfigOptionFloat>("max_print_height");
if (max_print_height != nullptr)
m_result.max_print_height = max_print_height->value;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
} }
void GCodeProcessor::enable_stealth_time_estimator(bool enabled) void GCodeProcessor::enable_stealth_time_estimator(bool enabled)

View File

@ -351,6 +351,9 @@ namespace Slic3r {
// Positions of ends of lines of the final G-code this->filename after TimeProcessor::post_process() finalizes the G-code. // Positions of ends of lines of the final G-code this->filename after TimeProcessor::post_process() finalizes the G-code.
std::vector<size_t> lines_ends; std::vector<size_t> lines_ends;
Pointfs bed_shape; Pointfs bed_shape;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
float max_print_height;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
SettingsIds settings_ids; SettingsIds settings_ids;
size_t extruders_count; size_t extruders_count;
std::vector<std::string> extruder_colors; std::vector<std::string> extruder_colors;

View File

@ -282,9 +282,11 @@ bool Bed3D::is_circle(const Pointfs& shape, Vec2d* center, double* radius)
avg_dist /= vertex_distances.size(); avg_dist /= vertex_distances.size();
double tolerance = avg_dist * 0.01;
bool defined_value = true; bool defined_value = true;
for (double el : vertex_distances) { for (double el : vertex_distances) {
if (fabs(el - avg_dist) > 10.0 * SCALED_EPSILON) if (fabs(el - avg_dist) > tolerance)
defined_value = false; defined_value = false;
break; break;
} }
@ -298,6 +300,11 @@ bool Bed3D::is_circle(const Pointfs& shape, Vec2d* center, double* radius)
return defined_value; return defined_value;
} }
bool Bed3D::is_convex(const Pointfs& shape)
{
return Polygon::new_scale(shape).convex_points().size() == shape.size();
}
Bed3D::EShapeType Bed3D::detect_shape_type(const Pointfs& shape) Bed3D::EShapeType Bed3D::detect_shape_type(const Pointfs& shape)
{ {
if (shape.size() < 3) if (shape.size() < 3)

View File

@ -139,6 +139,7 @@ public:
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
static bool is_rectangle(const Pointfs& shape, Vec2d* min = nullptr, Vec2d* max = nullptr); static bool is_rectangle(const Pointfs& shape, Vec2d* min = nullptr, Vec2d* max = nullptr);
static bool is_circle(const Pointfs& shape, Vec2d* center = nullptr, double* radius = nullptr); static bool is_circle(const Pointfs& shape, Vec2d* center = nullptr, double* radius = nullptr);
static bool is_convex(const Pointfs& shape);
static EShapeType detect_shape_type(const Pointfs& shape); static EShapeType detect_shape_type(const Pointfs& shape);
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS

View File

@ -11,6 +11,9 @@
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "BitmapCache.hpp" #include "BitmapCache.hpp"
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#include "3DBed.hpp"
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/ExtrusionEntityCollection.hpp" #include "libslic3r/ExtrusionEntityCollection.hpp"
@ -267,6 +270,12 @@ void GLIndexedVertexArray::render(
const std::pair<size_t, size_t>& tverts_range, const std::pair<size_t, size_t>& tverts_range,
const std::pair<size_t, size_t>& qverts_range) const const std::pair<size_t, size_t>& qverts_range) const
{ {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
// this method has been called before calling finalize() ?
if (this->vertices_and_normals_interleaved_VBO_id == 0 && !this->vertices_and_normals_interleaved.empty())
return;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
assert(this->vertices_and_normals_interleaved_VBO_id != 0); assert(this->vertices_and_normals_interleaved_VBO_id != 0);
assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0); assert(this->triangle_indices_VBO_id != 0 || this->quad_indices_VBO_id != 0);
@ -879,7 +888,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
GLVolume& v = *volumes.back(); GLVolume& v = *volumes.back();
v.indexed_vertex_array.load_mesh(mesh); v.indexed_vertex_array.load_mesh(mesh);
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
v.calc_convex_hull_3d(); v.set_convex_hull(mesh.convex_hull_3d());
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
v.indexed_vertex_array.finalize_geometry(opengl_initialized); v.indexed_vertex_array.finalize_geometry(opengl_initialized);
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0)); v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
@ -1038,7 +1047,11 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
} }
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state, bool as_toolpaths) const
#else
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
{ {
if (config == nullptr) if (config == nullptr)
return false; return false;
@ -1050,6 +1063,57 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast<float>(scale_(BedEpsilon))).front(); const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast<float>(scale_(BedEpsilon))).front();
const float bed_height = config->opt_float("max_print_height"); const float bed_height = config->opt_float("max_print_height");
const BoundingBox bed_box_2D = get_extents(bed_poly);
BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min.x()), unscale<double>(bed_box_2D.min.y()), -1e10 },
{ unscale<double>(bed_box_2D.max.x()), unscale<double>(bed_box_2D.max.y()), bed_height });
auto check_against_rectangular_bed = [&print_volume](GLVolume& volume, ModelInstanceEPrintVolumeState& state) {
const BoundingBoxf3* const bb = volume.is_sinking() ? &volume.transformed_non_sinking_bounding_box() : &volume.transformed_convex_hull_bounding_box();
volume.is_outside = !print_volume.contains(*bb);
if (volume.printable) {
if (state == ModelInstancePVS_Inside && volume.is_outside)
state = ModelInstancePVS_Fully_Outside;
if (state == ModelInstancePVS_Fully_Outside && volume.is_outside && print_volume.intersects(*bb))
state = ModelInstancePVS_Partly_Outside;
}
};
auto check_against_circular_bed = [](GLVolume& volume, ModelInstanceEPrintVolumeState& state, const Vec2d& center, double radius) {
const TriangleMesh* mesh = volume.is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : volume.convex_hull();
const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume.world_matrix().cast<float>(), 0.0f);
size_t outside_count = 0;
const double sq_radius = sqr(radius);
for (const Point& p : volume_hull_2d.points) {
if (sq_radius < (unscale(p) - center).squaredNorm())
++outside_count;
}
volume.is_outside = outside_count > 0;
if (volume.printable) {
if (state == ModelInstancePVS_Inside && volume.is_outside)
state = ModelInstancePVS_Fully_Outside;
if (state == ModelInstancePVS_Fully_Outside && volume.is_outside && outside_count < volume_hull_2d.size())
state = ModelInstancePVS_Partly_Outside;
}
};
auto check_against_convex_bed = [&bed_poly, bed_height](GLVolume& volume, ModelInstanceEPrintVolumeState& state) {
const TriangleMesh* mesh = volume.is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : volume.convex_hull();
const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume.world_matrix().cast<float>(), 0.0f);
const BoundingBoxf3* const bb = volume.is_sinking() ? &volume.transformed_non_sinking_bounding_box() : &volume.transformed_convex_hull_bounding_box();
ModelInstanceEPrintVolumeState volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb->min.z(), bb->max.z());
bool contained = (volume_state == ModelInstancePVS_Inside);
bool intersects = (volume_state == ModelInstancePVS_Partly_Outside);
volume.is_outside = !contained;
if (volume.printable) {
if (state == ModelInstancePVS_Inside && volume.is_outside)
state = ModelInstancePVS_Fully_Outside;
if (state == ModelInstancePVS_Fully_Outside && volume.is_outside && intersects)
state = ModelInstancePVS_Partly_Outside;
}
};
#else #else
const BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); const BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min.x()), unscale<double>(bed_box_2D.min.y()), 0.0 }, BoundingBoxf3 print_volume({ unscale<double>(bed_box_2D.min.x()), unscale<double>(bed_box_2D.min.y()), 0.0 },
@ -1063,36 +1127,33 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside; ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
bool contained_min_one = false; bool contained_min_one = false;
for (GLVolume* volume : this->volumes) { for (GLVolume* volume : this->volumes) {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
if (as_toolpaths && !volume->is_extrusion_path)
continue;
else if (!as_toolpaths && (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0))))
continue;
if (GUI::Bed3D::is_rectangle(opt->values))
check_against_rectangular_bed(*volume, overall_state);
else {
Vec2d center;
double radius;
if (GUI::Bed3D::is_circle(opt->values, &center, &radius))
check_against_circular_bed(*volume, overall_state, center, radius);
else if (GUI::Bed3D::is_convex(opt->values))
check_against_convex_bed(*volume, overall_state);
}
contained_min_one |= !volume->is_outside;
#else
if (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0))) if (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0)))
continue; continue;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
bool contained = false;
bool intersects = false;
bool is_aux_volume = volume->is_sla_support() || volume->is_sla_pad() || volume->is_wipe_tower;
const BoundingBoxf3 bb = is_aux_volume ? volume->transformed_convex_hull_bounding_box() : volume->transformed_non_sinking_bounding_box();
ModelInstanceEPrintVolumeState volume_state;
if (is_aux_volume) {
if (volume->is_sla_support() || volume->is_wipe_tower) {
const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast<float>(), 0.0f);
volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z());
}
}
else {
const TriangleMesh* mesh = volume->is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume->object_idx()]->volumes[volume->volume_idx()]->mesh() : volume->convex_hull();
const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume->world_matrix().cast<float>(), 0.0f);
volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z());
}
contained = (volume_state == ModelInstancePVS_Inside);
intersects = (volume_state == ModelInstancePVS_Partly_Outside);
#else
const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box(); const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
bool contained = print_volume.contains(bb); bool contained = print_volume.contains(bb);
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
volume->is_outside = !contained; volume->is_outside = !contained;
if (!volume->printable) if (!volume->printable)
@ -1103,10 +1164,6 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
if (overall_state == ModelInstancePVS_Inside && volume->is_outside) if (overall_state == ModelInstancePVS_Inside && volume->is_outside)
overall_state = ModelInstancePVS_Fully_Outside; overall_state = ModelInstancePVS_Fully_Outside;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && intersects)
overall_state = ModelInstancePVS_Partly_Outside;
#else
if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && print_volume.intersects(bb)) if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && print_volume.intersects(bb))
overall_state = ModelInstancePVS_Partly_Outside; overall_state = ModelInstancePVS_Partly_Outside;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS

View File

@ -654,7 +654,11 @@ public:
// returns true if all the volumes are completely contained in the print volume // returns true if all the volumes are completely contained in the print volume
// returns the containment state in the given out_state, if non-null // returns the containment state in the given out_state, if non-null
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state, bool as_toolpaths = false) const;
#else
bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const; bool check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
void reset_outside_state(); void reset_outside_state();
void update_colors_by_extruder(const DynamicPrintConfig* config); void update_colors_by_extruder(const DynamicPrintConfig* config);

View File

@ -6,10 +6,11 @@
#include "libslic3r/Model.hpp" #include "libslic3r/Model.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/LocalesUtils.hpp" #include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "MainFrame.hpp" #include "MainFrame.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "libslic3r/PresetBundle.hpp"
#include "Camera.hpp" #include "Camera.hpp"
#include "I18N.hpp" #include "I18N.hpp"
#include "GUI_Utils.hpp" #include "GUI_Utils.hpp"
@ -19,6 +20,10 @@
#include "GLToolbar.hpp" #include "GLToolbar.hpp"
#include "GUI_Preview.hpp" #include "GUI_Preview.hpp"
#include "GUI_ObjectManipulation.hpp" #include "GUI_ObjectManipulation.hpp"
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#include "3DBed.hpp"
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#include <imgui/imgui_internal.h> #include <imgui/imgui_internal.h>
#include <GL/glew.h> #include <GL/glew.h>
@ -674,6 +679,10 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print&
if (wxGetApp().is_gcode_viewer()) if (wxGetApp().is_gcode_viewer())
m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z; m_custom_gcode_per_print_z = gcode_result.custom_gcode_per_print_z;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
m_max_print_height = gcode_result.max_print_height;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
load_toolpaths(gcode_result); load_toolpaths(gcode_result);
if (m_layers.empty()) if (m_layers.empty())
@ -819,6 +828,9 @@ void GCodeViewer::reset()
m_paths_bounding_box = BoundingBoxf3(); m_paths_bounding_box = BoundingBoxf3();
m_max_bounding_box = BoundingBoxf3(); m_max_bounding_box = BoundingBoxf3();
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
m_max_print_height = 0.0f;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
m_tool_colors = std::vector<Color>(); m_tool_colors = std::vector<Color>();
m_extruders_count = 0; m_extruders_count = 0;
m_extruder_ids = std::vector<unsigned char>(); m_extruder_ids = std::vector<unsigned char>();
@ -835,6 +847,9 @@ void GCodeViewer::reset()
#if ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_STATISTICS
m_statistics.reset_all(); m_statistics.reset_all();
#endif // ENABLE_GCODE_VIEWER_STATISTICS #endif // ENABLE_GCODE_VIEWER_STATISTICS
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
m_contained_in_bed = true;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
} }
void GCodeViewer::render() void GCodeViewer::render()
@ -1554,7 +1569,49 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
// set approximate max bounding box (take in account also the tool marker) // set approximate max bounding box (take in account also the tool marker)
m_max_bounding_box = m_paths_bounding_box; m_max_bounding_box = m_paths_bounding_box;
m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ()); m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size().z() * Vec3d::UnitZ());
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
if (wxGetApp().is_editor()) {
const Bed3D::EShapeType bed_type = wxGetApp().plater()->get_bed().get_shape_type();
if (bed_type == Bed3D::EShapeType::Rectangle) {
BoundingBoxf3 print_volume = wxGetApp().plater()->get_bed().get_bounding_box(false);
print_volume.min.z() = -1e10;
print_volume.max.z() = m_max_print_height;
print_volume.min -= Vec3f(BedEpsilon, BedEpsilon, 0.0f).cast<double>();
print_volume.max += Vec3f(BedEpsilon, BedEpsilon, 0.0f).cast<double>();
m_contained_in_bed = print_volume.contains(m_paths_bounding_box);
}
else if (bed_type == Bed3D::EShapeType::Circle) {
Vec2d center;
double radius;
Bed3D::is_circle(wxGetApp().plater()->get_bed().get_shape(), &center, &radius);
const double sq_radius = sqr(radius);
for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) {
if (move.type == EMoveType::Extrude && move.extrusion_role != erCustom && move.width != 0.0f && move.height != 0.0f) {
if (sq_radius < (Vec2d(move.position.x(), move.position.y()) - center).squaredNorm()) {
m_contained_in_bed = false;
break;
}
}
}
}
else if (bed_type == Bed3D::EShapeType::Custom) {
const Pointfs& shape = wxGetApp().plater()->get_bed().get_shape();
if (Bed3D::is_convex(shape)) {
const Polygon poly = Polygon::new_scale(shape);
for (const GCodeProcessor::MoveVertex& move : gcode_result.moves) {
if (move.type == EMoveType::Extrude && move.extrusion_role != erCustom && move.width != 0.0f && move.height != 0.0f) {
if (!poly.contains(Point::new_scale(Vec2d(move.position.x(), move.position.y())))) {
m_contained_in_bed = false;
break;
}
}
}
}
}
}
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#if ENABLE_FIX_SEAMS_SYNCH #if ENABLE_FIX_SEAMS_SYNCH
m_sequential_view.gcode_ids.clear(); m_sequential_view.gcode_ids.clear();

View File

@ -780,6 +780,9 @@ private:
BoundingBoxf3 m_paths_bounding_box; BoundingBoxf3 m_paths_bounding_box;
// bounding box of toolpaths + marker tools // bounding box of toolpaths + marker tools
BoundingBoxf3 m_max_bounding_box; BoundingBoxf3 m_max_bounding_box;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
float m_max_print_height{ 0.0f };
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
std::vector<Color> m_tool_colors; std::vector<Color> m_tool_colors;
Layers m_layers; Layers m_layers;
std::array<unsigned int, 2> m_layers_z_range; std::array<unsigned int, 2> m_layers_z_range;
@ -804,6 +807,10 @@ private:
std::vector<CustomGCode::Item> m_custom_gcode_per_print_z; std::vector<CustomGCode::Item> m_custom_gcode_per_print_z;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
bool m_contained_in_bed{ true };
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
public: public:
GCodeViewer(); GCodeViewer();
~GCodeViewer() { reset(); } ~GCodeViewer() { reset(); }
@ -832,6 +839,10 @@ public:
const SequentialView& get_sequential_view() const { return m_sequential_view; } const SequentialView& get_sequential_view() const { return m_sequential_view; }
void update_sequential_view_current(unsigned int first, unsigned int last); void update_sequential_view_current(unsigned int first, unsigned int last);
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
bool is_contained_in_bed() const { return m_contained_in_bed; }
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
EViewType get_view_type() const { return m_view_type; } EViewType get_view_type() const { return m_view_type; }
void set_view_type(EViewType type) { void set_view_type(EViewType type) {
if (type == EViewType::Count) if (type == EViewType::Count)

View File

@ -1108,10 +1108,18 @@ void GLCanvas3D::reset_volumes()
_set_warning_notification(EWarning::ObjectOutside, false); _set_warning_notification(EWarning::ObjectOutside, false);
} }
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state(bool as_toolpaths) const
#else
ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const ModelInstanceEPrintVolumeState GLCanvas3D::check_volumes_outside_state() const
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
{ {
ModelInstanceEPrintVolumeState state; ModelInstanceEPrintVolumeState state;
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
m_volumes.check_outside_state(m_config, &state, as_toolpaths);
#else
m_volumes.check_outside_state(m_config, &state); m_volumes.check_outside_state(m_config, &state);
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
return state; return state;
} }
@ -5016,24 +5024,16 @@ void GLCanvas3D::_render_background() const
if (!m_volumes.empty()) if (!m_volumes.empty())
use_error_color &= _is_any_volume_outside(); use_error_color &= _is_any_volume_outside();
else {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
ModelInstanceEPrintVolumeState state;
if (m_gcode_viewer.has_data()) {
const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast<float>(scale_(BedEpsilon))).front();
const float bed_height = m_config->opt_float("max_print_height");
state = printbed_collision_state(bed_poly, bed_height, m_gcode_viewer.get_paths_bounding_box());
}
else else
state = ModelInstancePVS_Inside; #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
use_error_color &= m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
use_error_color &= state != ModelInstancePVS_Inside;
#else #else
{
const BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); const BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box(); const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box();
use_error_color &= (test_volume.radius() > 0.0 && paths_volume.radius() > 0.0) ? !test_volume.contains(paths_volume) : false; use_error_color &= (test_volume.radius() > 0.0 && paths_volume.radius() > 0.0) ? !test_volume.contains(paths_volume) : false;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
} }
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
} }
glsafe(::glPushMatrix()); glsafe(::glPushMatrix());
@ -6379,18 +6379,7 @@ void GLCanvas3D::_load_sla_shells()
void GLCanvas3D::_update_toolpath_volumes_outside_state() void GLCanvas3D::_update_toolpath_volumes_outside_state()
{ {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast<float>(scale_(BedEpsilon))).front(); check_volumes_outside_state(true);
const float bed_height = m_config->opt_float("max_print_height");
for (GLVolume* volume : m_volumes.volumes) {
if (volume->is_extrusion_path) {
const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast<float>(), 0.0f);
const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z());
volume->is_outside = (state != ModelInstancePVS_Inside);
}
else
volume->is_outside = false;
}
#else #else
BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
for (GLVolume* volume : m_volumes.volumes) { for (GLVolume* volume : m_volumes.volumes) {
@ -6402,18 +6391,7 @@ void GLCanvas3D::_update_toolpath_volumes_outside_state()
void GLCanvas3D::_update_sla_shells_outside_state() void GLCanvas3D::_update_sla_shells_outside_state()
{ {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast<float>(scale_(BedEpsilon))).front(); check_volumes_outside_state();
const float bed_height = m_config->opt_float("max_print_height");
for (GLVolume* volume : m_volumes.volumes) {
if (volume->shader_outside_printer_detection_enabled) {
const BoundingBoxf3& bb = volume->transformed_convex_hull_bounding_box();
const Polygon volume_hull_2d = its_convex_hull_2d_above(volume->convex_hull()->its, volume->world_matrix().cast<float>(), 0.0f);
const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z());
volume->is_outside = (state != ModelInstancePVS_Inside);
}
else
volume->is_outside = false;
}
#else #else
BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
for (GLVolume* volume : m_volumes.volumes) { for (GLVolume* volume : m_volumes.volumes) {
@ -6431,12 +6409,8 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
else { else {
if (wxGetApp().is_editor()) { if (wxGetApp().is_editor()) {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
if (current_printer_technology() != ptSLA) { if (current_printer_technology() != ptSLA)
const Polygon bed_poly = offset(Polygon::new_scale(wxGetApp().plater()->get_bed().get_shape()), static_cast<float>(scale_(BedEpsilon))).front(); show = m_gcode_viewer.has_data() && !m_gcode_viewer.is_contained_in_bed();
const float bed_height = m_config->opt_float("max_print_height");
const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, m_gcode_viewer.get_paths_bounding_box());
show = state != ModelInstancePVS_Inside;
}
#else #else
BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3();
const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box(); const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box();
@ -6445,6 +6419,7 @@ void GLCanvas3D::_set_warning_notification_if_needed(EWarning warning)
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
} }
} }
_set_warning_notification(warning, show); _set_warning_notification(warning, show);
} }

View File

@ -621,7 +621,11 @@ public:
unsigned int get_volumes_count() const; unsigned int get_volumes_count() const;
const GLVolumeCollection& get_volumes() const { return m_volumes; } const GLVolumeCollection& get_volumes() const { return m_volumes; }
void reset_volumes(); void reset_volumes();
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
ModelInstanceEPrintVolumeState check_volumes_outside_state(bool as_toolpaths = false) const;
#else
ModelInstanceEPrintVolumeState check_volumes_outside_state() const; ModelInstanceEPrintVolumeState check_volumes_outside_state() const;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#if ENABLE_SEAMS_USING_MODELS #if ENABLE_SEAMS_USING_MODELS
void init_gcode_viewer() { m_gcode_viewer.init(); } void init_gcode_viewer() { m_gcode_viewer.init(); }