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

New Tree Support Implementation #1282

Merged
merged 120 commits into from
Apr 25, 2023
Merged

Conversation

ThomasRahm
Copy link
Contributor

@ThomasRahm ThomasRahm commented Jul 2, 2020

Tree Support V2

I reimplemented the tree support, as the current implementation does not meet my expectations.
I have a fork where a compiled version of a Cura with this Tree Support modification can be downloaded.

How the new tree support looks:

New tree support

Feedback I have gotten recently

"I just want to thank you for these. With your stock settings I am getting amazing results . As someone coming from Prusa/superslicer , and new to any version of Cura, i'm shocked that supports can come off this cleanly , and leave no trace on the print."1

"I've been having a bunch of issues with the Main Cura tree supports not properly getting all of my overhangs, I just installed your fork and it looks like a vast improvement! "2

"The tree supports in Cura create a massive trunk that can surround whole parts in some cases, I always wanted a tool to cut archs out of those trunks to reduce the amount of filament wasted, or an arch-shaped blocker that would achieve the same result, but your tree supports seem to achieve a similar result"3

"What you've done here is awesome work, and I thank you for it."4

"I want to show to all of you the good work of this mod, in my opinion it is a good support way."5

"I'm still using this as my daily and tbh I think it's a shame it's getting slept on by not just Cura but the likes of prusaslicer/superslicer/etc. It's so much better than the stock Cura tree supports"6

Currently known issues:

  • Slicing with cross support and 0% support density causes the slice progress to hang. This is not an issue of my implementation and to my understanding also occurs in the official version. Bug report of this issue.
  • There are issues when Minimum Support X/Y Distance is larger than Support X/Y Distance. This can trigger an error message if the version displaying them is used. I will not fix this one, except by maybe disallowing it in the UI, as I think the assumption that a minimum is not larger than the expected one is reasonable.

Settings:

Recommended settings

To see the tree support specific settings set the Setting Visibility to all.

I recommend enabling roofs and setting a reasonable Minimum Support Roof Area (I use 10 mm²). My implementation will make sure to correctly support the lines generated by the support roof. If no roof is possible the branches will try to avoid moving for as many layer as the roof is thick. They will generate as regular tree support branches, as i have serious doubts about the stability of roofs in branches.
Do not use concentric floor. It will generate as intended (by my understanding at least), but I suspect it will not print (it will be obvious when you see it) when support infill is low.
Set Minimum support area to 0, higher values may cause very pointy overhangs to not be supported (as intended by my current understanding of this feature)

New Tree Support Settings

The changes for the fdmprinter.def.json can be found here.

Tree Support Preferred Branch Angle vs Tree Support Maximum Branch Angle

Tree Support Maximum Branch Angle is ONLY used when Tree Support Preferred Branch Angle is not enough to avoid the model. This causes branches to only move with Tree Support Preferred Branch Angle to merge with other branches.

Idea behind this is that Tree Support Preferred Branch Angle is a very stable angle, but if some parts could not be supported with the smaller angle the larger angle can be used to reach these parts.

Slow vs Fast branch angle

Tree Support Diameter Increase To Model

Branches that can reach the buildplate and branches that cannot are able to merge. This setting limits how much the diameter of the branch connecting with the model can be increased by such merges.

This setting is intended to specify how important it is that connections with the model are avoided (the lower this setting, the less contact area with the model).

Small Diameter Increase To Model:
Small Diameter increase to model

Large Diameter Increase To Model:
Large Diameter increase to model

Tree Support Minimum Height To Model

If only a few layers space are left between the position where the branch begins and where it ends, removing the support is impossible. This setting removes all branches that have a height lower than Tree Support Minimum Height To Model to prevent this. Only branches that rest on the model are removed.

Small Minimum Height To Model:
Small Diameter increase to model

Large Minimum Height To Model:
Large Diameter increase to model

Tree Support Initial Layer Diameter

Branches try to ensure to reach this diameter at layer 0.

Small Initial Layer Diameter:
Initial Layer Diameter

Large Initial Layer Diameter:
Initial Layer Diameter

Tree Support Branch Density

A percentage of space that has to be filled by the top most layer of a branch aka the layer that supports the overhang. When a roof is supported the overhang is the line of the roof. When no support roof is used it behaves similarly to the supporting (top most) layer when using regular support. High values (depends on your other settings) of >35% can cause the resulting support areas to overlap. This causes cura to merge them to a single area, as cura assumes every support area is supported by support areas below. If a low support infill is used this assumption is wrong. There is nothing reasonable I can do to prevent this, so in this case adjust your support infill accordingly.

Simulated regular support pattern:
Simulate regular support pattern

Tree Support Tip Diameter

Defines the diameter of the top most support area of a branch.
Using a large diameter without having a reasonable large support density would obviously not print well.

