8000 Fix checking if polygon is convex by Czaki · Pull Request #68 · 4DNucleome/PartSegCore-compiled-backend · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix checking if polygon is convex #68

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

Merged
merged 9 commits into from
Mar 13, 2025
Merged

Fix checking if polygon is convex #68

merged 9 commits into from
Mar 13, 2025

Conversation

Czaki
Copy link
Contributor
@Czaki Czaki commented Mar 12, 2025

Summary by CodeRabbit

  • New Features

    • Added a utility to compute centroids of point clusters.
    • Introduced functionality to assess whether a polygon is simple.
    • Enhanced polygon validation with improved checks for convexity.
  • Refactor

    • Improved geometric orientation handling by using clear, descriptive indicators.
  • Tests

    • Expanded the testing suite with new cases covering various polygon configurations and rotations for robust geometric validation.
    • Added assertions to verify polygon convexity before triangulation.

Copy link
Contributor
coderabbitai bot commented Mar 12, 2025

Walkthrough

This update introduces an enumeration type Orientation to replace integer literals in the _orientation routine, improving clarity in representing geometric orientation. A new centroid function is added for computing the average position of a set of points. An is_simple_polygon function is introduced to verify polygon simplicity, and the existing _is_convex function is refined accordingly. Additionally, new test utilities and cases are provided to support polygon generation, rotation, and convexity validation.

Changes

File(s) Summary
src/PartSegCore_compiled_backend/triangulation/intersection.hpp Introduces Orientation enum (COLLINEAR, CLOCKWISE, COUNTERCLOCKWISE) and updates _orientation to return the enum instead of an integer.
src/PartSegCore_compiled_backend/triangulation/point.hpp Adds a new centroid function to compute the average (centroid) of a list of points.
src/PartSegCore_compiled_backend/triangulation/triangulate.hpp Adds is_simple_polygon to validate polygon simplicity and refines the _is_convex function using the new orientation logic.
src/tests/test_triangulate.py Introduces helper functions (generate_regular_polygon, generate_self_intersecting_polygon, rotation_matrix) and new tests for checking polygon convexity and triangulation, including cases for self-intersecting and rotated shapes.

Possibly related PRs

Poem

I'm a rabbit hopping through the code,
With enums and centroids lighting my road.
Polygons twist and turn, so neat,
In every angle, a rhythm, a beat.
Testing each curve with carrot delight,
Coding through day and coding through night! 🐰🥕

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05bb237 and 627fb15.

📒 Files selected for processing (1)
  • src/tests/test_triangulate.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test on windows-latest with Python 3.12
  • GitHub Check: Test on windows-latest with Python 3.11
  • GitHub Check: Test on windows-latest with Python 3.10
  • GitHub Check: Test on windows-latest with Python 3.9
🔇 Additional comments (7)
src/tests/test_triangulate.py (7)

211-211: Great addition of a precondition check!

Adding this assertion ensures that the polygon being tested is actually convex before proceeding with the triangulation test. This helps validate the test's assumptions and prevents false positives.


697-702: Well-implemented utility function for regular polygon generation.

This function elegantly generates regular polygons using numpy's vectorized operations. The ability to create polygons in both clockwise and counter-clockwise order (via the reverse parameter) is valuable for comprehensive testing.


704-714: Good implementation with helpful documentation.

The function for generating self-intersecting polygons is well-documented and includes a proper assertion to ensure odd vertex count. The explanation of how it works (by doubling the angle range) is clear and helpful.


716-724: Clean and correct implementation of rotation matrix.

The rotation matrix function correctly converts degrees to radians and uses the proper mathematical formulas. The docstring clearly explains the purpose and parameters.


726-726: Good test angle selection.

The selected angles (0°, 5°, 75°, 95°, 355°) provide a good range of test cases, including edge cases near 0°/360° and different quadrants.


729-737: Comprehensive test for non-convex polygons.

This test function thoroughly verifies that self-intersecting polygons are correctly identified as non-convex across different orientations, sizes, and rotations. The parametrization ensures good test coverage.


739-747: Thorough test for convex polygons.

This test function comprehensively verifies that regular polygons are correctly identified as convex, regardless of rotation angle, vertex count, or orientation. The parameterization with various polygon sizes (from triangles to 20-sided polygons) ensures robust testing.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Czaki Czaki marked this pull request as ready for review March 12, 2025 23:48
@Czaki Czaki requested a review from Copilot March 12, 2025 23:48
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR improves the convex polygon checking by adding assertions in the triangulation tests and introduces new utility functions and tests for generating regular and star-shaped (pentagram) polygons. The changes include:

  • Adding an extra assertion in test_triangulate_polygon_py_convex to ensure the polygon is convex.
  • Introducing helper functions (generate_regular_polygon, pentagram, rotation_matrix) for generating test polygons.
  • Adding new parametrized tests that validate the convexity check on rotated and self-intersecting polygons.
