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

Fix wall ordering #1562

merged 72 commits into from
Feb 22, 2022

Conversation

BagelOrb
Copy link
Contributor

@BagelOrb BagelOrb commented Jan 24, 2022

This PR builds on #1554
That PR should be merged first - or it will be automatically merged with this one.

This PR comes with an accompanying frontend PR: Ultimaker/Cura#11334
Please merge both simultaneously.

This PR solves a number of bugs all relating to the order in which walls are printed:

  • Arachne splits wall polygons into several segments with extra starts/stops when Optimize Wall Printing Order is enabled, i.e. when Order Walls by Inset is disabled. (JIRA ticket CURA-8896)
  • Arachne then printed the separate segments belonging to each outline/hole region together, rather than printing whole polygons. It enforced ordering by region harder than stitching wall lines into polygons.
  • The order in which walls are printed had some bugs in 4.13 and in Arachne which could cause some polygons to be printed out of order (inner to outer vs outer to inner)
  • The gap filler walls were printed after the skin in 4.13, but in Arachne even before some of the walls when order was set to Outer to Inner.
  • Arachne would sometimes leave tiny travel gaps in between a single wall 'gap filler', because stitching wasn't implemented properly.
  • Wall lines were sometimes printed in the wrong direction (counter clockwise instead of clockwise).

Code changes:

  • This PR applies the PolylineStitcher introduced in Polyline handling fixes #1554 to form closed wall polygons before simplifying them en passing them to the optimizer.
  • Because a stitched ExtrusionLine can have multiple region_id s associated with it, the InsetOrderOptimizer needed to be overhauled.
  • I've implemented a proper weak order based on the adjacency between inset polygons, which is computed in InsetOrderOptimizer and used in PathOrderOptimizer.

Behavior changes:

  • Gap fillers should always be printed after their enclosing wall, and depending on whether we use Center Last ordering, after all walls.
  • Optimize wall order enabled / Order walls by inset disabled now strictly enforces the Inner-to-outer order per region, while wall polygons pertaining to two regions are not cut up, but printed before/after the other walls pertaining to both those regions.

Benefits:

  • The quality of surfaces is better for complex layers with holes in them and/or with thin parts.
  • The travel time is reduced.
  • Alternate Wall Direction works again
  • Order Inner Wals by Inset is re-renamed back to Optimize Wall Printing Order and the behavior is reflipped to the old behavior

Possibly affected behavior:

  • All wall ordering, z seam config etc.
  • of each wall feature type: Walls, infill walls, skin walls, support walls, support bottom walls, support infill walls, raft walls

Before:
image

After:
image

UM3_santa.3mf.renamed.zip

Before:
image

After:
image

UM3_perimeter_hole_connections.3mf.renamed.zip

The following items are not addressed by this PR, but came up during review of the surrounding code and during testing:

  • The description of Wall Transitioning Angle is wholly incorrect. The Transitioning Angle controls how often Arachne will introduce odd walls. A small transitioning angle means that transitioning between even and odd number of wall lines only happens for very sharp geometry. Reducing the Transitioning Angle reduces the number and length of odd gap filler segments. The Transitioning Angle has nothing to do with the angle of a transition; that angle is fully determined by the Wall Transition Length. The Wall Transitioning Angle is one of the most important Arachne settings, because it determines how much of the toolpaths are determined by Arachne, and how much uses normal constant width offsets.
  • ExtrusionLine.simplify() only works correctly for open polylines, not for closed polygons. Also you might want to remove the code duplication with Polygons.simply().
  • The Z seam config is currently used for all walls, rather than only the outer wall - as it was in 4.13.
  • PathOrderOptimizer::isLoopingPolyline returns true for polylines which have a total length smaller than coincident_point_distance
  • Wall Ordering Center Last can now become its own setting. Inner to Outer and Outer to Inner should be able to be configured separately from Print Odd Gap Filler Walls After All Even Walls
  • The starts of polylines are not communicated to the frontend. They don't show up as white squares in the layer view.
  • The gap filler walls don't appear yellow in the layer view any more, but maybe that's for the better.
  • The idea to stitch odd polylines to the polygonal walls at a Split reduces the number of starts/stops even further, but this feature has not been implemented.
  • In the original Arachne library the ends of non-stitched lines were chopped off so that there would be less overextrusion at the 3-way intersection of a split. This functionality was lost when the library got merged into Cura. This feature has not yet been reimplemented.

@BagelOrb
Copy link
Contributor Author

