Skip to content

fix(construction): preserve exact 2D layered strip vertices#486

Merged
acgetchell merged 4 commits into
mainfrom
fix/447-exact-layered-strip
Jun 30, 2026
Merged

fix(construction): preserve exact 2D layered strip vertices#486
acgetchell merged 4 commits into
mainfrom
fix/447-exact-layered-strip

Conversation

@acgetchell

Copy link
Copy Markdown
Owner
  • Add a non-enforcing construction option that returns valid Levels 1-4 triangulations without automatic Level 5 Delaunay repair.
  • Split exact 2D hull-edge insertions before symbolic perturbation can route them through interior insertion.
  • Allow explicit simplex imports to opt out of Level 5 validation while keeping strict Delaunay validation as the default.

Closes #447

- Add a non-enforcing construction option that returns valid Levels 1-4 triangulations without automatic Level 5 Delaunay repair.
- Split exact 2D hull-edge insertions before symbolic perturbation can route them through interior insertion.
- Allow explicit simplex imports to opt out of Level 5 validation while keeping strict Delaunay validation as the default.

Closes #447
@acgetchell acgetchell self-assigned this Jun 29, 2026
@acgetchell acgetchell enabled auto-merge (squash) June 29, 2026 09:27
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: e785bc6d-222e-4a7f-adb5-377b7b81f044

📥 Commits

Reviewing files that changed from the base of the PR and between db13cab and 5b1cf5b.

📒 Files selected for processing (2)
  • semgrep.yaml
  • tests/semgrep/src/project_rules/workflow_vertex_macro.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/semgrep/src/project_rules/workflow_vertex_macro.rs
  • semgrep.yaml

Walkthrough

Adds exact 2D boundary-edge splitting, embedding-only validation proof flow, conditional final Delaunay enforcement across construction and explicit builder paths, and broad test and fixture updates to the new APIs and vertex macro style.

Changes

Exact CDT strip construction and validation

