Follow-up to ee626eb65a
Refactored PerimeterGenerator for functional style, better constness with the goal of calling PerimeterGenerator::process_xxx() for each surface at once to collect its fill expolygons.
This commit is contained in:
parent
715a603ab4
commit
237e56c7ce
@ -268,13 +268,13 @@ void extrusion_paths_append(ExtrusionPaths &dst, const ClipperLib_Z::Paths &extr
|
||||
{
|
||||
for (const ClipperLib_Z::Path &extrusion_path : extrusion_paths) {
|
||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion_path);
|
||||
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
|
||||
Slic3r::append(dst, PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
|
||||
}
|
||||
}
|
||||
|
||||
void extrusion_paths_append(ExtrusionPaths &dst, const Arachne::ExtrusionLine &extrusion, const ExtrusionRole role, const Flow &flow)
|
||||
{
|
||||
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
|
||||
Slic3r::append(dst, thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
|
||||
Slic3r::append(dst, PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, role, flow, scaled<float>(0.05), float(SCALED_EPSILON)).paths);
|
||||
}
|
||||
} // namespace Slic3r
|
@ -8,6 +8,7 @@
|
||||
#include "../Print.hpp"
|
||||
#include "../PrintConfig.hpp"
|
||||
#include "../Surface.hpp"
|
||||
// for Arachne based infills
|
||||
#include "../PerimeterGenerator.hpp"
|
||||
|
||||
#include "FillBase.hpp"
|
||||
@ -427,7 +428,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
for (const ThickPolyline &thick_polyline : thick_polylines) {
|
||||
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
||||
|
||||
ExtrusionMultiPath multi_path = thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), float(SCALED_EPSILON));
|
||||
ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), float(SCALED_EPSILON));
|
||||
// Append paths to collection.
|
||||
if (!multi_path.empty()) {
|
||||
if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
|
||||
|
@ -72,35 +72,46 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||
(this->layer()->id() >= size_t(region_config.bottom_solid_layers.value) &&
|
||||
this->layer()->print_z >= region_config.bottom_solid_min_thickness - EPSILON);
|
||||
|
||||
PerimeterGenerator g(
|
||||
// input:
|
||||
&slices,
|
||||
PerimeterGenerator::Parameters params(
|
||||
this->layer()->height,
|
||||
int(this->layer()->id()),
|
||||
this->flow(frPerimeter),
|
||||
®ion_config,
|
||||
&this->layer()->object()->config(),
|
||||
&print_config,
|
||||
spiral_vase,
|
||||
|
||||
// output:
|
||||
&m_perimeters,
|
||||
&m_thin_fills,
|
||||
fill_surfaces
|
||||
this->flow(frExternalPerimeter),
|
||||
this->bridging_flow(frPerimeter),
|
||||
this->flow(frSolidInfill),
|
||||
region_config,
|
||||
this->layer()->object()->config(),
|
||||
print_config,
|
||||
spiral_vase
|
||||
);
|
||||
|
||||
if (this->layer()->lower_layer != nullptr)
|
||||
// Cummulative sum of polygons over all the regions.
|
||||
g.lower_slices = &this->layer()->lower_layer->lslices;
|
||||
|
||||
g.layer_id = (int)this->layer()->id();
|
||||
g.ext_perimeter_flow = this->flow(frExternalPerimeter);
|
||||
g.overhang_flow = this->bridging_flow(frPerimeter);
|
||||
g.solid_infill_flow = this->flow(frSolidInfill);
|
||||
|
||||
// Cummulative sum of polygons over all the regions.
|
||||
const ExPolygons *lower_slices = this->layer()->lower_layer ? &this->layer()->lower_layer->lslices : nullptr;
|
||||
// Cache for offsetted lower_slices
|
||||
Polygons lower_layer_polygons_cache;
|
||||
|
||||
if (this->layer()->object()->config().perimeter_generator.value == PerimeterGeneratorType::Arachne && !spiral_vase)
|
||||
g.process_arachne();
|
||||
PerimeterGenerator::process_arachne(
|
||||
// input:
|
||||
params,
|
||||
&slices,
|
||||
lower_slices,
|
||||
lower_layer_polygons_cache,
|
||||
// output:
|
||||
m_perimeters,
|
||||
m_thin_fills,
|
||||
*fill_surfaces);
|
||||
else
|
||||
g.process_classic();
|
||||
PerimeterGenerator::process_classic(
|
||||
// input:
|
||||
params,
|
||||
&slices,
|
||||
lower_slices,
|
||||
lower_layer_polygons_cache,
|
||||
// output:
|
||||
m_perimeters,
|
||||
m_thin_fills,
|
||||
*fill_surfaces);
|
||||
}
|
||||
|
||||
//#define EXTERNAL_SURFACES_OFFSET_PARAMETERS ClipperLib::jtMiter, 3.
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
|
||||
ExtrusionMultiPath PerimeterGenerator::thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, const float tolerance, const float merge_tolerance)
|
||||
{
|
||||
ExtrusionMultiPath multi_path;
|
||||
ExtrusionPath path(role);
|
||||
@ -121,7 +121,7 @@ static void variable_width(const ThickPolylines &polylines, ExtrusionRole role,
|
||||
// of segments, and any pruning shall be performed before we apply this tolerance.
|
||||
const auto tolerance = float(scale_(0.05));
|
||||
for (const ThickPolyline &p : polylines) {
|
||||
ExtrusionMultiPath multi_path = thick_polyline_to_multi_path(p, role, flow, tolerance, tolerance);
|
||||
ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(p, role, flow, tolerance, tolerance);
|
||||
// Append paths to collection.
|
||||
if (!multi_path.paths.empty()) {
|
||||
for (auto it = std::next(multi_path.paths.begin()); it != multi_path.paths.end(); ++it) {
|
||||
@ -157,7 +157,15 @@ public:
|
||||
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
||||
bool is_external() const { return this->depth == 0; }
|
||||
// An island, which may have holes, but it does not have another internal island.
|
||||
bool is_internal_contour() const;
|
||||
bool is_internal_contour() const {
|
||||
// An internal contour is a contour containing no other contours
|
||||
if (! this->is_contour)
|
||||
return false;
|
||||
for (const PerimeterGeneratorLoop &loop : this->children)
|
||||
if (loop.is_contour)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Thanks Cura developers for this function.
|
||||
@ -243,7 +251,7 @@ static void fuzzy_extrusion_line(Arachne::ExtrusionLine &ext_lines, double fuzzy
|
||||
|
||||
using PerimeterGeneratorLoops = std::vector<PerimeterGeneratorLoop>;
|
||||
|
||||
static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perimeter_generator, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls)
|
||||
static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls)
|
||||
{
|
||||
// loops is an arrayref of ::Loop objects
|
||||
// turn each one into an ExtrusionLoop object
|
||||
@ -269,30 +277,30 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
const Polygon &polygon = loop.fuzzify ? fuzzified : loop.polygon;
|
||||
if (loop.fuzzify) {
|
||||
fuzzified = loop.polygon;
|
||||
fuzzy_polygon(fuzzified, scaled<float>(perimeter_generator.config->fuzzy_skin_thickness.value), scaled<float>(perimeter_generator.config->fuzzy_skin_point_dist.value));
|
||||
fuzzy_polygon(fuzzified, scaled<float>(params.config.fuzzy_skin_thickness.value), scaled<float>(params.config.fuzzy_skin_point_dist.value));
|
||||
}
|
||||
if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers
|
||||
&& ! ((perimeter_generator.object_config->support_material || perimeter_generator.object_config->support_material_enforce_layers > 0) &&
|
||||
perimeter_generator.object_config->support_material_contact_distance.value == 0)) {
|
||||
if (params.config.overhangs && params.layer_id > params.object_config.raft_layers
|
||||
&& ! ((params.object_config.support_material || params.object_config.support_material_enforce_layers > 0) &&
|
||||
params.object_config.support_material_contact_distance.value == 0)) {
|
||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
intersection_pl({ polygon }, perimeter_generator.lower_slices_polygons()),
|
||||
intersection_pl({ polygon }, lower_slices_polygons_cache),
|
||||
role,
|
||||
is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm(),
|
||||
is_external ? perimeter_generator.ext_perimeter_flow.width() : perimeter_generator.perimeter_flow.width(),
|
||||
(float)perimeter_generator.layer_height);
|
||||
is_external ? params.ext_mm3_per_mm : params.mm3_per_mm,
|
||||
is_external ? params.ext_perimeter_flow.width() : params.perimeter_flow.width(),
|
||||
float(params.layer_height));
|
||||
|
||||
// get overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices (thus where the distance between
|
||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||
extrusion_paths_append(
|
||||
paths,
|
||||
diff_pl({ polygon }, perimeter_generator.lower_slices_polygons()),
|
||||
diff_pl({ polygon }, lower_slices_polygons_cache),
|
||||
erOverhangPerimeter,
|
||||
perimeter_generator.mm3_per_mm_overhang(),
|
||||
perimeter_generator.overhang_flow.width(),
|
||||
perimeter_generator.overhang_flow.height());
|
||||
params.mm3_per_mm_overhang,
|
||||
params.overhang_flow.width(),
|
||||
params.overhang_flow.height());
|
||||
|
||||
// Reapply the nearest point search for starting point.
|
||||
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
|
||||
@ -300,9 +308,9 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
} else {
|
||||
ExtrusionPath path(role);
|
||||
path.polyline = polygon.split_at_first_point();
|
||||
path.mm3_per_mm = is_external ? perimeter_generator.ext_mm3_per_mm() : perimeter_generator.mm3_per_mm();
|
||||
path.width = is_external ? perimeter_generator.ext_perimeter_flow.width() : perimeter_generator.perimeter_flow.width();
|
||||
path.height = (float)perimeter_generator.layer_height;
|
||||
path.mm3_per_mm = is_external ? params.ext_mm3_per_mm : params.mm3_per_mm;
|
||||
path.width = is_external ? params.ext_perimeter_flow.width() : params.perimeter_flow.width();
|
||||
path.height = float(params.layer_height);
|
||||
paths.push_back(path);
|
||||
}
|
||||
|
||||
@ -311,7 +319,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
|
||||
// Append thin walls to the nearest-neighbor search (only for first iteration)
|
||||
if (! thin_walls.empty()) {
|
||||
variable_width(thin_walls, erExternalPerimeter, perimeter_generator.ext_perimeter_flow, coll.entities);
|
||||
variable_width(thin_walls, erExternalPerimeter, params.ext_perimeter_flow, coll.entities);
|
||||
thin_walls.clear();
|
||||
}
|
||||
|
||||
@ -331,7 +339,7 @@ static ExtrusionEntityCollection traverse_loops(const PerimeterGenerator &perime
|
||||
} else {
|
||||
const PerimeterGeneratorLoop &loop = loops[idx.first];
|
||||
assert(thin_walls.empty());
|
||||
ExtrusionEntityCollection children = traverse_loops(perimeter_generator, loop.children, thin_walls);
|
||||
ExtrusionEntityCollection children = traverse_loops(params, lower_slices_polygons_cache, loop.children, thin_walls);
|
||||
out.entities.reserve(out.entities.size() + children.entities.size() + 1);
|
||||
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
|
||||
coll.entities[idx.first] = nullptr;
|
||||
@ -436,7 +444,7 @@ struct PerimeterGeneratorArachneExtrusion
|
||||
bool fuzzify = false;
|
||||
};
|
||||
|
||||
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &perimeter_generator, std::vector<PerimeterGeneratorArachneExtrusion> &pg_extrusions)
|
||||
static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator::Parameters ¶ms, const Polygons &lower_slices_polygons_cache, std::vector<PerimeterGeneratorArachneExtrusion> &pg_extrusions)
|
||||
{
|
||||
ExtrusionEntityCollection extrusion_coll;
|
||||
for (PerimeterGeneratorArachneExtrusion &pg_extrusion : pg_extrusions) {
|
||||
@ -448,13 +456,13 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
||||
ExtrusionRole role = is_external ? erExternalPerimeter : erPerimeter;
|
||||
|
||||
if (pg_extrusion.fuzzify)
|
||||
fuzzy_extrusion_line(*extrusion, scaled<float>(perimeter_generator.config->fuzzy_skin_thickness.value), scaled<float>(perimeter_generator.config->fuzzy_skin_point_dist.value));
|
||||
fuzzy_extrusion_line(*extrusion, scaled<float>(params.config.fuzzy_skin_thickness.value), scaled<float>(params.config.fuzzy_skin_point_dist.value));
|
||||
|
||||
ExtrusionPaths paths;
|
||||
// detect overhanging/bridging perimeters
|
||||
if (perimeter_generator.config->overhangs && perimeter_generator.layer_id > perimeter_generator.object_config->raft_layers
|
||||
&& ! ((perimeter_generator.object_config->support_material || perimeter_generator.object_config->support_material_enforce_layers > 0) &&
|
||||
perimeter_generator.object_config->support_material_contact_distance.value == 0)) {
|
||||
if (params.config.overhangs && params.layer_id > params.object_config.raft_layers
|
||||
&& ! ((params.object_config.support_material || params.object_config.support_material_enforce_layers > 0) &&
|
||||
params.object_config.support_material_contact_distance.value == 0)) {
|
||||
|
||||
ClipperLib_Z::Path extrusion_path;
|
||||
extrusion_path.reserve(extrusion->size());
|
||||
@ -462,8 +470,8 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
||||
extrusion_path.emplace_back(ej.p.x(), ej.p.y(), ej.w);
|
||||
|
||||
ClipperLib_Z::Paths lower_slices_paths;
|
||||
lower_slices_paths.reserve(perimeter_generator.lower_slices_polygons().size());
|
||||
for (const Polygon &poly : perimeter_generator.lower_slices_polygons()) {
|
||||
lower_slices_paths.reserve(lower_slices_polygons_cache.size());
|
||||
for (const Polygon &poly : lower_slices_polygons_cache) {
|
||||
lower_slices_paths.emplace_back();
|
||||
ClipperLib_Z::Path &out = lower_slices_paths.back();
|
||||
out.reserve(poly.points.size());
|
||||
@ -473,13 +481,13 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
||||
|
||||
// get non-overhang paths by intersecting this loop with the grown lower slices
|
||||
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctIntersection), role,
|
||||
is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow);
|
||||
is_external ? params.ext_perimeter_flow : params.perimeter_flow);
|
||||
|
||||
// get overhang paths by checking what parts of this loop fall
|
||||
// outside the grown lower slices (thus where the distance between
|
||||
// the loop centerline and original lower slices is >= half nozzle diameter
|
||||
extrusion_paths_append(paths, clip_extrusion(extrusion_path, lower_slices_paths, ClipperLib_Z::ctDifference), erOverhangPerimeter,
|
||||
perimeter_generator.overhang_flow);
|
||||
params.overhang_flow);
|
||||
|
||||
// Reapply the nearest point search for starting point.
|
||||
// We allow polyline reversal because Clipper may have randomly reversed polylines during clipping.
|
||||
@ -519,7 +527,7 @@ static ExtrusionEntityCollection traverse_extrusions(const PerimeterGenerator &p
|
||||
chain_and_reorder_extrusion_paths(paths, &start_point);
|
||||
}
|
||||
} else {
|
||||
extrusion_paths_append(paths, *extrusion, role, is_external ? perimeter_generator.ext_perimeter_flow : perimeter_generator.perimeter_flow);
|
||||
extrusion_paths_append(paths, *extrusion, role, is_external ? params.ext_perimeter_flow : params.perimeter_flow);
|
||||
}
|
||||
|
||||
// Append paths to collection.
|
||||
@ -590,42 +598,48 @@ static void export_perimeters_to_svg(const std::string &path, const Polygons &co
|
||||
|
||||
// Thanks, Cura developers, for implementing an algorithm for generating perimeters with variable width (Arachne) that is based on the paper
|
||||
// "A framework for adaptive width control of dense contour-parallel toolpaths in fused deposition modeling"
|
||||
void PerimeterGenerator::process_arachne()
|
||||
void PerimeterGenerator::process_arachne(
|
||||
// Inputs:
|
||||
const Parameters ¶ms,
|
||||
const SurfaceCollection *slices,
|
||||
const ExPolygons *lower_slices,
|
||||
// Cache:
|
||||
Polygons &lower_slices_polygons_cache,
|
||||
// Output:
|
||||
// Loops with the external thin walls
|
||||
ExtrusionEntityCollection &out_loops,
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces)
|
||||
{
|
||||
// other perimeters
|
||||
m_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
||||
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
|
||||
|
||||
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
||||
// external perimeters
|
||||
m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
|
||||
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
|
||||
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
|
||||
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
|
||||
|
||||
// overhang perimeters
|
||||
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
|
||||
|
||||
coord_t ext_perimeter_width = params.ext_perimeter_flow.scaled_width();
|
||||
coord_t ext_perimeter_spacing = params.ext_perimeter_flow.scaled_spacing();
|
||||
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
|
||||
// solid infill
|
||||
coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing();
|
||||
coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing();
|
||||
|
||||
// prepare grown lower layer slices for overhang detection
|
||||
if (this->lower_slices != nullptr && this->config->overhangs) {
|
||||
if (lower_slices != nullptr && params.config.overhangs) {
|
||||
// We consider overhang any part where the entire nozzle diameter is not supported by the
|
||||
// lower layer, so we take lower slices and offset them by half the nozzle diameter used
|
||||
// in the current layer
|
||||
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder-1);
|
||||
m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter/2)));
|
||||
double nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder-1);
|
||||
lower_slices_polygons_cache = offset(*lower_slices, float(scale_(+nozzle_diameter/2)));
|
||||
}
|
||||
|
||||
// we need to process each island separately because we might have different
|
||||
// extra perimeters for each one
|
||||
for (const Surface &surface : this->slices->surfaces) {
|
||||
for (const Surface &surface : slices->surfaces) {
|
||||
// detect how many perimeters must be generated for this island
|
||||
int loop_number = this->config->perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
ExPolygons last = offset_ex(surface.expolygon.simplify_p(m_scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
||||
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
ExPolygons last = offset_ex(surface.expolygon.simplify_p(params.scaled_resolution), - float(ext_perimeter_width / 2. - ext_perimeter_spacing / 2.));
|
||||
Polygons last_p = to_polygons(last);
|
||||
|
||||
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, layer_height, *this->object_config, *this->print_config);
|
||||
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, coord_t(loop_number + 1), 0, params.layer_height, params.object_config, params.print_config);
|
||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||
loop_number = int(perimeters.size()) - 1;
|
||||
|
||||
@ -651,7 +665,7 @@ void PerimeterGenerator::process_arachne()
|
||||
int end_perimeter = -1;
|
||||
int direction = -1;
|
||||
|
||||
if (this->config->external_perimeters_first) {
|
||||
if (params.config.external_perimeters_first) {
|
||||
start_perimeter = 0;
|
||||
end_perimeter = int(perimeters.size());
|
||||
direction = 1;
|
||||
@ -672,7 +686,7 @@ void PerimeterGenerator::process_arachne()
|
||||
for (size_t idx = 0; idx < all_extrusions.size(); idx++)
|
||||
map_extrusion_to_idx.emplace(all_extrusions[idx], idx);
|
||||
|
||||
auto extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, this->config->external_perimeters_first);
|
||||
auto extrusions_constrains = Arachne::WallToolPaths::getRegionOrder(all_extrusions, params.config.external_perimeters_first);
|
||||
for (auto [before, after] : extrusions_constrains) {
|
||||
auto after_it = map_extrusion_to_idx.find(after);
|
||||
++blocked[after_it->second];
|
||||
@ -736,18 +750,18 @@ void PerimeterGenerator::process_arachne()
|
||||
}
|
||||
}
|
||||
|
||||
if (this->layer_id > 0 && this->config->fuzzy_skin != FuzzySkinType::None) {
|
||||
if (params.layer_id > 0 && params.config.fuzzy_skin != FuzzySkinType::None) {
|
||||
std::vector<PerimeterGeneratorArachneExtrusion *> closed_loop_extrusions;
|
||||
for (PerimeterGeneratorArachneExtrusion &extrusion : ordered_extrusions)
|
||||
if (extrusion.extrusion->inset_idx == 0) {
|
||||
if (extrusion.extrusion->is_closed && this->config->fuzzy_skin == FuzzySkinType::External) {
|
||||
if (extrusion.extrusion->is_closed && params.config.fuzzy_skin == FuzzySkinType::External) {
|
||||
closed_loop_extrusions.emplace_back(&extrusion);
|
||||
} else {
|
||||
extrusion.fuzzify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->config->fuzzy_skin == FuzzySkinType::External) {
|
||||
if (params.config.fuzzy_skin == FuzzySkinType::External) {
|
||||
ClipperLib_Z::Paths loops_paths;
|
||||
loops_paths.reserve(closed_loop_extrusions.size());
|
||||
for (const auto &cl_extrusion : closed_loop_extrusions) {
|
||||
@ -776,8 +790,8 @@ void PerimeterGenerator::process_arachne()
|
||||
}
|
||||
}
|
||||
|
||||
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty())
|
||||
this->loops->append(extrusion_coll);
|
||||
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(params, lower_slices_polygons_cache, ordered_extrusions); !extrusion_coll.empty())
|
||||
out_loops.append(extrusion_coll);
|
||||
|
||||
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
|
||||
const coord_t spacing = (perimeters.size() == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
|
||||
@ -796,14 +810,14 @@ void PerimeterGenerator::process_arachne()
|
||||
// two or more loops?
|
||||
perimeter_spacing;
|
||||
|
||||
inset = coord_t(scale_(this->config->get_abs_value("infill_overlap", unscale<double>(inset))));
|
||||
inset = coord_t(scale_(params.config.get_abs_value("infill_overlap", unscale<double>(inset))));
|
||||
Polygons pp;
|
||||
for (ExPolygon &ex : infill_contour)
|
||||
ex.simplify_p(m_scaled_resolution, &pp);
|
||||
ex.simplify_p(params.scaled_resolution, &pp);
|
||||
// collapse too narrow infill areas
|
||||
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
// append infill areas to fill_surfaces
|
||||
this->fill_surfaces->append(
|
||||
out_fill_surfaces.append(
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- min_perimeter_infill_spacing / 2.),
|
||||
@ -812,24 +826,30 @@ void PerimeterGenerator::process_arachne()
|
||||
}
|
||||
}
|
||||
|
||||
void PerimeterGenerator::process_classic()
|
||||
void PerimeterGenerator::process_classic(
|
||||
// Inputs:
|
||||
const Parameters ¶ms,
|
||||
const SurfaceCollection *slices,
|
||||
const ExPolygons *lower_slices,
|
||||
// Cache:
|
||||
Polygons &lower_slices_polygons_cache,
|
||||
// Output:
|
||||
// Loops with the external thin walls
|
||||
ExtrusionEntityCollection &out_loops,
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces)
|
||||
{
|
||||
// other perimeters
|
||||
m_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
||||
coord_t perimeter_width = this->perimeter_flow.scaled_width();
|
||||
coord_t perimeter_spacing = this->perimeter_flow.scaled_spacing();
|
||||
|
||||
coord_t perimeter_width = params.perimeter_flow.scaled_width();
|
||||
coord_t perimeter_spacing = params.perimeter_flow.scaled_spacing();
|
||||
// external perimeters
|
||||
m_ext_mm3_per_mm = this->ext_perimeter_flow.mm3_per_mm();
|
||||
coord_t ext_perimeter_width = this->ext_perimeter_flow.scaled_width();
|
||||
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
|
||||
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (this->ext_perimeter_flow.spacing() + this->perimeter_flow.spacing()));
|
||||
|
||||
// overhang perimeters
|
||||
m_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
|
||||
|
||||
coord_t ext_perimeter_width = params.ext_perimeter_flow.scaled_width();
|
||||
coord_t ext_perimeter_spacing = params.ext_perimeter_flow.scaled_spacing();
|
||||
coord_t ext_perimeter_spacing2 = scaled<coord_t>(0.5f * (params.ext_perimeter_flow.spacing() + params.perimeter_flow.spacing()));
|
||||
// solid infill
|
||||
coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing();
|
||||
coord_t solid_infill_spacing = params.solid_infill_flow.scaled_spacing();
|
||||
|
||||
// Calculate the minimum required spacing between two adjacent traces.
|
||||
// This should be equal to the nominal flow spacing but we experiment
|
||||
@ -843,23 +863,23 @@ void PerimeterGenerator::process_classic()
|
||||
// internal flow which is unrelated.
|
||||
coord_t min_spacing = coord_t(perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
|
||||
coord_t ext_min_spacing = coord_t(ext_perimeter_spacing * (1 - INSET_OVERLAP_TOLERANCE));
|
||||
bool has_gap_fill = this->config->gap_fill_enabled.value && this->config->gap_fill_speed.value > 0;
|
||||
bool has_gap_fill = params.config.gap_fill_enabled.value && params.config.gap_fill_speed.value > 0;
|
||||
|
||||
// prepare grown lower layer slices for overhang detection
|
||||
if (this->lower_slices != NULL && this->config->overhangs) {
|
||||
if (lower_slices != nullptr && params.config.overhangs) {
|
||||
// We consider overhang any part where the entire nozzle diameter is not supported by the
|
||||
// lower layer, so we take lower slices and offset them by half the nozzle diameter used
|
||||
// in the current layer
|
||||
double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder-1);
|
||||
m_lower_slices_polygons = offset(*this->lower_slices, float(scale_(+nozzle_diameter/2)));
|
||||
double nozzle_diameter = params.print_config.nozzle_diameter.get_at(params.config.perimeter_extruder-1);
|
||||
lower_slices_polygons_cache = offset(*lower_slices, float(scale_(+nozzle_diameter/2)));
|
||||
}
|
||||
|
||||
// we need to process each island separately because we might have different
|
||||
// extra perimeters for each one
|
||||
for (const Surface &surface : this->slices->surfaces) {
|
||||
for (const Surface &surface : slices->surfaces) {
|
||||
// detect how many perimeters must be generated for this island
|
||||
int loop_number = this->config->perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
ExPolygons last = union_ex(surface.expolygon.simplify_p(m_scaled_resolution));
|
||||
int loop_number = params.config.perimeters + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
ExPolygons last = union_ex(surface.expolygon.simplify_p(params.scaled_resolution));
|
||||
ExPolygons gaps;
|
||||
if (loop_number >= 0) {
|
||||
// In case no perimeters are to be generated, loop_number will equal to -1.
|
||||
@ -873,17 +893,17 @@ void PerimeterGenerator::process_classic()
|
||||
if (i == 0) {
|
||||
// the minimum thickness of a single loop is:
|
||||
// ext_width/2 + ext_spacing/2 + spacing/2 + width/2
|
||||
offsets = this->config->thin_walls ?
|
||||
offsets = params.config.thin_walls ?
|
||||
offset2_ex(
|
||||
last,
|
||||
- float(ext_perimeter_width / 2. + ext_min_spacing / 2. - 1),
|
||||
+ float(ext_min_spacing / 2. - 1)) :
|
||||
offset_ex(last, - float(ext_perimeter_width / 2.));
|
||||
// look for thin walls
|
||||
if (this->config->thin_walls) {
|
||||
if (params.config.thin_walls) {
|
||||
// the following offset2 ensures almost nothing in @thin_walls is narrower than $min_width
|
||||
// (actually, something larger than that still may exist due to mitering or other causes)
|
||||
coord_t min_width = coord_t(scale_(this->ext_perimeter_flow.nozzle_diameter() / 3));
|
||||
coord_t min_width = coord_t(scale_(params.ext_perimeter_flow.nozzle_diameter() / 3));
|
||||
ExPolygons expp = opening_ex(
|
||||
// medial axis requires non-overlapping geometry
|
||||
diff_ex(last, offset(offsets, float(ext_perimeter_width / 2.) + ClipperSafetyOffset)),
|
||||
@ -892,7 +912,7 @@ void PerimeterGenerator::process_classic()
|
||||
for (ExPolygon &ex : expp)
|
||||
ex.medial_axis(ext_perimeter_width + ext_perimeter_spacing2, min_width, &thin_walls);
|
||||
}
|
||||
if (m_spiral_vase && offsets.size() > 1) {
|
||||
if (params.spiral_vase && offsets.size() > 1) {
|
||||
// Remove all but the largest area polygon.
|
||||
keep_largest_contour_only(offsets);
|
||||
}
|
||||
@ -900,7 +920,7 @@ void PerimeterGenerator::process_classic()
|
||||
//FIXME Is this offset correct if the line width of the inner perimeters differs
|
||||
// from the line width of the infill?
|
||||
coord_t distance = (i == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
|
||||
offsets = this->config->thin_walls ?
|
||||
offsets = params.config.thin_walls ?
|
||||
// This path will ensure, that the perimeters do not overfill, as in
|
||||
// prusa3d/Slic3r GH #32, but with the cost of rounding the perimeters
|
||||
// excessively, creating gaps, which then need to be filled in by the not very
|
||||
@ -933,8 +953,8 @@ void PerimeterGenerator::process_classic()
|
||||
break;
|
||||
}
|
||||
{
|
||||
const bool fuzzify_contours = this->config->fuzzy_skin != FuzzySkinType::None && i == 0 && this->layer_id > 0;
|
||||
const bool fuzzify_holes = fuzzify_contours && this->config->fuzzy_skin == FuzzySkinType::All;
|
||||
const bool fuzzify_contours = params.config.fuzzy_skin != FuzzySkinType::None && i == 0 && params.layer_id > 0;
|
||||
const bool fuzzify_holes = fuzzify_contours && params.config.fuzzy_skin == FuzzySkinType::All;
|
||||
for (const ExPolygon &expolygon : offsets) {
|
||||
// Outer contour may overlap with an inner contour,
|
||||
// inner contour may overlap with another inner contour,
|
||||
@ -951,7 +971,7 @@ void PerimeterGenerator::process_classic()
|
||||
}
|
||||
}
|
||||
last = std::move(offsets);
|
||||
if (i == loop_number && (! has_gap_fill || this->config->fill_density.value == 0)) {
|
||||
if (i == loop_number && (! has_gap_fill || params.config.fill_density.value == 0)) {
|
||||
// The last run of this loop is executed to collect gaps for gap fill.
|
||||
// As the gap fill is either disabled or not
|
||||
break;
|
||||
@ -1013,16 +1033,16 @@ void PerimeterGenerator::process_classic()
|
||||
}
|
||||
}
|
||||
// at this point, all loops should be in contours[0]
|
||||
ExtrusionEntityCollection entities = traverse_loops(*this, contours.front(), thin_walls);
|
||||
ExtrusionEntityCollection entities = traverse_loops(params, lower_slices_polygons_cache, contours.front(), thin_walls);
|
||||
// if brim will be printed, reverse the order of perimeters so that
|
||||
// we continue inwards after having finished the brim
|
||||
// TODO: add test for perimeter order
|
||||
if (this->config->external_perimeters_first ||
|
||||
(this->layer_id == 0 && this->object_config->brim_width.value > 0))
|
||||
if (params.config.external_perimeters_first ||
|
||||
(params.layer_id == 0 && params.object_config.brim_width.value > 0))
|
||||
entities.reverse();
|
||||
// append perimeters for this slice as a collection
|
||||
if (! entities.empty())
|
||||
this->loops->append(entities);
|
||||
out_loops.append(entities);
|
||||
} // for each loop of an island
|
||||
|
||||
// fill gaps
|
||||
@ -1039,7 +1059,7 @@ void PerimeterGenerator::process_classic()
|
||||
ex.medial_axis(max, min, &polylines);
|
||||
if (! polylines.empty()) {
|
||||
ExtrusionEntityCollection gap_fill;
|
||||
variable_width(polylines, erGapFill, this->solid_infill_flow, gap_fill.entities);
|
||||
variable_width(polylines, erGapFill, params.solid_infill_flow, gap_fill.entities);
|
||||
/* Make sure we don't infill narrow parts that are already gap-filled
|
||||
(we only consider this surface's gaps to reduce the diff() complexity).
|
||||
Growing actual extrusions ensures that gaps not filled by medial axis
|
||||
@ -1049,7 +1069,7 @@ void PerimeterGenerator::process_classic()
|
||||
//FIXME Vojtech: This grows by a rounded extrusion width, not by line spacing,
|
||||
// therefore it may cover the area, but no the volume.
|
||||
last = diff_ex(last, gap_fill.polygons_covered_by_width(10.f));
|
||||
this->gap_fill->append(std::move(gap_fill.entities));
|
||||
out_gap_fill.append(std::move(gap_fill.entities));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1066,15 +1086,15 @@ void PerimeterGenerator::process_classic()
|
||||
perimeter_spacing / 2;
|
||||
// only apply infill overlap if we actually have one perimeter
|
||||
if (inset > 0)
|
||||
inset -= coord_t(scale_(this->config->get_abs_value("infill_overlap", unscale<double>(inset + solid_infill_spacing / 2))));
|
||||
inset -= coord_t(scale_(params.config.get_abs_value("infill_overlap", unscale<double>(inset + solid_infill_spacing / 2))));
|
||||
// simplify infill contours according to resolution
|
||||
Polygons pp;
|
||||
for (ExPolygon &ex : last)
|
||||
ex.simplify_p(m_scaled_resolution, &pp);
|
||||
ex.simplify_p(params.scaled_resolution, &pp);
|
||||
// collapse too narrow infill areas
|
||||
coord_t min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
// append infill areas to fill_surfaces
|
||||
this->fill_surfaces->append(
|
||||
out_fill_surfaces.append(
|
||||
offset2_ex(
|
||||
union_ex(pp),
|
||||
float(- inset - min_perimeter_infill_spacing / 2.),
|
||||
@ -1083,15 +1103,4 @@ void PerimeterGenerator::process_classic()
|
||||
} // for each island
|
||||
}
|
||||
|
||||
bool PerimeterGeneratorLoop::is_internal_contour() const
|
||||
{
|
||||
// An internal contour is a contour containing no other contours
|
||||
if (! this->is_contour)
|
||||
return false;
|
||||
for (const PerimeterGeneratorLoop &loop : this->children)
|
||||
if (loop.is_contour)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,70 +10,93 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class PerimeterGenerator {
|
||||
public:
|
||||
// Inputs:
|
||||
const SurfaceCollection *slices;
|
||||
const ExPolygons *lower_slices;
|
||||
namespace PerimeterGenerator
|
||||
{
|
||||
|
||||
struct Parameters {
|
||||
Parameters(
|
||||
double layer_height,
|
||||
int layer_id,
|
||||
Flow perimeter_flow,
|
||||
Flow ext_perimeter_flow,
|
||||
Flow overhang_flow,
|
||||
Flow solid_infill_flow,
|
||||
const PrintRegionConfig &config,
|
||||
const PrintObjectConfig &object_config,
|
||||
const PrintConfig &print_config,
|
||||
const bool spiral_vase) :
|
||||
layer_height(layer_height),
|
||||
layer_id(layer_id),
|
||||
perimeter_flow(perimeter_flow),
|
||||
ext_perimeter_flow(ext_perimeter_flow),
|
||||
overhang_flow(overhang_flow),
|
||||
solid_infill_flow(solid_infill_flow),
|
||||
config(config),
|
||||
object_config(object_config),
|
||||
print_config(print_config),
|
||||
spiral_vase(spiral_vase),
|
||||
scaled_resolution(scaled<double>(print_config.gcode_resolution.value)),
|
||||
mm3_per_mm(perimeter_flow.mm3_per_mm()),
|
||||
ext_mm3_per_mm(ext_perimeter_flow.mm3_per_mm()),
|
||||
mm3_per_mm_overhang(overhang_flow.mm3_per_mm())
|
||||
{
|
||||
}
|
||||
|
||||
// Input parameters
|
||||
double layer_height;
|
||||
int layer_id;
|
||||
Flow perimeter_flow;
|
||||
Flow ext_perimeter_flow;
|
||||
Flow overhang_flow;
|
||||
Flow solid_infill_flow;
|
||||
const PrintRegionConfig *config;
|
||||
const PrintObjectConfig *object_config;
|
||||
const PrintConfig *print_config;
|
||||
// Outputs:
|
||||
ExtrusionEntityCollection *loops;
|
||||
ExtrusionEntityCollection *gap_fill;
|
||||
SurfaceCollection *fill_surfaces;
|
||||
|
||||
PerimeterGenerator(
|
||||
// Input:
|
||||
const SurfaceCollection* slices,
|
||||
double layer_height,
|
||||
Flow flow,
|
||||
const PrintRegionConfig* config,
|
||||
const PrintObjectConfig* object_config,
|
||||
const PrintConfig* print_config,
|
||||
const bool spiral_vase,
|
||||
// Output:
|
||||
// Loops with the external thin walls
|
||||
ExtrusionEntityCollection* loops,
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection* gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection* fill_surfaces)
|
||||
: slices(slices), lower_slices(nullptr), layer_height(layer_height),
|
||||
layer_id(-1), perimeter_flow(flow), ext_perimeter_flow(flow),
|
||||
overhang_flow(flow), solid_infill_flow(flow),
|
||||
config(config), object_config(object_config), print_config(print_config),
|
||||
m_spiral_vase(spiral_vase),
|
||||
m_scaled_resolution(scaled<double>(print_config->gcode_resolution.value)),
|
||||
loops(loops), gap_fill(gap_fill), fill_surfaces(fill_surfaces),
|
||||
m_ext_mm3_per_mm(-1), m_mm3_per_mm(-1), m_mm3_per_mm_overhang(-1)
|
||||
{}
|
||||
const PrintRegionConfig &config;
|
||||
const PrintObjectConfig &object_config;
|
||||
const PrintConfig &print_config;
|
||||
|
||||
void process_classic();
|
||||
void process_arachne();
|
||||
|
||||
double ext_mm3_per_mm() const { return m_ext_mm3_per_mm; }
|
||||
double mm3_per_mm() const { return m_mm3_per_mm; }
|
||||
double mm3_per_mm_overhang() const { return m_mm3_per_mm_overhang; }
|
||||
Polygons lower_slices_polygons() const { return m_lower_slices_polygons; }
|
||||
// Derived parameters
|
||||
bool spiral_vase;
|
||||
double scaled_resolution;
|
||||
double ext_mm3_per_mm;
|
||||
double mm3_per_mm;
|
||||
double mm3_per_mm_overhang;
|
||||
|
||||
private:
|
||||
bool m_spiral_vase;
|
||||
double m_scaled_resolution;
|
||||
double m_ext_mm3_per_mm;
|
||||
double m_mm3_per_mm;
|
||||
double m_mm3_per_mm_overhang;
|
||||
Polygons m_lower_slices_polygons;
|
||||
Parameters() = delete;
|
||||
};
|
||||
|
||||
void process_classic(
|
||||
// Inputs:
|
||||
const Parameters ¶ms,
|
||||
const SurfaceCollection *slices,
|
||||
const ExPolygons *lower_slices,
|
||||
// Cache:
|
||||
Polygons &lower_slices_polygons_cache,
|
||||
// Output:
|
||||
// Loops with the external thin walls
|
||||
ExtrusionEntityCollection &out_loops,
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces);
|
||||
|
||||
void process_arachne(
|
||||
// Inputs:
|
||||
const Parameters ¶ms,
|
||||
const SurfaceCollection *slices,
|
||||
const ExPolygons *lower_slices,
|
||||
// Cache:
|
||||
Polygons &lower_slices_polygons_cache,
|
||||
// Output:
|
||||
// Loops with the external thin walls
|
||||
ExtrusionEntityCollection &out_loops,
|
||||
// Gaps without the thin walls
|
||||
ExtrusionEntityCollection &out_gap_fill,
|
||||
// Infills without the gap fills
|
||||
SurfaceCollection &out_fill_surfaces);
|
||||
|
||||
ExtrusionMultiPath thick_polyline_to_multi_path(const ThickPolyline &thick_polyline, ExtrusionRole role, const Flow &flow, float tolerance, float merge_tolerance);
|
||||
|
||||
}
|
||||
} // namespace PerimeterGenerator
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
||||
|
@ -45,21 +45,29 @@ SCENARIO("Perimeter nesting", "[Perimeters]")
|
||||
ExtrusionEntityCollection loops;
|
||||
ExtrusionEntityCollection gap_fill;
|
||||
SurfaceCollection fill_surfaces;
|
||||
PerimeterGenerator perimeter_generator(
|
||||
&slices,
|
||||
Flow flow(1., 1., 1.);
|
||||
PerimeterGenerator::Parameters perimeter_generator_params(
|
||||
1., // layer height
|
||||
Flow(1., 1., 1.),
|
||||
static_cast<const PrintRegionConfig*>(&config),
|
||||
static_cast<const PrintObjectConfig*>(&config),
|
||||
static_cast<const PrintConfig*>(&config),
|
||||
false, // spiral_vase
|
||||
// output:
|
||||
&loops, &gap_fill, &fill_surfaces);
|
||||
-1, // layer ID
|
||||
flow, flow, flow, flow,
|
||||
static_cast<const PrintRegionConfig&>(config),
|
||||
static_cast<const PrintObjectConfig&>(config),
|
||||
static_cast<const PrintConfig&>(config),
|
||||
false); // spiral_vase
|
||||
Polygons lower_layer_polygons_cache;
|
||||
// FIXME Lukas H.: Disable this test for Arachne because it is failing and needs more investigation.
|
||||
// if (config.perimeter_generator == PerimeterGeneratorType::Arachne)
|
||||
// perimeter_generator.process_arachne();
|
||||
// PerimeterGenerator::process_arachne();
|
||||
// else
|
||||
perimeter_generator.process_classic();
|
||||
PerimeterGenerator::process_classic(
|
||||
// input:
|
||||
perimeter_generator_params,
|
||||
&slices,
|
||||
nullptr,
|
||||
// cache:
|
||||
lower_layer_polygons_cache,
|
||||
// output:
|
||||
loops, gap_fill, fill_surfaces);
|
||||
|
||||
THEN("expected number of collections") {
|
||||
REQUIRE(loops.entities.size() == data.expolygons.size());
|
||||
|
Loading…
Reference in New Issue
Block a user