More robust fix for 3D view and GUI buttons not in synch when object's size is almost identical to print volume's size

This commit is contained in:
Enrico Turri 2018-04-24 09:00:33 +02:00
parent 973060c728
commit 71d9500b2e
11 changed files with 33 additions and 76 deletions

View file

@ -1396,7 +1396,7 @@ sub Render {
if ($self->enable_picking) { if ($self->enable_picking) {
$self->mark_volumes_for_layer_height; $self->mark_volumes_for_layer_height;
$self->volumes->set_print_box($self->bed_bounding_box->x_min, $self->bed_bounding_box->y_min, 0.0, $self->bed_bounding_box->x_max, $self->bed_bounding_box->y_max, $self->{config}->get('max_print_height')); $self->volumes->set_print_box($self->bed_bounding_box->x_min, $self->bed_bounding_box->y_min, 0.0, $self->bed_bounding_box->x_max, $self->bed_bounding_box->y_max, $self->{config}->get('max_print_height'));
$self->volumes->update_outside_state($self->{config}, 0); $self->volumes->check_outside_state($self->{config});
# do not cull backfaces to show broken geometry, if any # do not cull backfaces to show broken geometry, if any
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
} }

View file

@ -1921,7 +1921,7 @@ sub object_list_changed {
} }
my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file}; my $export_in_progress = $self->{export_gcode_output_file} || $self->{send_gcode_file};
my $model_fits = $self->{model}->fits_print_volume($self->{config}); my $model_fits = $self->{canvas3D} ? $self->{canvas3D}->volumes->check_outside_state($self->{config}) : 1;
my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable'; my $method = ($have_objects && ! $export_in_progress && $model_fits) ? 'Enable' : 'Disable';
$self->{"btn_$_"}->$method $self->{"btn_$_"}->$method
for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode); for grep $self->{"btn_$_"}, qw(reslice export_gcode print send_gcode);

View file

@ -222,13 +222,14 @@ sub reload_scene {
# checks for geometry outside the print volume to render it accordingly # checks for geometry outside the print volume to render it accordingly
if (scalar @{$self->volumes} > 0) if (scalar @{$self->volumes} > 0)
{ {
if (!$self->{model}->fits_print_volume($self->{config})) { my $contained = $self->volumes->check_outside_state($self->{config});
if (!$contained) {
$self->set_warning_enabled(1); $self->set_warning_enabled(1);
Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume")); Slic3r::GUI::_3DScene::generate_warning_texture(L("Detected object outside print volume"));
$self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons); $self->on_enable_action_buttons->(0) if ($self->on_enable_action_buttons);
} else { } else {
$self->set_warning_enabled(0); $self->set_warning_enabled(0);
$self->volumes->update_outside_state($self->{config}, 1); $self->volumes->reset_outside_state();
Slic3r::GUI::_3DScene::reset_warning_texture(); Slic3r::GUI::_3DScene::reset_warning_texture();
$self->on_enable_action_buttons->(1) if ($self->on_enable_action_buttons); $self->on_enable_action_buttons->(1) if ($self->on_enable_action_buttons);
} }

View file

@ -147,31 +147,6 @@ public:
BoundingBoxf3() : BoundingBox3Base<Pointf3>() {}; BoundingBoxf3() : BoundingBox3Base<Pointf3>() {};
BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {}; BoundingBoxf3(const Pointf3 &pmin, const Pointf3 &pmax) : BoundingBox3Base<Pointf3>(pmin, pmax) {};
BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {}; BoundingBoxf3(const std::vector<Pointf3> &points) : BoundingBox3Base<Pointf3>(points) {};
// check if the given point is contained inside this bounding box
// all quantities are compared after being quantized to try to reduce instability due to float imprecision
bool contains_quantized(const Pointf3& point) const {
struct Helper
{
static coordf_t quantize(coordf_t value)
{
static const coordf_t INV_EPSILON = 1.0 / EPSILON;
return round(value * INV_EPSILON + 0.5) * EPSILON;
}
};
coordf_t x = Helper::quantize(point.x);
coordf_t y = Helper::quantize(point.y);
coordf_t z = Helper::quantize(point.z);
return (Helper::quantize(min.x) <= x) && (x <= Helper::quantize(max.x))
&& (Helper::quantize(min.y) <= y) && (y <= Helper::quantize(max.y))
&& (Helper::quantize(min.z) <= z) && (z <= Helper::quantize(max.z));
}
bool contains_quantized(const BoundingBoxf3& other) const {
return contains_quantized(other.min) && contains_quantized(other.max);
}
}; };
template<typename VT> template<typename VT>

View file

@ -447,36 +447,6 @@ void Model::adjust_min_z()
} }
} }
bool Model::fits_print_volume(const DynamicPrintConfig* config) const
{
if (config == nullptr)
return false;
if (objects.empty())
return true;
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape"));
if (opt == nullptr)
return false;
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height")));
// Allow the objects to protrude below the print bed
print_volume.min.z = -1e10;
return print_volume.contains_quantized(transformed_bounding_box());
}
bool Model::fits_print_volume(const FullPrintConfig &config) const
{
if (objects.empty())
return true;
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height));
// Allow the objects to protrude below the print bed
print_volume.min.z = -1e10;
return print_volume.contains_quantized(transformed_bounding_box());
}
unsigned int Model::get_auto_extruder_id() unsigned int Model::get_auto_extruder_id()
{ {
unsigned int id = s_auto_extruder_id; unsigned int id = s_auto_extruder_id;

View file

@ -285,10 +285,6 @@ public:
// Ensures that the min z of the model is not negative // Ensures that the min z of the model is not negative
void adjust_min_z(); void adjust_min_z();
// Returs true if this model is contained into the print volume defined inside the given config
bool fits_print_volume(const DynamicPrintConfig* config) const;
bool fits_print_volume(const FullPrintConfig &config) const;
void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); } void print_info() const { for (const ModelObject *o : this->objects) o->print_info(); }
static unsigned int get_auto_extruder_id(); static unsigned int get_auto_extruder_id();

View file

@ -522,7 +522,7 @@ std::string Print::validate() const
// Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced. // Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
print_volume.min.z = -1e10; print_volume.min.z = -1e10;
for (PrintObject *po : this->objects) { for (PrintObject *po : this->objects) {
if (!print_volume.contains_quantized(po->model_object()->tight_bounding_box(false))) if (!print_volume.contains(po->model_object()->tight_bounding_box(false)))
return "Some objects are outside of the print volume."; return "Some objects are outside of the print volume.";
} }

View file

@ -643,29 +643,40 @@ void GLVolumeCollection::render_legacy() const
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void GLVolumeCollection::update_outside_state(const DynamicPrintConfig* config, bool all_inside) bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
{ {
if (config == nullptr) if (config == nullptr)
return; return false;
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape")); const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config->option("bed_shape"));
if (opt == nullptr) if (opt == nullptr)
return; return false;
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values)); BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height"))); BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config->opt_float("max_print_height")));
// Allow the objects to protrude below the print bed // Allow the objects to protrude below the print bed
print_volume.min.z = -1e10; print_volume.min.z = -1e10;
bool contained = true;
for (GLVolume* volume : this->volumes) for (GLVolume* volume : this->volumes)
{ {
if (all_inside) if (volume != nullptr)
{ {
volume->is_outside = false; bool state = print_volume.contains(volume->transformed_bounding_box());
continue; contained &= state;
volume->is_outside = !state;
} }
}
volume->is_outside = !print_volume.contains_quantized(volume->transformed_bounding_box()); return contained;
}
void GLVolumeCollection::reset_outside_state()
{
for (GLVolume* volume : this->volumes)
{
if (volume != nullptr)
volume->is_outside = false;
} }
} }

View file

@ -422,7 +422,9 @@ public:
print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z; print_box_max[0] = max_x; print_box_max[1] = max_y; print_box_max[2] = max_z;
} }
void update_outside_state(const DynamicPrintConfig* config, bool all_inside); bool check_outside_state(const DynamicPrintConfig* config);
void reset_outside_state();
void update_colors_by_extruder(const DynamicPrintConfig* config); void update_colors_by_extruder(const DynamicPrintConfig* config);
// Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection // Returns a vector containing the sorted list of all the print_zs of the volumes contained in this collection

View file

@ -104,7 +104,12 @@
void release_geometry(); void release_geometry();
void set_print_box(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z); void set_print_box(float min_x, float min_y, float min_z, float max_x, float max_y, float max_z);
void update_outside_state(DynamicPrintConfig* config, bool all_inside); bool check_outside_state(DynamicPrintConfig* config)
%code%{
RETVAL = THIS->check_outside_state(config);
%};
void reset_outside_state();
void update_colors_by_extruder(DynamicPrintConfig* config); void update_colors_by_extruder(DynamicPrintConfig* config);
bool move_volume_up(int idx) bool move_volume_up(int idx)

View file

@ -99,9 +99,6 @@
void print_info() const; void print_info() const;
bool fits_print_volume(DynamicPrintConfig* config) const
%code%{ RETVAL = THIS->fits_print_volume(config); %};
bool store_stl(char *path, bool binary) bool store_stl(char *path, bool binary)
%code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %}; %code%{ TriangleMesh mesh = THIS->mesh(); RETVAL = Slic3r::store_stl(path, &mesh, binary); %};
bool store_amf(char *path, Print* print, bool export_print_config) bool store_amf(char *path, Print* print, bool export_print_config)