Can replace tips with roof!

Happens automatically when Minimum Support Roof Area is smaller than a circle with diameter Tree Support Tip Diameter and roofs are enabled.

Large Tip Diameter with minimum roof area being small:
Tip radius large interface

Large Tip Diameter with minimum roof area being large:
Tip Radius large2

Small Tip Diameter:
Small Tip Diameter

Large Tip Diameter:
Large Tip Diameter

Support Interface Priority

This setting defines how support roof and regular support (e.g. from other branches) interact.

Support preferred(Support Area Overwrites Interface Area):
Support Area Overwrites Interface Area

Interface preferred(Interface Area Overwrites Support Area):
Interface Area Overwrites Support Area

Support lines preferred(Support Lines Overwrite Interface Area):
Support Lines Overwrite Interface Area

Interface Lines preferred(Interface Lines Overwrite Support Area. This one will not be what you want when Support Wall Count > 0):
Interface Lines Overwrite Support Area

Both Overlap (This causes filament be extruded twice at the same location (Once the support and once the roof). This may cause issues when printing. Use with care!):
Both Overlap

Tree Support Limit Branch Reach and Tree Support Optimal Branch Range

Limit how far each branch should travel from the point it supports. This can make the support more sturdy, but will increase the amount of branches. Branches can violate this value to reach their destination.

Tree Support Limit Branch Reach Disabled:
Tree Support Limit Branch Reach Disabled
Tree Support Limit Branch Reach Enabled with a small distance:
Tree Support Limit Branch Reach Enabled with a small distance

Tree Support Rest Preference

The preferred placement of the support structures. Note that the buildplate is assumed to be also a flat surface (If not i think you have bigger issues than this setting)!
Only visible when the support can rest on the model.

Buildplate:
Buildplate
On any flat surface:
On any flat surface

Tree Support Branch Diameter and Tree Support Branch Diameter Angle behave like in the current tree support implementation, but Tree Support Branch Diameter Angle is ignored when a diameter increase would invalidate a branch, as a small branch has a higher chance of supporting the model than no branch at all.

What does it do better:

Uses significant less filament.

Also makes the branches of my implementation much easier to remove from the model.

Current tree support:
Current tree support

My tree support:
New tree support

Comparison of material usage:
Comparison

Disclaimer: This is only the material used for support structures, not the whole model. The measuring unit is mm of 1.75mm diameter filament, as displayed in Cura. Measurement was done in the 4.7.1 version, and exact numbers could differ slightly.

Can handle large branch angles.

Current tree support:
Current tree support

My tree support:
New tree support

Supports Roofs more consistently.

The images show the bottom-most roof layer and a few layers of the branches below. In the current tree support some lines of the roof have a large distance from one point where support is below it to the next. My implementation ensures consistent spacing.

Current tree support:
Current tree support

My tree support:
New tree support

Branches avoid support blocker.

Branches avoid support blocker

Setting applicable now on a per-mesh basis. All tree support related settings are now settable per mesh and support related settings are correctly used by the tree support. This may increase slicing time drastically for settings that are not only relevant on the top most support layers.

So to avoid slicing times being longer by factor 10 try not to slice 10 different models with different branch radii (Slicing 2 models with different settings should not take much longer than slicing 2 times).

Trees with settings that are incompatible with each other can not merge and will avoid each other.

Few settings differences allow merges:
Different interface settings can merge

More settings of the regular support are now supported by the tree support

The newly supported settings are: Support Distance Priority, Support Horizontal Expansion, Support Interface Horizontal Expansion, Minimum Support Roof Area (Some of these were enabled in the UI, but did not do anything if I understand the code correctly) and Minimum Support Area (though I would recommend leaving this setting at 0).

Slices faster on multicore cpus.

Measured was the time it takes to generate the tree support for the test model (hobgoblin).

Slice performance graph

Settings used for benchmarking:
Profile for current tree support
Profile for my tree support implementation

Benchmarking was done in the 4.10 Version.

Further attributes this implementation has:

If a model is sliced twice on the same machine, the same trees will result. If this is somehow not the case something went very wrong. (Trees generated on systems with a different amount of threads could theoretically differ).
Every point that can be supported with the given Branch Angle limitations, will be supported when the support can only rest on the build plate. This means some other settings may be paused to ensure such behavior. For example: Tree Support Branch Diameter Angle will be paused if a radius increase would cause a branch to become invalid.

How the algorithm generating the trees works

This explains the idea behind the algorithm. As such it is simplified a fair bit to avoid explaining fixes for some edge cases.

0. The model

The model

