Browse Source

Split Print.cpp and Layer.cpp into multiple compilation units

Alessandro Ranellucci 10 years ago
parent
commit
b8676241e0
6 changed files with 372 additions and 355 deletions
  1. 3 0
      xs/MANIFEST
  2. 0 40
      xs/src/Layer.cpp
  3. 45 0
      xs/src/LayerRegion.cpp
  4. 0 315
      xs/src/Print.cpp
  5. 254 0
      xs/src/PrintObject.cpp
  6. 70 0
      xs/src/PrintRegion.cpp

+ 3 - 0
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

+ 0 - 40
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),

+ 45 - 0
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
+
+}

+ 0 - 315
xs/src/Print.cpp

@@ -45,321 +45,6 @@ template class PrintState<PrintStep>;
 template class PrintState<PrintObjectStep>;
 
 
-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<t_config_option_key> &opt_keys)
-{
-    std::set<PrintObjectStep> steps;
-    
-    // this method only accepts PrintObjectConfig and PrintRegionConfig option keys
-    for (std::vector<t_config_option_key>::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<PrintObjectStep>::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<PrintObjectStep> steps = this->state.started;
-    
-    bool invalidated = false;
-    for (std::set<PrintObjectStep>::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)

+ 254 - 0
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<t_config_option_key> &opt_keys)
+{
+    std::set<PrintObjectStep> steps;
+    
+    // this method only accepts PrintObjectConfig and PrintRegionConfig option keys
+    for (std::vector<t_config_option_key>::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<PrintObjectStep>::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<PrintObjectStep> steps = this->state.started;
+    
+    bool invalidated = false;
+    for (std::set<PrintObjectStep>::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
+
+}

+ 70 - 0
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
+
+}