Skip to content

feat: Implement is_valid algorithm for polyhedral surfaces #1409

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

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

vissarion
Copy link
Member

@vissarion vissarion commented May 21, 2025

This PR introduces support for the is_valid algorithm for polyhedral surface geometries. A polyhedral_surface is a 3D composite geometry formed by a collection of polygonal faces that meet at shared edges. The implementation follows the OGC Simple Features Specification and introduces structural and topological checks for polyhedral surfaces.

The following properties should hold (following OGC standard):

  • Contiguity: All polygon patches must form a connected surface via shared boundary segments.
  • Shared Edges: Shared boundaries must be finite LineStrings used in at most two polygons.
  • Orientation: Shared boundaries must be traversed in opposite directions by adjacent polygons; global orientation must be consistent.

Six new validity failure types has been introduced that reflect the description of the standard.

Below there is a matrix with valid and invalid cases with visualizations. Those cases (and a few more) are included in the unit tests of this PR.

Name Geometry Figure
valid_surface POLYHEDRALSURFACE(((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),((0 0 0,0 0 1,0 1 1,0 1 0,0 0 0)),((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((1 1 1,0 1 1,0 0 1,1 0 1,1 1 1)),((1 1 1,1 0 1,1 0 0,1 1 0,1 1 1)),((1 1 1,1 1 0,0 1 0,0 1 1,1 1 1))) Screenshot from 2025-05-21 16-52-54
valid_surface_non_convex POLYHEDRALSURFACE(((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0)),((0 0 0,0 0 1,0 1 1,0 1 0,0 0 0)),((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((1 1 1,0 1 1,0 0 1,1 0 1,1 1 1)),((1 1 1,1 0 1,1 0 0,1 1 0,1 .5 .5,1 1 1))) Screenshot from 2025-05-21 16-53-30
valid_surface_holes POLYHEDRALSURFACE(((0 0 0,0 1 0,1 1 0,1 0 0,0 0 0),(0.2 0.2 0,0.2 0.5 0,0.5 0.5 0,0.5 0.2 0,0.2 0.2 0)),((0 0 0,0 0 1,0 1 1,0 1 0,0 0 0)),((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((1 1 1,0 1 1,0 0 1,1 0 1,1 1 1)),((1 1 1,1 0 1,1 0 0,1 1 0,1 1 1)),((1 1 1,1 1 0,0 1 0,0 1 1,1 1 1))) Screenshot from 2025-05-21 16-55-21
invalid_surface_non_planar_face POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 1,0 0 0)),((1 0 0,1 1 0,0 1 0,1 0 0))) Screenshot from 2025-05-21 17-20-01
invalid_surface_collinear_points POLYHEDRALSURFACE(((1 0 0,1 1 0,0 1 0,1 0 0)),((0 0 0,1 0 0,2 0 0,0 0 0))) Screenshot from 2025-05-21 17-10-21
invalid_surface_few_points POLYHEDRALSURFACE(((1 0 0,1 1 0,0 1 0,1 0 0)),((0 0 0,1 0 0,0 0 0))) Screenshot from 2025-05-21 17-11-01
invalid_surface_invalid_intersection_boundary_interior POLYHEDRALSURFACE(((0 0 0,1 0 0,0 0 1,0 0 0)),((0 1 0,0.5 -0.5 0.5,1 1 0,0 1 0))) Screenshot from 2025-05-21 17-11-20
invalid_surface_invalid_intersection_boundary_boundary POLYHEDRALSURFACE(((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((0 1 0,0 -1 1,1 -1 1,1 1 0,0 1 0))) Screenshot from 2025-05-21 17-11-36
invalid_surface_invalid_intersection_in_common_vertex POLYHEDRALSURFACE(((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((0 1 0,1 0 1,1 1 0,0 1 0))) Screenshot from 2025-05-21 17-11-57
invalid_surface_invalid_intersection_partial_edge POLYHEDRALSURFACE(((0 0 0,1 0 0,1 0 1,0 0 1,0 0 0)),((0 1 0,0.5 0 1,1 0 1,1 1 0,0 1 0))) Screenshot from 2025-05-21 17-12-11
invalid_surface_disconnected_polygons POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 0)),((1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))) Screenshot from 2025-05-21 17-19-31
invalid_surface_invalid_intersection_vertex_edge POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 0)),((0.5 0.5 0,2 1 0,2 2 0,1 2 0,0.5 0.5 0))) Screenshot from 2025-05-21 17-12-52
invalid_surface_invalid_intersection_vertex_vertex POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 0)),((1 0 0,2 1 0,2 2 0,1 2 0,1 0 0))) Screenshot from 2025-05-21 17-13-07
invalid_surface_invalid_intersection_parallel_edges POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 0)),((0 1 0,0.5 0.5 0,1 0 0,2 1 0,2 2 0,1 2 0,0 1 0))) Screenshot from 2025-05-21 17-13-24
invalid_surface_invalid_intersection_operlapping_faces POLYHEDRALSURFACE(((0 0 0,1 0.5 0,0.5 1 0,0 0 0)),((0 1 0,1 0 0,2 1 0,2 2 0,1 2 0,0 1 0))) Screenshot from 2025-05-21 17-13-45
invalid_surface_invalid_intersection_operlapping_faces2 POLYHEDRALSURFACE(((0 0 0,1 0 0,0.5 1 0,0 0 0)),((0 1 0,1 0 0,2 1 0,2 2 0,1 2 0,0 1 0))) Screenshot from 2025-05-21 17-14-04
invalid_surface_invalid_face POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 0)),((0 1 0,1 0 0,2 2 0,2 1 0,1 2 0,0 1 0))) Screenshot from 2025-05-21 17-14-25
invalid_surface_non_manifold_edge POLYHEDRALSURFACE(((0 0 0,1 0 0,0 1 0,0 0 0)),((0 1 0,1 0 0,2 1 0,2 2 0,1 2 0,0 1 0)),((0 1 0,1 0 0,1 1 1,0 1 0))) Screenshot from 2025-05-21 17-14-43