1. Calculate avoidance An avoidance is an area that has to be avoided to achieve certain given results. For example an area in which a branch would be unable to reach the buildplate has to be avoided, if the support is not allowed to rest on the model. This idea is identical to the current tree support. My implementation just uses a lot more avoidances(slow, fast, slow to model, fast to model, fast without holes, fast without holes to model), and precalculates them in parallel. Avoidances are calculated from the bottom up.

Avoidance

2. Generate influence areas An influence area is an area,in which every point of the represented current branch, can reach all support points it has to support. Is is similar to an avoidance, but other that the avoidance, it represents possible center point areas, rather than excluding impossible ones. If two influence areas intersect, only the intersection will be used going forward. This causes branches to merge. Influence areas are calculated from the top downwards, as they grow from the overhang downwards.

Influence areas

Influence areas 2

3. Generate tree path Using the influence areas, the center points of the circles that build the branches are set. This happens from the bottom up.

Tree path

4. Draw Tree The circles, which center-point was calculated in 3. are drawn. Here also happens a fair bit of post processing to avoid edge-cases by the fact that the drawn radius in the tip of a branch is always increased (for stability reasons), even if a normal circle would not fit.

Resulting tree

Possible future improvements:

Automatically increase branch height when the angle is large.

Further Information

I did not make the mini hobgoblin I used to test. I used it because it cloak makes it very hard to slice in a way that the cloak is supported while not having a connection of the branch to the model.
All screen-shots of the current tree support were made using version 4.7.1.
Thank you to DerGenaue for providing the images explaining the algorithm and creating the graphs out of the performance data.

@Ghostkeeper
Copy link
Collaborator

Ghostkeeper commented Jul 5, 2020

A couple of comments while you're working on this, to address the questions you've posed and some concerns:

  • Code style and naming conventions for C++ is a combination of the Generic Code Conventions of Ultimaker and the exceptions/expansions of that geared towards C++.
  • New settings have to be added to fdmprinter.def.json in the front-end. Here are the changes that originally introduced tree support, as an example. If you're on Windows you can edit that file in your Program Files to test. For Linux and MacOS that file will be packed inside the application file, which is a little harder to modify sometimes. It's also pretty easy for us to fix if you need some help.
  • This is a big pull request. We're talking several thousand lines of code here, a few new features as to customisation on how the branches are generated, and refactoring. This goes against some of the etiquette on how pull requests are presented. It's not necessarily a problem, but you have to understand that this is seriously hard to plan into a schedule. It also imposes serious risk for us: There are likely going to be new bugs in this code (unavoidable) and once we need to debug this, we are going to be less familiar with this code. This makes it harder to approve of a pull request.
  • The collision volumes were originally implemented with the same technique as what you're doing now: Multi-threaded generation of the volumes at different radii. It's still supposed to be multi-threaded, but it now lazily generates them in order to reduce the total amount of work, rather than pre-generating them. We did performance tests when this was implemented to compare performance, using different sorts of computers (few cores vs. many cores, old memory and new memory sticks) and different sorts of models (tall/small, organic/artificial) and found improvements for the most common cases.
  • We've learned to avoid creating settings for every little thing that could be adjusted. If nobody is going to adjust a setting, you might as well not have the setting. This makes a feature less overwhelming for someone who is not so involved in Cura or in your feature. From your description for instance I wouldn't know why people would want to adjust the support_tree_angle_slow setting or why they'd need that much control over the resolution at which the collision volumes are calculated.
  • Normally we prefer to have only one implementation of a feature. This is something that our users sometimes don't like (e.g. when we replaced the Prime Tower implementation), but it's important for the developers to be able to maintain an application with as many features as Cura. We're 6 programmers working with 2.5 million lines of code here, so we try to prevent having to maintain 5 different implementations of Tree Support that we added over time, so to say. For that we must be sure that the new implementation is capable of filling all the use cases of the old implementation. If some use cases are still possible but less than ideal (e.g. increased printing time) that may be acceptable.
  • For Cura 4.7, Tree Support is getting particular attention to try to get it out of the Experimental section. You might see some merge collisions and it might even alleviate your concerns as to why you decided to rewrite it.
  • That problem you found with the bridge settings adjusting the line directions is known and currently accepted. It's hard to ensure that the line directions of support are always perpendicular because that involves breaking up the support into zones with different line directions which is not beneficial to the strength of the supports or the quality of the overhangs either. I'd say that your fix is not proper then (as you describe it) because it would cause it to go wrong in different cases then.

We didn't review your code yet though. This is only a reaction to the description you posted on the pull request.

@ThomasRahm
Copy link
Contributor Author

ThomasRahm commented Jul 7, 2020

Thank you for your feedback.

Regarding the bullet points:

  1. Thank you very much, i will change my code over time as soon as i have time for it.

  2. Thanks, i did not know it was this easy :)
    I added a preliminary settings file to my description above.

  3. I understand. One of my main reasons to open the draft was that a friend wanted to be able to share the resulting binary with a friend, and i did not feel comfortable sharing it without publishing the source.

  4. I suspect the difference is that i only calculate the collision volumes up to the highest required layer, so collision volumes with a high radius may only be calculated for a few layer, instead of for the whole model.
    I am sure though that currently the lazy generation does not happen multi-threaded as i believe the comment:\warning This class is NOT currently thread-safe and should not be accessed in OpenMP blocks in TreeSupport.h.

  5. I agree and have reduced the amount of available settings.

  6. I did include the old implementation only because i believe every change breaks someones work-flow, and i did try to avoid that.
    My implementation aims to behave superior in every way and be a complete replacement. As such i now removed the old tree support.

  7. I am happy to hear that tree support gets extra attention in 4.7, and will try to ensure my implementation remains superior ;)
    I do not expect to be done with the documentation before its release as my exams are at the end of the month.

  8. I feared as much. This means i will have to check whether a skin area is a bridge, and what the line orientation will be. I will have to investigate how to get to this information.

@Ghostkeeper
Copy link
Collaborator

I did include the old implementation only because i believe every change breaks someones work-flow, and i did try to avoid that.

True. It's a concession we've needed to make. Our position on it has so far been that those people can stick with the old Cura version if they liked the workflow that one provided, rather than trying to pack all dozens of Cura versions in one release.

@Ghostkeeper
Copy link
Collaborator

On point 8, honestly it's probably easier on yourself and on the code base if you drop that feature! It's not in the expected behaviour now, and while the result will be better in the short term, if that makes the code harder to maintain in the long term it's also going to hurt. So you're welcome to try fixing it, but keep in mind that code complexity is something we'll look at too.

@ThomasRahm
Copy link
Contributor Author

Hi, i would like to release a version with my tree support implementation for others to be able to beta test it.
For this i would just upload a zip with a complete compiled cura with the treesupport replaced to the release section of my github fork.
I already modified the version from 4.9 to 4.9_TS2 to avoid issues with cached definitions.
Is there some issue with me doing it this way?

@Ghostkeeper
Copy link
Collaborator

No, I expect that would work fine. Maybe choose carefully which operating system(s) you'll release on.

I wonder how you'll know that your Cura version is being used, though? If you get no bug reports, is that a sign that it's bug free, or that nobody found your version?

@Ghostkeeper
Copy link
Collaborator

I should also say that reviewing and testing 5000 lines of C++ code is no small task. Might take quite a while to get that in, especially considering there is not going to be any push from our managers to merge this, I expect. It kind of hinges on us being able to explain well why this change is necessary.

@ThomasRahm
Copy link
Contributor Author

Thanks for the response :)
I currently plan to post a link to my treesupport version on reddit. I hope that the post will get enough attention, so that i can get feedback and bug reports to evaluate the situation in addition to enabling my treesupport to show its worth. I plan on releasing for windows only, as im going to assume that linux users are more likely able to compile it themselves. I dont know yet when i will have enough time available to be able to all this, as i want to be able to fix potential bugs fast when they come up, though i hope to find time within a month.

rburema and others added 17 commits March 21, 2023 20:01
…reas to be not supported. Also some small tweaks that maybe could prevent the same issue.
# Conflicts:
#	include/TreeModelVolumes.h
#	include/TreeSupport.h
Make the minimum increase per step configurable via the class. Set to 1/2 line-width in general. Also fix for negative offset values, which this was used with all the time, which my earlier div-by-0 stopgap-fix didn't take into account.

CURA-10464
Also don't rely on fudge-length anymore, make dependant on 1/2 line-width. I don't think this function is supposed to take negative offsets, like the other one, but please check my assumption in review.

CURA-10464
It doesn't really matter that much that the branches are circular, as long as they are circular 'enough'. Given the gigantic number of branches a model may have just under a large overhang, unioning these circles takes a long time.

CURA-10464
The cipper union algorithm seems to be written for a small number of complex polygons, rather than a large number of simple ones. This workaround seems to work very well in case there is, say, a large number of mostly overlapping circles that need to be unioned that where added to a single Polygons object.

CURA-10464
CURA-10464

Co-authored-by: Casper Lamboo <c.lamboo@ultimaker.com>
rburema and others added 11 commits April 6, 2023 18:24
Quick test to see if Scripta works on this branch

[CURA-10415]
…e branches). This includes porting a function from PrusaSlicer that intersects a Polygon with an AABB. Fixed a small bug related to line orientation for simulated support lines.
…orm a lower density structure below it instead of placing tips directly below the rooflines (which could cause tip-areas to merge, causing nothing to be supported)
@casperlamboo casperlamboo merged commit a11681d into Ultimaker:main Apr 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PR: Community Contribution 👑 Community Contribution PR's
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants