mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-08 15:37:30 -06:00
ENH: enable arachne for concentric pattern
Enable arachne for concentric pattern by referring to PrusaSlicer Also remove useless pattern we added. Signed-off-by: salt.wei <salt.wei@bambulab.com> Change-Id: Ie2574f7fc4751ebdf1caab4de52013f3101e104f
This commit is contained in:
parent
df321f8cd9
commit
db9ade2257
10 changed files with 153 additions and 167 deletions
|
@ -67,8 +67,6 @@ set(lisbslic3r_sources
|
||||||
Fill/FillBase.hpp
|
Fill/FillBase.hpp
|
||||||
Fill/FillConcentric.cpp
|
Fill/FillConcentric.cpp
|
||||||
Fill/FillConcentric.hpp
|
Fill/FillConcentric.hpp
|
||||||
Fill/FillConcentricWGapFill.cpp
|
|
||||||
Fill/FillConcentricWGapFill.hpp
|
|
||||||
Fill/FillConcentricInternal.cpp
|
Fill/FillConcentricInternal.cpp
|
||||||
Fill/FillConcentricInternal.hpp
|
Fill/FillConcentricInternal.hpp
|
||||||
Fill/FillHoneycomb.cpp
|
Fill/FillHoneycomb.cpp
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "FillBase.hpp"
|
#include "FillBase.hpp"
|
||||||
#include "FillRectilinear.hpp"
|
#include "FillRectilinear.hpp"
|
||||||
#include "FillConcentricInternal.hpp"
|
#include "FillConcentricInternal.hpp"
|
||||||
|
#include "FillConcentric.hpp"
|
||||||
|
|
||||||
#define NARROW_INFILL_AREA_THRESHOLD 3
|
#define NARROW_INFILL_AREA_THRESHOLD 3
|
||||||
|
|
||||||
|
@ -407,6 +408,11 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||||
assert(fill_concentric != nullptr);
|
assert(fill_concentric != nullptr);
|
||||||
fill_concentric->print_config = &this->object()->print()->config();
|
fill_concentric->print_config = &this->object()->print()->config();
|
||||||
fill_concentric->print_object_config = &this->object()->config();
|
fill_concentric->print_object_config = &this->object()->config();
|
||||||
|
} else if (surface_fill.params.pattern == ipConcentric) {
|
||||||
|
FillConcentric *fill_concentric = dynamic_cast<FillConcentric *>(f.get());
|
||||||
|
assert(fill_concentric != nullptr);
|
||||||
|
fill_concentric->print_config = &this->object()->print()->config();
|
||||||
|
fill_concentric->print_object_config = &this->object()->config();
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate flow spacing for infill pattern generation
|
// calculate flow spacing for infill pattern generation
|
||||||
|
@ -434,6 +440,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||||
params.anchor_length = surface_fill.params.anchor_length;
|
params.anchor_length = surface_fill.params.anchor_length;
|
||||||
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
||||||
params.resolution = resolution;
|
params.resolution = resolution;
|
||||||
|
params.use_arachne = surface_fill.params.pattern == ipConcentric;
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
params.flow = surface_fill.params.flow;
|
params.flow = surface_fill.params.flow;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "../PrintConfig.hpp"
|
#include "../PrintConfig.hpp"
|
||||||
#include "../Surface.hpp"
|
#include "../Surface.hpp"
|
||||||
#include "../libslic3r.h"
|
#include "../libslic3r.h"
|
||||||
|
#include "../VariableWidth.hpp"
|
||||||
|
|
||||||
#include "FillBase.hpp"
|
#include "FillBase.hpp"
|
||||||
#include "FillConcentric.hpp"
|
#include "FillConcentric.hpp"
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include "FillAdaptive.hpp"
|
#include "FillAdaptive.hpp"
|
||||||
#include "FillLightning.hpp"
|
#include "FillLightning.hpp"
|
||||||
// BBS: new infill pattern header
|
// BBS: new infill pattern header
|
||||||
#include "FillConcentricWGapFill.hpp"
|
|
||||||
#include "FillConcentricInternal.hpp"
|
#include "FillConcentricInternal.hpp"
|
||||||
|
|
||||||
// #define INFILL_DEBUG_OUTPUT
|
// #define INFILL_DEBUG_OUTPUT
|
||||||
|
@ -58,7 +58,6 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
||||||
case ipLightning: return new FillLightning::Filler();
|
case ipLightning: return new FillLightning::Filler();
|
||||||
#endif // HAS_LIGHTNING_INFILL
|
#endif // HAS_LIGHTNING_INFILL
|
||||||
// BBS: for internal solid infill only
|
// BBS: for internal solid infill only
|
||||||
case ipConcentricGapFill: return new FillConcentricWGapFill();
|
|
||||||
case ipConcentricInternal: return new FillConcentricInternal();
|
case ipConcentricInternal: return new FillConcentricInternal();
|
||||||
// BBS: for bottom and top surface only
|
// BBS: for bottom and top surface only
|
||||||
case ipMonotonicLine: return new FillMonotonicLineWGapFill();
|
case ipMonotonicLine: return new FillMonotonicLineWGapFill();
|
||||||
|
@ -107,16 +106,31 @@ Polylines Fill::fill_surface(const Surface *surface, const FillParams ¶ms)
|
||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ThickPolylines Fill::fill_surface_arachne(const Surface* surface, const FillParams& params)
|
||||||
|
{
|
||||||
|
// Perform offset.
|
||||||
|
Slic3r::ExPolygons expp = offset_ex(surface->expolygon, float(scale_(this->overlap - 0.5 * this->spacing)));
|
||||||
|
// Create the infills for each of the regions.
|
||||||
|
ThickPolylines thick_polylines_out;
|
||||||
|
for (ExPolygon& expoly : expp)
|
||||||
|
_fill_surface_single(params, surface->thickness_layers, _infill_direction(surface), std::move(expoly), thick_polylines_out);
|
||||||
|
return thick_polylines_out;
|
||||||
|
}
|
||||||
|
|
||||||
// BBS: this method is used to fill the ExtrusionEntityCollection. It call fill_surface by default
|
// BBS: this method is used to fill the ExtrusionEntityCollection. It call fill_surface by default
|
||||||
void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
|
void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
|
||||||
{
|
{
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
|
ThickPolylines thick_polylines;
|
||||||
try {
|
try {
|
||||||
polylines = this->fill_surface(surface, params);
|
if (params.use_arachne)
|
||||||
|
thick_polylines = this->fill_surface_arachne(surface, params);
|
||||||
|
else
|
||||||
|
polylines = this->fill_surface(surface, params);
|
||||||
}
|
}
|
||||||
catch (InfillFailedException&) {}
|
catch (InfillFailedException&) {}
|
||||||
|
|
||||||
if (!polylines.empty()) {
|
if (!polylines.empty() || !thick_polylines.empty()) {
|
||||||
// calculate actual flow from spacing (which might have been adjusted by the infill
|
// calculate actual flow from spacing (which might have been adjusted by the infill
|
||||||
// pattern generator)
|
// pattern generator)
|
||||||
double flow_mm3_per_mm = params.flow.mm3_per_mm();
|
double flow_mm3_per_mm = params.flow.mm3_per_mm();
|
||||||
|
@ -136,10 +150,17 @@ void Fill::fill_surface_extrusion(const Surface* surface, const FillParams& para
|
||||||
out.push_back(eec = new ExtrusionEntityCollection());
|
out.push_back(eec = new ExtrusionEntityCollection());
|
||||||
// Only concentric fills are not sorted.
|
// Only concentric fills are not sorted.
|
||||||
eec->no_sort = this->no_sort();
|
eec->no_sort = this->no_sort();
|
||||||
extrusion_entities_append_paths(
|
if (params.use_arachne) {
|
||||||
eec->entities, std::move(polylines),
|
Flow new_flow = params.flow.with_spacing(float(this->spacing));
|
||||||
params.extrusion_role,
|
variable_width(thick_polylines, params.extrusion_role, new_flow, eec->entities);
|
||||||
flow_mm3_per_mm, float(flow_width), params.flow.height());
|
thick_polylines.clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
extrusion_entities_append_paths(
|
||||||
|
eec->entities, std::move(polylines),
|
||||||
|
params.extrusion_role,
|
||||||
|
flow_mm3_per_mm, float(flow_width), params.flow.height());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,9 @@ struct FillParams
|
||||||
// in this case we don't try to make more continuous paths
|
// in this case we don't try to make more continuous paths
|
||||||
bool complete { false };
|
bool complete { false };
|
||||||
|
|
||||||
|
// For Concentric infill, to switch between Classic and Arachne.
|
||||||
|
bool use_arachne{ false };
|
||||||
|
|
||||||
// BBS
|
// BBS
|
||||||
Flow flow;
|
Flow flow;
|
||||||
ExtrusionRole extrusion_role{ ExtrusionRole(0) };
|
ExtrusionRole extrusion_role{ ExtrusionRole(0) };
|
||||||
|
@ -121,6 +124,7 @@ public:
|
||||||
|
|
||||||
// Perform the fill.
|
// Perform the fill.
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
|
virtual ThickPolylines fill_surface_arachne(const Surface* surface, const FillParams& params);
|
||||||
|
|
||||||
// BBS: this method is used to fill the ExtrusionEntityCollection.
|
// BBS: this method is used to fill the ExtrusionEntityCollection.
|
||||||
// It call fill_surface by default
|
// It call fill_surface by default
|
||||||
|
@ -149,6 +153,13 @@ protected:
|
||||||
ExPolygon /* expolygon */,
|
ExPolygon /* expolygon */,
|
||||||
Polylines & /* polylines_out */) {};
|
Polylines & /* polylines_out */) {};
|
||||||
|
|
||||||
|
// Used for concentric infill to generate ThickPolylines using Arachne.
|
||||||
|
virtual void _fill_surface_single(const FillParams& params,
|
||||||
|
unsigned int thickness_layers,
|
||||||
|
const std::pair<float, Point>& direction,
|
||||||
|
ExPolygon expolygon,
|
||||||
|
ThickPolylines& thick_polylines_out) {}
|
||||||
|
|
||||||
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
|
virtual float _layer_angle(size_t idx) const { return (idx & 1) ? float(M_PI/2.) : 0; }
|
||||||
|
|
||||||
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
virtual std::pair<float, Point> _infill_direction(const Surface *surface) const;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "../ClipperUtils.hpp"
|
#include "../ClipperUtils.hpp"
|
||||||
#include "../ExPolygon.hpp"
|
#include "../ExPolygon.hpp"
|
||||||
#include "../Surface.hpp"
|
#include "../Surface.hpp"
|
||||||
|
#include "../VariableWidth.hpp"
|
||||||
|
#include "Arachne/WallToolPaths.hpp"
|
||||||
|
|
||||||
#include "FillConcentric.hpp"
|
#include "FillConcentric.hpp"
|
||||||
|
|
||||||
|
@ -61,4 +63,84 @@ void FillConcentric::_fill_surface_single(
|
||||||
// We want the loops to be split inside the G-code generator to get optimum path planning.
|
// We want the loops to be split inside the G-code generator to get optimum path planning.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FillConcentric::_fill_surface_single(const FillParams& params,
|
||||||
|
unsigned int thickness_layers,
|
||||||
|
const std::pair<float, Point>& direction,
|
||||||
|
ExPolygon expolygon,
|
||||||
|
ThickPolylines& thick_polylines_out)
|
||||||
|
{
|
||||||
|
assert(params.use_arachne);
|
||||||
|
assert(this->print_config != nullptr && this->print_object_config != nullptr);
|
||||||
|
|
||||||
|
// no rotation is supported for this infill pattern
|
||||||
|
Point bbox_size = expolygon.contour.bounding_box().size();
|
||||||
|
coord_t min_spacing = scaled<coord_t>(this->spacing);
|
||||||
|
|
||||||
|
if (params.density > 0.9999f && !params.dont_adjust) {
|
||||||
|
coord_t loops_count = std::max(bbox_size.x(), bbox_size.y()) / min_spacing + 1;
|
||||||
|
Polygons polygons = offset(expolygon, float(min_spacing) / 2.f);
|
||||||
|
|
||||||
|
double min_nozzle_diameter = *std::min_element(print_config->nozzle_diameter.values.begin(), print_config->nozzle_diameter.values.end());
|
||||||
|
Arachne::WallToolPathsParams input_params;
|
||||||
|
input_params.min_bead_width = 0.85 * min_nozzle_diameter;
|
||||||
|
input_params.min_feature_size = 0.1;
|
||||||
|
input_params.wall_transition_length = 1.0 * min_nozzle_diameter;
|
||||||
|
input_params.wall_transition_angle = 10;
|
||||||
|
input_params.wall_transition_filter_deviation = 0.25 * min_nozzle_diameter;
|
||||||
|
input_params.wall_distribution_count = 1;
|
||||||
|
input_params.wall_add_middle_threshold = 0.75;
|
||||||
|
input_params.wall_split_middle_threshold = 0.5;
|
||||||
|
|
||||||
|
Arachne::WallToolPaths wallToolPaths(polygons, min_spacing, min_spacing, loops_count, 0, input_params);
|
||||||
|
|
||||||
|
std::vector<Arachne::VariableWidthLines> loops = wallToolPaths.getToolPaths();
|
||||||
|
std::vector<const Arachne::ExtrusionLine*> all_extrusions;
|
||||||
|
for (Arachne::VariableWidthLines& loop : loops) {
|
||||||
|
if (loop.empty())
|
||||||
|
continue;
|
||||||
|
for (const Arachne::ExtrusionLine& wall : loop)
|
||||||
|
all_extrusions.emplace_back(&wall);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split paths using a nearest neighbor search.
|
||||||
|
size_t firts_poly_idx = thick_polylines_out.size();
|
||||||
|
Point last_pos(0, 0);
|
||||||
|
for (const Arachne::ExtrusionLine* extrusion : all_extrusions) {
|
||||||
|
if (extrusion->empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
|
||||||
|
if (extrusion->is_closed && thick_polyline.points.front() == thick_polyline.points.back() && thick_polyline.width.front() == thick_polyline.width.back()) {
|
||||||
|
thick_polyline.points.pop_back();
|
||||||
|
assert(thick_polyline.points.size() * 2 == thick_polyline.width.size());
|
||||||
|
int nearest_idx = last_pos.nearest_point_index(thick_polyline.points);
|
||||||
|
std::rotate(thick_polyline.points.begin(), thick_polyline.points.begin() + nearest_idx, thick_polyline.points.end());
|
||||||
|
std::rotate(thick_polyline.width.begin(), thick_polyline.width.begin() + 2 * nearest_idx, thick_polyline.width.end());
|
||||||
|
thick_polyline.points.emplace_back(thick_polyline.points.front());
|
||||||
|
}
|
||||||
|
thick_polylines_out.emplace_back(std::move(thick_polyline));
|
||||||
|
last_pos = thick_polylines_out.back().last_point();
|
||||||
|
}
|
||||||
|
|
||||||
|
// clip the paths to prevent the extruder from getting exactly on the first point of the loop
|
||||||
|
// Keep valid paths only.
|
||||||
|
size_t j = firts_poly_idx;
|
||||||
|
for (size_t i = firts_poly_idx; i < thick_polylines_out.size(); ++i) {
|
||||||
|
thick_polylines_out[i].clip_end(this->loop_clipping);
|
||||||
|
if (thick_polylines_out[i].is_valid()) {
|
||||||
|
if (j < i)
|
||||||
|
thick_polylines_out[j] = std::move(thick_polylines_out[i]);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < thick_polylines_out.size())
|
||||||
|
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Polylines polylines;
|
||||||
|
this->_fill_surface_single(params, thickness_layers, direction, expolygon, polylines);
|
||||||
|
append(thick_polylines_out, to_thick_polylines(std::move(polylines), min_spacing));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -19,7 +19,18 @@ protected:
|
||||||
ExPolygon expolygon,
|
ExPolygon expolygon,
|
||||||
Polylines &polylines_out) override;
|
Polylines &polylines_out) override;
|
||||||
|
|
||||||
|
void _fill_surface_single(const FillParams& params,
|
||||||
|
unsigned int thickness_layers,
|
||||||
|
const std::pair<float, Point>& direction,
|
||||||
|
ExPolygon expolygon,
|
||||||
|
ThickPolylines& thick_polylines_out) override;
|
||||||
|
|
||||||
bool no_sort() const override { return true; }
|
bool no_sort() const override { return true; }
|
||||||
|
|
||||||
|
const PrintConfig* print_config = nullptr;
|
||||||
|
const PrintObjectConfig* print_object_config = nullptr;
|
||||||
|
|
||||||
|
friend class Layer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
#include "../ClipperUtils.hpp"
|
|
||||||
#include "../ExPolygon.hpp"
|
|
||||||
#include "../Surface.hpp"
|
|
||||||
#include "../VariableWidth.hpp"
|
|
||||||
#include "../ShortestPath.hpp"
|
|
||||||
|
|
||||||
#include "FillConcentricWGapFill.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
const float concentric_overlap_threshold = 0.02;
|
|
||||||
|
|
||||||
void FillConcentricWGapFill::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out)
|
|
||||||
{
|
|
||||||
//BBS: FillConcentricWGapFill.cpp is absolutely newly add by BBL for narrow internal solid infill area to reduce vibration
|
|
||||||
// Because the area is narrow, we should not use the surface->expolygon which has overlap with perimeter, but
|
|
||||||
// use no_overlap_expolygons instead to avoid overflow in narrow area.
|
|
||||||
//Slic3r::ExPolygons expp = offset_ex(surface->expolygon, double(scale_(0 - 0.5 * this->spacing)));
|
|
||||||
float min_spacing = this->spacing * (1 - concentric_overlap_threshold);
|
|
||||||
Slic3r::ExPolygons expp = offset2_ex(this->no_overlap_expolygons, -double(scale_(0.5 * this->spacing + 0.5 * min_spacing) - 1),
|
|
||||||
+double(scale_(0.5 * min_spacing) - 1));
|
|
||||||
// Create the infills for each of the regions.
|
|
||||||
Polylines polylines_out;
|
|
||||||
for (size_t i = 0; i < expp.size(); ++i) {
|
|
||||||
ExPolygon expolygon = expp[i];
|
|
||||||
|
|
||||||
coord_t distance = scale_(this->spacing / params.density);
|
|
||||||
if (params.density > 0.9999f && !params.dont_adjust) {
|
|
||||||
distance = scale_(this->spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExPolygons gaps;
|
|
||||||
Polygons loops = (Polygons)expolygon;
|
|
||||||
ExPolygons last = { expolygon };
|
|
||||||
bool first = true;
|
|
||||||
while (!last.empty()) {
|
|
||||||
ExPolygons next_onion = offset2_ex(last, -double(distance + scale_(this->spacing) / 2), +double(scale_(this->spacing) / 2));
|
|
||||||
for (auto it = next_onion.begin(); it != next_onion.end(); it++) {
|
|
||||||
Polygons temp_loops = (Polygons)(*it);
|
|
||||||
loops.insert(loops.end(), temp_loops.begin(), temp_loops.end());
|
|
||||||
}
|
|
||||||
append(gaps, diff_ex(
|
|
||||||
offset(last, -0.5f * distance),
|
|
||||||
offset(next_onion, 0.5f * distance + 10))); // 10 is safty offset
|
|
||||||
last = next_onion;
|
|
||||||
if (first && !this->no_overlap_expolygons.empty()) {
|
|
||||||
gaps = intersection_ex(gaps, this->no_overlap_expolygons);
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtrusionRole good_role = params.extrusion_role;
|
|
||||||
ExtrusionEntityCollection *coll_nosort = new ExtrusionEntityCollection();
|
|
||||||
coll_nosort->no_sort = this->no_sort(); //can be sorted inside the pass
|
|
||||||
extrusion_entities_append_loops(
|
|
||||||
coll_nosort->entities, std::move(loops),
|
|
||||||
good_role,
|
|
||||||
params.flow.mm3_per_mm(),
|
|
||||||
params.flow.width(),
|
|
||||||
params.flow.height());
|
|
||||||
|
|
||||||
//BBS: add internal gapfills between infill loops
|
|
||||||
if (!gaps.empty() && params.density >= 1) {
|
|
||||||
double min = 0.2 * distance * (1 - INSET_OVERLAP_TOLERANCE);
|
|
||||||
double max = 2. * distance;
|
|
||||||
ExPolygons gaps_ex = diff_ex(
|
|
||||||
offset2_ex(gaps, -float(min / 2), float(min / 2)),
|
|
||||||
offset2_ex(gaps, -float(max / 2), float(max / 2)),
|
|
||||||
ApplySafetyOffset::Yes);
|
|
||||||
//BBS: sort the gap_ex to avoid mess travel
|
|
||||||
Points ordering_points;
|
|
||||||
ordering_points.reserve(gaps_ex.size());
|
|
||||||
ExPolygons gaps_ex_sorted;
|
|
||||||
gaps_ex_sorted.reserve(gaps_ex.size());
|
|
||||||
for (const ExPolygon &ex : gaps_ex)
|
|
||||||
ordering_points.push_back(ex.contour.first_point());
|
|
||||||
std::vector<Points::size_type> order = chain_points(ordering_points);
|
|
||||||
for (size_t i : order)
|
|
||||||
gaps_ex_sorted.emplace_back(std::move(gaps_ex[i]));
|
|
||||||
|
|
||||||
ThickPolylines polylines;
|
|
||||||
for (ExPolygon& ex : gaps_ex_sorted) {
|
|
||||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
|
||||||
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
|
||||||
ex.medial_axis(max, min, &polylines);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!polylines.empty() && !is_bridge(good_role)) {
|
|
||||||
ExtrusionEntityCollection gap_fill;
|
|
||||||
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
|
|
||||||
coll_nosort->append(std::move(gap_fill.entities));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!coll_nosort->entities.empty())
|
|
||||||
out.push_back(coll_nosort);
|
|
||||||
else
|
|
||||||
delete coll_nosort;
|
|
||||||
}
|
|
||||||
|
|
||||||
//BBS: add external gapfill between perimeter and infill
|
|
||||||
ExPolygons external_gaps = diff_ex(this->no_overlap_expolygons, offset_ex(expp, double(scale_(0.5 * this->spacing))), ApplySafetyOffset::Yes);
|
|
||||||
external_gaps = union_ex(external_gaps);
|
|
||||||
if (!this->no_overlap_expolygons.empty())
|
|
||||||
external_gaps = intersection_ex(external_gaps, this->no_overlap_expolygons);
|
|
||||||
|
|
||||||
if (!external_gaps.empty()) {
|
|
||||||
double min = 0.4 * scale_(params.flow.nozzle_diameter()) * (1 - INSET_OVERLAP_TOLERANCE);
|
|
||||||
double max = 2. * params.flow.scaled_width();
|
|
||||||
//BBS: collapse, be sure we don't gapfill where the perimeters are already touching each other (negative spacing).
|
|
||||||
min = std::max(min, (double)Flow::rounded_rectangle_extrusion_width_from_spacing((float)EPSILON, (float)params.flow.height()));
|
|
||||||
ExPolygons external_gaps_collapsed = offset2_ex(external_gaps, double(-min / 2), double(+min / 2));
|
|
||||||
|
|
||||||
ThickPolylines polylines;
|
|
||||||
for (ExPolygon& ex : external_gaps_collapsed) {
|
|
||||||
//BBS: Use DP simplify to avoid duplicated points and accelerate medial-axis calculation as well.
|
|
||||||
ex.douglas_peucker(SCALED_RESOLUTION * 0.1);
|
|
||||||
ex.medial_axis(max, min, &polylines);
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtrusionEntityCollection* coll_external_gapfill = new ExtrusionEntityCollection();
|
|
||||||
coll_external_gapfill->no_sort = this->no_sort();
|
|
||||||
if (!polylines.empty() && !is_bridge(params.extrusion_role)) {
|
|
||||||
ExtrusionEntityCollection gap_fill;
|
|
||||||
variable_width(polylines, erGapFill, params.flow, gap_fill.entities);
|
|
||||||
coll_external_gapfill->append(std::move(gap_fill.entities));
|
|
||||||
}
|
|
||||||
if (!coll_external_gapfill->entities.empty())
|
|
||||||
out.push_back(coll_external_gapfill);
|
|
||||||
else
|
|
||||||
delete coll_external_gapfill;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
#ifndef slic3r_FillConcentricWGapFil_hpp_
|
|
||||||
#define slic3r_FillConcentricWGapFil_hpp_
|
|
||||||
|
|
||||||
#include "FillBase.hpp"
|
|
||||||
|
|
||||||
namespace Slic3r {
|
|
||||||
|
|
||||||
class FillConcentricWGapFill : public Fill
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
~FillConcentricWGapFill() override = default;
|
|
||||||
void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Fill* clone() const override { return new FillConcentricWGapFill(*this); };
|
|
||||||
bool no_sort() const override { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Slic3r
|
|
||||||
|
|
||||||
#endif // slic3r_FillConcentricWGapFil_hpp_
|
|
|
@ -239,6 +239,18 @@ public:
|
||||||
std::pair<bool,bool> endpoints;
|
std::pair<bool,bool> endpoints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline ThickPolylines to_thick_polylines(Polylines&& polylines, const coordf_t width)
|
||||||
|
{
|
||||||
|
ThickPolylines out;
|
||||||
|
out.reserve(polylines.size());
|
||||||
|
for (Polyline& polyline : polylines) {
|
||||||
|
out.emplace_back();
|
||||||
|
out.back().width.assign((polyline.points.size() - 1) * 2, width);
|
||||||
|
out.back().points = std::move(polyline.points);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
class Polyline3 : public MultiPoint3
|
class Polyline3 : public MultiPoint3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -46,7 +46,7 @@ enum class FuzzySkinType {
|
||||||
|
|
||||||
enum InfillPattern : int {
|
enum InfillPattern : int {
|
||||||
ipConcentric, ipRectilinear, ipGrid, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
|
ipConcentric, ipRectilinear, ipGrid, ipLine, ipCubic, ipTriangles, ipStars, ipGyroid, ipHoneycomb, ipAdaptiveCubic, ipMonotonic, ipMonotonicLine, ipAlignedRectilinear, ip3DHoneycomb,
|
||||||
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricGapFill, ipConcentricInternal,
|
ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipSupportCubic, ipSupportBase, ipConcentricInternal,
|
||||||
#if HAS_LIGHTNING_INFILL
|
#if HAS_LIGHTNING_INFILL
|
||||||
ipLightning,
|
ipLightning,
|
||||||
#endif // HAS_LIGHTNING_INFILL
|
#endif // HAS_LIGHTNING_INFILL
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue