Skip to content

Add GEOS-backed polygon triangulation to Core - #66

Open
pmeems wants to merge 2 commits into
developmentfrom
polygon-triangulation-core
Open

pmeems wants to merge 2 commits into
developmentfrom
polygon-triangulation-core

Conversation

@pmeems

@pmeems pmeems commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Motivation

The OpenGL backend only accepts convex single-ring polygons and everything else falls back to GDI. This PR is phase 1 of the polygon triangulation plan: provide reusable, backend-neutral triangulation in Core so phase 2 can render concave polygons, holes, and multipart geometries with indexed triangles.

Changes

  • rendering::TriangulatePolygon() converts polygon rings into an indexed TriangleMesh using OGRGeometry::ConstrainedDelaunayTriangulation() (GDAL 3.12, backed by GEOS). No custom triangulation algorithm; invalid input is rejected explicitly and never repaired.
  • VectorRenderScene gains fillMeshes: one optional mesh per polygon, aligned by index, prepared once when the scene is created so no renderer triangulates per frame. A polygon whose triangulation fails keeps its rings (for outlines and GDI) and simply has no mesh.
  • Meshes deduplicate vertices through the index buffer and have consistent counter-clockwise winding; coordinates stay in the source coordinate system (2D rendering mesh, no Z/M redesign).
  • New GoogleTest coverage: convex/concave/holed/multipart meshes, index validity, winding, area sums vs. polygon area, containment, non-overlap, hole exclusion, and input validation.

Verification

  • msbuild MapWinGIS6.slnx -restore -p:Configuration=Debug -p:Platform=x64 -m — succeeds with zero warnings.
  • MapWinGIS.Core.Tests.exe: 311 passed (20 new triangulation tests), 1 pre-existing skip.
  • MapWinGIS.ActiveX.Tests.exe: 56 passed, 2 pre-existing skips.

Memory: recorded GDAL 3.12 snake_case geometry accessors and GeoPackage invalid-geometry fixture behavior in .ai/memory/.

Dependencies

Stacked plan PR 1 of 3. PR 2 (polygon-triangulation-opengl, against this branch) will consume the meshes in the OpenGL backend; PR 3 verifies the pipeline and updates rendering documentation.

- Add rendering::TriangulatePolygon() building an indexed TriangleMesh
  from polygon rings via OGR ConstrainedDelaunayTriangulation() and GEOS.
- Extend VectorRenderScene with one optional fill mesh per polygon,
  prepared at scene creation so renderers never triangulate per frame;
  triangulation failures keep the original rings for GDI and outlines.
- Reject invalid input explicitly (no silent repair); deduplicate mesh
  vertices and enforce consistent counter-clockwise winding.
- Add PolygonTriangulationTests covering convex, concave, holed, and
  multipart meshes plus area, containment, overlap, and validation checks.
- Record GDAL 3.12 snake_case geometry accessors and GeoPackage
  invalid-geometry fixture behavior in project memory.

@Julian-MW Julian-MW left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

One edge-case correctness issue found; otherwise the implementation and test coverage look sound.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Critical exception handling in PolygonTriangulation.cpp discards captured logger exceptions and converts std::bad_alloc into recoverable geometry errors, preventing failures from reaching their intended handlers.

2 open issues
What changed in this PR

Adds reusable polygon triangulation to Core, preparing backend-neutral meshes for a later OpenGL update while preserving existing ring-based rendering.

Changes:

  • Introduces GEOS-backed triangulation with shared vertices, indexed triangles, and consistent counter-clockwise winding.
  • Prepares optional meshes alongside scene polygons, retaining original rings when triangulation fails.
  • Adds geometry and scene-integration tests, build registration, and documentation.

Builds and tests were not run during this review.

File Description
tests/​MapWinGIS.Core.Tests/​PolygonTriangulationTests.cpp Tests mesh geometry, validation, and scene integration.
tests/​MapWinGIS.Core.Tests/​MapWinGIS.Core.Tests.vcxproj Registers the triangulation tests.
src/​MapWinGIS.Core/​src/​rendering/​VectorRenderScene.cpp Prepares optional per-polygon fill meshes.
src/​MapWinGIS.Core/​src/​rendering/​PolygonTriangulation.cpp Implements validation, triangulation, and indexed mesh assembly.
src/​MapWinGIS.Core/​MapWinGIS.Core.vcxproj Registers the new Core header and implementation.
src/​MapWinGIS.Core/​include/​mapwingis/​rendering/​VectorRenderScene.h Defines triangle meshes and aligned scene storage.
src/​MapWinGIS.Core/​include/​mapwingis/​rendering/​PolygonTriangulation.h Declares the public triangulation API and contract.
docs/​ARCHITECTURE.md Documents scene-time mesh preparation and ring retention.
.ai/​memory/​testing/​testing.md Records GeoPackage geometry-fixture behavior.
.ai/​memory/​build/​dependencies.md Records GDAL accessor and intersection-result notes.

Review effort: Balanced

- Guard the mesh vertex count before narrowing the index to uint32_t
- Rethrow std::bad_alloc from triangulation instead of converting it to CoreError
- Rethrow captured GdalErrorScope exceptions after validation and triangulation
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.

3 participants