Skip to content
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

Fix wall ordering #1562

Merged
merged 72 commits into from
Feb 22, 2022
Merged
Changes from 1 commit
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
8b0455c
prevent stitching from reversing wall printing direction
BagelOrb Jan 11, 2022
e3a8620
stitch variable width walls
BagelOrb Jan 8, 2022
68e63a4
fix inset index and only stitch polygonal wall lines
BagelOrb Jan 8, 2022
decf0bd
Move wall stitching to separate function
BagelOrb Jan 8, 2022
a5726b5
stitch odd gap filling walls
BagelOrb Jan 10, 2022
7619882
don't stitch odd wall polylines to even wall polygons
BagelOrb Jan 11, 2022
663f2f1
Function to get the nesting information from a Polygons object
BagelOrb Jan 19, 2022
e7afd76
helper functions
BagelOrb Jan 20, 2022
089f575
WallToolPaths::getWeakOrder to compute the ordering requirements on w…
BagelOrb Jan 20, 2022
7f549a7
unit test for WallToolPaths::getWeakOrder
BagelOrb Jan 20, 2022
9ba6211
make wall order better
BagelOrb Jan 20, 2022
c27ee8a
option to use insertion method to path optimization
BagelOrb Jan 21, 2022
bd06470
Fix ordering requirements in complex cases with outer thin walls
BagelOrb Jan 22, 2022
203f3ff
fix insertion optimization and allow for weak order constraints
BagelOrb Jan 22, 2022
987f826
let getWeakOrder work on a flat vector of lines
BagelOrb Jan 22, 2022
732bd94
Optimize wall order using insertion ordering with weak adjacency orde…
BagelOrb Jan 22, 2022
3168a9d
Fix ironing being applied on wrong extruder(s)
BagelOrb Feb 7, 2022
3dde748
Extract feature specific settings out of InsetOrderOptimizer
BagelOrb Feb 7, 2022
4d9af7e
clean up unused functionality in InsetOrderOptimizer
BagelOrb Jan 22, 2022
02edffc
move getWeakOrder to InsetOrderOptimizer
BagelOrb Jan 22, 2022
1862f64
remove region_id from line
BagelOrb Jan 22, 2022
41d382b
lil cleanup
BagelOrb Jan 23, 2022
1a0478b
Mark polygonal ExtrusionLines as such
BagelOrb Jan 23, 2022
f23d587
remove debug svg output
BagelOrb Jan 23, 2022
1f54e3c
const correctness and reference correctness for Polygon
BagelOrb Jan 24, 2022
8c79bd5
std::hash for PolygonPointer
BagelOrb Jan 24, 2022
e120eac
Disallow containers of references
BagelOrb Jan 24, 2022
d042813
make order requirements native to pathOrderOptimizer
BagelOrb Jan 24, 2022
c2e5cc0
implement order requirements on selection sort path optimizer
BagelOrb Jan 24, 2022
d3819c6
remove insertion sort path order optimizer
BagelOrb Jan 24, 2022
6af2530
fix order by inset
BagelOrb Jan 24, 2022
0351841
lil comment
BagelOrb Jan 24, 2022
8405d57
fix check for open polyline
BagelOrb Jan 24, 2022
6916172
lil doc
BagelOrb Jan 24, 2022
4022c93
remove unused ExtrusionLine::chopEnd
BagelOrb Jan 24, 2022
7fa80c6
remove unused Polygon::set(paths)
BagelOrb Jan 24, 2022
e68b581
remove unused PathOrderOptimizer::Path helper functions
BagelOrb Jan 24, 2022
c61bced
Flip back optimize_wall_printing_order to it's original meaning
BagelOrb Jan 25, 2022
5fe9532
documentation and debugging for even contour walls which we haven't b…
BagelOrb Jan 25, 2022
12b9a05
lil: allow for odd wall lines to be closed
BagelOrb Jan 25, 2022
3f30291
fix inner contour not being generated on all sides
BagelOrb Jan 25, 2022
0b65752
Fix maximal single beads length.
BagelOrb Jan 25, 2022
970d3ab
remove small odd gap fillers
BagelOrb Jan 25, 2022
ed68d52
Force disconnecting generated paths when jumping to a new region.
BagelOrb Jan 26, 2022
c34457d
Ensure CW direction of arachne walls and ensure cutting at 3-way inte…
BagelOrb Jan 26, 2022
dd824f3
lil: logError instead of assert
BagelOrb Jan 26, 2022
d841021
debug output
BagelOrb Jan 26, 2022
e55763c
fix removing small line after another small line has just been removed
BagelOrb Jan 26, 2022
c4a0c18
prevent printing order infinite loop
BagelOrb Jan 26, 2022
3cb2fde
Fix handling of shared vertices in polygon::getNesting
BagelOrb Jan 26, 2022
69146b8
Revert "fix inner contour not being generated on all sides"
BagelOrb Jan 26, 2022
d4b0c03
fix asserts for more unusual cases
BagelOrb Jan 26, 2022
827ec02
lil fix for top surface skin ironing
BagelOrb Feb 7, 2022
0f6e26d
clarify test condition
BagelOrb Feb 17, 2022
eabfeae
remove debugging code
BagelOrb Feb 17, 2022
4b0fa03
lil code style and debug check
BagelOrb Feb 17, 2022
8bde507
Simpler getRegionOrder implementation
BagelOrb Feb 21, 2022
8c33703
remove unused polygon::getNesting(.)
BagelOrb Feb 21, 2022
e745b8f
fix order between too far away lines
BagelOrb Feb 21, 2022
04ebf5f
fix support infill wall
BagelOrb Feb 21, 2022
ae378b2
remove printing of infill walls which are never generated
BagelOrb Feb 21, 2022
39e4d71
fix unit test for ExtrusionLine
BagelOrb Feb 21, 2022
f99f911
lil code style and doc
BagelOrb Feb 22, 2022
3962373
make alternate_walls code more explicit
BagelOrb Feb 22, 2022
5a2f5dd
remove superfluous double assignment
BagelOrb Feb 22, 2022
e6e114f
lil refactor for readability
BagelOrb Feb 22, 2022
63ec958
prevent walls which should have been closed from being printed in rev…
BagelOrb Feb 22, 2022
5cc439e
increase searching radius of getRegionOrder a little
BagelOrb Feb 22, 2022
766c239
lil brackets to prevent compile warning
BagelOrb Feb 22, 2022
5f06212
make arachne stitch prevention choice more clear
BagelOrb Feb 22, 2022
fdbf8c1
remove ExtrusionJunction::region_id
BagelOrb Feb 22, 2022
d837179
remove edge_t::region
BagelOrb Feb 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 175 additions & 3 deletions src/PathOrderOptimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,27 @@ class PathOrderOptimizer
*/
size_t start_vertex;

