Fixed update on reset of the variable layer height profile.

Fixed update of the layer height profile on PrintObject when changing profiles.
Fixed crash due to the layer height editing refactoring & wipe tower.
This commit is contained in:
bubnikv 2019-01-23 14:00:03 +01:00
parent 94b5f9c567
commit 0af11c51e3
6 changed files with 83 additions and 52 deletions

View file

@ -1125,7 +1125,7 @@ std::string Print::validate() const
// Check horizontal clearance.
{
Polygons convex_hulls_other;
for (PrintObject *object : m_objects) {
for (const PrintObject *object : m_objects) {
// Get convex hull of all meshes assigned to this print object.
Polygon convex_hull;
{
@ -1186,46 +1186,63 @@ std::string Print::validate() const
return L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter and Repetier G-code flavors.");
if (! m_config.use_relative_e_distances)
return L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
const PrintObject* tallest_object = m_objects.front(); // let's find the tallest object
for (const auto* object : m_objects)
if (*(object->layer_height_profile.end()-2) > *(tallest_object->layer_height_profile.end()-2) )
tallest_object = object;
for (PrintObject *object : m_objects) {
SlicingParameters slicing_params = object->slicing_parameters();
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance)
return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
if (! equal_layering(slicing_params, slicing_params0))
return L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
if (m_config.variable_layer_height) { // comparing layer height profiles
bool failed = false;
// layer_height_profile should be set by Print::apply().
if (tallest_object->layer_height_profile.size() >= object->layer_height_profile.size()) {
int i = 0;
while (i < object->layer_height_profile.size() && i < tallest_object->layer_height_profile.size()) {
if (std::abs(tallest_object->layer_height_profile[i] - object->layer_height_profile[i])) {
failed = true;
break;
}
++i;
if (i == object->layer_height_profile.size()-2) // this element contains this objects max z
if (tallest_object->layer_height_profile[i] > object->layer_height_profile[i]) // the difference does not matter in this case
++i;
}
if (m_objects.size() > 1) {
bool has_custom_layering = false;
std::vector<std::vector<coordf_t>> layer_height_profiles;
for (const PrintObject *object : m_objects) {
has_custom_layering = ! object->model_object()->layer_height_ranges.empty() || ! object->model_object()->layer_height_profile.empty();
if (has_custom_layering) {
layer_height_profiles.assign(m_objects.size(), std::vector<coordf_t>());
break;
}
else
failed = true;
}
SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
size_t tallest_object_idx = 0;
if (has_custom_layering)
PrintObject::update_layer_height_profile(*m_objects.front()->model_object(), slicing_params0, layer_height_profiles.front());
for (size_t i = 1; i < m_objects.size(); ++ i) {
const PrintObject *object = m_objects[i];
const SlicingParameters slicing_params = object->slicing_parameters();
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
return L("The Wipe Tower is only supported for multiple objects if they have equal layer heigths");
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
return L("The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers");
if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance)
return L("The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance");
if (! equal_layering(slicing_params, slicing_params0))
return L("The Wipe Tower is only supported for multiple objects if they are sliced equally.");
if (has_custom_layering) {
PrintObject::update_layer_height_profile(*object->model_object(), slicing_params, layer_height_profiles[i]);
if (*(layer_height_profiles[i].end()-2) > *(layer_height_profiles[tallest_object_idx].end()-2))
tallest_object_idx = i;
}
}
if (failed)
return L("The Wipe tower is only supported if all objects have the same layer height profile");
if (has_custom_layering) {
const std::vector<coordf_t> &layer_height_profile_tallest = layer_height_profiles[tallest_object_idx];
for (size_t idx_object = 0; idx_object < m_objects.size(); ++ idx_object) {
const PrintObject *object = m_objects[idx_object];
const std::vector<coordf_t> &layer_height_profile = layer_height_profiles[idx_object];
bool failed = false;
if (layer_height_profile_tallest.size() >= layer_height_profile.size()) {
int i = 0;
while (i < layer_height_profile.size() && i < layer_height_profile_tallest.size()) {
if (std::abs(layer_height_profile_tallest[i] - layer_height_profile[i])) {
failed = true;
break;
}
++ i;
if (i == layer_height_profile.size() - 2) // this element contains this objects max z
if (layer_height_profile_tallest[i] > layer_height_profile[i]) // the difference does not matter in this case
++ i;
}
} else
failed = true;
if (failed)
return L("The Wipe tower is only supported if all objects have the same layer height profile");
}
}
}
}

View file

@ -83,10 +83,6 @@ public:
// vector of (vectors of volume ids), indexed by region_id
std::vector<std::vector<int>> region_volumes;
// Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers.
// The pairs of <z, layer_height> are packed into a 1D array.
std::vector<coordf_t> layer_height_profile;
// this is set to true when LayerRegion->slices is split in top/internal/bottom
// so that next call to make_perimeters() performs a union() before computing loops
bool typed_slices;
@ -175,7 +171,7 @@ private:
void infill();
void generate_support_material();
void _slice();
void _slice(const std::vector<coordf_t> &layer_height_profile);
std::string _fix_slicing_errors();
void _simplify_slices(double distance);
void _make_perimeters();

View file

@ -64,8 +64,6 @@ PrintObject::PrintObject(Print* print, ModelObject* model_object, bool add_insta
}
this->set_copies(copies);
}
this->layer_height_profile = model_object->layer_height_profile;
}
PrintBase::ApplyStatus PrintObject::set_copies(const Points &points)
@ -105,9 +103,10 @@ void PrintObject::slice()
if (! this->set_started(posSlice))
return;
m_print->set_status(10, "Processing triangulated mesh");
this->update_layer_height_profile(*this->model_object(), this->slicing_parameters(), this->layer_height_profile);
std::vector<coordf_t> layer_height_profile;
this->update_layer_height_profile(*this->model_object(), this->slicing_parameters(), layer_height_profile);
m_print->throw_if_canceled();
this->_slice();
this->_slice(layer_height_profile);
m_print->throw_if_canceled();
// Fix the model.
//FIXME is this the right place to do? It is done repeateadly at the UI and now here at the backend.
@ -1438,7 +1437,7 @@ bool PrintObject::update_layer_height_profile(const ModelObject &model_object, c
// Resulting expolygons of layer regions are marked as Internal.
//
// this should be idempotent
void PrintObject::_slice()
void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
{
BOOST_LOG_TRIVIAL(info) << "Slicing objects..." << log_memory_info();
@ -1457,7 +1456,7 @@ void PrintObject::_slice()
{
this->clear_layers();
// Object layers (pairs of bottom/top Z coordinate), without the raft.
std::vector<coordf_t> object_layers = generate_object_layers(slicing_params, this->layer_height_profile);
std::vector<coordf_t> object_layers = generate_object_layers(slicing_params, layer_height_profile);
// Reserve object layers for the raft. Last layer of the raft is the contact layer.
int id = int(slicing_params.raft_layers());
slice_zs.reserve(object_layers.size());

View file

@ -99,6 +99,8 @@ TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
return *this;
}
// #define SLIC3R_TRACE_REPAIR
void TriangleMesh::repair()
{
if (this->repaired) return;
@ -109,7 +111,9 @@ void TriangleMesh::repair()
BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() started";
// checking exact
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_exact";
#endif /* SLIC3R_TRACE_REPAIR */
stl_check_facets_exact(&stl);
stl.stats.facets_w_1_bad_edge = (stl.stats.connected_facets_2_edge - stl.stats.connected_facets_3_edge);
stl.stats.facets_w_2_bad_edge = (stl.stats.connected_facets_1_edge - stl.stats.connected_facets_2_edge);
@ -124,7 +128,9 @@ void TriangleMesh::repair()
for (int i = 0; i < iterations; i++) {
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_check_faces_nearby";
#endif /* SLIC3R_TRACE_REPAIR */
stl_check_facets_nearby(&stl, tolerance);
//printf(" Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed);
//last_edges_fixed = stl.stats.edges_fixed;
@ -137,7 +143,9 @@ void TriangleMesh::repair()
// remove_unconnected
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_remove_unconnected_facets";
#endif /* SLIC3R_TRACE_REPAIR */
stl_remove_unconnected_facets(&stl);
}
@ -146,26 +154,36 @@ void TriangleMesh::repair()
// Don't fill holes, the current algorithm does more harm than good on complex holes.
// Rather let the slicing algorithm close gaps in 2D slices.
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_fill_holes";
#endif /* SLIC3R_TRACE_REPAIR */
stl_fill_holes(&stl);
stl_clear_error(&stl);
}
#endif
// normal_directions
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_directions";
#endif /* SLIC3R_TRACE_REPAIR */
stl_fix_normal_directions(&stl);
// normal_values
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_fix_normal_values";
#endif /* SLIC3R_TRACE_REPAIR */
stl_fix_normal_values(&stl);
// always calculate the volume and reverse all normals if volume is negative
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_calculate_volume";
#endif /* SLIC3R_TRACE_REPAIR */
stl_calculate_volume(&stl);
// neighbors
#ifdef SLIC3R_TRACE_REPAIR
BOOST_LOG_TRIVIAL(trace) << "\tstl_verify_neighbors";
#endif /* SLIC3R_TRACE_REPAIR */
stl_verify_neighbors(&stl);
this->repaired = true;

View file

@ -1179,11 +1179,12 @@ void GLCanvas3D::LayersEditing::adjust_layer_height_profile()
m_layers_texture.valid = false;
}
void GLCanvas3D::LayersEditing::reset_layer_height_profile()
void GLCanvas3D::LayersEditing::reset_layer_height_profile(GLCanvas3D& canvas)
{
const_cast<ModelObject*>(m_model_object)->layer_height_profile.clear();
m_layer_height_profile.clear();
m_layers_texture.valid = false;
canvas.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
}
void GLCanvas3D::LayersEditing::generate_layer_height_texture()
@ -5117,7 +5118,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
if (evt.LeftDown())
{
// A volume is selected and the mouse is inside the reset button. Reset the ModelObject's layer height profile.
m_layers_editing.reset_layer_height_profile();
m_layers_editing.reset_layer_height_profile(*this);
// Index 2 means no editing, just wait for mouse up event.
m_layers_editing.state = LayersEditing::Completed;

View file

@ -360,7 +360,7 @@ class GLCanvas3D
void adjust_layer_height_profile();
void accept_changes(GLCanvas3D& canvas);
void reset_layer_height_profile();
void reset_layer_height_profile(GLCanvas3D& canvas);
static float get_cursor_z_relative(const GLCanvas3D& canvas);
static bool bar_rect_contains(const GLCanvas3D& canvas, float x, float y);