New supports now do rafts at least to the extent the test cases run through.
New supports enabled, old supports will go away soon.
This commit is contained in:
parent
5614e997a4
commit
955bc957ba
17 changed files with 279 additions and 308 deletions
|
@ -377,7 +377,9 @@ sub mouse_event {
|
|||
$self->_layer_height_edited(undef);
|
||||
} elsif ($e->Moving) {
|
||||
$self->_mouse_pos($pos);
|
||||
$self->Refresh;
|
||||
# Only refresh if picking is enabled, in that case the objects may get highlighted if the mouse cursor
|
||||
# hovers over.
|
||||
$self->Refresh if ($self->enable_picking);
|
||||
} else {
|
||||
$e->Skip();
|
||||
}
|
||||
|
@ -1047,9 +1049,10 @@ sub Render {
|
|||
|
||||
$self->draw_active_object_annotations;
|
||||
|
||||
glFlush();
|
||||
|
||||
$self->SwapBuffers();
|
||||
|
||||
# Calling glFinish has a performance penalty, but it seems to fix some OpenGL driver hang-up with extremely large scenes.
|
||||
glFinish();
|
||||
}
|
||||
|
||||
sub draw_volumes {
|
||||
|
|
|
@ -260,44 +260,35 @@ sub generate_support_material {
|
|||
|
||||
$self->clear_support_layers;
|
||||
|
||||
if ((!$self->config->support_material && $self->config->raft_layers == 0) || scalar(@{$self->layers}) < 2) {
|
||||
$self->set_step_done(STEP_SUPPORTMATERIAL);
|
||||
return;
|
||||
if (($self->config->support_material || $self->config->raft_layers > 0) && scalar(@{$self->layers}) > 1) {
|
||||
$self->print->status_cb->(85, "Generating support material");
|
||||
if (0) {
|
||||
# Old supports, Perl implementation.
|
||||
my $first_layer_flow = Slic3r::Flow->new_from_width(
|
||||
width => ($self->print->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width),
|
||||
role => FLOW_ROLE_SUPPORT_MATERIAL,
|
||||
nozzle_diameter => $self->print->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ]
|
||||
// $self->print->config->nozzle_diameter->[0],
|
||||
layer_height => $self->config->get_abs_value('first_layer_height'),
|
||||
bridge_flow_ratio => 0,
|
||||
);
|
||||
my $support_material = Slic3r::Print::SupportMaterial->new(
|
||||
print_config => $self->print->config,
|
||||
object_config => $self->config,
|
||||
first_layer_flow => $first_layer_flow,
|
||||
flow => $self->support_material_flow,
|
||||
interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
|
||||
);
|
||||
$support_material->generate($self);
|
||||
} else {
|
||||
# New supports, C++ implementation.
|
||||
$self->_generate_support_material;
|
||||
}
|
||||
}
|
||||
$self->print->status_cb->(85, "Generating support material");
|
||||
|
||||
$self->_support_material->generate($self);
|
||||
|
||||
$self->set_step_done(STEP_SUPPORTMATERIAL);
|
||||
}
|
||||
|
||||
sub _support_material {
|
||||
my ($self) = @_;
|
||||
|
||||
my $first_layer_flow = Slic3r::Flow->new_from_width(
|
||||
width => ($self->print->config->first_layer_extrusion_width || $self->config->support_material_extrusion_width),
|
||||
role => FLOW_ROLE_SUPPORT_MATERIAL,
|
||||
nozzle_diameter => $self->print->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ]
|
||||
// $self->print->config->nozzle_diameter->[0],
|
||||
layer_height => $self->config->get_abs_value('first_layer_height'),
|
||||
bridge_flow_ratio => 0,
|
||||
);
|
||||
|
||||
if (1) {
|
||||
# Old supports, Perl implementation.
|
||||
return Slic3r::Print::SupportMaterial->new(
|
||||
print_config => $self->print->config,
|
||||
object_config => $self->config,
|
||||
first_layer_flow => $first_layer_flow,
|
||||
flow => $self->support_material_flow,
|
||||
interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
|
||||
);
|
||||
} else {
|
||||
# New supports, C++ implementation.
|
||||
return Slic3r::Print::SupportMaterial2->new($self);
|
||||
}
|
||||
}
|
||||
|
||||
# Idempotence of this method is guaranteed by the fact that we don't remove things from
|
||||
# fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries.
|
||||
sub clip_fill_surfaces {
|
||||
|
|
|
@ -20,6 +20,7 @@ has 'interface_flow' => (is => 'rw', required => 1);
|
|||
use constant DEBUG_CONTACT_ONLY => 0;
|
||||
|
||||
# increment used to reach MARGIN in steps to avoid trespassing thin objects
|
||||
use constant MARGIN => 1.5;
|
||||
use constant MARGIN_STEP => MARGIN/3;
|
||||
|
||||
# generate a tree-like structure to save material
|
||||
|
|
|
@ -209,7 +209,6 @@ xsp/Polygon.xsp
|
|||
xsp/Polyline.xsp
|
||||
xsp/PolylineCollection.xsp
|
||||
xsp/Print.xsp
|
||||
xsp/SupportMaterial.xsp
|
||||
xsp/Surface.xsp
|
||||
xsp/SurfaceCollection.xsp
|
||||
xsp/TriangleMesh.xsp
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -159,6 +159,7 @@ public:
|
|||
void bridge_over_infill();
|
||||
void _make_perimeters();
|
||||
void _infill();
|
||||
void _generate_support_material();
|
||||
|
||||
private:
|
||||
Print* _print;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
} 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);
|
||||
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));
|
||||
}
|
||||
#endif
|
||||
return raft_polygons;
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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) ?
|
||||
|
|
|
@ -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;
|
||||
coordf_t m_support_material_interface_spacing;
|
||||
|
||||
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_layer_height_min;
|
||||
coordf_t m_support_layer_height_max;
|
||||
coordf_t m_support_interface_layer_height_max;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ _constant()
|
|||
void bridge_over_infill();
|
||||
void _make_perimeters();
|
||||
void _infill();
|
||||
void _generate_support_material();
|
||||
|
||||
void adjust_layer_height_profile(coordf_t z, coordf_t layer_thickness_delta, coordf_t band_width, int action)
|
||||
%code%{
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
%module{Slic3r::XS};
|
||||
|
||||
%{
|
||||
#include <xsinit.h>
|
||||
#include "libslic3r/SupportMaterial.hpp"
|
||||
%}
|
||||
|
||||
%name{Slic3r::Print::SupportMaterial2} class PrintObjectSupportMaterial {
|
||||
PrintObjectSupportMaterial(PrintObject *print_object);
|
||||
~PrintObjectSupportMaterial();
|
||||
|
||||
void generate(PrintObject *object)
|
||||
%code{% THIS->generate(*object); %};
|
||||
};
|
||||
|
||||
%package{Slic3r::Print::SupportMaterial};
|
||||
%{
|
||||
|
||||
SV*
|
||||
MARGIN()
|
||||
PROTOTYPE:
|
||||
CODE:
|
||||
RETVAL = newSVnv(SUPPORT_MATERIAL_MARGIN);
|
||||
OUTPUT: RETVAL
|
||||
|
||||
%}
|
Loading…
Reference in a new issue