added semi support for lightning infill
This commit is contained in:
parent
487d9209ed
commit
12f1cd0bc0
@ -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) {
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user