-
Notifications
You must be signed in to change notification settings - Fork 57
[WIP] Trapezoidal Decomposition Prototype for Discussion #658
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
base: master
Are you sure you want to change the base?
Conversation
tigercosmos
left a comment
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.
@yungyuc Could you take a look and discuss if the current PR approach is correct? I want to add trapezoidal decomposition with further support of polygon boolean operations. However, after studying a while, I am still confusing what to do next.
| struct Trapezoid | ||
| { | ||
| value_type top_y; ///< Y-coordinate of the top horizontal edge | ||
| value_type bottom_y; ///< Y-coordinate of the bottom horizontal edge | ||
| segment_type left_edge; ///< Left boundary segment of the trapezoid | ||
| segment_type right_edge; ///< Right boundary segment of the trapezoid | ||
| size_t source_polygon; ///< ID of the polygon this trapezoid came from | ||
| }; |
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.
Struct for trapazoid
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.
Trapezoid should be taken outside to be a normal class (with the name Trapezoid3d, class declaration, private data with prefix, and accessors). It will be so useful that you may just create TrapezoidPad using this PR.
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.
Got it. Thanks.
| * @throws std::out_of_range if polygon_id is invalid | ||
| * @throws std::invalid_argument if polygon has fewer than 3 nodes | ||
| */ | ||
| std::vector<Trapezoid> const & decompose_polygon(size_t polygon_id); |
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.
The API for trapazoidal decomposition.
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.
Create a helper class TrapezoidalDecomposition (or a more accurate name you like), and rename PolygonPad::decompose_polygon() to PolygonPad::decompose_to_trapezoid() for accurate semantics. Call the helper class from decompose_to_trapezoid().
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.
Got it.
| * @param p2 Second polygon | ||
| * @return Vector of polygons forming the union | ||
| */ | ||
| std::vector<polygon_type> boolean_union(polygon_type const & p1, polygon_type const & p2); |
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.
The part I am not sure. Do we want to have operation APIs in the PolygonPad? The operation is between polygon and polygon, or polygon pad or polygon pad?
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.
Good point. Area Boolean is set Boolean, so it operates between sets, so PolygonPad and PolygonPad.
Our goal is volumetric Boolean, but we need to make the area Boolean very clear before moving forward.
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.
Create helper classes AreaBooleanUnion, AreaBooleanIntersection, and AreaBooleanDifference for the 3 operations you are prototyping here.
Use naive implementation at this point. Add unit tests to make sure they have Python interface and do not crash. Leave TODO comments in the tests saying results are not confirmed to be correct and the correctness is left for a follow-up PR.
This is good progress.
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 see. Thanks!
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.
Did you use any AI tool to help? I am curious about it. If you did please specify.
This is good progress. Points to address:
- Make a normal (non-nested)
Trapezoid3dandTrapezoidPad. - Do not use hash table and do not use hash table to vectors.
- Create a helper class
TrapezoidalDecomposition(or a more accurate name you like). - Rename
PolygonPad::decompose_polygon()toPolygonPad::decompose_to_trapezoid()for accurate semantics. - Create helper classes
AreaBooleanUnion,AreaBooleanIntersection, andAreaBooleanDifferencefor the 3 operations. - For the area Boolean, add unit tests to make sure they have Python interface and do not crash. Leave TODO comments in the tests saying results are not confirmed to be correct and the correctness is left for a follow-up PR.
| struct Trapezoid | ||
| { | ||
| value_type top_y; ///< Y-coordinate of the top horizontal edge | ||
| value_type bottom_y; ///< Y-coordinate of the bottom horizontal edge | ||
| segment_type left_edge; ///< Left boundary segment of the trapezoid | ||
| segment_type right_edge; ///< Right boundary segment of the trapezoid | ||
| size_t source_polygon; ///< ID of the polygon this trapezoid came from | ||
| }; |
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.
Trapezoid should be taken outside to be a normal class (with the name Trapezoid3d, class declaration, private data with prefix, and accessors). It will be so useful that you may just create TrapezoidPad using this PR.
| // - Point location query structure | ||
| // - Integration with node lists for synchronization | ||
| /// Cache of trapezoidal decompositions, keyed by polygon ID. Computed lazily on first access. | ||
| std::unordered_map<size_t, std::vector<Trapezoid>> m_decompositions; |
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.
Do not use hash table. Hash table is the last resort when (1) you run out of ideas or (2) you run out of time.
A has table to vector is even worth: tons of dynamic memory allocation. It is bound to be slow.
This is why you need TrapezoidPad.
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.
Got it.
| * @throws std::out_of_range if polygon_id is invalid | ||
| * @throws std::invalid_argument if polygon has fewer than 3 nodes | ||
| */ | ||
| std::vector<Trapezoid> const & decompose_polygon(size_t polygon_id); |
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.
Create a helper class TrapezoidalDecomposition (or a more accurate name you like), and rename PolygonPad::decompose_polygon() to PolygonPad::decompose_to_trapezoid() for accurate semantics. Call the helper class from decompose_to_trapezoid().
| * @param p2 Second polygon | ||
| * @return Vector of polygons forming the union | ||
| */ | ||
| std::vector<polygon_type> boolean_union(polygon_type const & p1, polygon_type const & p2); |
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.
Good point. Area Boolean is set Boolean, so it operates between sets, so PolygonPad and PolygonPad.
Our goal is volumetric Boolean, but we need to make the area Boolean very clear before moving forward.
| * @param p2 Second polygon | ||
| * @return Vector of polygons forming the union | ||
| */ | ||
| std::vector<polygon_type> boolean_union(polygon_type const & p1, polygon_type const & p2); |
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.
Create helper classes AreaBooleanUnion, AreaBooleanIntersection, and AreaBooleanDifference for the 3 operations you are prototyping here.
Use naive implementation at this point. Add unit tests to make sure they have Python interface and do not crash. Leave TODO comments in the tests saying results are not confirmed to be correct and the correctness is left for a follow-up PR.
This is good progress.
|
@yungyuc Yes, I used AI and spent around 5–6 hours exploring how to implement the trapezoidal decomposition. In the end, I wasn’t happy with the outcome and wasn’t confident about the design direction. I removed most of the implementation, kept what seemed to be the most reasonable interface, and opened this PR for discussion. |
6 hours on the trapezoidal algorithm are not too many, but spending time to study it and then prototype incrementally will be more productive. Dividing tasks is an art that we cannot count on tools already. |
The PR is a prototype of trapezoidal decomposition for the further support of polygon operations.