From 13ef817a994a4b944a613d0e70a6b20fafc4b861 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 30 Sep 2021 14:51:09 +0200 Subject: [PATCH] Tech ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - Enable detection of collision with circular printbed in backend --- src/libslic3r/Model.cpp | 78 ++++++++++++++++++++++++++++++++++- src/libslic3r/Model.hpp | 18 +++++++- src/slic3r/GUI/3DScene.cpp | 31 -------------- src/slic3r/GUI/3DScene.hpp | 9 ---- src/slic3r/GUI/GLCanvas3D.cpp | 21 +++++----- src/slic3r/GUI/Plater.cpp | 7 ++++ 6 files changed, 111 insertions(+), 53 deletions(-) diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 7bc28f904..4546444ee 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -26,6 +26,37 @@ namespace Slic3r { +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const Polygon& obj_hull_2d, double obj_min_z, double obj_max_z) +{ + static const double Z_TOLERANCE = -1e10; + + const Polygons intersection_polys = intersection(printbed_shape, obj_hull_2d); + const bool contained_xy = !intersection_polys.empty() && Geometry::are_approx(intersection_polys.front(), obj_hull_2d); + const bool contained_z = Z_TOLERANCE < obj_min_z && obj_max_z < print_volume_height; + if (contained_xy && contained_z) + return ModelInstancePVS_Inside; + + const bool intersects_xy = !contained_xy && !intersection_polys.empty(); + const bool intersects_z = !contained_z && obj_min_z < print_volume_height&& Z_TOLERANCE < obj_max_z; + if (intersects_xy || intersects_z) + return ModelInstancePVS_Partly_Outside; + + return ModelInstancePVS_Fully_Outside; +} + +ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const BoundingBoxf3& box) +{ + const Polygon box_hull_2d({ + { scale_(box.min.x()), scale_(box.min.y()) }, + { scale_(box.max.x()), scale_(box.min.y()) }, + { scale_(box.max.x()), scale_(box.max.y()) }, + { scale_(box.min.x()), scale_(box.max.y()) } + }); + return printbed_collision_state(printbed_shape, print_volume_height, box_hull_2d, box.min.z(), box.max.z()); +} +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + Model& Model::assign_copy(const Model &rhs) { this->copy_id(rhs); @@ -330,13 +361,23 @@ BoundingBoxf3 Model::bounding_box() const return bb; } -unsigned int Model::update_print_volume_state(const BoundingBoxf3 &print_volume) +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +unsigned int Model::update_print_volume_state(const Polygon& printbed_shape, double print_volume_height) +{ + unsigned int num_printable = 0; + for (ModelObject* model_object : this->objects) + num_printable += model_object->check_instances_print_volume_state(printbed_shape, print_volume_height); + return num_printable; +} +#else +unsigned int Model::update_print_volume_state(const BoundingBoxf3 &print_volume) { unsigned int num_printable = 0; for (ModelObject *model_object : this->objects) num_printable += model_object->check_instances_print_volume_state(print_volume); return num_printable; } +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS bool Model::center_instances_around_point(const Vec2d &point) { @@ -1513,6 +1554,40 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const return max_z + inst->get_offset(Z); } +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +unsigned int ModelObject::check_instances_print_volume_state(const Polygon& printbed_shape, double print_volume_height) +{ + unsigned int num_printable = 0; + enum { + INSIDE = 1, + OUTSIDE = 2 + }; + for (ModelInstance* model_instance : this->instances) { + unsigned int inside_outside = 0; + for (const ModelVolume* vol : this->volumes) + if (vol->is_model_part()) { +#if ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION + const BoundingBoxf3 bb = vol->mesh().transformed_bounding_box(model_instance->get_matrix() * vol->get_matrix(), 0.0); +#else + const BoundingBoxf3 bb = vol->get_convex_hull().transformed_bounding_box(model_instance->get_matrix() * vol->get_matrix()); +#endif // ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION + ModelInstanceEPrintVolumeState state = printbed_collision_state(printbed_shape, print_volume_height, bb); + if (state == ModelInstancePVS_Inside) + inside_outside |= INSIDE; + else if (state == ModelInstancePVS_Fully_Outside) + inside_outside |= OUTSIDE; + else + inside_outside |= INSIDE | OUTSIDE; + } + model_instance->print_volume_state = + (inside_outside == (INSIDE | OUTSIDE)) ? ModelInstancePVS_Partly_Outside : + (inside_outside == INSIDE) ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside; + if (inside_outside == INSIDE) + ++num_printable; + } + return num_printable; +} +#else unsigned int ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume) { unsigned int num_printable = 0; @@ -1544,6 +1619,7 @@ unsigned int ModelObject::check_instances_print_volume_state(const BoundingBoxf3 } return num_printable; } +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS void ModelObject::print_info() const { diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index ea1d0ed17..1b92e01ed 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -367,7 +367,11 @@ public: double get_instance_max_z(size_t instance_idx) const; // Called by Print::validate() from the UI thread. +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + unsigned int check_instances_print_volume_state(const Polygon& printbed_shape, double print_volume_height); +#else unsigned int check_instances_print_volume_state(const BoundingBoxf3& print_volume); +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS // Print object statistics to console. void print_info() const; @@ -904,6 +908,14 @@ enum ModelInstanceEPrintVolumeState : unsigned char ModelInstanceNum_BedStates }; +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS +// return the state of the given object's volume (extrusion along z of obj_hull_2d from obj_min_z to obj_max_z) +// with respect to the given print volume (extrusion along z of printbed_shape from zero to print_volume_height) +ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const Polygon& obj_hull_2d, double obj_min_z, double obj_max_z); +// return the state of the given box +// with respect to the given print volume (extrusion along z of printbed_shape from zero to print_volume_height) +ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const BoundingBoxf3& box); +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS // A single instance of a ModelObject. // Knows the affine transformation of an object. @@ -1109,8 +1121,12 @@ public: BoundingBoxf3 bounding_box() const; // Set the print_volume_state of PrintObject::instances, // return total number of printable objects. +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + unsigned int update_print_volume_state(const Polygon& printbed_shape, double print_volume_height); +#else unsigned int update_print_volume_state(const BoundingBoxf3 &print_volume); - // Returns true if any ModelObject was modified. +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + // Returns true if any ModelObject was modified. bool center_instances_around_point(const Vec2d &point); void translate(coordf_t x, coordf_t y, coordf_t z) { for (ModelObject *o : this->objects) o->translate(x, y, z); } TriangleMesh mesh() const; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index a0d2e8c51..78da38b13 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -67,37 +67,6 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char namespace Slic3r { -#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS -ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const Polygon& obj_hull_2d, double obj_min_z, double obj_max_z) -{ - static const double Z_TOLERANCE = -1e10; - - const Polygons intersection_polys = intersection(printbed_shape, obj_hull_2d); - const bool contained_xy = !intersection_polys.empty() && Geometry::are_approx(intersection_polys.front(), obj_hull_2d); - const bool contained_z = Z_TOLERANCE < obj_min_z && obj_max_z < print_volume_height; - if (contained_xy && contained_z) - return ModelInstancePVS_Inside; - - const bool intersects_xy = !contained_xy && !intersection_polys.empty(); - const bool intersects_z = !contained_z && obj_min_z < print_volume_height && Z_TOLERANCE < obj_max_z; - if (intersects_xy || intersects_z) - return ModelInstancePVS_Partly_Outside; - - return ModelInstancePVS_Fully_Outside; -} - -ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const BoundingBoxf3& box) -{ - const Polygon box_hull_2d({ - { scale_(box.min.x()), scale_(box.min.y()) }, - { scale_(box.max.x()), scale_(box.min.y()) }, - { scale_(box.max.x()), scale_(box.max.y()) }, - { scale_(box.min.x()), scale_(box.max.y()) } - }); - return printbed_collision_state(printbed_shape, print_volume_height, box_hull_2d, box.min.z(), box.max.z()); -} -#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - #if ENABLE_SMOOTH_NORMALS static void smooth_normals_corner(TriangleMesh& mesh, std::vector& normals) { diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index ce57d5410..7df772c7f 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -41,15 +41,6 @@ enum ModelInstanceEPrintVolumeState : unsigned char; // Return appropriate color based on the ModelVolume. std::array color_from_model_volume(const ModelVolume& model_volume); -#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS -// return the state of given object volume (extrusion along z of obj_hull_2d by obj_height) -// with respect to the given print volume (extrusion along z of printbed_shape by print_volume_height) -ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const Polygon& obj_hull_2d, double obj_min_z, double obj_max_z); -// return the state of given box -// with respect to the given print volume (extrusion along z of printbed_shape by print_volume_height) -ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const BoundingBoxf3& box); -#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - // A container for interleaved arrays of 3D vertices and normals, // possibly indexed by triangles and / or quads. class GLIndexedVertexArray { diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index a5bba3471..66e231566 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5014,17 +5014,16 @@ void GLCanvas3D::_render_background() const use_error_color &= _is_any_volume_outside(); else { #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - const ConfigOptionPoints* opt = dynamic_cast(m_config->option("bed_shape")); - const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast(scale_(BedEpsilon))).front(); - 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()); -// const BoundingBoxf3& paths_volume = m_gcode_viewer.get_paths_bounding_box(); -// Polygon paths_hull_2d; -// paths_hull_2d.append({ scale_(paths_volume.min.x()), scale_(paths_volume.min.y()) }); -// paths_hull_2d.append({ scale_(paths_volume.max.x()), scale_(paths_volume.min.y()) }); -// paths_hull_2d.append({ scale_(paths_volume.max.x()), scale_(paths_volume.max.y()) }); -// paths_hull_2d.append({ scale_(paths_volume.min.x()), scale_(paths_volume.max.y()) }); -// const ModelInstanceEPrintVolumeState state = printbed_collision_state(bed_poly, bed_height, paths_hull_2d, paths_volume.min.z(), paths_volume.max.z()); + ModelInstanceEPrintVolumeState state; + if (m_gcode_viewer.has_data()) { + const ConfigOptionPoints* opt = dynamic_cast(m_config->option("bed_shape")); + const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast(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 + state = ModelInstancePVS_Inside; + use_error_color &= state != ModelInstancePVS_Inside; #else const BoundingBoxf3 test_volume = (m_config != nullptr) ? print_volume(*m_config) : BoundingBoxf3(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 87b83ec24..373323038 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -2946,12 +2946,19 @@ void Plater::priv::schedule_background_process() void Plater::priv::update_print_volume_state() { +#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS + const ConfigOptionPoints* opt = dynamic_cast(this->config->option("bed_shape")); + const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast(scale_(BedEpsilon))).front(); + const float bed_height = this->config->opt_float("max_print_height"); + this->q->model().update_print_volume_state(bed_poly, bed_height); +#else BoundingBox bed_box_2D = get_extents(Polygon::new_scale(this->config->opt("bed_shape")->values)); BoundingBoxf3 print_volume(unscale(bed_box_2D.min(0), bed_box_2D.min(1), 0.0), unscale(bed_box_2D.max(0), bed_box_2D.max(1), scale_(this->config->opt_float("max_print_height")))); // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. print_volume.offset(BedEpsilon); print_volume.min(2) = -1e10; this->q->model().update_print_volume_state(print_volume); +#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS }