Tech ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS - Enable detection of collision with circular printbed for toolpaths

This commit is contained in:
enricoturri1966 2021-09-30 12:08:05 +02:00
parent 448911df9f
commit 7cfe082621
4 changed files with 79 additions and 41 deletions

View file

@ -84,6 +84,32 @@ static inline bool is_ccw(const Polygon &poly)
return o == ORIENTATION_CCW; return o == ORIENTATION_CCW;
} }
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
// returns true if the given polygons are identical
static bool are_approx(const Polygon& lhs, const Polygon& rhs)
{
if (lhs.points.size() != rhs.points.size())
return false;
size_t rhs_id = 0;
while (rhs_id < rhs.points.size()) {
if (rhs.points[rhs_id].isApprox(lhs.points.front()))
break;
++rhs_id;
}
if (rhs_id == rhs.points.size())
return false;
for (size_t i = 0; i < lhs.points.size(); ++i) {
if (!lhs.points[i].isApprox(rhs.points[(i + rhs_id) % lhs.points.size()]))
return false;
}
return true;
}
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
inline bool ray_ray_intersection(const Vec2d &p1, const Vec2d &v1, const Vec2d &p2, const Vec2d &v2, Vec2d &res) inline bool ray_ray_intersection(const Vec2d &p1, const Vec2d &v1, const Vec2d &p2, const Vec2d &v2, Vec2d &res)
{ {
double denom = v1(0) * v2(1) - v2(0) * v1(1); double denom = v1(0) * v2(1) - v2(0) * v1(1);

View file

@ -10,6 +10,7 @@
#include "GLShader.hpp" #include "GLShader.hpp"
#include "GUI_App.hpp" #include "GUI_App.hpp"
#include "Plater.hpp" #include "Plater.hpp"
#include "BitmapCache.hpp"
#include "libslic3r/ExtrusionEntity.hpp" #include "libslic3r/ExtrusionEntity.hpp"
#include "libslic3r/ExtrusionEntityCollection.hpp" #include "libslic3r/ExtrusionEntityCollection.hpp"
@ -17,7 +18,6 @@
#include "libslic3r/Print.hpp" #include "libslic3r/Print.hpp"
#include "libslic3r/SLAPrint.hpp" #include "libslic3r/SLAPrint.hpp"
#include "libslic3r/Slicing.hpp" #include "libslic3r/Slicing.hpp"
#include "slic3r/GUI/BitmapCache.hpp"
#include "libslic3r/Format/STL.hpp" #include "libslic3r/Format/STL.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "libslic3r/AppConfig.hpp" #include "libslic3r/AppConfig.hpp"
@ -67,6 +67,26 @@ void glAssertRecentCallImpl(const char* file_name, unsigned int line, const char
namespace Slic3r { 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;
}
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
#if ENABLE_SMOOTH_NORMALS #if ENABLE_SMOOTH_NORMALS
static void smooth_normals_corner(TriangleMesh& mesh, std::vector<stl_normal>& normals) static void smooth_normals_corner(TriangleMesh& mesh, std::vector<stl_normal>& normals)
{ {
@ -929,31 +949,6 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
glsafe(::glDisable(GL_BLEND)); glsafe(::glDisable(GL_BLEND));
} }
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
static bool same(const Polygon& lhs, const Polygon& rhs)
{
if (lhs.points.size() != rhs.points.size())
return false;
size_t rhs_id = 0;
while (rhs_id < rhs.points.size()) {
if (rhs.points[rhs_id].isApprox(lhs.points.front()))
break;
++rhs_id;
}
if (rhs_id == rhs.points.size())
return false;
for (size_t i = 0; i < lhs.points.size(); ++i) {
if (!lhs.points[i].isApprox(rhs.points[(i + rhs_id) % lhs.points.size()]))
return false;
}
return true;
}
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstanceEPrintVolumeState* out_state) const
{ {
if (config == nullptr) if (config == nullptr)
@ -978,7 +973,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
print_volume.max.y() += BedEpsilon; print_volume.max.y() += BedEpsilon;
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
ModelInstanceEPrintVolumeState state = ModelInstancePVS_Inside; ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
bool contained_min_one = false; bool contained_min_one = false;
@ -993,13 +988,9 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS #if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
const indexed_triangle_set& its = GUI::wxGetApp().plater()->model().objects[volume->object_idx()]->volumes[volume->volume_idx()]->mesh().its; const indexed_triangle_set& its = GUI::wxGetApp().plater()->model().objects[volume->object_idx()]->volumes[volume->volume_idx()]->mesh().its;
const Polygon volume_hull_2d = its_convex_hull_2d_above(its, volume->world_matrix().cast<float>(), 0.0f); const Polygon volume_hull_2d = its_convex_hull_2d_above(its, volume->world_matrix().cast<float>(), 0.0f);
Polygons intersection_polys = intersection(bed_poly, volume_hull_2d); const ModelInstanceEPrintVolumeState volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb.min.z(), bb.max.z());
bool contained_xy = !intersection_polys.empty() && same(intersection_polys.front(), volume_hull_2d); contained = (volume_state == ModelInstancePVS_Inside);
bool contained_z = -1e10 < bb.min.z() && bb.max.z() < bed_height; intersects = (volume_state == ModelInstancePVS_Partly_Outside);
contained = contained_xy && contained_z;
bool intersects_xy = !contained_xy && !intersection_polys.empty();
bool intersects_z = !contained_z && bb.min.z() < bed_height && -1e10 < bb.max.z();
intersects = intersects_xy || intersects_z;
#else #else
contained = print_volume.contains(bb); contained = print_volume.contains(bb);
intersects = print_volume.intersects(bb); intersects = print_volume.intersects(bb);
@ -1015,20 +1006,20 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
contained_min_one |= contained; contained_min_one |= contained;
if (state == ModelInstancePVS_Inside && volume->is_outside) if (overall_state == ModelInstancePVS_Inside && volume->is_outside)
state = ModelInstancePVS_Fully_Outside; overall_state = ModelInstancePVS_Fully_Outside;
#if ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION #if ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION
if (state == ModelInstancePVS_Fully_Outside && volume->is_outside && intersects) if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && intersects)
state = ModelInstancePVS_Partly_Outside; overall_state = ModelInstancePVS_Partly_Outside;
#else #else
if (state == ModelInstancePVS_Fully_Outside && volume->is_outside && print_volume.intersects(bb)) if (overall_state == ModelInstancePVS_Fully_Outside && volume->is_outside && print_volume.intersects(bb))
state = ModelInstancePVS_Partly_Outside; overall_state = ModelInstancePVS_Partly_Outside;
#endif // ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION #endif // ENABLE_FIX_SINKING_OBJECT_OUT_OF_BED_DETECTION
} }
if (out_state != nullptr) if (out_state != nullptr)
*out_state = state; *out_state = overall_state;
return contained_min_one; return contained_min_one;
} }

View file

@ -41,6 +41,11 @@ enum ModelInstanceEPrintVolumeState : unsigned char;
// Return appropriate color based on the ModelVolume. // Return appropriate color based on the ModelVolume.
std::array<float, 4> color_from_model_volume(const ModelVolume& model_volume); std::array<float, 4> 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);
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
// A container for interleaved arrays of 3D vertices and normals, // A container for interleaved arrays of 3D vertices and normals,
// possibly indexed by triangles and / or quads. // possibly indexed by triangles and / or quads.

View file

@ -5011,9 +5011,25 @@ 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 { else {
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(m_config->option("bed_shape"));
if (opt != nullptr) {
const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast<float>(scale_(BedEpsilon))).front();
const float bed_height = m_config->opt_float("max_print_height");
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());
use_error_color &= state != ModelInstancePVS_Inside;
}
#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
} }
} }