Comments suppressed due to low confidence (2)

src/tests/test_triangulate.py:707

  • Using 4pi in the pentagram function may be confusing; consider adding a comment to explain why a 4pi range is needed for generating the star shape.
angles = np.linspace(0, 4 * np.pi, n, endpoint=False)

src/tests/test_triangulate.py:704

  • [nitpick] Consider renaming 'pentagram' to 'generate_pentagram' for consistency with 'generate_regular_polygon'.
def pentagram(reverse):

@Czaki
Copy link
Contributor Author
Czaki commented Mar 12, 2025

@coderabbitai review

Copy link
Contributor
coderabbitai bot commented Mar 12, 2025
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/PartSegCore_compiled_backend/triangulation/intersection.hpp (1)

132-153: Update function documentation to match enum return type.

The function implementation correctly returns the Orientation enum values, but the documentation still refers to returning integer values 0, 1, and 2.

/**
 * Determines the orientation of the triplet (p, q, r).
 *
 * @param p The first point.
 * @param q The second point.
 * @param r The third point.
 *
-* @return 0 if p, q and r are collinear.
-*         1 if the triplet (p, q, r) is in a clockwise orientation.
-*         2 if the triplet (p, q, r) is in a counterclockwise orientation.
+* @return Orientation::COLLINEAR if p, q and r are collinear.
+*         Orientation::CLOCKWISE if the triplet (p, q, r) is in a clockwise orientation.
+*         Orientation::COUNTERCLOCKWISE if the triplet (p, q, r) is in a counterclockwise orientation.
 */
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1878399 and fb47059.

📒 Files selected for processing (4)
  • src/PartSegCore_compiled_backend/triangulation/intersection.hpp (3 hunks)
  • src/PartSegCore_compiled_backend/triangulation/point.hpp (1 hunks)
  • src/PartSegCore_compiled_backend/triangulation/triangulate.hpp (3 hunks)
  • src/tests/test_triangulate.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Build wheels on macos-13
  • GitHub Check: Build wheels on ubuntu-latest
  • GitHub Check: Build wheels on windows-latest
🔇 Additional comments (9)
src/PartSegCore_compiled_backend/triangulation/triangulate.hpp (3)

606-634: Good implementation of polygon simplicity check.

The function correctly checks if a polygon is simple by verifying that all angles are in non-decreasing order when traversing the vertices. The calculation handles angle normalization properly.


648-664: Good enhancements to convexity check.

The changes to the _is_convex function improve the code by:

  1. Handling edge cases (polygons with fewer than 3 points)
  2. Early returning true for triangles (which are always convex)
  3. Using the new Orientation enum for better readability
  4. Proper initialization of orientation variable

665-690: Well-integrated simplicity check.

The function correctly uses the polygon's orientation to determine whether to check simplicity in forward or reverse order. This ensures correct handling of both clockwise and counterclockwise polygon definitions.

src/PartSegCore_compiled_backend/triangulation/intersection.hpp (1)

115-119: Good introduction of Orientation enum.

Replacing integer literals with named constants improves code readability and maintainability. This enum clearly represents the three possible orientations of points.

src/tests/test_triangulate.py (5)

697-702: Well-implemented regular polygon generator.

The function correctly generates regular polygons with configurable parameters. The use of numpy functions for angle generation and coordinate calculation is efficient.


704-711: Good pentagram generator for testing self-intersecting shapes.

The function correctly generates a pentagram by using angles that span 4π radians rather than 2π, creating the star pattern. This is useful for testing self-intersecting polygons.


713-720: Correct implementation of 2D rotation matrix.

The function correctly implements a 2D rotation matrix using numpy. The conversion from degrees to radians is properly handled.


725-732: Good test for self-intersecting polygons.

This test ensures that self-intersecting shapes like pentagrams are correctly identified as non-convex, regardless of rotation angle or winding order.


734-742: Comprehensive test for convex polygon detection.

This test verifies convexity detection across a range of regular polygons with different vertex counts, rotation angles, and winding orders. This provides thorough coverage of the convexity check functionality.

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/PartSegCore_compiled_backend/triangulation/point.hpp (3)

211-223: Consider adding documentation for the centroid function.

The function correctly calculates the centroid of a collection of points and handles empty input appropriately. However, it would benefit from documentation comments that explain its purpose, parameters, and return value, similar to other functions in this file.

