added semi support for lightning infill

This commit is contained in:
PavelMikus 2023-03-13 16:08:32 +01:00 committed by Pavel Mikuš
parent 487d9209ed
commit 12f1cd0bc0
4 changed files with 58 additions and 35 deletions

View File

@ -640,7 +640,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
#endif #endif
} }
Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree) const Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive::Octree* support_fill_octree, FillLightning::Generator* lightning_generator) const
{ {
std::vector<SurfaceFill> surface_fills = group_fills(*this); std::vector<SurfaceFill> surface_fills = group_fills(*this);
const Slic3r::BoundingBox bbox = this->object()->bounding_box(); const Slic3r::BoundingBox bbox = this->object()->bounding_box();
@ -654,14 +654,10 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
} }
switch (surface_fill.params.pattern) { switch (surface_fill.params.pattern) {
case ipLightning: {
auto polylines = to_polylines(shrink_ex(surface_fill.expolygons, 5.0 * surface_fill.params.flow.scaled_spacing()));
sparse_infill_polylines.insert(sparse_infill_polylines.end(), polylines.begin(), polylines.end());
continue;
}; break;
case ipCount: continue; break; case ipCount: continue; break;
case ipSupportBase: continue; break; case ipSupportBase: continue; break;
case ipEnsuring: continue; break; case ipEnsuring: continue; break;
case ipLightning:
case ipAdaptiveCubic: case ipAdaptiveCubic:
case ipSupportCubic: case ipSupportCubic:
case ipRectilinear: case ipRectilinear:
@ -692,6 +688,12 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc
f->print_config = &this->object()->print()->config(); f->print_config = &this->object()->print()->config();
f->print_object_config = &this->object()->config(); f->print_object_config = &this->object()->config();
if (surface_fill.params.pattern == ipLightning) {
auto *lf = dynamic_cast<FillLightning::Filler *>(f.get());
lf->generator = lightning_generator;
lf->num_raft_layers = this->object()->slicing_parameters().raft_layers();
}
// calculate flow spacing for infill pattern generation // calculate flow spacing for infill pattern generation
double link_max_length = 0.; double link_max_length = 0.;
if (!surface_fill.params.bridge) { if (!surface_fill.params.bridge) {

View File

@ -372,7 +372,8 @@ public:
FillAdaptive::Octree *support_fill_octree, FillAdaptive::Octree *support_fill_octree,
FillLightning::Generator *lightning_generator); FillLightning::Generator *lightning_generator);
Polylines generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree *adaptive_fill_octree, Polylines generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Octree *adaptive_fill_octree,
FillAdaptive::Octree *support_fill_octree) const; FillAdaptive::Octree *support_fill_octree,
FillLightning::Generator* lightning_generator) const;
void make_ironing(); void make_ironing();
void export_region_slices_to_svg(const char *path) const; void export_region_slices_to_svg(const char *path) const;

View File

@ -2,6 +2,7 @@
#define slic3r_Print_hpp_ #define slic3r_Print_hpp_
#include "Fill/FillAdaptive.hpp" #include "Fill/FillAdaptive.hpp"
#include "Fill/FillLightning.hpp"
#include "PrintBase.hpp" #include "PrintBase.hpp"
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
@ -413,7 +414,8 @@ private:
// so that next call to make_perimeters() performs a union() before computing loops // so that next call to make_perimeters() performs a union() before computing loops
bool m_typed_slices = false; bool m_typed_slices = false;
std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> adaptive_fill_octrees; std::pair<FillAdaptive::OctreePtr, FillAdaptive::OctreePtr> m_adaptive_fill_octrees;
FillLightning::GeneratorPtr m_lightning_generator;
}; };
struct WipeTowerData struct WipeTowerData

View File

