diff options
author | Enrico Turri <enricoturri@seznam.cz> | 2018-07-18 10:37:25 +0300 |
---|---|---|
committer | Enrico Turri <enricoturri@seznam.cz> | 2018-07-18 10:37:25 +0300 |
commit | d672a69554097aa445c710e5bfe84f4dbfa4a246 (patch) | |
tree | 90e792ef1f866b04d919dc9ea6e3852867cda17d | |
parent | eb95e29be6dac00c8ed371fffeb80c5105e9db0e (diff) |
Slice only objects contained into the print volume
-rw-r--r-- | xs/src/libslic3r/GCode.cpp | 7 | ||||
-rw-r--r-- | xs/src/libslic3r/GCode/ToolOrdering.cpp | 6 | ||||
-rw-r--r-- | xs/src/libslic3r/Model.cpp | 48 | ||||
-rw-r--r-- | xs/src/libslic3r/Model.hpp | 8 | ||||
-rw-r--r-- | xs/src/libslic3r/Print.cpp | 27 | ||||
-rw-r--r-- | xs/src/libslic3r/Print.hpp | 4 | ||||
-rw-r--r-- | xs/src/libslic3r/PrintObject.cpp | 17 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/GLCanvas3D.cpp | 4 |
8 files changed, 105 insertions, 16 deletions
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 98b3b4061..4345f2d07 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -776,9 +776,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) // Order objects using a nearest neighbor search. std::vector<size_t> object_indices; Points object_reference_points; - for (PrintObject *object : print.objects) + PrintObjectPtrs printable_objects = print.get_printable_objects(); + for (PrintObject *object : printable_objects) object_reference_points.push_back(object->_shifted_copies.front()); - Slic3r::Geometry::chained_path(object_reference_points, object_indices); + Slic3r::Geometry::chained_path(object_reference_points, object_indices); // Sort layers by Z. // All extrusion moves with the same top layer height are extruded uninterrupted. std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print); @@ -790,7 +791,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) // Verify, whether the print overaps the priming extrusions. BoundingBoxf bbox_print(get_print_extrusions_extents(print)); coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON; - for (const PrintObject *print_object : print.objects) + for (const PrintObject *print_object : printable_objects) bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz)); bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz)); BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print)); diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp index f1dbbfc1e..2a85319aa 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.cpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp @@ -67,11 +67,13 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material) { m_print_config_ptr = &print.config; + + PrintObjectPtrs objects = print.get_printable_objects(); // Initialize the print layers for all objects and all layers. coordf_t object_bottom_z = 0.; { std::vector<coordf_t> zs; - for (auto object : print.objects) { + for (auto object : objects) { zs.reserve(zs.size() + object->layers.size() + object->support_layers.size()); for (auto layer : object->layers) zs.emplace_back(layer->print_z); @@ -84,7 +86,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool } // Collect extruders reuqired to print the layers. - for (auto object : print.objects) + for (auto object : objects) this->collect_extruders(*object); // Reorder the extruders to minimize tool switches. diff --git a/xs/src/libslic3r/Model.cpp b/xs/src/libslic3r/Model.cpp index 2925251eb..bd95d9959 100644 --- a/xs/src/libslic3r/Model.cpp +++ b/xs/src/libslic3r/Model.cpp @@ -1235,6 +1235,54 @@ void ModelObject::split(ModelObjectPtrs* new_objects) return; } +void ModelObject::check_instances_printability(const BoundingBoxf3& print_volume) +{ + for (ModelVolume* vol : this->volumes) + { + if (!vol->modifier) + { + for (ModelInstance* inst : this->instances) + { + BoundingBoxf3 bb; + + double c = cos(inst->rotation); + double s = sin(inst->rotation); + + for (int f = 0; f < vol->mesh.stl.stats.number_of_facets; ++f) + { + const stl_facet& facet = vol->mesh.stl.facet_start[f]; + + for (int i = 0; i < 3; ++i) + { + // original point + const stl_vertex& v = facet.vertex[i]; + Pointf3 p((double)v.x, (double)v.y, (double)v.z); + + // scale + p.x *= inst->scaling_factor; + p.y *= inst->scaling_factor; + p.z *= inst->scaling_factor; + + // rotate Z + double x = p.x; + double y = p.y; + p.x = c * x - s * y; + p.y = s * x + c * y; + + // translate + p.x += inst->offset.x; + p.y += inst->offset.y; + + bb.merge(p); + + inst->is_printable = print_volume.contains(bb); + } + } + } + } + } +} + void ModelObject::print_info() const { using namespace std; diff --git a/xs/src/libslic3r/Model.hpp b/xs/src/libslic3r/Model.hpp index 5003f8330..08ba8487d 100644 --- a/xs/src/libslic3r/Model.hpp +++ b/xs/src/libslic3r/Model.hpp @@ -131,6 +131,7 @@ public: bool needed_repair() const; void cut(coordf_t z, Model* model) const; void split(ModelObjectPtrs* new_objects); + void check_instances_printability(const BoundingBoxf3& print_volume); // Print object statistics to console. void print_info() const; @@ -203,6 +204,9 @@ public: double scaling_factor; 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()) + bool is_printable; + ModelObject* get_object() const { return this->object; } // To be called on an external mesh @@ -218,9 +222,9 @@ private: // Parent object, owning this instance. ModelObject* object; - ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object) {} + ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), is_printable(false) {} ModelInstance(ModelObject *object, const ModelInstance &other) : - rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object) {} + rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), is_printable(false) {} }; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index d10d1a9dc..9c9f7f5bb 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -71,6 +71,13 @@ bool Print::reload_model_instances() return invalidated; } +PrintObjectPtrs Print::get_printable_objects() const +{ + PrintObjectPtrs printable_objects(this->objects); + printable_objects.erase(std::remove_if(printable_objects.begin(), printable_objects.end(), [](PrintObject* o) { return !o->is_printable(); }), printable_objects.end()); + return printable_objects; +} + PrintRegion* Print::add_region() { regions.push_back(new PrintRegion(this)); @@ -534,11 +541,17 @@ std::string Print::validate() const 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, only the part of the object above the print bed will be sliced. print_volume.min.z = -1e10; + unsigned int printable_count = 0; for (PrintObject *po : this->objects) { - if (!print_volume.contains(po->model_object()->tight_bounding_box(false))) - return L("Some objects are outside of the print volume."); + po->model_object()->check_instances_printability(print_volume); + po->reload_model_instances(); + if (po->is_printable()) + ++printable_count; } + if (printable_count == 0) + return L("All objects are outside of the print volume."); + if (this->config.complete_objects) { // Check horizontal clearance. { @@ -858,8 +871,9 @@ void Print::_make_skirt() // prepended to the first 'n' layers (with 'n' = skirt_height). // $skirt_height_z in this case is the highest possible skirt height for safety. coordf_t skirt_height_z = 0.; - for (const PrintObject *object : this->objects) { - size_t skirt_layers = this->has_infinite_skirt() ? + PrintObjectPtrs printable_objects = get_printable_objects(); + for (const PrintObject *object : printable_objects) { + size_t skirt_layers = this->has_infinite_skirt() ? object->layer_count() : std::min(size_t(this->config.skirt_height.value), object->layer_count()); skirt_height_z = std::max(skirt_height_z, object->layers[skirt_layers-1]->print_z); @@ -867,7 +881,7 @@ void Print::_make_skirt() // Collect points from all layers contained in skirt height. Points points; - for (const PrintObject *object : this->objects) { + for (const PrintObject *object : printable_objects) { Points object_points; // Get object layers up to skirt_height_z. for (const Layer *layer : object->layers) { @@ -980,7 +994,8 @@ void Print::_make_brim() // Brim is only printed on first layer and uses perimeter extruder. Flow flow = this->brim_flow(); Polygons islands; - for (PrintObject *object : this->objects) { + PrintObjectPtrs printable_objects = get_printable_objects(); + for (PrintObject *object : printable_objects) { Polygons object_islands; for (ExPolygon &expoly : object->layers.front()->slices.expolygons) object_islands.push_back(expoly.contour); diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 2217547ea..bcd61ea02 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -209,6 +209,8 @@ public: void combine_infill(); void _generate_support_material(); + bool is_printable() const { return !this->_shifted_copies.empty(); } + private: Print* _print; ModelObject* _model_object; @@ -257,6 +259,8 @@ public: void reload_object(size_t idx); bool reload_model_instances(); + PrintObjectPtrs get_printable_objects() const; + // methods for handling regions PrintRegion* get_region(size_t idx) { return regions.at(idx); } const PrintRegion* get_region(size_t idx) const { return regions.at(idx); } diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index 7ac165864..1d0a81cd2 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -102,7 +102,10 @@ bool PrintObject::reload_model_instances() Points copies; copies.reserve(this->_model_object->instances.size()); for (const ModelInstance *mi : this->_model_object->instances) - copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y)); + { + if (mi->is_printable) + copies.emplace_back(Point::new_scale(mi->offset.x, mi->offset.y)); + } return this->set_copies(copies); } @@ -291,6 +294,9 @@ bool PrintObject::has_support_material() const void PrintObject::_prepare_infill() { + if (!this->is_printable()) + return; + // This will assign a type (top/bottom/internal) to $layerm->slices. // Then the classifcation of $layerm->slices is transfered onto // the $layerm->fill_surfaces by clipping $layerm->fill_surfaces @@ -1442,6 +1448,9 @@ void PrintObject::_simplify_slices(double distance) void PrintObject::_make_perimeters() { + if (!this->is_printable()) + return; + if (this->state.is_done(posPerimeters)) return; this->state.set_started(posPerimeters); @@ -1550,6 +1559,9 @@ void PrintObject::_make_perimeters() void PrintObject::_infill() { + if (!this->is_printable()) + return; + if (this->state.is_done(posInfill)) return; this->state.set_started(posInfill); @@ -1954,6 +1966,9 @@ void PrintObject::combine_infill() void PrintObject::_generate_support_material() { + if (!this->is_printable()) + return; + PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters()); support_material.generate(*this); } diff --git a/xs/src/slic3r/GUI/GLCanvas3D.cpp b/xs/src/slic3r/GUI/GLCanvas3D.cpp index 208125a15..729c91cf3 100644 --- a/xs/src/slic3r/GUI/GLCanvas3D.cpp +++ b/xs/src/slic3r/GUI/GLCanvas3D.cpp @@ -2087,20 +2087,20 @@ void GLCanvas3D::reload_scene(bool force) { enable_warning_texture(true); _3DScene::generate_warning_texture(L("Detected object outside print volume")); - m_on_enable_action_buttons_callback.call(false); } else { enable_warning_texture(false); m_volumes.reset_outside_state(); _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 { enable_warning_texture(false); _3DScene::reset_warning_texture(); + m_on_enable_action_buttons_callback.call(false); } } |