Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
80ef0e0334
@ -122,21 +122,21 @@ Polygons AvoidCrossingPerimeters::collect_contours_all_layers(const PrintObjectP
|
|||||||
const Layer* layer1 = object->layers()[i * 2];
|
const Layer* layer1 = object->layers()[i * 2];
|
||||||
const Layer* layer2 = object->layers()[i * 2 + 1];
|
const Layer* layer2 = object->layers()[i * 2 + 1];
|
||||||
Polygons polys;
|
Polygons polys;
|
||||||
polys.reserve(layer1->slices.size() + layer2->slices.size());
|
polys.reserve(layer1->lslices.size() + layer2->lslices.size());
|
||||||
for (const ExPolygon &expoly : layer1->slices)
|
for (const ExPolygon &expoly : layer1->lslices)
|
||||||
//FIXME no holes?
|
//FIXME no holes?
|
||||||
polys.emplace_back(expoly.contour);
|
polys.emplace_back(expoly.contour);
|
||||||
for (const ExPolygon &expoly : layer2->slices)
|
for (const ExPolygon &expoly : layer2->lslices)
|
||||||
//FIXME no holes?
|
//FIXME no holes?
|
||||||
polys.emplace_back(expoly.contour);
|
polys.emplace_back(expoly.contour);
|
||||||
polygons_per_layer[i] = union_(polys);
|
polygons_per_layer[i] = union_(polys);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (object->layers().size() & 1) {
|
if (object->layers().size() & 1) {
|
||||||
const Layer *layer = object->layers().back();
|
const Layer *layer = object->layers().back();
|
||||||
Polygons polys;
|
Polygons polys;
|
||||||
polys.reserve(layer->slices.size());
|
polys.reserve(layer->lslices.size());
|
||||||
for (const ExPolygon &expoly : layer->slices)
|
for (const ExPolygon &expoly : layer->lslices)
|
||||||
//FIXME no holes?
|
//FIXME no holes?
|
||||||
polys.emplace_back(expoly.contour);
|
polys.emplace_back(expoly.contour);
|
||||||
polygons_per_layer.back() = union_(polys);
|
polygons_per_layer.back() = union_(polys);
|
||||||
@ -2006,8 +2006,8 @@ void GCode::process_layer(
|
|||||||
// - for each island, we extrude perimeters first, unless user set the infill_first
|
// - for each island, we extrude perimeters first, unless user set the infill_first
|
||||||
// option
|
// option
|
||||||
// (Still, we have to keep track of regions because we need to apply their config)
|
// (Still, we have to keep track of regions because we need to apply their config)
|
||||||
size_t n_slices = layer.slices.size();
|
size_t n_slices = layer.lslices.size();
|
||||||
const std::vector<BoundingBox> &layer_surface_bboxes = layer.slices_bboxes;
|
const std::vector<BoundingBox> &layer_surface_bboxes = layer.lslices_bboxes;
|
||||||
// Traverse the slices in an increasing order of bounding box size, so that the islands inside another islands are tested first,
|
// Traverse the slices in an increasing order of bounding box size, so that the islands inside another islands are tested first,
|
||||||
// so we can just test a point inside ExPolygon::contour and we may skip testing the holes.
|
// so we can just test a point inside ExPolygon::contour and we may skip testing the holes.
|
||||||
std::vector<size_t> slices_test_order;
|
std::vector<size_t> slices_test_order;
|
||||||
@ -2023,7 +2023,7 @@ void GCode::process_layer(
|
|||||||
const BoundingBox &bbox = layer_surface_bboxes[i];
|
const BoundingBox &bbox = layer_surface_bboxes[i];
|
||||||
return point(0) >= bbox.min(0) && point(0) < bbox.max(0) &&
|
return point(0) >= bbox.min(0) && point(0) < bbox.max(0) &&
|
||||||
point(1) >= bbox.min(1) && point(1) < bbox.max(1) &&
|
point(1) >= bbox.min(1) && point(1) < bbox.max(1) &&
|
||||||
layer.slices[i].contour.contains(point);
|
layer.lslices[i].contour.contains(point);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||||
@ -2155,7 +2155,7 @@ void GCode::process_layer(
|
|||||||
m_config.apply(instance_to_print.print_object.config(), true);
|
m_config.apply(instance_to_print.print_object.config(), true);
|
||||||
m_layer = layers[instance_to_print.layer_id].layer();
|
m_layer = layers[instance_to_print.layer_id].layer();
|
||||||
if (m_config.avoid_crossing_perimeters)
|
if (m_config.avoid_crossing_perimeters)
|
||||||
m_avoid_crossing_perimeters.init_layer_mp(union_ex(m_layer->slices, true));
|
m_avoid_crossing_perimeters.init_layer_mp(union_ex(m_layer->lslices, true));
|
||||||
|
|
||||||
if (this->config().gcode_label_objects)
|
if (this->config().gcode_label_objects)
|
||||||
gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
gcode += std::string("; printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||||
@ -2476,7 +2476,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
|||||||
// Create the distance field for a layer below.
|
// Create the distance field for a layer below.
|
||||||
const coord_t distance_field_resolution = coord_t(scale_(1.) + 0.5);
|
const coord_t distance_field_resolution = coord_t(scale_(1.) + 0.5);
|
||||||
*lower_layer_edge_grid = make_unique<EdgeGrid::Grid>();
|
*lower_layer_edge_grid = make_unique<EdgeGrid::Grid>();
|
||||||
(*lower_layer_edge_grid)->create(m_layer->lower_layer->slices, distance_field_resolution);
|
(*lower_layer_edge_grid)->create(m_layer->lower_layer->lslices, distance_field_resolution);
|
||||||
(*lower_layer_edge_grid)->calculate_sdf();
|
(*lower_layer_edge_grid)->calculate_sdf();
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
|
@ -47,8 +47,8 @@ void Layer::make_slices()
|
|||||||
slices = union_ex(slices_p);
|
slices = union_ex(slices_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->slices.clear();
|
this->lslices.clear();
|
||||||
this->slices.reserve(slices.size());
|
this->lslices.reserve(slices.size());
|
||||||
|
|
||||||
// prepare ordering points
|
// prepare ordering points
|
||||||
Points ordering_points;
|
Points ordering_points;
|
||||||
@ -61,19 +61,21 @@ void Layer::make_slices()
|
|||||||
|
|
||||||
// populate slices vector
|
// populate slices vector
|
||||||
for (size_t i : order)
|
for (size_t i : order)
|
||||||
this->slices.push_back(std::move(slices[i]));
|
this->lslices.emplace_back(std::move(slices[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
// Merge typed slices into untyped slices. This method is used to revert the effects of detect_surfaces_type() called for posPrepareInfill.
|
||||||
void Layer::merge_slices()
|
void Layer::merge_slices()
|
||||||
{
|
{
|
||||||
if (m_regions.size() == 1) {
|
if (m_regions.size() == 1 && (this->id() > 0 || this->object()->config().elefant_foot_compensation.value == 0)) {
|
||||||
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
|
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
|
||||||
// but use the non-split islands of a layer. For a single region print, these shall be equal.
|
// but use the non-split islands of a layer. For a single region print, these shall be equal.
|
||||||
m_regions.front()->slices.set(this->slices, stInternal);
|
// Don't use this optimization on 1st layer with Elephant foot compensation applied, as this->lslices are uncompensated,
|
||||||
|
// while regions are compensated.
|
||||||
|
m_regions.front()->slices.set(this->lslices, stInternal);
|
||||||
} else {
|
} else {
|
||||||
for (LayerRegion *layerm : m_regions)
|
for (LayerRegion *layerm : m_regions)
|
||||||
// without safety offset, artifacts are generated (GH #2494)
|
// without safety offset, artifacts are generated (upstream Slic3r GH #2494)
|
||||||
layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stInternal);
|
layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stInternal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,12 +106,16 @@ public:
|
|||||||
coordf_t print_z; // Z used for printing in unscaled coordinates
|
coordf_t print_z; // Z used for printing in unscaled coordinates
|
||||||
coordf_t height; // layer height in unscaled coordinates
|
coordf_t height; // layer height in unscaled coordinates
|
||||||
|
|
||||||
// collection of expolygons generated by slicing the original geometry;
|
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
|
||||||
// also known as 'islands' (all regions and surface types are merged here)
|
// (with possibly differing extruder ID and slicing parameters) and merged.
|
||||||
// The slices are chained by the shortest traverse distance and this traversal
|
// For the first layer, if the ELephant foot compensation is applied, this lslice is uncompensated, therefore
|
||||||
// order will be recovered by the G-code generator.
|
// it includes the Elephant foot effect, thus it corresponds to the shape of the printed 1st layer.
|
||||||
ExPolygons slices;
|
// These lslices aka islands are chained by the shortest traverse distance and this traversal
|
||||||
std::vector<BoundingBox> slices_bboxes;
|
// order will be applied by the G-code generator to the extrusions fitting into these lslices.
|
||||||
|
// These lslices are also used to detect overhangs and overlaps between successive layers, therefore it is important
|
||||||
|
// that the 1st lslice is not compensated by the Elephant foot compensation algorithm.
|
||||||
|
ExPolygons lslices;
|
||||||
|
std::vector<BoundingBox> lslices_bboxes;
|
||||||
|
|
||||||
size_t region_count() const { return m_regions.size(); }
|
size_t region_count() const { return m_regions.size(); }
|
||||||
const LayerRegion* get_region(int idx) const { return m_regions.at(idx); }
|
const LayerRegion* get_region(int idx) const { return m_regions.at(idx); }
|
||||||
|
@ -72,7 +72,7 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
|||||||
|
|
||||||
if (this->layer()->lower_layer != nullptr)
|
if (this->layer()->lower_layer != nullptr)
|
||||||
// Cummulative sum of polygons over all the regions.
|
// Cummulative sum of polygons over all the regions.
|
||||||
g.lower_slices = &this->layer()->lower_layer->slices;
|
g.lower_slices = &this->layer()->lower_layer->lslices;
|
||||||
|
|
||||||
g.layer_id = (int)this->layer()->id();
|
g.layer_id = (int)this->layer()->id();
|
||||||
g.ext_perimeter_flow = this->flow(frExternalPerimeter);
|
g.ext_perimeter_flow = this->flow(frExternalPerimeter);
|
||||||
@ -139,7 +139,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||||||
// Remove voids from fill_boundaries, that are not supported by the layer below.
|
// Remove voids from fill_boundaries, that are not supported by the layer below.
|
||||||
if (lower_layer_covered == nullptr) {
|
if (lower_layer_covered == nullptr) {
|
||||||
lower_layer_covered = &lower_layer_covered_tmp;
|
lower_layer_covered = &lower_layer_covered_tmp;
|
||||||
lower_layer_covered_tmp = to_polygons(lower_layer->slices);
|
lower_layer_covered_tmp = to_polygons(lower_layer->lslices);
|
||||||
}
|
}
|
||||||
if (! lower_layer_covered->empty())
|
if (! lower_layer_covered->empty())
|
||||||
voids = diff(voids, *lower_layer_covered);
|
voids = diff(voids, *lower_layer_covered);
|
||||||
@ -260,7 +260,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
|||||||
// of very thin (but still working) anchors, the grown expolygon would go beyond them
|
// of very thin (but still working) anchors, the grown expolygon would go beyond them
|
||||||
BridgeDetector bd(
|
BridgeDetector bd(
|
||||||
initial,
|
initial,
|
||||||
lower_layer->slices,
|
lower_layer->lslices,
|
||||||
this->flow(frInfill, true).scaled_width()
|
this->flow(frInfill, true).scaled_width()
|
||||||
);
|
);
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
|
@ -1658,7 +1658,7 @@ void Print::_make_skirt()
|
|||||||
for (const Layer *layer : object->m_layers) {
|
for (const Layer *layer : object->m_layers) {
|
||||||
if (layer->print_z > skirt_height_z)
|
if (layer->print_z > skirt_height_z)
|
||||||
break;
|
break;
|
||||||
for (const ExPolygon &expoly : layer->slices)
|
for (const ExPolygon &expoly : layer->lslices)
|
||||||
// Collect the outer contour points only, ignore holes for the calculation of the convex hull.
|
// Collect the outer contour points only, ignore holes for the calculation of the convex hull.
|
||||||
append(object_points, expoly.contour.points);
|
append(object_points, expoly.contour.points);
|
||||||
}
|
}
|
||||||
@ -1787,7 +1787,7 @@ void Print::_make_brim()
|
|||||||
Polygons islands;
|
Polygons islands;
|
||||||
for (PrintObject *object : m_objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
Polygons object_islands;
|
Polygons object_islands;
|
||||||
for (ExPolygon &expoly : object->m_layers.front()->slices)
|
for (ExPolygon &expoly : object->m_layers.front()->lslices)
|
||||||
object_islands.push_back(expoly.contour);
|
object_islands.push_back(expoly.contour);
|
||||||
if (! object->support_layers().empty())
|
if (! object->support_layers().empty())
|
||||||
object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
|
object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
|
||||||
|
@ -182,7 +182,7 @@ private:
|
|||||||
|
|
||||||
void _slice(const std::vector<coordf_t> &layer_height_profile);
|
void _slice(const std::vector<coordf_t> &layer_height_profile);
|
||||||
std::string _fix_slicing_errors();
|
std::string _fix_slicing_errors();
|
||||||
void _simplify_slices(double distance);
|
void simplify_slices(double distance);
|
||||||
bool has_support_material() const;
|
bool has_support_material() const;
|
||||||
void detect_surfaces_type();
|
void detect_surfaces_type();
|
||||||
void process_external_surfaces();
|
void process_external_surfaces();
|
||||||
|
@ -117,7 +117,7 @@ void PrintObject::slice()
|
|||||||
BOOST_LOG_TRIVIAL(info) << warning;
|
BOOST_LOG_TRIVIAL(info) << warning;
|
||||||
// Simplify slices if required.
|
// Simplify slices if required.
|
||||||
if (m_print->config().resolution)
|
if (m_print->config().resolution)
|
||||||
this->_simplify_slices(scale_(this->print()->config().resolution));
|
this->simplify_slices(scale_(this->print()->config().resolution));
|
||||||
// Update bounding boxes
|
// Update bounding boxes
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||||
@ -125,10 +125,10 @@ void PrintObject::slice()
|
|||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
Layer &layer = *m_layers[layer_idx];
|
Layer &layer = *m_layers[layer_idx];
|
||||||
layer.slices_bboxes.clear();
|
layer.lslices_bboxes.clear();
|
||||||
layer.slices_bboxes.reserve(layer.slices.size());
|
layer.lslices_bboxes.reserve(layer.lslices.size());
|
||||||
for (const ExPolygon &expoly : layer.slices)
|
for (const ExPolygon &expoly : layer.lslices)
|
||||||
layer.slices_bboxes.emplace_back(get_extents(expoly));
|
layer.lslices_bboxes.emplace_back(get_extents(expoly));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (m_layers.empty())
|
if (m_layers.empty())
|
||||||
@ -242,13 +242,6 @@ void PrintObject::make_perimeters()
|
|||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - end";
|
||||||
|
|
||||||
/*
|
|
||||||
simplify slices (both layer and region slices),
|
|
||||||
we only need the max resolution for perimeters
|
|
||||||
### This makes this method not-idempotent, so we keep it disabled for now.
|
|
||||||
###$self->_simplify_slices(&Slic3r::SCALED_RESOLUTION);
|
|
||||||
*/
|
|
||||||
|
|
||||||
this->set_done(posPerimeters);
|
this->set_done(posPerimeters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,7 +685,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
if (upper_layer) {
|
if (upper_layer) {
|
||||||
Polygons upper_slices = interface_shells ?
|
Polygons upper_slices = interface_shells ?
|
||||||
to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) :
|
to_polygons(upper_layer->get_region(idx_region)->slices.surfaces) :
|
||||||
to_polygons(upper_layer->slices);
|
to_polygons(upper_layer->lslices);
|
||||||
surfaces_append(top,
|
surfaces_append(top,
|
||||||
//FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
|
//FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
|
||||||
offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset),
|
offset_ex(offset_ex(diff_ex(layerm_slices_surfaces, upper_slices, true), -offset), offset),
|
||||||
@ -721,7 +714,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
surfaces_append(
|
surfaces_append(
|
||||||
bottom,
|
bottom,
|
||||||
offset2_ex(
|
offset2_ex(
|
||||||
diff(layerm_slices_surfaces, to_polygons(lower_layer->slices), true),
|
diff(layerm_slices_surfaces, to_polygons(lower_layer->lslices), true),
|
||||||
-offset, offset),
|
-offset, offset),
|
||||||
surface_type_bottom_other);
|
surface_type_bottom_other);
|
||||||
// if user requested internal shells, we need to identify surfaces
|
// if user requested internal shells, we need to identify surfaces
|
||||||
@ -733,7 +726,7 @@ void PrintObject::detect_surfaces_type()
|
|||||||
bottom,
|
bottom,
|
||||||
offset2_ex(
|
offset2_ex(
|
||||||
diff(
|
diff(
|
||||||
intersection(layerm_slices_surfaces, to_polygons(lower_layer->slices)), // supported
|
intersection(layerm_slices_surfaces, to_polygons(lower_layer->lslices)), // supported
|
||||||
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),
|
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),
|
||||||
true),
|
true),
|
||||||
-offset, offset),
|
-offset, offset),
|
||||||
@ -879,7 +872,7 @@ void PrintObject::process_external_surfaces()
|
|||||||
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
|
// Shrink the holes, let the layer above expand slightly inside the unsupported areas.
|
||||||
polygons_append(voids, offset(surface.expolygon, unsupported_width));
|
polygons_append(voids, offset(surface.expolygon, unsupported_width));
|
||||||
}
|
}
|
||||||
surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->slices), voids);
|
surfaces_covered[layer_idx] = diff(to_polygons(this->m_layers[layer_idx]->lslices), voids);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -985,8 +978,8 @@ void PrintObject::discover_vertical_shells()
|
|||||||
cache.bottom_surfaces = union_(cache.bottom_surfaces, false);
|
cache.bottom_surfaces = union_(cache.bottom_surfaces, false);
|
||||||
// For a multi-material print, simulate perimeter / infill split as if only a single extruder has been used for the whole print.
|
// For a multi-material print, simulate perimeter / infill split as if only a single extruder has been used for the whole print.
|
||||||
if (perimeter_offset > 0.) {
|
if (perimeter_offset > 0.) {
|
||||||
// The layer.slices are forced to merge by expanding them first.
|
// The layer.lslices are forced to merge by expanding them first.
|
||||||
polygons_append(cache.holes, offset(offset_ex(layer.slices, 0.3f * perimeter_min_spacing), - perimeter_offset - 0.3f * perimeter_min_spacing));
|
polygons_append(cache.holes, offset(offset_ex(layer.lslices, 0.3f * perimeter_min_spacing), - perimeter_offset - 0.3f * perimeter_min_spacing));
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
{
|
{
|
||||||
Slic3r::SVG svg(debug_out_path("discover_vertical_shells-extra-holes-%d.svg", debug_idx), get_extents(layer.slices));
|
Slic3r::SVG svg(debug_out_path("discover_vertical_shells-extra-holes-%d.svg", debug_idx), get_extents(layer.slices));
|
||||||
@ -1762,78 +1755,101 @@ end:
|
|||||||
;
|
;
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - begin";
|
||||||
tbb::parallel_for(
|
{
|
||||||
tbb::blocked_range<size_t>(0, m_layers.size()),
|
// Compensation value, scaled.
|
||||||
[this, upscaled, clipped](const tbb::blocked_range<size_t>& range) {
|
const float xy_compensation_scaled = float(scale_(m_config.xy_size_compensation.value));
|
||||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
const float elephant_foot_compensation_scaled = (m_config.raft_layers == 0) ?
|
||||||
m_print->throw_if_canceled();
|
// Only enable Elephant foot compensation if printing directly on the print bed.
|
||||||
Layer *layer = m_layers[layer_id];
|
float(scale_(m_config.elefant_foot_compensation.value)) :
|
||||||
// Apply size compensation and perform clipping of multi-part objects.
|
0.f;
|
||||||
float delta = float(scale_(m_config.xy_size_compensation.value));
|
// Uncompensated slices for the first layer in case the Elephant foot compensation is applied.
|
||||||
//FIXME only apply the compensation if no raft is enabled.
|
ExPolygons lslices_1st_layer;
|
||||||
float elephant_foot_compensation = 0.f;
|
tbb::parallel_for(
|
||||||
if (layer_id == 0 && m_config.raft_layers == 0)
|
tbb::blocked_range<size_t>(0, m_layers.size()),
|
||||||
// Only enable Elephant foot compensation if printing directly on the print bed.
|
[this, upscaled, clipped, xy_compensation_scaled, elephant_foot_compensation_scaled, &lslices_1st_layer]
|
||||||
elephant_foot_compensation = float(scale_(m_config.elefant_foot_compensation.value));
|
(const tbb::blocked_range<size_t>& range) {
|
||||||
if (layer->m_regions.size() == 1) {
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id) {
|
||||||
// Optimized version for a single region layer.
|
m_print->throw_if_canceled();
|
||||||
if (layer_id == 0) {
|
Layer *layer = m_layers[layer_id];
|
||||||
if (delta > elephant_foot_compensation) {
|
// Apply size compensation and perform clipping of multi-part objects.
|
||||||
delta -= elephant_foot_compensation;
|
float elfoot = (layer_id == 0) ? elephant_foot_compensation_scaled : 0.f;
|
||||||
elephant_foot_compensation = 0.f;
|
if (layer->m_regions.size() == 1) {
|
||||||
} else if (delta > 0)
|
assert(! upscaled);
|
||||||
elephant_foot_compensation -= delta;
|
assert(! clipped);
|
||||||
}
|
// Optimized version for a single region layer.
|
||||||
if (delta != 0.f || elephant_foot_compensation > 0.f) {
|
// Single region, growing or shrinking.
|
||||||
// Single region, growing or shrinking.
|
LayerRegion *layerm = layer->m_regions.front();
|
||||||
LayerRegion *layerm = layer->m_regions.front();
|
if (elfoot > 0) {
|
||||||
// Apply the XY compensation.
|
// Apply the elephant foot compensation and store the 1st layer slices without the Elephant foot compensation applied.
|
||||||
ExPolygons expolygons = (delta == 0.f) ?
|
lslices_1st_layer = to_expolygons(std::move(layerm->slices.surfaces));
|
||||||
to_expolygons(std::move(layerm->slices.surfaces)) :
|
float delta = xy_compensation_scaled;
|
||||||
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
|
if (delta > elfoot) {
|
||||||
// Apply the elephant foot compensation.
|
delta -= elfoot;
|
||||||
if (elephant_foot_compensation > 0)
|
elfoot = 0.f;
|
||||||
expolygons = union_ex(Slic3r::elephant_foot_compensation(expolygons, layerm->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation)));
|
} else if (delta > 0)
|
||||||
layerm->slices.set(std::move(expolygons), stInternal);
|
elfoot -= delta;
|
||||||
}
|
layerm->slices.set(
|
||||||
} else {
|
union_ex(
|
||||||
bool upscale = ! upscaled && delta > 0.f;
|
Slic3r::elephant_foot_compensation(
|
||||||
bool clip = ! clipped && m_config.clip_multipart_objects.value;
|
(delta == 0.f) ? lslices_1st_layer : offset_ex(lslices_1st_layer, delta),
|
||||||
if (upscale || clip) {
|
layerm->flow(frExternalPerimeter), unscale<double>(elfoot))),
|
||||||
// Multiple regions, growing or just clipping one region by the other.
|
stInternal);
|
||||||
// When clipping the regions, priority is given to the first regions.
|
if (xy_compensation_scaled != 0.f)
|
||||||
Polygons processed;
|
lslices_1st_layer = offset_ex(std::move(lslices_1st_layer), xy_compensation_scaled);
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
} else if (xy_compensation_scaled != 0.f) {
|
||||||
LayerRegion *layerm = layer->m_regions[region_id];
|
// Apply the XY compensation.
|
||||||
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
layerm->slices.set(
|
||||||
if (upscale)
|
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), xy_compensation_scaled),
|
||||||
slices = offset_ex(std::move(slices), delta);
|
stInternal);
|
||||||
if (region_id > 0 && clip)
|
}
|
||||||
// Trim by the slices of already processed regions.
|
} else {
|
||||||
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
bool upscale = ! upscaled && xy_compensation_scaled > 0.f;
|
||||||
if (clip && (region_id + 1 < layer->m_regions.size()))
|
bool clip = ! clipped && m_config.clip_multipart_objects.value;
|
||||||
// Collect the already processed regions to trim the to be processed regions.
|
if (upscale || clip) {
|
||||||
polygons_append(processed, slices);
|
// Multiple regions, growing or just clipping one region by the other.
|
||||||
layerm->slices.set(std::move(slices), stInternal);
|
// When clipping the regions, priority is given to the first regions.
|
||||||
}
|
Polygons processed;
|
||||||
}
|
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
|
||||||
if (delta < 0.f || elephant_foot_compensation > 0.f) {
|
LayerRegion *layerm = layer->m_regions[region_id];
|
||||||
// Apply the negative XY compensation.
|
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
|
||||||
Polygons trimming;
|
if (upscale)
|
||||||
static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
|
slices = offset_ex(std::move(slices), xy_compensation_scaled);
|
||||||
if (elephant_foot_compensation > 0.f) {
|
if (region_id > 0 && clip)
|
||||||
trimming = to_polygons(Slic3r::elephant_foot_compensation(offset_ex(layer->merged(eps), std::min(delta, 0.f) - eps),
|
// Trim by the slices of already processed regions.
|
||||||
layer->m_regions.front()->flow(frExternalPerimeter), unscale<double>(elephant_foot_compensation)));
|
slices = diff_ex(to_polygons(std::move(slices)), processed);
|
||||||
} else
|
if (clip && (region_id + 1 < layer->m_regions.size()))
|
||||||
trimming = offset(layer->merged(float(SCALED_EPSILON)), delta - float(SCALED_EPSILON));
|
// Collect the already processed regions to trim the to be processed regions.
|
||||||
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
polygons_append(processed, slices);
|
||||||
layer->m_regions[region_id]->trim_surfaces(trimming);
|
layerm->slices.set(std::move(slices), stInternal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Merge all regions' slices to get islands, chain them by a shortest path.
|
if (xy_compensation_scaled < 0.f || elfoot > 0.f) {
|
||||||
layer->make_slices();
|
// Apply the negative XY compensation.
|
||||||
}
|
Polygons trimming;
|
||||||
});
|
static const float eps = float(scale_(m_config.slice_closing_radius.value) * 1.5);
|
||||||
|
if (elfoot > 0.f) {
|
||||||
|
lslices_1st_layer = offset_ex(layer->merged(eps), std::min(xy_compensation_scaled, 0.f) - eps);
|
||||||
|
trimming = to_polygons(Slic3r::elephant_foot_compensation(lslices_1st_layer,
|
||||||
|
layer->m_regions.front()->flow(frExternalPerimeter), unscale<double>(elfoot)));
|
||||||
|
} else
|
||||||
|
trimming = offset(layer->merged(float(SCALED_EPSILON)), xy_compensation_scaled - float(SCALED_EPSILON));
|
||||||
|
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id)
|
||||||
|
layer->m_regions[region_id]->trim_surfaces(trimming);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Merge all regions' slices to get islands, chain them by a shortest path.
|
||||||
|
layer->make_slices();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (elephant_foot_compensation_scaled > 0.f) {
|
||||||
|
// The Elephant foot has been compensated, therefore the 1st layer's lslices are shrank with the Elephant foot compensation value.
|
||||||
|
// Store the uncompensated value there.
|
||||||
|
assert(! m_layers.empty());
|
||||||
|
assert(m_layers.front()->id() == 0);
|
||||||
|
m_layers.front()->lslices = std::move(lslices_1st_layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_print->throw_if_canceled();
|
m_print->throw_if_canceled();
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - make_slices in parallel - end";
|
||||||
}
|
}
|
||||||
@ -2131,7 +2147,7 @@ std::string PrintObject::_fix_slicing_errors()
|
|||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - end";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - fixing slicing errors in parallel - end";
|
||||||
|
|
||||||
// remove empty layers from bottom
|
// remove empty layers from bottom
|
||||||
while (! m_layers.empty() && m_layers.front()->slices.empty()) {
|
while (! m_layers.empty() && (m_layers.front()->lslices.empty() || m_layers.front()->empty())) {
|
||||||
delete m_layers.front();
|
delete m_layers.front();
|
||||||
m_layers.erase(m_layers.begin());
|
m_layers.erase(m_layers.begin());
|
||||||
m_layers.front()->lower_layer = nullptr;
|
m_layers.front()->lower_layer = nullptr;
|
||||||
@ -2147,7 +2163,7 @@ std::string PrintObject::_fix_slicing_errors()
|
|||||||
// Simplify the sliced model, if "resolution" configuration parameter > 0.
|
// Simplify the sliced model, if "resolution" configuration parameter > 0.
|
||||||
// The simplification is problematic, because it simplifies the slices independent from each other,
|
// The simplification is problematic, because it simplifies the slices independent from each other,
|
||||||
// which makes the simplified discretization visible on the object surface.
|
// which makes the simplified discretization visible on the object surface.
|
||||||
void PrintObject::_simplify_slices(double distance)
|
void PrintObject::simplify_slices(double distance)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - begin";
|
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - begin";
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
@ -2160,9 +2176,9 @@ void PrintObject::_simplify_slices(double distance)
|
|||||||
layer->m_regions[region_idx]->slices.simplify(distance);
|
layer->m_regions[region_idx]->slices.simplify(distance);
|
||||||
{
|
{
|
||||||
ExPolygons simplified;
|
ExPolygons simplified;
|
||||||
for (const ExPolygon& expoly : layer->slices)
|
for (const ExPolygon &expoly : layer->lslices)
|
||||||
expoly.simplify(distance, &simplified);
|
expoly.simplify(distance, &simplified);
|
||||||
layer->slices = std::move(simplified);
|
layer->lslices = std::move(simplified);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -2194,7 +2210,7 @@ void PrintObject::clip_fill_surfaces()
|
|||||||
// Detect things that we need to support.
|
// Detect things that we need to support.
|
||||||
// Cummulative slices.
|
// Cummulative slices.
|
||||||
Polygons slices;
|
Polygons slices;
|
||||||
polygons_append(slices, layer->slices);
|
polygons_append(slices, layer->lslices);
|
||||||
// Cummulative fill surfaces.
|
// Cummulative fill surfaces.
|
||||||
Polygons fill_surfaces;
|
Polygons fill_surfaces;
|
||||||
// Solid surfaces to be supported.
|
// Solid surfaces to be supported.
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "ClipperUtils.hpp"
|
#include "ClipperUtils.hpp"
|
||||||
#include "ExtrusionEntityCollection.hpp"
|
#include "ExtrusionEntityCollection.hpp"
|
||||||
#include "PerimeterGenerator.hpp"
|
|
||||||
#include "Layer.hpp"
|
#include "Layer.hpp"
|
||||||
#include "Print.hpp"
|
#include "Print.hpp"
|
||||||
#include "SupportMaterial.hpp"
|
#include "SupportMaterial.hpp"
|
||||||
@ -445,8 +444,8 @@ Polygons collect_region_slices_by_type(const Layer &layer, SurfaceType surface_t
|
|||||||
Polygons collect_slices_outer(const Layer &layer)
|
Polygons collect_slices_outer(const Layer &layer)
|
||||||
{
|
{
|
||||||
Polygons out;
|
Polygons out;
|
||||||
out.reserve(out.size() + layer.slices.size());
|
out.reserve(out.size() + layer.lslices.size());
|
||||||
for (const ExPolygon &expoly : layer.slices)
|
for (const ExPolygon &expoly : layer.lslices)
|
||||||
out.emplace_back(expoly.contour);
|
out.emplace_back(expoly.contour);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -907,9 +906,9 @@ namespace SupportMaterialInternal {
|
|||||||
polyline.extend_start(fw);
|
polyline.extend_start(fw);
|
||||||
polyline.extend_end(fw);
|
polyline.extend_end(fw);
|
||||||
// Is the straight perimeter segment supported at both sides?
|
// Is the straight perimeter segment supported at both sides?
|
||||||
for (size_t i = 0; i < lower_layer.slices.size(); ++ i)
|
for (size_t i = 0; i < lower_layer.lslices.size(); ++ i)
|
||||||
if (lower_layer.slices_bboxes[i].contains(polyline.first_point()) && lower_layer.slices_bboxes[i].contains(polyline.last_point()) &&
|
if (lower_layer.lslices_bboxes[i].contains(polyline.first_point()) && lower_layer.lslices_bboxes[i].contains(polyline.last_point()) &&
|
||||||
lower_layer.slices[i].contains(polyline.first_point()) && lower_layer.slices[i].contains(polyline.last_point())) {
|
lower_layer.lslices[i].contains(polyline.first_point()) && lower_layer.lslices[i].contains(polyline.last_point())) {
|
||||||
// Offset a polyline into a thick line.
|
// Offset a polyline into a thick line.
|
||||||
polygons_append(bridges, offset(polyline, 0.5f * w + 10.f));
|
polygons_append(bridges, offset(polyline, 0.5f * w + 10.f));
|
||||||
break;
|
break;
|
||||||
@ -998,7 +997,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
// inflate the polygons over and over.
|
// inflate the polygons over and over.
|
||||||
Polygons &covered = buildplate_covered[layer_id];
|
Polygons &covered = buildplate_covered[layer_id];
|
||||||
covered = buildplate_covered[layer_id - 1];
|
covered = buildplate_covered[layer_id - 1];
|
||||||
polygons_append(covered, offset(lower_layer.slices, scale_(0.01)));
|
polygons_append(covered, offset(lower_layer.lslices, scale_(0.01)));
|
||||||
covered = union_(covered, false); // don't apply the safety offset.
|
covered = union_(covered, false); // don't apply the safety offset.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1027,7 +1026,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
Polygons contact_polygons;
|
Polygons contact_polygons;
|
||||||
Polygons slices_margin_cached;
|
Polygons slices_margin_cached;
|
||||||
float slices_margin_cached_offset = -1.;
|
float slices_margin_cached_offset = -1.;
|
||||||
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->slices);
|
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->lslices);
|
||||||
// Offset of the lower layer, to trim the support polygons with to calculate dense supports.
|
// Offset of the lower layer, to trim the support polygons with to calculate dense supports.
|
||||||
float no_interface_offset = 0.f;
|
float no_interface_offset = 0.f;
|
||||||
if (layer_id == 0) {
|
if (layer_id == 0) {
|
||||||
@ -1166,7 +1165,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||||||
slices_margin_cached_offset = slices_margin_offset;
|
slices_margin_cached_offset = slices_margin_offset;
|
||||||
slices_margin_cached = (slices_margin_offset == 0.f) ?
|
slices_margin_cached = (slices_margin_offset == 0.f) ?
|
||||||
lower_layer_polygons :
|
lower_layer_polygons :
|
||||||
offset2(to_polygons(lower_layer.slices), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
offset2(to_polygons(lower_layer.lslices), - no_interface_offset * 0.5f, slices_margin_offset + no_interface_offset * 0.5f, SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
if (! buildplate_covered.empty()) {
|
if (! buildplate_covered.empty()) {
|
||||||
// Trim the inflated contact surfaces by the top surfaces as well.
|
// Trim the inflated contact surfaces by the top surfaces as well.
|
||||||
polygons_append(slices_margin_cached, buildplate_covered[layer_id]);
|
polygons_append(slices_margin_cached, buildplate_covered[layer_id]);
|
||||||
@ -1573,7 +1572,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||||||
task_group.run([this, &projection, &projection_raw, &layer, &layer_support_area, layer_id] {
|
task_group.run([this, &projection, &projection_raw, &layer, &layer_support_area, layer_id] {
|
||||||
// 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.
|
||||||
// Polygons trimming = union_(to_polygons(layer.slices), touching, true);
|
// Polygons trimming = union_(to_polygons(layer.slices), touching, true);
|
||||||
Polygons trimming = offset(layer.slices, float(SCALED_EPSILON));
|
Polygons trimming = offset(layer.lslices, float(SCALED_EPSILON));
|
||||||
projection = diff(projection_raw, trimming, false);
|
projection = diff(projection_raw, trimming, false);
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
{
|
{
|
||||||
@ -2105,7 +2104,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
|||||||
const Layer &object_layer = *object.layers()[i];
|
const Layer &object_layer = *object.layers()[i];
|
||||||
if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON)
|
if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON)
|
||||||
break;
|
break;
|
||||||
polygons_append(polygons_trimming, offset(object_layer.slices, gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
polygons_append(polygons_trimming, offset(object_layer.lslices, gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
}
|
}
|
||||||
if (! m_slicing_params.soluble_interface) {
|
if (! m_slicing_params.soluble_interface) {
|
||||||
// Collect all bottom surfaces, which will be extruded with a bridging flow.
|
// Collect all bottom surfaces, which will be extruded with a bridging flow.
|
||||||
@ -2218,7 +2217,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
|
|||||||
// Expand the bases of the support columns in the 1st layer.
|
// Expand the bases of the support columns in the 1st layer.
|
||||||
columns_base->polygons = diff(
|
columns_base->polygons = diff(
|
||||||
offset(columns_base->polygons, inflate_factor_1st_layer),
|
offset(columns_base->polygons, inflate_factor_1st_layer),
|
||||||
offset(m_object->layers().front()->slices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
offset(m_object->layers().front()->lslices, (float)scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
if (contacts != nullptr)
|
if (contacts != nullptr)
|
||||||
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user