BagelOrb commented Jan 25, 2022

Fixes:
#1495
Ultimaker/Cura#10957

@BagelOrb
Copy link
Contributor Author

BagelOrb commented Jan 25, 2022

Results of tests on Applicatas dataset (assembled from models from the internet). Tested on S5 with Generic PLA at 0.1mm layer height.

Travel times:
Benchy:
4.13: 0:09
Arachne beta 2: 0:11
this PR: 0:10

ACAM:
4.13: 2:04
Arachne beta 2: 1:18
this PR: 1:32

airhose splitter
4.13: 0:11
Arachne beta 2: 0:11
this PR: 0:09

Alahamra
4.13: 0:02
Arachne beta 2: 0:04
this PR: 0:03

David:
4.13: 0:53
Arachne beta 2: 1:03
this PR: 0:58

Decking fixture:
4.13: 0:26
Arachne beta 2: 0:29
this PR: 0:27

Jet engine Combustion_and_HPT_Casing
4.13: 0:32
Arachne beta 2: 0:39
this PR: 0:36

In all cases this PR reduced the Arachne travel time; in some cases this PR reduced travel time even more than before Arachne.

@rburema
Copy link
Member

rburema commented Jan 26, 2022

Sort of the same story for this one, except in this case the build-server is down for some reason. Can you run the test manually & report back? Otherwise we can do that, but it might slow down the process a bit.

@BagelOrb
Copy link
Contributor Author

Here's the order on a complex model with a lot of internal holes: (Outer to Inner, Optimize Wall Ordering, Gap fillers always (perhaps immediately) after enclosing wall)

Outer and inner walls are printed intermittently, but the ordering is preserved everywhere:
image

image

image

Now we can print some of the small islands of inner walls:
image

Here wall 2 is printed on the right side, then it takes a gap filler of index 2 to the left side, and then continues to print inset 3 for both islands, before moving on to a gap filler of index 2 farther away:
image

image

Notice how the gap filler of index 3 is printed together with the pieces of wall with index 3:
image

@BagelOrb
Copy link
Contributor Author

With the above model
UMS5_Stand.3mf.renamed.zip

These are the travel times:
Inside to Outside: 0:49
Outside to Inside: 0:49
Center Last: 0:42
Arachne beta 2, Center Last: 0:53
4.13, Inner before outer: 0:41

@BagelOrb BagelOrb force-pushed the variable_walls_stitching branch 2 times, most recently from e3177f7 to 1409d46 Compare January 27, 2022 10:24
@richfelker
Copy link

Is this PR in a state where it's suitable for testing? I'm the reporter of #1495 and would like to test if so.

@BagelOrb
Copy link
Contributor Author

BagelOrb commented Feb 3, 2022

Yes it is. If you are able to test from source then we would be very interested in your findings.

Before it will be merged some developers will review my code and some more tests will be performed, but there's always a chance for bugs to fall through, so I would be very happy if you could help our testing efforts.

@richfelker
Copy link

OK, I can confirm at least for my test case in that report that the problem is fixed.

@richfelker
Copy link

Unfortunately it segfaulted trying to slice a Benchy.

@richfelker
Copy link

The crash occurs with skin_monotonic=true which I always use. Here's the backtrace (sorry probably lacks sufficient debug info I didn't build with):
curacrash.txt

@BagelOrb
Copy link
Contributor Author

BagelOrb commented Feb 4, 2022

Could you please save your project as a 3mf file, put it in a zip and upload it here?

@richfelker
Copy link

I don't use or have the Cura gui, just CuraEngine. I can probably make you a minimal reproducing testcase with that.

@richfelker
Copy link

OK, all that's required to reproduce the issue is skin_monotonic=true and top_bottom_pattern_0=zigzag with the baseline fdmprinter.def.json and the standard Benchy STL.

@BagelOrb
Copy link
Contributor Author

BagelOrb commented Feb 5, 2022

Thanks. This is a problem on master. Fixed in fa196db

@richfelker
Copy link

OK, good to know. It was not present in master but appeared when checking out your PR branch which is a ways behind master and apparently doesn't merge cleanly. I'll try the merge or wait for you to get it merged upstream.

@BagelOrb
Copy link
Contributor Author

BagelOrb commented Feb 5, 2022

The bug was in master since somehwere last week, so perhaps you hadn't pulled he bug in yet. I'll merge master into this branch soon.

Copy link
Contributor

@casperlamboo casperlamboo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed part I would submit (the incomplete) review earlier. Expect part 2/2 of the review soon.

