-
Notifications
You must be signed in to change notification settings - Fork 101
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
avoid recursion in csg tree #1086
Conversation
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.
Thanks! Looks like a good direction, though a bit out of my wheelhouse. I'll be curious to understand where the bug is...
CondensedMatter16 hits #970 after this PR. I guess this is due to the code now performs optimization more aggressively, and there are more things that got feed into BatchUnion... |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1086 +/- ##
==========================================
+ Coverage 91.72% 91.87% +0.14%
==========================================
Files 30 30
Lines 5910 5882 -28
==========================================
- Hits 5421 5404 -17
+ Misses 489 478 -11 ☔ View full report in Codecov by Sentry. |
This slows down the overall test slightly, from 26180ms to 26877ms, ~2.5%. This is due to CondensedMatter64 being slower, which is due to If I tune the BatchUnion threshold from 1000 to 100, it is now taking 25641ms, ~2% faster. Not sure if this is general enough though. |
Will add documentation tmr, a bit tired today. |
Anyway, decided to write the documentation now :) About the original bug: The idea is that the flattening takes O(n) time in the old implementation, which makes it problematic because in the worst case we can have O(n) flattening operations as well, which gives us O(n^2) time. As an example, consider the following:
The implementation here doesn't attempt to do flattening when we construct the node. In fact, it is impossible to avoid this quadratic behavior if we perform (all) flattening when we construct the nodes, because there will be O(n^2) nodes if we do that. The algorithm only does one pass over the tree, and do flattening on-the-fly. Each node is moved only once. This makes it O(n). |
src/csg_tree.cpp
Outdated
node->Transform(transform))); | ||
else | ||
stack.push_back(std::make_shared<CsgStackFrame>( | ||
false, op, transform, children, |
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.
I don't quite follow this logic: either we add the node to the set of children, or we add a frame to the stack that contains this node and all the children? Do the children belong to this node or not (when the function is called)?
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.
You can view adding a stack frame as "we will call this node recursively".
Maybe I should add a recursion pseudocode to make things clearer, this code is quite indirect...
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.
See if it is better with the recursive pseudocode...
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.
Thanks, that's much clearer!
maybe wait for me to merge it, I just thought of some minor changes. |
After thinking about it, the fast path for testing |
Fixes #989.
This refactors the code into a single loop that does dfs on the csg tree, and perform flattening on-the-fly.
There are still some failures, I guess this is due to shared nodes being evaluated in a weird way... Will try to fix it soon. But for now I think the logic is mostly there and should be ready for review.
For comparison: