-
Notifications
You must be signed in to change notification settings - Fork 55
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.
cpp/modmesh/universe/polygon.hpp
Outdated
| 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.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @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.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @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.
cpp/modmesh/universe/polygon.hpp
Outdated
| 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.
cpp/modmesh/universe/polygon.hpp
Outdated
| // - 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.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @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().
cpp/modmesh/universe/polygon.hpp
Outdated
| * @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.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @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. |
cpp/modmesh/universe/polygon.hpp
Outdated
| } | ||
|
|
||
| TrianglePad( | ||
| TrianglePad( |
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.
GitHub's diff is weird here. There is new added Trapezoid3d and 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.
Since this is a large diff, the diff issue needs to be fixed. The messy diff stops reasonable tracking in the future.
Please reorder the new code to make diff looks good. Use a follow-up refactoring PR to reorder after this one.
tests/test_polygon3d.py
Outdated
| self.assertFalse(polygon1.is_same(polygon2)) | ||
| self.assertTrue(polygon1.is_not_same(polygon2)) | ||
|
|
||
| # TODO: Verify and implement boolean operations once the C++ side is complete. # noqa: E501 |
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.
Put TODO for now and only verify the interface.
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 waive flake8 E501 for comments other than URL. Fix the comment length instead.
cpp/modmesh/universe/polygon.hpp
Outdated
| std::shared_ptr<trapezoid_pad_type> m_trapezoids; | ||
| std::vector<ssize_type> m_begins; | ||
| std::vector<ssize_type> m_ends; |
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.
No hash table now.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @tparam T floating-point type | ||
| */ | ||
| template <typename T> | ||
| class AreaBooleanUnion |
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.
Helper classes as requsted.
| * @throws std::out_of_range if polygon_id is invalid | ||
| * @throws std::invalid_argument if polygon has fewer than 3 nodes | ||
| */ | ||
| std::pair<size_t, size_t> decompose_to_trapezoid(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.
Fixed the naming.
| } | ||
|
|
||
| template <typename T> | ||
| std::pair<size_t, size_t> PolygonPad<T>::decompose_to_trapezoid(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.
Get the index range of the trapazoids in the pad after decomposition.
|
@yungyuc the aforementioned issues are addressed. Please help take a look, 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.
Good progress. Points to address:
- Reorder the new code to make diff looks good.
- Rename
TrapezoidalDecomposer::Trapezoidto something very different fromTrapezoid3dorTrapezoidand make it private. - Reduce memory footprint for coordinates for
TrapezoidalDecomposer::YTrap. - Return
PolygonPadfromAreaBooleanUnion::compute,AreaBooleanIntersection::compute,AreaBooleanDifference::compute.
cpp/modmesh/universe/polygon.hpp
Outdated
| } | ||
|
|
||
| TrianglePad( | ||
| TrianglePad( |
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.
Since this is a large diff, the diff issue needs to be fixed. The messy diff stops reasonable tracking in the future.
Please reorder the new code to make diff looks good. Use a follow-up refactoring PR to reorder after this one.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @tparam T floating-point type | ||
| */ | ||
| template <typename T> | ||
| class Trapezoid3d |
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.
This (line 813) is the new Trapezoid3d. Add inline annotation close to the line to make discussions clear.
cpp/modmesh/universe/polygon.hpp
Outdated
| SimpleArray<T> const & y1, | ||
| SimpleArray<T> const & x2, | ||
| SimpleArray<T> const & y2, | ||
| SimpleArray<T> const & x3, |
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.
Diff algorithm has a hard time knowing that you are inserting a block of new code. So we need to choose a better location for the new code to make diff happy. Things like this happen, though inconvenience.
cpp/modmesh/universe/polygon.hpp
Outdated
| * In polygon decomposition, vertical lines are extended from each vertex to partition | ||
| * the polygon into trapezoids. | ||
| */ | ||
| struct 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.
It's confusing to have the inner class Trapezoid while there is a standalone Trapezoid3d. Rename this internal class name and make it private.
I suggest a name like YTrap because your scanlines are perpendicular to the Y-axis.
cpp/modmesh/universe/polygon.hpp
Outdated
| */ | ||
| struct Trapezoid | ||
| { | ||
| value_type top_y; |
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 are using scanlines perpendicular to the Y-axis and should take advantage of that constraint. You do not need flexibility at the moment. (You will in the future, but do not over-engineer.)
Use real number for member data. Don't use points.
value_type lower_y, upper_y;
value_type lower_x0, lower_x1, upper_x0, upper_x1;
value_type lower_z0, lower_z1, upper_z0, upper_z1;It takes only 10 real numbers for the trapezoid whose lower and upper edges are perpendicular to the Y-axis. Your old struct takes 14 real numbers. Don't be so wasteful.
value_type top_y;
value_type bottom_y;
segment_type left_edge;
segment_type right_edge;I usually see lower-left, lower-right, upper-left, and upper-right in geometry code. Let's use the convention and avoid top and bottom.
cpp/modmesh/universe/polygon.hpp
Outdated
| /** | ||
| * Trapezoid structure for decomposition. | ||
| * | ||
| * A trapezoid is a quadrilateral with two parallel horizontal edges (top and bottom). |
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.
Remove the trivial statement to explain trapezoid. People not understanding trapezoid cannot contribute.
Add descriptions for the fact that the struct is for traps whose bottom and top lines perpendicular to Y-axis. It's the most important point to understand the algorithm.
cpp/modmesh/universe/polygon.hpp
Outdated
| * @param polygon_id2 ID of second polygon | ||
| * @return Vector of polygons forming the union | ||
| */ | ||
| std::vector<Polygon3d<T>> compute(polygon_pad_type & pad, size_t polygon_id1, size_t polygon_id2); |
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.
Return PolygonPad from AreaBoolean*::compute.
41a1e4c to
a4317a4
Compare
a4317a4 to
8e85e92
Compare
|
@yungyuc I addressed the aforementioned issues. Cloud you take a look again? |
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.
Only cosmetic issues:
- Some overload signature of
TrapezoidPad::set()andTrapezoidPad::set_at()is too long. Break them with proper indentation. (Leave an inline annotation at the improved line to remind me to review.) - Do not waive flake8 E501 for comments other than URL. Fix the comment length instead.
cpp/modmesh/universe/polygon.hpp
Outdated
| x3_at(i) = x3; | ||
| y3_at(i) = y3; | ||
| } | ||
| void set_at(size_t i, value_type x0, value_type y0, value_type z0, value_type x1, value_type y1, value_type z1, value_type x2, value_type y2, value_type z2, value_type x3, value_type y3, value_type z3) |
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.
This line is too long. Break it with proper indent.
cpp/modmesh/universe/polygon.hpp
Outdated
| z3(i) = p3.z(); | ||
| } | ||
| } | ||
| void set(size_t i, value_type x0_value, value_type y0_value, value_type x1_value, value_type y1_value, value_type x2_value, value_type y2_value, value_type x3_value, value_type y3_value) |
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.
This line is too long. Break it with proper indent.
cpp/modmesh/universe/polygon.hpp
Outdated
| x3(i) = x3_value; | ||
| y3(i) = y3_value; | ||
| } | ||
| void set(size_t i, value_type x0_value, value_type y0_value, value_type z0_value, value_type x1_value, value_type y1_value, value_type z1_value, value_type x2_value, value_type y2_value, value_type z2_value, value_type x3_value, value_type y3_value, value_type z3_value) |
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.
This line is too long. Break it with proper indent.
tests/test_polygon3d.py
Outdated
| self.assertFalse(polygon1.is_same(polygon2)) | ||
| self.assertTrue(polygon1.is_not_same(polygon2)) | ||
|
|
||
| # TODO: Verify and implement boolean operations once the C++ side is complete. # noqa: E501 |
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 waive flake8 E501 for comments other than URL. Fix the comment length instead.
469d230 to
d8fb45d
Compare
d8fb45d to
ac56bae
Compare
yungyuc
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.
The PR is a prototype of trapezoidal decomposition for the further support of polygon operations.
- Write informative summary in the PR first comment and commit log. This PR added more than 1.4k lines of code and deserve a good summaries.
And consider to review the code formatting again. There is at least one defect but could be more.
| pass | ||
| # TODO: Verify and implement boolean operations | ||
| # once the C++ side is complete. | ||
|
|
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 blank line is misplaced. You can fix it in this PR or in a later one.
The PR is a prototype of trapezoidal decomposition for the further support of polygon operations.