Point getStartLocation() const
{
return (*converted)[start_vertex];
}

Point getEndLocation() const
{
if (is_closed)
{
return getStartLocation();
}
if (start_vertex == 0)
{
return converted->back();
}
else
{
return converted->front();
}
}

/*!
* Whether the path should be closed at the ends or not.
*
Expand Down Expand Up @@ -146,12 +167,13 @@ class PathOrderOptimizer
* it into a polygon.
* \param combing_boundary Boundary to avoid when making travel moves.
*/
PathOrderOptimizer(const Point start_point, const ZSeamConfig seam_config = ZSeamConfig(), const bool detect_loops = false, const Polygons* combing_boundary = nullptr, const bool reverse_direction = false)
PathOrderOptimizer(const Point start_point, const ZSeamConfig seam_config = ZSeamConfig(), const bool detect_loops = false, const Polygons* combing_boundary = nullptr, const bool reverse_direction = false, bool selection_optimization = true)
: start_point(start_point)
, seam_config(seam_config)
, combing_boundary((combing_boundary != nullptr && !combing_boundary->empty()) ? combing_boundary : nullptr)
, detect_loops(detect_loops)
, reverse_direction(reverse_direction)
, selection_optimization(selection_optimization)
{
}

Expand Down Expand Up @@ -207,7 +229,20 @@ class PathOrderOptimizer
}
}
}


if (selection_optimization)
{
optimizeSelection();
}
else
{
optimizeInsertion();
}

combing_grid.reset();
}
void optimizeSelection()
{
//Add all vertices to a bucket grid so that we can find nearby endpoints quickly.
const coord_t snap_radius = 10_mu; // 0.01mm grid cells. Chaining only needs to consider polylines which are next to each other.
SparsePointGridInclusive<size_t> line_bucket_grid(snap_radius);
Expand Down Expand Up @@ -357,7 +392,132 @@ class PathOrderOptimizer
{
std::swap(optimized_order, paths);
}
combing_grid.reset();
}