+/**
+ * Calculates the centroid (geometric center) of a set of points.
+ *
+ * If the input vector is empty, returns a point at the origin (0, 0).
+ * Otherwise, computes the average of all points' coordinates.
+ *
+ * @param point_list A vector of Point objects
+ * @return The centroid as a Point
+ */
Point centroid(const std::vector<Point> &point_list) {
  if (point_list.empty()) {
    return {0, 0};
  }
  Point res(0, 0);
  for (auto &point : point_list) {
    res.x += point.x;
    res.y += point.y;
  }
  res.x /= float(point_list.size());
  res.y /= float(point_list.size());
  return res;
}

220-221: Consider using static_cast for type conversion.

Replace C-style cast with static_cast for more explicit type conversion, which is preferred in modern C++.

-  res.x /= float(point_list.size());
-  res.y /= float(point_list.size());
+  res.x /= static_cast<float>(point_list.size());
+  res.y /= static_cast<float>(point_list.size());

212-214: Use consistent initialization style.

For consistency with the rest of the code, consider using the same initialization style throughout the function.

  if (point_list.empty()) {
-    return {0, 0};
+    return Point(0, 0);
  }
src/PartSegCore_compiled_backend/triangulation/intersection.hpp (1)

179-184: Use enum values in conditional checks for better clarity

While these comparisons will work due to implicit conversion between enum and int, it would be more consistent to use the enum values explicitly.

-if (o1 != o2 && o3 != o4) return true;
+if (o1 != o2 && o3 != o4) return true;

-if (o1 == 0 && _on_segment(p1, p2, q1)) return true;
-if (o2 == 0 && _on_segment(p1, q2, q1)) return true;
-if (o3 == 0 && _on_segment(p2, p1, q2)) return true;
-if (o4 == 0 && _on_segment(p2, q1, q2)) return true;
+if (o1 == Orientation::COLLINEAR && _on_segment(p1, p2, q1)) return true;
+if (o2 == Orientation::COLLINEAR && _on_segment(p1, q2, q1)) return true;
+if (o3 == Orientation::COLLINEAR && _on_segment(p2, p1, q2)) return true;
+if (o4 == Orientation::COLLINEAR && _on_segment(p2, q1, q2)) return true;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb47059 and 82eed0a.