Layer / File(s) Summary
Boundary-edge split flow
src/core/algorithms/incremental_insertion.rs, src/core/insertion.rs, src/core/algorithms/flips.rs
HullExtensionReason::MultipleBoundaryEdgeSplitFacets now carries facet handles, 2D boundary-edge matching is tightened, the split path is extracted into helpers, and insertion can return early from a located simplex split.
Embedding proof and enforcement options
src/delaunay/validation.rs, src/delaunay/construction.rs, src/delaunay/builder.rs, src/lib.rs
A Levels 1–4 validation proof is added, ConstructionOptions gains conditional final Delaunay enforcement, and explicit/default construction paths thread that enforcement through validation and error handling.
Exact CDT regressions and workflows
tests/prelude_exports.rs, tests/regressions.rs, tests/example_workflows.rs, tests/delaunay_*, tests/proptest_*, tests/circumsphere_debug_tools.rs
Regression, workflow, and property tests add exact layered CDT strip coverage, explicit-construction failure/success assertions, and related constructor-path updates.
Vertex macro fixture refactors
src/core/**/*.rs, src/delaunay/**/*.rs, src/geometry/**/*.rs, src/topology/**/*.rs, tests/**/*.rs
Test fixtures and helper code switch to vertex!-based construction across core, Delaunay, geometry, topology, and benchmark code.
Visibility, imports, and tooling cleanup
src/core/tds/*, src/geometry/*, src/core/operations.rs, benches/*, justfile, semgrep.yaml, tests/semgrep/*
Internal visibility qualifiers, imports, benchmark type paths, and Semgrep workflow fixtures are normalized without changing the runtime algorithms.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • acgetchell/causal-triangulations#447: The PR adds exact layered CDT strip handling with collinear boundary vertices, non-enforcing construction paths, and matching regression coverage.
  • acgetchell/causal-triangulations#195: The added embedding-only validation path and embedding-validated Delaunay conversion align with the issue’s split between Levels 1–4 acceptance and Level 5 enforcement.
  • acgetchell/delaunay#299: The boundary-edge splitting and hull-extension changes match the issue’s edge-splitting and constrained-boundary handling work.

Possibly related PRs

  • acgetchell/delaunay#458: It also changes 2D hull-extension boundary-edge splitting and typed failure handling.
  • acgetchell/delaunay#375: It overlaps on incremental insertion retryability and validation/error wiring in the same modules.
  • acgetchell/delaunay#363: It is directly tied to the flip error-kind conversion and HullExtensionReason wiring changes.

Suggested labels

bug, documentation, rust, geometry, api

A rabbit hopped through exact little lines,
With collinear edges and foliation signs.
Proof for the inside, and strictness set free,
While tests wore their vertex! bows with glee.
No jitter was needed; the strip held its song,
And the boundary facets all stayed where they belong. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes broad unrelated refactors like mass test vertex macro rewrites, semgrep rule changes, and benchmark/import cleanups beyond #447. Remove or split out unrelated refactors and tooling changes so this PR focuses on the exact 2D layered strip construction fix.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and matches the main change: preserving exact 2D layered strip vertices during construction.
Description check ✅ Passed The description directly describes the construction option, 2D hull-edge split, and explicit simplex validation changes in this PR.
Linked Issues check ✅ Passed The changes address #447 by preserving exact layered strip vertices, splitting exact 2D boundary-edge insertions, and allowing non-enforcing explicit construction.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 100.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/447-exact-layered-strip

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Jun 29, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 322 complexity

Metric Results
Complexity 322

View in Codacy

🟢 Coverage 97.22% diff coverage · -0.09% coverage variation

Metric Results
Coverage variation -0.09% coverage variation (-1.00%)
Diff coverage 97.22% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (f1109b6) 76459 69642 91.08%
Head commit (5b1cf5b) 75912 (-547) 69074 (-568) 90.99% (-0.09%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#486) 3269 3178 97.22%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@coderabbitai coderabbitai Bot added api bug Something isn't working geometry Geometry-related issues rust Pull requests that update rust code labels Jun 29, 2026
@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.20000% with 91 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.96%. Comparing base (f1109b6) to head (5b1cf5b).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/delaunay/construction.rs 83.91% 65 Missing ⚠️
src/core/algorithms/incremental_insertion.rs 94.40% 15 Missing ⚠️
src/core/insertion.rs 96.29% 7 Missing ⚠️
src/delaunay/builder.rs 96.07% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #486      +/-   ##
==========================================
- Coverage   91.06%   90.96%   -0.10%     
==========================================
  Files          86       86              
  Lines       76238    75691     -547     
==========================================
- Hits        69423    68855     -568     
- Misses       6815     6836      +21     
Flag Coverage Δ
unittests 90.96% <97.20%> (-0.10%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

Closes #447

- Preserve collinear 2D boundary vertices by splitting localized boundary-edge facets while keeping exact coordinates and labels intact.
- Allow exact degenerate batch construction to return after Levels 1-4 validation when final Level 5 Delaunay enforcement is disabled.
- Carry explicit simplex validation evidence into construction and reject point-insertion-only options before assembling explicit meshes.
- Enforce short vertex fixture construction across non-constructor tests, examples, and benchmarks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
semgrep.yaml (1)

1424-1450: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use a Rust-aware Semgrep rule here.

The new generic regex still matches embedded string literals and other non-call text because pattern-not-regex only skips lines whose first token is a comment or ". With the new /src/**/*.rs scope, that will create noisy warnings outside actual constructor calls.

Possible rewrite
-    languages:
-      - generic
+    languages:
+      - rust
@@
-    patterns:
-      - pattern-regex: >-
-          ^\s*[^\n]*\b(?:delaunay::prelude::)?Vertex\s*(?:::<[^;\n]+>)?\s*::\s*try_new(?:_with_data)?\s*\(
-      - pattern-not-regex: '^[ \t]*(//|///|/\*|\*|")'
+    patterns:
+      - pattern-either:
+          - pattern: Vertex::try_new(...)
+          - pattern: Vertex::<...>::try_new(...)
+          - pattern: Vertex::try_new_with_data(..., ...)
+          - pattern: Vertex::<...>::try_new_with_data(..., ...)
+          - pattern: delaunay::prelude::Vertex::try_new(...)
+          - pattern: delaunay::prelude::Vertex::<...>::try_new(...)
+          - pattern: delaunay::prelude::Vertex::try_new_with_data(..., ...)
+          - pattern: delaunay::prelude::Vertex::<...>::try_new_with_data(..., ...)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@semgrep.yaml` around lines 1424 - 1450, Replace the generic regex-based
matcher in this Semgrep rule with a Rust-aware pattern so it only flags real
constructor call sites, not embedded strings or other non-call text. Update the
rule that targets Vertex::try_new and Vertex::try_new_with_data to use AST-aware
Semgrep syntax for Rust, keeping the current paths and intent but ensuring
incidental matches in /src/**/*.rs and /tests/**/*.rs are eliminated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/delaunay/construction.rs`:
- Around line 3981-3986: `finalize_bulk_construction()` is restoring
`delaunay_repair_policy` but not the `use_global_repair_fallback` value that
seeded builders store in `dt.insertion_state`. Update the restore logic in
`finalize_bulk_construction()` (and any related batch-construction cleanup path
it shares) to also copy back `use_global_repair_fallback` from the saved
insertion state so `without_final_delaunay_enforcement()` and
`without_global_repair_fallback()` keep their intended post-build behavior. Use
the existing `final_delaunay.batch_repair_policy()`,
`final_delaunay.enforces_final_delaunay()`, and
`final_delaunay.use_global_repair_fallback()` flow as the reference point when
locating the fix.

---

Nitpick comments:
In `@semgrep.yaml`:
- Around line 1424-1450: Replace the generic regex-based matcher in this Semgrep
rule with a Rust-aware pattern so it only flags real constructor call sites, not
embedded strings or other non-call text. Update the rule that targets
Vertex::try_new and Vertex::try_new_with_data to use AST-aware Semgrep syntax
for Rust, keeping the current paths and intent but ensuring incidental matches
in /src/**/*.rs and /tests/**/*.rs are eliminated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: c6bd8e21-a258-4293-a11e-acd784a8112e

📥 Commits

Reviewing files that changed from the base of the PR and between 69b7be6 and fb35777.

📒 Files selected for processing (72)
  • benches/boundary_uuid_iter.rs
  • benches/circumsphere_containment.rs
  • justfile
  • semgrep.yaml
  • src/core/adjacency.rs
  • src/core/algorithms/flips.rs
  • src/core/algorithms/incremental_insertion.rs
  • src/core/algorithms/locate.rs
  • src/core/algorithms/pl_manifold_repair.rs
  • src/core/collections/triangulation_maps.rs
  • src/core/construction.rs
  • src/core/edge.rs
  • src/core/facet.rs
  • src/core/facet_incidence.rs
  • src/core/insertion.rs
  • src/core/operations.rs
  • src/core/orientation.rs
  • src/core/query.rs
  • src/core/repair.rs
  • src/core/rollback.rs
  • src/core/simplex.rs
  • src/core/tds/equality.rs
  • src/core/tds/incidence.rs
  • src/core/tds/mutation.rs
  • src/core/tds/snapshot.rs
  • src/core/tds/storage.rs
  • src/core/tds/validation.rs
  • src/core/traits/facet_cache.rs
  • src/core/util/canonical_points.rs
  • src/core/util/deduplication.rs
  • src/core/util/facet_keys.rs
  • src/core/util/facet_utils.rs
  • src/core/util/jaccard.rs
  • src/core/vertex.rs
  • src/delaunay/builder.rs
  • src/delaunay/construction.rs
  • src/delaunay/delaunayize.rs
  • src/delaunay/flips.rs
  • src/delaunay/locality.rs
  • src/delaunay/query.rs
  • src/delaunay/repair.rs
  • src/delaunay/rollback.rs
  • src/delaunay/serialization.rs
  • src/geometry/algorithms/convex_hull.rs
  • src/geometry/quality.rs
  • src/geometry/robust_predicates.rs
  • src/geometry/util/conversions.rs
  • src/geometry/util/measures.rs
  • src/geometry/util/triangulation_generation.rs
  • src/lib.rs
  • src/topology/characteristics/euler.rs
  • src/topology/manifold.rs
  • src/topology/ridge.rs
  • src/topology/traits/global_topology_model.rs
  • tests/circumsphere_debug_tools.rs
  • tests/dedup_batch_construction.rs
  • tests/delaunay_edge_cases.rs
  • tests/delaunay_repair_fallback.rs
  • tests/delaunayize_workflow.rs
  • tests/euler_characteristic.rs
  • tests/example_workflows.rs
  • tests/insert_with_statistics.rs
  • tests/large_scale_debug.rs
  • tests/pachner_roundtrip.rs
  • tests/proptest_delaunay_triangulation.rs
  • tests/proptest_euler_characteristic.rs
  • tests/proptest_flips.rs
  • tests/proptest_triangulation.rs
  • tests/proptest_vertex.rs
  • tests/public_topology_api.rs
  • tests/regressions.rs
  • tests/triangulation_builder.rs
✅ Files skipped from review due to trivial changes (28)
  • src/topology/traits/global_topology_model.rs
  • src/core/collections/triangulation_maps.rs
  • src/core/repair.rs
  • src/topology/characteristics/euler.rs
  • benches/circumsphere_containment.rs
  • src/core/adjacency.rs
  • src/geometry/util/triangulation_generation.rs
  • src/core/util/deduplication.rs
  • src/core/util/canonical_points.rs
  • src/topology/ridge.rs
  • src/core/operations.rs
  • benches/boundary_uuid_iter.rs
  • src/core/util/jaccard.rs
  • src/delaunay/serialization.rs
  • src/delaunay/flips.rs
  • src/geometry/robust_predicates.rs
  • src/core/algorithms/pl_manifold_repair.rs
  • src/core/util/facet_keys.rs
  • src/core/tds/equality.rs
  • src/delaunay/locality.rs
  • src/core/query.rs
  • src/core/facet_incidence.rs
  • src/geometry/quality.rs
  • src/core/tds/snapshot.rs
  • src/delaunay/delaunayize.rs
  • src/topology/manifold.rs
  • src/delaunay/query.rs
  • src/core/vertex.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/regressions.rs
  • src/core/insertion.rs
  • src/delaunay/builder.rs

Comment thread src/delaunay/construction.rs
- Restore seeded construction finalization from the final Delaunay policy so
  returned triangulations keep the intended repair and global-fallback behavior.
- Keep the workflow vertex-macro guardrail Rust-AST aware so it only flags real
  Vertex constructor calls.

Closes #447

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/semgrep/src/project_rules/workflow_vertex_macro.rs (1)

29-37: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a fixture for the qualified delaunay::prelude::Vertex branch.

Line 1453 now explicitly matches both bare Vertex and delaunay::prelude::Vertex, but this fixture file only exercises the bare form. Adding one bad case for the qualified path would keep that new regex branch from going untested.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/semgrep/src/project_rules/workflow_vertex_macro.rs` around lines 29 -
37, Add a semgrep fixture that exercises the qualified delaunay::prelude::Vertex
path, since workflow_vertex_text_ok and
workflow_vertex_constructor_with_data_bad only cover the bare Vertex form.
Introduce one bad case using the fully qualified constructor/macro pattern so
the new regex branch in the workflow vertex rule is actually tested alongside
the existing bare Vertex coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/semgrep/src/project_rules/workflow_vertex_macro.rs`:
- Around line 29-37: Add a semgrep fixture that exercises the qualified
delaunay::prelude::Vertex path, since workflow_vertex_text_ok and
workflow_vertex_constructor_with_data_bad only cover the bare Vertex form.
Introduce one bad case using the fully qualified constructor/macro pattern so
the new regex branch in the workflow vertex rule is actually tested alongside
the existing bare Vertex coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: a2398578-7ffa-4c1b-8043-cb1b82140508

📥 Commits

Reviewing files that changed from the base of the PR and between fb35777 and db13cab.

📒 Files selected for processing (3)
  • semgrep.yaml
  • src/delaunay/construction.rs
  • tests/semgrep/src/project_rules/workflow_vertex_macro.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/delaunay/construction.rs

@acgetchell acgetchell disabled auto-merge June 30, 2026 02:37
- Add a workflow vertex-macro fixture for the qualified
  delaunay::prelude::Vertex constructor path.
- Keep the Semgrep rule YAML formatted for the repository config checks.
@acgetchell acgetchell enabled auto-merge (squash) June 30, 2026 02:40
@coderabbitai coderabbitai Bot added documentation Improvements or additions to documentation and removed topology labels Jun 30, 2026
@acgetchell acgetchell merged commit 2b45995 into main Jun 30, 2026
22 checks passed
@acgetchell acgetchell deleted the fix/447-exact-layered-strip branch June 30, 2026 03:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api bug Something isn't working documentation Improvements or additions to documentation geometry Geometry-related issues rust Pull requests that update rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support exact layered CDT strips with collinear boundary vertices

1 participant