void optimizeInsertion()
{
if (seam_config.type == EZSeamType::USER_SPECIFIED)
{
start_point = seam_config.pos; // WARNING: is this correct?!
}

for (Path& path : paths)
{
if (!path.is_closed)
{
continue; //Can't pre-compute the seam for open polylines since they're at the endpoint nearest to the current position.
}
if (path.converted->empty())
{
continue;
}
path.start_vertex = findStartLocation(path, seam_config.pos);
}

std::list<std::pair<coord_t, Path>> optimized_order; // Distance to and next location

std::function<coord_t (Point, Point)> getDistance =
combing_boundary ?
std::function<coord_t (Point, Point)>( [this](Point from, Point to) { return getCombingDistance(from, to); } )
: std::function<coord_t (Point, Point)>( [this](Point from, Point to) { return getDirectDistance(from, to); } );

Path& first_path = paths.front(); // arbitrarily select the first path to add
coord_t distance = std::sqrt(getDistance(start_point, first_path.getStartLocation()));
optimized_order.emplace_back(distance, first_path);

for (size_t to_be_inserted_idx = 1; to_be_inserted_idx < paths.size(); to_be_inserted_idx++)
{
typename std::list<std::pair<coord_t, Path>>::iterator best_pos_it = optimized_order.end();
coord_t best_detour_distance = std::numeric_limits<coord_t>::max();
coord_t best_dist_before_to_here = 0;
coord_t best_dist_here_to_after = 0;
bool best_is_flipped = false;

Path& to_be_inserted = paths[to_be_inserted_idx];
Point start_here = to_be_inserted.getStartLocation();
Point end_here = to_be_inserted.getEndLocation();

// TODO: use grid

for (auto pos_after_it = optimized_order.end(); ; --pos_after_it) // update is performed at the end of the for loop
{
auto pos_before_it = pos_after_it;
pos_before_it--;
Path* path_before = (pos_after_it == optimized_order.begin()) ? nullptr : &pos_before_it->second;
Path* path_after = (pos_after_it == optimized_order.end()) ? nullptr : &pos_after_it->second;
Point loc_before = path_before? path_before->getEndLocation() : start_point;
coord_t current_distance = path_after? pos_after_it->first : 0;

coord_t dist_before = std::sqrt(getDistance(loc_before, start_here));
coord_t dist_after = path_after ? std::sqrt(getDistance(end_here, path_after->getStartLocation())) : 0;

if ( ! to_be_inserted.is_closed)
{
coord_t flipped_dist_before = std::sqrt(getDistance(loc_before, end_here));
coord_t flipped_dist_after = path_after ? std::sqrt(getDistance(start_here, path_after->getStartLocation())) : 0;
best_is_flipped = false;
if (flipped_dist_before + flipped_dist_after < dist_before + dist_after)
{
dist_before = flipped_dist_before;
dist_after = flipped_dist_after;
best_is_flipped = true;
}
}

coord_t detour_distance = dist_before + dist_after - current_distance;
if (detour_distance < best_detour_distance) // Less of a detour than the best candidate so far.
{
best_pos_it = pos_after_it;
best_detour_distance = detour_distance;
best_dist_before_to_here = dist_before;
best_dist_here_to_after = dist_after;
}

if (pos_after_it == optimized_order.begin())
{
break;
}
}

if (best_is_flipped)
{
assert( ! to_be_inserted.is_closed);
to_be_inserted.start_vertex = (to_be_inserted.start_vertex != 0) * (to_be_inserted.converted->size() - 1);
}
if (best_pos_it != optimized_order.end())
{
best_pos_it->first = best_dist_here_to_after;
}
optimized_order.insert(best_pos_it, std::make_pair(best_dist_before_to_here, to_be_inserted));

}

if (seam_config.type == EZSeamType::SHORTEST)
{ // only recompute the start when needed
Point current_location = start_point;
for (auto& [dist, path] : optimized_order)
{
path.start_vertex = findStartLocation(path, current_location);
current_location = path.getStartLocation();
}
}

//Apply the optimized order to the output field. Reverse if ordered to reverse.
paths.clear();
if (reverse_direction)
{
for (auto it = optimized_order.rbegin(); it != optimized_order.rend(); ++it)
{
paths.emplace_back(it->second);
}
}
else
{
for (auto& [fist, path] : optimized_order)
{
paths.emplace_back(path);
}
}
}

protected:
Expand Down Expand Up @@ -411,6 +571,18 @@ class PathOrderOptimizer
*/
bool reverse_direction;

/*!
* The core algorithm to use:
* - Selection sort based
* - Insertion sort based
*
* Selection does a greedy approach of finding the next best candidate to append to the result.
* Insertion considers the best location within the result to insert each path.
*
* Insertion sort can be wildly inefficient when polylines haven't been stitched.
*/
bool selection_optimization;
BagelOrb marked this conversation as resolved.
Show resolved Hide resolved

/*!
* Find the vertex which will be the starting point of printing a polygon or
* polyline.
Expand Down