Two unit tests are failing and are commented out. Those are dependent on #1406

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 the validity checking algorithm by introducing support for polyhedral surfaces in line with the OGC Simple Features Specification. Key changes include:

  • Adding several new failure types for polyhedral surfaces (e.g. collinear, non-coplanar points, inconsistent orientation, etc.).
  • Extending the test suite in is_valid.cpp with comprehensive cases for various valid and invalid polyhedral surfaces.
  • Updating include directives to incorporate polyhedral surface support in the core algorithm implementation.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
test/algorithms/is_valid.cpp Adds polyhedral surface test cases and minor documentation updates.
include/boost/geometry/algorithms/validity_failure_type.hpp Introduces new failure codes specific to polyhedral surfaces.
include/boost/geometry/algorithms/detail/is_valid/implementation.hpp Adds header inclusion for polyhedral surface implementation.

Copy link
Collaborator

@tinko92 tinko92 left a comment

Choose a reason for hiding this comment

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

I noted some points inline, mostly minor but importantly (imho) the question of separating some computations into strategy.

A minor point, this PR should probably include the removal of

@barendgehrels
Copy link
Collaborator

Looks great! I will review it next Wednesday or Thursday.

@vissarion vissarion force-pushed the feat/polysurf_is_valid branch 2 times, most recently from fe6743a to 36cb224 Compare May 28, 2025 12:35
@vissarion
Copy link
Member Author

@tinko92 thanks for the comments. I fixed all but the ones about tolerance and the strategy. I need to think of a unified and consistent solution for those.

@vissarion vissarion force-pushed the feat/polysurf_is_valid branch from 571d387 to 0295306 Compare June 12, 2025 15:19
@vissarion
Copy link
Member Author

@barendgehrels thanks for you comments! I addressed most of them. I need to work more on this PR. Apart from the orient3d some other simplifications can be implemented (the unaddressed comments of Barend are related to those simplifications). I will work on it next week.

@vissarion vissarion force-pushed the feat/polysurf_is_valid branch 2 times, most recently from 16c3e87 to c45c3b7 Compare July 10, 2025 14:40
@vissarion
Copy link
Member Author

vissarion commented Jul 10, 2025

I have updated this PR. Now strategies are used (with 2d and 3d orientation predicates) and there are no constructions on new geometries apart from coordinate projections (that are not that vulnerable to numerical errors). Also a new algorithm for segment-polygon intersection in 3D that only uses orientation predicates is implemented.

@vissarion vissarion force-pushed the feat/polysurf_is_valid branch from c45c3b7 to 895de6b Compare July 10, 2025 16:18
@barendgehrels
Copy link
Collaborator

Cool changes, thanks for the splits - I'll try to finish my review this weekend

Copy link
Collaborator

@tinko92 tinko92 left a comment

Choose a reason for hiding this comment

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

Thanks for all the work on incorporating the requested changes! This looks good to me. I left some comments on formatting (with diffs, see attached txt files in comments) and compiler warnings, but nothing that would require another review as far as I can see, so I'm marking it as approve.

@vissarion vissarion force-pushed the feat/polysurf_is_valid branch from 895de6b to 4a27cd5 Compare July 16, 2025 13:24
@vissarion
Copy link
Member Author

Thanks for your reviews! I addressed all the comments.
(However, I think @barendgehrels didn't finish his review yet)

Copy link
Collaborator

@barendgehrels barendgehrels left a comment

Choose a reason for hiding this comment

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

Big step! Thanks!

@tinko92
Copy link
Collaborator

tinko92 commented Jul 17, 2025

Thanks for the quick response. The latest force push broke b2 test, looks like a missing git add test/geometries/polyhedral_surface_fail.cpp.

@vissarion vissarion force-pushed the feat/polysurf_is_valid branch from 4a27cd5 to 50bc0c1 Compare July 17, 2025 09:08
@vissarion vissarion force-pushed the feat/polysurf_is_valid branch from 50bc0c1 to 0ff86d1 Compare July 17, 2025 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants