clean a bit some methods with newer c++
add more const to surfacecollection & create surfaceconstptr & a slice() method in layerregion that return const surfacecollection.
This commit is contained in:
supermerill 2019-10-14 16:08:07 +02:00
parent 6cc8f63f84
commit 81dc1e19d3
10 changed files with 132 additions and 216 deletions

View File

@ -21,7 +21,7 @@ Layer::~Layer()
bool Layer::empty() const
{
for (const LayerRegion *layerm : m_regions)
if (layerm != nullptr && ! layerm->slices.empty())
if (layerm != nullptr && ! layerm->slices().empty())
// Non empty layer.
return false;
return true;
@ -39,11 +39,11 @@ void Layer::make_slices()
ExPolygons slices;
if (m_regions.size() == 1) {
// optimization: if we only have one region, take its slices
slices = m_regions.front()->slices;
slices = m_regions.front()->slices();
} else {
Polygons slices_p;
for (LayerRegion *layerm : m_regions)
polygons_append(slices_p, to_polygons(layerm->slices));
polygons_append(slices_p, to_polygons(layerm->slices()));
slices = union_ex(slices_p);
}
@ -71,11 +71,11 @@ void Layer::merge_slices()
if (m_regions.size() == 1) {
// 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.
m_regions.front()->slices.set(this->slices.expolygons, stPosInternal | stDensSparse);
m_regions.front()->m_slices.set(this->slices.expolygons, stPosInternal | stDensSparse);
} else {
for (LayerRegion *layerm : m_regions)
// without safety offset, artifacts are generated (GH #2494)
layerm->slices.set(union_ex(to_polygons(std::move(layerm->slices.surfaces)), true), stPosInternal | stDensSparse);
layerm->m_slices.set(union_ex(to_polygons(std::move(layerm->m_slices.surfaces)), true), stPosInternal | stDensSparse);
}
}
@ -90,7 +90,7 @@ ExPolygons Layer::merged(float offset_scaled) const
}
Polygons polygons;
for (LayerRegion *layerm : m_regions)
append(polygons, offset(to_expolygons(layerm->slices.surfaces), offset_scaled));
append(polygons, offset(to_expolygons(layerm->slices().surfaces), offset_scaled));
ExPolygons out = union_ex(polygons);
if (offset_scaled2 != 0.f)
out = offset_ex(out, offset_scaled2);
@ -145,7 +145,7 @@ void Layer::make_perimeters()
if (layerms.size() == 1) { // optimization
(*layerm)->fill_surfaces.surfaces.clear();
(*layerm)->make_perimeters((*layerm)->slices, &(*layerm)->fill_surfaces);
(*layerm)->make_perimeters((*layerm)->slices(), &(*layerm)->fill_surfaces);
(*layerm)->fill_expolygons = to_expolygons((*layerm)->fill_surfaces.surfaces);
} else {
SurfaceCollection new_slices;
@ -155,7 +155,7 @@ void Layer::make_perimeters()
// group slices (surfaces) according to number of extra perimeters
std::map<unsigned short, Surfaces> slices; // extra_perimeters => [ surface, surface... ]
for (LayerRegion *layerm : layerms) {
for (Surface &surface : layerm->slices.surfaces)
for (const Surface &surface : layerm->slices().surfaces)
slices[surface.extra_perimeters].emplace_back(surface);
if (layerm->region()->config().fill_density > layerm_config->region()->config().fill_density)
layerm_config = layerm;
@ -173,7 +173,7 @@ void Layer::make_perimeters()
if (!fill_surfaces.surfaces.empty()) {
for (LayerRegionPtrs::iterator l = layerms.begin(); l != layerms.end(); ++l) {
// Separate the fill surfaces.
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices);
ExPolygons expp = intersection_ex(to_polygons(fill_surfaces), (*l)->slices());
(*l)->fill_expolygons = expp;
(*l)->fill_no_overlap_expolygons = (*layerm)->fill_no_overlap_expolygons;
(*l)->fill_surfaces.set(std::move(expp), fill_surfaces.surfaces.front());
@ -202,8 +202,8 @@ void Layer::make_fills()
void Layer::export_region_slices_to_svg(const char *path) const
{
BoundingBox bbox;
for (const auto *region : m_regions)
for (const auto &surface : region->slices.surfaces)
for (const LayerRegion *region : m_regions)
for (const Surface &surface : region->slices().surfaces)
bbox.merge(get_extents(surface.expolygon));
Point legend_size = export_surface_type_legend_to_svg_box_size();
Point legend_pos(bbox.min(0), bbox.max(1));
@ -211,8 +211,8 @@ void Layer::export_region_slices_to_svg(const char *path) const
SVG svg(path, bbox);
const float transparency = 0.5f;
for (const auto *region : m_regions)
for (const auto &surface : region->slices.surfaces)
for (const LayerRegion *region : m_regions)
for (const Surface &surface : region->slices().surfaces)
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
export_surface_type_legend_to_svg(svg, legend_pos);
svg.Close();
@ -228,8 +228,8 @@ void Layer::export_region_slices_to_svg_debug(const char *name) const
void Layer::export_region_fill_surfaces_to_svg(const char *path) const
{
BoundingBox bbox;
for (const auto *region : m_regions)
for (const auto &surface : region->slices.surfaces)
for (const LayerRegion *region : m_regions)
for (const Surface &surface : region->slices().surfaces)
bbox.merge(get_extents(surface.expolygon));
Point legend_size = export_surface_type_legend_to_svg_box_size();
Point legend_pos(bbox.min(0), bbox.max(1));
@ -237,8 +237,8 @@ void Layer::export_region_fill_surfaces_to_svg(const char *path) const
SVG svg(path, bbox);
const float transparency = 0.5f;
for (const auto *region : m_regions)
for (const auto &surface : region->slices.surfaces)
for (const LayerRegion *region : m_regions)
for (const Surface &surface : region->slices().surfaces)
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
export_surface_type_legend_to_svg(svg, legend_pos);
svg.Close();

View File

@ -25,7 +25,8 @@ public:
// collection of surfaces generated by slicing the original geometry
// divided by type top/bottom/internal
SurfaceCollection slices;
SurfaceCollection m_slices;
const SurfaceCollection& slices() const { return m_slices; }
// collection of extrusion paths/loops filling gaps
// These fills are generated by the perimeter generator.
@ -63,7 +64,7 @@ public:
Flow flow(FlowRole role, bool bridge = false, double width = -1) const;
void slices_to_fill_surfaces_clipped();
void prepare_fill_surfaces();
void make_perimeters(SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
void make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces);
void process_external_surfaces(const Layer *lower_layer, const Polygons *lower_layer_covered);
double infill_area_threshold() const;
// Trim surfaces by trimming polygons. Used by the elephant foot compensation at the 1st layer.
@ -129,7 +130,7 @@ public:
// Slices merged into islands, to be used by the elephant foot compensation to trim the individual surfaces with the shrunk merged slices.
ExPolygons merged(float offset) const;
template <class T> bool any_internal_region_slice_contains(const T &item) const {
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_internal_contains(item)) return true;
for (const LayerRegion *layerm : m_regions) if (layerm->slices().any_internal_contains(item)) return true;
return false;
}
template <class T> bool any_bottom_region_slice_contains(const T &item) const {

View File

@ -39,7 +39,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
Polygons fill_boundaries = to_polygons(this->fill_expolygons);
// Collect polygons per surface type.
std::map<SurfaceType, Polygons> polygons_by_surface;
for (Surface &surface : this->slices.surfaces) {
for (const Surface &surface : this->slices().surfaces) {
polygons_append(polygons_by_surface[surface.surface_type], surface.expolygon);
}
// Trim surfaces by the fill_boundaries.
@ -53,7 +53,7 @@ void LayerRegion::slices_to_fill_surfaces_clipped()
}
}
void LayerRegion::make_perimeters(SurfaceCollection &slices, SurfaceCollection* fill_surfaces)
void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollection* fill_surfaces)
{
this->perimeters.clear();
this->thin_fills.clear();
@ -438,7 +438,7 @@ void LayerRegion::trim_surfaces(const Polygons &trimming_polygons)
for (const Surface &surface : this->slices.surfaces)
assert(surface.surface_type == (stPosInternal | stDensSparse));
#endif /* NDEBUG */
this->slices.set(intersection_ex(to_polygons(std::move(this->slices.surfaces)), trimming_polygons, false), stPosInternal | stDensSparse);
this->m_slices.set(intersection_ex(to_polygons(std::move(this->slices().surfaces)), trimming_polygons, false), stPosInternal | stDensSparse);
}
void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_compensation_perimeter_step, const Polygons &trimming_polygons)
@ -447,25 +447,25 @@ void LayerRegion::elephant_foot_compensation_step(const float elephant_foot_comp
for (const Surface &surface : this->slices.surfaces)
assert(surface.surface_type == (stPosInternal | stDensSparse));
#endif /* NDEBUG */
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices.surfaces));
ExPolygons slices_expolygons = to_expolygons(std::move(this->slices().surfaces));
Polygons slices_polygons = to_polygons(slices_expolygons);
Polygons tmp = intersection(slices_polygons, trimming_polygons, false);
append(tmp, diff(slices_polygons, offset(offset_ex(slices_expolygons, -elephant_foot_compensation_perimeter_step), elephant_foot_compensation_perimeter_step)));
this->slices.set(std::move(union_ex(tmp)), stPosInternal | stDensSparse);
this->m_slices.set(std::move(union_ex(tmp)), stPosInternal | stDensSparse);
}
void LayerRegion::export_region_slices_to_svg(const char *path) const
{
BoundingBox bbox;
for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface)
bbox.merge(get_extents(surface->expolygon));
for (const Surface& surface : this->slices().surfaces)
bbox.merge(get_extents(surface.expolygon));
Point legend_size = export_surface_type_legend_to_svg_box_size();
Point legend_pos(bbox.min(0), bbox.max(1));
bbox.merge(Point(std::max(bbox.min(0) + legend_size(0), bbox.max(0)), bbox.max(1) + legend_size(1)));
SVG svg(path, bbox);
const float transparency = 0.5f;
for (Surfaces::const_iterator surface = this->slices.surfaces.begin(); surface != this->slices.surfaces.end(); ++surface)
for (Surfaces::const_iterator surface = this->slices().surfaces.begin(); surface != this->slices().surfaces.end(); ++surface)
svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency);
for (Surfaces::const_iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
svg.draw(surface->expolygon.lines(), surface_type_to_color_name(surface->surface_type));

View File

@ -353,7 +353,7 @@ void Print::_simplify_slices(double distance)
for (Layer *layer : object->m_layers) {
layer->slices.simplify(distance);
for (LayerRegion *layerm : layer->regions())
layerm->slices.simplify(distance);
layerm->m_slices.simplify(distance);
}
}
}

View File

@ -185,7 +185,6 @@ private:
void _smooth_curves(LayerRegion *layerm);
std::string _fix_slicing_errors();
void _simplify_slices(double distance);
void _make_perimeters();
bool has_support_material() const;
void detect_surfaces_type();
void process_external_surfaces();

View File

@ -170,7 +170,7 @@ void PrintObject::make_perimeters()
m_print->throw_if_canceled();
LayerRegion &layerm = *m_layers[layer_idx]->m_regions[region_id];
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->m_regions[region_id];
const Polygons upper_layerm_polygons = upper_layerm.slices;
const Polygons upper_layerm_polygons = upper_layerm.slices();
// Filter upper layer polygons in intersection_ppl by their bounding boxes?
// my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
const double total_loop_length = total_length(upper_layerm_polygons);
@ -179,7 +179,7 @@ void PrintObject::make_perimeters()
const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width();
const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing();
for (Surface &slice : layerm.slices.surfaces) {
for (Surface &slice : layerm.m_slices.surfaces) {
for (;;) {
// compute the total thickness of perimeters
const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2
@ -924,20 +924,21 @@ void PrintObject::detect_surfaces_type()
// unless internal shells are requested
Layer *upper_layer = (idx_layer + 1 < this->layer_count()) ? m_layers[idx_layer + 1] : nullptr;
Layer *lower_layer = (idx_layer > 0) ? m_layers[idx_layer - 1] : nullptr;
Layer *under_lower_layer = (idx_layer > 1) ? this->layers()[idx_layer - 2] : nullptr;
// collapse very narrow parts (using the safety offset in the diff is not enough)
float offset = layerm->flow(frExternalPerimeter).scaled_width() / 10.f;
Polygons layerm_slices_surfaces = to_polygons(layerm->slices().surfaces);
// no_perimeter_full_bridge allow to put bridges where there are nothing, hence adding area to silce, that's why we need to start from the result of PerimeterGenerator.
// i don't see the need tostart from layerm->slices.surfaces, but i'll keep that "in case of".
Polygons layerm_slices_surfaces = layerm->region()->config().no_perimeter_unsupported_algo == npuaFilled ? to_polygons(layerm->fill_surfaces) : to_polygons(layerm->slices.surfaces);
if (layerm->region()->config().no_perimeter_unsupported_algo == npuaFilled) {
layerm_slices_surfaces = union_(layerm_slices_surfaces, to_polygons(layerm->fill_surfaces));
}
// find top surfaces (difference between current surfaces
// of current layer and upper one)
Surfaces top;
if (upper_layer) {
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);
surfaces_append(top,
//FIXME implement offset2_ex working over ExPolygons, that should be a bit more efficient than calling offset_ex twice.
@ -946,7 +947,7 @@ void PrintObject::detect_surfaces_type()
} else {
// if no upper layer, all surfaces of this one are solid
// we clone surfaces because we're going to clear the slices collection
top = layerm->slices.surfaces;
top = layerm->m_slices.surfaces;
for (Surface &surface : top)
surface.surface_type = stPosTop | stDensSolid;
}
@ -985,7 +986,7 @@ void PrintObject::detect_surfaces_type()
offset2_ex(
diff(
intersection(layerm_slices_surfaces, to_polygons(lower_slices)), // supported
to_polygons(lower_layer->get_region(idx_region)->slices.surfaces),
to_polygons(lower_layer->get_region(idx_region)->slices().surfaces),
true),
-offset, offset),
stPosBottom | stDensSolid);
@ -994,7 +995,7 @@ void PrintObject::detect_surfaces_type()
} else {
// if no lower layer, all surfaces of this one are solid
// we clone surfaces because we're going to clear the slices collection
bottom = layerm->slices.surfaces;
bottom = layerm->slices().surfaces;
for (Surface &surface : bottom)
surface.surface_type = surface_type_bottom_1st;
}
@ -1019,14 +1020,13 @@ void PrintObject::detect_surfaces_type()
std::vector<std::pair<Slic3r::ExPolygons, SVG::ExPolygonAttributes>> expolygons_with_attributes;
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(top), SVG::ExPolygonAttributes("green")));
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottom), SVG::ExPolygonAttributes("brown")));
expolygons_with_attributes.emplace_back(std::make_pair(union_ex(bottomOverBridge), SVG::ExPolygonAttributes("grey")));
expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices.surfaces), SVG::ExPolygonAttributes("black")));
expolygons_with_attributes.emplace_back(std::make_pair(to_expolygons(layerm->slices().surfaces), SVG::ExPolygonAttributes("black")));
SVG::export_expolygons(debug_out_path("1_detect_surfaces_type_%d_region%d-layer_%f.svg", iRun ++, idx_region, layer->print_z).c_str(), expolygons_with_attributes);
}
#endif /* SLIC3R_DEBUG_SLICE_PROCESSING */
// save surfaces to layer
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->slices.surfaces;
Surfaces &surfaces_out = interface_shells ? surfaces_new[idx_layer] : layerm->m_slices.surfaces;
surfaces_out.clear();
// find internal surfaces (difference between top/bottom surfaces and others)
@ -1054,8 +1054,8 @@ void PrintObject::detect_surfaces_type()
if (interface_shells) {
// Move surfaces_new to layerm->slices.surfaces
for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++ idx_layer)
m_layers[idx_layer]->get_region(idx_region)->slices.surfaces = std::move(surfaces_new[idx_layer]);
for (size_t idx_layer = 0; idx_layer < m_layers.size(); ++idx_layer)
m_layers[idx_layer]->get_region(idx_region)->m_slices.surfaces = std::move(surfaces_new[idx_layer]);
}
BOOST_LOG_TRIVIAL(debug) << "Detecting solid surfaces for region " << idx_region << " - clipping in parallel - start";
@ -1211,16 +1211,16 @@ void PrintObject::discover_vertical_shells()
LayerRegion &layerm = *layer.m_regions[idx_region];
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
// Top surfaces.
append(cache.top_surfaces, offset(to_expolygons(layerm.slices.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
append(cache.top_surfaces, offset(to_expolygons(layerm.slices().filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
// Bottom surfaces.
const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
append(cache.bottom_surfaces, offset(to_expolygons(layerm.slices().filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
// Calculate the maximum perimeter offset as if the slice was extruded with a single extruder only.
// First find the maxium number of perimeters per region slice.
unsigned int perimeters = 0;
for (Surface &s : layerm.slices.surfaces)
for (const Surface &s : layerm.slices().surfaces)
perimeters = std::max<unsigned int>(perimeters, s.extra_perimeters);
perimeters += layerm.region()->config().perimeters.value;
// Then calculate the infill offset.
@ -1287,11 +1287,11 @@ void PrintObject::discover_vertical_shells()
float min_perimeter_infill_spacing = float(layerm.flow(frSolidInfill).scaled_spacing()) * 1.05f;
// Top surfaces.
auto &cache = cache_top_botom_regions[idx_layer];
cache.top_surfaces = offset(to_expolygons(layerm.slices.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing);
cache.top_surfaces = offset(to_expolygons(layerm.slices().filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing);
append(cache.top_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_type(stPosTop | stDensSolid)), min_perimeter_infill_spacing));
// Bottom surfaces.
const SurfaceType surfaces_bottom[2] = { stPosBottom | stDensSolid, stPosBottom | stDensSolid | stModBridge };
cache.bottom_surfaces = offset(to_expolygons(layerm.slices.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
cache.bottom_surfaces = offset(to_expolygons(layerm.slices().filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing);
append(cache.bottom_surfaces, offset(to_expolygons(layerm.fill_surfaces.filter_by_types(surfaces_bottom, 2)), min_perimeter_infill_spacing));
// Holes over all regions. Only collect them once, they are valid for all idx_region iterations.
if (cache.holes.empty()) {
@ -1939,7 +1939,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " start";
for (size_t layer_id = 0; layer_id < expolygons_by_layer.size(); ++ layer_id)
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse);
m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(expolygons_by_layer[layer_id]), stPosInternal | stDensSparse);
m_print->throw_if_canceled();
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - append slices " << region_id << " end";
}
@ -2018,7 +2018,7 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
if (num_volumes > 1)
// Merge the islands using a positive / negative offset.
expolygons = offset_ex(offset_ex(expolygons, double(scale_(EPSILON))), double( - scale_(EPSILON)));
m_layers[layer_id]->regions()[region_id]->slices.append(std::move(expolygons), stPosInternal | stDensSparse);
m_layers[layer_id]->regions()[region_id]->m_slices.append(std::move(expolygons), stPosInternal | stDensSparse);
}
}
});
@ -2048,16 +2048,16 @@ void PrintObject::_slice(const std::vector<coordf_t> &layer_height_profile)
Layer *layer = m_layers[layer_id];
LayerRegion *layerm = layer->m_regions[region_id];
LayerRegion *other_layerm = layer->m_regions[other_region_id];
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices.empty() || expolygons_by_layer[layer_id].empty())
if (layerm == nullptr || other_layerm == nullptr || other_layerm->slices().empty() || expolygons_by_layer[layer_id].empty())
continue;
Polygons other_slices = to_polygons(other_layerm->slices);
Polygons other_slices = to_polygons(other_layerm->slices());
ExPolygons my_parts = intersection_ex(other_slices, to_polygons(expolygons_by_layer[layer_id]));
if (my_parts.empty())
continue;
// Remove such parts from original region.
other_layerm->slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse);
other_layerm->m_slices.set(diff_ex(other_slices, to_polygons(my_parts)), stPosInternal | stDensSparse);
// Append new parts to our region.
layerm->slices.append(std::move(my_parts), stPosInternal | stDensSparse);
layerm->m_slices.append(std::move(my_parts), stPosInternal | stDensSparse);
}
}
});
@ -2114,8 +2114,8 @@ end:
LayerRegion *layerm = layer->m_regions.front();
// Apply the XY compensation.
ExPolygons expolygons = (delta == 0.f) ?
to_expolygons(std::move(layerm->slices.surfaces)) :
offset_ex(to_expolygons(std::move(layerm->slices.surfaces)), delta);
to_expolygons(std::move(layerm->slices().surfaces)) :
offset_ex(to_expolygons(std::move(layerm->slices().surfaces)), delta);
// Apply the elephant foot compensation.
if (elephant_foot_compensation != 0) {
float elephant_foot_spacing = float(layerm->flow(frExternalPerimeter).scaled_elephant_foot_spacing());
@ -2130,7 +2130,7 @@ end:
expolygons = union_ex(tmp);
}
}
layerm->slices.set(std::move(expolygons), stPosInternal | stDensSparse);
layerm->m_slices.set(std::move(expolygons), stPosInternal | stDensSparse);
}
_offset_holes(hole_delta, layer->regions().front());
_smooth_curves(layer->regions().front());
@ -2143,7 +2143,7 @@ end:
Polygons processed;
for (size_t region_id = 0; region_id < layer->m_regions.size(); ++ region_id) {
LayerRegion *layerm = layer->m_regions[region_id];
ExPolygons slices = to_expolygons(std::move(layerm->slices.surfaces));
ExPolygons slices = to_expolygons(std::move(layerm->slices().surfaces));
if (upscale)
slices = offset_ex(std::move(slices), delta);
if (region_id > 0 && clip)
@ -2152,7 +2152,7 @@ end:
if (clip && (region_id + 1 < layer->m_regions.size()))
// Collect the already processed regions to trim the to be processed regions.
polygons_append(processed, slices);
layerm->slices.set(std::move(slices), stPosInternal | stDensSparse);
layerm->m_slices.set(std::move(slices), stPosInternal | stDensSparse);
}
}
if (delta < 0.f) {
@ -2193,7 +2193,7 @@ end:
void PrintObject::_offset_holes(double hole_delta, LayerRegion *layerm) {
if (hole_delta != 0.f) {
ExPolygons polys = to_expolygons(std::move(layerm->slices.surfaces));
ExPolygons polys = to_expolygons(std::move(layerm->slices().surfaces));
ExPolygons new_polys;
for (const ExPolygon &ex_poly : polys) {
ExPolygon new_ex_poly(ex_poly);
@ -2226,7 +2226,7 @@ void PrintObject::_offset_holes(double hole_delta, LayerRegion *layerm) {
}
new_polys.push_back(new_ex_poly);
}
layerm->slices.set(std::move(new_polys), stPosInternal | stDensSparse);
layerm->m_slices.set(std::move(new_polys), stPosInternal | stDensSparse);
}
}
@ -2317,7 +2317,7 @@ void PrintObject::_smooth_curves(LayerRegion *layerm) {
if (layerm->region()->config().curve_smoothing_precision.value > 0.f) {
ExPolygons new_polys;
for (const Surface &srf : layerm->slices.surfaces) {
for (const Surface &srf : layerm->slices().surfaces) {
const ExPolygon &ex_poly = srf.expolygon;
ExPolygon new_ex_poly(ex_poly);
new_ex_poly.contour = _smooth_curve(new_ex_poly.contour, PI,
@ -2336,7 +2336,7 @@ void PrintObject::_smooth_curves(LayerRegion *layerm) {
}
new_polys.push_back(new_ex_poly);
}
layerm->slices.set(std::move(new_polys), stPosInternal | stDensSparse);
layerm->m_slices.set(std::move(new_polys), stPosInternal | stDensSparse);
}
}
@ -2591,12 +2591,12 @@ std::string PrintObject::_fix_slicing_errors()
const Surfaces *lower_surfaces = nullptr;
for (size_t j = idx_layer + 1; j < m_layers.size(); ++ j)
if (! m_layers[j]->slicing_errors) {
upper_surfaces = &m_layers[j]->regions()[region_id]->slices.surfaces;
upper_surfaces = &m_layers[j]->regions()[region_id]->slices().surfaces;
break;
}
for (int j = int(idx_layer) - 1; j >= 0; -- j)
if (! m_layers[j]->slicing_errors) {
lower_surfaces = &m_layers[j]->regions()[region_id]->slices.surfaces;
lower_surfaces = &m_layers[j]->regions()[region_id]->slices().surfaces;
break;
}
// Collect outer contours and holes from the valid layers above & below.
@ -2623,7 +2623,7 @@ std::string PrintObject::_fix_slicing_errors()
if (lower_surfaces)
for (const auto &surface : *lower_surfaces)
polygons_append(holes, surface.expolygon.holes);
layerm->slices.set(diff_ex(union_(outer), holes, false), stPosInternal | stDensSparse);
layerm->m_slices.set(diff_ex(union_(outer), holes, false), stPosInternal | stDensSparse);
}
// Update layer slices after repairing the single regions.
layer->make_slices();
@ -2659,115 +2659,13 @@ void PrintObject::_simplify_slices(double distance)
m_print->throw_if_canceled();
Layer *layer = m_layers[layer_idx];
for (size_t region_idx = 0; region_idx < layer->m_regions.size(); ++ region_idx)
layer->m_regions[region_idx]->slices.simplify(distance);
layer->m_regions[region_idx]->m_slices.simplify(distance);
layer->slices.simplify(distance);
}
});
BOOST_LOG_TRIVIAL(debug) << "Slicing objects - siplifying slices in parallel - end";
}
void PrintObject::_make_perimeters()
{
if (! this->set_started(posPerimeters))
return;
BOOST_LOG_TRIVIAL(info) << "Generating perimeters..." << log_memory_info();
// merge slices if they were split into types
if (this->typed_slices) {
for (Layer *layer : m_layers)
layer->merge_slices();
this->typed_slices = false;
this->invalidate_step(posPrepareInfill);
}
// compare each layer to the one below, and mark those slices needing
// one additional inner perimeter, like the top of domed objects-
// this algorithm makes sure that at least one perimeter is overlapping
// but we don't generate any extra perimeter if fill density is zero, as they would be floating
// inside the object - infill_only_where_needed should be the method of choice for printing
// hollow objects
for (size_t region_id = 0; region_id < this->region_volumes.size(); ++ region_id) {
const PrintRegion &region = *m_print->regions()[region_id];
if (! region.config().extra_perimeters || region.config().perimeters == 0 || region.config().fill_density == 0 || this->layer_count() < 2)
continue;
BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - start";
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size() - 1),
[this, &region, region_id](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx) {
LayerRegion &layerm = *m_layers[layer_idx]->regions()[region_id];
const LayerRegion &upper_layerm = *m_layers[layer_idx+1]->regions()[region_id];
const Polygons upper_layerm_polygons = upper_layerm.slices;
// Filter upper layer polygons in intersection_ppl by their bounding boxes?
// my $upper_layerm_poly_bboxes= [ map $_->bounding_box, @{$upper_layerm_polygons} ];
const double total_loop_length = total_length(upper_layerm_polygons);
const coord_t perimeter_spacing = layerm.flow(frPerimeter).scaled_spacing();
const Flow ext_perimeter_flow = layerm.flow(frExternalPerimeter);
const coord_t ext_perimeter_width = ext_perimeter_flow.scaled_width();
const coord_t ext_perimeter_spacing = ext_perimeter_flow.scaled_spacing();
for (Surface &slice : layerm.slices.surfaces) {
for (;;) {
// compute the total thickness of perimeters
const coord_t perimeters_thickness = ext_perimeter_width/2 + ext_perimeter_spacing/2
+ (region.config().perimeters-1 + slice.extra_perimeters) * perimeter_spacing;
// define a critical area where we don't want the upper slice to fall into
// (it should either lay over our perimeters or outside this area)
const coord_t critical_area_depth = coord_t(perimeter_spacing * 1.5);
const Polygons critical_area = diff(
offset(slice.expolygon, double(- perimeters_thickness)),
offset(slice.expolygon, double(- perimeters_thickness - critical_area_depth))
);
// check whether a portion of the upper slices falls inside the critical area
const Polylines intersection = intersection_pl(to_polylines(upper_layerm_polygons), critical_area);
// only add an additional loop if at least 30% of the slice loop would benefit from it
if (total_length(intersection) <= total_loop_length*0.3)
break;
/*
if (0) {
require "Slic3r/SVG.pm";
Slic3r::SVG::output(
"extra.svg",
no_arrows => 1,
expolygons => union_ex($critical_area),
polylines => [ map $_->split_at_first_point, map $_->p, @{$upper_layerm->slices} ],
);
}
*/
++ slice.extra_perimeters;
}
#ifdef DEBUG
if (slice.extra_perimeters > 0)
printf(" adding %d more perimeter(s) at layer %zu\n", slice.extra_perimeters, layer_idx);
#endif
}
}
});
BOOST_LOG_TRIVIAL(debug) << "Generating extra perimeters for region " << region_id << " in parallel - end";
}
BOOST_LOG_TRIVIAL(debug) << "Generating perimeters in parallel - start";
tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()),
[this](const tbb::blocked_range<size_t>& range) {
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
m_layers[layer_idx]->make_perimeters();
}
);
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);
}
// Only active if config->infill_only_where_needed. This step trims the sparse infill,
// so it acts as an internal support. It maintains all other infill types intact.
@ -2895,7 +2793,7 @@ void PrintObject::discover_horizontal_shells()
// (not covered by a layer above / below).
// This does not contain the areas covered by perimeters!
Polygons solid;
for (const Surface &surface : layerm->slices.surfaces)
for (const Surface &surface : layerm->slices().surfaces)
if (surface.surface_type == type)
polygons_append(solid, to_polygons(surface.expolygon));
// Infill areas (slices without the perimeters).

View File

@ -279,7 +279,6 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
MyLayersPtr intermediate_layers = this->raft_and_intermediate_support_layers(
object, bottom_contacts, top_contacts, layer_storage);
// this->trim_support_layers_by_object(object, top_contacts, m_slicing_params.soluble_interface ? 0. : m_support_layer_height_min, 0., m_gap_xy);
this->trim_support_layers_by_object(object, top_contacts,
m_slicing_params.soluble_interface ? 0. : this->m_slicing_params.gap_support_object,
@ -429,14 +428,14 @@ Polygons collect_region_slices_by_type(const Layer &layer, SurfaceType surface_t
// 1) Count the new polygons first.
size_t n_polygons_new = 0;
for (const LayerRegion *region : layer.regions())
for (const Surface &surface : region->slices.surfaces)
for (const Surface &surface : region->slices().surfaces)
if (surface.surface_type == surface_type)
n_polygons_new += surface.expolygon.holes.size() + 1;
// 2) Collect the new polygons.
Polygons out;
out.reserve(n_polygons_new);
for (const LayerRegion *region : layer.regions())
for (const Surface &surface : region->slices.surfaces)
for (const Surface &surface : region->slices().surfaces)
if (surface.surface_type == surface_type)
polygons_append(out, surface.expolygon);
return out;
@ -791,7 +790,6 @@ namespace SupportMaterialInternal {
{
for (const ExtrusionEntity *ee : perimeters.entities) {
if (ee->is_collection()) {
const ExtrusionEntityCollection * eec = static_cast<const ExtrusionEntityCollection*>(ee);
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) {
//assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !!
if (ee2->is_loop())
@ -854,15 +852,11 @@ namespace SupportMaterialInternal {
}
}
}
static void collect_bridging_perimeter_areas(const ExtrusionEntityCollection &perimeters, const float expansion_scaled, Polygons &out)
static void collect_bridging_perimeter_areas(const ExtrusionEntitiesPtr &perimeters, const float expansion_scaled, Polygons &out)
{
for (const ExtrusionEntity *ee : perimeters.entities) {
for (const ExtrusionEntity *ee : perimeters) {
if (ee->is_collection()) {
for (const ExtrusionEntity *ee2 : static_cast<const ExtrusionEntityCollection*>(ee)->entities) {
//assert(! ee2->is_collection()); // there are loops for perimeters and collections for thin walls !!
if (ee2->is_loop())
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee2), expansion_scaled, out);
}
collect_bridging_perimeter_areas(static_cast<const ExtrusionEntityCollection*>(ee)->entities, expansion_scaled, out);
} else if (ee->is_loop())
collect_bridging_perimeter_areas(*static_cast<const ExtrusionLoop*>(ee), expansion_scaled, out);
}
@ -1027,7 +1021,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
Polygons contact_polygons;
Polygons slices_margin_cached;
double slices_margin_cached_offset = -1.;
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id-1]->slices.expolygons);
Polygons lower_layer_polygons = (layer_id == 0) ? Polygons() : to_polygons(object.layers()[layer_id - 1]->slices.expolygons);
// Offset of the lower layer, to trim the support polygons with to calculate dense supports.
double no_interface_offset = 0.;
if (layer_id == 0) {
@ -1056,7 +1050,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
0.5f * fw);
// Overhang polygons for this layer and region.
Polygons diff_polygons;
Polygons layerm_polygons = to_polygons(layerm->slices);
Polygons layerm_polygons = to_polygons(layerm->slices());
if (lower_layer_offset == 0.f) {
// Support everything.
diff_polygons = diff(layerm_polygons, lower_layer_polygons);
@ -1466,7 +1460,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
if (! m_object_config->support_material_buildplate_only)
// Find the bottom contact layers above the top surfaces of this layer.
task_group.run([this, &object, &top_contacts, contact_idx, &layer, layer_id, &layer_storage, &layer_support_areas, &bottom_contacts, &projection_raw] {
Polygons top = collect_region_slices_by_type(layer, stPosTop| stDensSolid);
Polygons top = collect_region_slices_by_type(layer, stPosTop | stDensSolid);
#ifdef SLIC3R_DEBUG
{
BoundingBox bbox = get_extents(projection_raw);
@ -1538,7 +1532,6 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
}
}
}
#ifdef SLIC3R_DEBUG
Slic3r::SVG::export_expolygons(
debug_out_path("support-bottom-contacts-%d-%lf.svg", iRun, layer_new.print_z),
@ -2135,7 +2128,7 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
offset(to_expolygons(region->fill_surfaces.filter_by_type(stPosBottom | stDensSolid | stModBridge)),
gap_xy_scaled, SUPPORT_SURFACES_OFFSET_PARAMETERS));
if (region->region()->config().overhangs.value)
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters, gap_xy_scaled, polygons_trimming);
SupportMaterialInternal::collect_bridging_perimeter_areas(region->perimeters.entities, gap_xy_scaled, polygons_trimming);
}
if (! some_region_overlaps)
break;

View File

@ -140,6 +140,7 @@ public:
typedef std::vector<Surface> Surfaces;
typedef std::vector<Surface*> SurfacesPtr;
typedef std::vector<const Surface*> SurfacesConstPtr;
inline Polygons to_polygons(const Surfaces &src)
{
@ -171,6 +172,21 @@ inline Polygons to_polygons(const SurfacesPtr &src)
return polygons;
}
inline Polygons to_polygons(const SurfacesConstPtr &src)
{
size_t num = 0;
for (SurfacesConstPtr::const_iterator it = src.begin(); it != src.end(); ++it)
num += (*it)->expolygon.holes.size() + 1;
Polygons polygons;
polygons.reserve(num);
for (SurfacesConstPtr::const_iterator it = src.begin(); it != src.end(); ++it) {
polygons.emplace_back((*it)->expolygon.contour);
for (Polygons::const_iterator ith = (*it)->expolygon.holes.begin(); ith != (*it)->expolygon.holes.end(); ++ith)
polygons.emplace_back(*ith);
}
return polygons;
}
inline ExPolygons to_expolygons(const Surfaces &src)
{
ExPolygons expolygons;
@ -199,6 +215,15 @@ inline ExPolygons to_expolygons(const SurfacesPtr &src)
return expolygons;
}
inline ExPolygons to_expolygons(const SurfacesConstPtr &src)
{
ExPolygons expolygons;
expolygons.reserve(src.size());
for (SurfacesConstPtr::const_iterator it = src.begin(); it != src.end(); ++it)
expolygons.emplace_back((*it)->expolygon);
return expolygons;
}
// Count a nuber of polygons stored inside the vector of expolygons.
// Useful for allocating space for polygons when converting expolygons to polygons.
inline size_t number_polygons(const Surfaces &surfaces)

View File

@ -54,34 +54,34 @@ SurfaceCollection::group(std::vector<SurfacesPtr> *retval)
}
}
SurfacesPtr
SurfaceCollection::filter_by_type(const SurfaceType type)
SurfacesConstPtr
SurfaceCollection::filter_by_type(const SurfaceType type) const
{
SurfacesPtr ss;
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
if (surface->surface_type == type) ss.push_back(&*surface);
SurfacesConstPtr ss;
for (const Surface & surface : this->surfaces) {
if (surface.surface_type == type) ss.push_back(&surface);
}
return ss;
}
SurfacesPtr
SurfaceCollection::filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed)
SurfacesConstPtr
SurfaceCollection::filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed) const
{
SurfacesPtr ss;
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
if ((surface->surface_type & allowed) == allowed && (surface->surface_type & not_allowed) == 0) ss.push_back(&*surface);
SurfacesConstPtr ss;
for (const Surface & surface : this->surfaces) {
if ((surface.surface_type & allowed) == allowed && (surface.surface_type & not_allowed) == 0) ss.push_back(&surface);
}
return ss;
}
SurfacesPtr
SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
SurfacesConstPtr
SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes) const
{
SurfacesPtr ss;
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
SurfacesConstPtr ss;
for (const Surface & surface : this->surfaces) {
for (int i = 0; i < ntypes; ++ i) {
if (surface->surface_type == types[i]) {
ss.push_back(&*surface);
if (surface.surface_type == types[i]) {
ss.push_back(&surface);
break;
}
}
@ -90,21 +90,21 @@ SurfaceCollection::filter_by_types(const SurfaceType *types, int ntypes)
}
void
SurfaceCollection::filter_by_type(const SurfaceType type, Polygons* polygons)
SurfaceCollection::filter_by_type(const SurfaceType type, Polygons* polygons) const
{
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
if (surface->surface_type == type) {
Polygons pp = surface->expolygon;
for (const Surface & surface : this->surfaces) {
if (surface.surface_type == type) {
Polygons pp = surface.expolygon;
polygons->insert(polygons->end(), pp.begin(), pp.end());
}
}
}
void
SurfaceCollection::filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed)
SurfaceCollection::filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed) const
{
for (Surfaces::iterator surface = this->surfaces.begin(); surface != this->surfaces.end(); ++surface) {
if ((surface->surface_type & flags_needed) == flags_needed && (surface->surface_type & flags_not_allowed)==0) {
Polygons pp = surface->expolygon;
for (const Surface & surface : this->surfaces) {
if ((surface.surface_type & flags_needed) == flags_needed && (surface.surface_type & flags_not_allowed)==0) {
Polygons pp = surface.expolygon;
polygons->insert(polygons->end(), pp.begin(), pp.end());
}
}

View File

@ -27,17 +27,17 @@ public:
for (const Surface &surface : this->surfaces) if (surface.has_pos_bottom() && surface.expolygon.contains(item)) return true;
return false;
}
SurfacesPtr filter_by_type(const SurfaceType type);
SurfacesPtr filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed = stNone);
SurfacesPtr filter_by_types(const SurfaceType *types, int ntypes);
SurfacesConstPtr filter_by_type(const SurfaceType type) const;
SurfacesConstPtr filter_by_type_flag(const SurfaceType allowed, const SurfaceType not_allowed = stNone) const;
SurfacesConstPtr filter_by_types(const SurfaceType *types, int ntypes) const;
void keep_type(const SurfaceType type);
void keep_type_flag(const SurfaceType flags_needed, const SurfaceType flags_to_remove = stNone);
void keep_types(const SurfaceType *types, int ntypes);
void keep_types_flag(const SurfaceType flags_to_keep, const SurfaceType flags_to_remove = stNone);
void remove_type(const SurfaceType type);
void remove_types(const SurfaceType *types, int ntypes);
void filter_by_type(const SurfaceType type, Polygons* polygons);
void filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed = stNone);
void filter_by_type(const SurfaceType type, Polygons* polygons) const;
void filter_by_type_flag(Polygons* polygons, const SurfaceType flags_needed, const SurfaceType flags_not_allowed = stNone) const;
void clear() { surfaces.clear(); }
bool empty() const { return surfaces.empty(); }