📒 Files selected for processing (2)
  • src/PartSegCore_compiled_backend/triangulation/intersection.hpp (2 hunks)
  • src/PartSegCore_compiled_backend/triangulation/point.hpp (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test on windows-latest with Python 3.10
  • GitHub Check: Test on windows-latest with Python 3.9
  • GitHub Check: Test on windows-latest with Python 3.12
  • GitHub Check: Test on windows-latest with Python 3.11
🔇 Additional comments (3)
src/PartSegCore_compiled_backend/triangulation/intersection.hpp (3)

115-119: Great addition of an Orientation enum!

This is a good refactoring that replaces magic numbers with descriptive named constants, making the code more readable and self-documenting.


128-132: Documentation update correctly reflects the enum change

The function documentation has been properly updated to reference the new enum values instead of integer literals.


153-154: Return statements correctly use the new enum values

The function logic has been updated to properly return enum values instead of integer literals, which is consistent with the function signature change.

@Czaki Czaki requested a review from Copilot March 13, 2025 16:09
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR enhances polygon validation by improving convexity checks and expanding test coverage for various polygon configurations and rotations.

  • Added an assertion to validate convex polygons in the triangulation test.
  • Introduced helper functions to generate regular and self-intersecting polygons, as well as a rotation matrix function.
  • Added new test cases to verify behavior on rotated polygons and self-intersecting shapes.
Comments suppressed due to low confidence (2)

src/tests/test_triangulate.py:709

  • [nitpick] Consider adding an error message to the assertion to clarify that 'n' must be odd for generating a self-intersecting polygon.
assert n % 2 == 1

src/tests/test_triangulate.py:741

  • [nitpick] Consider renaming 'test_is_convex2' to a more descriptive name like 'test_regular_polygon_convex' to better convey its purpose.
def test_is_convex2(angle, n_vertex, reverse):

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/tests/test_triangulate.py (1)

716-722: Add type hints to rotation_matrix function.

While the implementation is correct, the function lacks type hints unlike the other new utility functions.

-def rotation_matrix(angle):
+def rotation_matrix(angle: float) -> np.ndarray:
    return np.array(
        [
            [np.cos(np.radians(angle)), -np.sin(np.radians(angle))],
            [np.sin(np.radians(angle)), np.cos(np.radians(angle))],
        ]
    )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f11a871 and e069591.

📒 Files selected for processing (1)
  • src/tests/test_triangulate.py (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Test on windows-latest with Python 3.12
  • GitHub Check: Test on windows-latest with Python 3.11
  • GitHub Check: Test on windows-latest with Python 3.10
  • GitHub Check: Test on windows-latest with Python 3.9
🔇 Additional comments (5)
src/tests/test_triangulate.py (5)

211-211: Good addition of convexity verification.

Adding the assertion to verify that the polygon is actually convex before testing ensures the triangulation algorithm is only tested with valid inputs. This makes the test more robust and better aligned with the function's preconditions.


697-702: Well-implemented polygon generation utility.

This function correctly implements regular polygon generation with proper type hints and parameterization. The ability to control orientation with the reverse parameter adds flexibility for testing various scenarios.


704-714: Good implementation of self-intersecting polygon generator.

The function ensures proper self-intersection by doubling the angle range to 4π. The assertion that checks for an odd number of vertices is a good safeguard to ensure the generated polygon will actually self-intersect as intended.


729-736: Comprehensive test for non-convexity of self-intersecting polygons.

Great use of parametrization to test multiple configurations of self-intersecting polygons. The test ensures that the is_convex function correctly identifies self-intersecting polygons as non-convex, regardless of rotation angle, vertex count, and orientation.


738-746: Thorough verification of convexity across polygon variations.

This test effectively verifies that regular polygons are correctly identified as convex under various conditions including rotation, different vertex counts, and orientation. The comprehensive parametrization ensures good test coverage.

Copy link
Contributor
@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/tests/test_triangulate.py (2)

716-722: Correctly implemented rotation matrix

The rotation matrix function is mathematically correct and properly converts the angle from degrees to radians using numpy's functions.

Consider adding a docstring to clarify that the angle is in degrees, since the function converts it to radians internally.

def rotation_matrix(angle: float) -> np.ndarray:
+    """Create a 2D rotation matrix for the given angle in degrees."""
    return np.array(
        [
            [np.cos(np.radians(angle)), -np.sin(np.radians(angle))],
            [np.sin(np.radians(angle)), np.cos(np.radians(angle))],
        ]
    )

738-745: Comprehensive test for convex polygons

This test thoroughly verifies that regular polygons maintain their convexity property after rotation, with good coverage across different vertex counts and orientations.

Consider renaming test_is_convex2 to something more descriptive like test_is_convex_regular_polygon to better reflect what it's testing.

-def test_is_convex2(angle, n_vertex, reverse):
+def test_is_convex_regular_polygon(angle, n_vertex, reverse):
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e069591 and ff7b775.

📒 Files selected for processing (1)
  • src/tests/test_triangulate.py (2 hunks)
🔇 Additional comments (5)
src/tests/test_triangulate.py (5)

211-211: LGTM: Improved input validation

Adding this assertion is good practice as it ensures the test correctly validates that input polygons are convex before proceeding with triangulation tests.


697-702: Well-implemented polygon generation utility

This helper function is well-implemented using numpy's vectorized operations. It provides a clean way to generate regular polygons for testing, including the ability to control orientation via the reverse parameter.


704-714: Good implementation with appropriate validation

The self-intersecting polygon generation function is well-implemented with proper validation to ensure an odd number of vertices (which is required for the implementation to work correctly).


725-726: Good set of test angles

This selection of angles provides good coverage for testing rotations, including edge cases (near 0°, near 90°, and near 360°).


728-736: Comprehensive parametrized test for non-convex polygons

This test thoroughly verifies that self-intersecting polygons are correctly identified as non-convex across various configurations and rotations. The parametrization ensures good test coverage.

@Czaki Czaki requested a review from Copilot March 13, 2025 16:47
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR enhances polygon validation by adding improved convexity checks and new testing functions.

  • Introduces explicit assertions for polygon convexity in triangulation tests.
  • Adds helper functions for generating both regular and self-intersecting polygons, along with a rotation matrix utility.
  • Expands tests to validate behavior under various rotations and polygon configurations.
Comments suppressed due to low confidence (1)

src/tests/test_triangulate.py:709

  • Consider revising the error message to be more grammatically clear, e.g., 'an odd number is required to generate a self-intersecting polygon'.
assert n % 2 == 1, 'need odd number to generate self-intersecting polygon'

@Czaki Czaki merged commit 72fc1f7 into master Mar 13, 2025
22 checks passed
@Czaki Czaki deleted the fix_is_convex branch March 13, 2025 20:02
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.

1 participant
0