@ -404,17 +404,16 @@ void PrintObject::infill()
if (this->set_started(posInfill)) { if (this->set_started(posInfill)) {
m_print->set_status(45, L("making infill")); m_print->set_status(45, L("making infill"));
const auto& adaptive_fill_octree = this->adaptive_fill_octrees.first; const auto& adaptive_fill_octree = this->m_adaptive_fill_octrees.first;
const auto& support_fill_octree = this->adaptive_fill_octrees.second; const auto& support_fill_octree = this->m_adaptive_fill_octrees.second;
auto lightning_generator = this->prepare_lightning_infill_data();
BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start"; BOOST_LOG_TRIVIAL(debug) << "Filling layers in parallel - start";
tbb::parallel_for( tbb::parallel_for(
tbb::blocked_range<size_t>(0, m_layers.size()), tbb::blocked_range<size_t>(0, m_layers.size()),
[this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree, &lightning_generator](const tbb::blocked_range<size_t>& range) { [this, &adaptive_fill_octree = adaptive_fill_octree, &support_fill_octree = support_fill_octree](const tbb::blocked_range<size_t>& range) {
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();
m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get(), lightning_generator.get()); m_layers[layer_idx]->make_fills(adaptive_fill_octree.get(), support_fill_octree.get(), this->m_lightning_generator.get());
} }
} }
); );
@ -1560,7 +1559,7 @@ void PrintObject::discover_vertical_shells()
} // for each region } // for each region
} // void PrintObject::discover_vertical_shells() } // void PrintObject::discover_vertical_shells()
#define DEBUG_BRIDGE_OVER_INFILL // #define DEBUG_BRIDGE_OVER_INFILL
#ifdef DEBUG_BRIDGE_OVER_INFILL #ifdef DEBUG_BRIDGE_OVER_INFILL
template<typename T> void debug_draw(std::string name, const T& a, const T& b, const T& c, const T& d) template<typename T> void debug_draw(std::string name, const T& a, const T& b, const T& c, const T& d)
{ {
@ -1586,13 +1585,22 @@ void PrintObject::bridge_over_infill()
struct CandidateSurface struct CandidateSurface
{ {
CandidateSurface(const Surface *original_surface, Polygons new_polys, const LayerRegion *region, double bridge_angle) CandidateSurface(const Surface *original_surface,
: original_surface(original_surface), new_polys(new_polys), region(region), bridge_angle(bridge_angle) Polygons new_polys,
const LayerRegion *region,
double bridge_angle,
bool supported_by_lightning)
: original_surface(original_surface)
, new_polys(new_polys)
, region(region)
, bridge_angle(bridge_angle)
, supported_by_lightning(supported_by_lightning)
{} {}
const Surface *original_surface; const Surface *original_surface;
Polygons new_polys; Polygons new_polys;
const LayerRegion *region; const LayerRegion *region;
double bridge_angle; double bridge_angle;
bool supported_by_lightning;
}; };
std::map<size_t, std::vector<CandidateSurface>> surfaces_by_layer; std::map<size_t, std::vector<CandidateSurface>> surfaces_by_layer;
@ -1610,7 +1618,11 @@ void PrintObject::bridge_over_infill()
auto spacing = layer->regions().front()->flow(frSolidInfill).scaled_spacing(); auto spacing = layer->regions().front()->flow(frSolidInfill).scaled_spacing();
Polygons unsupported_area; Polygons unsupported_area;
Polygons lower_layer_solids; Polygons lower_layer_solids;
bool contains_only_lightning = true;
for (const LayerRegion *region : layer->lower_layer->regions()) { for (const LayerRegion *region : layer->lower_layer->regions()) {
if (region->region().config().fill_pattern.value != ipLightning) {
contains_only_lightning = false;
}
Polygons fill_polys = to_polygons(region->fill_expolygons()); Polygons fill_polys = to_polygons(region->fill_expolygons());
unsupported_area = union_(unsupported_area, expand(fill_polys, spacing)); unsupported_area = union_(unsupported_area, expand(fill_polys, spacing));
for (const Surface &surface : region->fill_surfaces()) { for (const Surface &surface : region->fill_surfaces()) {
@ -1632,7 +1644,7 @@ void PrintObject::bridge_over_infill()
bool partially_supported = area(unsupported) < area(to_polygons(s->expolygon)) - EPSILON; bool partially_supported = area(unsupported) < area(to_polygons(s->expolygon)) - EPSILON;
if (!unsupported.empty() && (!partially_supported || area(unsupported) > 5 * 5 * spacing * spacing)) { if (!unsupported.empty() && (!partially_supported || area(unsupported) > 5 * 5 * spacing * spacing)) {
Polygons worth_bridging = intersection(to_polygons(s->expolygon), expand(unsupported, 5 * spacing)); Polygons worth_bridging = intersection(to_polygons(s->expolygon), expand(unsupported, 5 * spacing));
candidate_surfaces.push_back(CandidateSurface(s, worth_bridging, region, 0)); candidate_surfaces.push_back(CandidateSurface(s, worth_bridging, region, 0, contains_only_lightning));
#ifdef DEBUG_BRIDGE_OVER_INFILL #ifdef DEBUG_BRIDGE_OVER_INFILL
debug_draw(std::to_string(region->layer()->id()) + "_candidate_surface_" + std::to_string(area(s->expolygon)), debug_draw(std::to_string(region->layer()->id()) + "_candidate_surface_" + std::to_string(area(s->expolygon)),
@ -1660,7 +1672,9 @@ void PrintObject::bridge_over_infill()
} }
} }
this->adaptive_fill_octrees = this->prepare_adaptive_infill_data(surfaces_w_bottom_z); this->m_adaptive_fill_octrees = this->prepare_adaptive_infill_data(surfaces_w_bottom_z);
this->m_lightning_generator = this->prepare_lightning_infill_data();
std::vector<size_t> layers_to_generate_infill; std::vector<size_t> layers_to_generate_infill;
for (const auto &pair : surfaces_by_layer) { for (const auto &pair : surfaces_by_layer) {
assert(pair.first > 0); assert(pair.first > 0);
@ -1674,8 +1688,9 @@ void PrintObject::bridge_over_infill()
for (size_t job_idx = r.begin(); job_idx < r.end(); job_idx++) { for (size_t job_idx = r.begin(); job_idx < r.end(); job_idx++) {
size_t lidx = layers_to_generate_infill[job_idx]; size_t lidx = layers_to_generate_infill[job_idx];
infill_lines.at( infill_lines.at(
lidx) = po->get_layer(lidx)->generate_sparse_infill_polylines_for_anchoring(po->adaptive_fill_octrees.first.get(), lidx) = po->get_layer(lidx)->generate_sparse_infill_polylines_for_anchoring(po->m_adaptive_fill_octrees.first.get(),
po->adaptive_fill_octrees.second.get()); po->m_adaptive_fill_octrees.second.get(),
po->m_lightning_generator.get());
} }
}); });
#ifdef DEBUG_BRIDGE_OVER_INFILL #ifdef DEBUG_BRIDGE_OVER_INFILL
@ -2061,21 +2076,21 @@ void PrintObject::bridge_over_infill()
} }
expansion_area = closing(expansion_area, SCALED_EPSILON); expansion_area = closing(expansion_area, SCALED_EPSILON);
expansion_area = intersection(expansion_area, deep_infill_area); expansion_area = intersection(expansion_area, deep_infill_area);
Lines anchors = to_lines(intersection_pl(infill_lines[lidx - 1], expansion_area)); Polylines anchors = intersection_pl(infill_lines[lidx - 1], expansion_area);
std::vector<CandidateSurface> expanded_surfaces; std::vector<CandidateSurface> expanded_surfaces;
expanded_surfaces.reserve(surfaces_by_layer[lidx].size()); expanded_surfaces.reserve(surfaces_by_layer[lidx].size());
for (const CandidateSurface &candidate : surfaces_by_layer[lidx]) { for (const CandidateSurface &candidate : surfaces_by_layer[lidx]) {
const Flow &flow = candidate.region->bridging_flow(frSolidInfill, true); const Flow &flow = candidate.region->bridging_flow(frSolidInfill, true);
Polygons area_to_be_bridged = intersection(candidate.new_polys, deep_infill_area); Polygons area_to_be_bridge = intersection(candidate.new_polys, deep_infill_area);
if (area_to_be_bridged.empty()) if (area_to_be_bridge.empty())
continue; continue;
Polygons boundary_area = union_(expansion_area, expand(area_to_be_bridged, flow.scaled_spacing())); Polygons boundary_area = union_(expansion_area, expand(area_to_be_bridge, flow.scaled_spacing()));
Lines boundary_lines = to_lines(boundary_area); Polylines boundary_plines = to_polylines(boundary_area);
double bridging_angle = 0; double bridging_angle = 0;
Polygons tmp_expanded_area = expand(area_to_be_bridged, 3.0 * flow.scaled_spacing()); Polygons tmp_expanded_area = expand(area_to_be_bridge, 3.0 * flow.scaled_spacing());
for (const CandidateSurface &s : expanded_surfaces) { for (const CandidateSurface &s : expanded_surfaces) {
if (!intersection(s.new_polys, tmp_expanded_area).empty()) { if (!intersection(s.new_polys, tmp_expanded_area).empty()) {
bridging_angle = s.bridge_angle; bridging_angle = s.bridge_angle;
@ -2084,30 +2099,33 @@ void PrintObject::bridge_over_infill()
} }
if (bridging_angle == 0) { if (bridging_angle == 0) {
if (!anchors.empty()) { if (!anchors.empty()) {
bridging_angle = determine_bridging_angle(area_to_be_bridged, anchors, bridging_angle = determine_bridging_angle(area_to_be_bridge, to_lines(anchors),
candidate.region->region().config().fill_pattern.value); candidate.region->region().config().fill_pattern.value);
} else { } else {
// use expansion boundaries as anchors. // use expansion boundaries as anchors.
// Also, use Infill pattern that is neutral for angle determination, since there are no infill lines. // Also, use Infill pattern that is neutral for angle determination, since there are no infill lines.
bridging_angle = determine_bridging_angle(area_to_be_bridged, boundary_lines, InfillPattern::ipLine); bridging_angle = determine_bridging_angle(area_to_be_bridge, to_lines(boundary_plines), InfillPattern::ipLine);
} }
} }
boundary_lines.insert(boundary_lines.end(), anchors.begin(), anchors.end()); boundary_plines.insert(boundary_plines.end(), anchors.begin(), anchors.end());
Polygons bridged_area = construct_anchored_polygon(area_to_be_bridged, boundary_lines, flow, bridging_angle); if (candidate.supported_by_lightning) {
bridged_area = intersection(bridged_area, boundary_area); boundary_plines = intersection_pl(boundary_plines, expand(area_to_be_bridge, scale_(10)));
bridged_area = opening(bridged_area, flow.scaled_spacing()); }
expansion_area = diff(expansion_area, bridged_area); Polygons bridging_area = construct_anchored_polygon(area_to_be_bridge, to_lines(boundary_plines), flow, bridging_angle);
bridging_area = intersection(bridging_area, boundary_area);
bridging_area = opening(bridging_area, flow.scaled_spacing());
expansion_area = diff(expansion_area, bridging_area);
#ifdef DEBUG_BRIDGE_OVER_INFILL #ifdef DEBUG_BRIDGE_OVER_INFILL
debug_draw(std::to_string(lidx) + "_" + std::to_string(cluster_idx) + "_" + std::to_string(job_idx) + debug_draw(std::to_string(lidx) + "_" + std::to_string(cluster_idx) + "_" + std::to_string(job_idx) +
"_expanded_bridging", "_expanded_bridging",
to_lines(layer->lslices), to_lines(candidate.original_surface->expolygon), to_lines(candidate.new_polys), to_lines(layer->lslices), to_lines(candidate.original_surface->expolygon), to_lines(candidate.new_polys),
to_lines(bridged_area)); to_lines(bridging_area));
#endif #endif
expanded_surfaces.push_back( expanded_surfaces.push_back(
CandidateSurface(candidate.original_surface, bridged_area, candidate.region, bridging_angle)); CandidateSurface(candidate.original_surface, bridging_area, candidate.region, bridging_angle, candidate.supported_by_lightning));
} }
surfaces_by_layer[lidx].swap(expanded_surfaces); surfaces_by_layer[lidx].swap(expanded_surfaces);
expanded_surfaces.clear(); expanded_surfaces.clear();