diff --git a/xs/MANIFEST b/xs/MANIFEST index 985445d7e..c38096709 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -1673,6 +1673,7 @@ src/Geometry.cpp src/Geometry.hpp src/Layer.cpp src/Layer.hpp +src/LayerRegion.cpp src/Line.cpp src/Line.hpp src/Model.cpp @@ -1712,6 +1713,8 @@ src/Print.cpp src/Print.hpp src/PrintConfig.cpp src/PrintConfig.hpp +src/PrintObject.cpp +src/PrintRegion.cpp src/Surface.cpp src/Surface.hpp src/SurfaceCollection.cpp diff --git a/xs/src/Layer.cpp b/xs/src/Layer.cpp index 107ff1be7..689077d46 100644 --- a/xs/src/Layer.cpp +++ b/xs/src/Layer.cpp @@ -6,46 +6,6 @@ namespace Slic3r { -LayerRegion::LayerRegion(Layer *layer, PrintRegion *region) -: _layer(layer), - _region(region) -{ -} - -LayerRegion::~LayerRegion() -{ -} - -Layer* -LayerRegion::layer() -{ - return this->_layer; -} - -PrintRegion* -LayerRegion::region() -{ - return this->_region; -} - -Flow -LayerRegion::flow(FlowRole role, bool bridge, double width) const -{ - return this->_region->flow( - role, - this->_layer->height, - bridge, - this->_layer->id() == 0, - width, - *this->_layer->object() - ); -} - -#ifdef SLIC3RXS -REGISTER_CLASS(LayerRegion, "Layer::Region"); -#endif - - Layer::Layer(int id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) : _id(id), diff --git a/xs/src/LayerRegion.cpp b/xs/src/LayerRegion.cpp new file mode 100644 index 000000000..cb92c4ee3 --- /dev/null +++ b/xs/src/LayerRegion.cpp @@ -0,0 +1,45 @@ +#include "Layer.hpp" +#include "Print.hpp" + +namespace Slic3r { + +LayerRegion::LayerRegion(Layer *layer, PrintRegion *region) +: _layer(layer), + _region(region) +{ +} + +LayerRegion::~LayerRegion() +{ +} + +Layer* +LayerRegion::layer() +{ + return this->_layer; +} + +PrintRegion* +LayerRegion::region() +{ + return this->_region; +} + +Flow +LayerRegion::flow(FlowRole role, bool bridge, double width) const +{ + return this->_region->flow( + role, + this->_layer->height, + bridge, + this->_layer->id() == 0, + width, + *this->_layer->object() + ); +} + +#ifdef SLIC3RXS +REGISTER_CLASS(LayerRegion, "Layer::Region"); +#endif + +} diff --git a/xs/src/Print.cpp b/xs/src/Print.cpp index eab745f7c..d71cb4349 100644 --- a/xs/src/Print.cpp +++ b/xs/src/Print.cpp @@ -45,321 +45,6 @@ template class PrintState; template class PrintState; -PrintRegion::PrintRegion(Print* print) - : _print(print) -{ -} - -PrintRegion::~PrintRegion() -{ -} - -Print* -PrintRegion::print() -{ - return this->_print; -} - -Flow -PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const -{ - ConfigOptionFloatOrPercent config_width; - if (width != -1) { - // use the supplied custom width, if any - config_width.value = width; - config_width.percent = false; - } else { - // otherwise, get extrusion width from configuration - // (might be an absolute value, or a percent value, or zero for auto) - if (first_layer && this->_print->config.first_layer_extrusion_width.value > 0) { - config_width = this->_print->config.first_layer_extrusion_width; - } else if (role == frExternalPerimeter) { - config_width = this->config.external_perimeter_extrusion_width; - } else if (role == frPerimeter) { - config_width = this->config.perimeter_extrusion_width; - } else if (role == frInfill) { - config_width = this->config.infill_extrusion_width; - } else if (role == frSolidInfill) { - config_width = this->config.solid_infill_extrusion_width; - } else if (role == frTopSolidInfill) { - config_width = this->config.top_infill_extrusion_width; - } else { - CONFESS("Unknown role"); - } - } - if (config_width.value == 0) { - config_width = object.config.extrusion_width; - } - - // get the configured nozzle_diameter for the extruder associated - // to the flow role requested - size_t extruder; // 1-based - if (role == frPerimeter || role == frExternalPerimeter) { - extruder = this->config.perimeter_extruder; - } else if (role == frInfill || role == frSolidInfill || role == frTopSolidInfill) { - extruder = this->config.infill_extruder; - } else { - CONFESS("Unknown role $role"); - } - double nozzle_diameter = this->_print->config.nozzle_diameter.get_at(extruder-1); - - return Flow::new_from_config_width(role, config_width, nozzle_diameter, layer_height, bridge ? this->config.bridge_flow_ratio : 0); -} - -#ifdef SLIC3RXS -REGISTER_CLASS(PrintRegion, "Print::Region"); -#endif - - -PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox) -: _print(print), - _model_object(model_object), - typed_slices(false) -{ - region_volumes.resize(this->_print->regions.size()); - - // Compute the translation to be applied to our meshes so that we work with smaller coordinates - { - // Translate meshes so that our toolpath generation algorithms work with smaller - // XY coordinates; this translation is an optimization and not strictly required. - // A cloned mesh will be aligned to 0 before slicing in _slice_region() since we - // don't assume it's already aligned and we don't alter the original position in model. - // We store the XY translation so that we can place copies correctly in the output G-code - // (copies are expressed in G-code coordinates and this translation is not publicly exposed). - this->_copies_shift = Point( - scale_(modobj_bbox.min.x), scale_(modobj_bbox.min.y)); - - // TODO: $self->_trigger_copies; - - // Scale the object size and store it - Pointf3 size = modobj_bbox.size(); - this->size = Point3(scale_(size.x), scale_(size.y), scale_(size.z)); - } -} - -PrintObject::~PrintObject() -{ -} - -Print* -PrintObject::print() -{ - return this->_print; -} - -ModelObject* -PrintObject::model_object() -{ - return this->_model_object; -} - -void -PrintObject::add_region_volume(int region_id, int volume_id) -{ - if (region_id >= region_volumes.size()) { - region_volumes.resize(region_id + 1); - } - - region_volumes[region_id].push_back(volume_id); -} - -size_t -PrintObject::layer_count() -{ - return this->layers.size(); -} - -void -PrintObject::clear_layers() -{ - for (int i = this->layers.size()-1; i >= 0; --i) - this->delete_layer(i); -} - -Layer* -PrintObject::get_layer(int idx) -{ - return this->layers.at(idx); -} - -Layer* -PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z) -{ - Layer* layer = new Layer(id, this, height, print_z, slice_z); - layers.push_back(layer); - return layer; -} - -void -PrintObject::delete_layer(int idx) -{ - LayerPtrs::iterator i = this->layers.begin() + idx; - delete *i; - this->layers.erase(i); -} - -size_t -PrintObject::support_layer_count() -{ - return this->support_layers.size(); -} - -void -PrintObject::clear_support_layers() -{ - for (int i = this->support_layers.size()-1; i >= 0; --i) - this->delete_support_layer(i); -} - -SupportLayer* -PrintObject::get_support_layer(int idx) -{ - return this->support_layers.at(idx); -} - -SupportLayer* -PrintObject::add_support_layer(int id, coordf_t height, coordf_t print_z, - coordf_t slice_z) -{ - SupportLayer* layer = new SupportLayer(id, this, height, print_z, slice_z); - support_layers.push_back(layer); - return layer; -} - -void -PrintObject::delete_support_layer(int idx) -{ - SupportLayerPtrs::iterator i = this->support_layers.begin() + idx; - delete *i; - this->support_layers.erase(i); -} - -bool -PrintObject::invalidate_state_by_config_options(const std::vector &opt_keys) -{ - std::set steps; - - // this method only accepts PrintObjectConfig and PrintRegionConfig option keys - for (std::vector::const_iterator opt_key = opt_keys.begin(); opt_key != opt_keys.end(); ++opt_key) { - if (*opt_key == "perimeters" - || *opt_key == "extra_perimeters" - || *opt_key == "gap_fill_speed" - || *opt_key == "overhangs" - || *opt_key == "perimeter_extrusion_width" - || *opt_key == "thin_walls" - || *opt_key == "external_perimeters_first") { - steps.insert(posPerimeters); - } else if (*opt_key == "resolution" - || *opt_key == "layer_height" - || *opt_key == "first_layer_height" - || *opt_key == "xy_size_compensation" - || *opt_key == "raft_layers") { - steps.insert(posSlice); - } else if (*opt_key == "support_material" - || *opt_key == "support_material_angle" - || *opt_key == "support_material_extruder" - || *opt_key == "support_material_extrusion_width" - || *opt_key == "support_material_interface_layers" - || *opt_key == "support_material_interface_extruder" - || *opt_key == "support_material_interface_spacing" - || *opt_key == "support_material_interface_speed" - || *opt_key == "support_material_pattern" - || *opt_key == "support_material_spacing" - || *opt_key == "support_material_threshold" - || *opt_key == "dont_support_bridges") { - steps.insert(posSupportMaterial); - } else if (*opt_key == "interface_shells" - || *opt_key == "infill_only_where_needed" - || *opt_key == "bottom_solid_layers" - || *opt_key == "top_solid_layers" - || *opt_key == "infill_extruder" - || *opt_key == "infill_extrusion_width") { - steps.insert(posPrepareInfill); - } else if (*opt_key == "fill_angle" - || *opt_key == "fill_pattern" - || *opt_key == "solid_fill_pattern" - || *opt_key == "infill_every_layers" - || *opt_key == "solid_infill_below_area" - || *opt_key == "solid_infill_every_layers" - || *opt_key == "top_infill_extrusion_width") { - steps.insert(posInfill); - } else if (*opt_key == "fill_density" - || *opt_key == "solid_infill_extrusion_width") { - steps.insert(posPerimeters); - steps.insert(posPrepareInfill); - } else if (*opt_key == "external_perimeter_extrusion_width" - || *opt_key == "perimeter_extruder") { - steps.insert(posPerimeters); - steps.insert(posSupportMaterial); - } else if (*opt_key == "bridge_flow_ratio") { - steps.insert(posPerimeters); - steps.insert(posInfill); - } else if (*opt_key == "seam_position" - || *opt_key == "support_material_speed" - || *opt_key == "bridge_speed" - || *opt_key == "external_perimeter_speed" - || *opt_key == "infill_speed" - || *opt_key == "perimeter_speed" - || *opt_key == "small_perimeter_speed" - || *opt_key == "solid_infill_speed" - || *opt_key == "top_solid_infill_speed") { - // these options only affect G-code export, so nothing to invalidate - } else { - // for legacy, if we can't handle this option let's invalidate all steps - return this->invalidate_all_steps(); - } - } - - bool invalidated = false; - for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) { - if (this->invalidate_step(*step)) invalidated = true; - } - - return invalidated; -} - -bool -PrintObject::invalidate_step(PrintObjectStep step) -{ - bool invalidated = this->state.invalidate(step); - - // propagate to dependent steps - if (step == posPerimeters) { - this->invalidate_step(posPrepareInfill); - this->_print->invalidate_step(psSkirt); - this->_print->invalidate_step(psBrim); - } else if (step == posPrepareInfill) { - this->invalidate_step(posInfill); - } else if (step == posInfill) { - this->_print->invalidate_step(psSkirt); - this->_print->invalidate_step(psBrim); - } else if (step == posSlice) { - this->invalidate_step(posPerimeters); - this->invalidate_step(posSupportMaterial); - } - - return invalidated; -} - -bool -PrintObject::invalidate_all_steps() -{ - // make a copy because when invalidating steps the iterators are not working anymore - std::set steps = this->state.started; - - bool invalidated = false; - for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) { - if (this->invalidate_step(*step)) invalidated = true; - } - return invalidated; -} - - -#ifdef SLIC3RXS -REGISTER_CLASS(PrintObject, "Print::Object"); -#endif - - Print::Print() : total_used_filament(0), total_extruded_volume(0) diff --git a/xs/src/PrintObject.cpp b/xs/src/PrintObject.cpp new file mode 100644 index 000000000..4dac94cf6 --- /dev/null +++ b/xs/src/PrintObject.cpp @@ -0,0 +1,254 @@ +#include "Print.hpp" +#include "BoundingBox.hpp" + +namespace Slic3r { + +PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox) +: _print(print), + _model_object(model_object), + typed_slices(false) +{ + region_volumes.resize(this->_print->regions.size()); + + // Compute the translation to be applied to our meshes so that we work with smaller coordinates + { + // Translate meshes so that our toolpath generation algorithms work with smaller + // XY coordinates; this translation is an optimization and not strictly required. + // A cloned mesh will be aligned to 0 before slicing in _slice_region() since we + // don't assume it's already aligned and we don't alter the original position in model. + // We store the XY translation so that we can place copies correctly in the output G-code + // (copies are expressed in G-code coordinates and this translation is not publicly exposed). + this->_copies_shift = Point( + scale_(modobj_bbox.min.x), scale_(modobj_bbox.min.y)); + + // TODO: $self->_trigger_copies; + + // Scale the object size and store it + Pointf3 size = modobj_bbox.size(); + this->size = Point3(scale_(size.x), scale_(size.y), scale_(size.z)); + } +} + +PrintObject::~PrintObject() +{ +} + +Print* +PrintObject::print() +{ + return this->_print; +} + +ModelObject* +PrintObject::model_object() +{ + return this->_model_object; +} + +void +PrintObject::add_region_volume(int region_id, int volume_id) +{ + if (region_id >= region_volumes.size()) { + region_volumes.resize(region_id + 1); + } + + region_volumes[region_id].push_back(volume_id); +} + +size_t +PrintObject::layer_count() +{ + return this->layers.size(); +} + +void +PrintObject::clear_layers() +{ + for (int i = this->layers.size()-1; i >= 0; --i) + this->delete_layer(i); +} + +Layer* +PrintObject::get_layer(int idx) +{ + return this->layers.at(idx); +} + +Layer* +PrintObject::add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z) +{ + Layer* layer = new Layer(id, this, height, print_z, slice_z); + layers.push_back(layer); + return layer; +} + +void +PrintObject::delete_layer(int idx) +{ + LayerPtrs::iterator i = this->layers.begin() + idx; + delete *i; + this->layers.erase(i); +} + +size_t +PrintObject::support_layer_count() +{ + return this->support_layers.size(); +} + +void +PrintObject::clear_support_layers() +{ + for (int i = this->support_layers.size()-1; i >= 0; --i) + this->delete_support_layer(i); +} + +SupportLayer* +PrintObject::get_support_layer(int idx) +{ + return this->support_layers.at(idx); +} + +SupportLayer* +PrintObject::add_support_layer(int id, coordf_t height, coordf_t print_z, + coordf_t slice_z) +{ + SupportLayer* layer = new SupportLayer(id, this, height, print_z, slice_z); + support_layers.push_back(layer); + return layer; +} + +void +PrintObject::delete_support_layer(int idx) +{ + SupportLayerPtrs::iterator i = this->support_layers.begin() + idx; + delete *i; + this->support_layers.erase(i); +} + +bool +PrintObject::invalidate_state_by_config_options(const std::vector &opt_keys) +{ + std::set steps; + + // this method only accepts PrintObjectConfig and PrintRegionConfig option keys + for (std::vector::const_iterator opt_key = opt_keys.begin(); opt_key != opt_keys.end(); ++opt_key) { + if (*opt_key == "perimeters" + || *opt_key == "extra_perimeters" + || *opt_key == "gap_fill_speed" + || *opt_key == "overhangs" + || *opt_key == "perimeter_extrusion_width" + || *opt_key == "thin_walls" + || *opt_key == "external_perimeters_first") { + steps.insert(posPerimeters); + } else if (*opt_key == "resolution" + || *opt_key == "layer_height" + || *opt_key == "first_layer_height" + || *opt_key == "xy_size_compensation" + || *opt_key == "raft_layers") { + steps.insert(posSlice); + } else if (*opt_key == "support_material" + || *opt_key == "support_material_angle" + || *opt_key == "support_material_extruder" + || *opt_key == "support_material_extrusion_width" + || *opt_key == "support_material_interface_layers" + || *opt_key == "support_material_interface_extruder" + || *opt_key == "support_material_interface_spacing" + || *opt_key == "support_material_interface_speed" + || *opt_key == "support_material_pattern" + || *opt_key == "support_material_spacing" + || *opt_key == "support_material_threshold" + || *opt_key == "dont_support_bridges") { + steps.insert(posSupportMaterial); + } else if (*opt_key == "interface_shells" + || *opt_key == "infill_only_where_needed" + || *opt_key == "bottom_solid_layers" + || *opt_key == "top_solid_layers" + || *opt_key == "infill_extruder" + || *opt_key == "infill_extrusion_width") { + steps.insert(posPrepareInfill); + } else if (*opt_key == "fill_angle" + || *opt_key == "fill_pattern" + || *opt_key == "solid_fill_pattern" + || *opt_key == "infill_every_layers" + || *opt_key == "solid_infill_below_area" + || *opt_key == "solid_infill_every_layers" + || *opt_key == "top_infill_extrusion_width") { + steps.insert(posInfill); + } else if (*opt_key == "fill_density" + || *opt_key == "solid_infill_extrusion_width") { + steps.insert(posPerimeters); + steps.insert(posPrepareInfill); + } else if (*opt_key == "external_perimeter_extrusion_width" + || *opt_key == "perimeter_extruder") { + steps.insert(posPerimeters); + steps.insert(posSupportMaterial); + } else if (*opt_key == "bridge_flow_ratio") { + steps.insert(posPerimeters); + steps.insert(posInfill); + } else if (*opt_key == "seam_position" + || *opt_key == "support_material_speed" + || *opt_key == "bridge_speed" + || *opt_key == "external_perimeter_speed" + || *opt_key == "infill_speed" + || *opt_key == "perimeter_speed" + || *opt_key == "small_perimeter_speed" + || *opt_key == "solid_infill_speed" + || *opt_key == "top_solid_infill_speed") { + // these options only affect G-code export, so nothing to invalidate + } else { + // for legacy, if we can't handle this option let's invalidate all steps + return this->invalidate_all_steps(); + } + } + + bool invalidated = false; + for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) { + if (this->invalidate_step(*step)) invalidated = true; + } + + return invalidated; +} + +bool +PrintObject::invalidate_step(PrintObjectStep step) +{ + bool invalidated = this->state.invalidate(step); + + // propagate to dependent steps + if (step == posPerimeters) { + this->invalidate_step(posPrepareInfill); + this->_print->invalidate_step(psSkirt); + this->_print->invalidate_step(psBrim); + } else if (step == posPrepareInfill) { + this->invalidate_step(posInfill); + } else if (step == posInfill) { + this->_print->invalidate_step(psSkirt); + this->_print->invalidate_step(psBrim); + } else if (step == posSlice) { + this->invalidate_step(posPerimeters); + this->invalidate_step(posSupportMaterial); + } + + return invalidated; +} + +bool +PrintObject::invalidate_all_steps() +{ + // make a copy because when invalidating steps the iterators are not working anymore + std::set steps = this->state.started; + + bool invalidated = false; + for (std::set::const_iterator step = steps.begin(); step != steps.end(); ++step) { + if (this->invalidate_step(*step)) invalidated = true; + } + return invalidated; +} + + +#ifdef SLIC3RXS +REGISTER_CLASS(PrintObject, "Print::Object"); +#endif + +} diff --git a/xs/src/PrintRegion.cpp b/xs/src/PrintRegion.cpp new file mode 100644 index 000000000..d651b57ab --- /dev/null +++ b/xs/src/PrintRegion.cpp @@ -0,0 +1,70 @@ +#include "Print.hpp" + +namespace Slic3r { + +PrintRegion::PrintRegion(Print* print) + : _print(print) +{ +} + +PrintRegion::~PrintRegion() +{ +} + +Print* +PrintRegion::print() +{ + return this->_print; +} + +Flow +PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const +{ + ConfigOptionFloatOrPercent config_width; + if (width != -1) { + // use the supplied custom width, if any + config_width.value = width; + config_width.percent = false; + } else { + // otherwise, get extrusion width from configuration + // (might be an absolute value, or a percent value, or zero for auto) + if (first_layer && this->_print->config.first_layer_extrusion_width.value > 0) { + config_width = this->_print->config.first_layer_extrusion_width; + } else if (role == frExternalPerimeter) { + config_width = this->config.external_perimeter_extrusion_width; + } else if (role == frPerimeter) { + config_width = this->config.perimeter_extrusion_width; + } else if (role == frInfill) { + config_width = this->config.infill_extrusion_width; + } else if (role == frSolidInfill) { + config_width = this->config.solid_infill_extrusion_width; + } else if (role == frTopSolidInfill) { + config_width = this->config.top_infill_extrusion_width; + } else { + CONFESS("Unknown role"); + } + } + if (config_width.value == 0) { + config_width = object.config.extrusion_width; + } + + // get the configured nozzle_diameter for the extruder associated + // to the flow role requested + size_t extruder; // 1-based + if (role == frPerimeter || role == frExternalPerimeter) { + extruder = this->config.perimeter_extruder; + } else if (role == frInfill || role == frSolidInfill || role == frTopSolidInfill) { + extruder = this->config.infill_extruder; + } else { + CONFESS("Unknown role $role"); + } + double nozzle_diameter = this->_print->config.nozzle_diameter.get_at(extruder-1); + + return Flow::new_from_config_width(role, config_width, nozzle_diameter, layer_height, bridge ? this->config.bridge_flow_ratio : 0); +} + +#ifdef SLIC3RXS +REGISTER_CLASS(PrintRegion, "Print::Region"); +#endif + +}