Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2016-12-20 14:19:13 +0300
committerbubnikv <bubnikv@gmail.com>2016-12-20 14:19:13 +0300
commit955bc957bac5afafca26ead0894c9fdf1e0a3a20 (patch)
tree243a426ede0ee7048819eb355c6da0dd90c9517b /xs/src/libslic3r
parent5614e997a4bca88b29b806293cc7e548b3348211 (diff)
New supports now do rafts at least to the extent the test cases run through.
New supports enabled, old supports will go away soon.
Diffstat (limited to 'xs/src/libslic3r')
-rw-r--r--xs/src/libslic3r/EdgeGrid.cpp35
-rw-r--r--xs/src/libslic3r/EdgeGrid.hpp2
-rw-r--r--xs/src/libslic3r/Fill/FillRectilinear2.cpp6
-rw-r--r--xs/src/libslic3r/Print.hpp1
-rw-r--r--xs/src/libslic3r/PrintObject.cpp7
-rw-r--r--xs/src/libslic3r/Slicing.cpp27
-rw-r--r--xs/src/libslic3r/Slicing.hpp18
-rw-r--r--xs/src/libslic3r/SupportMaterial.cpp313
-rw-r--r--xs/src/libslic3r/SupportMaterial.hpp67
-rw-r--r--xs/src/libslic3r/SurfaceCollection.cpp14
-rw-r--r--xs/src/libslic3r/libslic3r.h2
11 files changed, 247 insertions, 245 deletions
diff --git a/xs/src/libslic3r/EdgeGrid.cpp b/xs/src/libslic3r/EdgeGrid.cpp
index 4d1432722..b39b12ab8 100644
--- a/xs/src/libslic3r/EdgeGrid.cpp
+++ b/xs/src/libslic3r/EdgeGrid.cpp
@@ -1222,17 +1222,39 @@ bool EdgeGrid::Grid::signed_distance(const Point &pt, coord_t search_radius, coo
return true;
}
-Polygons EdgeGrid::Grid::contours_simplified() const
+Polygons EdgeGrid::Grid::contours_simplified(coord_t offset) const
{
typedef std::unordered_multimap<Point, int, PointHash> EndPointMapType;
+ // 0) Prepare a binary grid.
+ size_t cell_rows = m_rows + 2;
+ size_t cell_cols = m_cols + 2;
+ std::vector<char> cell_inside(cell_rows * cell_cols, false);
+ for (int r = 0; r < int(cell_rows); ++ r)
+ for (int c = 0; c < int(cell_cols); ++ c)
+ cell_inside[r * cell_cols + c] = cell_inside_or_crossing(r - 1, c - 1);
+ // Fill in empty cells, which have a left / right neighbor filled.
+ // Fill in empty cells, which have the top / bottom neighbor filled.
+ {
+ std::vector<char> cell_inside2(cell_inside);
+ for (int r = 1; r + 1 < int(cell_rows); ++ r) {
+ for (int c = 1; c + 1 < int(cell_cols); ++ c) {
+ int addr = r * cell_cols + c;
+ if ((cell_inside2[addr - 1] && cell_inside2[addr + 1]) ||
+ (cell_inside2[addr - cell_cols] && cell_inside2[addr + cell_cols]))
+ cell_inside[addr] = true;
+ }
+ }
+ }
+
// 1) Collect the lines.
std::vector<Line> lines;
EndPointMapType start_point_to_line_idx;
for (int r = 0; r <= int(m_rows); ++ r) {
for (int c = 0; c <= int(m_cols); ++ c) {
- bool left = cell_inside_or_crossing(r , c-1);
- bool top = cell_inside_or_crossing(r-1, c );
- bool current = cell_inside_or_crossing(r , c );
+ int addr = (r + 1) * cell_cols + c + 1;
+ bool left = cell_inside[addr - 1];
+ bool top = cell_inside[addr - cell_cols];
+ bool current = cell_inside[addr];
if (left != current) {
lines.push_back(
left ?
@@ -1312,7 +1334,6 @@ Polygons EdgeGrid::Grid::contours_simplified() const
// Remove collineaer points.
Points pts;
pts.reserve(poly.points.size());
- coord_t downscale = 5;
for (size_t j = 0; j < poly.points.size(); ++ j) {
size_t j0 = (j == 0) ? poly.points.size() - 1 : j - 1;
size_t j2 = (j + 1 == poly.points.size()) ? 0 : j + 1;
@@ -1320,8 +1341,8 @@ Polygons EdgeGrid::Grid::contours_simplified() const
if (v.x != 0 && v.y != 0) {
// This is a corner point. Copy it to the output contour.
Point p = poly.points[j];
- p.y += (v.x < 0) ? downscale : -downscale;
- p.x += (v.y > 0) ? downscale : -downscale;
+ p.y += (v.x < 0) ? - offset : offset;
+ p.x += (v.y > 0) ? - offset : offset;
pts.push_back(p);
}
}
diff --git a/xs/src/libslic3r/EdgeGrid.hpp b/xs/src/libslic3r/EdgeGrid.hpp
index 2473ce423..a0b23211e 100644
--- a/xs/src/libslic3r/EdgeGrid.hpp
+++ b/xs/src/libslic3r/EdgeGrid.hpp
@@ -58,7 +58,7 @@ public:
const size_t cols() const { return m_cols; }
// For supports: Contours enclosing the rasterized edges.
- Polygons contours_simplified() const;
+ Polygons contours_simplified(coord_t offset) const;
protected:
struct Cell {
diff --git a/xs/src/libslic3r/Fill/FillRectilinear2.cpp b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
index 3f7232e06..5122de144 100644
--- a/xs/src/libslic3r/Fill/FillRectilinear2.cpp
+++ b/xs/src/libslic3r/Fill/FillRectilinear2.cpp
@@ -882,7 +882,7 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
Point refpt = rotate_vector.second.rotated(- rotate_vector.first);
// _align_to_grid will not work correctly with positive pattern_shift.
coord_t pattern_shift_scaled = coord_t(scale_(pattern_shift)) % line_spacing;
- refpt.x -= (pattern_shift_scaled > 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
+ refpt.x -= (pattern_shift_scaled >= 0) ? pattern_shift_scaled : (line_spacing + pattern_shift_scaled);
bounding_box.merge(_align_to_grid(
bounding_box.min,
Point(line_spacing, line_spacing),
@@ -892,7 +892,9 @@ bool FillRectilinear2::fill_surface_by_lines(const Surface *surface, const FillP
// Intersect a set of euqally spaced vertical lines wiht expolygon.
// n_vlines = ceil(bbox_width / line_spacing)
size_t n_vlines = (bounding_box.max.x - bounding_box.min.x + line_spacing - 1) / line_spacing;
- coord_t x0 = bounding_box.min.x + (line_spacing + SCALED_EPSILON) / 2;
+ coord_t x0 = bounding_box.min.x;
+ if (full_infill)
+ x0 += (line_spacing + SCALED_EPSILON) / 2;
#ifdef SLIC3R_DEBUG
static int iRun = 0;
diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp
index f97f888cd..e8b0e0a03 100644
--- a/xs/src/libslic3r/Print.hpp
+++ b/xs/src/libslic3r/Print.hpp
@@ -159,6 +159,7 @@ public:
void bridge_over_infill();
void _make_perimeters();
void _infill();
+ void _generate_support_material();
private:
Print* _print;
diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp
index 8d6ddaf21..3c92aad24 100644
--- a/xs/src/libslic3r/PrintObject.cpp
+++ b/xs/src/libslic3r/PrintObject.cpp
@@ -2,6 +2,7 @@
#include "BoundingBox.hpp"
#include "ClipperUtils.hpp"
#include "Geometry.hpp"
+#include "SupportMaterial.hpp"
#include <boost/log/trivial.hpp>
@@ -1243,4 +1244,10 @@ PrintObject::_infill()
this->state.set_done(posInfill);
}
+void PrintObject::_generate_support_material()
+{
+ PrintObjectSupportMaterial support_material(this, PrintObject::slicing_parameters());
+ support_material.generate(*this);
+}
+
} // namespace Slic3r
diff --git a/xs/src/libslic3r/Slicing.cpp b/xs/src/libslic3r/Slicing.cpp
index 0de781c64..5bd6bfc27 100644
--- a/xs/src/libslic3r/Slicing.cpp
+++ b/xs/src/libslic3r/Slicing.cpp
@@ -33,10 +33,18 @@ SlicingParameters SlicingParameters::create_from_config(
SlicingParameters params;
params.layer_height = object_config.layer_height.value;
+ params.first_print_layer_height = first_layer_height;
params.first_object_layer_height = first_layer_height;
params.object_print_z_min = 0.;
params.object_print_z_max = object_height;
params.base_raft_layers = object_config.raft_layers.value;
+ params.soluble_interface = soluble_interface;
+
+ if (! soluble_interface) {
+ params.gap_raft_object = object_config.support_material_contact_distance.value;
+ params.gap_object_support = object_config.support_material_contact_distance.value;
+ params.gap_support_object = object_config.support_material_contact_distance.value;
+ }
if (params.base_raft_layers > 0) {
params.interface_raft_layers = (params.base_raft_layers + 1) / 2;
@@ -70,18 +78,21 @@ SlicingParameters SlicingParameters::create_from_config(
if (params.has_raft()) {
// Raise first object layer Z by the thickness of the raft itself plus the extra distance required by the support material logic.
//FIXME The last raft layer is the contact layer, which shall be printed with a bridging flow for ease of separation. Currently it is not the case.
- coordf_t print_z = first_layer_height + object_config.support_material_contact_distance.value;
if (params.raft_layers() == 1) {
+ // There is only the contact layer.
params.contact_raft_layer_height = first_layer_height;
+ params.raft_contact_top_z = first_layer_height;
} else {
- print_z +=
- // Number of the base raft layers is decreased by the first layer, which has already been added to print_z.
- coordf_t(params.base_raft_layers - 1) * params.base_raft_layer_height +
- // Number of the interface raft layers is decreased by the contact layer.
- coordf_t(params.interface_raft_layers - 1) * params.interface_raft_layer_height +
- params.contact_raft_layer_height;
+ assert(params.base_raft_layers > 0);
+ assert(params.interface_raft_layers > 0);
+ // Number of the base raft layers is decreased by the first layer.
+ params.raft_base_top_z = first_layer_height + coordf_t(params.base_raft_layers - 1) * params.base_raft_layer_height;
+ // Number of the interface raft layers is decreased by the contact layer.
+ params.raft_interface_top_z = params.raft_base_top_z + coordf_t(params.interface_raft_layers - 1) * params.interface_raft_layer_height;
+ params.raft_contact_top_z = params.raft_interface_top_z + params.contact_raft_layer_height;
}
- params.object_print_z_min = print_z;
+ coordf_t print_z = params.raft_contact_top_z + params.gap_raft_object;
+ params.object_print_z_min = print_z;
params.object_print_z_max += print_z;
}
diff --git a/xs/src/libslic3r/Slicing.hpp b/xs/src/libslic3r/Slicing.hpp
index 349be2e4a..02ae7dd9e 100644
--- a/xs/src/libslic3r/Slicing.hpp
+++ b/xs/src/libslic3r/Slicing.hpp
@@ -53,6 +53,10 @@ struct SlicingParameters
// or by the variable layer thickness table.
coordf_t layer_height;
+ // First layer height of the print, this may be used for the first layer of the raft
+ // or for the first layer of the print.
+ coordf_t first_print_layer_height;
+
// Thickness of the first layer. This is either the first print layer thickness if printed without a raft,
// or a bridging flow thickness if printed over a non-soluble raft,
// or a normal layer height if printed over a soluble raft.
@@ -61,6 +65,16 @@ struct SlicingParameters
// If the object is printed over a non-soluble raft, the first layer may be printed with a briding flow.
bool first_object_layer_bridging;
+ // Soluble interface? (PLA soluble in water, HIPS soluble in lemonen)
+ // otherwise the interface must be broken off.
+ bool soluble_interface;
+ // Gap when placing object over raft.
+ coordf_t gap_raft_object;
+ // Gap when placing support over object.
+ coordf_t gap_object_support;
+ // Gap when placing object over support.
+ coordf_t gap_support_object;
+
// Minimum / maximum layer height, to be used for the automatic adaptive layer height algorithm,
// or by an interactive layer height editor.
coordf_t min_layer_height;
@@ -69,6 +83,10 @@ struct SlicingParameters
// Bottom and top of the printed object.
// If printed without a raft, object_print_z_min = 0 and object_print_z_max = object height.
// Otherwise object_print_z_min is equal to the raft height.
+ coordf_t raft_base_top_z;
+ coordf_t raft_interface_top_z;
+ coordf_t raft_contact_top_z;
+ // In case of a soluble interface, object_print_z_min == raft_contact_top_z, otherwise there is a gap between the raft and the 1st object layer.
coordf_t object_print_z_min;
coordf_t object_print_z_max;
};
diff --git a/xs/src/libslic3r/SupportMaterial.cpp b/xs/src/libslic3r/SupportMaterial.cpp
index 8bf9e9fc7..7806e36a5 100644
--- a/xs/src/libslic3r/SupportMaterial.cpp
+++ b/xs/src/libslic3r/SupportMaterial.cpp
@@ -31,60 +31,35 @@ namespace Slic3r {
#define PILLAR_SIZE (2.5)
#define PILLAR_SPACING 10
-PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object) :
+PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params) :
m_object (object),
m_print_config (&object->print()->config),
m_object_config (&object->config),
+ m_slicing_params (slicing_params),
m_first_layer_flow (Flow::new_from_config_width(
frSupportMaterial,
+ // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->print()->config.first_layer_extrusion_width.value > 0) ? object->print()->config.first_layer_extrusion_width : object->config.support_material_extrusion_width,
object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1),
- object->config.get_abs_value("first_layer_height"),
+ slicing_params.first_print_layer_height,
false
)),
m_support_material_flow (Flow::new_from_config_width(
frSupportMaterial,
+ // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
(object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1),
- object->config.layer_height.value,
+ slicing_params.layer_height,
false)),
m_support_material_interface_flow(Flow::new_from_config_width(
frSupportMaterialInterface,
- (object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
+ // The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
+ (object->config.support_material_extrusion_width > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
object->print()->config.nozzle_diameter.get_at(object->config.support_material_interface_extruder-1),
object->config.layer_height.value,
false)),
- m_soluble_interface (object->config.support_material_contact_distance.value == 0),
- m_support_material_raft_base_flow(0, 0, 0, false),
- m_support_material_raft_interface_flow(0, 0, 0, false),
- m_support_material_raft_contact_flow(0, 0, 0, false),
-
- m_has_raft (object->config.raft_layers.value > 0),
- m_num_base_raft_layers (0),
- m_num_interface_raft_layers (0),
- m_num_contact_raft_layers (0),
-
- // If set, the raft contact layer is laid with round strings, which are easily detachable
- // from both the below and above layes.
- // Otherwise a normal flow is used and the strings are squashed against the layer below,
- // creating a firm bond with the layer below and making the interface top surface flat.
-#if 1
- // This is the standard Slic3r behavior.
- m_raft_contact_layer_bridging(false),
- m_object_1st_layer_bridging (true),
-#else
- // This is more akin to what Simplify3D or Zortrax do.
- m_raft_contact_layer_bridging(true),
- m_object_1st_layer_bridging (false),
-#endif
-
- m_raft_height (0.),
- m_raft_base_height (0.),
- m_raft_interface_height (0.),
- m_raft_contact_height (0.),
-
// 50 mirons layer
m_support_layer_height_min (0.05),
m_support_layer_height_max (0.),
@@ -101,79 +76,6 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
// the support layers will be synchronized with the object layers exactly, no layer will be combined.
m_combine_support_layers (true)
{
- // Based on the raft style and size, initialize the raft layers and the 1st object layer attributes.
-
- size_t num_raft_layers = m_object_config->raft_layers.value;
-
- //FIXME better to draw thin strings, which are easier to remove from the object.
- if (m_has_raft)
- {
- if (m_raft_contact_layer_bridging)
- m_support_material_raft_contact_flow = Flow::new_from_spacing(
- m_support_material_raft_interface_flow.spacing(),
- m_support_material_raft_interface_flow.nozzle_diameter,
- m_support_material_raft_interface_flow.height,
- true);
-
- if (m_raft_contact_layer_bridging && num_raft_layers == 1)
- // The bridging contact layer will not bond to the bed well on its own.
- // Ensure there is at least the 1st layer printed with a firm squash.
- ++ num_raft_layers;
-
- // Split the raft layers into a single contact layer
- // and an equal number of interface and base layers,
- // with m_num_interface_raft_layers >= m_num_base_raft_layers.
- m_num_contact_raft_layers = 1;
- m_num_interface_raft_layers = num_raft_layers / 2;
- m_num_base_raft_layers = num_raft_layers - m_num_contact_raft_layers - m_num_interface_raft_layers;
- assert(m_num_interface_raft_layers >= m_num_base_raft_layers);
- assert(m_num_contact_raft_layers + m_num_base_raft_layers + m_num_interface_raft_layers == num_raft_layers);
-
- m_raft_contact_height = m_num_contact_raft_layers * m_support_material_raft_contact_flow.height;
- if (m_num_base_raft_layers > 0) {
- m_raft_base_height = first_layer_height() + (m_num_base_raft_layers - 1) * m_support_material_raft_base_flow.height;
- m_raft_interface_height = m_num_interface_raft_layers * m_support_material_raft_interface_flow.height;
- } else if (m_num_interface_raft_layers > 0) {
- m_raft_base_height = 0;
- m_raft_interface_height = first_layer_height() + (m_num_interface_raft_layers - 1) * m_support_material_raft_interface_flow.height;
- } else {
- m_raft_base_height = 0;
- m_raft_interface_height = 0;
- }
- m_raft_height = m_raft_base_height + m_raft_interface_height + m_raft_contact_height;
-
- // Find the layer height of the 1st object layer.
- if (m_object_1st_layer_bridging) {
- // Use an average nozzle diameter.
- std::set<size_t> extruders = m_object->print()->object_extruders();
- coordf_t nozzle_dmr = 0;
- for (std::set<size_t>::const_iterator it = extruders.begin(); it != extruders.end(); ++ it) {
- nozzle_dmr += m_object->print()->config.nozzle_diameter.get_at(*it);
- }
- nozzle_dmr /= extruders.size();
- m_object_1st_layer_height = nozzle_dmr;
- } else {
- m_object_1st_layer_height = m_object->config.layer_height.value;
- for (t_layer_height_ranges::const_iterator it = m_object->layer_height_ranges.begin(); it != m_object->layer_height_ranges.end(); ++ it) {
- if (m_object_1st_layer_height >= it->first.first && m_object_1st_layer_height <= it->first.second) {
- m_object_1st_layer_height = it->second;
- break;
- }
- }
- }
-
- m_object_1st_layer_gap = m_soluble_interface ? 0. : m_object_config->support_material_contact_distance.value;
- m_object_1st_layer_print_z = m_raft_height + m_object_1st_layer_gap + m_object_1st_layer_height;
- }
- else
- {
- // No raft.
- m_raft_contact_layer_bridging = false;
- m_object_1st_layer_bridging = false;
- m_object_1st_layer_height = m_first_layer_flow.height;
- m_object_1st_layer_gap = 0;
- m_object_1st_layer_print_z = m_object_1st_layer_height;
- }
}
// Using the std::deque as an allocator.
@@ -286,7 +188,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
// There is a contact layer below the 1st object layer in the bottom contacts.
// There is also a 1st intermediate layer containing bases of support columns.
// Extend the bases of the support columns and create the raft base.
- Polygons raft = this->generate_raft_base(object, bottom_contacts, intermediate_layers);
+ MyLayersPtr raft_layers = this->generate_raft_base(object, top_contacts, intermediate_layers, layer_storage);
/*
// If we wanted to apply some special logic to the first support layers lying on
@@ -323,7 +225,8 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
// Install support layers into the object.
MyLayersPtr layers_sorted;
- layers_sorted.reserve(bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size());
+ layers_sorted.reserve(raft_layers.size() + bottom_contacts.size() + top_contacts.size() + intermediate_layers.size() + interface_layers.size());
+ layers_append(layers_sorted, raft_layers);
layers_append(layers_sorted, bottom_contacts);
layers_append(layers_sorted, top_contacts);
layers_append(layers_sorted, intermediate_layers);
@@ -351,7 +254,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
BOOST_LOG_TRIVIAL(info) << "Support generator - Generating tool paths";
// Generate the actual toolpaths and save them into each layer.
- this->generate_toolpaths(object, raft, bottom_contacts, top_contacts, intermediate_layers, interface_layers);
+ this->generate_toolpaths(object, raft_layers, bottom_contacts, top_contacts, intermediate_layers, interface_layers);
BOOST_LOG_TRIVIAL(info) << "Support generator - End";
}
@@ -670,7 +573,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
MyLayer &new_layer = layer_allocate(layer_storage, sltTopContact);
const Layer *layer_below = (layer_id > 0) ? object.get_layer(layer_id - 1) : NULL;
new_layer.idx_object_layer_above = layer_id;
- if (m_soluble_interface) {
+ if (m_slicing_params.soluble_interface) {
// Align the contact surface height with a layer immediately below the supported layer.
new_layer.height = layer_below ?
// Interface layer will be synchronized with the object.
@@ -984,16 +887,16 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
// Grow top surfaces so that interface and support generation are generated
// with some spacing from object - it looks we don't need the actual
// top shapes so this can be done here
- layer_new.height = m_soluble_interface ?
+ layer_new.height = m_slicing_params.soluble_interface ?
// Align the interface layer with the object's layer height.
object.get_layer(layer_id + 1)->height :
// Place a bridge flow interface layer over the top surface.
m_support_material_interface_flow.nozzle_diameter;
layer_new.print_z = layer.print_z + layer_new.height +
- (m_soluble_interface ? 0. : m_object_config->support_material_contact_distance.value);
+ (m_slicing_params.soluble_interface ? 0. : m_object_config->support_material_contact_distance.value);
layer_new.bottom_z = layer.print_z;
layer_new.idx_object_layer_below = layer_id;
- layer_new.bridging = ! m_soluble_interface;
+ layer_new.bridging = ! m_slicing_params.soluble_interface;
//FIXME how much to inflate the top surface?
layer_new.polygons = offset(touching, float(m_support_material_flow.scaled_width()));
#ifdef SLIC3R_DEBUG
@@ -1011,7 +914,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
// Create an EdgeGrid, initialize it with projection, initialize signed distance field.
Slic3r::EdgeGrid::Grid grid;
- coord_t grid_resolution = scale_(1.5f);
+ coordf_t support_spacing = m_object_config->support_material_spacing.value + m_support_material_flow.spacing();
+ coord_t grid_resolution = scale_(support_spacing); // scale_(1.5f);
BoundingBox bbox = get_extents(projection);
bbox.offset(20);
bbox.align_to_grid(grid_resolution);
@@ -1020,7 +924,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
grid.calculate_sdf();
// Extract a bounding contour from the grid.
- Polygons projection_simplified = grid.contours_simplified();
+ Polygons projection_simplified = grid.contours_simplified(-5);
#ifdef SLIC3R_DEBUG
{
BoundingBox bbox = get_extents(projection);
@@ -1031,12 +935,15 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
svg.draw(union_ex(projection_simplified, false), "red", 0.5);
}
#endif /* SLIC3R_DEBUG */
- projection = std::move(projection_simplified);
+ layer_support_areas[layer_id] = diff(
+ grid.contours_simplified(m_support_material_flow.scaled_spacing()/2 + 5),
+ to_polygons(layer.slices.expolygons),
+ true);
- // Remove the areas that touched from the projection that will continue on next, lower, top surfaces.
+ // Remove the areas that touched from the projection that will continue on next, lower, top surfaces.
// projection = diff(projection, touching);
- projection = diff(projection, to_polygons(layer.slices.expolygons), true);
- layer_support_areas[layer_id] = projection;
+ projection = diff(projection_simplified, to_polygons(layer.slices.expolygons), true);
+// layer_support_areas[layer_id] = projection;
}
std::reverse(bottom_contacts.begin(), bottom_contacts.end());
} // ! top_contacts.empty()
@@ -1058,7 +965,7 @@ void PrintObjectSupportMaterial::trim_top_contacts_by_bottom_contacts(
// For all top contact layers overlapping with the thick bottom contact layer:
for (size_t idx_top = idx_top_first; idx_top < top_contacts.size(); ++ idx_top) {
MyLayer &layer_top = *top_contacts[idx_top];
- coordf_t interface_z = m_soluble_interface ?
+ coordf_t interface_z = m_slicing_params.soluble_interface ?
(layer_top.bottom_z + EPSILON) :
(layer_top.bottom_z - m_support_layer_height_min);
if (interface_z < layer_bottom.print_z) {
@@ -1093,9 +1000,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
return intermediate_layers;
std::sort(extremes.begin(), extremes.end());
- // Top of the 0th layer.
- coordf_t top_z_0th = this->raft_base_height() + this->raft_interface_height();
- assert(extremes.front().z() > top_z_0th && extremes.front().z() >= this->first_layer_height());
+ assert(extremes.front().z() > m_slicing_params.raft_interface_top_z && extremes.front().z() >= m_slicing_params.first_print_layer_height);
// Generate intermediate layers.
// The first intermediate layer is the same as the 1st layer if there is no raft,
@@ -1103,7 +1008,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
// Intermediate layers are always printed with a normal etrusion flow (non-bridging).
for (size_t idx_extreme = 0; idx_extreme < extremes.size(); ++ idx_extreme) {
LayerExtreme *extr1 = (idx_extreme == 0) ? NULL : &extremes[idx_extreme-1];
- coordf_t extr1z = (extr1 == NULL) ? top_z_0th : extr1->z();
+ coordf_t extr1z = (extr1 == NULL) ? m_slicing_params.raft_interface_top_z : extr1->z();
LayerExtreme &extr2 = extremes[idx_extreme];
coordf_t extr2z = extr2.z();
coordf_t dist = extr2z - extr1z;
@@ -1112,7 +1017,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
size_t n_layers_extra = size_t(ceil(dist / m_support_layer_height_max));
assert(n_layers_extra > 0);
coordf_t step = dist / coordf_t(n_layers_extra);
- if (! m_soluble_interface && ! m_synchronize_support_layers_with_object && extr2.layer->layer_type == sltTopContact) {
+ if (! m_slicing_params.soluble_interface && ! m_synchronize_support_layers_with_object && extr2.layer->layer_type == sltTopContact) {
assert(extr2.layer->height == 0.);
// This is a top interface layer, which does not have a height assigned yet. Do it now.
if (m_synchronize_support_layers_with_object) {
@@ -1345,43 +1250,74 @@ void PrintObjectSupportMaterial::generate_base_layers(
#endif /* SLIC3R_DEBUG */
}
-Polygons PrintObjectSupportMaterial::generate_raft_base(
+PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raft_base(
const PrintObject &object,
- const MyLayersPtr &bottom_contacts,
- MyLayersPtr &intermediate_layers) const
+ const MyLayersPtr &top_contacts,
+ MyLayersPtr &intermediate_layers,
+ MyLayerStorage &layer_storage) const
{
- assert(! bottom_contacts.empty());
-
+ // Areas covered by the raft, supporting the raft interface and the support columns.
Polygons raft_polygons;
- #if 0
+ // How much to inflate the support columns to be stable. This also applies to the 1st layer, if no raft layers are to be printed.
const float inflate_factor = scale_(3.);
- if (this->has_raft()) {
- MyLayer &contacts = *bottom_contacts.front();
- MyLayer &columns_base = *intermediate_layers.front();
- if (m_num_base_raft_layers == 0 && m_num_interface_raft_layers == 0 && m_num_contact_raft_layers == 1) {
- // Having only the contact layer, which has the height of the 1st layer.
- // We are free to merge the contacts with the columns_base, they will be printed the same way.
- polygons_append(contacts.polygons, offset(columns_base.polygons, inflate_factor));
- contacts.polygons = union_(contacts.polygons);
- } else {
- // Having multiple raft layers.
- assert(m_num_interface_raft_layers > 0);
- // Extend the raft base by the bases of the support columns, add the raft contacts.
- raft_polygons = raft_interface_polygons;
- //FIXME make the offset configurable.
- polygons_append(raft_polygons, offset(columns_base.polygons, inflate_factor));
- raft_polygons = union_(raft_polygons);
+ MyLayer *contacts = top_contacts.empty() ? nullptr : top_contacts.front();
+ MyLayer *columns_base = intermediate_layers.empty() ? nullptr : intermediate_layers.front();
+ if (contacts != nullptr && contacts->print_z > m_slicing_params.raft_contact_top_z + EPSILON)
+ // This is not the raft contact layer.
+ contacts = nullptr;
+
+ // Output vector.
+ MyLayersPtr raft_layers;
+
+ // Expand the 1st intermediate layer, which contains the bases of the support columns.
+ Polygons base;
+ if (columns_base != nullptr) {
+ base = offset(columns_base->polygons, inflate_factor);
+ // Modify the 1st intermediate layer with the expanded support columns.
+ columns_base->polygons = diff(
+ base,
+ offset(m_object->layers.front()->slices.expolygons, scale_(m_gap_xy)));
+ if (contacts != nullptr)
+ columns_base->polygons = diff(columns_base->polygons, contacts->polygons);
+ }
+ if (m_slicing_params.has_raft() && contacts != nullptr) {
+ // Merge the untrimmed columns base with the expanded raft interface, to be used for the support base and interface.
+ base = union_(base, offset(contacts->polygons, inflate_factor));
+ }
+ if (m_slicing_params.has_raft() && m_slicing_params.raft_layers() > 1 && ! base.empty()) {
+ // Do not add the raft contact layer, only add the raft layers below the contact layer.
+ // Insert the 1st layer.
+ {
+ MyLayer &new_layer = layer_allocate(layer_storage, (m_slicing_params.base_raft_layers > 0) ? sltRaftBase : sltRaftInterface);
+ raft_layers.push_back(&new_layer);
+ new_layer.print_z = m_slicing_params.first_print_layer_height;
+ new_layer.height = m_slicing_params.first_print_layer_height;
+ new_layer.bottom_z = 0.;
+ new_layer.polygons = base;
}
- } else {
- // No raft. The 1st intermediate layer contains the bases of the support columns.
- // Expand the polygons, but trim with the object.
- MyLayer &columns_base = *intermediate_layers.front();
- columns_base.polygons = diff(
- offset(columns_base.polygons, inflate_factor),
- offset(m_object->get_layer(0), safety_factor);
+ // Insert the base layers.
+ for (size_t i = 1; i < m_slicing_params.base_raft_layers; ++ i) {
+ coordf_t print_z = raft_layers.back()->print_z;
+ MyLayer &new_layer = layer_allocate(layer_storage, sltRaftBase);
+ raft_layers.push_back(&new_layer);
+ new_layer.print_z = print_z + m_slicing_params.base_raft_layer_height;
+ new_layer.height = m_slicing_params.base_raft_layer_height;
+ new_layer.bottom_z = print_z;
+ new_layer.polygons = base;
+ }
+ // Insert the interface layers.
+ for (size_t i = 1; i < m_slicing_params.interface_raft_layers; ++ i) {
+ coordf_t print_z = raft_layers.back()->print_z;
+ MyLayer &new_layer = layer_allocate(layer_storage, sltRaftInterface);
+ raft_layers.push_back(&new_layer);
+ new_layer.print_z = print_z + m_slicing_params.interface_raft_layer_height;
+ new_layer.height = m_slicing_params.interface_raft_layer_height;
+ new_layer.bottom_z = print_z;
+ new_layer.polygons = base;
+ }
}
- #endif
- return raft_polygons;
+
+ return raft_layers;
}
// Convert some of the intermediate layers into top/bottom interface layers.
@@ -1474,6 +1410,7 @@ static inline void fill_expolygons_generate_paths(
FillParams fill_params;
fill_params.density = density;
fill_params.complete = true;
+ fill_params.dont_adjust = true;
for (ExPolygons::const_iterator it_expolygon = expolygons.begin(); it_expolygon != expolygons.end(); ++ it_expolygon) {
Surface surface(stInternal, *it_expolygon);
extrusion_entities_append_paths(
@@ -1495,6 +1432,7 @@ static inline void fill_expolygons_generate_paths(
FillParams fill_params;
fill_params.density = density;
fill_params.complete = true;
+ fill_params.dont_adjust = true;
for (ExPolygons::iterator it_expolygon = expolygons.begin(); it_expolygon != expolygons.end(); ++ it_expolygon) {
Surface surface(stInternal, std::move(*it_expolygon));
extrusion_entities_append_paths(
@@ -1636,7 +1574,7 @@ void LoopInterfaceProcessor::generate(MyLayerExtruded &top_contact_layer, const
void PrintObjectSupportMaterial::generate_toolpaths(
const PrintObject &object,
- const Polygons &raft,
+ const MyLayersPtr &raft_layers,
const MyLayersPtr &bottom_contacts,
const MyLayersPtr &top_contacts,
const MyLayersPtr &intermediate_layers,
@@ -1667,7 +1605,8 @@ void PrintObjectSupportMaterial::generate_toolpaths(
std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(ipRectilinear));
std::unique_ptr<Fill> filler_support = std::unique_ptr<Fill>(Fill::new_from_type(infill_pattern));
{
- BoundingBox bbox_object = object.bounding_box();
+// BoundingBox bbox_object = object.bounding_box();
+ BoundingBox bbox_object(Point(-scale_(1.), -scale_(1.0)), Point(scale_(1.), scale_(1.)));
filler_interface->set_bounding_box(bbox_object);
filler_support->set_bounding_box(bbox_object);
}
@@ -1694,12 +1633,64 @@ void PrintObjectSupportMaterial::generate_toolpaths(
},
);
*/
+ // Insert the raft base layers.
+ size_t support_layer_id = 0;
+ for (; support_layer_id < size_t(std::max(0, int(m_slicing_params.raft_layers()) - 1)); ++ support_layer_id) {
+ SupportLayer &support_layer = *object.support_layers[support_layer_id];
+ assert(support_layer_id < raft_layers.size());
+ MyLayer &raft_layer = *raft_layers[support_layer_id];
+ //FIXME When paralellizing, each thread shall have its own copy of the fillers.
+ Fill *filler = filler_support.get();
+ filler->angle = 0.;
+ // We don't use $base_flow->spacing because we need a constant spacing
+ // value that guarantees that all layers are correctly aligned.
+ Flow flow(m_support_material_flow.width, raft_layer.height, m_support_material_flow.nozzle_diameter, raft_layer.bridging);
+ filler->spacing = m_support_material_flow.spacing();
+ float density = support_density;
+ // find centerline of the external loop/extrusions
+ ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
+ // union_ex(base_polygons, true) :
+ offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON) :
+ offset2_ex(raft_layer.polygons, SCALED_EPSILON, - SCALED_EPSILON - 0.5*flow.scaled_width());
+ if (support_layer_id == 0) {
+ // Base flange.
+ filler = filler_interface.get();
+ filler->angle = m_object_config->support_material_angle + 90.;
+ density = 0.5f;
+ flow = m_first_layer_flow;
+ // use the proper spacing for first layer as we don't need to align
+ // its pattern to the other layers
+ //FIXME When paralellizing, each thread shall have its own copy of the fillers.
+ filler->spacing = flow.spacing();
+ } else if (with_sheath) {
+ // Draw a perimeter all around the support infill. This makes the support stable, but difficult to remove.
+ // TODO: use brim ordering algorithm
+ Polygons to_infill_polygons = to_polygons(to_infill);
+ // TODO: use offset2_ex()
+ to_infill = offset_ex(to_infill, - flow.scaled_spacing());
+ extrusion_entities_append_paths(
+ support_layer.support_fills.entities,
+ to_polylines(STDMOVE(to_infill_polygons)),
+ erSupportMaterial, flow.mm3_per_mm(), flow.width, flow.height);
+ }
+ fill_expolygons_generate_paths(
+ // Destination
+ support_layer.support_fills.entities,
+ // Regions to fill
+ STDMOVE(to_infill),
+ // Filler and its parameters
+ filler, density,
+ // Extrusion parameters
+ erSupportMaterial, flow);
+
+ }
+
// Indices of the 1st layer in their respective container at the support layer height.
size_t idx_layer_bottom_contact = 0;
size_t idx_layer_top_contact = 0;
size_t idx_layer_intermediate = 0;
size_t idx_layer_inteface = 0;
- for (size_t support_layer_id = 0; support_layer_id < object.support_layers.size(); ++ support_layer_id)
+ for (; support_layer_id < object.support_layers.size(); ++ support_layer_id)
{
SupportLayer &support_layer = *object.support_layers[support_layer_id];
@@ -1754,7 +1745,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// If no loops are allowed, we treat the contact layer exactly as a generic interface layer.
if (interface_layer.could_merge(top_contact_layer))
interface_layer.merge(std::move(top_contact_layer));
- }
+ }
if (! interface_layer.empty() && ! base_layer.empty()) {
// turn base support into interface when it's contained in our holes
@@ -1814,7 +1805,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
// We don't use $base_flow->spacing because we need a constant spacing
// value that guarantees that all layers are correctly aligned.
Flow flow(m_support_material_flow.width, base_layer.layer->height, m_support_material_flow.nozzle_diameter, base_layer.layer->bridging);
- filler->spacing = flow.spacing();
+ filler->spacing = m_support_material_flow.spacing();
float density = support_density;
// find centerline of the external loop/extrusions
ExPolygons to_infill = (support_layer_id == 0 || ! with_sheath) ?
diff --git a/xs/src/libslic3r/SupportMaterial.hpp b/xs/src/libslic3r/SupportMaterial.hpp
index abcaf676a..c9cbee488 100644
--- a/xs/src/libslic3r/SupportMaterial.hpp
+++ b/xs/src/libslic3r/SupportMaterial.hpp
@@ -3,6 +3,7 @@
#include "Flow.hpp"
#include "PrintConfig.hpp"
+#include "Slicing.hpp"
namespace Slic3r {
@@ -22,7 +23,8 @@ class PrintObjectSupportMaterial
public:
enum SupporLayerType {
sltUnknown = 0,
- sltRaft,
+ sltRaftBase,
+ sltRaftInterface,
stlFirstLayer,
sltBottomContact,
sltBottomInterface,
@@ -118,37 +120,17 @@ public:
typedef std::deque<MyLayer> MyLayerStorage;
public:
- PrintObjectSupportMaterial(const PrintObject *object);
+ PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params);
// Height of the 1st layer is user configured as it is important for the print
// to stick to he print bed.
coordf_t first_layer_height() const { return m_object_config->first_layer_height.value; }
// Is raft enabled?
- bool has_raft() const { return m_has_raft; }
+ bool has_raft() const { return m_slicing_params.has_raft(); }
// Has any support?
bool has_support() const { return m_object_config->support_material.value; }
- // How many raft layers are there below the 1st object layer?
- // The 1st object layer_id will be offsetted by this number.
- size_t num_raft_layers() const { return m_object_config->raft_layers.value; }
- // num_raft_layers() == num_raft_base_layers() + num_raft_interface_layers() + num_raft_contact_layers().
- size_t num_raft_base_layers() const { return m_num_base_raft_layers; }
- size_t num_raft_interface_layers() const { return m_num_interface_raft_layers; }
- size_t num_raft_contact_layers() const { return m_num_contact_raft_layers; }
-
- coordf_t raft_height() const { return m_raft_height; }
- coordf_t raft_base_height() const { return m_raft_base_height; }
- coordf_t raft_interface_height() const { return m_raft_interface_height; }
- coordf_t raft_contact_height() const { return m_raft_contact_height; }
- bool raft_bridging() const { return m_raft_contact_layer_bridging; }
-
- // 1st layer of the object will be printed depeding on the raft settings.
- coordf_t first_object_layer_print_z() const { return m_object_1st_layer_print_z; }
- coordf_t first_object_layer_height() const { return m_object_1st_layer_height; }
- coordf_t first_object_layer_gap() const { return m_object_1st_layer_gap; }
- bool first_object_layer_bridging() const { return m_object_1st_layer_bridging; }
-
// Generate support material for the object.
// New support layers will be added to the object,
// with extrusion paths and islands filled in for each support layer.
@@ -185,10 +167,11 @@ private:
MyLayersPtr &intermediate_layers,
std::vector<Polygons> &layer_support_areas) const;
- Polygons generate_raft_base(
+ MyLayersPtr generate_raft_base(
const PrintObject &object,
- const MyLayersPtr &bottom_contacts,
- MyLayersPtr &intermediate_layers) const;
+ const MyLayersPtr &top_contacts,
+ MyLayersPtr &intermediate_layers,
+ MyLayerStorage &layer_storage) const;
MyLayersPtr generate_interface_layers(
const PrintObject &object,
@@ -205,7 +188,7 @@ private:
// Produce the actual G-code.
void generate_toolpaths(
const PrintObject &object,
- const Polygons &raft,
+ const MyLayersPtr &raft_layers,
const MyLayersPtr &bottom_contacts,
const MyLayersPtr &top_contacts,
const MyLayersPtr &intermediate_layers,
@@ -214,36 +197,14 @@ private:
const PrintObject *m_object;
const PrintConfig *m_print_config;
const PrintObjectConfig *m_object_config;
+ SlicingParameters m_slicing_params;
Flow m_first_layer_flow;
Flow m_support_material_flow;
+ coordf_t m_support_material_spacing;
Flow m_support_material_interface_flow;
- bool m_soluble_interface;
-
- Flow m_support_material_raft_base_flow;
- Flow m_support_material_raft_interface_flow;
- Flow m_support_material_raft_contact_flow;
-
- bool m_has_raft;
- size_t m_num_base_raft_layers;
- size_t m_num_interface_raft_layers;
- size_t m_num_contact_raft_layers;
- // If set, the raft contact layer is laid with round strings, which are easily detachable
- // from both the below and above layes.
- // Otherwise a normal flow is used and the strings are squashed against the layer below,
- // creating a firm bond with the layer below and making the interface top surface flat.
- coordf_t m_raft_height;
- coordf_t m_raft_base_height;
- coordf_t m_raft_interface_height;
- coordf_t m_raft_contact_height;
- bool m_raft_contact_layer_bridging;
-
- coordf_t m_object_1st_layer_print_z;
- coordf_t m_object_1st_layer_height;
- coordf_t m_object_1st_layer_gap;
- bool m_object_1st_layer_bridging;
-
- coordf_t m_object_layer_height_max;
+ coordf_t m_support_material_interface_spacing;
+
coordf_t m_support_layer_height_min;
coordf_t m_support_layer_height_max;
coordf_t m_support_interface_layer_height_max;
diff --git a/xs/src/libslic3r/SurfaceCollection.cpp b/xs/src/libslic3r/SurfaceCollection.cpp
index cfeae4ccc..70272fede 100644
--- a/xs/src/libslic3r/SurfaceCollection.cpp
+++ b/xs/src/libslic3r/SurfaceCollection.cpp
@@ -8,22 +8,12 @@ namespace Slic3r {
SurfaceCollection::operator Polygons() const
{
- Polygons polygons;
- for (Surfaces::const_iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
- Polygons surface_p = surface->expolygon;
- polygons.insert(polygons.end(), surface_p.begin(), surface_p.end());
- }
- return polygons;
+ return to_polygons(surfaces);
}
SurfaceCollection::operator ExPolygons() const
{
- ExPolygons expp;
- expp.reserve(this->surfaces.size());
- for (Surfaces::const_iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
- expp.push_back(surface->expolygon);
- }
- return expp;
+ return to_expolygons(surfaces);
}
void
diff --git a/xs/src/libslic3r/libslic3r.h b/xs/src/libslic3r/libslic3r.h
index 89db6d81e..d2a3c7c86 100644
--- a/xs/src/libslic3r/libslic3r.h
+++ b/xs/src/libslic3r/libslic3r.h
@@ -123,7 +123,7 @@ parallelize(std::queue<T> queue, boost::function<void(T)> func,
if (threads_count == 0) threads_count = 2;
boost::mutex queue_mutex;
boost::thread_group workers;
- for (int i = 0; i < fminf(threads_count, queue.size()); i++)
+ for (int i = 0; i < std::min(threads_count, int(queue.size())); ++ i)
workers.add_thread(new boost::thread(&_parallelize_do<T>, &queue, &queue_mutex, func));
workers.join_all();
}