src/utils/PolylineStitcher.h Outdated Show resolved Hide resolved
Comment on lines 119 to 199
if (wall_idx >= wall_lines.size())
{
wall_lines.resize(wall_idx + 1);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As wall_lines was just cleared before it's size is always 0, making the statement wall_idx >= wall_lines.size() always true

Suggested change
if (wall_idx >= wall_lines.size())
{
wall_lines.resize(wall_idx + 1);
}
wall_lines.resize(wall_idx + 1);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally I also don't really get why you would want to resize the vector to wall_idx. Seems like the vector needs a size of closed_polygons.size()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't find that code and github can't find the commit. Looks like you're looking at outdated commits. Idk.

src/WallToolPaths.cpp Outdated Show resolved Hide resolved
src/WallToolPaths.cpp Outdated Show resolved Hide resolved
src/utils/polygon.cpp Outdated Show resolved Hide resolved
src/WallToolPaths.h Outdated Show resolved Hide resolved
src/utils/polygon.cpp Outdated Show resolved Hide resolved
src/utils/polygon.cpp Outdated Show resolved Hide resolved
Comment on lines 1595 to 1597
auto it = node_to_index.find(child);
assert(it != node_to_index.end() && "Each PolyNode should be mapped to the corresponding Polygon index!");
ret[index].emplace_back(it->second);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this part is deserving of a comment. Why shoudn't it equal node_to_index.end(), and why push it->second to ret[index]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. This exact line doesn't appear anymore in the latest branch. Please check if the new code is still unclear to you.

src/PathOrderOptimizer.h Outdated Show resolved Hide resolved
@Ghostkeeper
Copy link
Collaborator

Fixes #1552.

Simply use a SparseGrid to see which lines are adjacent to each other,
rather than using nesting informtoin and info from region_idx.
This makes the code simpler to read,
the algorithm more reobust to when stitching hasn't been accomplished where it should have,
while have negligle impact in slicing time.
We didn't check the distance between two lines properly, so wall lines which weren;t adjacent could end up with an order constraint.
This effectively meant that in some cases Optimize Wall Printing Order acted as if it wasn't enabled.
Fixes merge comflicts with ca83659
Contributes to CURA-8067
Fixes an issue with code duplication introduced in ca83659
Contributes to CURA-8067
The test assumed that the pat hwas closed.
Only for closed polygons is a size of 2 or 1 not allowed.
src/FffGcodeWriter.cpp Outdated Show resolved Hide resolved
src/InsetOrderOptimizer.cpp Outdated Show resolved Hide resolved
src/InsetOrderOptimizer.cpp Show resolved Hide resolved
src/InsetOrderOptimizer.cpp Outdated Show resolved Hide resolved
src/utils/ExtrusionLine.cpp Outdated Show resolved Hide resolved
src/SkeletalTrapezoidation.h Show resolved Hide resolved
src/utils/PolylineStitcher.h Show resolved Hide resolved
src/WallToolPaths.cpp Outdated Show resolved Hide resolved
src/WallToolPaths.cpp Outdated Show resolved Hide resolved
src/SkeletalTrapezoidation.cpp Outdated Show resolved Hide resolved
…erse direction

Polygonal walls with even index should always be closed into polygons,
but if they somehow weren't closed, we should at least retain their printing direction.
Is better for finding neighboring walls in uncommon cases where the vertices of consectuive walls are not next to each other.
@BagelOrb
Copy link
Contributor Author

Mostly just code conventions and documentation.

Please pay special attention when reviewing the last two commits, since they are behavioral changes/fixes.

An extrusion junction lies on an edge of the MAT, but
since each edge has two half edges which may belong to a different region,
the extrusion junction should have recorded two region_ids.
The region_id recorded in the junction was therefore not reliable,
and code depending on it was very bug-prone.
It's not used anymore.
@@ -38,13 +39,14 @@ void TopSurface::setAreasFromMeshAndLayerNumber(SliceMeshStorage& mesh, size_t l
}
}

bool TopSurface::ironing(const SliceMeshStorage& mesh, const GCodePathConfig& line_config, LayerPlan& layer) const
bool TopSurface::ironing(const SliceDataStorage& storage, const SliceMeshStorage& mesh, const GCodePathConfig& line_config, LayerPlan& layer, const FffGcodeWriter& gcode_writer) const
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't touch the order of ironing lines, only of the walls of ironing.

@BagelOrb BagelOrb mentioned this pull request Mar 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants