-
-
Notifications
You must be signed in to change notification settings - Fork 882
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CURA-7979] Lock outer wall in place and width as much as possible #1405
Merged
rburema
merged 21 commits into
libArachne_rebased
from
CURA-7979_fix_outer_wall_artifacts
Feb 16, 2021
Merged
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
a5f9acf
Possible to adjust how close to optimal-width/place outer walls are.
rburema 869cc4d
Rethink left-over width w.r.t. redistribution.
rburema 99f7349
Handle the 'initially only outer walls' case.
rburema aca8aeb
Don't handle 0-width signalling walls.
rburema 4928723
Handle case where inner walls dissapear.
rburema 3f28e22
Expose 'Outer Wall Lock Factor' setting to frontend.
rburema d13d08b
Add new setting to tests as well.
rburema 21c93de
Rewrote outer wall lock factor usage.
jellespijker 5582c23
Calculate weights only once
jellespijker 2e0af51
Inner beads should also be processed
jellespijker c1b75ab
Make sure that all beads still adhere to minimum width
jellespijker 8c60b9a
Take into account filtered out beads
jellespijker 3bd13c9
Removed indention
jellespijker 667ef4a
Reimplemented old distribution calculation.
jellespijker a12e989
Force symmetry from and early start.
jellespijker 2d63dab
Made outer wall lock default behaviour.
jellespijker 219a48c
Updated and added documentation
jellespijker 5b7e466
Renamed parameter to minimum_width_inner for consistency
jellespijker 82eb2b5
Merge remote-tracking branch 'origin/libArachne_rebased' into CURA-79…
jellespijker 4404c7e
Remove dead code. Correct English spelling.
rburema 88e793e
Merge branch 'CURA-7979_fix_outer_wall_artifacts' of https://github.c…
rburema File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,65 +4,126 @@ | |
#include "RedistributeBeadingStrategy.h" | ||
|
||
#include <algorithm> | ||
#include <numeric> | ||
|
||
namespace cura | ||
{ | ||
BeadingStrategy::Beading RedistributeBeadingStrategy::compute(coord_t thickness, coord_t bead_count) const | ||
BeadingStrategy::Beading RedistributeBeadingStrategy::compute(coord_t thickness, coord_t bead_count) const | ||
{ | ||
Beading ret; | ||
if (bead_count > 2) | ||
{ | ||
Beading ret = parent->compute(thickness, bead_count); | ||
const coord_t inner_transition_width = optimal_width_inner * minimum_variable_line_width; | ||
const coord_t outer_bead_width = | ||
getOptimalOuterBeadWidth(thickness, optimal_width_outer, inner_transition_width); | ||
|
||
// Actual count and thickness as represented by extant walls. Don't count any potential zero-width 'signalling' walls. | ||
bead_count = std::count_if(ret.bead_widths.begin(), ret.bead_widths.end(), [](const coord_t width) { return width > 0; }); | ||
thickness -= ret.left_over; | ||
// Outer wall is locked in size en position for wall regions of 3 and higher which have at least a | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 'size en position' -> 'size and position' |
||
// thickness equal to two times the optimal outer width and the minimal inner wall width. | ||
const coord_t virtual_thickness = thickness - outer_bead_width * 2; | ||
const coord_t virtual_bead_count = bead_count - 2; | ||
|
||
// Early out when the only walls are outer, the parent can have been trusted to handle it. | ||
if (bead_count < 3) | ||
{ | ||
return ret; | ||
} | ||
// Calculate the beads and widths of the inner walls only | ||
ret = parent->compute(virtual_thickness, virtual_bead_count); | ||
|
||
// Calculate the factors with which to multiply the outer and inner walls: | ||
const coord_t current_total_outer_walls_width = ret.bead_widths.front() + ret.bead_widths.back(); | ||
const coord_t current_total_inner_walls_width = thickness - current_total_outer_walls_width; | ||
const coord_t optimal_total_outer_walls_width = optimal_width_outer * 2; | ||
const coord_t optimal_total_inner_walls_width = optimal_width_inner * (bead_count - 2); | ||
// Insert the outer beads | ||
ret.bead_widths.insert(ret.bead_widths.begin(), outer_bead_width); | ||
ret.bead_widths.emplace_back(outer_bead_width); | ||
} | ||
else | ||
{ | ||
ret = parent->compute(thickness, bead_count); | ||
} | ||
|
||
const coord_t outer_factor_numerator = optimal_total_outer_walls_width * thickness; | ||
const coord_t outer_factor_denominator = current_total_outer_walls_width * (optimal_total_outer_walls_width + optimal_total_inner_walls_width); | ||
const coord_t inner_factor_numerator = optimal_total_inner_walls_width * thickness; | ||
const coord_t inner_factor_denominator = current_total_inner_walls_width * (optimal_total_outer_walls_width + optimal_total_inner_walls_width); | ||
// Filter out beads that violate the minimum inner wall widths and recompute if necessary | ||
const coord_t outer_transition_width = optimal_width_inner * minimum_variable_line_width; | ||
const bool removed_inner_beads = validateInnerBeadWidths(ret, outer_transition_width); | ||
if (removed_inner_beads) | ||
{ | ||
ret = compute(thickness, bead_count - 1); | ||
} | ||
|
||
// Multiply the bead-widths with the right factors: | ||
ret.bead_widths[0] = (ret.bead_widths[0] * outer_factor_numerator) / outer_factor_denominator; | ||
for (coord_t i_width = 1; i_width < (bead_count - 1); ++i_width) | ||
// Ensure that the positions of the beads are distributed over the thickness | ||
resetToolPathLocations(ret, thickness); | ||
|
||
return ret; | ||
} | ||
|
||
coord_t RedistributeBeadingStrategy::getOptimalOuterBeadWidth(const coord_t thickness, const coord_t optimal_width_outer, const coord_t minimum_width_inner) | ||
{ | ||
const coord_t total_outer_optimal_width = optimal_width_outer * 2; | ||
coord_t outer_bead_width = thickness / 2; | ||
if (total_outer_optimal_width < thickness) | ||
{ | ||
if (total_outer_optimal_width + minimum_width_inner > thickness) | ||
{ | ||
ret.bead_widths[i_width] = (ret.bead_widths[i_width] * inner_factor_numerator) / inner_factor_denominator; | ||
outer_bead_width -= minimum_width_inner / 2; | ||
} | ||
ret.bead_widths[bead_count - 1] = (ret.bead_widths[bead_count - 1] * outer_factor_numerator) / outer_factor_denominator; | ||
|
||
// Update the first half of the toolpath-locations with the updated bead-widths (starting from 0, up to half): | ||
coord_t last_coord = 0; | ||
coord_t last_width = 0; | ||
for (coord_t i_location = 0; i_location < bead_count / 2; ++i_location) | ||
else | ||
{ | ||
ret.toolpath_locations[i_location] = last_coord + (last_width + ret.bead_widths[i_location]) / 2; | ||
last_coord = ret.toolpath_locations[i_location]; | ||
last_width = ret.bead_widths[i_location]; | ||
outer_bead_width = optimal_width_outer; | ||
} | ||
} | ||
return outer_bead_width; | ||
} | ||
|
||
// NOTE: Don't have to alter the middle toolpath if there's any, it'll already be at half thickness. | ||
void RedistributeBeadingStrategy::resetToolPathLocations(BeadingStrategy::Beading& beading, const coord_t thickness) | ||
{ | ||
const size_t bead_count = beading.bead_widths.size(); | ||
beading.toolpath_locations.resize(bead_count); | ||
|
||
// Update the last half of the toolpath-locations with the updated bead-widths (starting from thickness, down to half): | ||
last_coord = thickness; | ||
last_width = 0; | ||
for (coord_t i_location = bead_count - 1; i_location >= bead_count - (bead_count / 2); --i_location) | ||
{ | ||
ret.toolpath_locations[i_location] = last_coord - (last_width + ret.bead_widths[i_location]) / 2; | ||
last_coord = ret.toolpath_locations[i_location]; | ||
last_width = ret.bead_widths[i_location]; | ||
} | ||
if (bead_count < 1) | ||
{ | ||
beading.toolpath_locations.resize(0); | ||
beading.total_thickness = thickness; | ||
beading.left_over = thickness; | ||
return; | ||
} | ||
|
||
// Update the first half of the toolpath-locations with the updated bead-widths (starting from 0, up to half): | ||
coord_t last_coord = 0; | ||
coord_t last_width = 0; | ||
for (size_t i_location = 0; i_location < bead_count / 2; ++i_location) | ||
{ | ||
beading.toolpath_locations[i_location] = last_coord + (last_width + beading.bead_widths[i_location]) / 2; | ||
last_coord = beading.toolpath_locations[i_location]; | ||
last_width = beading.bead_widths[i_location]; | ||
} | ||
|
||
return ret; | ||
// Handle the position of any middle wall (note that the width will already have been set correctly): | ||
if (bead_count % 2 == 1) | ||
{ | ||
beading.toolpath_locations[bead_count / 2] = thickness / 2; | ||
} | ||
|
||
// Update the last half of the toolpath-locations with the updated bead-widths (starting from thickness, down to half): | ||
last_coord = thickness; | ||
last_width = 0; | ||
for (size_t i_location = bead_count - 1; i_location >= bead_count - (bead_count / 2); --i_location) | ||
{ | ||
beading.toolpath_locations[i_location] = last_coord - (last_width + beading.bead_widths[i_location]) / 2; | ||
last_coord = beading.toolpath_locations[i_location]; | ||
last_width = beading.bead_widths[i_location]; | ||
} | ||
|
||
// Ensure correct total and left over thickness | ||
beading.total_thickness = thickness; | ||
beading.left_over = thickness - std::accumulate(beading.bead_widths.cbegin(), beading.bead_widths.cend(), static_cast<coord_t>(0)); | ||
} | ||
|
||
bool RedistributeBeadingStrategy::validateInnerBeadWidths(BeadingStrategy::Beading& beading, const coord_t minimum_width_inner) | ||
{ | ||
// Filter out bead_widths that violate the transition width and recalculate if needed | ||
const size_t unfiltered_beads = beading.bead_widths.size(); | ||
auto inner_begin = std::next(beading.bead_widths.begin()); | ||
auto inner_end = std::prev(beading.bead_widths.end()); | ||
beading.bead_widths.erase( | ||
std::remove_if(inner_begin, inner_end, | ||
[&minimum_width_inner](const coord_t width) | ||
{ | ||
return width < minimum_width_inner; | ||
}), | ||
inner_end); | ||
return unfiltered_beads != beading.bead_widths.size(); | ||
} | ||
|
||
} // namespace cura |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this import.