Disable slicing when one object crosses the print volume boundary
This commit is contained in:
parent
d672a69554
commit
d805c8ac3b
@ -103,6 +103,10 @@ public:
|
|||||||
bool contains(const BoundingBox3Base<PointClass>& other) const {
|
bool contains(const BoundingBox3Base<PointClass>& other) const {
|
||||||
return contains(other.min) && contains(other.max);
|
return contains(other.min) && contains(other.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool intersects(const BoundingBox3Base<PointClass>& other) const {
|
||||||
|
return (min.x < other.max.x) && (max.x > other.min.x) && (min.y < other.max.y) && (max.y > other.min.y) && (min.z < other.max.z) && (max.z > other.min.z);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BoundingBox : public BoundingBoxBase<Point>
|
class BoundingBox : public BoundingBoxBase<Point>
|
||||||
|
@ -1235,7 +1235,7 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelObject::check_instances_printability(const BoundingBoxf3& print_volume)
|
void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_volume)
|
||||||
{
|
{
|
||||||
for (ModelVolume* vol : this->volumes)
|
for (ModelVolume* vol : this->volumes)
|
||||||
{
|
{
|
||||||
@ -1274,10 +1274,15 @@ void ModelObject::check_instances_printability(const BoundingBoxf3& print_volume
|
|||||||
p.y += inst->offset.y;
|
p.y += inst->offset.y;
|
||||||
|
|
||||||
bb.merge(p);
|
bb.merge(p);
|
||||||
|
|
||||||
inst->is_printable = print_volume.contains(bb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (print_volume.contains(bb))
|
||||||
|
inst->print_volume_state = ModelInstance::PVS_Inside;
|
||||||
|
else if (print_volume.intersects(bb))
|
||||||
|
inst->print_volume_state = ModelInstance::PVS_Partly_Outside;
|
||||||
|
else
|
||||||
|
inst->print_volume_state = ModelInstance::PVS_Fully_Outside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,8 @@ public:
|
|||||||
bool needed_repair() const;
|
bool needed_repair() const;
|
||||||
void cut(coordf_t z, Model* model) const;
|
void cut(coordf_t z, Model* model) const;
|
||||||
void split(ModelObjectPtrs* new_objects);
|
void split(ModelObjectPtrs* new_objects);
|
||||||
void check_instances_printability(const BoundingBoxf3& print_volume);
|
|
||||||
|
void check_instances_print_volume_state(const BoundingBoxf3& print_volume);
|
||||||
|
|
||||||
// Print object statistics to console.
|
// Print object statistics to console.
|
||||||
void print_info() const;
|
void print_info() const;
|
||||||
@ -198,14 +199,23 @@ private:
|
|||||||
// Knows the affine transformation of an object.
|
// Knows the affine transformation of an object.
|
||||||
class ModelInstance
|
class ModelInstance
|
||||||
{
|
{
|
||||||
friend class ModelObject;
|
|
||||||
public:
|
public:
|
||||||
|
enum EPrintVolumeState : unsigned char
|
||||||
|
{
|
||||||
|
PVS_Inside,
|
||||||
|
PVS_Partly_Outside,
|
||||||
|
PVS_Fully_Outside,
|
||||||
|
Num_BedStates
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class ModelObject;
|
||||||
|
|
||||||
double rotation; // Rotation around the Z axis, in radians around mesh center point
|
double rotation; // Rotation around the Z axis, in radians around mesh center point
|
||||||
double scaling_factor;
|
double scaling_factor;
|
||||||
Pointf offset; // in unscaled coordinates
|
Pointf offset; // in unscaled coordinates
|
||||||
|
|
||||||
// whether or not this instance is contained in the print volume (set by Print::validate() using ModelObject::check_instances_printability())
|
// flag showing the position of this instance with respect to the print volume (set by Print::validate() using ModelObject::check_instances_print_volume_state())
|
||||||
bool is_printable;
|
EPrintVolumeState print_volume_state;
|
||||||
|
|
||||||
ModelObject* get_object() const { return this->object; }
|
ModelObject* get_object() const { return this->object; }
|
||||||
|
|
||||||
@ -217,14 +227,16 @@ public:
|
|||||||
BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const;
|
BoundingBoxf3 transform_bounding_box(const BoundingBoxf3 &bbox, bool dont_translate = false) const;
|
||||||
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
|
// To be called on an external polygon. It does not translate the polygon, only rotates and scales.
|
||||||
void transform_polygon(Polygon* polygon) const;
|
void transform_polygon(Polygon* polygon) const;
|
||||||
|
|
||||||
|
bool is_printable() const { return print_volume_state == PVS_Inside; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Parent object, owning this instance.
|
// Parent object, owning this instance.
|
||||||
ModelObject* object;
|
ModelObject* object;
|
||||||
|
|
||||||
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), is_printable(false) {}
|
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), print_volume_state(PVS_Inside) {}
|
||||||
ModelInstance(ModelObject *object, const ModelInstance &other) :
|
ModelInstance(ModelObject *object, const ModelInstance &other) :
|
||||||
rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), is_printable(false) {}
|
rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), print_volume_state(PVS_Inside) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -543,7 +543,7 @@ std::string Print::validate() const
|
|||||||
print_volume.min.z = -1e10;
|
print_volume.min.z = -1e10;
|
||||||
unsigned int printable_count = 0;
|
unsigned int printable_count = 0;
|
||||||
for (PrintObject *po : this->objects) {
|
for (PrintObject *po : this->objects) {
|
||||||
po->model_object()->check_instances_printability(print_volume);
|
po->model_object()->check_instances_print_volume_state(print_volume);
|
||||||
po->reload_model_instances();
|
po->reload_model_instances();
|
||||||
if (po->is_printable())
|
if (po->is_printable())
|
||||||
++printable_count;
|
++printable_count;
|
||||||
|
@ -103,7 +103,7 @@ bool PrintObject::reload_model_instances()
|
|||||||
copies.reserve(this->_model_object->instances.size());
|
copies.reserve(this->_model_object->instances.size());
|
||||||
for (const ModelInstance *mi : this->_model_object->instances)
|
for (const ModelInstance *mi : this->_model_object->instances)
|
||||||
{
|
{
|
||||||
if (mi->is_printable)
|
if (mi->is_printable())
|
||||||
copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y));
|
copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y));
|
||||||
}
|
}
|
||||||
return this->set_copies(copies);
|
return this->set_copies(copies);
|
||||||
|
@ -743,7 +743,7 @@ void GLVolumeCollection::render_legacy() const
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
|
bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state)
|
||||||
{
|
{
|
||||||
if (config == nullptr)
|
if (config == nullptr)
|
||||||
return false;
|
return false;
|
||||||
@ -757,18 +757,31 @@ bool GLVolumeCollection::check_outside_state(const DynamicPrintConfig* config)
|
|||||||
// 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;
|
ModelInstance::EPrintVolumeState state = ModelInstance::PVS_Inside;
|
||||||
|
bool all_contained = true;
|
||||||
|
|
||||||
for (GLVolume* volume : this->volumes)
|
for (GLVolume* volume : this->volumes)
|
||||||
{
|
{
|
||||||
if ((volume != nullptr) && !volume->is_modifier)
|
if ((volume != nullptr) && !volume->is_modifier)
|
||||||
{
|
{
|
||||||
bool state = print_volume.contains(volume->transformed_bounding_box());
|
const BoundingBoxf3& bb = volume->transformed_bounding_box();
|
||||||
contained &= state;
|
bool contained = print_volume.contains(bb);
|
||||||
volume->is_outside = !state;
|
all_contained &= contained;
|
||||||
|
|
||||||
|
volume->is_outside = !contained;
|
||||||
|
|
||||||
|
if ((state == ModelInstance::PVS_Inside) && volume->is_outside)
|
||||||
|
state = ModelInstance::PVS_Fully_Outside;
|
||||||
|
|
||||||
|
if ((state == ModelInstance::PVS_Fully_Outside) && volume->is_outside && print_volume.intersects(bb))
|
||||||
|
state = ModelInstance::PVS_Partly_Outside;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return contained;
|
if (out_state != nullptr)
|
||||||
|
*out_state = state;
|
||||||
|
|
||||||
|
return all_contained;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLVolumeCollection::reset_outside_state()
|
void GLVolumeCollection::reset_outside_state()
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "../../libslic3r/Line.hpp"
|
#include "../../libslic3r/Line.hpp"
|
||||||
#include "../../libslic3r/TriangleMesh.hpp"
|
#include "../../libslic3r/TriangleMesh.hpp"
|
||||||
#include "../../libslic3r/Utils.hpp"
|
#include "../../libslic3r/Utils.hpp"
|
||||||
|
#include "../../libslic3r/Model.hpp"
|
||||||
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
|
#include "../../slic3r/GUI/GLCanvas3DManager.hpp"
|
||||||
|
|
||||||
class wxBitmap;
|
class wxBitmap;
|
||||||
@ -422,7 +423,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_outside_state(const DynamicPrintConfig* config);
|
// 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
|
||||||
|
bool check_outside_state(const DynamicPrintConfig* config, ModelInstance::EPrintVolumeState* out_state);
|
||||||
void reset_outside_state();
|
void reset_outside_state();
|
||||||
|
|
||||||
void update_colors_by_extruder(const DynamicPrintConfig* config);
|
void update_colors_by_extruder(const DynamicPrintConfig* config);
|
||||||
|
@ -1381,7 +1381,8 @@ void GLCanvas3D::Gizmos::render(const GLCanvas3D& canvas, const BoundingBoxf3& b
|
|||||||
|
|
||||||
::glDisable(GL_DEPTH_TEST);
|
::glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
_render_current_gizmo(box);
|
if (box.radius() > 0.0)
|
||||||
|
_render_current_gizmo(box);
|
||||||
|
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glLoadIdentity();
|
::glLoadIdentity();
|
||||||
@ -1657,7 +1658,7 @@ void GLCanvas3D::update_volumes_selection(const std::vector<int>& selections)
|
|||||||
|
|
||||||
bool GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const
|
bool GLCanvas3D::check_volumes_outside_state(const DynamicPrintConfig* config) const
|
||||||
{
|
{
|
||||||
return m_volumes.check_outside_state(config);
|
return m_volumes.check_outside_state(config, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLCanvas3D::move_volume_up(unsigned int id)
|
bool GLCanvas3D::move_volume_up(unsigned int id)
|
||||||
@ -2082,19 +2083,22 @@ void GLCanvas3D::reload_scene(bool force)
|
|||||||
// checks for geometry outside the print volume to render it accordingly
|
// checks for geometry outside the print volume to render it accordingly
|
||||||
if (!m_volumes.empty())
|
if (!m_volumes.empty())
|
||||||
{
|
{
|
||||||
bool contained = m_volumes.check_outside_state(m_config);
|
ModelInstance::EPrintVolumeState state;
|
||||||
|
bool contained = m_volumes.check_outside_state(m_config, &state);
|
||||||
|
|
||||||
if (!contained)
|
if (!contained)
|
||||||
{
|
{
|
||||||
enable_warning_texture(true);
|
enable_warning_texture(true);
|
||||||
_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
_3DScene::generate_warning_texture(L("Detected object outside print volume"));
|
||||||
|
m_on_enable_action_buttons_callback.call(state == ModelInstance::PVS_Fully_Outside);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enable_warning_texture(false);
|
enable_warning_texture(false);
|
||||||
m_volumes.reset_outside_state();
|
m_volumes.reset_outside_state();
|
||||||
_3DScene::reset_warning_texture();
|
_3DScene::reset_warning_texture();
|
||||||
|
m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
|
||||||
}
|
}
|
||||||
m_on_enable_action_buttons_callback.call(!m_model->objects.empty());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3130,6 +3134,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
|
|||||||
m_mouse.set_start_position_3D_as_invalid();
|
m_mouse.set_start_position_3D_as_invalid();
|
||||||
m_mouse.set_start_position_2D_as_invalid();
|
m_mouse.set_start_position_2D_as_invalid();
|
||||||
m_mouse.dragging = false;
|
m_mouse.dragging = false;
|
||||||
|
m_dirty = true;
|
||||||
}
|
}
|
||||||
else if (evt.Moving())
|
else if (evt.Moving())
|
||||||
{
|
{
|
||||||
@ -3272,7 +3277,7 @@ BoundingBoxf3 GLCanvas3D::_selected_volumes_bounding_box() const
|
|||||||
BoundingBoxf3 bb;
|
BoundingBoxf3 bb;
|
||||||
for (const GLVolume* volume : m_volumes.volumes)
|
for (const GLVolume* volume : m_volumes.volumes)
|
||||||
{
|
{
|
||||||
if ((volume != nullptr) && volume->selected)
|
if ((volume != nullptr) && !volume->is_wipe_tower && volume->selected)
|
||||||
bb.merge(volume->transformed_bounding_box());
|
bb.merge(volume->transformed_bounding_box());
|
||||||
}
|
}
|
||||||
return bb;
|
return bb;
|
||||||
@ -3549,7 +3554,7 @@ void GLCanvas3D::_render_objects() const
|
|||||||
{
|
{
|
||||||
const BoundingBoxf3& bed_bb = m_bed.get_bounding_box();
|
const BoundingBoxf3& bed_bb = m_bed.get_bounding_box();
|
||||||
m_volumes.set_print_box((float)bed_bb.min.x, (float)bed_bb.min.y, 0.0f, (float)bed_bb.max.x, (float)bed_bb.max.y, (float)m_config->opt_float("max_print_height"));
|
m_volumes.set_print_box((float)bed_bb.min.x, (float)bed_bb.min.y, 0.0f, (float)bed_bb.max.x, (float)bed_bb.max.y, (float)m_config->opt_float("max_print_height"));
|
||||||
m_volumes.check_outside_state(m_config);
|
m_volumes.check_outside_state(m_config, nullptr);
|
||||||
}
|
}
|
||||||
// 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);
|
||||||
|
@ -105,10 +105,6 @@
|
|||||||
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);
|
||||||
bool check_outside_state(DynamicPrintConfig* config)
|
|
||||||
%code%{
|
|
||||||
RETVAL = THIS->check_outside_state(config);
|
|
||||||
%};
|
|
||||||
|
|
||||||
void reset_outside_state();
|
void reset_outside_state();
|
||||||
void update_colors_by_extruder(DynamicPrintConfig* config);
|
void update_colors_by_extruder(DynamicPrintConfig* config);
|
||||||
|
Loading…
Reference in New Issue
Block a user