Documented the new print bed collision detection algorithm requirements:
Only convex print bed is supported. Optimization of collision detection by precomputing the print bed shape type.
This commit is contained in:
parent
36baae05f1
commit
0bc2448e22
4 changed files with 23 additions and 11 deletions
|
@ -27,6 +27,7 @@
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
|
// Using rotating callipers to check for collision of two convex polygons. Thus both printbed_shape and obj_hull_2d are convex polygons.
|
||||||
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)
|
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)
|
||||||
{
|
{
|
||||||
if (!Geometry::convex_polygons_intersect(printbed_shape, obj_hull_2d))
|
if (!Geometry::convex_polygons_intersect(printbed_shape, obj_hull_2d))
|
||||||
|
@ -362,6 +363,7 @@ BoundingBoxf3 Model::bounding_box() const
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
|
// printbed_shape is convex polygon
|
||||||
unsigned int Model::update_print_volume_state(const Polygon& printbed_shape, double print_volume_height)
|
unsigned int Model::update_print_volume_state(const Polygon& printbed_shape, double print_volume_height)
|
||||||
{
|
{
|
||||||
unsigned int num_printable = 0;
|
unsigned int num_printable = 0;
|
||||||
|
@ -1571,6 +1573,7 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
|
// printbed_shape is convex polygon
|
||||||
unsigned int ModelObject::check_instances_print_volume_state(const Polygon& printbed_shape, double print_volume_height)
|
unsigned int ModelObject::check_instances_print_volume_state(const Polygon& printbed_shape, double print_volume_height)
|
||||||
{
|
{
|
||||||
unsigned int num_printable = 0;
|
unsigned int num_printable = 0;
|
||||||
|
|
|
@ -911,9 +911,11 @@ enum ModelInstanceEPrintVolumeState : unsigned char
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#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)
|
// 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)
|
// with respect to the given print volume (extrusion along z of printbed_shape from zero to print_volume_height)
|
||||||
|
// Using rotating callipers to check for collision of two convex polygons.
|
||||||
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);
|
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
|
// 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)
|
// with respect to the given print volume (extrusion along z of printbed_shape from zero to print_volume_height)
|
||||||
|
// Commented out, using rotating callipers is quite expensive for a bounding box test.
|
||||||
//ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const BoundingBoxf3& box);
|
//ModelInstanceEPrintVolumeState printbed_collision_state(const Polygon& printbed_shape, double print_volume_height, const BoundingBoxf3& box);
|
||||||
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#endif // ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
|
|
||||||
|
@ -1122,6 +1124,7 @@ public:
|
||||||
// Set the print_volume_state of PrintObject::instances,
|
// Set the print_volume_state of PrintObject::instances,
|
||||||
// return total number of printable objects.
|
// return total number of printable objects.
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
|
// printbed_shape is convex polygon
|
||||||
unsigned int update_print_volume_state(const Polygon& printbed_shape, double print_volume_height);
|
unsigned int update_print_volume_state(const Polygon& printbed_shape, double print_volume_height);
|
||||||
#else
|
#else
|
||||||
unsigned int update_print_volume_state(const BoundingBoxf3 &print_volume);
|
unsigned int update_print_volume_state(const BoundingBoxf3 &print_volume);
|
||||||
|
|
|
@ -992,6 +992,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
||||||
|
|
||||||
auto check_against_circular_bed = [](GLVolume& volume, ModelInstanceEPrintVolumeState& state, const Vec2d& center, double radius) {
|
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 TriangleMesh* mesh = volume.is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : volume.convex_hull();
|
||||||
|
//FIXME 2D convex hull is O(n log n), while testing the 2D points against 2D circle is O(n).
|
||||||
const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume.world_matrix().cast<float>(), 0.0f);
|
const Polygon volume_hull_2d = its_convex_hull_2d_above(mesh->its, volume.world_matrix().cast<float>(), 0.0f);
|
||||||
size_t outside_count = 0;
|
size_t outside_count = 0;
|
||||||
const double sq_radius = sqr(radius);
|
const double sq_radius = sqr(radius);
|
||||||
|
@ -1013,6 +1014,7 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
||||||
const TriangleMesh* mesh = volume.is_sinking() ? &GUI::wxGetApp().plater()->model().objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh() : volume.convex_hull();
|
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 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();
|
const BoundingBoxf3* const bb = volume.is_sinking() ? &volume.transformed_non_sinking_bounding_box() : &volume.transformed_convex_hull_bounding_box();
|
||||||
|
// Using rotating callipers to check for collision of two convex polygons.
|
||||||
ModelInstanceEPrintVolumeState volume_state = printbed_collision_state(bed_poly, bed_height, volume_hull_2d, bb->min.z(), bb->max.z());
|
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 contained = (volume_state == ModelInstancePVS_Inside);
|
||||||
bool intersects = (volume_state == ModelInstancePVS_Partly_Outside);
|
bool intersects = (volume_state == ModelInstancePVS_Partly_Outside);
|
||||||
|
@ -1041,6 +1043,14 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
||||||
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
|
ModelInstanceEPrintVolumeState overall_state = ModelInstancePVS_Inside;
|
||||||
bool contained_min_one = false;
|
bool contained_min_one = false;
|
||||||
|
|
||||||
|
enum class BedShape { Rectangle, Circle, Convex, NonConvex };
|
||||||
|
Vec2d center;
|
||||||
|
double radius;
|
||||||
|
BedShape bed_shape =
|
||||||
|
GUI::Bed3D::is_rectangle(opt->values) ? BedShape::Rectangle :
|
||||||
|
GUI::Bed3D::is_circle(opt->values, ¢er, &radius) ? BedShape::Circle :
|
||||||
|
GUI::Bed3D::is_convex(opt->values) ? BedShape::Convex : BedShape::NonConvex;
|
||||||
|
|
||||||
for (GLVolume* volume : this->volumes) {
|
for (GLVolume* volume : this->volumes) {
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
if (as_toolpaths && !volume->is_extrusion_path)
|
if (as_toolpaths && !volume->is_extrusion_path)
|
||||||
|
@ -1048,15 +1058,11 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, M
|
||||||
else if (!as_toolpaths && (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0))))
|
else if (!as_toolpaths && (volume->is_modifier || (!volume->shader_outside_printer_detection_enabled && (volume->is_wipe_tower || volume->composite_id.volume_id < 0))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (GUI::Bed3D::is_rectangle(opt->values))
|
switch (bed_shape) {
|
||||||
check_against_rectangular_bed(*volume, overall_state);
|
case BedShape::Rectangle: check_against_rectangular_bed(*volume, overall_state); break;
|
||||||
else {
|
case BedShape::Circle: check_against_circular_bed(*volume, overall_state, center, radius); break;
|
||||||
Vec2d center;
|
case BedShape::Convex: check_against_convex_bed(*volume, overall_state); break;
|
||||||
double radius;
|
default: break;
|
||||||
if (GUI::Bed3D::is_circle(opt->values, ¢er, &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;
|
contained_min_one |= !volume->is_outside;
|
||||||
|
|
|
@ -3011,9 +3011,9 @@ void Plater::priv::update_print_volume_state()
|
||||||
{
|
{
|
||||||
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
#if ENABLE_OUT_OF_BED_DETECTION_IMPROVEMENTS
|
||||||
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(this->config->option("bed_shape"));
|
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(this->config->option("bed_shape"));
|
||||||
const Polygon bed_poly = offset(Polygon::new_scale(opt->values), static_cast<float>(scale_(BedEpsilon))).front();
|
const Polygon bed_poly_convex = offset(Geometry::convex_hull(Polygon::new_scale(opt->values).points), static_cast<float>(scale_(BedEpsilon))).front();
|
||||||
const float bed_height = this->config->opt_float("max_print_height");
|
const float bed_height = this->config->opt_float("max_print_height");
|
||||||
this->q->model().update_print_volume_state(bed_poly, bed_height);
|
this->q->model().update_print_volume_state(bed_poly_convex, bed_height);
|
||||||
#else
|
#else
|
||||||
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(this->config->opt<ConfigOptionPoints>("bed_shape")->values));
|
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(this->config->opt<ConfigOptionPoints>("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"))));
|
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"))));
|
||||||
|
|
Loading…
Add table
Reference in a new issue