Merge branch 'master' of https://github.com/prusa3d/Slic3r into objects_centering
This commit is contained in:
commit
c2c7a3ad8f
13 changed files with 105 additions and 72 deletions
BIN
resources/models/sl1_bed.stl
Normal file
BIN
resources/models/sl1_bed.stl
Normal file
Binary file not shown.
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -738,45 +738,46 @@ public:
|
|||
const TriangleMesh& merged_mesh() const {
|
||||
if(meshcache_valid) return meshcache;
|
||||
|
||||
meshcache = TriangleMesh();
|
||||
Contour3D merged;
|
||||
|
||||
for(auto& head : heads()) {
|
||||
if(m_ctl.stopcondition()) break;
|
||||
if(head.is_valid()) {
|
||||
auto&& m = mesh(head.mesh);
|
||||
meshcache.merge(m);
|
||||
}
|
||||
if(head.is_valid())
|
||||
merged.merge(head.mesh);
|
||||
}
|
||||
|
||||
for(auto& stick : pillars()) {
|
||||
if(m_ctl.stopcondition()) break;
|
||||
meshcache.merge(mesh(stick.mesh));
|
||||
meshcache.merge(mesh(stick.base));
|
||||
merged.merge(stick.mesh);
|
||||
merged.merge(stick.base);
|
||||
}
|
||||
|
||||
for(auto& j : junctions()) {
|
||||
if(m_ctl.stopcondition()) break;
|
||||
meshcache.merge(mesh(j.mesh));
|
||||
merged.merge(j.mesh);
|
||||
}
|
||||
|
||||
for(auto& cb : compact_bridges()) {
|
||||
if(m_ctl.stopcondition()) break;
|
||||
meshcache.merge(mesh(cb.mesh));
|
||||
merged.merge(cb.mesh);
|
||||
}
|
||||
|
||||
for(auto& bs : bridges()) {
|
||||
if(m_ctl.stopcondition()) break;
|
||||
meshcache.merge(mesh(bs.mesh));
|
||||
merged.merge(bs.mesh);
|
||||
}
|
||||
|
||||
|
||||
if(m_ctl.stopcondition()) {
|
||||
// In case of failure we have to return an empty mesh
|
||||
meshcache = TriangleMesh();
|
||||
return meshcache;
|
||||
}
|
||||
|
||||
meshcache = mesh(merged);
|
||||
|
||||
// TODO: Is this necessary?
|
||||
meshcache.repair();
|
||||
//meshcache.repair();
|
||||
|
||||
BoundingBoxf3&& bb = meshcache.bounding_box();
|
||||
model_height = bb.max(Z) - bb.min(Z);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// Improves navigation between sidebar fields
|
||||
#define ENABLE_IMPROVED_SIDEBAR_OBJECTS_MANIPULATION (1 && ENABLE_1_42_0_ALPHA2)
|
||||
// Adds print bed models to 3D scene
|
||||
#define ENABLE_PRINT_BED_MODELS (0 && ENABLE_1_42_0_ALPHA2)
|
||||
#define ENABLE_PRINT_BED_MODELS (1 && ENABLE_1_42_0_ALPHA2)
|
||||
#endif // _technologies_h_
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -588,7 +588,7 @@ void GLCanvas3D::Bed::_render_prusa(const std::string &key, float theta) const
|
|||
{
|
||||
filename = model_path + "_bed.stl";
|
||||
if ((m_model.get_filename() != filename) && m_model.init_from_file(filename, useVBOs))
|
||||
m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 1.0 + 0.5 * m_model.get_bounding_box().size()(2)));
|
||||
m_model.center_around(m_bounding_box.center() - Vec3d(0.0, 0.0, 0.1 + 0.5 * m_model.get_bounding_box().size()(2)));
|
||||
|
||||
if (!m_model.get_filename().empty())
|
||||
{
|
||||
|
@ -1197,11 +1197,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()
|
||||
|
@ -5061,7 +5062,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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1574,15 +1574,17 @@ void GLGizmoFlatten::update_planes()
|
|||
m_planes.pop_back();
|
||||
}
|
||||
|
||||
// Let's prepare transformation of the normal vector from mesh to instance coordinates.
|
||||
Geometry::Transformation t(inst_matrix);
|
||||
Vec3d scaling = t.get_scaling_factor();
|
||||
t.set_scaling_factor(Vec3d(1./scaling(0), 1./scaling(1), 1./scaling(2)));
|
||||
|
||||
// Now we'll go through all the polygons, transform the points into xy plane to process them:
|
||||
for (unsigned int polygon_id=0; polygon_id < m_planes.size(); ++polygon_id) {
|
||||
Pointf3s& polygon = m_planes[polygon_id].vertices;
|
||||
const Vec3d& normal = m_planes[polygon_id].normal;
|
||||
|
||||
// let's transform the normal accodring to the instance matrix:
|
||||
Geometry::Transformation t(inst_matrix);
|
||||
Vec3d scaling = t.get_scaling_factor();
|
||||
t.set_scaling_factor(Vec3d(1./(scaling(0)*scaling(0)), 1./(scaling(0)*scaling(0)), 1./(scaling(0)*scaling(0))));
|
||||
// transform the normal according to the instance matrix:
|
||||
Vec3d normal_transformed = t.get_matrix() * normal;
|
||||
|
||||
// We are going to rotate about z and y to flatten the plane
|
||||
|
|
|
@ -194,6 +194,8 @@ bool GUI_App::OnInit()
|
|||
preset_updater->slic3r_update_notify();
|
||||
}
|
||||
preset_updater->sync(preset_bundle);
|
||||
|
||||
load_current_presets();
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -155,7 +155,6 @@ void MainFrame::create_preset_tabs()
|
|||
add_created_tab(new TabSLAPrint(m_tabpanel));
|
||||
add_created_tab(new TabSLAMaterial(m_tabpanel));
|
||||
add_created_tab(new TabPrinter(m_tabpanel));
|
||||
GUI::wxGetApp().load_current_presets();
|
||||
}
|
||||
|
||||
void MainFrame::add_created_tab(Tab* panel)
|
||||
|
|
|
@ -49,8 +49,6 @@ _constant()
|
|||
Ref<StaticPrintConfig> config()
|
||||
%code%{ RETVAL = &THIS->config(); %};
|
||||
Points copies();
|
||||
std::vector<double> layer_height_profile()
|
||||
%code%{ RETVAL = THIS->layer_height_profile; %};
|
||||
Clone<BoundingBox> bounding_box();
|
||||
|
||||
Points _shifted_copies()
|
||||
|
|
Loading…
Reference in a new issue