mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 16:57:53 -06:00
Slice only objects contained into the print volume
This commit is contained in:
parent
eb95e29be6
commit
d672a69554
8 changed files with 105 additions and 16 deletions
|
@ -776,9 +776,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// Order objects using a nearest neighbor search.
|
// Order objects using a nearest neighbor search.
|
||||||
std::vector<size_t> object_indices;
|
std::vector<size_t> object_indices;
|
||||||
Points object_reference_points;
|
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());
|
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.
|
// Sort layers by Z.
|
||||||
// All extrusion moves with the same top layer height are extruded uninterrupted.
|
// 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);
|
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.
|
// Verify, whether the print overaps the priming extrusions.
|
||||||
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
|
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;
|
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_print_object_extrusions_extents(*print_object, twolayers_printz));
|
||||||
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
|
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
|
||||||
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
|
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
|
||||||
|
|
|
@ -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)
|
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
|
||||||
{
|
{
|
||||||
m_print_config_ptr = &print.config;
|
m_print_config_ptr = &print.config;
|
||||||
|
|
||||||
|
PrintObjectPtrs objects = print.get_printable_objects();
|
||||||
// Initialize the print layers for all objects and all layers.
|
// Initialize the print layers for all objects and all layers.
|
||||||
coordf_t object_bottom_z = 0.;
|
coordf_t object_bottom_z = 0.;
|
||||||
{
|
{
|
||||||
std::vector<coordf_t> zs;
|
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());
|
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
|
||||||
for (auto layer : object->layers)
|
for (auto layer : object->layers)
|
||||||
zs.emplace_back(layer->print_z);
|
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.
|
// Collect extruders reuqired to print the layers.
|
||||||
for (auto object : print.objects)
|
for (auto object : objects)
|
||||||
this->collect_extruders(*object);
|
this->collect_extruders(*object);
|
||||||
|
|
||||||
// Reorder the extruders to minimize tool switches.
|
// Reorder the extruders to minimize tool switches.
|
||||||
|
|
|
@ -1235,6 +1235,54 @@ void ModelObject::split(ModelObjectPtrs* new_objects)
|
||||||
return;
|
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
|
void ModelObject::print_info() const
|
||||||
{
|
{
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
|
@ -131,6 +131,7 @@ 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);
|
||||||
|
|
||||||
// Print object statistics to console.
|
// Print object statistics to console.
|
||||||
void print_info() const;
|
void print_info() const;
|
||||||
|
@ -203,6 +204,9 @@ public:
|
||||||
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())
|
||||||
|
bool is_printable;
|
||||||
|
|
||||||
ModelObject* get_object() const { return this->object; }
|
ModelObject* get_object() const { return this->object; }
|
||||||
|
|
||||||
// To be called on an external mesh
|
// To be called on an external mesh
|
||||||
|
@ -218,9 +222,9 @@ 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) {}
|
ModelInstance(ModelObject *object) : rotation(0), scaling_factor(1), object(object), is_printable(false) {}
|
||||||
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) {}
|
rotation(other.rotation), scaling_factor(other.scaling_factor), offset(other.offset), object(object), is_printable(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,13 @@ bool Print::reload_model_instances()
|
||||||
return invalidated;
|
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()
|
PrintRegion* Print::add_region()
|
||||||
{
|
{
|
||||||
regions.push_back(new PrintRegion(this));
|
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));
|
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.
|
// 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;
|
||||||
|
unsigned int printable_count = 0;
|
||||||
for (PrintObject *po : this->objects) {
|
for (PrintObject *po : this->objects) {
|
||||||
if (!print_volume.contains(po->model_object()->tight_bounding_box(false)))
|
po->model_object()->check_instances_printability(print_volume);
|
||||||
return L("Some objects are outside of the 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) {
|
if (this->config.complete_objects) {
|
||||||
// Check horizontal clearance.
|
// Check horizontal clearance.
|
||||||
{
|
{
|
||||||
|
@ -858,8 +871,9 @@ void Print::_make_skirt()
|
||||||
// prepended to the first 'n' layers (with 'n' = skirt_height).
|
// prepended to the first 'n' layers (with 'n' = skirt_height).
|
||||||
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
||||||
coordf_t skirt_height_z = 0.;
|
coordf_t skirt_height_z = 0.;
|
||||||
for (const PrintObject *object : this->objects) {
|
PrintObjectPtrs printable_objects = get_printable_objects();
|
||||||
size_t skirt_layers = this->has_infinite_skirt() ?
|
for (const PrintObject *object : printable_objects) {
|
||||||
|
size_t skirt_layers = this->has_infinite_skirt() ?
|
||||||
object->layer_count() :
|
object->layer_count() :
|
||||||
std::min(size_t(this->config.skirt_height.value), 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);
|
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.
|
// Collect points from all layers contained in skirt height.
|
||||||
Points points;
|
Points points;
|
||||||
for (const PrintObject *object : this->objects) {
|
for (const PrintObject *object : printable_objects) {
|
||||||
Points object_points;
|
Points object_points;
|
||||||
// Get object layers up to skirt_height_z.
|
// Get object layers up to skirt_height_z.
|
||||||
for (const Layer *layer : object->layers) {
|
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.
|
// Brim is only printed on first layer and uses perimeter extruder.
|
||||||
Flow flow = this->brim_flow();
|
Flow flow = this->brim_flow();
|
||||||
Polygons islands;
|
Polygons islands;
|
||||||
for (PrintObject *object : this->objects) {
|
PrintObjectPtrs printable_objects = get_printable_objects();
|
||||||
|
for (PrintObject *object : printable_objects) {
|
||||||
Polygons object_islands;
|
Polygons object_islands;
|
||||||
for (ExPolygon &expoly : object->layers.front()->slices.expolygons)
|
for (ExPolygon &expoly : object->layers.front()->slices.expolygons)
|
||||||
object_islands.push_back(expoly.contour);
|
object_islands.push_back(expoly.contour);
|
||||||
|
|
|
@ -209,6 +209,8 @@ public:
|
||||||
void combine_infill();
|
void combine_infill();
|
||||||
void _generate_support_material();
|
void _generate_support_material();
|
||||||
|
|
||||||
|
bool is_printable() const { return !this->_shifted_copies.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Print* _print;
|
Print* _print;
|
||||||
ModelObject* _model_object;
|
ModelObject* _model_object;
|
||||||
|
@ -257,6 +259,8 @@ public:
|
||||||
void reload_object(size_t idx);
|
void reload_object(size_t idx);
|
||||||
bool reload_model_instances();
|
bool reload_model_instances();
|
||||||
|
|
||||||
|
PrintObjectPtrs get_printable_objects() const;
|
||||||
|
|
||||||
// methods for handling regions
|
// methods for handling regions
|
||||||
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
|
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
|
||||||
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }
|
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }
|
||||||
|
|
|
@ -102,7 +102,10 @@ bool PrintObject::reload_model_instances()
|
||||||
Points copies;
|
Points copies;
|
||||||
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)
|
||||||
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);
|
return this->set_copies(copies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +294,9 @@ bool PrintObject::has_support_material() const
|
||||||
|
|
||||||
void PrintObject::_prepare_infill()
|
void PrintObject::_prepare_infill()
|
||||||
{
|
{
|
||||||
|
if (!this->is_printable())
|
||||||
|
return;
|
||||||
|
|
||||||
// This will assign a type (top/bottom/internal) to $layerm->slices.
|
// This will assign a type (top/bottom/internal) to $layerm->slices.
|
||||||
// Then the classifcation of $layerm->slices is transfered onto
|
// Then the classifcation of $layerm->slices is transfered onto
|
||||||
// the $layerm->fill_surfaces by clipping $layerm->fill_surfaces
|
// the $layerm->fill_surfaces by clipping $layerm->fill_surfaces
|
||||||
|
@ -1442,6 +1448,9 @@ void PrintObject::_simplify_slices(double distance)
|
||||||
|
|
||||||
void PrintObject::_make_perimeters()
|
void PrintObject::_make_perimeters()
|
||||||
{
|
{
|
||||||
|
if (!this->is_printable())
|
||||||
|
return;
|
||||||
|
|
||||||
if (this->state.is_done(posPerimeters)) return;
|
if (this->state.is_done(posPerimeters)) return;
|
||||||
this->state.set_started(posPerimeters);
|
this->state.set_started(posPerimeters);
|
||||||
|
|
||||||
|
@ -1550,6 +1559,9 @@ void PrintObject::_make_perimeters()
|
||||||
|
|
||||||
void PrintObject::_infill()
|
void PrintObject::_infill()
|
||||||
{
|
{
|
||||||
|
if (!this->is_printable())
|
||||||
|
return;
|
||||||
|
|
||||||
if (this->state.is_done(posInfill)) return;
|
if (this->state.is_done(posInfill)) return;
|
||||||
this->state.set_started(posInfill);
|
this->state.set_started(posInfill);
|
||||||
|
|
||||||
|
@ -1954,6 +1966,9 @@ void PrintObject::combine_infill()
|
||||||
|
|
||||||
void PrintObject::_generate_support_material()
|
void PrintObject::_generate_support_material()
|
||||||
{
|
{
|
||||||
|
if (!this->is_printable())
|
||||||
|
return;
|
||||||
|
|
||||||
PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
|
PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
|
||||||
support_material.generate(*this);
|
support_material.generate(*this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2087,20 +2087,20 @@ void GLCanvas3D::reload_scene(bool force)
|
||||||
{
|
{
|
||||||
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(false);
|
|
||||||
}
|
}
|
||||||
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
|
||||||
{
|
{
|
||||||
enable_warning_texture(false);
|
enable_warning_texture(false);
|
||||||
_3DScene::reset_warning_texture();
|
_3DScene::reset_warning_texture();
|
||||||
|
m_on_enable_action_buttons_callback.call(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue