ENH: generate outer wall contour paths in arachne
1. Add OuterWallContourStrategy class to generate outer wall contour paths. 2. Fix top one wall issue in arachne jira:NONE Signed-off-by: xun.zhang <xun.zhang@bambulab.com> Change-Id: I44574df765cdd0d0d3fc4f6c3f7b846dfb4fa21f
This commit is contained in:
parent
032b34eded
commit
6018d326f4
|
@ -13,6 +13,8 @@ namespace Slic3r::Arachne
|
|||
|
||||
template<typename T> constexpr T pi_div(const T div) { return static_cast<T>(M_PI) / div; }
|
||||
|
||||
constexpr int WallContourMarkedWidth = 0;
|
||||
constexpr int FirstWallContourMarkedWidth = 1;
|
||||
/*!
|
||||
* Mostly virtual base class template.
|
||||
*
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "DistributedBeadingStrategy.hpp"
|
||||
#include "RedistributeBeadingStrategy.hpp"
|
||||
#include "OuterWallInsetBeadingStrategy.hpp"
|
||||
#include "OuterWallContourStrategy.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
@ -44,9 +45,16 @@ BeadingStrategyPtr BeadingStrategyFactory::makeStrategy(
|
|||
ret = std::make_unique<OuterWallInsetBeadingStrategy>(outer_wall_offset, std::move(ret));
|
||||
}
|
||||
|
||||
//Apply the OuterWallContourStrategy last, since that adds a 1-width marker wall to mark the boundary of first beading.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Applying the First Beading Contour Strategy.";
|
||||
ret = std::make_unique<OuterWallContourStrategy>(std::move(ret));
|
||||
|
||||
//Apply the LimitedBeadingStrategy last, since that adds a 0-width marker wall which other beading strategies shouldn't touch.
|
||||
BOOST_LOG_TRIVIAL(debug) << "Applying the Limited Beading meta-strategy with maximum bead count = " << max_bead_count << ".";
|
||||
ret = std::make_unique<LimitedBeadingStrategy>(max_bead_count, std::move(ret));
|
||||
ret = std::make_unique<LimitedBeadingStrategy>(max_bead_count + 2, std::move(ret));
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
} // namespace Slic3r::Arachne
|
||||
|
|
|
@ -48,7 +48,7 @@ LimitedBeadingStrategy::Beading LimitedBeadingStrategy::compute(coord_t thicknes
|
|||
const coord_t innermost_toolpath_location = ret.toolpath_locations[max_bead_count / 2 - 1];
|
||||
const coord_t innermost_toolpath_width = ret.bead_widths[max_bead_count / 2 - 1];
|
||||
ret.toolpath_locations.insert(ret.toolpath_locations.begin() + max_bead_count / 2, innermost_toolpath_location + innermost_toolpath_width / 2);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin() + max_bead_count / 2, 0);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin() + max_bead_count / 2, WallContourMarkedWidth);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -77,14 +77,14 @@ LimitedBeadingStrategy::Beading LimitedBeadingStrategy::compute(coord_t thicknes
|
|||
coord_t innermost_toolpath_location = ret.toolpath_locations[max_bead_count / 2 - 1];
|
||||
coord_t innermost_toolpath_width = ret.bead_widths[max_bead_count / 2 - 1];
|
||||
ret.toolpath_locations.insert(ret.toolpath_locations.begin() + max_bead_count / 2, innermost_toolpath_location + innermost_toolpath_width / 2);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin() + max_bead_count / 2, 0);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin() + max_bead_count / 2, WallContourMarkedWidth);
|
||||
|
||||
//Symmetry on both sides. Symmetry is guaranteed since this code is stopped early if the bead_count <= max_bead_count, and never reaches this point then.
|
||||
const size_t opposite_bead = bead_count - (max_bead_count / 2 - 1);
|
||||
innermost_toolpath_location = ret.toolpath_locations[opposite_bead];
|
||||
innermost_toolpath_width = ret.bead_widths[opposite_bead];
|
||||
ret.toolpath_locations.insert(ret.toolpath_locations.begin() + opposite_bead, innermost_toolpath_location - innermost_toolpath_width / 2);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin() + opposite_bead, 0);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin() + opposite_bead, WallContourMarkedWidth);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
|
||||
#include "OuterWallContourStrategy.hpp"
|
||||
#include "Point.hpp"
|
||||
|
||||
namespace Slic3r::Arachne
|
||||
{
|
||||
|
||||
|
||||
OuterWallContourStrategy::OuterWallContourStrategy(BeadingStrategyPtr parent)
|
||||
: BeadingStrategy(*parent)
|
||||
, parent(std::move(parent))
|
||||
{
|
||||
}
|
||||
|
||||
std::string OuterWallContourStrategy::toString() const
|
||||
{
|
||||
return std::string("OuterWallContourStrategy+") + parent->toString();
|
||||
}
|
||||
|
||||
coord_t OuterWallContourStrategy::getTransitioningLength(coord_t lower_bead_count) const
|
||||
{
|
||||
return parent->getTransitioningLength(lower_bead_count);
|
||||
}
|
||||
|
||||
float OuterWallContourStrategy::getTransitionAnchorPos(coord_t lower_bead_count) const
|
||||
{
|
||||
return parent->getTransitionAnchorPos(lower_bead_count);
|
||||
}
|
||||
|
||||
std::vector<coord_t> OuterWallContourStrategy::getNonlinearThicknesses(coord_t lower_bead_count) const
|
||||
{
|
||||
return parent->getNonlinearThicknesses(lower_bead_count);
|
||||
}
|
||||
|
||||
|
||||
coord_t OuterWallContourStrategy::getTransitionThickness(coord_t lower_bead_count) const
|
||||
{
|
||||
if(lower_bead_count <= 1)
|
||||
return parent->getTransitionThickness(lower_bead_count);
|
||||
else if(lower_bead_count == 2 || lower_bead_count ==3)
|
||||
return parent->getTransitionThickness(1);
|
||||
return parent->getTransitionThickness(lower_bead_count-2);
|
||||
}
|
||||
|
||||
|
||||
coord_t OuterWallContourStrategy::getOptimalBeadCount(coord_t thickness) const
|
||||
{
|
||||
coord_t parent_bead_count = parent->getOptimalBeadCount(thickness);
|
||||
if(parent_bead_count <= 1)
|
||||
return parent_bead_count;
|
||||
return parent_bead_count + 2;
|
||||
}
|
||||
|
||||
|
||||
coord_t OuterWallContourStrategy::getOptimalThickness(coord_t bead_count) const
|
||||
{
|
||||
if (bead_count <= 1)
|
||||
return parent->getOptimalThickness(bead_count);
|
||||
return parent->getOptimalThickness(bead_count - 2) + 2;
|
||||
}
|
||||
|
||||
BeadingStrategy::Beading OuterWallContourStrategy::compute(coord_t thickness, coord_t bead_count) const
|
||||
{
|
||||
if (bead_count <= 1)
|
||||
return parent->compute(thickness, bead_count);
|
||||
|
||||
assert(bead_count >= 3);
|
||||
Beading ret = parent->compute(thickness, bead_count - 2);
|
||||
if(ret.toolpath_locations.size() == 1){
|
||||
return ret;
|
||||
}
|
||||
if(ret.toolpath_locations.size() > 0 ){
|
||||
assert(ret.bead_widths.size()>0);
|
||||
double location = ret.toolpath_locations.front() + ret.bead_widths.front() / 2;
|
||||
double location_reverse = ret.toolpath_locations.back() - ret.bead_widths.back() / 2;
|
||||
ret.toolpath_locations.insert(ret.toolpath_locations.begin()+1, location);
|
||||
ret.bead_widths.insert(ret.bead_widths.begin()+1, FirstWallContourMarkedWidth);
|
||||
ret.toolpath_locations.insert((ret.toolpath_locations.rbegin()+1).base(), location_reverse);
|
||||
ret.bead_widths.insert((ret.bead_widths.rbegin()).base(), FirstWallContourMarkedWidth);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} // namespace Slic3r::Arachne
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef OUTER_WALL_CONTOUR_STRATEGY_H
|
||||
#define OUTER_WALL_CONTOUR_STRATEGY_H
|
||||
|
||||
#include "BeadingStrategy.hpp"
|
||||
namespace Slic3r::Arachne
|
||||
{
|
||||
|
||||
class OuterWallContourStrategy : public BeadingStrategy
|
||||
{
|
||||
public:
|
||||
OuterWallContourStrategy(BeadingStrategyPtr parent);
|
||||
~OuterWallContourStrategy() override = default;
|
||||
|
||||
Beading compute(coord_t thickness, coord_t bead_count) const override;
|
||||
coord_t getOptimalThickness(coord_t bead_count) const override;
|
||||
coord_t getTransitionThickness(coord_t lower_bead_count) const override;
|
||||
coord_t getOptimalBeadCount(coord_t thickness) const override;
|
||||
std::string toString() const override;
|
||||
|
||||
coord_t getTransitioningLength(coord_t lower_bead_count) const override;
|
||||
float getTransitionAnchorPos(coord_t lower_bead_count) const override;
|
||||
std::vector<coord_t> getNonlinearThicknesses(coord_t lower_bead_count) const override;
|
||||
|
||||
protected:
|
||||
const BeadingStrategyPtr parent;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
|
@ -700,27 +700,37 @@ const std::vector<VariableWidthLines> &WallToolPaths::getToolPaths()
|
|||
|
||||
void WallToolPaths::separateOutInnerContour()
|
||||
{
|
||||
enum PathType{
|
||||
ActualPath,
|
||||
WallContour,
|
||||
FirstWallContour
|
||||
};
|
||||
|
||||
//We'll remove all 0-width paths from the original toolpaths and store them separately as polygons.
|
||||
std::vector<VariableWidthLines> actual_toolpaths;
|
||||
actual_toolpaths.reserve(toolpaths.size()); //A bit too much, but the correct order of magnitude.
|
||||
std::vector<VariableWidthLines> contour_paths;
|
||||
contour_paths.reserve(toolpaths.size() / inset_count);
|
||||
std::vector<VariableWidthLines> wall_contour_paths;
|
||||
wall_contour_paths.reserve(toolpaths.size() / inset_count);
|
||||
std::vector<VariableWidthLines> first_wall_contour_paths;
|
||||
inner_contour.clear();
|
||||
first_wall_contour.clear();
|
||||
for (const VariableWidthLines &inset : toolpaths) {
|
||||
if (inset.empty())
|
||||
continue;
|
||||
bool is_contour = false;
|
||||
PathType type;
|
||||
for (const ExtrusionLine &line : inset) {
|
||||
for (const ExtrusionJunction &j : line) {
|
||||
if (j.w == 0)
|
||||
is_contour = true;
|
||||
if (j.w == Arachne::WallContourMarkedWidth)
|
||||
type = WallContour;
|
||||
else if(j.w == Arachne::FirstWallContourMarkedWidth)
|
||||
type = FirstWallContour;
|
||||
else
|
||||
is_contour = false;
|
||||
type = ActualPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_contour) {
|
||||
if (type==WallContour) {
|
||||
#ifdef DEBUG
|
||||
for (const ExtrusionLine &line : inset)
|
||||
for (const ExtrusionJunction &j : line)
|
||||
|
@ -732,7 +742,16 @@ void WallToolPaths::separateOutInnerContour()
|
|||
else if (line.is_closed) // sometimes an very small even polygonal wall is not stitched into a polygon
|
||||
inner_contour.emplace_back(line.toPolygon());
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else if (type == FirstWallContour){
|
||||
for (const ExtrusionLine &line : inset) {
|
||||
if (line.is_odd)
|
||||
continue;
|
||||
else if (line.is_closed)
|
||||
first_wall_contour.emplace_back(line.toPolygon());
|
||||
}
|
||||
}
|
||||
else {
|
||||
actual_toolpaths.emplace_back(inset);
|
||||
}
|
||||
}
|
||||
|
@ -747,6 +766,15 @@ void WallToolPaths::separateOutInnerContour()
|
|||
//This can be done by applying the even-odd rule to the shape. This rule is not sensitive to the winding order of the polygon.
|
||||
//The even-odd rule would be incorrect if the polygon self-intersects, but that should never be generated by the skeletal trapezoidation.
|
||||
inner_contour = union_(inner_contour, ClipperLib::PolyFillType::pftEvenOdd);
|
||||
first_wall_contour = union_(first_wall_contour, ClipperLib::PolyFillType::pftEvenOdd);
|
||||
|
||||
// restore the idx of non first wall paths
|
||||
for (auto& paths : toolpaths) {
|
||||
for (auto& path : paths) {
|
||||
if (path.inset_idx > 1)
|
||||
path.inset_idx -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Polygons& WallToolPaths::getInnerContour()
|
||||
|
@ -762,6 +790,20 @@ const Polygons& WallToolPaths::getInnerContour()
|
|||
return inner_contour;
|
||||
}
|
||||
|
||||
const Polygons& WallToolPaths::getFirstWallContour()
|
||||
{
|
||||
if (!toolpaths_generated && inset_count > 0)
|
||||
{
|
||||
generate();
|
||||
}
|
||||
else if(inset_count == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return first_wall_contour;
|
||||
}
|
||||
|
||||
|
||||
bool WallToolPaths::removeEmptyToolPaths(std::vector<VariableWidthLines> &toolpaths)
|
||||
{
|
||||
toolpaths.erase(std::remove_if(toolpaths.begin(), toolpaths.end(), [](const VariableWidthLines& lines)
|
||||
|
|
|
@ -78,6 +78,8 @@ public:
|
|||
*/
|
||||
const Polygons& getInnerContour();
|
||||
|
||||
const Polygons& getFirstWallContour();
|
||||
|
||||
/*!
|
||||
* Removes empty paths from the toolpaths
|
||||
* \param toolpaths the VariableWidthPaths generated with \p generate()
|
||||
|
@ -131,6 +133,7 @@ private:
|
|||
bool toolpaths_generated; //<! Are the toolpaths generated
|
||||
std::vector<VariableWidthLines> toolpaths; //<! The generated toolpaths
|
||||
Polygons inner_contour; //<! The inner contour of the generated toolpaths
|
||||
Polygons first_wall_contour; //<! The contour of the first wall
|
||||
const WallToolPathsParams m_params;
|
||||
private:
|
||||
bool enable_hole_compensation{ false };
|
||||
|
|
|
@ -401,6 +401,8 @@ set(lisbslic3r_sources
|
|||
Arachne/BeadingStrategy/RedistributeBeadingStrategy.cpp
|
||||
Arachne/BeadingStrategy/WideningBeadingStrategy.hpp
|
||||
Arachne/BeadingStrategy/WideningBeadingStrategy.cpp
|
||||
Arachne/BeadingStrategy/OuterWallContourStrategy.hpp
|
||||
Arachne/BeadingStrategy/OuterWallContourStrategy.cpp
|
||||
Arachne/utils/ExtrusionJunction.hpp
|
||||
Arachne/utils/ExtrusionJunction.cpp
|
||||
Arachne/utils/ExtrusionLine.hpp
|
||||
|
|
|
@ -1797,14 +1797,11 @@ void PerimeterGenerator::process_arachne()
|
|||
// we need to process each island separately because we might have different
|
||||
// extra perimeters for each one
|
||||
|
||||
|
||||
for (const Surface& surface : this->slices->surfaces) {
|
||||
bool generate_one_wall = false;
|
||||
bool generate_one_wall_by_first_layer = this->object_config->only_one_wall_first_layer && layer_id == 0;
|
||||
bool generate_one_wall_by_top_one_wall = this->object_config->top_one_wall_type == TopOneWallType::Topmost && this->upper_slices == nullptr ||
|
||||
this->object_config->top_one_wall_type == TopOneWallType::Alltop;
|
||||
|
||||
generate_one_wall = generate_one_wall_by_first_layer || generate_one_wall_by_top_one_wall;
|
||||
bool generate_one_wall = generate_one_wall_by_first_layer || generate_one_wall_by_top_one_wall;
|
||||
// detect how many perimeters must be generated for this island
|
||||
int loop_number = this->config->wall_loops + surface.extra_perimeters - 1; // 0-indexed loops
|
||||
|
||||
|
@ -1815,35 +1812,6 @@ void PerimeterGenerator::process_arachne()
|
|||
if (last.size() != 1 || new_size != surface.expolygon.num_contours())
|
||||
apply_circle_compensation = false;
|
||||
|
||||
std::vector<int> circle_poly_indices;
|
||||
Polygons last_p;
|
||||
if (apply_circle_compensation)
|
||||
last_p = to_polygons_with_flag(last.front(), surface.counter_circle_compensation, surface.holes_circle_compensation, circle_poly_indices);
|
||||
else
|
||||
last_p = to_polygons(last);
|
||||
|
||||
// check whether to activate one wall mode
|
||||
if (generate_one_wall && !generate_one_wall_by_first_layer)
|
||||
{
|
||||
ExPolygons top_expolys;
|
||||
ExPolygons infill_contour_by_one_wall = offset_ex(last, -(ext_perimeter_width + perimeter_spacing) / 2.f);
|
||||
|
||||
BoundingBox infill_bbox = get_extents(infill_contour_by_one_wall);
|
||||
infill_bbox.offset(EPSILON);
|
||||
|
||||
Polygons upper_polygons_clipped;
|
||||
if (this->upper_slices)
|
||||
upper_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->upper_slices, infill_bbox);
|
||||
top_expolys = diff_ex(infill_contour_by_one_wall, upper_polygons_clipped);
|
||||
|
||||
Polygons lower_polygons_clipped;
|
||||
if (this->lower_slices)
|
||||
lower_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, infill_bbox);
|
||||
ExPolygons bottom_expolys = offset_ex(diff_ex(top_expolys, lower_polygons_clipped), std::max(ext_perimeter_spacing, perimeter_width));
|
||||
|
||||
top_expolys = diff_ex(top_expolys, bottom_expolys);
|
||||
generate_one_wall = should_enable_top_one_wall(last, top_expolys);
|
||||
}
|
||||
|
||||
double min_nozzle_diameter = *std::min_element(print_config->nozzle_diameter.values.begin(), print_config->nozzle_diameter.values.end());
|
||||
Arachne::WallToolPathsParams input_params;
|
||||
|
@ -1864,15 +1832,77 @@ void PerimeterGenerator::process_arachne()
|
|||
input_params.wall_distribution_count = this->object_config->wall_distribution_count.value;
|
||||
}
|
||||
|
||||
coord_t real_loop_number = generate_one_wall ? 1 : loop_number + 1;
|
||||
|
||||
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, real_loop_number, 0, layer_height, input_params);
|
||||
std::vector<int> circle_poly_indices;
|
||||
Polygons last_p;
|
||||
if (apply_circle_compensation)
|
||||
last_p = to_polygons_with_flag(last.front(), surface.counter_circle_compensation, surface.holes_circle_compensation, circle_poly_indices);
|
||||
else
|
||||
last_p = to_polygons(last);
|
||||
|
||||
Arachne::WallToolPaths wallToolPaths(last_p, ext_perimeter_spacing, perimeter_spacing, loop_number + 1, 0, layer_height, input_params);
|
||||
if (apply_circle_compensation)
|
||||
wallToolPaths.EnableHoleCompensation(true, circle_poly_indices);
|
||||
|
||||
std::vector<Arachne::VariableWidthLines> perimeters = wallToolPaths.getToolPaths();
|
||||
ExPolygons infill_contour = union_ex(wallToolPaths.getInnerContour());
|
||||
ExPolygons top_expolys_by_one_wall;
|
||||
ExPolygons infill_contour_by_one_wall = union_ex(wallToolPaths.getFirstWallContour());
|
||||
|
||||
// do detail check whether to enable one wall
|
||||
if (generate_one_wall && !generate_one_wall_by_first_layer)
|
||||
{
|
||||
BoundingBox infill_bbox = get_extents(infill_contour_by_one_wall);
|
||||
infill_bbox.offset(EPSILON);
|
||||
|
||||
Polygons upper_polygons_clipped;
|
||||
if (this->upper_slices)
|
||||
upper_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->upper_slices, infill_bbox);
|
||||
top_expolys_by_one_wall = diff_ex(infill_contour_by_one_wall, upper_polygons_clipped);
|
||||
|
||||
Polygons lower_polygons_clipped;
|
||||
if (this->lower_slices)
|
||||
lower_polygons_clipped = ClipperUtils::clip_clipper_polygons_with_subject_bbox(*this->lower_slices, infill_bbox);
|
||||
ExPolygons bottom_expolys = diff_ex(top_expolys_by_one_wall, lower_polygons_clipped);
|
||||
|
||||
top_expolys_by_one_wall = diff_ex(top_expolys_by_one_wall, bottom_expolys);
|
||||
generate_one_wall = should_enable_top_one_wall(last, top_expolys_by_one_wall);
|
||||
if (generate_one_wall)
|
||||
top_expolys_by_one_wall = offset_ex(top_expolys_by_one_wall, perimeter_width);
|
||||
}
|
||||
|
||||
std::vector<Arachne::VariableWidthLines> total_perimeters;
|
||||
ExPolygons infill_contour;
|
||||
if (!generate_one_wall) {
|
||||
total_perimeters = wallToolPaths.getToolPaths();
|
||||
infill_contour = union_ex(wallToolPaths.getInnerContour());
|
||||
}
|
||||
else if(loop_number >0) {
|
||||
last = diff_ex(infill_contour_by_one_wall, top_expolys_by_one_wall);
|
||||
last_p = to_polygons(last);
|
||||
Arachne::WallToolPaths paths_new(last_p, perimeter_spacing, perimeter_spacing, loop_number, 0, layer_height, input_params);
|
||||
|
||||
auto old_perimeters = wallToolPaths.getToolPaths();
|
||||
auto new_perimeters = paths_new.getToolPaths();
|
||||
for (auto& perimeters : old_perimeters) {
|
||||
if (std::find_if(perimeters.begin(), perimeters.end(), [](auto& item) {return item.inset_idx == 0; }) != perimeters.end()) {
|
||||
total_perimeters.emplace_back();
|
||||
for (auto& p : perimeters) {
|
||||
if (p.inset_idx == 0)
|
||||
total_perimeters.back().emplace_back(std::move(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& perimeters : new_perimeters) {
|
||||
if (!perimeters.empty()) {
|
||||
for (auto& p : perimeters){
|
||||
p.inset_idx += 1;
|
||||
}
|
||||
total_perimeters.emplace_back(std::move(perimeters));
|
||||
}
|
||||
}
|
||||
infill_contour = union_ex(union_ex(paths_new.getInnerContour()), top_expolys_by_one_wall);
|
||||
infill_contour = intersection_ex(infill_contour, infill_contour_by_one_wall);
|
||||
}
|
||||
|
||||
#ifdef ARACHNE_DEBUG
|
||||
{
|
||||
static int iRun = 0;
|
||||
|
@ -1883,15 +1913,15 @@ void PerimeterGenerator::process_arachne()
|
|||
// All closed ExtrusionLine should have the same the first and the last point.
|
||||
// But in rare cases, Arachne produce ExtrusionLine marked as closed but without
|
||||
// equal the first and the last point.
|
||||
assert([&perimeters = std::as_const(perimeters)]() -> bool {
|
||||
for (const Arachne::VariableWidthLines& perimeter : perimeters)
|
||||
assert([&total_perimeters = std::as_const(total_perimeters)]() -> bool {
|
||||
for (const Arachne::VariableWidthLines& perimeter : total_perimeters)
|
||||
for (const Arachne::ExtrusionLine& el : perimeter)
|
||||
if (el.is_closed && el.junctions.front().p != el.junctions.back().p)
|
||||
return false;
|
||||
return true;
|
||||
}());
|
||||
|
||||
int start_perimeter = int(perimeters.size()) - 1;
|
||||
int start_perimeter = int(total_perimeters.size()) - 1;
|
||||
int end_perimeter = -1;
|
||||
int direction = -1;
|
||||
|
||||
|
@ -1899,15 +1929,15 @@ void PerimeterGenerator::process_arachne()
|
|||
this->object_config->wall_sequence == WallSequence::OuterInner || this->object_config->wall_sequence == WallSequence::InnerOuterInner;
|
||||
if (is_outer_wall_first) {
|
||||
start_perimeter = 0;
|
||||
end_perimeter = int(perimeters.size());
|
||||
end_perimeter = int(total_perimeters.size());
|
||||
direction = 1;
|
||||
}
|
||||
|
||||
std::vector<Arachne::ExtrusionLine*> all_extrusions;
|
||||
for (int perimeter_idx = start_perimeter; perimeter_idx != end_perimeter; perimeter_idx += direction) {
|
||||
if (perimeters[perimeter_idx].empty())
|
||||
if (total_perimeters[perimeter_idx].empty())
|
||||
continue;
|
||||
for (Arachne::ExtrusionLine& wall : perimeters[perimeter_idx])
|
||||
for (Arachne::ExtrusionLine& wall : total_perimeters[perimeter_idx])
|
||||
all_extrusions.emplace_back(&wall);
|
||||
}
|
||||
|
||||
|
@ -2069,7 +2099,7 @@ void PerimeterGenerator::process_arachne()
|
|||
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty())
|
||||
this->loops->append(extrusion_coll);
|
||||
|
||||
const coord_t spacing = (perimeters.size() == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
|
||||
const coord_t spacing = (total_perimeters.size() == 1) ? ext_perimeter_spacing2 : perimeter_spacing;
|
||||
|
||||
// collapse too narrow infill areas
|
||||
const auto min_perimeter_infill_spacing = coord_t(solid_infill_spacing * (1. - INSET_OVERLAP_TOLERANCE));
|
||||
|
|
Loading…
Reference in New Issue